diff options
Diffstat (limited to 'tests')
5 files changed, 186 insertions, 46 deletions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt index 4efee55b97b5..8f07f213521b 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt @@ -109,11 +109,11 @@ class OpenAppFromLockNotificationWithLockOverlayApp(flicker: FlickerTest) : override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() /** {@inheritDoc} */ - @FlakyTest(bugId = 209599395) + @Presubmit @Test override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - @FlakyTest(bugId = 266730606) + @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered() diff --git a/tests/testables/src/android/testing/TestWithLooperRule.java b/tests/testables/src/android/testing/TestWithLooperRule.java new file mode 100644 index 000000000000..99b303e0c43a --- /dev/null +++ b/tests/testables/src/android/testing/TestWithLooperRule.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2023 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 android.testing; + +import android.testing.TestableLooper.LooperFrameworkMethod; +import android.testing.TestableLooper.RunWithLooper; + +import org.junit.internal.runners.statements.InvokeMethod; +import org.junit.rules.MethodRule; +import org.junit.runner.RunWith; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/* + * This rule is meant to be an alternative of using AndroidTestingRunner. + * It let tests to start from background thread, and assigns mainLooper or new + * Looper for the Statement. + */ +public class TestWithLooperRule implements MethodRule { + + /* + * This rule requires to be the inner most Rule, so the next statement is RunAfters + * instead of another rule. You can set it by '@Rule(order = Integer.MAX_VALUE)' + */ + @Override + public Statement apply(Statement base, FrameworkMethod method, Object target) { + // getting testRunner check, if AndroidTestingRunning then we skip this rule + RunWith runWithAnnotation = target.getClass().getAnnotation(RunWith.class); + if (runWithAnnotation != null) { + // if AndroidTestingRunner or it's subclass is in use, do nothing + if (AndroidTestingRunner.class.isAssignableFrom(runWithAnnotation.value())) { + return base; + } + } + + // check if RunWithLooper annotation is used. If not skip this rule + RunWithLooper looperAnnotation = method.getAnnotation(RunWithLooper.class); + if (looperAnnotation == null) { + looperAnnotation = target.getClass().getAnnotation(RunWithLooper.class); + } + if (looperAnnotation == null) { + return base; + } + + try { + wrapMethodInStatement(base, method, target); + } catch (Exception e) { + throw new RuntimeException(e); + } + return base; + } + + // This method is based on JUnit4 test runner flow. It might need to be revisited when JUnit is + // upgraded + // TODO(b/277743626): use a cleaner way to wrap each statements; may require some JUnit + // patching to facilitate this. + private void wrapMethodInStatement(Statement base, FrameworkMethod method, Object target) + throws Exception { + Statement next = base; + try { + while (next != null) { + switch (next.getClass().getSimpleName()) { + case "RunAfters": + this.<List<FrameworkMethod>>wrapFieldMethodFor(next, + next.getClass(), "afters", method, target); + next = getNextStatement(next, "next"); + break; + case "RunBefores": + this.<List<FrameworkMethod>>wrapFieldMethodFor(next, + next.getClass(), "befores", method, target); + next = getNextStatement(next, "next"); + break; + case "FailOnTimeout": + // Note: withPotentialTimeout() from BlockJUnit4ClassRunner might use + // FailOnTimeout which always wraps a new thread during InvokeMethod + // method evaluation. + next = getNextStatement(next, "originalStatement"); + break; + case "InvokeMethod": + this.<FrameworkMethod>wrapFieldMethodFor(next, + InvokeMethod.class, "testMethod", method, target); + return; + default: + throw new Exception( + String.format("Unexpected Statement received: [%s]", + next.getClass().getName()) + ); + } + } + } catch (Exception e) { + throw e; + } + } + + // Wrapping the befores, afters, and InvokeMethods with LooperFrameworkMethod + // within the statement. + private <T> void wrapFieldMethodFor(Statement base, Class<?> targetClass, String fieldStr, + FrameworkMethod method, Object target) + throws NoSuchFieldException, IllegalAccessException { + Field field = targetClass.getDeclaredField(fieldStr); + field.setAccessible(true); + T fieldInstance = (T) field.get(base); + if (fieldInstance instanceof FrameworkMethod) { + field.set(base, looperWrap(method, target, (FrameworkMethod) fieldInstance)); + } else { + // Befores and afters methods lists + field.set(base, looperWrap(method, target, (List<FrameworkMethod>) fieldInstance)); + } + } + + // Retrieve the next wrapped statement based on the selected field string + private Statement getNextStatement(Statement base, String fieldStr) + throws NoSuchFieldException, IllegalAccessException { + Field nextField = base.getClass().getDeclaredField(fieldStr); + nextField.setAccessible(true); + Object value = nextField.get(base); + return value instanceof Statement ? (Statement) value : null; + } + + protected FrameworkMethod looperWrap(FrameworkMethod method, Object test, + FrameworkMethod base) { + RunWithLooper annotation = method.getAnnotation(RunWithLooper.class); + if (annotation == null) annotation = test.getClass().getAnnotation(RunWithLooper.class); + if (annotation != null) { + return LooperFrameworkMethod.get(base, annotation.setAsMainLooper(), test); + } + return base; + } + + protected List<FrameworkMethod> looperWrap(FrameworkMethod method, Object test, + List<FrameworkMethod> methods) { + RunWithLooper annotation = method.getAnnotation(RunWithLooper.class); + if (annotation == null) annotation = test.getClass().getAnnotation(RunWithLooper.class); + if (annotation != null) { + methods = new ArrayList<>(methods); + for (int i = 0; i < methods.size(); i++) { + methods.set(i, LooperFrameworkMethod.get(methods.get(i), + annotation.setAsMainLooper(), test)); + } + } + return methods; + } +} diff --git a/tests/testables/src/android/testing/TestableResources.java b/tests/testables/src/android/testing/TestableResources.java index c60f07d56d92..27d5b66b355e 100644 --- a/tests/testables/src/android/testing/TestableResources.java +++ b/tests/testables/src/android/testing/TestableResources.java @@ -59,7 +59,8 @@ public class TestableResources { * Since resource ids are unique there is a single addOverride that will override the value * whenever it is gotten regardless of which method is used (i.e. getColor or getDrawable). * </p> - * @param id The resource id to be overridden + * + * @param id The resource id to be overridden * @param value The value of the resource, null to cause a {@link Resources.NotFoundException} * when gotten. */ @@ -74,28 +75,33 @@ public class TestableResources { * cause a {@link Resources.NotFoundException} whereas removing the override will actually * switch back to returning the default/real value of the resource. * </p> - * @param id */ public void removeOverride(int id) { mOverrides.remove(id); } private Object answer(InvocationOnMock invocationOnMock) throws Throwable { - try { - int id = invocationOnMock.getArgument(0); - int index = mOverrides.indexOfKey(id); - if (index >= 0) { - Object value = mOverrides.valueAt(index); - if (value == null) throw new Resources.NotFoundException(); - return value; + // Only try to override methods with an integer first argument + if (invocationOnMock.getArguments().length > 0) { + Object argument = invocationOnMock.getArgument(0); + if (argument instanceof Integer) { + try { + int id = (Integer)argument; + int index = mOverrides.indexOfKey(id); + if (index >= 0) { + Object value = mOverrides.valueAt(index); + if (value == null) throw new Resources.NotFoundException(); + return value; + } + } catch (Resources.NotFoundException e) { + // Let through NotFoundException. + throw e; + } catch (Throwable t) { + // Generic catching for the many things that can go wrong, fall back to + // the real implementation. + Log.i(TAG, "Falling back to default resources call " + t); + } } - } catch (Resources.NotFoundException e) { - // Let through NotFoundException. - throw e; - } catch (Throwable t) { - // Generic catching for the many things that can go wrong, fall back to - // the real implementation. - Log.i(TAG, "Falling back to default resources call " + t); } return invocationOnMock.callRealMethod(); } diff --git a/tests/testables/tests/AndroidManifest.xml b/tests/testables/tests/AndroidManifest.xml index 1731f6be4bf2..2bfb04fdb765 100644 --- a/tests/testables/tests/AndroidManifest.xml +++ b/tests/testables/tests/AndroidManifest.xml @@ -21,7 +21,7 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> - <application android:debuggable="true" android:testOnly="true"> + <application android:debuggable="true"> <uses-library android:name="android.test.runner" /> </application> diff --git a/tests/testables/tests/AndroidTest.xml b/tests/testables/tests/AndroidTest.xml deleted file mode 100644 index 6d2979423efa..000000000000 --- a/tests/testables/tests/AndroidTest.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2022 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. - --> -<configuration description="Runs Testable Tests."> - <option name="test-tag" value="TestablesTests" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="install-arg" value="-t" /> - <option name="test-file-name" value="TestablesTests.apk" /> - </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest"> - <option name="package" value="com.android.testables"/> - </test> -</configuration> |