Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b521dd1 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12205827 from 87b99b86 to 24Q4-release

Change-Id: I594ce4d78486611dc2f85a92f159b1087aed40b1
parents 68a0e8f7 87b99b86
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ java_test_host {
    ],
    static_libs: [
        "kotlinx_coroutines",
        "kotlinx_coroutines_test",
    ],
    libs: [
        "junit",
+3 −82
Original line number Diff line number Diff line
@@ -16,27 +16,22 @@

package com.android.app.tracing.coroutines

import com.android.app.tracing.FakeTraceState.getOpenTraceSectionsOnCurrentThread
import com.android.app.tracing.setAndroidSystemTracingEnabled
import com.android.systemui.Flags
import com.android.systemui.util.Compile
import java.util.concurrent.CyclicBarrier
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.newSingleThreadContext
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.withContext
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
@@ -45,29 +40,12 @@ import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.BlockJUnit4ClassRunner

@RunWith(BlockJUnit4ClassRunner::class)
class CoroutineTracingTest {
    @Before
    fun setup() {
        TraceData.strictModeForTesting = true
        Compile.setIsDebug(true)
        Flags.setCoroutineTracingEnabled(true)
        setAndroidSystemTracingEnabled(true)
    }

    @After
    fun checkFinished() {
        val lastEvent = eventCounter.get()
        assertTrue(
            "Expected `finish(${lastEvent + 1})` to be called, but the test finished",
            lastEvent == FINAL_EVENT || lastEvent == 0,
        )
    }
class CoroutineTracingTest : TestBase() {

    @Test
    fun simpleTraceSection() = runTestWithTraceContext {
@@ -119,7 +97,7 @@ class CoroutineTracingTest {
    fun nestedUpdateAndRestoreOnSingleThread_unconfinedDispatcher() = runTestWithTraceContext {
        traceCoroutine("parent-span") {
            expect(1, "parent-span")
            launch(UnconfinedTestDispatcher(scheduler = testScheduler)) {
            launch(Dispatchers.Unconfined) {
                // While this may appear unusual, it is actually expected behavior:
                //   1) The parent has an open trace section called "parent-span".
                //   2) The child launches, it inherits from its parent, and it is resumed
@@ -605,61 +583,4 @@ class CoroutineTracingTest {
            }
        }
    }

    private fun expect(vararg expectedOpenTraceSections: String) {
        expect(null, *expectedOpenTraceSections)
    }

    /**
     * Checks the currently active trace sections on the current thread, and optionally checks the
     * order of operations if [expectedEvent] is not null.
     */
    private fun expect(expectedEvent: Int? = null, vararg expectedOpenTraceSections: String) {
        if (expectedEvent != null) {
            val previousEvent = eventCounter.getAndAdd(1)
            val currentEvent = previousEvent + 1
            check(expectedEvent == currentEvent) {
                if (previousEvent == FINAL_EVENT) {
                    "Expected event=$expectedEvent, but finish() was already called"
                } else {
                    "Expected event=$expectedEvent," +
                        " but the event counter is currently at $currentEvent"
                }
            }
        }

        // Inspect trace output to the fake used for recording android.os.Trace API calls:
        assertArrayEquals(expectedOpenTraceSections, getOpenTraceSectionsOnCurrentThread())
    }

    /** Same as [expect], except that no more [expect] statements can be called after it. */
    private fun finish(expectedEvent: Int, vararg expectedOpenTraceSections: String) {
        val previousEvent = eventCounter.getAndSet(FINAL_EVENT)
        val currentEvent = previousEvent + 1
        check(expectedEvent == currentEvent) {
            if (previousEvent == FINAL_EVENT) {
                "finish() was called more than once"
            } else {
                "Finished with event=$expectedEvent," +
                    " but the event counter is currently $currentEvent"
            }
        }

        // Inspect trace output to the fake used for recording android.os.Trace API calls:
        assertArrayEquals(expectedOpenTraceSections, getOpenTraceSectionsOnCurrentThread())
    }

    private val eventCounter = AtomicInteger(0)

    companion object {
        const val FINAL_EVENT = Int.MIN_VALUE
    }
}

/**
 * Helper util for calling [runTest] with a [TraceContextElement]. This is useful for formatting
 * purposes. Passing an arg to `runTest {}` directly, as in `fun testStuff() =
 * runTestWithTraceContext {}` would require more indentations according to our style guide.
 */
private fun runTestWithTraceContext(testBody: suspend TestScope.() -> Unit) =
    runTest(context = TraceContextElement(), testBody = testBody)
+114 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.app.tracing.coroutines

import com.android.app.tracing.FakeTraceState.getOpenTraceSectionsOnCurrentThread
import com.android.app.tracing.setAndroidSystemTracingEnabled
import com.android.systemui.Flags
import com.android.systemui.util.Compile
import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.runner.RunWith
import org.junit.runners.BlockJUnit4ClassRunner

@RunWith(BlockJUnit4ClassRunner::class)
open class TestBase {
    @Before
    fun setup() {
        TraceData.strictModeForTesting = true
        Compile.setIsDebug(true)
        Flags.setCoroutineTracingEnabled(true)
        setAndroidSystemTracingEnabled(true)
    }

    @After
    fun checkFinished() {
        val lastEvent = eventCounter.get()
        assertTrue(
            "Expected `finish(${lastEvent + 1})` to be called, but the test finished",
            lastEvent == FINAL_EVENT || lastEvent == 0,
        )
    }

    protected fun runTestWithTraceContext(block: suspend CoroutineScope.() -> Unit) {
        runTest(TraceContextElement(), block)
    }

    protected fun runTest(
        context: CoroutineContext = EmptyCoroutineContext,
        block: suspend CoroutineScope.() -> Unit,
    ) {
        runBlocking(context, block)
    }

    protected fun expect(vararg expectedOpenTraceSections: String) {
        println('s')
        expect(null, *expectedOpenTraceSections)
    }

    /**
     * Checks the currently active trace sections on the current thread, and optionally checks the
     * order of operations if [expectedEvent] is not null.
     */
    protected fun expect(expectedEvent: Int? = null, vararg expectedOpenTraceSections: String) {
        if (expectedEvent != null) {
            val previousEvent = eventCounter.getAndAdd(1)
            val currentEvent = previousEvent + 1
            check(expectedEvent == currentEvent) {
                if (previousEvent == FINAL_EVENT) {
                    "Expected event=$expectedEvent, but finish() was already called"
                } else {
                    "Expected event=$expectedEvent," +
                        " but the event counter is currently at $currentEvent"
                }
            }
        }

        // Inspect trace output to the fake used for recording android.os.Trace API calls:
        assertArrayEquals(expectedOpenTraceSections, getOpenTraceSectionsOnCurrentThread())
    }

    /** Same as [expect], except that no more [expect] statements can be called after it. */
    protected fun finish(expectedEvent: Int, vararg expectedOpenTraceSections: String) {
        val previousEvent = eventCounter.getAndSet(FINAL_EVENT)
        val currentEvent = previousEvent + 1
        check(expectedEvent == currentEvent) {
            if (previousEvent == FINAL_EVENT) {
                "finish() was called more than once"
            } else {
                "Finished with event=$expectedEvent," +
                    " but the event counter is currently $currentEvent"
            }
        }

        // Inspect trace output to the fake used for recording android.os.Trace API calls:
        assertArrayEquals(expectedOpenTraceSections, getOpenTraceSectionsOnCurrentThread())
    }

    private val eventCounter = AtomicInteger(0)

    companion object {
        const val FINAL_EVENT = Int.MIN_VALUE
    }
}