Moving Wait to kotlin

Making LauncherInstrumentation optional and removing some reduntant constants.
This allows less dependency on AbstractLauncherUITest

Bug: 377772352
Test: Presubmit
Flag: EXEMPT test refactor
Change-Id: I7cf78d6acc5fef0359dee141a06fd51ff9d4f5a8
This commit is contained in:
Sunny Goyal
2024-11-07 13:25:25 -08:00
parent d39c31da74
commit 8bbe47c31b
14 changed files with 118 additions and 117 deletions
@@ -26,6 +26,7 @@ import androidx.test.uiautomator.Until;
import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.TestUtil;
import com.android.quickstep.views.RecentsView;
import org.junit.rules.RuleChain;
@@ -56,7 +57,7 @@ public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest<Quick
protected void assertTestActivityIsRunning(int activityNumber, String message) {
assertTrue(message, mDevice.wait(
Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity" + activityNumber)),
DEFAULT_UI_TIMEOUT));
TestUtil.DEFAULT_UI_TIMEOUT));
}
protected LaunchedAppState getAndAssertLaunchedApp() {
@@ -22,9 +22,7 @@ import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_ACTIVITY_TIMEOUT;
import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_BROADCAST_TIMEOUT_SECS;
import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_UI_TIMEOUT;
import static com.android.launcher3.ui.AbstractLauncherUiTest.resolveSystemApp;
import static com.android.launcher3.ui.AbstractLauncherUiTest.startAppFast;
import static com.android.launcher3.ui.AbstractLauncherUiTest.startTestActivity;
@@ -56,6 +54,7 @@ import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ExtendedLongPressTimeoutRule;
import com.android.launcher3.util.rule.FailureWatcher;
@@ -214,7 +213,7 @@ public class FallbackRecentsTest {
}
result[0] = f.apply(activity);
return true;
}).get(), DEFAULT_UI_TIMEOUT, mLauncher);
}).get(), mLauncher);
return (T) result[0];
}
@@ -244,7 +243,7 @@ public class FallbackRecentsTest {
Wait.atMost("Recents activity didn't stop",
() -> getFromRecents(recents -> !recents.isStarted()),
DEFAULT_UI_TIMEOUT, mLauncher);
mLauncher);
}
@Test
@@ -254,7 +253,8 @@ public class FallbackRecentsTest {
startTestActivity(2);
waitForRecentsActivityStop();
Wait.atMost("Expected three apps in the task list",
() -> mLauncher.getRecentTasks().size() >= 3, DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
() -> mLauncher.getRecentTasks().size() >= 3,
mLauncher);
checkTestLauncher();
BaseOverview overview = mLauncher.getLaunchedAppState().switchToOverview();
@@ -282,7 +282,7 @@ public class FallbackRecentsTest {
assertNotNull("OverviewTask.open returned null", task.open());
assertTrue("Test activity didn't open from Overview", TestHelpers.wait(Until.hasObject(
By.pkg(getAppPackageName()).text("TestActivity2")),
DEFAULT_UI_TIMEOUT));
TestUtil.DEFAULT_UI_TIMEOUT));
// Test dismissing a task.
@@ -57,8 +57,6 @@ public class NavigationModeSwitchRule implements TestRule {
static final String TAG = "QuickStepOnOffRule";
public static final int WAIT_TIME_MS = 10000;
public enum Mode {
THREE_BUTTON, ZERO_BUTTON, ALL
}
@@ -179,12 +177,13 @@ public class NavigationModeSwitchRule implements TestRule {
}
Wait.atMost("Couldn't switch to " + overlayPackage,
() -> launcher.getNavigationModel() == expectedMode, WAIT_TIME_MS, launcher);
() -> launcher.getNavigationModel() == expectedMode,
launcher);
Wait.atMost(() -> "Switching nav mode: "
+ launcher.getNavigationModeMismatchError(false),
() -> launcher.getNavigationModeMismatchError(false) == null,
WAIT_TIME_MS, launcher);
launcher);
AbstractLauncherUiTest.checkDetectedLeaks(launcher, false);
return true;
}
@@ -26,6 +26,7 @@ import com.android.launcher3.tapl.OverviewTask
import com.android.launcher3.ui.AbstractLauncherUiTest
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape
import com.android.launcher3.uioverrides.QuickstepLauncher
import com.android.launcher3.util.TestUtil
import com.google.common.truth.Truth.assertWithMessage
import org.junit.Before
import org.junit.Test
@@ -172,7 +173,7 @@ class TaplTestsOverviewDesktop : AbstractLauncherUiTest<QuickstepLauncher?>() {
.that(
mDevice.wait(
Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity$index")),
DEFAULT_UI_TIMEOUT,
TestUtil.DEFAULT_UI_TIMEOUT,
)
)
.isTrue()
@@ -47,6 +47,7 @@ import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.SelectModeButtons;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TestStabilityRule;
@@ -145,7 +146,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
assertNotNull("OverviewTask.open returned null", task.open());
assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
By.pkg(getAppPackageName()).text("TestActivity2")),
DEFAULT_UI_TIMEOUT));
TestUtil.DEFAULT_UI_TIMEOUT));
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
@@ -448,7 +449,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text(
mLauncher.isGridOnlyOverviewEnabled() ? "TestActivity12"
: "TestActivity13")),
DEFAULT_UI_TIMEOUT));
TestUtil.DEFAULT_UI_TIMEOUT));
// Scroll the task offscreen as it is now first
overview = mLauncher.goHome().switchToOverview();
@@ -563,7 +564,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
mLauncher.getDevice().setOrientationLeft();
startTestActivity(7);
Wait.atMost("Device should not be in natural orientation",
() -> !mDevice.isNaturalOrientation(), DEFAULT_UI_TIMEOUT, mLauncher);
() -> !mDevice.isNaturalOrientation(), mLauncher);
mLauncher.goHome();
} finally {
mLauncher.setExpectedRotationCheckEnabled(true);
@@ -23,7 +23,7 @@ import android.content.Intent;
import android.platform.test.annotations.LargeTest;
import android.view.KeyEvent;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.SearchRecyclerView;
@@ -69,8 +69,7 @@ public class TaplUninstallRemoveTest extends AbstractLauncherUiTest<Launcher> {
private void verifyAppUninstalledFromAllApps(Workspace workspace, String appName) {
final HomeAllApps allApps = workspace.switchToAllApps();
Wait.atMost(appName + " app was found on all apps after being uninstalled",
() -> allApps.tryGetAppIcon(appName) == null,
DEFAULT_UI_TIMEOUT, mLauncher);
() -> allApps.tryGetAppIcon(appName) == null, mLauncher);
}
private void installDummyAppAndWaitForUIUpdate() throws IOException {
@@ -32,8 +32,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Point;
@@ -97,10 +95,8 @@ import java.util.function.Supplier;
*/
public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 10;
public static final long DEFAULT_UI_TIMEOUT = TestUtil.DEFAULT_UI_TIMEOUT;
private static final String TAG = "AbstractLauncherUiTest";
private static final long BYTES_PER_MEGABYTE = 1 << 20;
@@ -151,7 +147,7 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
launcher.forceGc();
return MAIN_EXECUTOR.submit(
() -> launcher.noLeakedActivities(requireOneActiveActivity)).get();
}, DEFAULT_UI_TIMEOUT, launcher);
}, launcher);
}
public static String getAppPackageName() {
@@ -443,7 +439,7 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
*/
protected <T> T getOnUiThread(final Callable<T> callback) {
try {
return mMainThreadExecutor.submit(callback).get(DEFAULT_UI_TIMEOUT,
return mMainThreadExecutor.submit(callback).get(TestUtil.DEFAULT_UI_TIMEOUT,
TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
Log.e(TAG, "Timeout in getOnUiThread, sending SIGABRT", e);
@@ -498,13 +494,7 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
// flakiness.
protected void waitForLauncherCondition(String
message, Function<LAUNCHER_TYPE, Boolean> condition) {
waitForLauncherCondition(message, condition, DEFAULT_ACTIVITY_TIMEOUT);
}
// Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
// flakiness.
protected <O> O getOnceNotNull(String message, Function<LAUNCHER_TYPE, O> f) {
return getOnceNotNull(message, f, DEFAULT_ACTIVITY_TIMEOUT);
waitForLauncherCondition(message, condition, TestUtil.DEFAULT_UI_TIMEOUT);
}
// Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
@@ -513,12 +503,12 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
String message, Function<LAUNCHER_TYPE, Boolean> condition, long timeout) {
verifyKeyguardInvisible();
if (!TestHelpers.isInLauncherProcess()) return;
Wait.atMost(message, () -> getFromLauncher(condition), timeout, mLauncher);
Wait.atMost(message, () -> getFromLauncher(condition), mLauncher, timeout);
}
// Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
// flakiness.
protected <T> T getOnceNotNull(String message, Function<LAUNCHER_TYPE, T> f, long timeout) {
protected <T> T getOnceNotNull(String message, Function<LAUNCHER_TYPE, T> f) {
if (!TestHelpers.isInLauncherProcess()) return null;
final Object[] output = new Object[1];
@@ -526,7 +516,7 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
final Object fromLauncher = getFromLauncher(f);
output[0] = fromLauncher;
return fromLauncher != null;
}, timeout, mLauncher);
}, mLauncher);
return (T) output[0];
}
@@ -540,12 +530,7 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
Wait.atMost(message, () -> {
testThreadAction.run();
return getFromLauncher(condition);
}, timeout, mLauncher);
}
protected LauncherActivityInfo getSettingsApp() {
return mTargetContext.getSystemService(LauncherApps.class)
.getActivityList("com.android.settings", Process.myUserHandle()).get(0);
}, mLauncher, timeout);
}
/**
@@ -633,13 +618,13 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
}
getInstrumentation().getTargetContext().startActivity(intent);
assertTrue("App didn't start: " + selector,
TestHelpers.wait(Until.hasObject(selector), DEFAULT_UI_TIMEOUT));
TestHelpers.wait(Until.hasObject(selector), TestUtil.DEFAULT_UI_TIMEOUT));
// Wait for the Launcher to stop.
final LauncherInstrumentation launcherInstrumentation = new LauncherInstrumentation();
Wait.atMost("Launcher activity didn't stop",
() -> !launcherInstrumentation.isLauncherActivityStarted(),
DEFAULT_ACTIVITY_TIMEOUT, launcherInstrumentation);
launcherInstrumentation);
}
public static ActivityInfo resolveSystemAppInfo(String category) {
@@ -662,8 +647,7 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
launcher.finish();
}
});
waitForLauncherCondition(
"Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT);
waitForLauncherCondition("Launcher still active", launcher -> launcher == null);
}
protected boolean isInLaunchedApp(LAUNCHER_TYPE launcher) {
@@ -103,12 +103,12 @@ public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest<Launcher> {
setResultAndWaitForAnimation(acceptConfig);
if (acceptConfig) {
Wait.atMost("", new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
Wait.atMost("", new WidgetSearchCondition(), mLauncher);
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
} else {
// Verify that the widget id is deleted.
Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null,
DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
mLauncher);
}
}
@@ -29,6 +29,7 @@ import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -68,7 +69,7 @@ public class TaplAddWidgetTest extends AbstractLauncherUiTest<Launcher> {
resizeFrame.dismiss();
final Widget widget = mLauncher.getWorkspace().tryGetWidget(widgetInfo.label,
DEFAULT_UI_TIMEOUT);
TestUtil.DEFAULT_UI_TIMEOUT);
assertNotNull("Widget not found on the workspace", widget);
widget.launch(getAppPackageName());
mLauncher.disableDebugTracing(); // b/289161193
@@ -53,6 +53,7 @@ import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -233,13 +234,15 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
}
private void verifyWidgetPresent(LauncherAppWidgetProviderInfo info) {
final Widget widget = mLauncher.getWorkspace().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT);
final Widget widget = mLauncher.getWorkspace().tryGetWidget(info.label,
TestUtil.DEFAULT_UI_TIMEOUT);
assertTrue("Widget is not present",
widget != null);
}
private void verifyPendingWidgetPresent() {
final Widget widget = mLauncher.getWorkspace().tryGetPendingWidget(DEFAULT_UI_TIMEOUT);
final Widget widget = mLauncher.getWorkspace().tryGetPendingWidget(
TestUtil.DEFAULT_UI_TIMEOUT);
assertTrue("Pending widget is not present",
widget != null);
}
@@ -169,8 +169,7 @@ public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
// Go back to home
mLauncher.goHome();
Wait.atMost("", new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT,
mLauncher);
Wait.atMost("", new ItemSearchCondition(itemMatcher), mLauncher);
}
/**
@@ -1,66 +0,0 @@
package com.android.launcher3.util;
import android.os.SystemClock;
import android.util.Log;
import com.android.launcher3.tapl.LauncherInstrumentation;
import org.junit.Assert;
import java.util.function.Supplier;
/**
* A utility class for waiting for a condition to be true.
*/
public class Wait {
private static final long DEFAULT_SLEEP_MS = 200;
public static void atMost(String message, Condition condition, long timeout,
LauncherInstrumentation launcher) {
atMost(() -> message, condition, timeout, DEFAULT_SLEEP_MS, launcher);
}
public static void atMost(Supplier<String> message, Condition condition, long timeout,
LauncherInstrumentation launcher) {
atMost(message, condition, timeout, DEFAULT_SLEEP_MS, launcher);
}
public static void atMost(Supplier<String> message, Condition condition, long timeout,
long sleepMillis,
LauncherInstrumentation launcher) {
final long startTime = SystemClock.uptimeMillis();
long endTime = startTime + timeout;
Log.d("Wait", "atMost: " + startTime + " - " + endTime);
while (SystemClock.uptimeMillis() < endTime) {
try {
if (condition.isTrue()) {
return;
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
SystemClock.sleep(sleepMillis);
}
// Check once more before returning false.
try {
if (condition.isTrue()) {
return;
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
Log.d("Wait", "atMost: timed out: " + SystemClock.uptimeMillis());
launcher.checkForAnomaly(false, false);
Assert.fail(message.get());
}
/**
* Interface representing a generic condition
*/
public interface Condition {
boolean isTrue() throws Throwable;
}
}
@@ -0,0 +1,79 @@
/*
* 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.launcher3.util
import android.os.SystemClock
import android.util.Log
import com.android.launcher3.tapl.LauncherInstrumentation
import java.util.function.Supplier
import org.junit.Assert
/** A utility class for waiting for a condition to be true. */
object Wait {
private const val DEFAULT_SLEEP_MS: Long = 200
@JvmStatic
@JvmOverloads
fun atMost(
message: String,
condition: Condition,
launcherInstrumentation: LauncherInstrumentation? = null,
timeout: Long = TestUtil.DEFAULT_UI_TIMEOUT,
) {
atMost({ message }, condition, launcherInstrumentation, timeout)
}
@JvmStatic
@JvmOverloads
fun atMost(
message: Supplier<String>,
condition: Condition,
launcherInstrumentation: LauncherInstrumentation? = null,
timeout: Long = TestUtil.DEFAULT_UI_TIMEOUT,
) {
val startTime = SystemClock.uptimeMillis()
val endTime = startTime + timeout
Log.d("Wait", "atMost: $startTime - $endTime")
while (SystemClock.uptimeMillis() < endTime) {
try {
if (condition.isTrue()) {
return
}
} catch (t: Throwable) {
throw RuntimeException(t)
}
SystemClock.sleep(DEFAULT_SLEEP_MS)
}
// Check once more before returning false.
try {
if (condition.isTrue()) {
return
}
} catch (t: Throwable) {
throw RuntimeException(t)
}
Log.d("Wait", "atMost: timed out: " + SystemClock.uptimeMillis())
launcherInstrumentation?.checkForAnomaly(false, false)
Assert.fail(message.get())
}
/** Interface representing a generic condition */
fun interface Condition {
@Throws(Throwable::class) fun isTrue(): Boolean
}
}