diff options
author | Raphael Moll <ralf@android.com> | 2012-04-11 12:47:40 -0700 |
---|---|---|
committer | Raphael Moll <ralf@android.com> | 2012-04-11 13:24:17 -0700 |
commit | b354c5dcba5e2b4334132fb50b0b343d325f448e (patch) | |
tree | 53f14d9a11e96fa38362b36d643630dec2742f77 /sdkstats | |
parent | abd814d21bcc4772e8ae7062366568dd667e9db2 (diff) | |
download | sdk-b354c5dcba5e2b4334132fb50b0b343d325f448e.zip sdk-b354c5dcba5e2b4334132fb50b0b343d325f448e.tar.gz sdk-b354c5dcba5e2b4334132fb50b0b343d325f448e.tar.bz2 |
SDK: adjust reported OS/JVM name/arch.
Also add some UTs for testing.
Change-Id: I55d4ad04feade4b4e8a81316511720731f9afdc9
Diffstat (limited to 'sdkstats')
-rw-r--r-- | sdkstats/.classpath | 2 | ||||
-rw-r--r-- | sdkstats/src/com/android/sdkstats/SdkStatsService.java | 84 | ||||
-rwxr-xr-x | sdkstats/tests/com/android/sdkstats/SdkStatsServiceTest.java | 279 |
3 files changed, 337 insertions, 28 deletions
diff --git a/sdkstats/.classpath b/sdkstats/.classpath index e823aa5..299175e 100644 --- a/sdkstats/.classpath +++ b/sdkstats/.classpath @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="tests"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/> <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/linux-x86/swt/swt.jar"/> <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/eclipse/org.eclipse.core.commands_3.6.0.I20100512-1500.jar"/> <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/eclipse/org.eclipse.equinox.common_3.6.0.v20100503.jar"/> <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/eclipse/org.eclipse.jface_3.6.2.M20110210-1200.jar"/> + <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/sdkstats/src/com/android/sdkstats/SdkStatsService.java b/sdkstats/src/com/android/sdkstats/SdkStatsService.java index 298132d..9c3a008 100644 --- a/sdkstats/src/com/android/sdkstats/SdkStatsService.java +++ b/sdkstats/src/com/android/sdkstats/SdkStatsService.java @@ -23,12 +23,18 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; /** Utility class to send "ping" usage reports to the server. */ public class SdkStatsService { + protected static final String SYS_PROP_OS_ARCH = "os.arch"; //$NON-NLS-1$ + protected static final String SYS_PROP_JAVA_VERSION = "java.version"; //$NON-NLS-1$ + protected static final String SYS_PROP_OS_VERSION = "os.version"; //$NON-NLS-1$ + protected static final String SYS_PROP_OS_NAME = "os.name"; //$NON-NLS-1$ + /** Minimum interval between ping, in milliseconds. */ private static final long PING_INTERVAL_MSEC = 86400 * 1000; // 1 day @@ -42,7 +48,7 @@ public class SdkStatsService { * elapsed since the last ping, and if the user has not opted out.<br> * * The ping will not be sent if the user opt out dialog has not been shown yet. - * Use {@link #getUserPermissionForPing(Shell)} to display the dialog requesting + * Use {@link #checkUserPermissionForPing(Shell)} to display the dialog requesting * user permissions.<br> * * Note: The actual ping (if any) is sent in a <i>non-daemon</i> background thread. @@ -58,8 +64,8 @@ public class SdkStatsService { * Display a dialog to the user providing information about the ping service, * and whether they'd like to opt-out of it. * - * Once the dialog has been shown, it sets a preference internally indicating that the user has - * viewed this dialog. This setting can be queried using {@link #pingPermissionsSet()}. + * Once the dialog has been shown, it sets a preference internally indicating + * that the user has viewed this dialog. */ public void checkUserPermissionForPing(Shell parent) { if (!mStore.hasPingId()) { @@ -137,7 +143,7 @@ public class SdkStatsService { * @param id of the local installation * @throws IOException if the ping failed */ - private static void actuallySendPing(String app, String version, long id) + private void actuallySendPing(String app, String version, long id) throws IOException { String osName = URLEncoder.encode(getOsName(), "UTF-8"); String osArch = URLEncoder.encode(getOsArch(), "UTF-8"); @@ -173,26 +179,28 @@ public class SdkStatsService { * For Windows and Mac also append the version, so for example * Win XP will return win-5.1. */ - private static String getOsName() { - String os = System.getProperty("os.name"); //$NON-NLS-1$ + protected String getOsName() { // made protected for testing + String os = getSystemProperty(SYS_PROP_OS_NAME); if (os == null || os.length() == 0) { return "unknown"; //$NON-NLS-1$ } - if (os.startsWith("Mac OS")) { //$NON-NLS-1$ + String os2 = os.toLowerCase(Locale.US); + + if (os2.startsWith("mac")) { //$NON-NLS-1$ os = "mac"; //$NON-NLS-1$ String osVers = getOsVersion(); if (osVers != null) { os = os + '-' + osVers; } - } else if (os.startsWith("Windows")) { //$NON-NLS-1$ + } else if (os2.startsWith("win")) { //$NON-NLS-1$ os = "win"; //$NON-NLS-1$ String osVers = getOsVersion(); if (osVers != null) { os = os + '-' + osVers; } - } else if (os.startsWith("Linux")) { //$NON-NLS-1$ + } else if (os2.startsWith("linux")) { //$NON-NLS-1$ os = "linux"; //$NON-NLS-1$ } else if (os.length() > 32) { @@ -208,7 +216,7 @@ public class SdkStatsService { * This may differ or be equal to the JVM architecture in the sense that * a 64-bit OS can run a 32-bit JVM. */ - private static String getOsArch() { + protected String getOsArch() { // made protected for testing String arch = getJvmArch(); if ("x86_64".equals(arch)) { //$NON-NLS-1$ @@ -229,16 +237,16 @@ public class SdkStatsService { // it sets PROCESSOR_ARCHITEW6432 to AMD64 or IA64 accordingly. // Ref: http://msdn.microsoft.com/en-us/library/aa384274(v=vs.85).aspx - String w6432 = System.getenv("PROCESSOR_ARCHITEW6432"); //$NON-NLS-1$ + String w6432 = getSystemEnv("PROCESSOR_ARCHITEW6432"); //$NON-NLS-1$ if (w6432 != null && w6432.indexOf("64") != -1) { //$NON-NLS-1$ return "x86_64"; //$NON-NLS-1$ } } else if (os.startsWith("linux")) { //$NON-NLS-1$ // Let's try the obvious. This works in Ubuntu and Debian - String s = System.getenv("HOSTTYPE"); //$NON-NLS-1$ + String s = getSystemEnv("HOSTTYPE"); //$NON-NLS-1$ s = sanitizeOsArch(s); - if (s.indexOf("86") != -1) { + if (s.indexOf("86") != -1) { //$NON-NLS-1$ arch = s; } } @@ -253,15 +261,17 @@ public class SdkStatsService { * Example of returned versions can be found at http://lopica.sourceforge.net/os.html * <p/> * This method removes any exiting micro versions. + * Returns null if the version doesn't match X.Y.Z. */ - private static String getOsVersion() { - Pattern p = Pattern.compile("(\\d+)\\.(\\d+).*"); //$NON-NLS-1$ - String osVers = System.getProperty("os.version"); //$NON-NLS-1$ - Matcher m = p.matcher(osVers); - if (m.matches()) { - return m.group(1) + '.' + m.group(2); + protected String getOsVersion() { // made protected for testing + Pattern p = Pattern.compile("(\\d+)\\.(\\d+).*"); //$NON-NLS-1$ + String osVers = getSystemProperty(SYS_PROP_OS_VERSION); + if (osVers != null && osVers.length() > 0) { + Matcher m = p.matcher(osVers); + if (m.matches()) { + return m.group(1) + '.' + m.group(2); + } } - return null; } @@ -269,7 +279,7 @@ public class SdkStatsService { * Detects and returns the JVM info: version + architecture. * Examples: 1.4-ppc, 1.6-x86, 1.7-x86_64 */ - private static String getJvmInfo() { + protected String getJvmInfo() { // made protected for testing return getJvmVersion() + '-' + getJvmArch(); } @@ -279,8 +289,8 @@ public class SdkStatsService { * The "java.version" property returns something like "1.6.0_20" * of which we want to return "1.6". */ - private static String getJvmVersion() { - String version = System.getProperty("java.version"); //$NON-NLS-1$ + protected String getJvmVersion() { // made protected for testing + String version = getSystemProperty(SYS_PROP_JAVA_VERSION); if (version == null || version.length() == 0) { return "unknown"; //$NON-NLS-1$ @@ -318,12 +328,12 @@ public class SdkStatsService { * Mac untested x86_64 * </pre> */ - private static String getJvmArch() { - String arch = System.getProperty("os.arch"); //$NON-NLS-1$ + protected String getJvmArch() { // made protected for testing + String arch = getSystemProperty(SYS_PROP_OS_ARCH); return sanitizeOsArch(arch); } - private static String sanitizeOsArch(String arch) { + private String sanitizeOsArch(String arch) { if (arch == null || arch.length() == 0) { return "unknown"; //$NON-NLS-1$ } @@ -334,7 +344,7 @@ public class SdkStatsService { return "x86_64"; //$NON-NLS-1$ } - if (arch.length() == 4 && arch.charAt(0) == 'i' && arch.lastIndexOf("86") == 2) { + if (arch.length() >= 4 && arch.charAt(0) == 'i' && arch.indexOf("86") == 2) { //$NON-NLS-1$ // Any variation of iX86 counts as x86 (i386, i486, i686). return "x86"; //$NON-NLS-1$ } @@ -356,7 +366,7 @@ public class SdkStatsService { * @param version supplied by caller * @return normalized dotted quad version */ - private static String normalizeVersion(String app, String version) { + private String normalizeVersion(String app, String version) { // Application name must contain only word characters (no punctuation) if (!app.matches("\\w+")) { //$NON-NLS-1$ throw new IllegalArgumentException("Bad app name: " + app); //$NON-NLS-1$ @@ -380,4 +390,22 @@ public class SdkStatsService { } return normal.toString(); } + + /** + * Calls {@link System#getProperty(String)}. + * Allows unit-test to override the return value. + * @see System#getProperty(String) + */ + protected String getSystemProperty(String name) { + return System.getProperty(name); + } + + /** + * Calls {@link System#getenv(String)}. + * Allows unit-test to override the return value. + * @see System#getenv(String) + */ + protected String getSystemEnv(String name) { + return System.getenv(name); + } } diff --git a/sdkstats/tests/com/android/sdkstats/SdkStatsServiceTest.java b/sdkstats/tests/com/android/sdkstats/SdkStatsServiceTest.java new file mode 100755 index 0000000..6b8a4eb --- /dev/null +++ b/sdkstats/tests/com/android/sdkstats/SdkStatsServiceTest.java @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2012 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.sdkstats; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +public class SdkStatsServiceTest extends TestCase { + + private static class MockSdkStatsService extends SdkStatsService { + + private final String mOsName; + private final String mOsVersion; + private final String mOsArch; + private final String mJavaVersion; + private final Map<String, String> mEnvVars = new HashMap<String, String>(); + + public MockSdkStatsService(String osName, + String osVersion, + String osArch, + String javaVersion) { + mOsName = osName; + mOsVersion = osVersion; + mOsArch = osArch; + mJavaVersion = javaVersion; + } + + public void setSystemEnv(String varName, String value) { + mEnvVars.put(varName, value); + } + + @Override + protected String getSystemProperty(String name) { + if (SdkStatsService.SYS_PROP_OS_NAME.equals(name)) { + return mOsName; + } else if (SdkStatsService.SYS_PROP_OS_VERSION.equals(name)) { + return mOsVersion; + } else if (SdkStatsService.SYS_PROP_OS_ARCH.equals(name)) { + return mOsArch; + } else if (SdkStatsService.SYS_PROP_JAVA_VERSION.equals(name)) { + return mJavaVersion; + } + // Don't use current properties values, we don't want the tests to be flaky + fail("SdkStatsServiceTest doesn't define a system.property for " + name); + return null; + } + + @Override + protected String getSystemEnv(String name) { + if (mEnvVars.containsKey(name)) { + return mEnvVars.get(name); + } + // Don't use current env vars, we don't want the tests to be flaky + fail("SdkStatsServiceTest doesn't define a system.getenv for " + name); + return null; + } + + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSdkStatsService_getJvmArch() { + MockSdkStatsService m; + + m = new MockSdkStatsService("Windows", "4.0", "x86", "1.7"); + assertEquals("x86", m.getJvmArch()); + m = new MockSdkStatsService("Windows", "4.0", "i386", "1.7"); + assertEquals("x86", m.getJvmArch()); + m = new MockSdkStatsService("Windows", "4.0", "i486", "1.7"); + assertEquals("x86", m.getJvmArch()); + m = new MockSdkStatsService("Linux", "4.0", "i486-linux", "1.7"); + assertEquals("x86", m.getJvmArch()); + m = new MockSdkStatsService("Windows", "4.0", "i586", "1.7"); + assertEquals("x86", m.getJvmArch()); + m = new MockSdkStatsService("Windows", "4.0", "i686", "1.7"); + assertEquals("x86", m.getJvmArch()); + + m = new MockSdkStatsService("Mac OS", "10.0", "x86_64", "1.7"); + assertEquals("x86_64", m.getJvmArch()); + m = new MockSdkStatsService("Mac OS", "8.0", "PowerPC", "1.7"); + assertEquals("ppc", m.getJvmArch()); + + m = new MockSdkStatsService("Mac OS", "4.0", "x86_64", "1.7"); + assertEquals("x86_64", m.getJvmArch()); + m = new MockSdkStatsService("Windows", "4.0", "ia64", "1.7"); + assertEquals("x86_64", m.getJvmArch()); + m = new MockSdkStatsService("Windows", "4.0", "amd64", "1.7"); + assertEquals("x86_64", m.getJvmArch()); + + m = new MockSdkStatsService("Windows", "4.0", "atom", "1.7"); + assertEquals("atom", m.getJvmArch()); + + // 32 chars max + m = new MockSdkStatsService("Windows", "4.0", + "one3456789ten3456789twenty6789thirty6789", "1.7"); + assertEquals("one3456789ten3456789twenty6789th", m.getJvmArch()); + + m = new MockSdkStatsService("Windows", "4.0", "", "1.7"); + assertEquals("unknown", m.getJvmArch()); + + m = new MockSdkStatsService("Windows", "4.0", null, "1.7"); + assertEquals("unknown", m.getJvmArch()); + } + + public void testSdkStatsService_getJvmVersion() { + MockSdkStatsService m; + + m = new MockSdkStatsService("Windows", "4.0", "x86", "1.7.8_09"); + assertEquals("1.7", m.getJvmVersion()); + + m = new MockSdkStatsService("Windows", "4.0", "x86", ""); + assertEquals("unknown", m.getJvmVersion()); + + m = new MockSdkStatsService("Windows", "4.0", "x86", null); + assertEquals("unknown", m.getJvmVersion()); + + // 8 chars max + m = new MockSdkStatsService("Windows", "4.0", "x86", + "one3456789ten3456789twenty6789thirty6789"); + assertEquals("one34567", m.getJvmVersion()); + } + + public void testSdkStatsService_getJvmInfo() { + MockSdkStatsService m; + + m = new MockSdkStatsService("Windows", "4.0", "x86", "1.7.8_09"); + assertEquals("1.7-x86", m.getJvmInfo()); + + m = new MockSdkStatsService("Windows", "4.0", "amd64", "1.7.8_09"); + assertEquals("1.7-x86_64", m.getJvmInfo()); + + m = new MockSdkStatsService("Windows", "4.0", "", ""); + assertEquals("unknown-unknown", m.getJvmInfo()); + + m = new MockSdkStatsService("Windows", "4.0", null, null); + assertEquals("unknown-unknown", m.getJvmInfo()); + + // 8+32 chars max + m = new MockSdkStatsService("Windows", "4.0", + "one3456789ten3456789twenty6789thirty6789", + "one3456789ten3456789twenty6789thirty6789"); + assertEquals("one34567-one3456789ten3456789twenty6789th", m.getJvmInfo()); + } + + public void testSdkStatsService_getOsVersion() { + MockSdkStatsService m; + + m = new MockSdkStatsService("Windows", "4.0.32", "x86", "1.7.8_09"); + assertEquals("4.0", m.getOsVersion()); + + m = new MockSdkStatsService("Windows", "4.0", "x86", "1.7.8_09"); + assertEquals("4.0", m.getOsVersion()); + + m = new MockSdkStatsService("Windows", "4", "x86", "1.7.8_09"); + assertEquals(null, m.getOsVersion()); + + m = new MockSdkStatsService("Windows", "4.0;extrainfo", "x86", "1.7.8_09"); + assertEquals("4.0", m.getOsVersion()); + + m = new MockSdkStatsService("Mac OS", "10.8.32", "x86_64", "1.7.8_09"); + assertEquals("10.8", m.getOsVersion()); + + m = new MockSdkStatsService("Mac OS", "10.8", "x86_64", "1.7.8_09"); + assertEquals("10.8", m.getOsVersion()); + + m = new MockSdkStatsService("Other", "", "x86_64", "1.7.8_09"); + assertEquals(null, m.getOsVersion()); + + m = new MockSdkStatsService("Other", null, "x86_64", "1.7.8_09"); + assertEquals(null, m.getOsVersion()); + } + + public void testSdkStatsService_getOsArch() { + MockSdkStatsService m; + + // 64 bit jvm + m = new MockSdkStatsService("Mac OS", "10.8.32", "x86_64", "1.7.8_09"); + assertEquals("x86_64", m.getOsArch()); + + m = new MockSdkStatsService("Windows", "8.32", "x86_64", "1.7.8_09"); + assertEquals("x86_64", m.getOsArch()); + + m = new MockSdkStatsService("Linux", "8.32", "x86_64", "1.7.8_09"); + assertEquals("x86_64", m.getOsArch()); + + // 32 bit jvm with 32 vs 64 bit os + m = new MockSdkStatsService("Windows", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("PROCESSOR_ARCHITEW6432", null); + assertEquals("x86", m.getOsArch()); + + m = new MockSdkStatsService("Windows", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("PROCESSOR_ARCHITEW6432", "AMD64"); + assertEquals("x86_64", m.getOsArch()); + + m = new MockSdkStatsService("Windows", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("PROCESSOR_ARCHITEW6432", "IA64"); + assertEquals("x86_64", m.getOsArch()); + + // 32 bit jvm with 32 vs 64 bit os + m = new MockSdkStatsService("Linux", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("HOSTTYPE", null); + assertEquals("x86", m.getOsArch()); + + m = new MockSdkStatsService("Linux", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("HOSTTYPE", "i686-linux"); + assertEquals("x86", m.getOsArch()); + + m = new MockSdkStatsService("Linux", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("HOSTTYPE", "AMD64"); + assertEquals("x86_64", m.getOsArch()); + + m = new MockSdkStatsService("Linux", "8.32", "x86", "1.7.8_09"); + m.setSystemEnv("HOSTTYPE", "x86_64"); + assertEquals("x86_64", m.getOsArch()); + } + + public void testSdkStatsService_getOsName() { + MockSdkStatsService m; + + m = new MockSdkStatsService("Mac OS", "10.8.32", "x86_64", "1.7.8_09"); + assertEquals("mac-10.8", m.getOsName()); + + m = new MockSdkStatsService("mac", "10", "x86", "1.7.8_09"); + assertEquals("mac", m.getOsName()); + + m = new MockSdkStatsService("Windows", "6.2", "x86_64", "1.7.8_09"); + assertEquals("win-6.2", m.getOsName()); + + m = new MockSdkStatsService("win", "6.2", "x86", "1.7.8_09"); + assertEquals("win-6.2", m.getOsName()); + + m = new MockSdkStatsService("win", "6", "x86_64", "1.7.8_09"); + assertEquals("win", m.getOsName()); + + m = new MockSdkStatsService("Linux", "foobuntu-32", "x86", "1.7.8_09"); + assertEquals("linux", m.getOsName()); + + m = new MockSdkStatsService("linux", "1", "x86_64", "1.7.8_09"); + assertEquals("linux", m.getOsName()); + + m = new MockSdkStatsService("PowerPC", "32", "ppc", "1.7.8_09"); + assertEquals("PowerPC", m.getOsName()); + + m = new MockSdkStatsService("freebsd", "42", "x86_64", "1.7.8_09"); + assertEquals("freebsd", m.getOsName()); + + m = new MockSdkStatsService("openbsd", "43", "x86_64", "1.7.8_09"); + assertEquals("openbsd", m.getOsName()); + + // 32 chars max + m = new MockSdkStatsService("one3456789ten3456789twenty6789thirty6789", + "42", "x86_64", "1.7.8_09"); + assertEquals("one3456789ten3456789twenty6789th", m.getOsName()); + } +} |