blob: 96ab977b799c56edf62233c9b8202e11517bb457 [file] [log] [blame]
/*
* Copyright (C) 2018 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.overlaytest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import android.app.UiAutomation;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.support.test.InstrumentationRegistry;
import android.util.AttributeSet;
import android.util.Xml;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
@Ignore
public abstract class OverlayBaseTest {
private Resources mResources;
private final int mMode;
static final int MODE_NO_OVERLAY = 0;
static final int MODE_SINGLE_OVERLAY = 1;
static final int MODE_MULTIPLE_OVERLAYS = 2;
static final String APP_OVERLAY_ONE_PKG = "com.android.overlaytest.app_overlay_one";
static final String APP_OVERLAY_TWO_PKG = "com.android.overlaytest.app_overlay_two";
static final String FRAMEWORK_OVERLAY_PKG = "com.android.overlaytest.framework";
protected OverlayBaseTest(int mode) {
mMode = mode;
}
@Before
public void setUp() {
mResources = InstrumentationRegistry.getContext().getResources();
}
private int calculateRawResourceChecksum(int resId) throws Throwable {
try (InputStream input = mResources.openRawResource(resId)) {
int ch, checksum = 0;
while ((ch = input.read()) != -1) {
checksum = (checksum + ch) % 0xffddbb00;
}
return checksum;
}
}
private void setLocale(Locale locale) {
final LocaleList locales = new LocaleList(locale);
LocaleList.setDefault(locales);
Configuration config = new Configuration();
config.setLocales(locales);
mResources.updateConfiguration(config, mResources.getDisplayMetrics());
}
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, 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[] 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) {
assertEquals("index " + i + ":", actual[i], expected[i]);
}
}
@Test
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);
}
@Test
public void testBooleanOverlay() throws Throwable {
// 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);
}
@Test
public void testBoolean() throws Throwable {
// always_true has no overlay
final int resId = R.bool.always_true;
assertResource(resId, true, true, true);
}
@Test
public void testIntegerArrayOverlay() throws Throwable {
// 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});
}
@Test
public void testIntegerArray() throws Throwable {
// 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);
}
@Test
public void testDrawable() throws Throwable {
// drawable-nodpi/drawable has overlay (default config)
final int resId = R.drawable.drawable;
int actual = calculateRawResourceChecksum(resId);
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);
}
@Test
public void testAppString() throws Throwable {
final int resId = R.string.str;
assertResource(resId, "none", "single", "multiple");
}
@Test
public void testApp2() throws Throwable {
final int resId = R.string.str2; // only in base package and first app overlay
assertResource(resId, "none", "single", "single");
}
@Test
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);
}
@Test
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 {
if (reader != null) {
reader.close();
}
if (input != null) {
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 AppOverlayOne (default) 300
* D AppOverlayOne -sv 400
* E AppOverlayTwo (default) 500
* F AppOverlayTwo -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.
*/
@Test
public void testMatrix100000() throws Throwable {
final int resId = R.integer.matrix_100000;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 100, 100);
}
@Test
public void testMatrix100001() throws Throwable {
final int resId = R.integer.matrix_100001;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 100, 600);
}
@Test
public void testMatrix100010() throws Throwable {
final int resId = R.integer.matrix_100010;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 100, 500);
}
@Test
public void testMatrix100011() throws Throwable {
final int resId = R.integer.matrix_100011;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 100, 600);
}
@Test
public void testMatrix100100() throws Throwable {
final int resId = R.integer.matrix_100100;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 400);
}
@Test
public void testMatrix100101() throws Throwable {
final int resId = R.integer.matrix_100101;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 600);
}
@Test
public void testMatrix100110() throws Throwable {
final int resId = R.integer.matrix_100110;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 400);
}
@Test
public void testMatrix100111() throws Throwable {
final int resId = R.integer.matrix_100111;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 600);
}
@Test
public void testMatrix101000() throws Throwable {
final int resId = R.integer.matrix_101000;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 300, 300);
}
@Test
public void testMatrix101001() throws Throwable {
final int resId = R.integer.matrix_101001;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 300, 600);
}
@Test
public void testMatrix101010() throws Throwable {
final int resId = R.integer.matrix_101010;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 300, 500);
}
@Test
public void testMatrix101011() throws Throwable {
final int resId = R.integer.matrix_101011;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 300, 600);
}
@Test
public void testMatrix101100() throws Throwable {
final int resId = R.integer.matrix_101100;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 400);
}
@Test
public void testMatrix101101() throws Throwable {
final int resId = R.integer.matrix_101101;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 600);
}
@Test
public void testMatrix101110() throws Throwable {
final int resId = R.integer.matrix_101110;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 400);
}
@Test
public void testMatrix101111() throws Throwable {
final int resId = R.integer.matrix_101111;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 100, 400, 600);
}
@Test
public void testMatrix110000() throws Throwable {
final int resId = R.integer.matrix_110000;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 200);
}
@Test
public void testMatrix110001() throws Throwable {
final int resId = R.integer.matrix_110001;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 600);
}
@Test
public void testMatrix110010() throws Throwable {
final int resId = R.integer.matrix_110010;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 200);
}
@Test
public void testMatrix110011() throws Throwable {
final int resId = R.integer.matrix_110011;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 600);
}
@Test
public void testMatrix110100() throws Throwable {
final int resId = R.integer.matrix_110100;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 400);
}
@Test
public void testMatrix110101() throws Throwable {
final int resId = R.integer.matrix_110101;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 600);
}
@Test
public void testMatrix110110() throws Throwable {
final int resId = R.integer.matrix_110110;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 400);
}
@Test
public void testMatrix110111() throws Throwable {
final int resId = R.integer.matrix_110111;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 600);
}
@Test
public void testMatrix111000() throws Throwable {
final int resId = R.integer.matrix_111000;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 200);
}
@Test
public void testMatrix111001() throws Throwable {
final int resId = R.integer.matrix_111001;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 600);
}
@Test
public void testMatrix111010() throws Throwable {
final int resId = R.integer.matrix_111010;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 200);
}
@Test
public void testMatrix111011() throws Throwable {
final int resId = R.integer.matrix_111011;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 200, 600);
}
@Test
public void testMatrix111100() throws Throwable {
final int resId = R.integer.matrix_111100;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 400);
}
@Test
public void testMatrix111101() throws Throwable {
final int resId = R.integer.matrix_111101;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 600);
}
@Test
public void testMatrix111110() throws Throwable {
final int resId = R.integer.matrix_111110;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 400);
}
@Test
public void testMatrix111111() throws Throwable {
final int resId = R.integer.matrix_111111;
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 600);
}
/**
* Executes the shell command and reads all the output to ensure the command ran and didn't
* get stuck buffering on output.
*/
protected static String executeShellCommand(UiAutomation automation, String command)
throws Exception {
final ParcelFileDescriptor pfd = automation.executeShellCommand(command);
try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(in, StandardCharsets.UTF_8));
StringBuilder str = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
str.append(line);
}
return str.toString();
}
}
/**
* Enables overlay packages and waits for a configuration change event before
* returning, to guarantee that Resources are up-to-date.
* @param packages the list of package names to enable.
*/
protected static void enableOverlayPackages(String... packages) throws Exception {
enableOverlayPackages(true, packages);
}
/**
* Disables overlay packages and waits for a configuration change event before
* returning, to guarantee that Resources are up-to-date.
* @param packages the list of package names to disable.
*/
protected static void disableOverlayPackages(String... packages) throws Exception {
enableOverlayPackages(false, packages);
}
/**
* Enables/disables overlay packages and waits for a configuration change event before
* returning, to guarantee that Resources are up-to-date.
* @param enable enables the overlays when true, disables when false.
* @param packages the list of package names to enable/disable.
*/
private static void enableOverlayPackages(boolean enable, String[] packages)
throws Exception {
final UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation()
.getUiAutomation();
for (final String pkg : packages) {
executeShellCommand(uiAutomation,
"cmd overlay " + (enable ? "enable " : "disable ") + pkg);
}
// Wait for the overlay change to propagate.
Thread.sleep(1000);
}
}