diff options
author | 2024-11-23 00:29:29 +0000 | |
---|---|---|
committer | 2024-11-23 00:29:29 +0000 | |
commit | 2f3a9c61f771790f0d59fc6b9991d63cfddbf2c7 (patch) | |
tree | b63ec2e2a56a26de31ef03e3d3f1425093e43ea6 | |
parent | 558cd71f0f6ec8f1af5d49fd9c208411f7b77615 (diff) |
[Ravenwood] Update system property handling
- Split out "core" system properties (the default properties we set
during the global initialization) and "test" system properties (the
properties defined and set through RavenwoodRule)
- Reset only the "test" system properties before each test execution
- Update the implementation to support nested RavenwoodRule in the
future
Flag: EXEMPT host test change only
Bug: 377765941
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Change-Id: Ia9a2ee217aa89e0f2565d14fb26e3842947e9dc7
-rw-r--r-- | ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java | 80 | ||||
-rw-r--r-- | ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java | 28 | ||||
-rw-r--r-- | ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java (renamed from ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java) | 84 | ||||
-rw-r--r-- | ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java | 10 | ||||
-rw-r--r-- | ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodTestProperties.java | 59 | ||||
-rw-r--r-- | ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java | 6 | ||||
-rw-r--r-- | ravenwood/runtime-jni/jni_helper.h | 1 | ||||
-rw-r--r-- | ravenwood/runtime-jni/ravenwood_sysprop.cpp | 29 | ||||
-rw-r--r-- | ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/SystemPropertyTest.java | 88 |
9 files changed, 277 insertions, 108 deletions
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java index 110de989b524..6dfcf4ce03cf 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java @@ -15,12 +15,23 @@ */ 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.Pair; + +import com.android.ravenwood.RavenwoodRuntimeNative; 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. * * We don't want to put it in junit-src to avoid having to recompile all the downstream @@ -30,6 +41,11 @@ import org.junit.runner.Description; */ public final class 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; @@ -53,6 +69,7 @@ public final class RavenwoodRunnerState { public void exitTestClass() { Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName()); + assertTrue(RAVENWOOD_RULE_ERROR, sActiveProperties.isEmpty()); RavenwoodRuntimeEnvironmentController.exitTestClass(); } @@ -66,9 +83,68 @@ public final class RavenwoodRunnerState { } public void enterRavenwoodRule(RavenwoodRule rule) { - RavenwoodRuntimeEnvironmentController.setSystemProperties(rule.mSystemProperties); + pushTestProperties(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"); + } } } diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java index c2ed45d8f427..e730a292a9da 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -163,8 +163,6 @@ public class RavenwoodRuntimeEnvironmentController { @GuardedBy("sInitializationLock") private static Throwable sExceptionFromGlobalInit; - private static RavenwoodSystemProperties sProps; - private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; @@ -234,7 +232,6 @@ public class RavenwoodRuntimeEnvironmentController { // Do the basic set up for the android sysprops. RavenwoodSystemProperties.initialize(); - setSystemProperties(null); // Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()), // before loadFrameworkNativeCode() (which uses $ANDROID_LOG_TAGS). @@ -356,10 +353,13 @@ public class RavenwoodRuntimeEnvironmentController { // will call Mockito.framework().clearInlineMocks() after execution. sInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); + // Reset some global state Process_ravenwood.reset(); DeviceConfig_host.reset(); Binder.restoreCallingIdentity(sCallingIdentity); + SystemProperties.clearChangeCallbacksForTest(); + if (ENABLE_TIMEOUT_STACKS) { sPendingTimeout = sTimeoutExecutor.schedule( RavenwoodRuntimeEnvironmentController::dumpStacks, @@ -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!" + " Your test or its dependencies use one of the \"mockito-target-*\"" + " modules as static library, which is unusable on host side." @@ -546,15 +533,6 @@ public class RavenwoodRuntimeEnvironmentController { 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() { Log.i(TAG, "JVM arguments:"); diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java index 9bd376a76f77..c545baacdf3e 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package android.platform.test.ravenwood; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; @@ -21,26 +20,30 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.getRavenwoodRunt import android.util.Log; +import com.android.ravenwood.RavenwoodRuntimeNative; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +/** + * A class to manage the core default system properties of the Ravenwood environment. + */ public class 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"; /** 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"; /** 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 = { "bootimage", @@ -91,7 +94,7 @@ public class RavenwoodSystemProperties { var deviceValue = deviceProps.get(deviceKey); if (deviceValue == null) { throw new RuntimeException("Failed to initialize system properties. Key '" - + deviceKey + "' doesn't exist in the device side build.prop"); + + deviceKey + "' doesn't exist in the device side build.prop"); } value = deviceValue; } else { @@ -115,6 +118,7 @@ public class RavenwoodSystemProperties { } } } + if (RAVENWOOD_VERBOSE_LOGGING) { // Dump all properties for local debugging. Log.v(TAG, "All system properties:"); @@ -122,35 +126,12 @@ public class RavenwoodSystemProperties { 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() { - return new HashMap<>(mValues); + // Actually set the system properties + sDefaultValues.forEach(RavenwoodRuntimeNative::setSystemProperty); } - public boolean isKeyReadable(String key) { + private static boolean isKeyReadable(String key) { final String root = getKeyRoot(key); if (root.startsWith("debug.")) return true; @@ -183,10 +164,10 @@ public class RavenwoodSystemProperties { return true; } - return mKeyReadable.contains(key); + return false; } - public boolean isKeyWritable(String key) { + private static boolean isKeyWritable(String key) { final String root = getKeyRoot(key); if (root.startsWith("debug.")) return true; @@ -194,42 +175,11 @@ public class RavenwoodSystemProperties { // For PropertyInvalidatedCache if (root.startsWith("cache_key.")) return true; - return mKeyWritable.contains(key); - } - - 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); + return false; } - public void setAccessReadWrite(String key) { - ensureNotImmutable(); - mKeyReadable.add(key); - mKeyWritable.add(key); + static boolean isKeyAccessible(String key, boolean write) { + return write ? isKeyWritable(key) : isKeyReadable(key); } /** diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java index 6262ad160c0f..e49d3d934e9f 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java @@ -92,7 +92,7 @@ public final class RavenwoodRule implements TestRule { } } - final RavenwoodSystemProperties mSystemProperties = new RavenwoodSystemProperties(); + final RavenwoodTestProperties mProperties = new RavenwoodTestProperties(); public static class Builder { @@ -144,8 +144,8 @@ public final class RavenwoodRule implements TestRule { * Has no effect on non-Ravenwood environments. */ public Builder setSystemPropertyImmutable(@NonNull String key, @Nullable Object value) { - mRule.mSystemProperties.setValue(key, value); - mRule.mSystemProperties.setAccessReadOnly(key); + mRule.mProperties.setValue(key, value); + mRule.mProperties.setAccessReadOnly(key); return this; } @@ -160,8 +160,8 @@ public final class RavenwoodRule implements TestRule { * Has no effect on non-Ravenwood environments. */ public Builder setSystemPropertyMutable(@NonNull String key, @Nullable Object value) { - mRule.mSystemProperties.setValue(key, value); - mRule.mSystemProperties.setAccessReadWrite(key); + mRule.mProperties.setValue(key, value); + mRule.mProperties.setAccessReadWrite(key); return this; } diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodTestProperties.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodTestProperties.java new file mode 100644 index 000000000000..66a26b511213 --- /dev/null +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodTestProperties.java @@ -0,0 +1,59 @@ +/* + * 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); + } +} diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java index 7b940b423b69..9a78989dad55 100644 --- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java +++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java @@ -56,7 +56,11 @@ public class RavenwoodRuntimeNative { public static native boolean setSystemProperty(String key, String value); - public static native void clearSystemProperties(); + public static native boolean removeSystemProperty(String key); + + public static void clearSystemProperties() { + removeSystemProperty(null); + } public static native int gettid(); diff --git a/ravenwood/runtime-jni/jni_helper.h b/ravenwood/runtime-jni/jni_helper.h index 561fb3beda6b..25d75193de09 100644 --- a/ravenwood/runtime-jni/jni_helper.h +++ b/ravenwood/runtime-jni/jni_helper.h @@ -26,6 +26,7 @@ constexpr const char* kCommonUtils = "com/android/ravenwood/common/RavenwoodCommonUtils"; constexpr const char* kRuntimeEnvController = "android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController"; +constexpr const char* kRunnerState = "android/platform/test/ravenwood/RavenwoodRunnerState"; constexpr const char* kRuntimeNative = "com/android/ravenwood/RavenwoodRuntimeNative"; // We have to explicitly decode the string to real UTF-8, because when using GetStringUTFChars diff --git a/ravenwood/runtime-jni/ravenwood_sysprop.cpp b/ravenwood/runtime-jni/ravenwood_sysprop.cpp index aafc4268d782..a78aa8da9052 100644 --- a/ravenwood/runtime-jni/ravenwood_sysprop.cpp +++ b/ravenwood/runtime-jni/ravenwood_sysprop.cpp @@ -117,7 +117,7 @@ void __system_property_read_callback(const prop_info* pi, // ---- JNI ---- static JavaVM* gVM = nullptr; -static jclass gEnvController = nullptr; +static jclass gRunnerState = nullptr; static jmethodID gCheckSystemPropertyAccess; static void reloadNativeLibrary(JNIEnv* env, jclass, jstring javaPath) { @@ -128,11 +128,11 @@ static void reloadNativeLibrary(JNIEnv* env, jclass, jstring javaPath) { // Call back into Java code to check property access static void check_system_property_access(const char* key, bool write) { - if (gVM != nullptr && gEnvController != nullptr) { + if (gVM != nullptr && gRunnerState != nullptr) { JNIEnv* env; if (gVM->GetEnv((void**)&env, JNI_VERSION_1_4) >= 0) { ALOGI("%s access to system property '%s'", write ? "Write" : "Read", key); - env->CallStaticVoidMethod(gEnvController, gCheckSystemPropertyAccess, + env->CallStaticVoidMethod(gRunnerState, gCheckSystemPropertyAccess, env->NewStringUTF(key), write ? JNI_TRUE : JNI_FALSE); return; } @@ -155,16 +155,29 @@ static jboolean setSystemProperty(JNIEnv* env, jclass, jstring javaKey, jstring return property_set(key.c_str(), value.c_str()) ? JNI_TRUE : JNI_FALSE; } -static void clearSystemProperties(JNIEnv*, jclass) { +static jboolean removeSystemProperty(JNIEnv* env, jclass, jstring javaKey) { std::lock_guard lock(g_properties_lock); - g_properties.clear(); + + if (javaKey == nullptr) { + g_properties.clear(); + return JNI_TRUE; + } else { + ScopedUtfChars key(env, javaKey); + auto it = g_properties.find(key); + if (it != g_properties.end()) { + g_properties.erase(it); + return JNI_TRUE; + } else { + return JNI_FALSE; + } + } } static const JNINativeMethod sMethods[] = { {"reloadNativeLibrary", "(Ljava/lang/String;)V", (void*)reloadNativeLibrary}, {"getSystemProperty", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getSystemProperty}, {"setSystemProperty", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)setSystemProperty}, - {"clearSystemProperties", "()V", (void*)clearSystemProperties}, + {"removeSystemProperty", "(Ljava/lang/String;)Z", (void*)removeSystemProperty}, }; extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) { @@ -174,9 +187,9 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) { gVM = vm; // Fetch several references for future use - gEnvController = FindGlobalClassOrDie(env, kRuntimeEnvController); + gRunnerState = FindGlobalClassOrDie(env, kRunnerState); gCheckSystemPropertyAccess = - GetStaticMethodIDOrDie(env, gEnvController, "checkSystemPropertyAccess", + GetStaticMethodIDOrDie(env, gRunnerState, "checkSystemPropertyAccess", "(Ljava/lang/String;Z)V"); // Expose raw property methods as JNI methods diff --git a/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/SystemPropertyTest.java b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/SystemPropertyTest.java new file mode 100644 index 000000000000..70bf204ed823 --- /dev/null +++ b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/SystemPropertyTest.java @@ -0,0 +1,88 @@ +/* + * 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 com.android.ravenwoodtest.runtimetest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.os.SystemProperties; +import android.platform.test.ravenwood.RavenwoodRule; + +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runners.model.Statement; + +public class SystemPropertyTest { + + private static final String PROP_KEY_1 = "debug.ravenwood.prop1"; + private static final String PROP_VAL_1 = "ravenwood.1"; + private static final String PROP_KEY_2 = "debug.ravenwood.prop2"; + private static final String PROP_VAL_2 = "ravenwood.2"; + private static final String PROP_KEY_3 = "debug.ravenwood.prop3"; + private static final String PROP_VAL_3 = "ravenwood.3"; + private static final String PROP_VAL_4 = "ravenwood.4"; + + @ClassRule(order = 0) + public static TestRule mCheckClassRule = (base, description) -> new Statement() { + @Override + public void evaluate() throws Throwable { + assertTrue(SystemProperties.get(PROP_KEY_1).isEmpty()); + assertTrue(SystemProperties.get(PROP_KEY_3).isEmpty()); + try { + base.evaluate(); + } finally { + assertTrue(SystemProperties.get(PROP_KEY_1).isEmpty()); + assertTrue(SystemProperties.get(PROP_KEY_3).isEmpty()); + } + } + }; + + @ClassRule(order = 1) + public static RavenwoodRule mClassRule = new RavenwoodRule.Builder() + .setSystemPropertyImmutable(PROP_KEY_1, PROP_VAL_1) + .setSystemPropertyImmutable(PROP_KEY_3, PROP_VAL_4) + .build(); + + @Rule(order = 0) + public TestRule mCheckRule = (base, description) -> new Statement() { + @Override + public void evaluate() throws Throwable { + assertTrue(SystemProperties.get(PROP_KEY_2).isEmpty()); + assertEquals(SystemProperties.get(PROP_KEY_3), PROP_VAL_4); + try { + base.evaluate(); + } finally { + assertTrue(SystemProperties.get(PROP_KEY_2).isEmpty()); + assertEquals(SystemProperties.get(PROP_KEY_3), PROP_VAL_4); + } + } + }; + + @Rule(order = 1) + public RavenwoodRule mRule = new RavenwoodRule.Builder() + .setSystemPropertyImmutable(PROP_KEY_2, PROP_VAL_2) + .setSystemPropertyImmutable(PROP_KEY_3, PROP_VAL_3) + .build(); + + @Test + public void testRavenwoodRuleSetProperty() { + assertEquals(SystemProperties.get(PROP_KEY_1), PROP_VAL_1); + assertEquals(SystemProperties.get(PROP_KEY_2), PROP_VAL_2); + assertEquals(SystemProperties.get(PROP_KEY_3), PROP_VAL_3); + } +} |