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

Commit b1d9917f authored by Charles Chen's avatar Charles Chen
Browse files

Split tests into several test cases

Then we can write flicker tests by reusing the test cases.
This CL also put helper classes into utils package.

Test: atest WMShellExplicitFlickerTestsBubbles
Flag: TEST_ONLY
Bug: 396020056

Change-Id: Id09f6bda34dc8aa755575eba040e40ada61ffab9
parent 563dfe05
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@ package com.android.wm.shell.flicker.bubbles
import android.platform.test.flag.junit.CheckFlagsRule
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.tools.Tag
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.flicker.assertions.SubjectsParser
import android.tools.flicker.subject.events.EventLogSubject
import android.tools.flicker.subject.layers.LayerTraceEntrySubject
import android.tools.flicker.subject.layers.LayersTraceSubject
import android.tools.flicker.subject.wm.WindowManagerStateSubject
@@ -28,8 +30,11 @@ import android.tools.io.Reader
import android.tools.traces.component.ComponentNameMatcher
import android.tools.traces.surfaceflinger.LayerTraceEntry
import android.tools.traces.wm.WindowManagerState
import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel
import com.android.server.wm.flicker.assertNavBarPosition
import com.android.server.wm.flicker.assertStatusBarLayerPosition
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerSubjects
import com.android.wm.shell.flicker.bubbles.utils.FlickerPropertyInitializer
import org.junit.Rule
import org.junit.Test

@@ -39,7 +44,7 @@ import org.junit.Test
 * - Launcher visibility tests: checks launcher window/layer is always visible
 * - System Bars tests; checks the visibility of navigation and status bar
 */
abstract class BubbleFlickerTestBase {
abstract class BubbleFlickerTestBase : BubbleFlickerSubjects {

