summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAdnan Begovic <adnan@cyngn.com>2016-02-04 16:39:43 -0800
committerAdnan Begovic <adnan@cyngn.com>2016-02-05 13:52:31 -0800
commiteb173968310dbdc8c8edbcde25a51c9e41724c73 (patch)
tree0e49a29a1d6793800b66ba7ce6f00bd2a0d563d5 /tests
parenta6ce9b8325dcaffcf28a5a06c37723a973c9d295 (diff)
downloadvendor_cmsdk-eb173968310dbdc8c8edbcde25a51c9e41724c73.zip
vendor_cmsdk-eb173968310dbdc8c8edbcde25a51c9e41724c73.tar.gz
vendor_cmsdk-eb173968310dbdc8c8edbcde25a51c9e41724c73.tar.bz2
cmsdk: Add concept of parameterized BinderIdTransactionTest.
To avoid any future release having offset binder transaction call ids, create a means to validate binder transaction ids within a parameterized environment based off of prior releases. This requires utilizing the new android testing support library for junit4 support. Change-Id: Iefe3c183de2bdfa127ea53dcf21c8223f0355c34
Diffstat (limited to 'tests')
-rw-r--r--tests/Android.mk3
-rw-r--r--tests/AndroidManifest.xml5
-rw-r--r--tests/README.md2
-rw-r--r--tests/src/org/cyanogenmod/tests/CyanogenModTestApplication.java37
-rw-r--r--tests/src/org/cyanogenmod/tests/versioning/unit/BinderTransactionTest.java165
-rw-r--r--tests/src/org/cyanogenmod/tests/versioning/unit/ClassPathTest.java20
-rw-r--r--tests/src/org/cyanogenmod/tests/versioning/unit/MagicalDexHelper.java55
-rw-r--r--tests/src/org/cyanogenmod/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java118
8 files changed, 382 insertions, 23 deletions
diff --git a/tests/Android.mk b/tests/Android.mk
index e8a7383..525b39e 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -19,7 +19,8 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := \
- org.cyanogenmod.platform.sdk
+ org.cyanogenmod.platform.sdk \
+ android-support-test
LOCAL_SRC_FILES := $(call all-subdir-java-files, src/)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 8eeb269..5016a35 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -22,7 +22,8 @@
<uses-permission android:name="cyanogenmod.permission.MANAGE_PERSISTENT_STORAGE" />
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
- <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+ <application android:name=".CyanogenModTestApplication"
+ android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<uses-library android:name="android.test.runner" />
<activity android:name=".customtiles.CMStatusBarTest"
android:label="@string/app_name">
@@ -79,6 +80,6 @@
</application>
<instrumentation
- android:name="android.test.InstrumentationTestRunner"
+ android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="org.cyanogenmod.tests" />
</manifest>
diff --git a/tests/README.md b/tests/README.md
index a6e3b0c..9d32357 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -4,4 +4,4 @@ tests which can be ran utilizing the InstrumentationTestRunner from android.
To run the tests (on a live device):
- ```adb shell am instrument -w org.cyanogenmod.tests/android.test.InstrumentationTestRunner```
+ ```adb shell am instrument -w org.cyanogenmod.tests/android.support.test.runner.AndroidJUnitRunner```
diff --git a/tests/src/org/cyanogenmod/tests/CyanogenModTestApplication.java b/tests/src/org/cyanogenmod/tests/CyanogenModTestApplication.java
new file mode 100644
index 0000000..a738908
--- /dev/null
+++ b/tests/src/org/cyanogenmod/tests/CyanogenModTestApplication.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod 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 org.cyanogenmod.tests;
+
+import android.app.Application;
+import android.content.Context;
+
+/**
+ * Created by adnan on 2/4/16.
+ */
+public class CyanogenModTestApplication extends Application {
+ private static Context sApplicationContext;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ sApplicationContext = getApplicationContext();
+ }
+
+ public static Context getStaticApplicationContext() {
+ return sApplicationContext;
+ }
+}
diff --git a/tests/src/org/cyanogenmod/tests/versioning/unit/BinderTransactionTest.java b/tests/src/org/cyanogenmod/tests/versioning/unit/BinderTransactionTest.java
new file mode 100644
index 0000000..b83b727
--- /dev/null
+++ b/tests/src/org/cyanogenmod/tests/versioning/unit/BinderTransactionTest.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod 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 org.cyanogenmod.tests.versioning.unit;
+
+import android.content.Context;
+import android.os.Binder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.cyanogenmod.tests.CyanogenModTestApplication;
+import org.cyanogenmod.tests.versioning.unit.apiv2.ApiV2PriorReleaseInterfaces;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.runner.AndroidJUnitRunner;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * These tests validate the enumerated binder transaction call ids per each
+ * release api level against the current framework.
+ *
+ * This is to validate that no interface contracts are broken in terms of binder
+ * call method mapping between releases.
+ *
+ * After too much searching on the internet, I found that no one was bored enough to
+ * spend time on this awesomely boring concept. But I am.
+ *
+ * Also this is a fun endeavour into parameterized unit testing, and by fun, I mean
+ * horrible and full of drinking.
+ *
+ * If you need to blame anyone for this concept, look no further than danesh@cyngn.com
+ */
+@RunWith(Parameterized.class)
+@LargeTest
+public class BinderTransactionTest extends AndroidTestCase {
+ private static final String STUB_SUFFIX = "$Stub";
+ private static final String CYANOGENMOD_NAMESPACE = "cyanogenmod";
+ private static final String TRANSACTION_PREFIX = "TRANSACTION_";
+
+ private static final int NOT_FROM_PRIOR_RELEASE = -1;
+
+ private String mField;
+ private int mExpectedValue;
+ private int mActualValue;
+ private static Context sContext;
+
+ private static ArrayList<String> mKnownSdkClasses;
+ private static Map<String, Integer> mApiMethodsAndValues = new HashMap<String, Integer>();
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Test
+ public void testClassLoaderGivesSDKClasses() {
+ /**
+ * Verify we can retrieve our sdk classes from this package
+ */
+ assertNotNull(mKnownSdkClasses);
+ assertTrue(mKnownSdkClasses.size() > 0);
+ }
+
+ private static void doSetup() {
+ mKnownSdkClasses = MagicalDexHelper.getLoadedClasses(
+ CyanogenModTestApplication.getStaticApplicationContext(), CYANOGENMOD_NAMESPACE);
+ sContext = CyanogenModTestApplication.getStaticApplicationContext();
+ mApiMethodsAndValues.putAll(ApiV2PriorReleaseInterfaces.getInterfaces());
+ }
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> data() {
+ doSetup();
+ //Ughhh, lets pretend this never happened
+ ArrayList<String> targetFields = new ArrayList<String>();
+ ArrayList<Integer> actualValues = new ArrayList<Integer>();
+
+ for (String sClazz : mKnownSdkClasses) {
+ if (sClazz.endsWith(STUB_SUFFIX)) {
+ try {
+ Class clazz = MagicalDexHelper.loadClassForNameSpace(CyanogenModTestApplication
+ .getStaticApplicationContext(), sClazz);
+ Field[] fields = clazz.getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getName().startsWith(TRANSACTION_PREFIX)) {
+ field.setAccessible(true);
+ targetFields.add(field.getName()
+ .substring(TRANSACTION_PREFIX.length()));
+ try {
+ actualValues.add(field.getInt(clazz));
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Unable to access " + field.getName());
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new AssertionError("Unable to load class " + sClazz);
+ }
+ }
+ }
+ Object[][] values = new Object[targetFields.size()][3];
+
+ for (int i = 0; i < targetFields.size(); i++) {
+ String targetField = targetFields.get(i);
+ values[i][0] = targetField;
+ values[i][1] = lookupValueForField(targetField);
+ values[i][2] = actualValues.get(i);
+ }
+ return Arrays.asList(values);
+ }
+
+ //Look up the target fields value from a prior release
+ private static Object lookupValueForField(String fieldName) {
+ if (!mApiMethodsAndValues.containsKey(fieldName)) {
+ return NOT_FROM_PRIOR_RELEASE;
+ }
+ return mApiMethodsAndValues.get(fieldName);
+ }
+
+ public BinderTransactionTest(String targetField, Integer expectedValue, Integer actualValue) {
+ mField = targetField;
+ mExpectedValue = expectedValue;
+ mActualValue = actualValue;
+ }
+
+ @Test
+ public void testBinderTransactionValidation() {
+ System.out.print("Testing: " + mField);
+ if (mExpectedValue == NOT_FROM_PRIOR_RELEASE) {
+ //This is a new interface, no need to test against
+ return;
+ }
+ try {
+ assertEquals(mExpectedValue, mActualValue);
+ } catch (AssertionError e) {
+ throw new AssertionError("For the field " + mField + " expected value "
+ + mExpectedValue + " but got " + mActualValue);
+ }
+ }
+}
diff --git a/tests/src/org/cyanogenmod/tests/versioning/unit/ClassPathTest.java b/tests/src/org/cyanogenmod/tests/versioning/unit/ClassPathTest.java
index e1ae1c3..481ae7b 100644
--- a/tests/src/org/cyanogenmod/tests/versioning/unit/ClassPathTest.java
+++ b/tests/src/org/cyanogenmod/tests/versioning/unit/ClassPathTest.java
@@ -39,7 +39,7 @@ public class ClassPathTest extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
- mKnownSdkClasses = getLoadedClasses();
+ mKnownSdkClasses = MagicalDexHelper.getLoadedClasses(mContext, CYANOGENMOD_NAMESPACE);
}
@SmallTest
@@ -86,24 +86,6 @@ public class ClassPathTest extends AndroidTestCase {
}
}
- private ArrayList<String> getLoadedClasses() {
- ArrayList<String> listOfClasses = new ArrayList<String>();
- try {
- DexFile dexFile = new DexFile(new File(mContext.getPackageCodePath()));
- Enumeration<String> enumeration = dexFile.entries();
-
- while (enumeration.hasMoreElements()){
- String className = enumeration.nextElement();
- if (className.startsWith(CYANOGENMOD_NAMESPACE)) {
- listOfClasses.add(className);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return listOfClasses;
- }
-
private void processAndCompare(String name) throws ClassPathException {
if (mKnownSdkClasses.contains(name)) {
throw new ClassPathException(name);
diff --git a/tests/src/org/cyanogenmod/tests/versioning/unit/MagicalDexHelper.java b/tests/src/org/cyanogenmod/tests/versioning/unit/MagicalDexHelper.java
new file mode 100644
index 0000000..a7f2ccc
--- /dev/null
+++ b/tests/src/org/cyanogenmod/tests/versioning/unit/MagicalDexHelper.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod 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 org.cyanogenmod.tests.versioning.unit;
+
+import android.content.Context;
+import dalvik.system.DexFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Created by adnan on 2/3/16.
+ */
+public class MagicalDexHelper {
+
+ public static ArrayList<String> getLoadedClasses(Context context, String targetNameSpace) {
+ ArrayList<String> listOfClasses = new ArrayList<String>();
+ try {
+ DexFile dexFile = new DexFile(new File(context.getPackageCodePath()));
+ Enumeration<String> enumeration = dexFile.entries();
+
+ while (enumeration.hasMoreElements()){
+ String className = enumeration.nextElement();
+ if (className.startsWith(targetNameSpace)) {
+ listOfClasses.add(className);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return listOfClasses;
+ }
+
+ public static Class loadClassForNameSpace(Context context,
+ String classToLoad) throws IOException {
+ DexFile dexFile = new DexFile(new File(context.getPackageCodePath()));
+ return dexFile.loadClass(classToLoad, context.getClassLoader());
+ }
+}
diff --git a/tests/src/org/cyanogenmod/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java b/tests/src/org/cyanogenmod/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java
new file mode 100644
index 0000000..26a0ce9
--- /dev/null
+++ b/tests/src/org/cyanogenmod/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod 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 org.cyanogenmod.tests.versioning.unit.apiv2;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by adnan on 2/4/16.
+ */
+public class ApiV2PriorReleaseInterfaces {
+ private static Map<String, Integer> mApiMethodsAndValues = new HashMap<String, Integer>();
+
+ //Profiles Aidl (IProfileManager)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ mApiMethodsAndValues.put("setActiveProfile", 1);
+ mApiMethodsAndValues.put("etActiveProfileByName", 2);
+ mApiMethodsAndValues.put("getActiveProfile", 3);
+ mApiMethodsAndValues.put("addProfile", 4);
+ mApiMethodsAndValues.put("removeProfile", 5);
+ mApiMethodsAndValues.put("updateProfile", 6);
+ mApiMethodsAndValues.put("getProfile", 7);
+ mApiMethodsAndValues.put("getProfileByName", 8);
+ mApiMethodsAndValues.put("getProfiles", 9);
+ mApiMethodsAndValues.put("profileExists", 10);
+ mApiMethodsAndValues.put("profileExistsByName", 11);
+ mApiMethodsAndValues.put("notificationGroupExistsByName", 12);
+ mApiMethodsAndValues.put("getNotificationGroups", 13);
+ mApiMethodsAndValues.put("addNotificationGroup", 14);
+ mApiMethodsAndValues.put("removeNotificationGroup", 15);
+ mApiMethodsAndValues.put("updateNotificationGroup", 16);
+ mApiMethodsAndValues.put("getNotificationGroupForPackage", 17);
+ mApiMethodsAndValues.put("getNotificationGroup", 18);
+ mApiMethodsAndValues.put("resetAll", 19);
+
+ //FUTURE RELEASE
+ }
+
+ //PartnerInterface Aidl (IPartnerInterface)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ mApiMethodsAndValues.put("setAirplaneModeEnabled_0", 1);
+ mApiMethodsAndValues.put("setMobileDataEnabled_1", 2);
+ mApiMethodsAndValues.put("setZenMode", 3);
+ mApiMethodsAndValues.put("shutdown", 4);
+ mApiMethodsAndValues.put("reboot", 5);
+ mApiMethodsAndValues.put("getCurrentHotwordPackageName", 6);
+
+ //FUTURE RELEASE
+ }
+
+ //CMHardwareManager Aidl (ICMHardwareService)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ mApiMethodsAndValues.put("getSupportedFeatures_0", 1);
+ mApiMethodsAndValues.put("get_1", 2);
+ mApiMethodsAndValues.put("set", 3);
+ mApiMethodsAndValues.put("getDisplayColorCalibration", 4);
+ mApiMethodsAndValues.put("setDisplayColorCalibration", 5);
+ mApiMethodsAndValues.put("getNumGammaControls", 6);
+ mApiMethodsAndValues.put("getDisplayGammaCalibration", 7);
+ mApiMethodsAndValues.put("setDisplayGammaCalibration", 8);
+ mApiMethodsAndValues.put("getVibratorIntensity", 9);
+ mApiMethodsAndValues.put("setVibratorIntensity", 10);
+ mApiMethodsAndValues.put("getLtoSource", 11);
+ mApiMethodsAndValues.put("getLtoDestination", 12);
+ mApiMethodsAndValues.put("getLtoDownloadInterval", 13);
+ mApiMethodsAndValues.put("getSerialNumber", 14);
+ mApiMethodsAndValues.put("requireAdaptiveBacklightForSunlightEnhancement", 15);
+ mApiMethodsAndValues.put("getDisplayModes", 16);
+ mApiMethodsAndValues.put("getCurrentDisplayMode", 17);
+ mApiMethodsAndValues.put("getDefaultDisplayMode", 18);
+ mApiMethodsAndValues.put("setDisplayMode", 19);
+ mApiMethodsAndValues.put("writePersistentBytes", 20);
+ mApiMethodsAndValues.put("readPersistentBytes", 21);
+ mApiMethodsAndValues.put("getThermalState", 22);
+ mApiMethodsAndValues.put("registerThermalListener", 23);
+ mApiMethodsAndValues.put("unRegisterThermalListener", 24);
+
+ //FUTURE RELEASE
+ }
+
+ //CMStatusBarManager Aidl (ICMStatusBarManager)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ mApiMethodsAndValues.put("createCustomTileWithTag", 1);
+ mApiMethodsAndValues.put("removeCustomTileWithTag", 2);
+ mApiMethodsAndValues.put("registerListener", 3);
+ mApiMethodsAndValues.put("unregisterListener", 4);
+ mApiMethodsAndValues.put("removeCustomTileFromListener", 5);
+
+ //FUTURE RELEASE
+ }
+
+ //AppSuggestManager Aidl (IAppSuggestManager)
+ static {
+ mApiMethodsAndValues.put("handles_0", 1);
+ mApiMethodsAndValues.put("getSuggestions_1", 2);
+ }
+
+ public static Map<String, Integer> getInterfaces() {
+ return mApiMethodsAndValues;
+ }
+}