diff options
13 files changed, 446 insertions, 321 deletions
diff --git a/services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java b/services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java new file mode 100644 index 000000000000..a329f5a14477 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java @@ -0,0 +1,181 @@ +/* + * 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 com.android.server; + +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Optional; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import com.google.common.collect.Table; +import com.google.common.truth.BigDecimalSubject; +import com.google.common.truth.BooleanSubject; +import com.google.common.truth.ClassSubject; +import com.google.common.truth.ComparableSubject; +import com.google.common.truth.DoubleSubject; +import com.google.common.truth.Expect; +import com.google.common.truth.FloatSubject; +import com.google.common.truth.GuavaOptionalSubject; +import com.google.common.truth.IntegerSubject; +import com.google.common.truth.IterableSubject; +import com.google.common.truth.LongSubject; +import com.google.common.truth.MapSubject; +import com.google.common.truth.MultimapSubject; +import com.google.common.truth.MultisetSubject; +import com.google.common.truth.ObjectArraySubject; +import com.google.common.truth.PrimitiveBooleanArraySubject; +import com.google.common.truth.PrimitiveByteArraySubject; +import com.google.common.truth.PrimitiveCharArraySubject; +import com.google.common.truth.PrimitiveDoubleArraySubject; +import com.google.common.truth.PrimitiveFloatArraySubject; +import com.google.common.truth.PrimitiveIntArraySubject; +import com.google.common.truth.PrimitiveLongArraySubject; +import com.google.common.truth.PrimitiveShortArraySubject; +import com.google.common.truth.StandardSubjectBuilder; +import com.google.common.truth.StringSubject; +import com.google.common.truth.Subject; +import com.google.common.truth.TableSubject; +import com.google.common.truth.ThrowableSubject; + +import org.junit.Rule; + +import java.math.BigDecimal; +import java.util.Map; + +// NOTE: it could be a more generic AbstractTruthTestCase that provide similar methods +// for assertThat() / assertWithMessage(), but then we'd need to remove all static import imports +// from classes that indirectly extend it. +/** + * Base class to make it easier to use {@code Truth} {@link Expect} assertions. + */ +public abstract class ExpectableTestCase { + + @Rule + public final Expect mExpect = Expect.create(); + + protected final StandardSubjectBuilder expectWithMessage(String msg) { + return mExpect.withMessage(msg); + } + + protected final StandardSubjectBuilder expectWithMessage(String format, Object...args) { + return mExpect.withMessage(format, args); + } + + protected final <ComparableT extends Comparable<?>> ComparableSubject<ComparableT> expectThat( + ComparableT actual) { + return mExpect.that(actual); + } + + protected final BigDecimalSubject expectThat(BigDecimal actual) { + return mExpect.that(actual); + } + + protected final Subject expectThat(Object actual) { + return mExpect.that(actual); + } + + @GwtIncompatible("ClassSubject.java") + protected final ClassSubject expectThat(Class<?> actual) { + return mExpect.that(actual); + } + + protected final ThrowableSubject expectThat(Throwable actual) { + return mExpect.that(actual); + } + + protected final LongSubject expectThat(Long actual) { + return mExpect.that(actual); + } + + protected final DoubleSubject expectThat(Double actual) { + return mExpect.that(actual); + } + + protected final FloatSubject expectThat(Float actual) { + return mExpect.that(actual); + } + + protected final IntegerSubject expectThat(Integer actual) { + return mExpect.that(actual); + } + + protected final BooleanSubject expectThat(Boolean actual) { + return mExpect.that(actual); + } + + protected final StringSubject expectThat(String actual) { + return mExpect.that(actual); + } + + protected final IterableSubject expectThat(Iterable<?> actual) { + return mExpect.that(actual); + } + + protected final <T> ObjectArraySubject<T> expectThat(T[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveBooleanArraySubject expectThat(boolean[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveShortArraySubject expectThat(short[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveIntArraySubject expectThat(int[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveLongArraySubject expectThat(long[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveCharArraySubject expectThat(char[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveByteArraySubject expectThat(byte[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveFloatArraySubject expectThat(float[] actual) { + return mExpect.that(actual); + } + + protected final PrimitiveDoubleArraySubject expectThat(double[] actual) { + return mExpect.that(actual); + } + + protected final GuavaOptionalSubject expectThat(Optional<?> actual) { + return mExpect.that(actual); + } + + protected final MapSubject expectThat(Map<?, ?> actual) { + return mExpect.that(actual); + } + + protected final MultimapSubject expectThat(Multimap<?, ?> actual) { + return mExpect.that(actual); + } + + protected final MultisetSubject expectThat(Multiset<?> actual) { + return mExpect.that(actual); + } + + protected final TableSubject expectThat(Table<?, ?, ?> actual) { + return mExpect.that(actual); + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java new file mode 100644 index 000000000000..881dd504428d --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java @@ -0,0 +1,183 @@ +/* + * 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 com.android.server; + +import android.annotation.Nullable; +import android.util.Log; + +import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; +import com.android.internal.util.Preconditions; +import com.android.modules.utils.testing.StaticMockFixture; +import com.android.modules.utils.testing.StaticMockFixtureRule; + +import org.mockito.Mockito; +import org.mockito.quality.Strictness; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Rule to make it easier to use Extended Mockito. + * + * <p>It's derived from {@link StaticMockFixtureRule}, with the additional features: + * + * <ul> + * <li>Easier to define which classes must be statically mocked or spied + * <li>Automatically starts mocking (so tests don't need a mockito runner or rule) + * <li>Automatically clears the inlined mocks at the end (to avoid OOM) + * <li>Allows other customization like strictness + * </ul> + */ +public final class ExtendedMockitoRule extends StaticMockFixtureRule { + + private static final String TAG = ExtendedMockitoRule.class.getSimpleName(); + + private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); + + private final Object mTestClassInstance; + private final Strictness mStrictness; + + private ExtendedMockitoRule(Builder builder) { + super(() -> new SimpleStatickMockFixture(builder.mMockedStaticClasses, + builder.mSpiedStaticClasses, builder.mDynamicSessionBuilderConfigurator, + builder.mAfterSessionFinishedCallback)); + mTestClassInstance = builder.mTestClassInstance; + mStrictness = builder.mStrictness; + if (VERBOSE) { + Log.v(TAG, "strictness=" + mStrictness + ", testClassInstance" + mTestClassInstance + + ", mockedStaticClasses=" + builder.mMockedStaticClasses + + ", spiedStaticClasses=" + builder.mSpiedStaticClasses + + ", dynamicSessionBuilderConfigurator=" + + builder.mDynamicSessionBuilderConfigurator + + ", afterSessionFinishedCallback=" + builder.mAfterSessionFinishedCallback); + } + } + + @Override + public StaticMockitoSessionBuilder getSessionBuilder() { + StaticMockitoSessionBuilder sessionBuilder = super.getSessionBuilder(); + if (mStrictness != null) { + if (VERBOSE) { + Log.v(TAG, "Setting strictness to " + mStrictness + " on " + sessionBuilder); + } + sessionBuilder.strictness(mStrictness); + } + return sessionBuilder.initMocks(mTestClassInstance); + } + + public static final class Builder { + private final Object mTestClassInstance; + private @Nullable Strictness mStrictness; + private final List<Class<?>> mMockedStaticClasses = new ArrayList<>(); + private final List<Class<?>> mSpiedStaticClasses = new ArrayList<>(); + private @Nullable Visitor<StaticMockitoSessionBuilder> mDynamicSessionBuilderConfigurator; + private @Nullable Runnable mAfterSessionFinishedCallback; + + public Builder(Object testClassInstance) { + mTestClassInstance = Objects.requireNonNull(testClassInstance); + } + + public Builder setStrictness(Strictness strictness) { + mStrictness = Objects.requireNonNull(strictness); + return this; + } + + public Builder mockStatic(Class<?> clazz) { + Objects.requireNonNull(clazz); + Preconditions.checkState(!mMockedStaticClasses.contains(clazz), + "class %s already mocked", clazz); + mMockedStaticClasses.add(clazz); + return this; + } + + public Builder spyStatic(Class<?> clazz) { + Objects.requireNonNull(clazz); + Preconditions.checkState(!mSpiedStaticClasses.contains(clazz), + "class %s already spied", clazz); + mSpiedStaticClasses.add(clazz); + return this; + } + + public Builder dynamiclyConfigureSessionBuilder( + Visitor<StaticMockitoSessionBuilder> dynamicSessionBuilderConfigurator) { + mDynamicSessionBuilderConfigurator = Objects + .requireNonNull(dynamicSessionBuilderConfigurator); + return this; + } + + public Builder afterSessionFinished(Runnable runnable) { + mAfterSessionFinishedCallback = Objects.requireNonNull(runnable); + return this; + } + + public ExtendedMockitoRule build() { + return new ExtendedMockitoRule(this); + } + } + + private static final class SimpleStatickMockFixture implements StaticMockFixture { + + private final List<Class<?>> mMockedStaticClasses; + private final List<Class<?>> mSpiedStaticClasses; + @Nullable + private final Visitor<StaticMockitoSessionBuilder> mDynamicSessionBuilderConfigurator; + @Nullable + private final Runnable mAfterSessionFinishedCallback; + + private SimpleStatickMockFixture(List<Class<?>> mockedStaticClasses, + List<Class<?>> spiedStaticClasses, + @Nullable Visitor<StaticMockitoSessionBuilder> dynamicSessionBuilderConfigurator, + @Nullable Runnable afterSessionFinishedCallback) { + mMockedStaticClasses = mockedStaticClasses; + mSpiedStaticClasses = spiedStaticClasses; + mDynamicSessionBuilderConfigurator = dynamicSessionBuilderConfigurator; + mAfterSessionFinishedCallback = afterSessionFinishedCallback; + } + + @Override + public StaticMockitoSessionBuilder setUpMockedClasses( + StaticMockitoSessionBuilder sessionBuilder) { + mMockedStaticClasses.forEach((c) -> sessionBuilder.mockStatic(c)); + mSpiedStaticClasses.forEach((c) -> sessionBuilder.spyStatic(c)); + if (mDynamicSessionBuilderConfigurator != null) { + mDynamicSessionBuilderConfigurator.visit(sessionBuilder); + } + return sessionBuilder; + } + + @Override + public void setUpMockBehaviors() { + } + + @Override + public void tearDown() { + try { + if (mAfterSessionFinishedCallback != null) { + mAfterSessionFinishedCallback.run(); + } + } finally { + if (VERBOSE) { + Log.v(TAG, "calling Mockito.framework().clearInlineMocks()"); + } + // When using inline mock maker, clean up inline mocks to prevent OutOfMemory + // errors. See https://github.com/mockito/mockito/issues/1614 and b/259280359. + Mockito.framework().clearInlineMocks(); + } + } + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java deleted file mode 100644 index 48483a14a8a0..000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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. - */ -package com.android.server; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; - -import android.annotation.Nullable; -import android.util.Log; - -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -import com.google.common.truth.Expect; -import com.google.common.truth.StandardSubjectBuilder; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.rules.RuleChain; -import org.mockito.Mockito; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.lang.reflect.Constructor; - -/** - * Base class to make it easier to write tests that uses {@code ExtendedMockito}. - * - */ -public abstract class ExtendedMockitoTestCase { - - private static final String TAG = ExtendedMockitoTestCase.class.getSimpleName(); - - private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); - - /** - * Number of invocations, used to force a failure on {@link #forceFailure(int, Class, String)}. - */ - private static int sInvocationsCounter; - - /** - * Sessions follow the "Highlander Rule": There can be only one! - * - * <p>So, we keep track of that and force-close it if needed. - */ - @Nullable - private static MockitoSession sHighlanderSession; - - /** - * Points to where the current session was created. - */ - private static Exception sSessionCreationLocation; - - private MockitoSession mSession; - - protected final Expect mExpect = Expect.create(); - protected final DumpableDumperRule mDumpableDumperRule = new DumpableDumperRule(); - - @Rule - public final RuleChain mTwoRingsOfPowerAndOneChainToRuleThemAll = RuleChain - .outerRule(mDumpableDumperRule) - .around(mExpect); - - public ExtendedMockitoTestCase() { - sInvocationsCounter++; - } - - @Before - public final void startSession() { - if (VERBOSE) { - Log.v(TAG, "startSession() for " + getTestName() + " on thread " - + Thread.currentThread() + "; sHighlanderSession=" + sHighlanderSession); - } - createSessionLocation(); - finishHighlanderSessionIfNeeded("startSession()"); - StaticMockitoSessionBuilder builder = mockitoSession() - .initMocks(this) - .strictness(getSessionStrictness()); - initializeSession(builder); - sHighlanderSession = mSession = builder.startMocking(); - } - - private void createSessionLocation() { - try { - sSessionCreationLocation = new Exception(getTestName()); - } catch (Exception e) { - // Better safe than sorry... - Log.e(TAG, "Could not create sSessionCreationLocation with " + getTestName() - + " on thread " + Thread.currentThread(), e); - sSessionCreationLocation = e; - } - } - - /** - * Gets the session strictness. - * - * @return {@link Strictness.LENIENT} by default; subclasses can override. - */ - protected Strictness getSessionStrictness() { - return Strictness.LENIENT; - } - - /** - * Initializes the mockito session. - * - * <p>Typically used to define which classes should have static methods mocked or spied. - */ - protected void initializeSession(StaticMockitoSessionBuilder builder) { - if (VERBOSE) { - Log.v(TAG, "initializeSession()"); - } - } - - @After - public final void finishSession() throws Exception { - if (false) { // For obvious reasons, should NEVER be merged as true - forceFailure(1, RuntimeException.class, "to simulate an unfinished session"); - } - - // mSession.finishMocking() must ALWAYS be called (hence the over-protective try/finally - // statements), otherwise it would cause failures on future tests as mockito - // cannot start a session when a previous one is not finished - try { - if (VERBOSE) { - Log.v(TAG, "finishSession() for " + getTestName() + " on thread " - + Thread.currentThread() + "; sHighlanderSession=" + sHighlanderSession); - - } - } finally { - sHighlanderSession = null; - finishSessionMocking(); - afterSessionFinished(); - } - } - - /** - * Called after the mockito session was finished - * - * <p>This method should be used by subclasses that MUST do their cleanup after the session is - * finished (as methods marked with {@link After} in the subclasses would be called BEFORE - * that). - */ - protected void afterSessionFinished() { - if (VERBOSE) { - Log.v(TAG, "afterSessionFinished()"); - } - } - - private void finishSessionMocking() { - if (mSession == null) { - Log.w(TAG, getClass().getSimpleName() + ".finishSession(): no session"); - return; - } - try { - mSession.finishMocking(); - } finally { - // Shouldn't need to set mSession to null as JUnit always instantiate a new object, - // but it doesn't hurt.... - mSession = null; - // When using inline mock maker, clean up inline mocks to prevent OutOfMemory - // errors. See https://github.com/mockito/mockito/issues/1614 and b/259280359. - Mockito.framework().clearInlineMocks(); - } - } - - private void finishHighlanderSessionIfNeeded(String where) { - if (sHighlanderSession == null) { - if (VERBOSE) { - Log.v(TAG, "finishHighlanderSessionIfNeeded(): sHighlanderSession already null"); - } - return; - } - - if (sSessionCreationLocation != null) { - if (VERBOSE) { - Log.e(TAG, where + ": There can be only one! Closing unfinished session, " - + "created at", sSessionCreationLocation); - } else { - Log.e(TAG, where + ": There can be only one! Closing unfinished session, " - + "created at " + sSessionCreationLocation); - } - } else { - Log.e(TAG, where + ": There can be only one! Closing unfinished session created at " - + "unknown location"); - } - try { - sHighlanderSession.finishMocking(); - } catch (Throwable t) { - if (VERBOSE) { - Log.e(TAG, "Failed to close unfinished session on " + getTestName(), t); - } else { - Log.e(TAG, "Failed to close unfinished session on " + getTestName() + ": " + t); - } - } finally { - if (VERBOSE) { - Log.v(TAG, "Resetting sHighlanderSession at finishHighlanderSessionIfNeeded()"); - } - sHighlanderSession = null; - } - } - - /** - * Forces a failure at the given invocation of a test method by throwing an exception. - */ - protected final <T extends Throwable> void forceFailure(int invocationCount, - Class<T> failureClass, String reason) throws T { - if (sInvocationsCounter != invocationCount) { - Log.d(TAG, "forceFailure(" + invocationCount + "): no-op on invocation #" - + sInvocationsCounter); - return; - } - String message = "Throwing on invocation #" + sInvocationsCounter + ": " + reason; - Log.e(TAG, message); - T throwable; - try { - Constructor<T> constructor = failureClass.getConstructor(String.class); - throwable = constructor.newInstance("Throwing on invocation #" + sInvocationsCounter - + ": " + reason); - } catch (Exception e) { - throw new IllegalArgumentException("Could not create exception of class " + failureClass - + " using msg='" + message + "' as constructor"); - } - throw throwable; - } - - protected final @Nullable String getTestName() { - return mDumpableDumperRule.getTestName(); - } - - protected final StandardSubjectBuilder expectWithMessage(String msg) { - return mExpect.withMessage(msg); - } - - protected final StandardSubjectBuilder expectWithMessage(String format, Object...args) { - return mExpect.withMessage(format, args); - } -} diff --git a/services/tests/mockingservicestests/src/com/android/server/Visitor.java b/services/tests/mockingservicestests/src/com/android/server/Visitor.java new file mode 100644 index 000000000000..447910eba60b --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/Visitor.java @@ -0,0 +1,23 @@ +/* + * 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 com.android.server; + +/** + * Generic visitor. + */ +public interface Visitor<V> { + void visit(V visitee); +} diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java index 9dd2f82ad59b..b395f42478b1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -159,7 +159,6 @@ import android.util.SparseArray; import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.MockedVoidMethod; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; @@ -168,7 +167,7 @@ import com.android.server.AlarmManagerInternal; import com.android.server.AppStateTracker; import com.android.server.AppStateTrackerImpl; import com.android.server.DeviceIdleInternal; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExtendedMockitoRule; import com.android.server.LocalServices; import com.android.server.SystemClockTime.TimeConfidence; import com.android.server.SystemService; @@ -182,6 +181,7 @@ import com.android.server.usage.AppStandbyInternal; import libcore.util.EmptyArray; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; @@ -204,7 +204,7 @@ import java.util.function.LongConsumer; @Presubmit @SuppressWarnings("GuardedBy") // This test enforces synchronous behavior. @RunWith(AndroidJUnit4.class) -public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase { +public final class AlarmManagerServiceTest { private static final String TAG = AlarmManagerServiceTest.class.getSimpleName(); private static final int SYSTEM_UI_UID = 12345; private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID); @@ -411,14 +411,9 @@ public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase { } } - @Override - protected Strictness getSessionStrictness() { - return Strictness.WARN; - } - - @Override - protected void initializeSession(StaticMockitoSessionBuilder builder) { - builder + @Rule + public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .setStrictness(Strictness.WARN) .spyStatic(ActivityManager.class) .mockStatic(CompatChanges.class) .spyStatic(DateFormat.class) @@ -431,8 +426,10 @@ public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase { .mockStatic(ServiceManager.class) .mockStatic(Settings.Global.class) .mockStatic(SystemProperties.class) - .spyStatic(UserHandle.class); - } + .spyStatic(UserHandle.class) + .afterSessionFinished( + () -> LocalServices.removeServiceForTest(AlarmManagerInternal.class)) + .build(); @Before public final void setUp() { @@ -3805,9 +3802,4 @@ public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase { mListener.removeListenerAlarmsForCachedUid(TEST_CALLING_UID_2); assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); } - - @Override - public void afterSessionFinished() { - LocalServices.removeServiceForTest(AlarmManagerInternal.class); - } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java index e01a9a9d473a..9ceb5e7b018d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java @@ -31,11 +31,11 @@ import android.os.UserManager; import android.util.Log; import android.view.Display; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExtendedMockitoRule; import com.android.server.am.ActivityManagerService.Injector; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; @@ -45,7 +45,7 @@ import java.util.Arrays; * Run as {@code atest * FrameworksMockingServicesTests:com.android.server.am.ActivityManagerServiceInjectorTest} */ -public final class ActivityManagerServiceInjectorTest extends ExtendedMockitoTestCase { +public final class ActivityManagerServiceInjectorTest { private static final String TAG = ActivityManagerServiceInjectorTest.class.getSimpleName(); @@ -63,10 +63,10 @@ public final class ActivityManagerServiceInjectorTest extends ExtendedMockitoTes when(mContext.getSystemService(DisplayManager.class)).thenReturn(mDisplayManager); } - @Override - protected void initializeSession(StaticMockitoSessionBuilder builder) { - builder.spyStatic(UserManager.class); - } + @Rule + public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .spyStatic(UserManager.class) + .build(); @Test public void testGetDisplayIdsForStartingBackgroundUsers_notSupported() { diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java index dcdee37059a9..95c2ed2f841f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java @@ -78,18 +78,15 @@ import android.util.Pair; import androidx.test.filters.SmallTest; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; import com.android.internal.util.FrameworkStatsLog; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExtendedMockitoRule; import com.android.server.am.BroadcastQueueTest.SyncBarrier; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.junit.MockitoJUnitRunner; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; @@ -98,8 +95,7 @@ import java.util.ArrayList; import java.util.List; @SmallTest -@RunWith(MockitoJUnitRunner.class) -public class BroadcastQueueModernImplTest extends ExtendedMockitoTestCase { +public final class BroadcastQueueModernImplTest { private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID; private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1; @@ -118,15 +114,13 @@ public class BroadcastQueueModernImplTest extends ExtendedMockitoTestCase { BroadcastProcessQueue mHead; - @Override - protected void initializeSession(StaticMockitoSessionBuilder builder) { - builder.spyStatic(FrameworkStatsLog.class); - } + @Rule + public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .spyStatic(FrameworkStatsLog.class) + .build(); @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mHandlerThread = new HandlerThread(getClass().getSimpleName()); mHandlerThread.start(); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java index f8cfdf131a28..ec9e5b50579c 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java @@ -40,9 +40,8 @@ import android.text.TextUtils; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; import com.android.modules.utils.testing.TestableDeviceConfig; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExtendedMockitoRule; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.appop.AppOpsService; @@ -69,7 +68,7 @@ import java.util.concurrent.TimeUnit; * atest FrameworksMockingServicesTests:CachedAppOptimizerTest */ @Presubmit -public final class CachedAppOptimizerTest extends ExtendedMockitoTestCase { +public final class CachedAppOptimizerTest { private ServiceThread mThread; @@ -93,10 +92,11 @@ public final class CachedAppOptimizerTest extends ExtendedMockitoTestCase { public final ApplicationExitInfoTest.ServiceThreadRule mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); - @Override - protected void initializeSession(StaticMockitoSessionBuilder builder) { - mDeviceConfig.setUpMockedClasses(builder); - } + @Rule + public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .dynamiclyConfigureSessionBuilder( + sessionBuilder -> mDeviceConfig.setUpMockedClasses(sessionBuilder)) + .build(); @Before public void setUp() { diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java index 9f3bc3358a4c..b21478753301 100644 --- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java @@ -29,7 +29,7 @@ import android.content.res.AssetManager; import android.util.Log; import android.util.SparseArray; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExpectableTestCase; import libcore.io.Streams; @@ -44,7 +44,7 @@ import java.io.OutputStream; import java.util.Objects; /** This class contains unit tests for the {@link CpuInfoReader}. */ -public final class CpuInfoReaderTest extends ExtendedMockitoTestCase { +public final class CpuInfoReaderTest extends ExpectableTestCase { private static final String TAG = CpuInfoReaderTest.class.getSimpleName(); private static final String ROOT_DIR_NAME = "CpuInfoReaderTest"; private static final String VALID_CPUSET_DIR = "valid_cpuset"; @@ -426,7 +426,7 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase { .isNull(); } - private static void compareCpuInfos(String message, + private void compareCpuInfos(String message, SparseArray<CpuInfoReader.CpuInfo> expected, SparseArray<CpuInfoReader.CpuInfo> actual) { assertWithMessage("%s. Total CPU infos", message).that(actual.size()) @@ -435,7 +435,7 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase { int cpuCoreId = expected.keyAt(i); CpuInfoReader.CpuInfo expectedCpuInfo = expected.valueAt(i); CpuInfoReader.CpuInfo actualCpuInfo = actual.get(cpuCoreId); - assertWithMessage("%s. Core %d's CPU info", message, cpuCoreId).that(actualCpuInfo) + expectWithMessage("%s. Core %s's CPU info", message, cpuCoreId).that(actualCpuInfo) .isEqualTo(expectedCpuInfo); } } diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java index 7ab1363b5087..49a2cc696744 100644 --- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java @@ -32,16 +32,16 @@ import android.os.HandlerExecutor; import android.os.Looper; import android.os.ServiceManager; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExtendedMockitoRule; import com.android.server.LocalServices; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -public final class CpuMonitorServiceTest extends ExtendedMockitoTestCase { +public final class CpuMonitorServiceTest { private static final CpuAvailabilityMonitoringConfig TEST_CPU_AVAILABILITY_MONITORING_CONFIG = new CpuAvailabilityMonitoringConfig.Builder(CPUSET_ALL) .addThreshold(30).addThreshold(70).build(); @@ -56,10 +56,10 @@ public final class CpuMonitorServiceTest extends ExtendedMockitoTestCase { private HandlerExecutor mHandlerExecutor; private CpuMonitorInternal mLocalService; - @Override - protected void initializeSession(StaticMockitoSessionBuilder builder) { - builder.mockStatic(ServiceManager.class); - } + @Rule + public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .mockStatic(ServiceManager.class) + .build(); @Before public void setUp() { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java index 1ed2f789d9b2..564893c3c629 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java @@ -40,9 +40,8 @@ import android.util.SparseArray; import androidx.test.annotation.UiThreadTest; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; import com.android.internal.widget.LockSettingsInternal; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.ExtendedMockitoRule; import com.android.server.LocalServices; import com.android.server.am.UserState; import com.android.server.pm.UserManagerService.UserData; @@ -50,13 +49,14 @@ import com.android.server.storage.DeviceStorageMonitorInternal; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; /** * Run as {@code atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest} */ -public final class UserManagerServiceTest extends ExtendedMockitoTestCase { +public final class UserManagerServiceTest { private static final String TAG = UserManagerServiceTest.class.getSimpleName(); @@ -84,6 +84,13 @@ public final class UserManagerServiceTest extends ExtendedMockitoTestCase { */ private static final int PROFILE_USER_ID = 643; + @Rule + public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .spyStatic(UserManager.class) + .spyStatic(LocalServices.class) + .mockStatic(Settings.Global.class) + .build(); + private final Object mPackagesLock = new Object(); private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation() .getTargetContext(); @@ -109,14 +116,6 @@ public final class UserManagerServiceTest extends ExtendedMockitoTestCase { */ private UserManagerInternal mUmi; - @Override - protected void initializeSession(StaticMockitoSessionBuilder builder) { - builder - .spyStatic(UserManager.class) - .spyStatic(LocalServices.class) - .mockStatic(Settings.Global.class); - } - @Before @UiThreadTest // Needed to initialize main handler public void setFixtures() { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java index 38cf6341e798..9aa53db6fe1b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java @@ -20,8 +20,6 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE; -import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE; -import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE; import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE; import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible; import static com.android.server.pm.UserVisibilityChangedEvent.onVisible; @@ -128,7 +126,8 @@ public final class UserVisibilityMediatorMUPANDTest listener.verify(); } - /* TODO: re-add + + /* TODO(b/261538337): re-add after the reverted CL is merged again @Test public void diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java index 5176d684ace6..1bf921c503d8 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java @@ -45,7 +45,8 @@ import android.util.IntArray; import android.util.Log; import com.android.internal.util.Preconditions; -import com.android.server.ExtendedMockitoTestCase; +import com.android.server.DumpableDumperRule; +import com.android.server.ExpectableTestCase; import org.junit.Before; import org.junit.Test; @@ -64,7 +65,7 @@ import java.util.Arrays; * is visible, display associated to the user, etc...) for each scenario (full user started on fg, * profile user started on bg, etc...). */ -abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { +abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase { private static final String TAG = UserVisibilityMediatorTestCase.class.getSimpleName(); @@ -125,6 +126,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { mBackgroundUserOnDefaultDisplayAllowed = backgroundUserOnDefaultDisplayAllowed; } + protected final DumpableDumperRule mDumpableDumperRule = new DumpableDumperRule(); + @Before public final void setFixtures() { mHandler = Handler.getMain(); |