| package org.robolectric.manifest; |
| |
| import android.Manifest; |
| import android.content.Intent; |
| import com.google.common.base.Charsets; |
| import com.google.common.io.Files; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TemporaryFolder; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.robolectric.annotation.Config; |
| import org.robolectric.res.Fs; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import static org.assertj.core.api.Assertions.assertThat; |
| import static org.junit.Assert.assertEquals; |
| import static org.robolectric.util.TestUtil.newConfig; |
| import static org.robolectric.util.TestUtil.resourceFile; |
| |
| @RunWith(JUnit4.class) |
| public class AndroidManifestTest { |
| @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); |
| |
| @Test |
| public void parseManifest_shouldReadContentProviders() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithContentProviders.xml"); |
| |
| assertThat(config.getContentProviders().get(0).getClassName()).isEqualTo("org.robolectric.tester.FullyQualifiedClassName"); |
| assertThat(config.getContentProviders().get(0).getAuthorities()).isEqualTo("org.robolectric.authority1"); |
| |
| assertThat(config.getContentProviders().get(1).getClassName()).isEqualTo("org.robolectric.tester.PartiallyQualifiedClassName"); |
| assertThat(config.getContentProviders().get(1).getAuthorities()).isEqualTo("org.robolectric.authority2"); |
| } |
| |
| @Test |
| public void parseManifest_shouldReadPermissions() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithPermissions.xml"); |
| |
| assertThat(config.getPermissions().keySet()) |
| .contains("some_permission", |
| "permission_with_literal_label", |
| "permission_with_minimal_fields"); |
| PermissionItemData permissionItemData = config.getPermissions().get("some_permission"); |
| assertThat(permissionItemData.getMetaData().getValueMap()).containsEntry("meta_data_name", "meta_data_value"); |
| assertThat(permissionItemData.getName()).isEqualTo("some_permission"); |
| assertThat(permissionItemData.getPermissionGroup()).isEqualTo("my_permission_group"); |
| assertThat(permissionItemData.getDescription()).isEqualTo("@string/test_permission_description"); |
| assertThat(permissionItemData.getProtectionLevel()).isEqualTo("dangerous"); |
| } |
| |
| @Test |
| public void parseManifest_shouldReadBroadcastReceivers() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithReceivers.xml"); |
| assertThat(config.getBroadcastReceivers()).hasSize(8); |
| |
| assertThat(config.getBroadcastReceivers().get(0).getClassName()).isEqualTo("org.robolectric.ConfigTestReceiver.InnerReceiver"); |
| assertThat(config.getBroadcastReceivers().get(0).getActions()).contains("org.robolectric.ACTION1", "org.robolectric.ACTION2"); |
| |
| assertThat(config.getBroadcastReceivers().get(1).getClassName()).isEqualTo("org.robolectric.fakes.ConfigTestReceiver"); |
| assertThat(config.getBroadcastReceivers().get(1).getActions()).contains("org.robolectric.ACTION_SUPERSET_PACKAGE"); |
| |
| assertThat(config.getBroadcastReceivers().get(2).getClassName()).isEqualTo("org.robolectric.ConfigTestReceiver"); |
| assertThat(config.getBroadcastReceivers().get(2).getActions()).contains("org.robolectric.ACTION_SUBSET_PACKAGE"); |
| |
| assertThat(config.getBroadcastReceivers().get(3).getClassName()).isEqualTo("org.robolectric.DotConfigTestReceiver"); |
| assertThat(config.getBroadcastReceivers().get(3).getActions()).contains("org.robolectric.ACTION_DOT_PACKAGE"); |
| |
| assertThat(config.getBroadcastReceivers().get(4).getClassName()).isEqualTo("org.robolectric.test.ConfigTestReceiver"); |
| assertThat(config.getBroadcastReceivers().get(4).getActions()).contains("org.robolectric.ACTION_DOT_SUBPACKAGE"); |
| |
| assertThat(config.getBroadcastReceivers().get(5).getClassName()).isEqualTo("com.foo.Receiver"); |
| assertThat(config.getBroadcastReceivers().get(5).getActions()).contains("org.robolectric.ACTION_DIFFERENT_PACKAGE"); |
| |
| assertThat(config.getBroadcastReceivers().get(6).getClassName()).isEqualTo("com.bar.ReceiverWithoutIntentFilter"); |
| assertThat(config.getBroadcastReceivers().get(6).getActions()).isEmpty(); |
| |
| assertThat(config.getBroadcastReceivers().get(7).getClassName()).isEqualTo("org.robolectric.ConfigTestReceiverPermissionsAndActions"); |
| assertThat(config.getBroadcastReceivers().get(7).getActions()).contains("org.robolectric.ACTION_RECEIVER_PERMISSION_PACKAGE"); |
| } |
| |
| @Test |
| public void parseManifest_shouldReadServices() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithServices.xml"); |
| assertThat(config.getServices()).hasSize(2); |
| |
| assertThat(config.getServices().get(0).getClassName()).isEqualTo("com.foo.Service"); |
| assertThat(config.getServices().get(0).getActions()).contains("org.robolectric.ACTION_DIFFERENT_PACKAGE"); |
| assertThat(config.getServices().get(0).getIntentFilters()).isNotEmpty(); |
| assertThat(config.getServices().get(0).getIntentFilters().get(0).getMimeTypes()).containsExactly("image/jpeg"); |
| |
| assertThat(config.getServices().get(1).getClassName()).isEqualTo("com.bar.ServiceWithoutIntentFilter"); |
| assertThat(config.getServices().get(1).getActions()).isEmpty(); |
| assertThat(config.getServices().get(1).getIntentFilters()).isEmpty(); |
| |
| assertThat(config.getServiceData("com.foo.Service").getClassName()).isEqualTo("com.foo.Service"); |
| assertThat(config.getServiceData("com.bar.ServiceWithoutIntentFilter").getClassName()).isEqualTo("com.bar.ServiceWithoutIntentFilter"); |
| assertEquals(config.getServiceData("com.foo.Service").getPermission(), "com.foo.Permission"); |
| } |
| |
| @Test |
| public void testManifestWithNoApplicationElement() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestNoApplicationElement.xml"); |
| assertThat(config.getPackageName()).isEqualTo("org.robolectric"); |
| } |
| |
| @Test |
| public void parseManifest_shouldReadBroadcastReceiversWithMetaData() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithReceivers.xml"); |
| |
| assertThat(config.getBroadcastReceivers().get(4).getClassName()).isEqualTo("org.robolectric.test.ConfigTestReceiver"); |
| assertThat(config.getBroadcastReceivers().get(4).getActions()).contains("org.robolectric.ACTION_DOT_SUBPACKAGE"); |
| |
| Map<String, Object> meta = config.getBroadcastReceivers().get(4).getMetaData().getValueMap(); |
| Object metaValue = meta.get("org.robolectric.metaName1"); |
| assertEquals("metaValue1", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaName2"); |
| assertEquals("metaValue2", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaFalse"); |
| assertEquals("false", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaTrue"); |
| assertEquals("true", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaInt"); |
| assertEquals("123", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaFloat"); |
| assertEquals("1.23", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaColor"); |
| assertEquals("#FFFFFF", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaBooleanFromRes"); |
| assertEquals("@bool/false_bool_value", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaIntFromRes"); |
| assertEquals("@integer/test_integer1", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaColorFromRes"); |
| assertEquals("@color/clear", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaStringFromRes"); |
| assertEquals("@string/app_name", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaStringOfIntFromRes"); |
| assertEquals("@string/str_int", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaStringRes"); |
| assertEquals("@string/app_name", metaValue); |
| } |
| |
| @Test |
| public void shouldReadBroadcastReceiverPermissions() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithReceivers.xml"); |
| |
| assertThat(config.getBroadcastReceivers().get(7).getClassName()).isEqualTo("org.robolectric.ConfigTestReceiverPermissionsAndActions"); |
| assertThat(config.getBroadcastReceivers().get(7).getActions()).contains("org.robolectric.ACTION_RECEIVER_PERMISSION_PACKAGE"); |
| |
| assertEquals("org.robolectric.CUSTOM_PERM", config.getBroadcastReceivers().get(7).getPermission()); |
| } |
| |
| @Test |
| public void shouldReadTargetSdkVersionFromAndroidManifestOrDefaultToMin() throws Exception { |
| assertEquals(42, newConfigWith("targetsdk42minsdk6.xml", "android:targetSdkVersion=\"42\" android:minSdkVersion=\"7\"").getTargetSdkVersion()); |
| assertEquals(7, newConfigWith("minsdk7.xml", "android:minSdkVersion=\"7\"").getTargetSdkVersion()); |
| assertEquals(1, newConfigWith("noattributes.xml", "").getTargetSdkVersion()); |
| } |
| |
| @Test |
| public void shouldReadMinSdkVersionFromAndroidManifestOrDefaultToOne() throws Exception { |
| assertEquals(17, newConfigWith("minsdk17.xml", "android:minSdkVersion=\"17\"").getMinSdkVersion()); |
| assertEquals(1, newConfigWith("noattributes.xml", "").getMinSdkVersion()); |
| } |
| |
| /** |
| * For Android O preview, apps are encouraged to use targetSdkVersion="O". |
| * |
| * @see <a href="http://google.com">https://developer.android.com/preview/migration.html</a> |
| */ |
| @Test |
| public void shouldReadTargetSDKVersionOPreview() throws Exception { |
| assertEquals(26, newConfigWith("TestAndroidManifestForPreview.xml", "android:targetSdkVersion=\"O\"").getTargetSdkVersion()); |
| } |
| |
| @Test |
| public void shouldReadProcessFromAndroidManifest() throws Exception { |
| assertEquals("robolectricprocess", newConfig("TestAndroidManifestWithProcess.xml").getProcessName()); |
| } |
| |
| @Test |
| public void shouldReturnPackageNameWhenNoProcessIsSpecifiedInTheManifest() { |
| assertEquals("org.robolectric", newConfig("TestAndroidManifestWithNoProcess.xml").getProcessName()); |
| } |
| |
| @Test |
| @Config(manifest = "TestAndroidManifestWithAppMetaData.xml") |
| public void shouldReturnApplicationMetaData() throws Exception { |
| Map<String, Object> meta = newConfig("TestAndroidManifestWithAppMetaData.xml").getApplicationMetaData(); |
| |
| Object metaValue = meta.get("org.robolectric.metaName1"); |
| assertEquals("metaValue1", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaName2"); |
| assertEquals("metaValue2", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaFalse"); |
| assertEquals("false", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaTrue"); |
| assertEquals("true", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaInt"); |
| assertEquals("123", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaFloat"); |
| assertEquals("1.23", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaColor"); |
| assertEquals("#FFFFFF", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaBooleanFromRes"); |
| assertEquals("@bool/false_bool_value", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaIntFromRes"); |
| assertEquals("@integer/test_integer1", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaColorFromRes"); |
| assertEquals("@color/clear", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaStringFromRes"); |
| assertEquals("@string/app_name", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaStringOfIntFromRes"); |
| assertEquals("@string/str_int", metaValue); |
| |
| metaValue = meta.get("org.robolectric.metaStringRes"); |
| assertEquals("@string/app_name", metaValue); |
| } |
| |
| @Test |
| public void shouldTolerateMissingRFile() throws Exception { |
| AndroidManifest appManifest = new AndroidManifest(resourceFile("TestAndroidManifestWithNoRFile.xml"), resourceFile("res"), resourceFile("assets")); |
| assertEquals(appManifest.getPackageName(), "org.no.resources.for.me"); |
| assertThat(appManifest.getRClass()).isNull(); |
| } |
| |
| @Test |
| public void whenNullManifestFile_getRClass_shouldComeFromPackageName() throws Exception { |
| AndroidManifest appManifest = new AndroidManifest(null, resourceFile("res"), resourceFile("assets"), "org.robolectric.lib1"); |
| assertThat(appManifest.getRClass()).isEqualTo(org.robolectric.lib1.R.class); |
| assertThat(appManifest.getPackageName()).isEqualTo("org.robolectric.lib1"); |
| } |
| |
| @Test |
| public void whenMissingManifestFile_getRClass_shouldComeFromPackageName() throws Exception { |
| AndroidManifest appManifest = new AndroidManifest(resourceFile("none.xml"), resourceFile("res"), resourceFile("assets"), "org.robolectric.lib1"); |
| assertThat(appManifest.getRClass()).isEqualTo(org.robolectric.lib1.R.class); |
| assertThat(appManifest.getPackageName()).isEqualTo("org.robolectric.lib1"); |
| } |
| |
| @Test |
| public void shouldRead1IntentFilter() { |
| AndroidManifest appManifest = newConfig("TestAndroidManifestForActivitiesWithIntentFilter.xml"); |
| appManifest.getMinSdkVersion(); // Force parsing |
| |
| ActivityData activityData = appManifest.getActivityData("org.robolectric.shadows.TestActivity"); |
| final List<IntentFilterData> ifd = activityData.getIntentFilters(); |
| assertThat(ifd).isNotNull(); |
| assertThat(ifd.size()).isEqualTo(1); |
| |
| final IntentFilterData data = ifd.get(0); |
| assertThat(data.getActions().size()).isEqualTo(1); |
| assertThat(data.getActions().get(0)).isEqualTo(Intent.ACTION_MAIN); |
| assertThat(data.getCategories().size()).isEqualTo(1); |
| assertThat(data.getCategories().get(0)).isEqualTo(Intent.CATEGORY_LAUNCHER); |
| } |
| |
| @Test |
| public void shouldReadMultipleIntentFilters() { |
| AndroidManifest appManifest = newConfig("TestAndroidManifestForActivitiesWithMultipleIntentFilters.xml"); |
| appManifest.getMinSdkVersion(); // Force parsing |
| |
| ActivityData activityData = appManifest.getActivityData("org.robolectric.shadows.TestActivity"); |
| final List<IntentFilterData> ifd = activityData.getIntentFilters(); |
| assertThat(ifd).isNotNull(); |
| assertThat(ifd.size()).isEqualTo(2); |
| |
| IntentFilterData data = ifd.get(0); |
| assertThat(data.getActions().size()).isEqualTo(1); |
| assertThat(data.getActions().get(0)).isEqualTo(Intent.ACTION_MAIN); |
| assertThat(data.getCategories().size()).isEqualTo(1); |
| assertThat(data.getCategories().get(0)).isEqualTo(Intent.CATEGORY_LAUNCHER); |
| |
| data = ifd.get(1); |
| assertThat(data.getActions().size()).isEqualTo(3); |
| assertThat(data.getActions().get(0)).isEqualTo(Intent.ACTION_VIEW); |
| assertThat(data.getActions().get(1)).isEqualTo(Intent.ACTION_EDIT); |
| assertThat(data.getActions().get(2)).isEqualTo(Intent.ACTION_PICK); |
| |
| assertThat(data.getCategories().size()).isEqualTo(3); |
| assertThat(data.getCategories().get(0)).isEqualTo(Intent.CATEGORY_DEFAULT); |
| assertThat(data.getCategories().get(1)).isEqualTo(Intent.CATEGORY_ALTERNATIVE); |
| assertThat(data.getCategories().get(2)).isEqualTo(Intent.CATEGORY_SELECTED_ALTERNATIVE); |
| } |
| |
| @Test |
| public void shouldReadTaskAffinity() { |
| AndroidManifest appManifest = newConfig("TestAndroidManifestForActivitiesWithTaskAffinity.xml"); |
| assertThat(appManifest.getTargetSdkVersion()).isEqualTo(16); |
| |
| ActivityData activityData = appManifest.getActivityData("org.robolectric.shadows.TestTaskAffinityActivity"); |
| assertThat(activityData).isNotNull(); |
| assertThat(activityData.getTaskAffinity()).isEqualTo("org.robolectric.shadows.TestTaskAffinity"); |
| } |
| |
| @Test |
| public void shouldReadPermissions() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithPermissions.xml"); |
| |
| assertThat(config.getUsedPermissions()).hasSize(3); |
| assertThat(config.getUsedPermissions().get(0)).isEqualTo(Manifest.permission.INTERNET); |
| assertThat(config.getUsedPermissions().get(1)).isEqualTo(Manifest.permission.SYSTEM_ALERT_WINDOW); |
| assertThat(config.getUsedPermissions().get(2)).isEqualTo(Manifest.permission.GET_TASKS); |
| } |
| |
| @Test |
| public void shouldReadPartiallyQualifiedActivities() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestForActivities.xml"); |
| assertThat(config.getActivityDatas()).hasSize(2); |
| assertThat(config.getActivityDatas()).containsKey("org.robolectric.shadows.TestActivity"); |
| assertThat(config.getActivityDatas()).containsKey("org.robolectric.shadows.TestActivity2"); |
| } |
| |
| @Test |
| public void shouldReadActivityAliases() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestForActivityAliases.xml"); |
| assertThat(config.getActivityDatas()).hasSize(2); |
| assertThat(config.getActivityDatas()).containsKey("org.robolectric.shadows.TestActivity"); |
| assertThat(config.getActivityDatas()).containsKey("org.robolectric.shadows.TestActivityAlias"); |
| } |
| |
| @Test |
| public void shouldReadIntentFilterWithData() { |
| AndroidManifest appManifest = newConfig("TestAndroidManifestForActivitiesWithIntentFilterWithData.xml"); |
| appManifest.getMinSdkVersion(); // Force parsing |
| |
| ActivityData activityData = appManifest.getActivityData("org.robolectric.shadows.TestActivity"); |
| final List<IntentFilterData> ifd = activityData.getIntentFilters(); |
| assertThat(ifd).isNotNull(); |
| assertThat(ifd.size()).isEqualTo(1); |
| |
| final IntentFilterData intentFilterData = ifd.get(0); |
| assertThat(intentFilterData.getActions().size()).isEqualTo(1); |
| assertThat(intentFilterData.getActions().get(0)).isEqualTo(Intent.ACTION_VIEW); |
| assertThat(intentFilterData.getCategories().size()).isEqualTo(1); |
| assertThat(intentFilterData.getCategories().get(0)).isEqualTo(Intent.CATEGORY_DEFAULT); |
| |
| assertThat(intentFilterData.getSchemes().size()).isEqualTo(3); |
| assertThat(intentFilterData.getAuthorities().size()).isEqualTo(3); |
| assertThat(intentFilterData.getMimeTypes().size()).isEqualTo(3); |
| assertThat(intentFilterData.getPaths().size()).isEqualTo(1); |
| assertThat(intentFilterData.getPathPatterns().size()).isEqualTo(1); |
| assertThat(intentFilterData.getPathPrefixes().size()).isEqualTo(1); |
| |
| |
| assertThat(intentFilterData.getSchemes().get(0)).isEqualTo("content"); |
| assertThat(intentFilterData.getPaths().get(0)).isEqualTo("/testPath/test.jpeg"); |
| assertThat(intentFilterData.getMimeTypes().get(0)).isEqualTo("video/mpeg"); |
| assertThat(intentFilterData.getAuthorities().get(0).getHost()).isEqualTo("testhost1.com"); |
| assertThat(intentFilterData.getAuthorities().get(0).getPort()).isEqualTo("1"); |
| |
| assertThat(intentFilterData.getSchemes().get(1)).isEqualTo("http"); |
| assertThat(intentFilterData.getPathPrefixes().get(0)).isEqualTo("/testPrefix"); |
| assertThat(intentFilterData.getMimeTypes().get(1)).isEqualTo("image/jpeg"); |
| assertThat(intentFilterData.getAuthorities().get(1).getHost()).isEqualTo("testhost2.com"); |
| assertThat(intentFilterData.getAuthorities().get(1).getPort()).isEqualTo("2"); |
| |
| assertThat(intentFilterData.getSchemes().get(2)).isEqualTo("https"); |
| assertThat(intentFilterData.getPathPatterns().get(0)).isEqualTo("/.*testPattern"); |
| assertThat(intentFilterData.getMimeTypes().get(2)).isEqualTo("image/*"); |
| assertThat(intentFilterData.getAuthorities().get(2).getHost()).isEqualTo("testhost3.com"); |
| assertThat(intentFilterData.getAuthorities().get(2).getPort()).isEqualTo("3"); |
| } |
| |
| @Test |
| public void shouldHaveStableHashCode() throws Exception { |
| AndroidManifest manifest = newConfig("TestAndroidManifestWithContentProviders.xml"); |
| int hashCode1 = manifest.hashCode(); |
| manifest.getServices(); |
| int hashCode2 = manifest.hashCode(); |
| assertEquals(hashCode1, hashCode2); |
| } |
| |
| @Test |
| public void shouldReadApplicationAttrsFromAndroidManifest() throws Exception { |
| AndroidManifest config = newConfig("TestAndroidManifestWithFlags.xml"); |
| assertThat(config.getApplicationAttributes().get("android:allowBackup")).isEqualTo("true"); |
| } |
| |
| @Test |
| public void allFieldsShouldBePrimitivesOrJavaLangOrRobolectric() throws Exception { |
| List<Field> wrongFields = new ArrayList<>(); |
| for (Field field : AndroidManifest.class.getDeclaredFields()) { |
| Class<?> type = field.getType(); |
| if (type.isPrimitive()) continue; |
| |
| String packageName = type.getPackage().getName(); |
| if (packageName.startsWith("java.") |
| || packageName.equals("org.robolectric.res") |
| || packageName.equals("org.robolectric.manifest") |
| ) continue; |
| |
| wrongFields.add(field); |
| } |
| |
| assertThat(wrongFields).isEmpty(); |
| } |
| |
| ///////////////////////////// |
| |
| private AndroidManifest newConfigWith(String fileName, String usesSdkAttrs) throws IOException { |
| String contents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + |
| "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + |
| " package=\"org.robolectric\">\n" + |
| " <uses-sdk " + usesSdkAttrs + "/>\n" + |
| "</manifest>\n"; |
| File f = temporaryFolder.newFile(fileName); |
| Files.write(contents, f, Charsets.UTF_8); |
| return new AndroidManifest(Fs.newFile(f), null, null); |
| } |
| } |