diff options
author | 2024-02-15 14:12:07 -0700 | |
---|---|---|
committer | 2024-02-20 13:43:19 -0700 | |
commit | 3e91c2b2bc3b90da2513cc84b0c65ddce9fae46b (patch) | |
tree | 6d64621bdc31c20407babfa5b3229af03d6d8ab8 /ravenwood/junit-src | |
parent | f17902765f6d34d0e07d0836e8676358605d868f (diff) |
First pass of "real" services on Ravenwood.
One of our eventual goals with Ravenwood is to support usage of
system services from test code. Robolectric takes the approach of
publishing "shadows" which are effectively fakes of the Manager
objects visible to app processes, and it unfortunately doesn't offer
a mechanism to run "real" services code.
In contrast, Ravenwood aims to support API owners progressively
offering their system services either via a "fake" approach, or by
using various levels of the "real" code that would run on a device.
This change wires up the foundational support and uses the simple
`SerialManager` example to demonstrate using the same "real" code
on both Ravenwood and devices. It also demonstrates the `Internal`
pattern being used to customize behavior for tests.
To offer as hermetic as a test environment as possible, we start
new instances of each requested service for each test. Requiring
developers to be explicit about the services they need will help
keep overhead low, especially for tests that don't need services.
Bug: 325506297
Test: atest RavenwoodServicesTest
Change-Id: Ie22436b38f2176f91dfce746b899ebab7752bbb8
Diffstat (limited to 'ravenwood/junit-src')
-rw-r--r-- | ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java index b90f112c1655..a8c24fcbd7e0 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java @@ -22,10 +22,13 @@ import static android.os.UserHandle.USER_SYSTEM; import static org.junit.Assert.fail; +import android.app.Instrumentation; +import android.content.Context; import android.platform.test.annotations.DisabledOnNonRavenwood; import android.platform.test.annotations.DisabledOnRavenwood; import android.platform.test.annotations.EnabledOnRavenwood; import android.platform.test.annotations.IgnoreUnderRavenwood; +import android.util.ArraySet; import org.junit.Assume; import org.junit.rules.TestRule; @@ -122,6 +125,11 @@ public class RavenwoodRule implements TestRule { final RavenwoodSystemProperties mSystemProperties = new RavenwoodSystemProperties(); + final ArraySet<Class<?>> mServicesRequired = new ArraySet<>(); + + volatile Context mContext; + volatile Instrumentation mInstrumentation; + public RavenwoodRule() { } @@ -192,6 +200,23 @@ public class RavenwoodRule implements TestRule { return this; } + /** + * Configure the set of system services that are required for this test to operate. + * + * For example, passing {@code android.hardware.SerialManager.class} as an argument will + * ensure that the underlying service is created, initialized, and ready to use for the + * duration of the test. The {@code SerialManager} instance can be obtained via + * {@code RavenwoodRule.getContext()} and {@code Context.getSystemService()}, and + * {@code SerialManagerInternal} can be obtained via {@code LocalServices.getService()}. + */ + public Builder setServicesRequired(Class<?>... services) { + mRule.mServicesRequired.clear(); + for (Class<?> service : services) { + mRule.mServicesRequired.add(service); + } + return this; + } + public RavenwoodRule build() { return mRule; } @@ -212,6 +237,28 @@ public class RavenwoodRule implements TestRule { return IS_ON_RAVENWOOD; } + /** + * Return a {@code Context} available for usage during the currently running test case. + * + * Each test should obtain needed information or references via this method; + * references must not be stored beyond the scope of a test case. + */ + public Context getContext() { + return Objects.requireNonNull(mContext, + "Context is only available during @Test execution"); + } + + /** + * Return a {@code Instrumentation} available for usage during the currently running test case. + * + * Each test should obtain needed information or references via this method; + * references must not be stored beyond the scope of a test case. + */ + public Instrumentation getInstrumentation() { + return Objects.requireNonNull(mInstrumentation, + "Instrumentation is only available during @Test execution"); + } + static boolean shouldEnableOnDevice(Description description) { if (description.isTest()) { if (description.getAnnotation(DisabledOnNonRavenwood.class) != null) { |