    @get:Rule
    val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@@ -49,11 +54,19 @@ abstract class BubbleFlickerTestBase {
     */
    abstract val traceDataReader: Reader

    /**
     * The event log subject.
     */
    override val eventLogSubject = EventLogSubject(
        traceDataReader.readEventLogTrace() ?: error("Failed to read event log"),
        traceDataReader
    )

    /**
     * The WindowManager trace subject, which is equivalent to the data shown in
     * `Window Manager` tab in go/winscope.
     */
    val wmTraceSubject = WindowManagerTraceSubject(
    override val wmTraceSubject = WindowManagerTraceSubject(
        traceDataReader.readWmTrace() ?: error("Failed to read WM trace")
    )

@@ -61,34 +74,38 @@ abstract class BubbleFlickerTestBase {
     * The Layer trace subject, which is equivalent to the data shown in
     * `Surface Flinger` tab in go/winscope.
     */
    val layersTraceSubject = LayersTraceSubject(
    override val layersTraceSubject = LayersTraceSubject(
        traceDataReader.readLayersTrace() ?: error("Failed to read layer trace")
    )

    /**
     * The first [WindowManagerState] of the WindowManager trace.
     */
    val wmStateSubjectAtStart: WindowManagerStateSubject
    final override val wmStateSubjectAtStart: WindowManagerStateSubject

    /**
     * The last [WindowManagerState] of the WindowManager trace.
     */
    val wmStateSubjectAtEnd: WindowManagerStateSubject
    final override val wmStateSubjectAtEnd: WindowManagerStateSubject

    /**
     * The first [LayerTraceEntry] of the Layers trace.
     */
    val layerTraceEntrySubjectAtStart: LayerTraceEntrySubject
    final override val layerTraceEntrySubjectAtStart: LayerTraceEntrySubject

    /**
     * The last [LayerTraceEntry] of the Layers trace.
     */
    val layerTraceEntrySubjectAtEnd: LayerTraceEntrySubject
    final override val layerTraceEntrySubjectAtEnd: LayerTraceEntrySubject

    // TODO(b/396020056): Verify bubble scenarios in 3-button mode.
    /**
     * Indicates whether the device uses gesture navigation bar or not.
     */
    abstract val isGesturalNavBar: Boolean
    override val isGesturalNavBar = tapl.navigationModel == NavigationModel.ZERO_BUTTON

    override val testApp: StandardAppHelper
        get() = CollapseBubbleViaBackTest.testApp

    /**
     * Initialize subjects inherited from [FlickerSubject].
@@ -131,7 +148,7 @@ abstract class BubbleFlickerTestBase {

// endregion

// Launcher visibility tests
// region Launcher visibility tests

    /**
     * Verifies the launcher window is always visible.
@@ -210,4 +227,6 @@ abstract class BubbleFlickerTestBase {
    }

// endregion

    companion object : FlickerPropertyInitializer()
}
 No newline at end of file
+13 −29
Original line number Diff line number Diff line
@@ -20,12 +20,15 @@ import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.platform.test.annotations.RequiresFlagsEnabled
import android.tools.flicker.subject.events.EventLogSubject
import android.tools.traces.component.ComponentNameMatcher
import android.tools.traces.component.ComponentNameMatcher.Companion.LAUNCHER
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel
import com.android.wm.shell.Flags
import com.android.wm.shell.flicker.bubbles.EnterBubbleViaBubbleMenuTest.Companion.testApp
import com.android.wm.shell.flicker.bubbles.testcase.BubbleStackAlwaysVisibleTestCases
import com.android.wm.shell.flicker.bubbles.utils.FlickerPropertyInitializer
import com.android.wm.shell.flicker.bubbles.utils.RecordTraceWithTransitionRule
import com.android.wm.shell.flicker.bubbles.utils.collapseBubbleViaBackKey
import com.android.wm.shell.flicker.bubbles.utils.launchBubbleViaBubbleMenu
import com.android.wm.shell.flicker.bubbles.utils.setUpBeforeTransition
import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Test
@@ -46,13 +49,18 @@ import org.junit.runners.MethodSorters
 * ```
 *     Collapse bubble via back key
 * ```
 *
 * Verified tests:
 * - [BubbleFlickerTestBase]
 * - [BubbleStackAlwaysVisibleTestCases]
 * - The focus changes to [LAUNCHER] from [testApp] and [LAUNCHER] becomes the top window
 */
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE)
@RunWith(AndroidJUnit4::class)
@RequiresDevice
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Presubmit
class CollapseBubbleViaBackTest : BubbleFlickerTestBase() {
class CollapseBubbleViaBackTest : BubbleFlickerTestBase(), BubbleStackAlwaysVisibleTestCases {

    companion object : FlickerPropertyInitializer() {

@@ -71,29 +79,6 @@ class CollapseBubbleViaBackTest : BubbleFlickerTestBase() {
    override val traceDataReader
        get() = recordTraceWithTransitionRule.reader

    // TODO(b/396020056): Verify bubble scenarios in 3-button mode.
    override val isGesturalNavBar = tapl.navigationModel == NavigationModel.ZERO_BUTTON

// region Bubble related tests

    /**
     * Verifies the bubble window is visible at the end of transition.
     */
    @Test
    fun bubbleWindowIsAlwaysVisible() {
        wmTraceSubject.isAboveAppWindowVisible(ComponentNameMatcher.BUBBLE)
    }

    /**
     * Verifies the bubble layer is visible at the end of transition.
     */
    @Test
    fun bubbleLayerIsAlwaysVisible() {
        layersTraceSubject.isVisible(ComponentNameMatcher.BUBBLE)
    }

// endregion

// region launcher related tests

    /**
@@ -126,7 +111,7 @@ class CollapseBubbleViaBackTest : BubbleFlickerTestBase() {
     * Verifies [LAUNCHER] is the top window at the end of transition.
     */
    @Test
    fun appWindowAsTopWindowAtEnd() {
    fun launcherWindowAsTopWindowAtEnd() {
        wmStateSubjectAtEnd.isAppWindowOnTop(LAUNCHER)
    }

@@ -136,7 +121,6 @@ class CollapseBubbleViaBackTest : BubbleFlickerTestBase() {
    @Test
    fun launcherWindowBecomesTopWindow() {
        wmTraceSubject
            .skipUntilFirstAssertion()
            .isAppWindowNotOnTop(LAUNCHER)
            .then()
            .isAppWindowOnTop(LAUNCHER)
+9 −108
Original line number Diff line number Diff line
@@ -19,11 +19,15 @@ package com.android.wm.shell.flicker.bubbles
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.platform.test.annotations.RequiresFlagsEnabled
import android.tools.flicker.subject.events.EventLogSubject
import android.tools.traces.component.ComponentNameMatcher
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel
import com.android.wm.shell.Flags
import com.android.wm.shell.flicker.bubbles.testcase.BubbleAppBecomesExpandedTestCases
import com.android.wm.shell.flicker.bubbles.utils.FlickerPropertyInitializer
import com.android.wm.shell.flicker.bubbles.utils.RecordTraceWithTransitionRule
import com.android.wm.shell.flicker.bubbles.utils.launchBubbleViaBubbleMenu
import com.android.wm.shell.flicker.bubbles.utils.setUpBeforeTransition
import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Test
@@ -40,13 +44,16 @@ import org.junit.runners.MethodSorters
 *     Long press [simpleApp] icon to show [AppIconMenu].
 *     Click the bubble menu to launch [simpleApp] into bubble.
 * ```
 * Verified tests:
 * - [BubbleFlickerTestBase]
 * - [BubbleAppBecomesExpandedTestCases]
 */
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE)
@RunWith(AndroidJUnit4::class)
@RequiresDevice
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Presubmit
class EnterBubbleViaBubbleMenuTest : BubbleFlickerTestBase() {
class EnterBubbleViaBubbleMenuTest : BubbleFlickerTestBase(), BubbleAppBecomesExpandedTestCases {

    companion object : FlickerPropertyInitializer() {

@@ -109,111 +116,5 @@ class EnterBubbleViaBubbleMenuTest : BubbleFlickerTestBase() {
            .forAllEntries()
    }

// endregion

// region App Launch related tests

    /**
     * Verifies the focus changed from launcher to [testApp].
     */
    @Test
    fun focusChanges() {
        EventLogSubject(
            traceDataReader.readEventLogTrace() ?: error("Failed to read event log"),
            traceDataReader
        ).focusChanges(
            ComponentNameMatcher.LAUNCHER.toWindowName(),
            testApp.toWindowName()
        )
    }

    /**
     * Verifies the [testApp] replaces launcher to be the top window.
     */
    @Test
    fun appWindowReplacesLauncherAsTopWindow() {
        wmTraceSubject
            .isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
            .then()
            .isAppWindowOnTop(
                ComponentNameMatcher.SNAPSHOT
                    .or(ComponentNameMatcher.SPLASH_SCREEN),
                isOptional = true,
            )
            .then()
            .isAppWindowOnTop(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] is the top window at the end of transition.
     */
    @Test
    fun appWindowAsTopWindowAtEnd() {
        wmStateSubjectAtEnd.isAppWindowOnTop(testApp)
    }

    /**
     * Verifies the [testApp] becomes the top window.
     */
    @Test
    fun appWindowBecomesTopWindow() {
        wmTraceSubject
            .skipUntilFirstAssertion()
            .isAppWindowNotOnTop(testApp)
            .then()
            .isAppWindowOnTop(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] window becomes visible.
     */
    @Test
    fun appWindowBecomesVisible() {
        wmTraceSubject
            .skipUntilFirstAssertion()
            .isAppWindowInvisible(testApp)
            .then()
            .isAppWindowVisible(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] layer becomes visible.
     */
    @Test
    fun appLayerBecomesVisible() {
        layersTraceSubject
            .isInvisible(testApp)
            .then()
            .isVisible(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] window is visible at the end of transition.
     */
    @Test
    fun appWindowIsVisibleAtEnd() {
        wmStateSubjectAtEnd.isAppWindowVisible(testApp)
    }

    /**
     * Verifies the [testApp] layer is visible at the end of transition.
     */
    @Test
    fun appLayerIsVisibleAtEnd() {
        layerTraceEntrySubjectAtEnd.isVisible(testApp)
    }

    /**
     * Verifies the [testApp] layer has rounded corners
     */
    @Test
    fun appLayerHasRoundedCorner() {
        layerTraceEntrySubjectAtEnd.hasRoundedCorners(testApp)
    }

// endregion
}
 No newline at end of file
+2 −2
Original line number Diff line number Diff line
@@ -19,8 +19,8 @@ package com.android.wm.shell.flicker.bubbles.samples
import android.tools.flicker.subject.events.EventLogSubject
import android.tools.flicker.subject.layers.LayersTraceSubject
import android.tools.flicker.subject.wm.WindowManagerTraceSubject
import com.android.wm.shell.flicker.bubbles.RecordTraceWithTransitionRule
import com.android.wm.shell.flicker.bubbles.runTransitionWithTrace
import com.android.wm.shell.flicker.bubbles.utils.RecordTraceWithTransitionRule
import com.android.wm.shell.flicker.bubbles.utils.runTransitionWithTrace

/**
 * Sample to illustrate how to use [runTransitionWithTrace].
+125 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.wm.shell.flicker.bubbles.testcase

import android.tools.traces.component.ComponentNameMatcher
import android.tools.traces.component.ComponentNameMatcher.Companion.LAUNCHER
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerSubjects
import org.junit.Test

/**
 * The test cases to verify [testApp] goes to expanded bubble state, which verifies [testApp]
 * replaces [LAUNCHER] to be top and visible and has rounded corner at the end of transition.
 */
interface BubbleAppBecomesExpandedTestCases : BubbleFlickerSubjects {

    /**
     * Verifies the focus changed from launcher to [testApp].
     */
    @Test
    fun focusChanges() {
        eventLogSubject.focusChanges(LAUNCHER.toWindowName(), testApp.toWindowName())
    }

    /**
     * Verifies the [testApp] replaces launcher to be the top window.
     */
    @Test
    fun appWindowReplacesLauncherAsTopWindow() {
        wmTraceSubject
            .isAppWindowOnTop(LAUNCHER)
            .then()
            .isAppWindowOnTop(
                ComponentNameMatcher.SNAPSHOT
                    .or(ComponentNameMatcher.SPLASH_SCREEN),
                isOptional = true,
            )
            .then()
            .isAppWindowOnTop(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] is the top window at the end of transition.
     */
    @Test
    fun appWindowAsTopWindowAtEnd() {
        wmStateSubjectAtEnd.isAppWindowOnTop(testApp)
    }

    /**
     * Verifies the [testApp] becomes the top window.
     */
    @Test
    fun appWindowBecomesTopWindow() {
        wmTraceSubject
            .skipUntilFirstAssertion()
            .isAppWindowNotOnTop(testApp)
            .then()
            .isAppWindowOnTop(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] window becomes visible.
     */
    @Test
    fun appWindowBecomesVisible() {
        wmTraceSubject
            .skipUntilFirstAssertion()
            .isAppWindowInvisible(testApp)
            .then()
            .isAppWindowVisible(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] layer becomes visible.
     */
    @Test
    fun appLayerBecomesVisible() {
        layersTraceSubject
            .isInvisible(testApp)
            .then()
            .isVisible(testApp)
            .forAllEntries()
    }

    /**
     * Verifies the [testApp] window is visible at the end of transition.
     */
    @Test
    fun appWindowIsVisibleAtEnd() {
        wmStateSubjectAtEnd.isAppWindowVisible(testApp)
    }

    /**
     * Verifies the [testApp] layer is visible at the end of transition.
     */
    @Test
    fun appLayerIsVisibleAtEnd() {
        layerTraceEntrySubjectAtEnd.isVisible(testApp)
    }

    /**
     * Verifies the [testApp] layer has rounded corners
     */
    @Test
    fun appLayerHasRoundedCorner() {
        layerTraceEntrySubjectAtEnd.hasRoundedCorners(testApp)
    }
}
 No newline at end of file
Loading