From 0ba15f156807c1b2ccaed4f8fe8bda48b6e08da0 Mon Sep 17 00:00:00 2001 From: Alexander Dorokhine Date: Tue, 9 Nov 2021 12:02:34 -0800 Subject: [PATCH] Move TestableDeviceConfig to modules-utils. This allows it to be reused by mainline modules. Bug: 192108282 Test: AppSearchMockingServicesTests ModulesUtilsTests FrameworksMockingServicesTests Change-Id: I605ae012902141717a0bc3001fb5166c81c53581 --- .../tests/mockingservicestests/Android.bp | 7 +- .../android/server/am/CacheOomRankerTest.java | 2 +- .../server/am/CachedAppOptimizerTest.java | 2 +- .../server/blob/BlobStoreConfigTest.java | 2 +- .../AppCompatOverridesServiceTest.java | 2 +- .../server/power/FaceDownDetectorTest.java | 2 +- .../server/power/ScreenUndimDetectorTest.java | 2 +- .../testables/MultipleStaticMocksTest.java | 163 ---------- .../server/testables/StaticMockFixture.java | 56 ---- .../testables/StaticMockFixtureRule.java | 141 --------- .../testables/StaticMockFixtureRuleTest.java | 258 ---------------- .../testables/TestableDeviceConfig.java | 284 ------------------ ...leDeviceConfigAndOtherStaticMocksTest.java | 172 ----------- .../testables/TestableDeviceConfigTest.java | 229 -------------- 14 files changed, 10 insertions(+), 1312 deletions(-) delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/MultipleStaticMocksTest.java delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixture.java delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRule.java delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRuleTest.java delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfig.java delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigAndOtherStaticMocksTest.java delete mode 100644 services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigTest.java diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp index 6bb127a1b3c58..48a8b1bca99b0 100644 --- a/services/tests/mockingservicestests/Android.bp +++ b/services/tests/mockingservicestests/Android.bp @@ -29,7 +29,10 @@ package { android_test { name: "FrameworksMockingServicesTests", - defaults: ["FrameworkMockingServicesTests-jni-defaults"], + defaults: [ + "FrameworkMockingServicesTests-jni-defaults", + "modules-utils-testable-device-config-defaults", + ], srcs: [ "src/**/*.java", @@ -67,9 +70,7 @@ android_test { ], jni_libs: [ - "libdexmakerjvmtiagent", "libpsi", - "libstaticjvmtiagent", ], certificate: "platform", diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java index 609768c0e62a4..766ba72d7cb72 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java @@ -38,10 +38,10 @@ import android.provider.DeviceConfig; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.modules.utils.testing.TestableDeviceConfig; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.appop.AppOpsService; -import com.android.server.testables.TestableDeviceConfig; import com.android.server.wm.ActivityTaskManagerService; import org.junit.Before; 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 a883293b13b99..303f95565c763 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java @@ -40,10 +40,10 @@ import android.text.TextUtils; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.modules.utils.testing.TestableDeviceConfig; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.appop.AppOpsService; -import com.android.server.testables.TestableDeviceConfig; import com.android.server.wm.ActivityTaskManagerService; import org.junit.After; diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreConfigTest.java b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreConfigTest.java index ad19a48931536..d747914caa9af 100644 --- a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreConfigTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreConfigTest.java @@ -29,7 +29,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.server.testables.TestableDeviceConfig; +import com.android.modules.utils.testing.TestableDeviceConfig; import org.junit.Before; import org.junit.Rule; diff --git a/services/tests/mockingservicestests/src/com/android/server/compat/overrides/AppCompatOverridesServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/compat/overrides/AppCompatOverridesServiceTest.java index 007191f026319..349da03e3f4e2 100644 --- a/services/tests/mockingservicestests/src/com/android/server/compat/overrides/AppCompatOverridesServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/compat/overrides/AppCompatOverridesServiceTest.java @@ -59,7 +59,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.compat.CompatibilityOverrideConfig; import com.android.internal.compat.CompatibilityOverridesToRemoveConfig; import com.android.internal.compat.IPlatformCompat; -import com.android.server.testables.TestableDeviceConfig.TestableDeviceConfigRule; +import com.android.modules.utils.testing.TestableDeviceConfig.TestableDeviceConfigRule; import org.junit.Before; import org.junit.Rule; diff --git a/services/tests/mockingservicestests/src/com/android/server/power/FaceDownDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/FaceDownDetectorTest.java index e093f13963850..9fac0c0298156 100644 --- a/services/tests/mockingservicestests/src/com/android/server/power/FaceDownDetectorTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/power/FaceDownDetectorTest.java @@ -34,7 +34,7 @@ import android.testing.TestableContext; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.server.testables.TestableDeviceConfig; +import com.android.modules.utils.testing.TestableDeviceConfig; import org.junit.Before; import org.junit.ClassRule; diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java index f94377fe51c23..6a3548178cbac 100644 --- a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java @@ -36,7 +36,7 @@ import android.testing.TestableContext; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.server.testables.TestableDeviceConfig; +import com.android.modules.utils.testing.TestableDeviceConfig; import org.junit.Before; import org.junit.ClassRule; diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/MultipleStaticMocksTest.java b/services/tests/mockingservicestests/src/com/android/server/testables/MultipleStaticMocksTest.java deleted file mode 100644 index c0ab70a57327f..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/MultipleStaticMocksTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - -import static com.google.common.truth.Truth.assertThat; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class MultipleStaticMocksTest { - @Rule - public StaticMockFixtureRule mStaticMockFixtureRule = - new StaticMockFixtureRule(AB::new, CD::new); - - private List mCollected; - - @Test - public void testMultipleStaticMocks() throws Exception { - mCollected = new ArrayList<>(); - int n = 0; - - A.a(); - n = verifyCollected(n, "A.a"); - - D.b(); - n = verifyCollected(n, "D.b"); - - C.b(); - n = verifyCollected(n, "C.b"); - - B.a(); - n = verifyCollected(n, "B.a"); - } - - private int verifyCollected(int n, String... last) { - assertThat(mCollected).hasSize(n + last.length); - assertThat(mCollected.subList(n, mCollected.size())) - .containsExactlyElementsIn(last).inOrder(); - return n + last.length; - } - - private static class A { - /* package */ static void a() {} - /* package */ static void b() {} - } - - private static class B { - /* package */ static void a() {} - /* package */ static void b() {} - } - - private static class C { - /* package */ static void a() {} - /* package */ static void b() {} - } - - private static class D { - /* package */ static void a() {} - /* package */ static void b() {} - } - - /** - * AB StaticMockFixture class that handles two mocked classes, {@link A} and {@link B}. - */ - private class AB implements StaticMockFixture { - @Override - public StaticMockitoSessionBuilder setUpMockedClasses( - StaticMockitoSessionBuilder sessionBuilder) { - sessionBuilder.spyStatic(A.class); - sessionBuilder.spyStatic(B.class); - return sessionBuilder; - } - - @Override - public void setUpMockBehaviors() { - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("A.a"); - return null; - }).when(A::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("A.b"); - return null; - }).when(A::b); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("B.a"); - return null; - }).when(B::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("B.b"); - return null; - }).when(B::b); - } - - @Override - public void tearDown() { - - } - } - - /** - * AB StaticMockFixture class that handles two mocked classes, {@link C} and {@link D}. - */ - private class CD implements StaticMockFixture { - @Override - public StaticMockitoSessionBuilder setUpMockedClasses( - StaticMockitoSessionBuilder sessionBuilder) { - sessionBuilder.spyStatic(C.class); - sessionBuilder.spyStatic(D.class); - return sessionBuilder; - } - - @Override - public void setUpMockBehaviors() { - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("C.a"); - return null; - }).when(C::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("C.b"); - return null; - }).when(C::b); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("D.a"); - return null; - }).when(D::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("D.b"); - return null; - }).when(D::b); - } - - @Override - public void tearDown() { - - } - } -} diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixture.java b/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixture.java deleted file mode 100644 index 0303fe1e1eb05..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixture.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - - -import com.android.dx.mockito.inline.extended.StaticMockitoSession; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -/** - * Provides support for a set of static mocks for use within a single shared - * {@link StaticMockitoSession}. - */ -public interface StaticMockFixture { - /** - * Adds any required mock or spy classes managed by this {@link StaticMockFixture} to the - * {@link StaticMockitoSessionBuilder} provided. - * - * Call this to set up the classes that this expects to be mocked, by adding them to the - * {@link StaticMockitoSessionBuilder} using - * {@link StaticMockitoSessionBuilder#mockStatic(Class)}, - * {@link StaticMockitoSessionBuilder#spyStatic(Class)} or similar as appropriate. - * - * @param sessionBuilder the {@link StaticMockitoSessionBuilder} to which the classes should be - * added to mock, spy, or otherwise as required - * @return sessionBuilder, to allow for fluent programming - */ - StaticMockitoSessionBuilder setUpMockedClasses(StaticMockitoSessionBuilder sessionBuilder); - - /** - * Configures the behaviours of any mock or spy classes managed by this - * {@link StaticMockFixture}. - * - * Call this after {@link StaticMockitoSessionBuilder#startMocking()} has been called. - * This sets up any default behaviors for the mocks, spys, etc. - */ - void setUpMockBehaviors(); - - /** - * Tear everything down. - */ - void tearDown(); -} diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRule.java b/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRule.java deleted file mode 100644 index 3566aee2eba39..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRule.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; - -import com.android.dx.mockito.inline.extended.StaticMockitoSession; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -import org.junit.AssumptionViolatedException; -import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; -import org.mockito.quality.Strictness; - -import java.util.function.Supplier; - -/** - *

StaticMockFixtureRule is a {@link TestRule} that wraps one or more {@link StaticMockFixture}s - * to set them up and tear it down automatically. This works well when you have no other static - * mocks than the ones supported by their respective {@link StaticMockFixture}s.

- * - *

StaticMockFixtureRule should be defined as a rule on your test so it can clean up after - * itself. Like the following:

- *
-*  public final StaticMockFixture mStaticMockFixtures = ...;
- * @Rule
- * public final StaticMockFixtureRule mStaticMockFixtureRule =
- *     new StaticMockFixtureRule(mStaticMockFixtures);
- * 
- */ -public class StaticMockFixtureRule implements TestRule { - private StaticMockitoSession mMockitoSession; - private StaticMockFixture[] mStaticMockFixtures; - private Supplier[] mSupplier; - - /** - * Constructs a StaticMockFixtureRule that always uses the same {@link StaticMockFixture} - * instance(s). - * - * @param staticMockFixtures the {@link StaticMockFixture}(s) to use. - */ - public StaticMockFixtureRule(StaticMockFixture... staticMockFixtures) { - mStaticMockFixtures = staticMockFixtures; - mSupplier = null; - } - - /** - * Constructs a StaticMockFixtureRule that retrieves a new {@link StaticMockFixture} instance - * from one or more {@link Supplier}s for each test invocation. - * - * @param supplier the {@link Supplier}(s) that will supply the - * {@link StaticMockFixture}(s). - */ - @SafeVarargs - public StaticMockFixtureRule(Supplier... supplier) { - mStaticMockFixtures = null; - mSupplier = supplier; - } - - @Override - public Statement apply(Statement base, Description description) { - StaticMockitoSessionBuilder sessionBuilder = getSessionBuilder(); - - if (mSupplier != null) { - mStaticMockFixtures = new StaticMockFixture[mSupplier.length]; - for (int i = 0; i < mSupplier.length; i++) { - mStaticMockFixtures[i] = mSupplier[i].get(); - } - } - - for (int i = 0; i < mStaticMockFixtures.length; i++) { - sessionBuilder = mStaticMockFixtures[i].setUpMockedClasses(sessionBuilder); - } - - mMockitoSession = sessionBuilder.startMocking(); - - for (int i = 0; i < mStaticMockFixtures.length; i++) { - mStaticMockFixtures[i].setUpMockBehaviors(); - } - - return new TestWatcher() { - @Override - protected void succeeded(Description description) { - tearDown(null); - } - - @Override - protected void skipped(AssumptionViolatedException e, Description description) { - tearDown(e); - } - - @Override - protected void failed(Throwable e, Description description) { - tearDown(e); - } - }.apply(base, description); - } - - /** - * This allows overriding the creation of the builder for a new {@link StaticMockitoSession}. - * Mainly for testing, but also useful if you have other requirements for the session. - * - * @return a new {@link StaticMockitoSessionBuilder}. - */ - public StaticMockitoSessionBuilder getSessionBuilder() { - return mockitoSession().strictness(Strictness.LENIENT); - } - - private void tearDown(Throwable e) { - mMockitoSession.finishMocking(e); - - for (int i = mStaticMockFixtures.length - 1; i >= 0; i--) { - mStaticMockFixtures[i].tearDown(); - if (mSupplier != null) { - mStaticMockFixtures[i] = null; - } - } - - if (mSupplier != null) { - mStaticMockFixtures = null; - } - - mMockitoSession = null; - } -} diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRuleTest.java b/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRuleTest.java deleted file mode 100644 index 8e0ccf01d7a74..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/StaticMockFixtureRuleTest.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.mockito.quality.Strictness.LENIENT; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.dx.mockito.inline.extended.StaticMockitoSession; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -import org.junit.After; -import org.junit.AssumptionViolatedException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.Description; -import org.junit.runner.RunWith; -import org.junit.runners.model.Statement; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoSession; - -import java.util.function.Supplier; - -/** Tests that StaticMockFixture manages fixtures and suppliers correctly. */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class StaticMockFixtureRuleTest { - private MockitoSession mMockitoSession; - - @Mock private StaticMockitoSessionBuilder mSessionBuilder; - @Mock private StaticMockitoSession mSession; - @Mock private StaticMockFixture mA1; - @Mock private StaticMockFixture mB1; - @Mock private StaticMockFixture mA2; - @Mock private StaticMockFixture mB2; - @Mock private Supplier mSupplyA; - @Mock private Supplier mSupplyB; - @Mock private Statement mStatement; - @Mock private Statement mSkipStatement; - @Mock private Statement mThrowStatement; - @Mock private Description mDescription; - - @Before - public void setUp() throws Throwable { - mMockitoSession = Mockito.mockitoSession() - .strictness(LENIENT) - .initMocks(this) - .startMocking(); - prepareMockBehaviours(); - } - - @After - public void tearDown() { - mMockitoSession.finishMocking(); - } - - private void prepareFixtureMocks(StaticMockFixture... mocks) { - for (StaticMockFixture mock : mocks) { - when(mock.setUpMockedClasses(any())).thenAnswer( - invocation -> invocation.getArgument(0)); - doNothing().when(mock).setUpMockBehaviors(); - } - } - - private void prepareMockBehaviours() throws Throwable { - when(mSessionBuilder.startMocking()).thenReturn(mSession); - when(mSupplyA.get()).thenReturn(mA1, mA2); - when(mSupplyB.get()).thenReturn(mB1, mB2); - prepareFixtureMocks(mA1, mA2, mB1, mB2); - when(mA1.setUpMockedClasses(any())).thenAnswer(invocation -> invocation.getArgument(0)); - doNothing().when(mA1).setUpMockBehaviors(); - when(mB1.setUpMockedClasses(any())).thenAnswer(invocation -> invocation.getArgument(0)); - doNothing().when(mB1).setUpMockBehaviors(); - doNothing().when(mStatement).evaluate(); - doThrow(new AssumptionViolatedException("bad assumption, test should be skipped")) - .when(mSkipStatement).evaluate(); - doThrow(new IllegalArgumentException("bad argument, test should be failed")) - .when(mThrowStatement).evaluate(); - doNothing().when(mA1).tearDown(); - doNothing().when(mB1).tearDown(); - } - - private InOrder mocksInOrder() { - return inOrder(mSessionBuilder, mSession, mSupplyA, mSupplyB, mA1, mA2, mB1, mB2, - mStatement, mSkipStatement, mThrowStatement, mDescription); - } - - private void verifyNoMoreImportantMockInteractions() { - verifyNoMoreInteractions(mSupplyA, mSupplyB, mA1, mA2, mB1, mB2, mStatement, - mSkipStatement, mThrowStatement); - } - - @Test - public void testRuleWorksWithExplicitFixtures() throws Throwable { - InOrder inOrder = mocksInOrder(); - - StaticMockFixtureRule rule = new StaticMockFixtureRule(mA1, mB1) { - @Override public StaticMockitoSessionBuilder getSessionBuilder() { - return mSessionBuilder; - } - }; - Statement runMe = rule.apply(mStatement, mDescription); - - inOrder.verify(mA1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mB1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mA1).setUpMockBehaviors(); - inOrder.verify(mB1).setUpMockBehaviors(); - - runMe.evaluate(); - - inOrder.verify(mStatement).evaluate(); - // note: tearDown in reverse order - inOrder.verify(mB1).tearDown(); - inOrder.verify(mA1).tearDown(); - - // Round two: use the same fixtures again. - rule.apply(mStatement, mDescription).evaluate(); - - inOrder.verify(mA1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mB1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mA1).setUpMockBehaviors(); - inOrder.verify(mB1).setUpMockBehaviors(); - inOrder.verify(mStatement).evaluate(); - // note: tearDown in reverse order - inOrder.verify(mB1).tearDown(); - inOrder.verify(mA1).tearDown(); - - verifyNoMoreImportantMockInteractions(); - } - - @Test - public void testRuleWorksWithFixtureSuppliers() throws Throwable { - InOrder inOrder = mocksInOrder(); - - StaticMockFixtureRule rule = new StaticMockFixtureRule(mSupplyA, mSupplyB) { - @Override public StaticMockitoSessionBuilder getSessionBuilder() { - return mSessionBuilder; - } - }; - Statement runMe = rule.apply(mStatement, mDescription); - - inOrder.verify(mSupplyA).get(); - inOrder.verify(mSupplyB).get(); - inOrder.verify(mA1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mB1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mA1).setUpMockBehaviors(); - inOrder.verify(mB1).setUpMockBehaviors(); - - runMe.evaluate(); - - inOrder.verify(mStatement).evaluate(); - // note: tearDown in reverse order - inOrder.verify(mB1).tearDown(); - inOrder.verify(mA1).tearDown(); - - // Round two: use the same suppliers again to retrieve different fixtures: mA2 and mB2 - rule.apply(mStatement, mDescription).evaluate(); - - inOrder.verify(mSupplyA).get(); - inOrder.verify(mSupplyB).get(); - inOrder.verify(mA2).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mB2).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mA2).setUpMockBehaviors(); - inOrder.verify(mB2).setUpMockBehaviors(); - inOrder.verify(mStatement).evaluate(); - // note: tearDown in reverse order - inOrder.verify(mB2).tearDown(); - inOrder.verify(mA2).tearDown(); - - verifyNoMoreImportantMockInteractions(); - } - - @Test - public void testTearDownOnSkippedTests() throws Throwable { - InOrder inOrder = mocksInOrder(); - - StaticMockFixtureRule rule = new StaticMockFixtureRule(mA1, mB1) { - @Override public StaticMockitoSessionBuilder getSessionBuilder() { - return mSessionBuilder; - } - }; - Statement skipStatement = rule.apply(mSkipStatement, mDescription); - - inOrder.verify(mA1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mB1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mA1).setUpMockBehaviors(); - inOrder.verify(mB1).setUpMockBehaviors(); - - try { - skipStatement.evaluate(); - fail("AssumptionViolatedException should have been thrown"); - } catch (AssumptionViolatedException e) { - // expected - } - - inOrder.verify(mSkipStatement).evaluate(); - // note: tearDown in reverse order - inOrder.verify(mB1).tearDown(); - inOrder.verify(mA1).tearDown(); - - verifyNoMoreImportantMockInteractions(); - } - - @Test - public void testTearDownOnFailedTests() throws Throwable { - InOrder inOrder = mocksInOrder(); - - StaticMockFixtureRule rule = new StaticMockFixtureRule(mA1, mB1) { - @Override public StaticMockitoSessionBuilder getSessionBuilder() { - return mSessionBuilder; - } - }; - Statement failStatement = rule.apply(mThrowStatement, mDescription); - - inOrder.verify(mA1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mB1).setUpMockedClasses(any(StaticMockitoSessionBuilder.class)); - inOrder.verify(mA1).setUpMockBehaviors(); - inOrder.verify(mB1).setUpMockBehaviors(); - - try { - failStatement.evaluate(); - fail("IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - // expected - } - - inOrder.verify(mThrowStatement).evaluate(); - // note: tearDown in reverse order - inOrder.verify(mB1).tearDown(); - inOrder.verify(mA1).tearDown(); - - verifyNoMoreImportantMockInteractions(); - } -} diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfig.java b/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfig.java deleted file mode 100644 index 60a7f78c6949d..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfig.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.when; - -import android.provider.DeviceConfig; -import android.provider.DeviceConfig.Properties; -import android.util.ArrayMap; -import android.util.Pair; - -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -import org.junit.rules.TestRule; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; -import org.mockito.stubbing.Answer; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; - -/** - * TestableDeviceConfig is a {@link StaticMockFixture} that uses ExtendedMockito to replace the real - * implementation of DeviceConfig with essentially a local HashMap in the callers process. This - * allows for unit testing that do not modify the real DeviceConfig on the device at all. - */ -public final class TestableDeviceConfig implements StaticMockFixture { - - private Map> - mOnPropertiesChangedListenerMap = new HashMap<>(); - private Map mKeyValueMap = new ConcurrentHashMap<>(); - - /** - * Clears out all local overrides. - */ - public void clearDeviceConfig() { - mKeyValueMap.clear(); - } - - /** - * {@inheritDoc} - */ - @Override - public StaticMockitoSessionBuilder setUpMockedClasses( - StaticMockitoSessionBuilder sessionBuilder) { - sessionBuilder.spyStatic(DeviceConfig.class); - return sessionBuilder; - } - - /** - * {@inheritDoc} - */ - @Override - public void setUpMockBehaviors() { - doAnswer((Answer) invocationOnMock -> { - String namespace = invocationOnMock.getArgument(0); - Executor executor = invocationOnMock.getArgument(1); - DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener = - invocationOnMock.getArgument(2); - mOnPropertiesChangedListenerMap.put( - onPropertiesChangedListener, new Pair<>(namespace, executor)); - return null; - }).when(() -> DeviceConfig.addOnPropertiesChangedListener( - anyString(), any(Executor.class), - any(DeviceConfig.OnPropertiesChangedListener.class))); - - doAnswer((Answer) invocationOnMock -> { - String namespace = invocationOnMock.getArgument(0); - String name = invocationOnMock.getArgument(1); - String value = invocationOnMock.getArgument(2); - mKeyValueMap.put(getKey(namespace, name), value); - invokeListeners(namespace, getProperties(namespace, name, value)); - return true; - } - ).when(() -> DeviceConfig.setProperty(anyString(), anyString(), anyString(), anyBoolean())); - - doAnswer((Answer) invocationOnMock -> { - String namespace = invocationOnMock.getArgument(0); - String name = invocationOnMock.getArgument(1); - mKeyValueMap.remove(getKey(namespace, name)); - invokeListeners(namespace, getProperties(namespace, name, null)); - return true; - } - ).when(() -> DeviceConfig.deleteProperty(anyString(), anyString())); - - doAnswer((Answer) invocationOnMock -> { - Properties properties = invocationOnMock.getArgument(0); - String namespace = properties.getNamespace(); - Map keyValues = new ArrayMap<>(); - for (String name : properties.getKeyset()) { - String value = properties.getString(name, /* defaultValue= */ ""); - mKeyValueMap.put(getKey(namespace, name), value); - keyValues.put(name.toLowerCase(), value); - } - invokeListeners(namespace, getProperties(namespace, keyValues)); - return true; - } - ).when(() -> DeviceConfig.setProperties(any(Properties.class))); - - doAnswer((Answer) invocationOnMock -> { - String namespace = invocationOnMock.getArgument(0); - String name = invocationOnMock.getArgument(1); - return mKeyValueMap.get(getKey(namespace, name)); - }).when(() -> DeviceConfig.getProperty(anyString(), anyString())); - - doAnswer((Answer) invocationOnMock -> { - String namespace = invocationOnMock.getArgument(0); - final int varargStartIdx = 1; - Map keyValues = new ArrayMap<>(); - if (invocationOnMock.getArguments().length == varargStartIdx) { - mKeyValueMap.entrySet().forEach(entry -> { - Pair nameSpaceAndName = getNameSpaceAndName(entry.getKey()); - if (!nameSpaceAndName.first.equals(namespace)) { - return; - } - keyValues.put(nameSpaceAndName.second.toLowerCase(), entry.getValue()); - }); - } else { - for (int i = varargStartIdx; i < invocationOnMock.getArguments().length; ++i) { - String name = invocationOnMock.getArgument(i); - keyValues.put(name.toLowerCase(), mKeyValueMap.get(getKey(namespace, name))); - } - } - return getProperties(namespace, keyValues); - }).when(() -> DeviceConfig.getProperties(anyString(), ArgumentMatchers.any())); - } - - /** - * {@inheritDoc} - */ - @Override - public void tearDown() { - clearDeviceConfig(); - mOnPropertiesChangedListenerMap.clear(); - } - - private static String getKey(String namespace, String name) { - return namespace + "/" + name; - } - - private Pair getNameSpaceAndName(String key) { - final String[] values = key.split("/"); - return Pair.create(values[0], values[1]); - } - - private void invokeListeners(String namespace, Properties properties) { - for (DeviceConfig.OnPropertiesChangedListener listener : - mOnPropertiesChangedListenerMap.keySet()) { - if (namespace.equals(mOnPropertiesChangedListenerMap.get(listener).first)) { - mOnPropertiesChangedListenerMap.get(listener).second.execute( - () -> listener.onPropertiesChanged(properties)); - } - } - } - - private Properties getProperties(String namespace, String name, String value) { - return getProperties(namespace, Collections.singletonMap(name.toLowerCase(), value)); - } - - private Properties getProperties(String namespace, Map keyValues) { - Properties properties = Mockito.mock(Properties.class); - when(properties.getNamespace()).thenReturn(namespace); - when(properties.getKeyset()).thenReturn(keyValues.keySet()); - when(properties.getBoolean(anyString(), anyBoolean())).thenAnswer( - invocation -> { - String key = invocation.getArgument(0); - boolean defaultValue = invocation.getArgument(1); - final String value = keyValues.get(key.toLowerCase()); - if (value != null) { - return Boolean.parseBoolean(value); - } else { - return defaultValue; - } - } - ); - when(properties.getFloat(anyString(), anyFloat())).thenAnswer( - invocation -> { - String key = invocation.getArgument(0); - float defaultValue = invocation.getArgument(1); - final String value = keyValues.get(key.toLowerCase()); - if (value != null) { - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } else { - return defaultValue; - } - } - ); - when(properties.getInt(anyString(), anyInt())).thenAnswer( - invocation -> { - String key = invocation.getArgument(0); - int defaultValue = invocation.getArgument(1); - final String value = keyValues.get(key.toLowerCase()); - if (value != null) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } else { - return defaultValue; - } - } - ); - when(properties.getLong(anyString(), anyLong())).thenAnswer( - invocation -> { - String key = invocation.getArgument(0); - long defaultValue = invocation.getArgument(1); - final String value = keyValues.get(key.toLowerCase()); - if (value != null) { - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } else { - return defaultValue; - } - } - ); - when(properties.getString(anyString(), nullable(String.class))).thenAnswer( - invocation -> { - String key = invocation.getArgument(0); - String defaultValue = invocation.getArgument(1); - final String value = keyValues.get(key.toLowerCase()); - if (value != null) { - return value; - } else { - return defaultValue; - } - } - ); - - return properties; - } - - /** - *

TestableDeviceConfigRule is a {@link TestRule} that wraps a {@link TestableDeviceConfig} - * to set it up and tear it down automatically. This works well when you have no other static - * mocks.

- * - *

TestableDeviceConfigRule should be defined as a rule on your test so it can clean up after - * itself. Like the following:

- *
-     * @Rule
-     * public final TestableDeviceConfigRule mTestableDeviceConfigRule =
-     *     new TestableDeviceConfigRule();
-     * 
- */ - public static class TestableDeviceConfigRule extends StaticMockFixtureRule { - public TestableDeviceConfigRule() { - super(TestableDeviceConfig::new); - } - } -} diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigAndOtherStaticMocksTest.java b/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigAndOtherStaticMocksTest.java deleted file mode 100644 index 9616d13e42fea..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigAndOtherStaticMocksTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - -import android.provider.DeviceConfig; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class TestableDeviceConfigAndOtherStaticMocksTest { - @Rule - public StaticMockFixtureRule mStaticMockFixtureRule = - new StaticMockFixtureRule(TestableDeviceConfig::new, AB::new, CD::new); - - private List mCollected; - - @Test - public void testDeviceConfigAndOtherStaticMocks() throws Exception { - mCollected = new ArrayList<>(); - int n = 0; - - String namespace = "foo"; - String flag = "bar"; - String flagValue = "new value"; - - Assert.assertNull(DeviceConfig.getProperty(namespace, flag)); - - A.a(); - verifyCollected(++n, "A.a"); - - DeviceConfig.setProperty(namespace, flag, flagValue, false); - - D.b(); - verifyCollected(++n, "D.b"); - - Assert.assertEquals(flagValue, DeviceConfig.getProperty(namespace, flag)); - - C.b(); - verifyCollected(++n, "C.b"); - - B.a(); - verifyCollected(++n, "B.a"); - } - - private void verifyCollected(int n, String last) { - Assert.assertEquals(n, mCollected.size()); - Assert.assertEquals(last, mCollected.get(n - 1)); - } - - private static class A { - /* package */ static void a() {} - /* package */ static void b() {} - } - - private static class B { - /* package */ static void a() {} - /* package */ static void b() {} - } - - private static class C { - /* package */ static void a() {} - /* package */ static void b() {} - } - - private static class D { - /* package */ static void a() {} - /* package */ static void b() {} - } - - /** - * AB StaticMockFixture class that handles two mocked classes, {@link A} and {@link B}. - */ - private class AB implements StaticMockFixture { - @Override - public StaticMockitoSessionBuilder setUpMockedClasses( - StaticMockitoSessionBuilder sessionBuilder) { - sessionBuilder.spyStatic(A.class); - sessionBuilder.spyStatic(B.class); - return sessionBuilder; - } - - @Override - public void setUpMockBehaviors() { - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("A.a"); - return null; - }).when(A::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("A.b"); - return null; - }).when(A::b); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("B.a"); - return null; - }).when(B::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("B.b"); - return null; - }).when(B::b); - } - - @Override - public void tearDown() { - - } - } - - /** - * AB StaticMockFixture class that handles two mocked classes, {@link C} and {@link D}. - */ - private class CD implements StaticMockFixture { - @Override - public StaticMockitoSessionBuilder setUpMockedClasses( - StaticMockitoSessionBuilder sessionBuilder) { - sessionBuilder.spyStatic(C.class); - sessionBuilder.spyStatic(D.class); - return sessionBuilder; - } - - @Override - public void setUpMockBehaviors() { - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("C.a"); - return null; - }).when(C::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("C.b"); - return null; - }).when(C::b); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("D.a"); - return null; - }).when(D::a); - ExtendedMockito.doAnswer(invocation -> { - mCollected.add("D.b"); - return null; - }).when(D::b); - } - - @Override - public void tearDown() { - - } - } -} diff --git a/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigTest.java b/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigTest.java deleted file mode 100644 index f9f43876f39a9..0000000000000 --- a/services/tests/mockingservicestests/src/com/android/server/testables/TestableDeviceConfigTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2019 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.testables; - -import static android.provider.DeviceConfig.OnPropertiesChangedListener; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.ActivityThread; -import android.platform.test.annotations.Presubmit; -import android.provider.DeviceConfig; -import android.provider.DeviceConfig.BadConfigException; -import android.provider.DeviceConfig.Properties; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** Tests that ensure appropriate settings are backed up. */ -@Presubmit -@RunWith(AndroidJUnit4.class) -@SmallTest -public class TestableDeviceConfigTest { - private static final String sNamespace = "namespace1"; - private static final String sKey = "key1"; - private static final String sValue = "value1"; - private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec - - @Rule - public TestableDeviceConfig.TestableDeviceConfigRule - mTestableDeviceConfig = new TestableDeviceConfig.TestableDeviceConfigRule(); - - @Test - public void getProperty_empty() { - String result = DeviceConfig.getProperty(sNamespace, sKey); - assertThat(result).isNull(); - } - - @Test - public void setAndGetProperty_sameNamespace() { - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - String result = DeviceConfig.getProperty(sNamespace, sKey); - assertThat(result).isEqualTo(sValue); - } - - @Test - public void setAndGetProperty_differentNamespace() { - String newNamespace = "namespace2"; - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - String result = DeviceConfig.getProperty(newNamespace, sKey); - assertThat(result).isNull(); - } - - @Test - public void setAndGetProperty_multipleNamespaces() { - String newNamespace = "namespace2"; - String newValue = "value2"; - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - DeviceConfig.setProperty(newNamespace, sKey, newValue, false); - String result = DeviceConfig.getProperty(sNamespace, sKey); - assertThat(result).isEqualTo(sValue); - result = DeviceConfig.getProperty(newNamespace, sKey); - assertThat(result).isEqualTo(newValue); - } - - @Test - public void setAndGetProperty_overrideValue() { - String newValue = "value2"; - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - DeviceConfig.setProperty(sNamespace, sKey, newValue, false); - String result = DeviceConfig.getProperty(sNamespace, sKey); - assertThat(result).isEqualTo(newValue); - } - - @Test - public void setProperties() throws BadConfigException { - String newKey = "key2"; - String newValue = "value2"; - DeviceConfig.setProperties(new Properties.Builder(sNamespace).setString(sKey, - sValue).setString(newKey, newValue).build()); - assertThat(DeviceConfig.getProperty(sNamespace, sKey)).isEqualTo(sValue); - assertThat(DeviceConfig.getProperty(sNamespace, newKey)).isEqualTo(newValue); - } - - @Test - public void deleteProperty() { - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - assertThat(DeviceConfig.getProperty(sNamespace, sKey)).isEqualTo(sValue); - DeviceConfig.deleteProperty(sNamespace, sKey); - assertThat(DeviceConfig.getProperty(sNamespace, sKey)).isNull(); - String newNamespace = "namespace2"; - String newValue = "value2"; - DeviceConfig.setProperty(newNamespace, sKey, newValue, false); - assertThat(DeviceConfig.getProperty(newNamespace, sKey)).isEqualTo(newValue); - DeviceConfig.deleteProperty(newNamespace, sKey); - assertThat(DeviceConfig.getProperty(newNamespace, sKey)).isNull(); - } - - @Test - public void getProperties_empty() { - String newKey = "key2"; - String newValue = "value2"; - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - Properties properties = DeviceConfig.getProperties(sNamespace); - assertThat(properties.getString(sKey, null)).isEqualTo(sValue); - assertThat(properties.getString(newKey, null)).isNull(); - - DeviceConfig.setProperty(sNamespace, newKey, newValue, false); - properties = DeviceConfig.getProperties(sNamespace); - assertThat(properties.getString(sKey, null)).isEqualTo(sValue); - assertThat(properties.getString(newKey, null)).isEqualTo(newValue); - - } - - @Test - public void getProperties() { - Properties properties = DeviceConfig.getProperties(sNamespace, sKey); - assertThat(properties.getString(sKey, null)).isNull(); - - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - properties = DeviceConfig.getProperties(sNamespace, sKey); - assertThat(properties.getString(sKey, null)).isEqualTo(sValue); - - String newKey = "key2"; - String newValue = "value2"; - DeviceConfig.setProperty(sNamespace, newKey, newValue, false); - properties = DeviceConfig.getProperties(sNamespace, sKey, newKey); - assertThat(properties.getString(sKey, null)).isEqualTo(sValue); - assertThat(properties.getString(newKey, null)).isEqualTo(newValue); - - String unsetKey = "key3"; - properties = DeviceConfig.getProperties(sNamespace, newKey, unsetKey); - assertThat(properties.getKeyset()).containsExactly(newKey, unsetKey); - assertThat(properties.getString(newKey, null)).isEqualTo(newValue); - assertThat(properties.getString(unsetKey, null)).isNull(); - } - - @Test - public void testListener_setProperty() throws InterruptedException { - CountDownLatch countDownLatch = new CountDownLatch(1); - - OnPropertiesChangedListener changeListener = (properties) -> { - assertThat(properties.getNamespace()).isEqualTo(sNamespace); - assertThat(properties.getKeyset()).containsExactly(sKey); - assertThat(properties.getString(sKey, "bogus_value")).isEqualTo(sValue); - assertThat(properties.getString("bogus_key", "bogus_value")).isEqualTo("bogus_value"); - countDownLatch.countDown(); - }; - try { - DeviceConfig.addOnPropertiesChangedListener(sNamespace, - ActivityThread.currentApplication().getMainExecutor(), changeListener); - DeviceConfig.setProperty(sNamespace, sKey, sValue, false); - assertThat(countDownLatch.await( - WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue(); - } finally { - DeviceConfig.removeOnPropertiesChangedListener(changeListener); - } - } - - @Test - public void testListener_setProperties() throws BadConfigException, InterruptedException { - CountDownLatch countDownLatch = new CountDownLatch(1); - String newKey = "key2"; - String newValue = "value2"; - - OnPropertiesChangedListener changeListener = (properties) -> { - assertThat(properties.getNamespace()).isEqualTo(sNamespace); - assertThat(properties.getKeyset()).containsExactly(sKey, newKey); - assertThat(properties.getString(sKey, "bogus_value")).isEqualTo(sValue); - assertThat(properties.getString(newKey, "bogus_value")).isEqualTo(newValue); - assertThat(properties.getString("bogus_key", "bogus_value")).isEqualTo("bogus_value"); - countDownLatch.countDown(); - }; - try { - DeviceConfig.addOnPropertiesChangedListener(sNamespace, - ActivityThread.currentApplication().getMainExecutor(), changeListener); - DeviceConfig.setProperties(new Properties.Builder(sNamespace).setString(sKey, - sValue).setString(newKey, newValue).build()); - assertThat(countDownLatch.await( - WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue(); - } finally { - DeviceConfig.removeOnPropertiesChangedListener(changeListener); - } - } - - @Test - public void testListener_deleteProperty() throws InterruptedException { - CountDownLatch countDownLatch = new CountDownLatch(1); - - OnPropertiesChangedListener changeListener = (properties) -> { - assertThat(properties.getNamespace()).isEqualTo(sNamespace); - assertThat(properties.getKeyset()).containsExactly(sKey); - assertThat(properties.getString(sKey, "bogus_value")).isEqualTo("bogus_value"); - assertThat(properties.getString("bogus_key", "bogus_value")).isEqualTo("bogus_value"); - countDownLatch.countDown(); - }; - try { - DeviceConfig.addOnPropertiesChangedListener(sNamespace, - ActivityThread.currentApplication().getMainExecutor(), changeListener); - DeviceConfig.deleteProperty(sNamespace, sKey); - assertThat(countDownLatch.await( - WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue(); - } finally { - DeviceConfig.removeOnPropertiesChangedListener(changeListener); - } - } -} - -