diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java index c397f23b2b5a3..0752537abfccf 100644 --- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java +++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java @@ -26,6 +26,7 @@ import android.provider.Settings; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; @@ -36,7 +37,7 @@ import org.robolectric.annotation.Config; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) -@SystemLoaderClasses({BackupManagerConstants.class}) +@SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class BackupManagerConstantsTest { private static final String PACKAGE_NAME = "some.package.name"; diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java index b60ad4b3f8150..df09780ecdd02 100644 --- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java +++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java @@ -48,7 +48,8 @@ import com.android.server.backup.testing.TransportData; import com.android.server.backup.testing.TransportTestUtils.TransportMock; import com.android.server.backup.transport.TransportNotRegisteredException; import com.android.server.testing.FrameworkRobolectricTestRunner; -import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; + import java.io.File; import java.util.HashMap; import java.util.List; @@ -74,11 +75,7 @@ import org.robolectric.shadows.ShadowSystemClock; sdk = 26, shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class} ) -@SystemLoaderClasses({ - BackupManagerService.class, - TransportManager.class, - PackageManagerBackupAgent.class -}) +@SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class BackupManagerServiceTest { private static final String TAG = "BMSTest"; diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java index 1360828bc81c4..e103464207d2f 100644 --- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java +++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java @@ -69,6 +69,7 @@ import com.android.server.backup.testing.TransportTestUtils.TransportMock; import com.android.server.backup.transport.TransportClient; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; import com.android.server.testing.shadows.FrameworkShadowPackageManager; import com.android.server.testing.shadows.ShadowBackupDataInput; import com.android.server.testing.shadows.ShadowBackupDataOutput; @@ -102,12 +103,10 @@ import java.util.stream.Stream; ShadowQueuedWork.class } ) +@SystemLoaderPackages({"com.android.server.backup"}) @SystemLoaderClasses({ - BackupManagerService.class, - PerformBackupTask.class, BackupDataOutput.class, FullBackupDataOutput.class, - TransportManager.class, BackupAgent.class, IBackupTransport.class, IBackupAgent.class, diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java index 068fe81374677..44ac8039bbed9 100644 --- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java +++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java @@ -51,7 +51,7 @@ import com.android.server.backup.transport.TransportClient; import com.android.server.backup.transport.TransportClientManager; import com.android.server.backup.transport.TransportNotRegisteredException; import com.android.server.testing.FrameworkRobolectricTestRunner; -import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; import com.android.server.testing.shadows.FrameworkShadowContextImpl; import com.android.server.testing.shadows.FrameworkShadowPackageManager; import java.util.ArrayList; @@ -75,7 +75,7 @@ import org.robolectric.shadows.ShadowPackageManager; sdk = 26, shadows = {FrameworkShadowPackageManager.class, FrameworkShadowContextImpl.class} ) -@SystemLoaderClasses({TransportManager.class}) +@SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class TransportManagerTest { private static final String PACKAGE_A = "some.package.a"; diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java index 55fb46068eeb4..5810c30acbf51 100644 --- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java +++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java @@ -49,7 +49,7 @@ import com.android.server.backup.testing.TransportData; import com.android.server.backup.testing.TransportTestUtils.TransportMock; import com.android.server.backup.transport.TransportClient; import com.android.server.testing.FrameworkRobolectricTestRunner; -import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; @@ -67,11 +67,7 @@ import java.util.stream.Stream; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) -@SystemLoaderClasses({ - BackupManagerService.class, - PerformInitializeTaskTest.class, - TransportManager.class -}) +@SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class PerformInitializeTaskTest { @Mock private BackupManagerService mBackupManagerService; diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java index db6e62f87a34d..ff1644cb75ad6 100644 --- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java +++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java @@ -46,6 +46,7 @@ import com.android.server.EventLogTags; import com.android.server.backup.TransportManager; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; import com.android.server.testing.shadows.ShadowCloseGuard; import com.android.server.testing.shadows.ShadowEventLog; import com.android.server.testing.shadows.ShadowSlog; @@ -66,7 +67,7 @@ import org.robolectric.shadows.ShadowLooper; sdk = 26, shadows = {ShadowEventLog.class, ShadowCloseGuard.class, ShadowSlog.class} ) -@SystemLoaderClasses({TransportManager.class, TransportClient.class}) +@SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class TransportClientTest { private static final String PACKAGE_NAME = "some.package.name"; diff --git a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java index c94d5983d2f52..d2a4d06dfbd07 100644 --- a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java +++ b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java @@ -16,8 +16,7 @@ package com.android.server.testing; -import com.android.server.backup.PerformBackupTaskTest; -import com.android.server.backup.internal.PerformBackupTask; +import static java.util.Arrays.asList; import com.google.common.collect.ImmutableSet; @@ -33,10 +32,11 @@ import org.robolectric.util.Util; import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; +import java.util.Arrays; import java.util.Enumeration; +import java.util.HashSet; import java.util.Set; +import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -51,9 +51,9 @@ import javax.annotation.Nonnull; * against the actual classes that are in the tree, not a past version of them. Ideally we would * have a locally built jar referenced by Robolectric, but until that happens one can use this * class. - * This class reads the {@link SystemLoaderClasses} annotation on test classes and for each class - * in that annotation value it will bypass the android jar and load it from the system class loader. - * Allowing the test to test the actual class in the tree. + * This class reads the {@link SystemLoaderClasses} or {@link SystemLoaderPackages} annotations on + * test classes, for classes that match the annotations it will bypass the android jar and load it + * from the system class loader. Allowing the test to test the actual class in the tree. * * Implementation note: One could think about overriding * {@link RobolectricTestRunner#createClassLoaderConfig(FrameworkMethod)} method and putting the @@ -72,11 +72,21 @@ public class FrameworkRobolectricTestRunner extends RobolectricTestRunner { public FrameworkRobolectricTestRunner(Class testClass) throws InitializationError { super(testClass); - SystemLoaderClasses annotation = testClass.getAnnotation(SystemLoaderClasses.class); - Class[] systemLoaderClasses = - (annotation != null) ? annotation.value() : new Class[0]; - Set systemLoaderClassNames = classesToClassNames(systemLoaderClasses); - mSandboxFactory = new FrameworkSandboxFactory(systemLoaderClassNames); + Set classPrefixes = getSystemLoaderClassPrefixes(testClass); + mSandboxFactory = new FrameworkSandboxFactory(classPrefixes); + } + + private Set getSystemLoaderClassPrefixes(Class testClass) { + Set classPrefixes = new HashSet<>(); + SystemLoaderClasses byClass = testClass.getAnnotation(SystemLoaderClasses.class); + if (byClass != null) { + Stream.of(byClass.value()).map(Class::getName).forEach(classPrefixes::add); + } + SystemLoaderPackages byPackage = testClass.getAnnotation(SystemLoaderPackages.class); + if (byPackage != null) { + classPrefixes.addAll(asList(byPackage.value())); + } + return classPrefixes; } @Nonnull @@ -92,15 +102,15 @@ public class FrameworkRobolectricTestRunner extends RobolectricTestRunner { } private static class FrameworkClassLoader extends SandboxClassLoader { - private final Set mSystemLoaderClasses; + private final Set mSystemLoaderClassPrefixes; private FrameworkClassLoader( - Set systemLoaderClasses, + Set systemLoaderClassPrefixes, ClassLoader systemClassLoader, InstrumentationConfiguration instrumentationConfig, URL... urls) { super(systemClassLoader, instrumentationConfig, urls); - mSystemLoaderClasses = systemLoaderClasses; + mSystemLoaderClassPrefixes = systemLoaderClassPrefixes; } @Override @@ -146,8 +156,8 @@ public class FrameworkRobolectricTestRunner extends RobolectricTestRunner { * loader, so we test if the classes in the annotation are prefixes of the class to load. */ private boolean shouldLoadFromSystemLoader(String className) { - for (String classNamePrefix : mSystemLoaderClasses) { - if (className.startsWith(classNamePrefix)) { + for (String classPrefix : mSystemLoaderClassPrefixes) { + if (className.startsWith(classPrefix)) { return true; } } @@ -156,10 +166,10 @@ public class FrameworkRobolectricTestRunner extends RobolectricTestRunner { } private static class FrameworkSandboxFactory extends SandboxFactory { - private final Set mSystemLoaderClasses; + private final Set mSystemLoaderClassPrefixes; - private FrameworkSandboxFactory(Set systemLoaderClasses) { - mSystemLoaderClasses = systemLoaderClasses; + private FrameworkSandboxFactory(Set systemLoaderClassPrefixes) { + mSystemLoaderClassPrefixes = systemLoaderClassPrefixes; } @Nonnull @@ -167,18 +177,10 @@ public class FrameworkRobolectricTestRunner extends RobolectricTestRunner { public ClassLoader createClassLoader( InstrumentationConfiguration instrumentationConfig, URL... urls) { return new FrameworkClassLoader( - mSystemLoaderClasses, + mSystemLoaderClassPrefixes, ClassLoader.getSystemClassLoader(), instrumentationConfig, urls); } } - - private static Set classesToClassNames(Class[] classes) { - ImmutableSet.Builder builder = ImmutableSet.builder(); - for (Class classObject : classes) { - builder.add(classObject.getName()); - } - return builder.build(); - } } diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java new file mode 100644 index 0000000000000..e01c0a4cffa5d --- /dev/null +++ b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 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.testing; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}. + * This will make the classes under the specified packages be loaded from the system class loader, + * NOT from the Robolectric android jar. + * + * @see FrameworkRobolectricTestRunner + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SystemLoaderPackages { + String[] value() default {}; +}