Loading ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java +78 −2 Original line number Original line Diff line number Diff line Loading @@ -15,12 +15,23 @@ */ */ package android.platform.test.ravenwood; package android.platform.test.ravenwood; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.util.Log; import android.util.Log; import android.util.Pair; import com.android.ravenwood.RavenwoodRuntimeNative; import org.junit.runner.Description; import org.junit.runner.Description; import java.util.ArrayList; import java.util.List; import java.util.Set; /** /** * Used to store various states associated with the current test runner that's inly needed * Used to store various states associated with the current test runner that's only needed * in junit-impl. * in junit-impl. * * * We don't want to put it in junit-src to avoid having to recompile all the downstream * We don't want to put it in junit-src to avoid having to recompile all the downstream Loading @@ -30,6 +41,11 @@ import org.junit.runner.Description; */ */ public final class RavenwoodRunnerState { public final class RavenwoodRunnerState { private static final String TAG = "RavenwoodRunnerState"; private static final String TAG = "RavenwoodRunnerState"; private static final String RAVENWOOD_RULE_ERROR = "RavenwoodRule(s) are not executed in the correct order"; private static final List<Pair<RavenwoodRule, RavenwoodPropertyState>> sActiveProperties = new ArrayList<>(); private final RavenwoodAwareTestRunner mRunner; private final RavenwoodAwareTestRunner mRunner; Loading @@ -53,6 +69,7 @@ public final class RavenwoodRunnerState { public void exitTestClass() { public void exitTestClass() { Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName()); Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName()); assertTrue(RAVENWOOD_RULE_ERROR, sActiveProperties.isEmpty()); RavenwoodRuntimeEnvironmentController.exitTestClass(); RavenwoodRuntimeEnvironmentController.exitTestClass(); } } Loading @@ -66,9 +83,68 @@ public final class RavenwoodRunnerState { } } public void enterRavenwoodRule(RavenwoodRule rule) { public void enterRavenwoodRule(RavenwoodRule rule) { RavenwoodRuntimeEnvironmentController.setSystemProperties(rule.mSystemProperties); pushTestProperties(rule); } } public void exitRavenwoodRule(RavenwoodRule rule) { public void exitRavenwoodRule(RavenwoodRule rule) { popTestProperties(rule); } static class RavenwoodPropertyState { final List<Pair<String, String>> mBackup; final Set<String> mKeyReadable; final Set<String> mKeyWritable; RavenwoodPropertyState(RavenwoodTestProperties props) { mBackup = props.mValues.keySet().stream() .map(key -> Pair.create(key, RavenwoodRuntimeNative.getSystemProperty(key))) .toList(); mKeyReadable = Set.copyOf(props.mKeyReadable); mKeyWritable = Set.copyOf(props.mKeyWritable); } boolean isKeyAccessible(String key, boolean write) { return write ? mKeyWritable.contains(key) : mKeyReadable.contains(key); } void restore() { mBackup.forEach(pair -> { if (pair.second == null) { RavenwoodRuntimeNative.removeSystemProperty(pair.first); } else { RavenwoodRuntimeNative.setSystemProperty(pair.first, pair.second); } }); } } private static void pushTestProperties(RavenwoodRule rule) { sActiveProperties.add(Pair.create(rule, new RavenwoodPropertyState(rule.mProperties))); rule.mProperties.mValues.forEach(RavenwoodRuntimeNative::setSystemProperty); } private static void popTestProperties(RavenwoodRule rule) { var pair = sActiveProperties.removeLast(); assertNotNull(RAVENWOOD_RULE_ERROR, pair); assertEquals(RAVENWOOD_RULE_ERROR, rule, pair.first); pair.second.restore(); } @SuppressWarnings("unused") // Called from native code (ravenwood_sysprop.cpp) private static void checkSystemPropertyAccess(String key, boolean write) { if (write && RavenwoodSystemProperties.sDefaultValues.containsKey(key)) { // The default core values should never be modified throw new IllegalArgumentException( "Setting core system property '" + key + "' is not allowed"); } final boolean result = RavenwoodSystemProperties.isKeyAccessible(key, write) || sActiveProperties.stream().anyMatch(p -> p.second.isKeyAccessible(key, write)); if (!result) { throw new IllegalArgumentException((write ? "Write" : "Read") + " access to system property '" + key + "' denied via RavenwoodRule"); } } } } } ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +3 −25 Original line number Original line Diff line number Diff line Loading @@ -163,8 +163,6 @@ public class RavenwoodRuntimeEnvironmentController { @GuardedBy("sInitializationLock") @GuardedBy("sInitializationLock") private static Throwable sExceptionFromGlobalInit; private static Throwable sExceptionFromGlobalInit; private static RavenwoodSystemProperties sProps; private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; Loading Loading @@ -234,7 +232,6 @@ public class RavenwoodRuntimeEnvironmentController { // Do the basic set up for the android sysprops. // Do the basic set up for the android sysprops. RavenwoodSystemProperties.initialize(); RavenwoodSystemProperties.initialize(); setSystemProperties(null); // Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()), // Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()), // before loadFrameworkNativeCode() (which uses $ANDROID_LOG_TAGS). // before loadFrameworkNativeCode() (which uses $ANDROID_LOG_TAGS). Loading Loading @@ -356,10 +353,13 @@ public class RavenwoodRuntimeEnvironmentController { // will call Mockito.framework().clearInlineMocks() after execution. // will call Mockito.framework().clearInlineMocks() after execution. sInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); sInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); // Reset some global state Process_ravenwood.reset(); Process_ravenwood.reset(); DeviceConfig_host.reset(); DeviceConfig_host.reset(); Binder.restoreCallingIdentity(sCallingIdentity); Binder.restoreCallingIdentity(sCallingIdentity); SystemProperties.clearChangeCallbacksForTest(); if (ENABLE_TIMEOUT_STACKS) { if (ENABLE_TIMEOUT_STACKS) { sPendingTimeout = sTimeoutExecutor.schedule( sPendingTimeout = sTimeoutExecutor.schedule( RavenwoodRuntimeEnvironmentController::dumpStacks, RavenwoodRuntimeEnvironmentController::dumpStacks, Loading Loading @@ -484,19 +484,6 @@ public class RavenwoodRuntimeEnvironmentController { } } } } /** * Set the current configuration to the actual SystemProperties. */ public static void setSystemProperties(@Nullable RavenwoodSystemProperties systemProperties) { SystemProperties.clearChangeCallbacksForTest(); RavenwoodRuntimeNative.clearSystemProperties(); if (systemProperties == null) systemProperties = new RavenwoodSystemProperties(); sProps = new RavenwoodSystemProperties(systemProperties, true); for (var entry : systemProperties.getValues().entrySet()) { RavenwoodRuntimeNative.setSystemProperty(entry.getKey(), entry.getValue()); } } private static final String MOCKITO_ERROR = "FATAL: Unsupported Mockito detected!" private static final String MOCKITO_ERROR = "FATAL: Unsupported Mockito detected!" + " Your test or its dependencies use one of the \"mockito-target-*\"" + " Your test or its dependencies use one of the \"mockito-target-*\"" + " modules as static library, which is unusable on host side." + " modules as static library, which is unusable on host side." Loading Loading @@ -546,15 +533,6 @@ public class RavenwoodRuntimeEnvironmentController { return mock; return mock; } } @SuppressWarnings("unused") // Called from native code (ravenwood_sysprop.cpp) private static void checkSystemPropertyAccess(String key, boolean write) { boolean result = write ? sProps.isKeyWritable(key) : sProps.isKeyReadable(key); if (!result) { throw new IllegalArgumentException((write ? "Write" : "Read") + " access to system property '" + key + "' denied via RavenwoodConfig"); } } private static void dumpCommandLineArgs() { private static void dumpCommandLineArgs() { Log.i(TAG, "JVM arguments:"); Log.i(TAG, "JVM arguments:"); Loading ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java→ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java +17 −67 Original line number Original line Diff line number Diff line Loading @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * See the License for the specific language governing permissions and * limitations under the License. * limitations under the License. */ */ package android.platform.test.ravenwood; package android.platform.test.ravenwood; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; Loading @@ -21,26 +20,30 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.getRavenwoodRunt import android.util.Log; import android.util.Log; import com.android.ravenwood.RavenwoodRuntimeNative; import java.io.IOException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Path; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.Set; /** * A class to manage the core default system properties of the Ravenwood environment. */ public class RavenwoodSystemProperties { public class RavenwoodSystemProperties { private static final String TAG = "RavenwoodSystemProperties"; private static final String TAG = "RavenwoodSystemProperties"; /** We pull in propeties from this file. */ /** We pull in properties from this file. */ private static final String RAVENWOOD_BUILD_PROP = "ravenwood-data/ravenwood-build.prop"; private static final String RAVENWOOD_BUILD_PROP = "ravenwood-data/ravenwood-build.prop"; /** This is the actual build.prop we use to build the device (contents depends on lunch). */ /** This is the actual build.prop we use to build the device (contents depends on lunch). */ private static final String DEVICE_BUILD_PROP = "ravenwood-data/build.prop"; private static final String DEVICE_BUILD_PROP = "ravenwood-data/build.prop"; /** The default values. */ /** The default values. */ private static final Map<String, String> sDefaultValues = new HashMap<>(); static final Map<String, String> sDefaultValues = new HashMap<>(); private static final String[] PARTITIONS = { private static final String[] PARTITIONS = { "bootimage", "bootimage", Loading Loading @@ -115,6 +118,7 @@ public class RavenwoodSystemProperties { } } } } } } if (RAVENWOOD_VERBOSE_LOGGING) { if (RAVENWOOD_VERBOSE_LOGGING) { // Dump all properties for local debugging. // Dump all properties for local debugging. Log.v(TAG, "All system properties:"); Log.v(TAG, "All system properties:"); Loading @@ -122,35 +126,12 @@ public class RavenwoodSystemProperties { Log.v(TAG, "" + key + "=" + sDefaultValues.get(key)); Log.v(TAG, "" + key + "=" + sDefaultValues.get(key)); } } } } } private volatile boolean mIsImmutable; private final Map<String, String> mValues = new HashMap<>(); /** Set of additional keys that should be considered readable */ private final Set<String> mKeyReadable = new HashSet<>(); /** Set of additional keys that should be considered writable */ private final Set<String> mKeyWritable = new HashSet<>(); public RavenwoodSystemProperties() { mValues.putAll(sDefaultValues); } /** Copy constructor */ public RavenwoodSystemProperties(RavenwoodSystemProperties source, boolean immutable) { mKeyReadable.addAll(source.mKeyReadable); mKeyWritable.addAll(source.mKeyWritable); mValues.putAll(source.mValues); mIsImmutable = immutable; } public Map<String, String> getValues() { // Actually set the system properties return new HashMap<>(mValues); sDefaultValues.forEach(RavenwoodRuntimeNative::setSystemProperty); } } public boolean isKeyReadable(String key) { private static boolean isKeyReadable(String key) { final String root = getKeyRoot(key); final String root = getKeyRoot(key); if (root.startsWith("debug.")) return true; if (root.startsWith("debug.")) return true; Loading Loading @@ -183,10 +164,10 @@ public class RavenwoodSystemProperties { return true; return true; } } return mKeyReadable.contains(key); return false; } } public boolean isKeyWritable(String key) { private static boolean isKeyWritable(String key) { final String root = getKeyRoot(key); final String root = getKeyRoot(key); if (root.startsWith("debug.")) return true; if (root.startsWith("debug.")) return true; Loading @@ -194,42 +175,11 @@ public class RavenwoodSystemProperties { // For PropertyInvalidatedCache // For PropertyInvalidatedCache if (root.startsWith("cache_key.")) return true; if (root.startsWith("cache_key.")) return true; return mKeyWritable.contains(key); return false; } private void ensureNotImmutable() { if (mIsImmutable) { throw new RuntimeException("Unable to update immutable instance"); } } public void setValue(String key, Object value) { ensureNotImmutable(); final String valueString = (value == null) ? null : String.valueOf(value); if ((valueString == null) || valueString.isEmpty()) { mValues.remove(key); } else { mValues.put(key, valueString); } } public void setAccessNone(String key) { ensureNotImmutable(); mKeyReadable.remove(key); mKeyWritable.remove(key); } public void setAccessReadOnly(String key) { ensureNotImmutable(); mKeyReadable.add(key); mKeyWritable.remove(key); } } public void setAccessReadWrite(String key) { static boolean isKeyAccessible(String key, boolean write) { ensureNotImmutable(); return write ? isKeyWritable(key) : isKeyReadable(key); mKeyReadable.add(key); mKeyWritable.add(key); } } /** /** Loading ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +5 −5 Original line number Original line Diff line number Diff line Loading @@ -92,7 +92,7 @@ public final class RavenwoodRule implements TestRule { } } } } final RavenwoodSystemProperties mSystemProperties = new RavenwoodSystemProperties(); final RavenwoodTestProperties mProperties = new RavenwoodTestProperties(); public static class Builder { public static class Builder { Loading Loading @@ -144,8 +144,8 @@ public final class RavenwoodRule implements TestRule { * Has no effect on non-Ravenwood environments. * Has no effect on non-Ravenwood environments. */ */ public Builder setSystemPropertyImmutable(@NonNull String key, @Nullable Object value) { public Builder setSystemPropertyImmutable(@NonNull String key, @Nullable Object value) { mRule.mSystemProperties.setValue(key, value); mRule.mProperties.setValue(key, value); mRule.mSystemProperties.setAccessReadOnly(key); mRule.mProperties.setAccessReadOnly(key); return this; return this; } } Loading @@ -160,8 +160,8 @@ public final class RavenwoodRule implements TestRule { * Has no effect on non-Ravenwood environments. * Has no effect on non-Ravenwood environments. */ */ public Builder setSystemPropertyMutable(@NonNull String key, @Nullable Object value) { public Builder setSystemPropertyMutable(@NonNull String key, @Nullable Object value) { mRule.mSystemProperties.setValue(key, value); mRule.mProperties.setValue(key, value); mRule.mSystemProperties.setAccessReadWrite(key); mRule.mProperties.setAccessReadWrite(key); return this; return this; } } Loading ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodTestProperties.java 0 → 100644 +59 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.platform.test.ravenwood; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * A class to store system properties defined by tests. */ public class RavenwoodTestProperties { final Map<String, String> mValues = new HashMap<>(); /** Set of additional keys that should be considered readable */ final Set<String> mKeyReadable = new HashSet<>(); /** Set of additional keys that should be considered writable */ final Set<String> mKeyWritable = new HashSet<>(); public void setValue(String key, Object value) { final String valueString = (value == null) ? null : String.valueOf(value); if ((valueString == null) || valueString.isEmpty()) { mValues.remove(key); } else { mValues.put(key, valueString); } } public void setAccessNone(String key) { mKeyReadable.remove(key); mKeyWritable.remove(key); } public void setAccessReadOnly(String key) { mKeyReadable.add(key); mKeyWritable.remove(key); } public void setAccessReadWrite(String key) { mKeyReadable.add(key); mKeyWritable.add(key); } } Loading
ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java +78 −2 Original line number Original line Diff line number Diff line Loading @@ -15,12 +15,23 @@ */ */ package android.platform.test.ravenwood; package android.platform.test.ravenwood; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.util.Log; import android.util.Log; import android.util.Pair; import com.android.ravenwood.RavenwoodRuntimeNative; import org.junit.runner.Description; import org.junit.runner.Description; import java.util.ArrayList; import java.util.List; import java.util.Set; /** /** * Used to store various states associated with the current test runner that's inly needed * Used to store various states associated with the current test runner that's only needed * in junit-impl. * in junit-impl. * * * We don't want to put it in junit-src to avoid having to recompile all the downstream * We don't want to put it in junit-src to avoid having to recompile all the downstream Loading @@ -30,6 +41,11 @@ import org.junit.runner.Description; */ */ public final class RavenwoodRunnerState { public final class RavenwoodRunnerState { private static final String TAG = "RavenwoodRunnerState"; private static final String TAG = "RavenwoodRunnerState"; private static final String RAVENWOOD_RULE_ERROR = "RavenwoodRule(s) are not executed in the correct order"; private static final List<Pair<RavenwoodRule, RavenwoodPropertyState>> sActiveProperties = new ArrayList<>(); private final RavenwoodAwareTestRunner mRunner; private final RavenwoodAwareTestRunner mRunner; Loading @@ -53,6 +69,7 @@ public final class RavenwoodRunnerState { public void exitTestClass() { public void exitTestClass() { Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName()); Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName()); assertTrue(RAVENWOOD_RULE_ERROR, sActiveProperties.isEmpty()); RavenwoodRuntimeEnvironmentController.exitTestClass(); RavenwoodRuntimeEnvironmentController.exitTestClass(); } } Loading @@ -66,9 +83,68 @@ public final class RavenwoodRunnerState { } } public void enterRavenwoodRule(RavenwoodRule rule) { public void enterRavenwoodRule(RavenwoodRule rule) { RavenwoodRuntimeEnvironmentController.setSystemProperties(rule.mSystemProperties); pushTestProperties(rule); } } public void exitRavenwoodRule(RavenwoodRule rule) { public void exitRavenwoodRule(RavenwoodRule rule) { popTestProperties(rule); } static class RavenwoodPropertyState { final List<Pair<String, String>> mBackup; final Set<String> mKeyReadable; final Set<String> mKeyWritable; RavenwoodPropertyState(RavenwoodTestProperties props) { mBackup = props.mValues.keySet().stream() .map(key -> Pair.create(key, RavenwoodRuntimeNative.getSystemProperty(key))) .toList(); mKeyReadable = Set.copyOf(props.mKeyReadable); mKeyWritable = Set.copyOf(props.mKeyWritable); } boolean isKeyAccessible(String key, boolean write) { return write ? mKeyWritable.contains(key) : mKeyReadable.contains(key); } void restore() { mBackup.forEach(pair -> { if (pair.second == null) { RavenwoodRuntimeNative.removeSystemProperty(pair.first); } else { RavenwoodRuntimeNative.setSystemProperty(pair.first, pair.second); } }); } } private static void pushTestProperties(RavenwoodRule rule) { sActiveProperties.add(Pair.create(rule, new RavenwoodPropertyState(rule.mProperties))); rule.mProperties.mValues.forEach(RavenwoodRuntimeNative::setSystemProperty); } private static void popTestProperties(RavenwoodRule rule) { var pair = sActiveProperties.removeLast(); assertNotNull(RAVENWOOD_RULE_ERROR, pair); assertEquals(RAVENWOOD_RULE_ERROR, rule, pair.first); pair.second.restore(); } @SuppressWarnings("unused") // Called from native code (ravenwood_sysprop.cpp) private static void checkSystemPropertyAccess(String key, boolean write) { if (write && RavenwoodSystemProperties.sDefaultValues.containsKey(key)) { // The default core values should never be modified throw new IllegalArgumentException( "Setting core system property '" + key + "' is not allowed"); } final boolean result = RavenwoodSystemProperties.isKeyAccessible(key, write) || sActiveProperties.stream().anyMatch(p -> p.second.isKeyAccessible(key, write)); if (!result) { throw new IllegalArgumentException((write ? "Write" : "Read") + " access to system property '" + key + "' denied via RavenwoodRule"); } } } } }
ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +3 −25 Original line number Original line Diff line number Diff line Loading @@ -163,8 +163,6 @@ public class RavenwoodRuntimeEnvironmentController { @GuardedBy("sInitializationLock") @GuardedBy("sInitializationLock") private static Throwable sExceptionFromGlobalInit; private static Throwable sExceptionFromGlobalInit; private static RavenwoodSystemProperties sProps; private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; Loading Loading @@ -234,7 +232,6 @@ public class RavenwoodRuntimeEnvironmentController { // Do the basic set up for the android sysprops. // Do the basic set up for the android sysprops. RavenwoodSystemProperties.initialize(); RavenwoodSystemProperties.initialize(); setSystemProperties(null); // Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()), // Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()), // before loadFrameworkNativeCode() (which uses $ANDROID_LOG_TAGS). // before loadFrameworkNativeCode() (which uses $ANDROID_LOG_TAGS). Loading Loading @@ -356,10 +353,13 @@ public class RavenwoodRuntimeEnvironmentController { // will call Mockito.framework().clearInlineMocks() after execution. // will call Mockito.framework().clearInlineMocks() after execution. sInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); sInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); // Reset some global state Process_ravenwood.reset(); Process_ravenwood.reset(); DeviceConfig_host.reset(); DeviceConfig_host.reset(); Binder.restoreCallingIdentity(sCallingIdentity); Binder.restoreCallingIdentity(sCallingIdentity); SystemProperties.clearChangeCallbacksForTest(); if (ENABLE_TIMEOUT_STACKS) { if (ENABLE_TIMEOUT_STACKS) { sPendingTimeout = sTimeoutExecutor.schedule( sPendingTimeout = sTimeoutExecutor.schedule( RavenwoodRuntimeEnvironmentController::dumpStacks, RavenwoodRuntimeEnvironmentController::dumpStacks, Loading Loading @@ -484,19 +484,6 @@ public class RavenwoodRuntimeEnvironmentController { } } } } /** * Set the current configuration to the actual SystemProperties. */ public static void setSystemProperties(@Nullable RavenwoodSystemProperties systemProperties) { SystemProperties.clearChangeCallbacksForTest(); RavenwoodRuntimeNative.clearSystemProperties(); if (systemProperties == null) systemProperties = new RavenwoodSystemProperties(); sProps = new RavenwoodSystemProperties(systemProperties, true); for (var entry : systemProperties.getValues().entrySet()) { RavenwoodRuntimeNative.setSystemProperty(entry.getKey(), entry.getValue()); } } private static final String MOCKITO_ERROR = "FATAL: Unsupported Mockito detected!" private static final String MOCKITO_ERROR = "FATAL: Unsupported Mockito detected!" + " Your test or its dependencies use one of the \"mockito-target-*\"" + " Your test or its dependencies use one of the \"mockito-target-*\"" + " modules as static library, which is unusable on host side." + " modules as static library, which is unusable on host side." Loading Loading @@ -546,15 +533,6 @@ public class RavenwoodRuntimeEnvironmentController { return mock; return mock; } } @SuppressWarnings("unused") // Called from native code (ravenwood_sysprop.cpp) private static void checkSystemPropertyAccess(String key, boolean write) { boolean result = write ? sProps.isKeyWritable(key) : sProps.isKeyReadable(key); if (!result) { throw new IllegalArgumentException((write ? "Write" : "Read") + " access to system property '" + key + "' denied via RavenwoodConfig"); } } private static void dumpCommandLineArgs() { private static void dumpCommandLineArgs() { Log.i(TAG, "JVM arguments:"); Log.i(TAG, "JVM arguments:"); Loading
ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java→ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java +17 −67 Original line number Original line Diff line number Diff line Loading @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * See the License for the specific language governing permissions and * limitations under the License. * limitations under the License. */ */ package android.platform.test.ravenwood; package android.platform.test.ravenwood; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; Loading @@ -21,26 +20,30 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.getRavenwoodRunt import android.util.Log; import android.util.Log; import com.android.ravenwood.RavenwoodRuntimeNative; import java.io.IOException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Path; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.Set; /** * A class to manage the core default system properties of the Ravenwood environment. */ public class RavenwoodSystemProperties { public class RavenwoodSystemProperties { private static final String TAG = "RavenwoodSystemProperties"; private static final String TAG = "RavenwoodSystemProperties"; /** We pull in propeties from this file. */ /** We pull in properties from this file. */ private static final String RAVENWOOD_BUILD_PROP = "ravenwood-data/ravenwood-build.prop"; private static final String RAVENWOOD_BUILD_PROP = "ravenwood-data/ravenwood-build.prop"; /** This is the actual build.prop we use to build the device (contents depends on lunch). */ /** This is the actual build.prop we use to build the device (contents depends on lunch). */ private static final String DEVICE_BUILD_PROP = "ravenwood-data/build.prop"; private static final String DEVICE_BUILD_PROP = "ravenwood-data/build.prop"; /** The default values. */ /** The default values. */ private static final Map<String, String> sDefaultValues = new HashMap<>(); static final Map<String, String> sDefaultValues = new HashMap<>(); private static final String[] PARTITIONS = { private static final String[] PARTITIONS = { "bootimage", "bootimage", Loading Loading @@ -115,6 +118,7 @@ public class RavenwoodSystemProperties { } } } } } } if (RAVENWOOD_VERBOSE_LOGGING) { if (RAVENWOOD_VERBOSE_LOGGING) { // Dump all properties for local debugging. // Dump all properties for local debugging. Log.v(TAG, "All system properties:"); Log.v(TAG, "All system properties:"); Loading @@ -122,35 +126,12 @@ public class RavenwoodSystemProperties { Log.v(TAG, "" + key + "=" + sDefaultValues.get(key)); Log.v(TAG, "" + key + "=" + sDefaultValues.get(key)); } } } } } private volatile boolean mIsImmutable; private final Map<String, String> mValues = new HashMap<>(); /** Set of additional keys that should be considered readable */ private final Set<String> mKeyReadable = new HashSet<>(); /** Set of additional keys that should be considered writable */ private final Set<String> mKeyWritable = new HashSet<>(); public RavenwoodSystemProperties() { mValues.putAll(sDefaultValues); } /** Copy constructor */ public RavenwoodSystemProperties(RavenwoodSystemProperties source, boolean immutable) { mKeyReadable.addAll(source.mKeyReadable); mKeyWritable.addAll(source.mKeyWritable); mValues.putAll(source.mValues); mIsImmutable = immutable; } public Map<String, String> getValues() { // Actually set the system properties return new HashMap<>(mValues); sDefaultValues.forEach(RavenwoodRuntimeNative::setSystemProperty); } } public boolean isKeyReadable(String key) { private static boolean isKeyReadable(String key) { final String root = getKeyRoot(key); final String root = getKeyRoot(key); if (root.startsWith("debug.")) return true; if (root.startsWith("debug.")) return true; Loading Loading @@ -183,10 +164,10 @@ public class RavenwoodSystemProperties { return true; return true; } } return mKeyReadable.contains(key); return false; } } public boolean isKeyWritable(String key) { private static boolean isKeyWritable(String key) { final String root = getKeyRoot(key); final String root = getKeyRoot(key); if (root.startsWith("debug.")) return true; if (root.startsWith("debug.")) return true; Loading @@ -194,42 +175,11 @@ public class RavenwoodSystemProperties { // For PropertyInvalidatedCache // For PropertyInvalidatedCache if (root.startsWith("cache_key.")) return true; if (root.startsWith("cache_key.")) return true; return mKeyWritable.contains(key); return false; } private void ensureNotImmutable() { if (mIsImmutable) { throw new RuntimeException("Unable to update immutable instance"); } } public void setValue(String key, Object value) { ensureNotImmutable(); final String valueString = (value == null) ? null : String.valueOf(value); if ((valueString == null) || valueString.isEmpty()) { mValues.remove(key); } else { mValues.put(key, valueString); } } public void setAccessNone(String key) { ensureNotImmutable(); mKeyReadable.remove(key); mKeyWritable.remove(key); } public void setAccessReadOnly(String key) { ensureNotImmutable(); mKeyReadable.add(key); mKeyWritable.remove(key); } } public void setAccessReadWrite(String key) { static boolean isKeyAccessible(String key, boolean write) { ensureNotImmutable(); return write ? isKeyWritable(key) : isKeyReadable(key); mKeyReadable.add(key); mKeyWritable.add(key); } } /** /** Loading
ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +5 −5 Original line number Original line Diff line number Diff line Loading @@ -92,7 +92,7 @@ public final class RavenwoodRule implements TestRule { } } } } final RavenwoodSystemProperties mSystemProperties = new RavenwoodSystemProperties(); final RavenwoodTestProperties mProperties = new RavenwoodTestProperties(); public static class Builder { public static class Builder { Loading Loading @@ -144,8 +144,8 @@ public final class RavenwoodRule implements TestRule { * Has no effect on non-Ravenwood environments. * Has no effect on non-Ravenwood environments. */ */ public Builder setSystemPropertyImmutable(@NonNull String key, @Nullable Object value) { public Builder setSystemPropertyImmutable(@NonNull String key, @Nullable Object value) { mRule.mSystemProperties.setValue(key, value); mRule.mProperties.setValue(key, value); mRule.mSystemProperties.setAccessReadOnly(key); mRule.mProperties.setAccessReadOnly(key); return this; return this; } } Loading @@ -160,8 +160,8 @@ public final class RavenwoodRule implements TestRule { * Has no effect on non-Ravenwood environments. * Has no effect on non-Ravenwood environments. */ */ public Builder setSystemPropertyMutable(@NonNull String key, @Nullable Object value) { public Builder setSystemPropertyMutable(@NonNull String key, @Nullable Object value) { mRule.mSystemProperties.setValue(key, value); mRule.mProperties.setValue(key, value); mRule.mSystemProperties.setAccessReadWrite(key); mRule.mProperties.setAccessReadWrite(key); return this; return this; } } Loading
ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodTestProperties.java 0 → 100644 +59 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.platform.test.ravenwood; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * A class to store system properties defined by tests. */ public class RavenwoodTestProperties { final Map<String, String> mValues = new HashMap<>(); /** Set of additional keys that should be considered readable */ final Set<String> mKeyReadable = new HashSet<>(); /** Set of additional keys that should be considered writable */ final Set<String> mKeyWritable = new HashSet<>(); public void setValue(String key, Object value) { final String valueString = (value == null) ? null : String.valueOf(value); if ((valueString == null) || valueString.isEmpty()) { mValues.remove(key); } else { mValues.put(key, valueString); } } public void setAccessNone(String key) { mKeyReadable.remove(key); mKeyWritable.remove(key); } public void setAccessReadOnly(String key) { mKeyReadable.add(key); mKeyWritable.remove(key); } public void setAccessReadWrite(String key) { mKeyReadable.add(key); mKeyWritable.add(key); } }