| /* |
| * Copyright (C) 2009 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 tests.util; |
| |
| import java.io.File; |
| import java.util.Arrays; |
| import java.util.Locale; |
| import java.util.Properties; |
| import java.util.TimeZone; |
| import java.util.prefs.BackingStoreException; |
| import java.util.prefs.Preferences; |
| |
| /** |
| * Prepares system properties and preferences to hygienic values for testing: |
| * <ul> |
| * <li>System properties are set to reasonable defaults. Referenced |
| * directories such as the user and Java home directories will be |
| * writable. |
| * <li>System and user preferences are cleared. Once the preferences classes |
| * have been initialized, the path where their data is stored is fixed. |
| * For this reason, every test that reads or writes preferences should |
| * first reset the system configuration with this API. |
| * </ul> |
| * |
| * <p>Use this class to clean up before and/or after your test. Sample usage: |
| * <pre> |
| * public void MyTest extends TestCase { |
| * |
| * protected void setUp() throws Exception { |
| * super.setUp(); |
| * TestEnvironment().reset(); |
| * } |
| * |
| * protected void tearDown() throws Exception { |
| * TestEnvironment().reset(); |
| * super.tearDown(); |
| * } |
| * |
| * ... |
| * }</pre> |
| */ |
| public final class TestEnvironment { |
| private TestEnvironment() {} |
| |
| public static synchronized void reset() { |
| resetSystemProperties(); |
| resetPreferences(); |
| resetDefaultLocale(); |
| resetDefaultTimeZone(); |
| // TODO: SecurityManager? |
| } |
| |
| private static void resetDefaultLocale() { |
| // This is hard-coded in resetSystemProperties, so no need to be clever here. |
| Locale.setDefault(Locale.US); |
| } |
| |
| private static void resetDefaultTimeZone() { |
| TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); |
| } |
| |
| private static String getExistingSystemProperty(String name) { |
| String result = System.getProperty(name); |
| if (result == null) { |
| throw new AssertionError("Tests require the '" + name + "' system property"); |
| } |
| return result; |
| } |
| |
| private static void resetSystemProperties() { |
| // There are two system properties we can't live without. |
| // 1. We need somewhere writable to stash our stuff. |
| String tmpDir = getExistingSystemProperty("java.io.tmpdir"); |
| // 2. We need to know who we are, specifically "am I root?" because that affects what |
| // the OS lets us do, and that affects test expectations. |
| String userName = getExistingSystemProperty("user.name"); |
| |
| Properties p = new Properties(); |
| |
| // runtime properties that we never want to clobber |
| copyProperty(p, "android.vm.dexfile"); |
| copyProperty(p, "java.boot.class.path"); |
| copyProperty(p, "java.class.path"); |
| copyProperty(p, "java.io.tmpdir"); |
| copyProperty(p, "java.library.path"); |
| copyProperty(p, "os.arch"); |
| copyProperty(p, "os.name"); |
| copyProperty(p, "os.version"); |
| |
| // paths with writable values for testing |
| String userHome = tmpDir + "/user.home"; |
| String javaHome = tmpDir + "/java.home"; |
| String userDir = tmpDir + "/user.dir"; |
| makeDirectory(new File(userHome)); |
| makeDirectory(new File(javaHome)); |
| makeDirectory(new File(userDir)); |
| p.put("java.home", javaHome); |
| p.put("user.dir", userDir); |
| p.put("user.home", userHome); |
| |
| // hardcoded properties |
| p.put("file.encoding", "UTF-8"); |
| p.put("file.separator", "/"); |
| p.put("java.class.version", "46.0"); |
| p.put("java.compiler", ""); |
| p.put("java.ext.dirs", ""); |
| p.put("java.net.preferIPv6Addresses", "true"); |
| p.put("java.runtime.name", "Android Runtime"); |
| p.put("java.runtime.version", "0.9"); |
| p.put("java.specification.name", "Dalvik Core Library"); |
| p.put("java.specification.vendor", "The Android Project"); |
| p.put("java.specification.version", "0.9"); |
| p.put("java.vendor", "The Android Project"); |
| p.put("java.vendor.url", "http://www.android.com/"); |
| p.put("java.version", "0"); |
| p.put("java.vm.name", "Dalvik"); |
| p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification"); |
| p.put("java.vm.specification.vendor", "The Android Project"); |
| p.put("java.vm.specification.version", "0.9"); |
| p.put("java.vm.vendor", "The Android Project"); |
| p.put("java.vm.vendor.url", "http://www.android.com/"); |
| p.put("java.vm.version", "1.2.0"); |
| p.put("javax.net.ssl.trustStore", "/etc/security/cacerts.bks"); |
| p.put("line.separator", "\n"); |
| p.put("path.separator", ":"); |
| p.put("user.language", "en"); |
| p.put("user.name", userName); |
| p.put("user.region", "US"); |
| |
| System.setProperties(p); |
| } |
| |
| private static void copyProperty(Properties p, String key) { |
| p.put(key, System.getProperty(key)); |
| } |
| |
| private static void makeDirectory(File path) { |
| boolean success; |
| if (!path.exists()) { |
| success = path.mkdirs(); |
| } else if (!path.isDirectory()) { |
| success = path.delete() && path.mkdirs(); |
| } else { |
| success = true; |
| } |
| |
| if (!success) { |
| throw new RuntimeException("Failed to make directory " + path); |
| } |
| } |
| |
| private static void resetPreferences() { |
| try { |
| for (Preferences root : Arrays.asList( |
| Preferences.systemRoot(), Preferences.userRoot())) { |
| for (String child : root.childrenNames()) { |
| root.node(child).removeNode(); |
| } |
| root.clear(); |
| root.flush(); |
| } |
| } catch (BackingStoreException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |