am 97de064a: am 133f6826: am 89492190: Merge "Runtime resource overlay, iteration 2, test cases"

* commit '97de064a9a01d2481c47767d7fbb5b7d5482a3aa':
  Runtime resource overlay, iteration 2, test cases
This commit is contained in:
Dianne Hackborn
2014-02-12 22:19:53 +00:00
committed by Android Git Automerger
29 changed files with 1303 additions and 211 deletions

View File

@@ -0,0 +1,12 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := com.android.overlaytest.first_app_overlay
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.overlaytest.first_app_overlay"
android:versionCode="1"
android:versionName="1.0">
<overlay android:targetPackage="com.android.overlaytest" android:priority="1"/>
</manifest>

View File

@@ -0,0 +1 @@
Lorem ipsum: single overlay.

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="matrix_100100">400</integer>
<integer name="matrix_100101">400</integer>
<integer name="matrix_100110">400</integer>
<integer name="matrix_100111">400</integer>
<integer name="matrix_101100">400</integer>
<integer name="matrix_101101">400</integer>
<integer name="matrix_101110">400</integer>
<integer name="matrix_101111">400</integer>
<integer name="matrix_110100">400</integer>
<integer name="matrix_110101">400</integer>
<integer name="matrix_110110">400</integer>
<integer name="matrix_110111">400</integer>
<integer name="matrix_111100">400</integer>
<integer name="matrix_111101">400</integer>
<integer name="matrix_111110">400</integer>
<integer name="matrix_111111">400</integer>
</resources>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="str">single</string>
<string name="str2">single</string>
<integer name="matrix_101000">300</integer>
<integer name="matrix_101001">300</integer>
<integer name="matrix_101010">300</integer>
<integer name="matrix_101011">300</integer>
<integer name="matrix_101100">300</integer>
<integer name="matrix_101101">300</integer>
<integer name="matrix_101110">300</integer>
<integer name="matrix_101111">300</integer>
<integer name="matrix_111000">300</integer>
<integer name="matrix_111001">300</integer>
<integer name="matrix_111010">300</integer>
<integer name="matrix_111011">300</integer>
<integer name="matrix_111100">300</integer>
<integer name="matrix_111101">300</integer>
<integer name="matrix_111110">300</integer>
<integer name="matrix_111111">300</integer>
<bool name="usually_false">true</bool>
<integer-array name="fibonacci">
<item>21</item>
<item>13</item>
<item>8</item>
<item>5</item>
<item>3</item>
<item>2</item>
<item>1</item>
<item>1</item>
</integer-array>
<!-- The following integer does not exist in the original package. Idmap
generation should therefore ignore it. -->
<integer name="integer_not_in_original_package">0</integer>
</resources>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<integer value="1"/>

View File

@@ -0,0 +1,12 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := com.android.overlaytest.second_app_overlay
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.overlaytest.second_app_overlay"
android:versionCode="1"
android:versionName="1.0">
<overlay android:targetPackage="com.android.overlaytest" android:priority="2"/>
</manifest>

View File

@@ -0,0 +1 @@
Lorem ipsum: multiple overlays.

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="matrix_100001">600</integer>
<integer name="matrix_100011">600</integer>
<integer name="matrix_100101">600</integer>
<integer name="matrix_100111">600</integer>
<integer name="matrix_101001">600</integer>
<integer name="matrix_101011">600</integer>
<integer name="matrix_101101">600</integer>
<integer name="matrix_101111">600</integer>
<integer name="matrix_110001">600</integer>
<integer name="matrix_110011">600</integer>
<integer name="matrix_110101">600</integer>
<integer name="matrix_110111">600</integer>
<integer name="matrix_111001">600</integer>
<integer name="matrix_111011">600</integer>
<integer name="matrix_111101">600</integer>
<integer name="matrix_111111">600</integer>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="str">multiple</string>
<integer name="matrix_100010">500</integer>
<integer name="matrix_100011">500</integer>
<integer name="matrix_100110">500</integer>
<integer name="matrix_100111">500</integer>
<integer name="matrix_101010">500</integer>
<integer name="matrix_101011">500</integer>
<integer name="matrix_101110">500</integer>
<integer name="matrix_101111">500</integer>
<integer name="matrix_110010">500</integer>
<integer name="matrix_110011">500</integer>
<integer name="matrix_110110">500</integer>
<integer name="matrix_110111">500</integer>
<integer name="matrix_111010">500</integer>
<integer name="matrix_111011">500</integer>
<integer name="matrix_111110">500</integer>
<integer name="matrix_111111">500</integer>
<bool name="usually_false">false</bool>
</resources>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<integer value="2"/>

View File

@@ -5,6 +5,10 @@ LOCAL_MODULE_TAGS := tests
LOCAL_PACKAGE_NAME := OverlayTest
LOCAL_DEX_PREOPT := false
LOCAL_MODULE_PATH := $(TARGET_OUT)/app
LOCAL_SRC_FILES := $(call all-java-files-under, src)
include $(BUILD_PACKAGE)

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

View File

@@ -0,0 +1 @@
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="matrix_110000">200</integer>
<integer name="matrix_110001">200</integer>
<integer name="matrix_110010">200</integer>
<integer name="matrix_110011">200</integer>
<integer name="matrix_110100">200</integer>
<integer name="matrix_110101">200</integer>
<integer name="matrix_110110">200</integer>
<integer name="matrix_110111">200</integer>
<integer name="matrix_111000">200</integer>
<integer name="matrix_111001">200</integer>
<integer name="matrix_111010">200</integer>
<integer name="matrix_111011">200</integer>
<integer name="matrix_111100">200</integer>
<integer name="matrix_111101">200</integer>
<integer name="matrix_111110">200</integer>
<integer name="matrix_111111">200</integer>
</resources>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="str">none</string>
<string name="str2">none</string>
<integer name="matrix_100000">100</integer>
<integer name="matrix_100001">100</integer>
<integer name="matrix_100010">100</integer>
<integer name="matrix_100011">100</integer>
<integer name="matrix_100100">100</integer>
<integer name="matrix_100101">100</integer>
<integer name="matrix_100110">100</integer>
<integer name="matrix_100111">100</integer>
<integer name="matrix_101000">100</integer>
<integer name="matrix_101001">100</integer>
<integer name="matrix_101010">100</integer>
<integer name="matrix_101011">100</integer>
<integer name="matrix_101100">100</integer>
<integer name="matrix_101101">100</integer>
<integer name="matrix_101110">100</integer>
<integer name="matrix_101111">100</integer>
<integer name="matrix_110000">100</integer>
<integer name="matrix_110001">100</integer>
<integer name="matrix_110010">100</integer>
<integer name="matrix_110011">100</integer>
<integer name="matrix_110100">100</integer>
<integer name="matrix_110101">100</integer>
<integer name="matrix_110110">100</integer>
<integer name="matrix_110111">100</integer>
<integer name="matrix_111000">100</integer>
<integer name="matrix_111001">100</integer>
<integer name="matrix_111010">100</integer>
<integer name="matrix_111011">100</integer>
<integer name="matrix_111100">100</integer>
<integer name="matrix_111101">100</integer>
<integer name="matrix_111110">100</integer>
<integer name="matrix_111111">100</integer>
<bool name="usually_false">false</bool>
<bool name="always_true">true</bool>
<integer-array name="fibonacci">
<item>1</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>5</item>
<item>8</item>
<item>13</item>
<item>21</item>
</integer-array>
<integer-array name="prime_numbers">
<item>2</item>
<item>3</item>
<item>5</item>
<item>7</item>
<item>11</item>
<item>13</item>
<item>17</item>
<item>19</item>
</integer-array>
</resources>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<integer value="0"/>

View File

