blob: 37d1b2c55f02b087870e8c9afdfcfc7f39756f65 [file] [log] [blame]
package org.robolectric.plugins;
import static com.google.common.collect.ImmutableMap.of;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.robolectric.annotation.Config.DEFAULT_APPLICATION;
import android.app.Application;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.model.InitializationError;
import org.robolectric.TestFakeApp;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowView;
import org.robolectric.shadows.ShadowViewGroup;
import org.robolectric.shadows.testing.TestApplication;
@RunWith(JUnit4.class)
public class DefaultConfigMergerTest {
@Test public void defaultValuesAreMerged() throws Exception {
assertThat(configFor(Test2.class, "withoutAnnotation",
new Config.Builder().build()).manifest())
.isEqualTo("AndroidManifest.xml");
}
@Test public void globalValuesAreMerged() throws Exception {
assertThat(configFor(Test2.class, "withoutAnnotation",
new Config.Builder().setManifest("ManifestFromGlobal.xml").build()).manifest())
.isEqualTo("ManifestFromGlobal.xml");
}
@Test
public void whenClassHasConfigAnnotation_getConfig_shouldMergeClassAndMethodConfig() throws Exception {
assertConfig(
configFor(Test1.class, "withoutAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-test",
"test/res",
"test/assets",
new Class[] {Test1.class},
new String[] {"com.example.test1"},
new String[] {"libs/test"});
assertConfig(
configFor(Test1.class, "withDefaultsAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-test",
"test/res",
"test/assets",
new Class[] {Test1.class},
new String[] {"com.example.test1"},
new String[] {"libs/test"});
assertConfig(
configFor(Test1.class, "withOverrideAnnotation"),
new int[] {9},
"furf",
TestApplication.class,
"com.example.method",
"from-method",
"method/res",
"method/assets",
new Class[] {Test1.class, Test2.class},
new String[] {"com.example.test1", "com.example.method1"},
new String[] {"libs/method", "libs/test"});
}
@Test
public void whenClassDoesntHaveConfigAnnotation_getConfig_shouldUseMethodConfig() throws Exception {
assertConfig(
configFor(Test2.class, "withoutAnnotation"),
new int[0],
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {});
assertConfig(
configFor(Test2.class, "withDefaultsAnnotation"),
new int[0],
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {});
assertConfig(
configFor(Test2.class, "withOverrideAnnotation"),
new int[] {9},
"furf",
TestFakeApp.class,
"com.example.method",
"from-method",
"method/res",
"method/assets",
new Class[] {Test1.class},
new String[] {"com.example.method2"},
new String[] {"libs/method"});
}
@Test
public void whenClassDoesntHaveConfigAnnotation_getConfig_shouldMergeParentClassAndMethodConfig() throws Exception {
assertConfig(
configFor(Test5.class, "withoutAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-test",
"test/res",
"test/assets",
new Class[] {Test1.class, Test1.class},
new String[] {"com.example.test1"},
new String[] {"libs/test"});
assertConfig(
configFor(Test5.class, "withDefaultsAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-test",
"test/res",
"test/assets",
new Class[] {Test1.class, Test1.class},
new String[] {"com.example.test1"},
new String[] {"libs/test"});
assertConfig(
configFor(Test5.class, "withOverrideAnnotation"),
new int[] {14},
"foo",
TestFakeApp.class,
"com.example.test",
"from-method5",
"test/res",
"method5/assets",
new Class[] {Test1.class, Test1.class, Test5.class},
new String[] {"com.example.test1", "com.example.method5"},
new String[] {"libs/test"});
}
@Test
public void whenClassAndParentClassHaveConfigAnnotation_getConfig_shouldMergeParentClassAndMethodConfig() throws Exception {
assertConfig(
configFor(Test6.class, "withoutAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-class6",
"class6/res",
"test/assets",
new Class[] {Test1.class, Test1.class, Test6.class},
new String[] {"com.example.test1", "com.example.test6"},
new String[] {"libs/test"});
assertConfig(
configFor(Test6.class, "withDefaultsAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-class6",
"class6/res",
"test/assets",
new Class[] {Test1.class, Test1.class, Test6.class},
new String[] {"com.example.test1", "com.example.test6"},
new String[] {"libs/test"});
assertConfig(
configFor(Test6.class, "withOverrideAnnotation"),
new int[] {14},
"foo",
TestFakeApp.class,
"com.example.test",
"from-method5",
"class6/res",
"method5/assets",
new Class[] {Test1.class, Test1.class, Test6.class, Test5.class},
new String[] {"com.example.test1", "com.example.method5", "com.example.test6"},
new String[] {"libs/test"});
}
@Test
public void whenClassAndSubclassHaveConfigAnnotation_getConfig_shouldMergeClassSubclassAndMethodConfig() throws Exception {
assertConfig(
configFor(Test3.class, "withoutAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-subclass",
"test/res",
"test/assets",
new Class[] {Test1.class},
new String[] {"com.example.test1"},
new String[] {"libs/test"});
assertConfig(
configFor(Test3.class, "withDefaultsAnnotation"),
new int[] {1},
"foo",
TestFakeApp.class,
"com.example.test",
"from-subclass",
"test/res",
"test/assets",
new Class[] {Test1.class},
new String[] {"com.example.test1"},
new String[] {"libs/test"});
assertConfig(
configFor(Test3.class, "withOverrideAnnotation"),
new int[] {9},
"furf",
TestApplication.class,
"com.example.method",
"from-method",
"method/res",
"method/assets",
new Class[] {Test1.class, Test2.class},
new String[] {"com.example.test1", "com.example.method1"},
new String[] {"libs/method", "libs/test"});
}
@Test
public void whenClassDoesntHaveConfigAnnotationButSubclassDoes_getConfig_shouldMergeSubclassAndMethodConfig() throws Exception {
assertConfig(
configFor(Test4.class, "withoutAnnotation"),
new int[0],
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"from-subclass",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {});
assertConfig(
configFor(Test4.class, "withDefaultsAnnotation"),
new int[0],
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"from-subclass",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {});
assertConfig(
configFor(Test4.class, "withOverrideAnnotation"),
new int[] {9},
"furf",
TestFakeApp.class,
"com.example.method",
"from-method",
"method/res",
"method/assets",
new Class[] {Test1.class},
new String[] {"com.example.method2"},
new String[] {"libs/method"});
}
@Test
public void shouldLoadDefaultsFromGlobalPropertiesFile() throws Exception {
String properties =
"sdk: 432\n"
+ "manifest: --none\n"
+ "qualifiers: from-properties-file\n"
+ "resourceDir: from/properties/file/res\n"
+ "assetDir: from/properties/file/assets\n"
+ "shadows: org.robolectric.shadows.ShadowView, org.robolectric.shadows.ShadowViewGroup\n"
+ "application: org.robolectric.TestFakeApp\n"
+ "packageName: com.example.test\n"
+ "instrumentedPackages: com.example.test1, com.example.test2\n"
+ "libraries: libs/test, libs/test2";
assertConfig(
configFor(Test2.class, "withoutAnnotation", of("robolectric.properties", properties)),
new int[] {432},
"--none",
TestFakeApp.class,
"com.example.test",
"from-properties-file",
"from/properties/file/res",
"from/properties/file/assets",
new Class[] {ShadowView.class, ShadowViewGroup.class},
new String[] {"com.example.test1", "com.example.test2"},
new String[] {"libs/test", "libs/test2"});
}
@Test
public void shouldMergeConfigFromTestClassPackageProperties() throws Exception {
assertConfig(
configFor(
Test2.class,
"withoutAnnotation",
of("org/robolectric/robolectric.properties", "sdk: 432\n")),
new int[] {432},
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {});
}
@Test
public void shouldMergeConfigUpPackageHierarchy() throws Exception {
assertConfig(
configFor(
Test2.class,
"withoutAnnotation",
of(
"org/robolectric/robolectric.properties",
"qualifiers: from-org-robolectric\nlibraries: FromOrgRobolectric\n",
"org/robolectric.properties",
"sdk: 123\nqualifiers: from-org\nlibraries: FromOrg\n",
"robolectric.properties",
"sdk: 456\nqualifiers: from-top-level\nlibraries: FromTopLevel\n")),
new int[] {123},
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"from-org-robolectric",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {"FromOrgRobolectric", "FromOrg", "FromTopLevel"});
}
@Test
public void withEmptyShadowList_shouldLoadDefaultsFromGlobalPropertiesFile() throws Exception {
assertConfig(
configFor(Test2.class, "withoutAnnotation", of("robolectric.properties", "shadows:")),
new int[0],
"AndroidManifest.xml",
DEFAULT_APPLICATION,
"",
"",
"res",
"assets",
new Class[] {},
new String[] {},
new String[] {});
}
@Test public void testPackageHierarchyOf() throws Exception {
assertThat(new DefaultConfigMerger().packageHierarchyOf(DefaultConfigMergerTest.class))
.containsExactly("org.robolectric.plugins", "org.robolectric", "org", "");
}
/////////////////////////////
private Config configFor(Class<?> testClass, String methodName, final Map<String, String> configProperties) throws InitializationError {
return configFor(testClass, methodName, configProperties, Config.Builder.defaults().build());
}
private Config configFor(Class<?> testClass, String methodName) throws InitializationError {
Config.Implementation globalConfig = Config.Builder.defaults().build();
return configFor(testClass, methodName, globalConfig);
}
private Config configFor(Class<?> testClass, String methodName, Config.Implementation globalConfig) throws InitializationError {
return configFor(testClass, methodName, new HashMap<>(), globalConfig);
}
private Config configFor(Class<?> testClass, String methodName, final Map<String, String> configProperties, Config.Implementation globalConfig) throws InitializationError {
Method info = getMethod(testClass, methodName);
return new DefaultConfigMerger() {
@Override
InputStream getResourceAsStream(String resourceName) {
String properties = configProperties.get(resourceName);
return properties == null ? null : new ByteArrayInputStream(properties.getBytes(UTF_8));
}
}.getConfig(testClass, info, globalConfig);
}
private static Method getMethod(Class<?> testClass, String methodName) {
try {
return testClass.getMethod(methodName);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
private static void assertConfig(
Config config,
int[] sdk,
String manifest,
Class<? extends Application> application,
String packageName,
String qualifiers,
String resourceDir,
String assetsDir,
Class<?>[] shadows,
String[] instrumentedPackages,
String[] libraries) {
assertThat(config.sdk()).isEqualTo(sdk);
assertThat(config.manifest()).isEqualTo(manifest);
assertThat(config.application()).isEqualTo(application);
assertThat(config.packageName()).isEqualTo(packageName);
assertThat(config.qualifiers()).isEqualTo(qualifiers);
assertThat(config.resourceDir()).isEqualTo(resourceDir);
assertThat(config.assetDir()).isEqualTo(assetsDir);
assertThat(config.shadows()).asList().containsAllIn(shadows).inOrder();
assertThat(config.instrumentedPackages()).asList().containsAllIn(instrumentedPackages);
assertThat(config.libraries()).asList().containsAllIn(libraries);
}
@Ignore
@Config(
sdk = 1,
manifest = "foo",
application = TestFakeApp.class,
packageName = "com.example.test",
shadows = Test1.class,
instrumentedPackages = "com.example.test1",
libraries = "libs/test",
qualifiers = "from-test",
resourceDir = "test/res",
assetDir = "test/assets")
public static class Test1 {
@Test
public void withoutAnnotation() throws Exception {
}
@Test
@Config
public void withDefaultsAnnotation() throws Exception {
}
@Test
@Config(
sdk = 9,
manifest = "furf",
application = TestApplication.class,
packageName = "com.example.method",
shadows = Test2.class,
instrumentedPackages = "com.example.method1",
libraries = "libs/method",
qualifiers = "from-method",
resourceDir = "method/res",
assetDir = "method/assets")
public void withOverrideAnnotation() throws Exception {}
}
@Ignore
public static class Test2 {
@Test
public void withoutAnnotation() throws Exception {
}
@Test
@Config
public void withDefaultsAnnotation() throws Exception {
}
@Test
@Config(
sdk = 9,
manifest = "furf",
application = TestFakeApp.class,
packageName = "com.example.method",
shadows = Test1.class,
instrumentedPackages = "com.example.method2",
libraries = "libs/method",
qualifiers = "from-method",
resourceDir = "method/res",
assetDir = "method/assets")
public void withOverrideAnnotation() throws Exception {}
}
@Ignore
@Config(qualifiers = "from-subclass")
public static class Test3 extends Test1 {
}
@Ignore
@Config(qualifiers = "from-subclass")
public static class Test4 extends Test2 {
}
@Ignore
public static class Test5 extends Test1 {
@Override
@Test
public void withoutAnnotation() throws Exception {
}
@Override
@Test
@Config
public void withDefaultsAnnotation() throws Exception {
}
@Override
@Test
@Config(
sdk = 14,
shadows = Test5.class,
instrumentedPackages = "com.example.method5",
packageName = "com.example.test",
qualifiers = "from-method5",
assetDir = "method5/assets")
public void withOverrideAnnotation() throws Exception {}
}
@Ignore
@Config(
qualifiers = "from-class6",
shadows = Test6.class,
instrumentedPackages = "com.example.test6",
resourceDir = "class6/res")
public static class Test6 extends Test5 {}
}