@@ -2,13 +2,21 @@ package com.android.overlaytest;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.Xml;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
public abstract class OverlayBaseTest extends AndroidTestCase {
private Resources mResources;
protected boolean mWithOverlay; // will be set by subclasses
protected int mMode; // will be set by subclasses
static final protected int MODE_NO_OVERLAY = 0;
static final protected int MODE_SINGLE_OVERLAY = 1;
static final protected int MODE_MULTIPLE_OVERLAYS = 2;
protected void setUp() {
mResources = getContext().getResources();
@@ -36,20 +44,82 @@ public abstract class OverlayBaseTest extends AndroidTestCase {
mResources.updateConfiguration(config, mResources.getDisplayMetrics());
}
private void assertResource(int resId, boolean ewo, boolean ew) throws Throwable {
boolean expected = mWithOverlay ? ew : ewo;
private boolean getExpected(boolean no, boolean so, boolean mo) {
switch (mMode) {
case MODE_NO_OVERLAY:
return no;
case MODE_SINGLE_OVERLAY:
return so;
case MODE_MULTIPLE_OVERLAYS:
return mo;
default:
fail("Unknown mode!");
return no;
}
}
private String getExpected(String no, String so, String mo) {
switch (mMode) {
case MODE_NO_OVERLAY:
return no;
case MODE_SINGLE_OVERLAY:
return so;
case MODE_MULTIPLE_OVERLAYS:
return mo;
default:
fail("Unknown mode!");
return no;
}
}
private int getExpected(int no, int so, int mo) {
switch (mMode) {
case MODE_NO_OVERLAY:
return no;
case MODE_SINGLE_OVERLAY:
return so;
case MODE_MULTIPLE_OVERLAYS:
return mo;
default:
fail("Unknown mode!");
return no;
}
}
private int[] getExpected(int[] no, int[] so, int[] mo) {
switch (mMode) {
case MODE_NO_OVERLAY:
return no;
case MODE_SINGLE_OVERLAY:
return so;
case MODE_MULTIPLE_OVERLAYS:
return mo;
default:
fail("Unknown mode!");
return no;
}
}
private void assertResource(int resId, boolean no, boolean so, boolean mo) throws Throwable {
boolean expected = getExpected(no, so, mo);
boolean actual = mResources.getBoolean(resId);
assertEquals(expected, actual);
}
private void assertResource(int resId, String ewo, String ew) throws Throwable {
String expected = mWithOverlay ? ew : ewo;
private void assertResource(int resId, int no, int so, int mo) throws Throwable {
int expected = getExpected(no, so, mo);
int actual = mResources.getInteger(resId);
assertEquals(expected, actual);
}
private void assertResource(int resId, String no, String so, String mo) throws Throwable {
String expected = getExpected(no, so, mo);
String actual = mResources.getString(resId);
assertEquals(expected, actual);
}
private void assertResource(int resId, int[] ewo, int[] ew) throws Throwable {
int[] expected = mWithOverlay ? ew : ewo;
private void assertResource(int resId, int[] no, int[] so, int[] mo) throws Throwable {
int[] expected = getExpected(no, so, mo);
int[] actual = mResources.getIntArray(resId);
assertEquals("length:", expected.length, actual.length);
for (int i = 0; i < actual.length; ++i) {
@@ -57,62 +127,334 @@ public abstract class OverlayBaseTest extends AndroidTestCase {
}
}
public void testFrameworkBooleanOverlay() throws Throwable {
// config_annoy_dianne has the value:
// - true when no overlay exists (MODE_NO_OVERLAY)
// - false when a single overlay exists (MODE_SINGLE_OVERLAY)
// - false when multiple overlays exists (MODE_MULTIPLE_OVERLAYS)
final int resId = com.android.internal.R.bool.config_annoy_dianne;
assertResource(resId, true, false, false);
}
public void testBooleanOverlay() throws Throwable {
// config_automatic_brightness_available has overlay (default config)
final int resId = com.android.internal.R.bool.config_automatic_brightness_available;
assertResource(resId, false, true);
// usually_false has the value:
// - false when no overlay exists (MODE_NO_OVERLAY)
// - true when a single overlay exists (MODE_SINGLE_OVERLAY)
// - false when multiple overlays exists (MODE_MULTIPLE_OVERLAYS)
final int resId = R.bool.usually_false;
assertResource(resId, false, true, false);
}
public void testBoolean() throws Throwable {
// config_annoy_dianne has no overlay
final int resId = com.android.internal.R.bool.config_annoy_dianne;
assertResource(resId, true, true);
}
public void testStringOverlay() throws Throwable {
// phoneTypeCar has an overlay (default config), which shouldn't shadow
// the Swedish translation
final int resId = com.android.internal.R.string.phoneTypeCar;
setLocale("sv_SE");
assertResource(resId, "Bil", "Bil");
}
public void testStringSwedishOverlay() throws Throwable {
// phoneTypeWork has overlay (no default config, only for lang=sv)
final int resId = com.android.internal.R.string.phoneTypeWork;
setLocale("en_US");
assertResource(resId, "Work", "Work");
setLocale("sv_SE");
assertResource(resId, "Arbete", "Jobb");
}
public void testString() throws Throwable {
// phoneTypeHome has no overlay
final int resId = com.android.internal.R.string.phoneTypeHome;
setLocale("en_US");
assertResource(resId, "Home", "Home");
setLocale("sv_SE");
assertResource(resId, "Hem", "Hem");
// always_true has no overlay
final int resId = R.bool.always_true;
assertResource(resId, true, true, true);
}
public void testIntegerArrayOverlay() throws Throwable {
// config_scrollBarrierVibePattern has overlay (default config)
final int resId = com.android.internal.R.array.config_scrollBarrierVibePattern;
assertResource(resId, new int[]{0, 15, 10, 10}, new int[]{100, 200, 300});
// fibonacci has values:
// - eight first values of Fibonacci sequence, when no overlay exists (MODE_NO_OVERLAY)
// - eight first values of Fibonacci sequence (reversed), for single and multiple overlays
// (MODE_SINGLE_OVERLAY, MODE_MULTIPLE_OVERLAYS)
final int resId = R.array.fibonacci;
assertResource(resId,
new int[]{1, 1, 2, 3, 5, 8, 13, 21},
new int[]{21, 13, 8, 5, 3, 2, 1, 1},
new int[]{21, 13, 8, 5, 3, 2, 1, 1});
}
public void testIntegerArray() throws Throwable {
// config_virtualKeyVibePattern has no overlay
final int resId = com.android.internal.R.array.config_virtualKeyVibePattern;
final int[] expected = {0, 10, 20, 30};
assertResource(resId, expected, expected);
// prime_numbers has no overlay
final int resId = R.array.prime_numbers;
final int[] expected = {2, 3, 5, 7, 11, 13, 17, 19};
assertResource(resId, expected, expected, expected);
}
public void testAsset() throws Throwable {
// drawable/default_background.jpg has overlay (default config)
final int resId = com.android.internal.R.drawable.default_wallpaper;
public void testDrawable() throws Throwable {
// drawable-nodpi/drawable has overlay (default config)
final int resId = R.drawable.drawable;
int actual = calculateRawResourceChecksum(resId);
int expected = mWithOverlay ? 0x000051da : 0x0014ebce;
int expected = 0;
switch (mMode) {
case MODE_NO_OVERLAY:
expected = 0x00005665;
break;
case MODE_SINGLE_OVERLAY:
case MODE_MULTIPLE_OVERLAYS:
expected = 0x000051da;
break;
default:
fail("Unknown mode " + mMode);
}
assertEquals(expected, actual);
}
public void testAppString() throws Throwable {
final int resId = R.string.str;
assertResource(resId, "none", "single", "multiple");
}
public void testApp2() throws Throwable {
final int resId = R.string.str2; // only in base package and first app overlay
assertResource(resId, "none", "single", "single");
}
public void testAppXml() throws Throwable {
int expected = getExpected(0, 1, 2);
int actual = -1;
XmlResourceParser parser = mResources.getXml(R.xml.integer);
int type = parser.getEventType();
while (type != XmlResourceParser.END_DOCUMENT && actual == -1) {
if (type == XmlResourceParser.START_TAG && "integer".equals(parser.getName())) {
AttributeSet as = Xml.asAttributeSet(parser);
actual = as.getAttributeIntValue(null, "value", -1);
}
type = parser.next();
}
parser.close();
assertEquals(expected, actual);
}
public void testAppRaw() throws Throwable {
final int resId = R.raw.lorem_ipsum;
InputStream input = null;
BufferedReader reader = null;
String actual = "";
try {
input = mResources.openRawResource(resId);
reader = new BufferedReader(new InputStreamReader(input));
actual = reader.readLine();
} finally {
reader.close();
input.close();
}
final String no = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " +
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip " +
"ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " +
"esse cillum dolore eu fugiat nulla pariatur. " +
"Excepteur sint occaecat cupidatat non proident, " +
"sunt in culpa qui officia deserunt mollit anim id est laborum.";
final String so = "Lorem ipsum: single overlay.";
final String mo = "Lorem ipsum: multiple overlays.";
assertEquals(getExpected(no, so, mo), actual);
}
/*
* testMatrix* tests
*
* The naming convention textMatrixABCDEF refers to in which packages and
* which configurations a resource is defined (1 if the resource is
* defined). If defined, a slot is always given the same value.
*
* SLOT PACKAGE CONFIGURATION VALUE
* A target package (default) 100
* B target package -sv 200
* C OverlayAppFirst (default) 300
* D OverlayAppFirst -sv 400
* E OverlayAppSecond (default) 500
* F OverlayAppSecond -sv 600
*
* Example: in testMatrix101110, the base package defines the
* R.integer.matrix101110 resource for the default configuration (value
* 100), OverlayAppFirst defines it for both default and Swedish
* configurations (values 300 and 400, respectively), and OverlayAppSecond
* defines it for the default configuration (value 500). If both overlays
* are loaded, the expected value after setting the language to Swedish is
* 400.
*/
public void testMatrix100000() throws Throwable {
final int resId = R.integer.matrix_100000;
setLocale("sv_SE");
assertResource(resId, 100, 100, 100);
}
public void testMatrix100001() throws Throwable {
final int resId = R.integer.matrix_100001;
setLocale("sv_SE");
assertResource(resId, 100, 100, 600);
}
public void testMatrix100010() throws Throwable {
final int resId = R.integer.matrix_100010;
setLocale("sv_SE");
assertResource(resId, 100, 100, 500);
}
public void testMatrix100011() throws Throwable {
final int resId = R.integer.matrix_100011;
setLocale("sv_SE");
assertResource(resId, 100, 100, 600);
}
public void testMatrix100100() throws Throwable {
final int resId = R.integer.matrix_100100;
setLocale("sv_SE");
assertResource(resId, 100, 400, 400);
}
public void testMatrix100101() throws Throwable {
final int resId = R.integer.matrix_100101;
setLocale("sv_SE");
assertResource(resId, 100, 400, 600);
}
public void testMatrix100110() throws Throwable {
final int resId = R.integer.matrix_100110;
setLocale("sv_SE");
assertResource(resId, 100, 400, 400);
}
public void testMatrix100111() throws Throwable {
final int resId = R.integer.matrix_100111;
setLocale("sv_SE");
assertResource(resId, 100, 400, 600);
}
public void testMatrix101000() throws Throwable {
final int resId = R.integer.matrix_101000;
setLocale("sv_SE");
assertResource(resId, 100, 300, 300);
}
public void testMatrix101001() throws Throwable {
final int resId = R.integer.matrix_101001;
setLocale("sv_SE");
assertResource(resId, 100, 300, 600);
}
public void testMatrix101010() throws Throwable {
final int resId = R.integer.matrix_101010;
setLocale("sv_SE");
assertResource(resId, 100, 300, 500);
}
public void testMatrix101011() throws Throwable {
final int resId = R.integer.matrix_101011;
setLocale("sv_SE");
assertResource(resId, 100, 300, 600);
}
public void testMatrix101100() throws Throwable {
final int resId = R.integer.matrix_101100;
setLocale("sv_SE");
assertResource(resId, 100, 400, 400);
}
public void testMatrix101101() throws Throwable {
final int resId = R.integer.matrix_101101;
setLocale("sv_SE");
assertResource(resId, 100, 400, 600);
}
public void testMatrix101110() throws Throwable {
final int resId = R.integer.matrix_101110;
setLocale("sv_SE");
assertResource(resId, 100, 400, 400);
}
public void testMatrix101111() throws Throwable {
final int resId = R.integer.matrix_101111;
setLocale("sv_SE");
assertResource(resId, 100, 400, 600);
}
public void testMatrix110000() throws Throwable {
final int resId = R.integer.matrix_110000;
setLocale("sv_SE");
assertResource(resId, 200, 200, 200);
}
public void testMatrix110001() throws Throwable {
final int resId = R.integer.matrix_110001;
setLocale("sv_SE");
assertResource(resId, 200, 200, 600);
}
public void testMatrix110010() throws Throwable {
final int resId = R.integer.matrix_110010;
setLocale("sv_SE");
assertResource(resId, 200, 200, 200);
}
public void testMatrix110011() throws Throwable {
final int resId = R.integer.matrix_110011;
setLocale("sv_SE");
assertResource(resId, 200, 200, 600);
}
public void testMatrix110100() throws Throwable {
final int resId = R.integer.matrix_110100;
setLocale("sv_SE");
assertResource(resId, 200, 400, 400);
}
public void testMatrix110101() throws Throwable {
final int resId = R.integer.matrix_110101;
setLocale("sv_SE");
assertResource(resId, 200, 400, 600);
}
public void testMatrix110110() throws Throwable {
final int resId = R.integer.matrix_110110;
setLocale("sv_SE");
assertResource(resId, 200, 400, 400);
}
public void testMatrix110111() throws Throwable {
final int resId = R.integer.matrix_110111;
setLocale("sv_SE");
assertResource(resId, 200, 400, 600);
}
public void testMatrix111000() throws Throwable {
final int resId = R.integer.matrix_111000;
setLocale("sv_SE");
assertResource(resId, 200, 200, 200);
}
public void testMatrix111001() throws Throwable {
final int resId = R.integer.matrix_111001;
setLocale("sv_SE");
assertResource(resId, 200, 200, 600);
}
public void testMatrix111010() throws Throwable {
final int resId = R.integer.matrix_111010;
setLocale("sv_SE");
assertResource(resId, 200, 200, 200);
}
public void testMatrix111011() throws Throwable {
final int resId = R.integer.matrix_111011;
setLocale("sv_SE");
assertResource(resId, 200, 200, 600);
}
public void testMatrix111100() throws Throwable {
final int resId = R.integer.matrix_111100;
setLocale("sv_SE");
assertResource(resId, 200, 400, 400);
}
public void testMatrix111101() throws Throwable {
final int resId = R.integer.matrix_111101;
setLocale("sv_SE");
assertResource(resId, 200, 400, 600);
}
public void testMatrix111110() throws Throwable {
final int resId = R.integer.matrix_111110;
setLocale("sv_SE");
assertResource(resId, 200, 400, 400);
}
public void testMatrix111111() throws Throwable {
final int resId = R.integer.matrix_111111;
setLocale("sv_SE");
assertResource(resId, 200, 400, 600);
}
}

View File

@@ -0,0 +1,7 @@
package com.android.overlaytest;
public class WithMultipleOverlaysTest extends OverlayBaseTest {
public WithMultipleOverlaysTest() {
mMode = MODE_MULTIPLE_OVERLAYS;
}
}

View File

@@ -2,6 +2,6 @@ package com.android.overlaytest;
public class WithOverlayTest extends OverlayBaseTest {
public WithOverlayTest() {
mWithOverlay = true;
mMode = MODE_SINGLE_OVERLAY;
}
}

View File

@@ -2,6 +2,6 @@ package com.android.overlaytest;
public class WithoutOverlayTest extends OverlayBaseTest {
public WithoutOverlayTest() {
mWithOverlay = false;
mMode = MODE_NO_OVERLAY;
}
}

View File

@@ -2,5 +2,5 @@
package="com.android.overlaytest.overlay"
android:versionCode="1"
android:versionName="1.0">
<overlay-package android:name="android"/>
<overlay android:targetPackage="android" android:priority="1"/>
</manifest>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="phoneTypeWork">Jobb</string>
</resources>

View File

@@ -1,13 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="config_automatic_brightness_available">true</bool>
<string name="phoneTypeCar">Automobile</string>
<integer-array name="config_scrollBarrierVibePattern">
<item>100</item>
<item>200</item>
<item>300</item>
</integer-array>
<!-- The following integer does not exist in the original package. Idmap
generation should therefore ignore it. -->
<integer name="integer_not_in_original_package">0</integer>
<bool name="config_annoy_dianne">false</bool>
</resources>

View File

@@ -1,15 +0,0 @@
Unit tests for runtime resource overlay
=======================================
As of this writing, runtime resource overlay is only triggered for
/system/framework/framework-res.apk. Because of this, installation of
overlay packages require the Android platform be rebooted. However, the
regular unit tests (triggered via development/testrunner/runtest.py)
cannot handle reboots. As a workaround, this directory contains a shell
script which will trigger the tests in a non-standard way.
Once runtime resource overlay may be applied to applications, the tests
in this directory should be moved to core/tests/coretests. Also, by
applying runtime resource overlay to a dedicated test application, the
test cases would not need to assume default values for non-overlaid
resources.

View File

@@ -1,129 +0,0 @@
#!/bin/bash
adb="adb"
if [[ $# -gt 0 ]]; then
adb="adb $*" # for setting -e, -d or -s <serial>
fi
function atexit()
{
local retval=$?
if [[ $retval -eq 0 ]]; then
rm $log
else
echo "There were errors, please check log at $log"
fi
}
log=$(mktemp)
trap "atexit" EXIT
function compile_module()
{
local android_mk="$1"
echo "Compiling .${android_mk:${#PWD}}"
ONE_SHOT_MAKEFILE="$android_mk" make -C "../../../../../" files | tee -a $log
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
exit 1
fi
}
function wait_for_boot_completed()
{
echo "Rebooting device"
$adb wait-for-device logcat -c
$adb wait-for-device logcat | grep -m 1 -e 'PowerManagerService.*bootCompleted' >/dev/null
}
function mkdir_if_needed()
{
local path="$1"
if [[ "${path:0:1}" != "/" ]]; then
echo "mkdir_if_needed: error: path '$path' does not begin with /" | tee -a $log
exit 1
fi
local basename=$(basename "$path")
local dirname=$(dirname "$path")
local t=$($adb shell ls -l $dirname | tr -d '\r' | grep -e "${basename}$" | grep -oe '^.')
case "$t" in
d) # File exists, and is a directory ...
# do nothing
;;
l) # ... (or symbolic link possibly to a directory).
# do nothing
;;
"") # File does not exist.
mkdir_if_needed "$dirname"
$adb shell mkdir "$path"
;;
*) # File exists, but is not a directory.
echo "mkdir_if_needed: file '$path' exists, but is not a directory" | tee -a $log
exit 1
;;
esac
}
function disable_overlay()
{
echo "Disabling overlay"
$adb shell rm /vendor/overlay/framework/framework-res.apk
$adb shell rm /data/resource-cache/vendor@overlay@framework@framework-res.apk@idmap
}
function enable_overlay()
{
echo "Enabling overlay"
mkdir_if_needed "/system/vendor"
mkdir_if_needed "/vendor/overlay/framework"
$adb shell ln -s /data/app/com.android.overlaytest.overlay.apk /vendor/overlay/framework/framework-res.apk
}
function instrument()
{
local class="$1"
echo "Instrumenting $class"
$adb shell am instrument -w -e class $class com.android.overlaytest/android.test.InstrumentationTestRunner | tee -a $log
}
function remount()
{
echo "Remounting file system writable"
$adb remount | tee -a $log
}
function sync()
{
echo "Syncing to device"
$adb sync data | tee -a $log
}
# some commands require write access, remount once and for all
remount
# build and sync
compile_module "$PWD/OverlayTest/Android.mk"
compile_module "$PWD/OverlayTestOverlay/Android.mk"
sync
# instrument test (without overlay)
$adb shell stop
disable_overlay
$adb shell start
wait_for_boot_completed
instrument "com.android.overlaytest.WithoutOverlayTest"
# instrument test (with overlay)
$adb shell stop
enable_overlay
$adb shell start
wait_for_boot_completed
instrument "com.android.overlaytest.WithOverlayTest"
# cleanup
exit $(grep -c -e '^FAILURES' $log)

View File

@@ -0,0 +1,679 @@
#!/usr/bin/python
import hashlib
import optparse
import os
import re
import shlex
import subprocess
import sys
import threading
import time
TASK_COMPILATION = 'compile'
TASK_DISABLE_OVERLAYS = 'disable overlays'
TASK_ENABLE_MULTIPLE_OVERLAYS = 'enable multiple overlays'
TASK_ENABLE_SINGLE_OVERLAY = 'enable single overlay'
TASK_FILE_EXISTS_TEST = 'test (file exists)'
TASK_GREP_IDMAP_TEST = 'test (grep idmap)'
TASK_MD5_TEST = 'test (md5)'
TASK_IDMAP_PATH = 'idmap --path'
TASK_IDMAP_SCAN = 'idmap --scan'
TASK_INSTRUMENTATION = 'instrumentation'
TASK_INSTRUMENTATION_TEST = 'test (instrumentation)'
TASK_MKDIR = 'mkdir'
TASK_PUSH = 'push'
TASK_ROOT = 'root'
TASK_REMOUNT = 'remount'
TASK_RM = 'rm'
TASK_SETUP_IDMAP_PATH = 'setup idmap --path'
TASK_SETUP_IDMAP_SCAN = 'setup idmap --scan'
TASK_START = 'start'
TASK_STOP = 'stop'
adb = 'adb'
def _adb_shell(cmd):
argv = shlex.split(adb + " shell '" + cmd + "; echo $?'")
proc = subprocess.Popen(argv, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
(stdout, stderr) = (stdout.replace('\r', ''), stderr.replace('\r', ''))
tmp = stdout.rsplit('\n', 2)
if len(tmp) == 2:
stdout == ''
returncode = int(tmp[0])
else:
stdout = tmp[0] + '\n'
returncode = int(tmp[1])
return returncode, stdout, stderr
class VerbosePrinter:
class Ticker(threading.Thread):
def _print(self):
s = '\r' + self.text + '[' + '.' * self.i + ' ' * (4 - self.i) + ']'
sys.stdout.write(s)
sys.stdout.flush()
self.i = (self.i + 1) % 5
def __init__(self, cond_var, text):
threading.Thread.__init__(self)
self.text = text
self.setDaemon(True)
self.cond_var = cond_var
self.running = False
self.i = 0
self._print()
self.running = True
def run(self):
self.cond_var.acquire()
while True:
self.cond_var.wait(0.25)
running = self.running
if not running:
break
self._print()
self.cond_var.release()
def stop(self):
self.cond_var.acquire()
self.running = False
self.cond_var.notify_all()
self.cond_var.release()
def _start_ticker(self):
self.ticker = VerbosePrinter.Ticker(self.cond_var, self.text)
self.ticker.start()
def _stop_ticker(self):
self.ticker.stop()
self.ticker.join()
self.ticker = None
def _format_begin(self, type, name):
N = self.width - len(type) - len(' [ ] ')
fmt = '%%s %%-%ds ' % N
return fmt % (type, name)
def __init__(self, use_color):
self.cond_var = threading.Condition()
self.ticker = None
if use_color:
self.color_RED = '\033[1;31m'
self.color_red = '\033[0;31m'
self.color_reset = '\033[0;37m'
else:
self.color_RED = ''
self.color_red = ''
self.color_reset = ''
argv = shlex.split('stty size') # get terminal width
proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
if proc.returncode == 0:
(h, w) = stdout.split()
self.width = int(w)
else:
self.width = 72 # conservative guesstimate
def begin(self, type, name):
self.text = self._format_begin(type, name)
sys.stdout.write(self.text + '[ ]')
sys.stdout.flush()
self._start_ticker()
def end_pass(self, type, name):
self._stop_ticker()
sys.stdout.write('\r' + self.text + '[ OK ]\n')
sys.stdout.flush()
def end_fail(self, type, name, msg):
self._stop_ticker()
sys.stdout.write('\r' + self.color_RED + self.text + '[FAIL]\n')
sys.stdout.write(self.color_red)
sys.stdout.write(msg)
sys.stdout.write(self.color_reset)
sys.stdout.flush()
class QuietPrinter:
def begin(self, type, name):
pass
def end_pass(self, type, name):
sys.stdout.write('PASS ' + type + ' ' + name + '\n')
sys.stdout.flush()
def end_fail(self, type, name, msg):
sys.stdout.write('FAIL ' + type + ' ' + name + '\n')
sys.stdout.flush()
class CompilationTask:
def __init__(self, makefile):
self.makefile = makefile
def get_type(self):
return TASK_COMPILATION
def get_name(self):
return self.makefile
def execute(self):
os.putenv('ONE_SHOT_MAKEFILE', os.getcwd() + "/" + self.makefile)
argv = shlex.split('make -C "../../../../../" files')
proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
return proc.returncode, stdout, stderr
class InstrumentationTask:
def __init__(self, instrumentation_class):
self.instrumentation_class = instrumentation_class
def get_type(self):
return TASK_INSTRUMENTATION
def get_name(self):
return self.instrumentation_class
def execute(self):
return _adb_shell('am instrument -r -w -e class %s com.android.overlaytest/android.test.InstrumentationTestRunner' % self.instrumentation_class)
class PushTask:
def __init__(self, src, dest):
self.src = src
self.dest = dest
def get_type(self):
return TASK_PUSH
def get_name(self):
return "%s -> %s" % (self.src, self.dest)
def execute(self):
src = os.getenv('OUT') + "/" + self.src
argv = shlex.split(adb + ' push %s %s' % (src, self.dest))
proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
return proc.returncode, stdout, stderr
class MkdirTask:
def __init__(self, path):
self.path = path
def get_type(self):
return TASK_MKDIR
def get_name(self):
return self.path
def execute(self):
return _adb_shell('mkdir -p %s' % self.path)
class RmTask:
def __init__(self, path):
self.path = path
def get_type(self):
return TASK_RM
def get_name(self):
return self.path
def execute(self):
returncode, stdout, stderr = _adb_shell('ls %s' % self.path)
if returncode != 0 and stdout.endswith(': No such file or directory\n'):
return 0, "", ""
return _adb_shell('rm -r %s' % self.path)
class IdmapPathTask:
def __init__(self, path_target_apk, path_overlay_apk, path_idmap):
self.path_target_apk = path_target_apk
self.path_overlay_apk = path_overlay_apk
self.path_idmap = path_idmap
def get_type(self):
return TASK_IDMAP_PATH
def get_name(self):
return self.path_idmap
def execute(self):
return _adb_shell('su system idmap --path "%s" "%s" "%s"' % (self.path_target_apk, self.path_overlay_apk, self.path_idmap))
class IdmapScanTask:
def __init__(self, overlay_dir, target_pkg_name, target_pkg, idmap_dir, symlink_dir):
self.overlay_dir = overlay_dir
self.target_pkg_name = target_pkg_name
self.target_pkg = target_pkg
self.idmap_dir = idmap_dir
self.symlink_dir = symlink_dir
def get_type(self):
return TASK_IDMAP_SCAN
def get_name(self):
return self.target_pkg_name
def execute(self):
return _adb_shell('su system idmap --scan "%s" "%s" "%s" "%s"' % (self.overlay_dir, self.target_pkg_name, self.target_pkg, self.idmap_dir))
class FileExistsTest:
def __init__(self, path):
self.path = path
def get_type(self):
return TASK_FILE_EXISTS_TEST
def get_name(self):
return self.path
def execute(self):
return _adb_shell('ls %s' % self.path)
class GrepIdmapTest:
def __init__(self, path_idmap, pattern, expected_n):
self.path_idmap = path_idmap
self.pattern = pattern
self.expected_n = expected_n
def get_type(self):
return TASK_GREP_IDMAP_TEST
def get_name(self):
return self.pattern
def execute(self):
returncode, stdout, stderr = _adb_shell('idmap --inspect %s' % self.path_idmap)
if returncode != 0:
return returncode, stdout, stderr
all_matches = re.findall('\s' + self.pattern + '$', stdout, flags=re.MULTILINE)
if len(all_matches) != self.expected_n:
return 1, 'pattern=%s idmap=%s expected=%d found=%d\n' % (self.pattern, self.path_idmap, self.expected_n, len(all_matches)), ''
return 0, "", ""
class Md5Test:
def __init__(self, path, expected_content):
self.path = path
self.expected_md5 = hashlib.md5(expected_content).hexdigest()
def get_type(self):
return TASK_MD5_TEST
def get_name(self):
return self.path
def execute(self):
returncode, stdout, stderr = _adb_shell('md5 %s' % self.path)
if returncode != 0:
return returncode, stdout, stderr
actual_md5 = stdout.split()[0]
if actual_md5 != self.expected_md5:
return 1, 'expected %s, got %s\n' % (self.expected_md5, actual_md5), ''
return 0, "", ""
class StartTask:
def get_type(self):
return TASK_START
def get_name(self):
return ""
def execute(self):
(returncode, stdout, stderr) = _adb_shell('start')
if returncode != 0:
return returncode, stdout, stderr
while True:
(returncode, stdout, stderr) = _adb_shell('getprop dev.bootcomplete')
if returncode != 0:
return returncode, stdout, stderr
if stdout.strip() == "1":
break
time.sleep(0.5)
return 0, "", ""
class StopTask:
def get_type(self):
return TASK_STOP
def get_name(self):
return ""
def execute(self):
(returncode, stdout, stderr) = _adb_shell('stop')
if returncode != 0:
return returncode, stdout, stderr
return _adb_shell('setprop dev.bootcomplete 0')
class RootTask:
def get_type(self):
return TASK_ROOT
def get_name(self):
return ""
def execute(self):
(returncode, stdout, stderr) = _adb_shell('getprop service.adb.root 0')
if returncode != 0:
return returncode, stdout, stderr
if stdout.strip() == '1': # already root
return 0, "", ""
argv = shlex.split(adb + ' root')
proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
return proc.returncode, stdout, stderr
argv = shlex.split(adb + ' wait-for-device')
proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
return proc.returncode, stdout, stderr
class RemountTask:
def get_type(self):
return TASK_REMOUNT
def get_name(self):
return ""
def execute(self):
argv = shlex.split(adb + ' remount')
proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
# adb remount returns 0 even if the operation failed, so check stdout
if stdout.startswith('remount failed:'):
return 1, stdout, stderr
return proc.returncode, stdout, stderr
class CompoundTask:
def __init__(self, type, tasks):
self.type = type
self.tasks = tasks
def get_type(self):
return self.type
def get_name(self):
return ""
def execute(self):
for t in self.tasks:
(returncode, stdout, stderr) = t.execute()
if returncode != 0:
return returncode, stdout, stderr
return 0, "", ""
def _create_disable_overlays_task():
tasks = [
RmTask("/vendor/overlay/framework_a.apk"),
RmTask("/vendor/overlay/framework_b.apk"),
RmTask("/data/resource-cache/vendor@overlay@framework_a.apk@idmap"),
RmTask("/data/resource-cache/vendor@overlay@framework_b.apk@idmap"),
RmTask("/vendor/overlay/app_a.apk"),
RmTask("/vendor/overlay/app_b.apk"),
RmTask("/data/resource-cache/vendor@overlay@app_a.apk@idmap"),
RmTask("/data/resource-cache/vendor@overlay@app_b.apk@idmap"),
]
return CompoundTask(TASK_DISABLE_OVERLAYS, tasks)
def _create_enable_single_overlay_task():
tasks = [
_create_disable_overlays_task(),
MkdirTask('/system/vendor'),
MkdirTask('/vendor/overlay'),
PushTask('/data/app/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_a.apk'),
PushTask('/data/app/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
]
return CompoundTask(TASK_ENABLE_SINGLE_OVERLAY, tasks)
def _create_enable_multiple_overlays_task():
tasks = [
_create_disable_overlays_task(),
MkdirTask('/system/vendor'),
MkdirTask('/vendor/overlay'),
PushTask('/data/app/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_b.apk'),
PushTask('/data/app/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
PushTask('/data/app/com.android.overlaytest.second_app_overlay.apk', '/vendor/overlay/app_b.apk'),
]
return CompoundTask(TASK_ENABLE_MULTIPLE_OVERLAYS, tasks)
def _create_setup_idmap_path_task(idmaps, symlinks):
tasks = [
_create_enable_single_overlay_task(),
RmTask(symlinks),
RmTask(idmaps),
MkdirTask(idmaps),
MkdirTask(symlinks),
]
return CompoundTask(TASK_SETUP_IDMAP_PATH, tasks)
def _create_setup_idmap_scan_task(idmaps, symlinks):
tasks = [
_create_enable_single_overlay_task(),
RmTask(symlinks),
RmTask(idmaps),
MkdirTask(idmaps),
MkdirTask(symlinks),
_create_enable_multiple_overlays_task(),
]
return CompoundTask(TASK_SETUP_IDMAP_SCAN, tasks)
def _handle_instrumentation_task_output(stdout, printer):
regex_status_code = re.compile(r'^INSTRUMENTATION_STATUS_CODE: -?(\d+)')
regex_name = re.compile(r'^INSTRUMENTATION_STATUS: test=(.*)')
regex_begin_stack = re.compile(r'^INSTRUMENTATION_STATUS: stack=(.*)')
regex_end_stack = re.compile(r'^$')
failed_tests = 0
current_test = None
current_stack = []
mode_stack = False
for line in stdout.split("\n"):
line = line.rstrip() # strip \r from adb output
m = regex_status_code.match(line)
if m:
c = int(m.group(1))
if c == 1:
printer.begin(TASK_INSTRUMENTATION_TEST, current_test)
elif c == 0:
printer.end_pass(TASK_INSTRUMENTATION_TEST, current_test)
else:
failed_tests += 1
current_stack.append("\n")
msg = "\n".join(current_stack)
printer.end_fail(TASK_INSTRUMENTATION_TEST, current_test, msg.rstrip() + '\n')
continue
m = regex_name.match(line)
if m:
current_test = m.group(1)
continue
m = regex_begin_stack.match(line)
if m:
mode_stack = True
current_stack = []
current_stack.append(" " + m.group(1))
continue
m = regex_end_stack.match(line)
if m:
mode_stack = False
continue
if mode_stack:
current_stack.append(" " + line.strip())
return failed_tests
def _set_adb_device(option, opt, value, parser):
global adb
if opt == '-d' or opt == '--device':
adb = 'adb -d'
if opt == '-e' or opt == '--emulator':
adb = 'adb -e'
if opt == '-s' or opt == '--serial':
adb = 'adb -s ' + value
def _create_opt_parser():
parser = optparse.OptionParser()
parser.add_option('-d', '--device', action='callback', callback=_set_adb_device,
help='pass -d to adb')
parser.add_option('-e', '--emulator', action='callback', callback=_set_adb_device,
help='pass -e to adb')
parser.add_option('-s', '--serial', type="str", action='callback', callback=_set_adb_device,
help='pass -s <serical> to adb')
parser.add_option('-C', '--no-color', action='store_false',
dest='use_color', default=True,
help='disable color escape sequences in output')
parser.add_option('-q', '--quiet', action='store_true',
dest='quiet_mode', default=False,
help='quiet mode, output only results')
parser.add_option('-b', '--no-build', action='store_false',
dest='do_build', default=True,
help='do not rebuild test projects')
parser.add_option('-k', '--continue', action='store_true',
dest='do_continue', default=False,
help='do not rebuild test projects')
parser.add_option('-i', '--test-idmap', action='store_true',
dest='test_idmap', default=False,
help='run tests for single overlay')
parser.add_option('-0', '--test-no-overlay', action='store_true',
dest='test_no_overlay', default=False,
help='run tests without any overlay')
parser.add_option('-1', '--test-single-overlay', action='store_true',
dest='test_single_overlay', default=False,
help='run tests for single overlay')
parser.add_option('-2', '--test-multiple-overlays', action='store_true',
dest='test_multiple_overlays', default=False,
help='run tests for multiple overlays')
return parser
if __name__ == '__main__':
opt_parser = _create_opt_parser()
opts, args = opt_parser.parse_args(sys.argv[1:])
if not opts.test_idmap and not opts.test_no_overlay and not opts.test_single_overlay and not opts.test_multiple_overlays:
opts.test_idmap = True
opts.test_no_overlay = True
opts.test_single_overlay = True
opts.test_multiple_overlays = True
if len(args) > 0:
opt_parser.error("unexpected arguments: %s" % " ".join(args))
# will never reach this: opt_parser.error will call sys.exit
if opts.quiet_mode:
printer = QuietPrinter()
else:
printer = VerbosePrinter(opts.use_color)
tasks = []
# must be in the same directory as this script for compilation tasks to work
script = sys.argv[0]
dirname = os.path.dirname(script)
wd = os.path.realpath(dirname)
os.chdir(wd)
# build test cases
if opts.do_build:
tasks.append(CompilationTask('OverlayTest/Android.mk'))
tasks.append(CompilationTask('OverlayTestOverlay/Android.mk'))
tasks.append(CompilationTask('OverlayAppFirst/Android.mk'))
tasks.append(CompilationTask('OverlayAppSecond/Android.mk'))
# remount filesystem, install test project
tasks.append(RootTask())
tasks.append(RemountTask())
tasks.append(PushTask('/system/app/OverlayTest.apk', '/system/app/OverlayTest.apk'))
# test idmap
if opts.test_idmap:
idmaps='/data/local/tmp/idmaps'
symlinks='/data/local/tmp/symlinks'
# idmap --path
tasks.append(StopTask())
tasks.append(_create_setup_idmap_path_task(idmaps, symlinks))
tasks.append(StartTask())
tasks.append(IdmapPathTask('/vendor/overlay/framework_a.apk', '/system/framework/framework-res.apk', idmaps + '/a.idmap'))
tasks.append(FileExistsTest(idmaps + '/a.idmap'))
tasks.append(GrepIdmapTest(idmaps + '/a.idmap', 'bool/config_annoy_dianne', 1))
# idmap --scan
idmap = idmaps + '/vendor@overlay@framework_b.apk@idmap'
tasks.append(StopTask())
tasks.append(_create_setup_idmap_scan_task(idmaps, symlinks))
tasks.append(StartTask())
tasks.append(IdmapScanTask('/vendor/overlay', 'android', '/system/framework/framework-res.apk', idmaps, symlinks))
tasks.append(FileExistsTest(idmap))
tasks.append(GrepIdmapTest(idmap, 'bool/config_annoy_dianne', 1))
# overlays.list
overlays_list_path = '/data/resource-cache/overlays.list'
expected_content = '''\
/vendor/overlay/framework_b.apk /data/resource-cache/vendor@overlay@framework_b.apk@idmap
'''
tasks.append(FileExistsTest(overlays_list_path))
tasks.append(Md5Test(overlays_list_path, expected_content))
# idmap cleanup
tasks.append(RmTask(symlinks))
tasks.append(RmTask(idmaps))
# test no overlay
if opts.test_no_overlay:
tasks.append(StopTask())
tasks.append(_create_disable_overlays_task())
tasks.append(StartTask())
tasks.append(InstrumentationTask('com.android.overlaytest.WithoutOverlayTest'))
# test single overlay
if opts.test_single_overlay:
tasks.append(StopTask())
tasks.append(_create_enable_single_overlay_task())
tasks.append(StartTask())
tasks.append(InstrumentationTask('com.android.overlaytest.WithOverlayTest'))
# test multiple overlays
if opts.test_multiple_overlays:
tasks.append(StopTask())
tasks.append(_create_enable_multiple_overlays_task())
tasks.append(StartTask())
tasks.append(InstrumentationTask('com.android.overlaytest.WithMultipleOverlaysTest'))
ignored_errors = 0
for t in tasks:
type = t.get_type()
name = t.get_name()
if type == TASK_INSTRUMENTATION:
# InstrumentationTask will run several tests, but we want it
# to appear as if each test was run individually. Calling
# "am instrument" with a single test method is prohibitively
# expensive, so let's instead post-process the output to
# emulate individual calls.
retcode, stdout, stderr = t.execute()
if retcode != 0:
printer.begin(TASK_INSTRUMENTATION, name)
printer.end_fail(TASK_INSTRUMENTATION, name, stderr)
sys.exit(retcode)
retcode = _handle_instrumentation_task_output(stdout, printer)
if retcode != 0:
if not opts.do_continue:
sys.exit(retcode)
else:
ignored_errors += retcode
else:
printer.begin(type, name)
retcode, stdout, stderr = t.execute()
if retcode == 0:
printer.end_pass(type, name)
if retcode != 0:
if len(stderr) == 0:
# hope for output from stdout instead (true for eg adb shell rm)
stderr = stdout
printer.end_fail(type, name, stderr)
if not opts.do_continue:
sys.exit(retcode)
else:
ignored_errors += retcode
sys.exit(ignored_errors)