1package org.robolectric;
2
3import static org.assertj.core.api.Assertions.assertThat;
4import static org.junit.Assert.assertEquals;
5import static org.robolectric.util.TestUtil.resourceFile;
6
7import java.util.ArrayList;
8import java.util.Collection;
9import java.util.List;
10import java.util.Properties;
11import org.junit.Test;
12import org.junit.runner.RunWith;
13import org.junit.runners.JUnit4;
14import org.junit.runners.model.InitializationError;
15import org.robolectric.annotation.Config;
16import org.robolectric.internal.DefaultManifestFactory;
17import org.robolectric.internal.ManifestFactory;
18import org.robolectric.internal.ManifestIdentifier;
19import org.robolectric.manifest.AndroidManifest;
20import org.robolectric.res.Fs;
21import org.robolectric.res.ResourcePath;
22import org.robolectric.util.TestUtil;
23
24@RunWith(JUnit4.class)
25public class ManifestFactoryTest {
26  @Test
27  public void shouldLoadLibraryManifests() throws Exception {
28    Properties properties = new Properties();
29    properties.setProperty("manifest", resourceFile("TestAndroidManifest.xml").toString());
30    properties.setProperty("libraries", "lib1");
31    Config config = Config.Implementation.fromProperties(properties);
32    RobolectricTestRunner testRunner = simulateTestRunnerWithoutBuildSystemAPI();
33    ManifestFactory manifestFactory = testRunner.getManifestFactory(config);
34    AndroidManifest manifest = RobolectricTestRunner
35        .createAndroidManifest(manifestFactory.identify(config));
36
37    List<AndroidManifest> libraryManifests = manifest.getLibraryManifests();
38    assertEquals(1, libraryManifests.size());
39    assertEquals("org.robolectric.lib1", libraryManifests.get(0).getPackageName());
40  }
41
42  private static RobolectricTestRunner simulateTestRunnerWithoutBuildSystemAPI()
43      throws InitializationError {
44    return new RobolectricTestRunner(ManifestFactoryTest.class) {
45      @Override
46      Properties getBuildSystemApiProperties() {
47        // Even if the build system executing this test provides properties, pretend that it doesn't
48        // so we can test the old mechanism.
49        return null;
50      }
51    };
52  }
53
54  @Test
55  public void shouldLoadAllResourcesForExistingLibraries() throws Exception {
56    Properties properties = new Properties();
57    properties.setProperty("manifest", resourceFile("TestAndroidManifest.xml").toString());
58    properties.setProperty("resourceDir", "res");
59    properties.setProperty("assetDir", "assets");
60    Config config = Config.Implementation.fromProperties(properties);
61    RobolectricTestRunner testRunner = simulateTestRunnerWithoutBuildSystemAPI();
62    ManifestFactory manifestFactory = testRunner.getManifestFactory(config);
63    AndroidManifest appManifest = RobolectricTestRunner
64        .createAndroidManifest(manifestFactory.identify(config));
65
66    // This intentionally loads from the non standard resources/project.properties
67    List<String> resourcePaths = stringify(appManifest.getIncludedResourcePaths());
68    String baseDir = "./" + TestUtil.resourcesBaseDir().getPath();
69    assertThat(resourcePaths).contains(
70        baseDir + "/res",
71        baseDir + "/lib1/res",
72        baseDir + "/lib1/../lib3/res",
73        baseDir + "/lib1/../lib2/res");
74  }
75
76  @Test
77  public void whenBuildSystemApiPropertiesFileIsPresent_shouldUseDefaultManifestFactory() throws Exception {
78    final Properties properties = new Properties();
79    properties.setProperty("android_sdk_home", "");
80    properties.setProperty("android_merged_manifest", "/path/to/MergedManifest.xml");
81    properties.setProperty("android_merged_resources", "/path/to/merged-resources");
82    properties.setProperty("android_merged_assets", "/path/to/merged-assets");
83
84    RobolectricTestRunner testRunner = new RobolectricTestRunner(ManifestFactoryTest.class) {
85      @Override Properties getBuildSystemApiProperties() {
86        return properties;
87      }
88    };
89
90    Config.Implementation config = Config.Builder.defaults().build();
91    ManifestFactory manifestFactory = testRunner.getManifestFactory(config);
92    assertThat(manifestFactory).isInstanceOf(DefaultManifestFactory.class);
93    ManifestIdentifier manifestIdentifier = manifestFactory.identify(config);
94    assertThat(manifestIdentifier.getManifestFile()).isEqualTo(Fs.fileFromPath("/path/to/MergedManifest.xml"));
95    assertThat(manifestIdentifier.getResDir()).isEqualTo(Fs.fileFromPath("/path/to/merged-resources"));
96    assertThat(manifestIdentifier.getAssetDir()).isEqualTo(Fs.fileFromPath("/path/to/merged-assets"));
97    assertThat(manifestIdentifier.getLibraries()).isEmpty();
98    assertThat(manifestIdentifier.getPackageName()).isNull();
99
100    AndroidManifest androidManifest = RobolectricTestRunner
101        .createAndroidManifest(manifestIdentifier);
102    assertThat(androidManifest.getAndroidManifestFile()).isEqualTo(Fs.fileFromPath("/path/to/MergedManifest.xml"));
103    assertThat(androidManifest.getResDirectory()).isEqualTo(Fs.fileFromPath("/path/to/merged-resources"));
104    assertThat(androidManifest.getAssetsDirectory()).isEqualTo(Fs.fileFromPath("/path/to/merged-assets"));
105  }
106
107  @Test
108  public void whenConfigSpecified_overridesValuesFromFile() throws Exception {
109    final Properties properties = new Properties();
110    properties.setProperty("android_sdk_home", "");
111    properties.setProperty("android_merged_manifest", "/path/to/MergedManifest.xml");
112    properties.setProperty("android_merged_resources", "/path/to/merged-resources");
113    properties.setProperty("android_merged_assets", "/path/to/merged-assets");
114
115    RobolectricTestRunner testRunner = new RobolectricTestRunner(ManifestFactoryTest.class) {
116      @Override Properties getBuildSystemApiProperties() {
117        return properties;
118      }
119    };
120
121    Config.Implementation config = Config.Builder.defaults()
122        .setManifest("TestAndroidManifest.xml")
123        .setPackageName("another.package")
124        .build();
125    ManifestFactory manifestFactory = testRunner.getManifestFactory(config);
126    assertThat(manifestFactory).isInstanceOf(DefaultManifestFactory.class);
127    ManifestIdentifier manifestIdentifier = manifestFactory.identify(config);
128    assertThat(manifestIdentifier.getManifestFile())
129            .isEqualTo(Fs.fromURL(getClass().getClassLoader().getResource("TestAndroidManifest.xml")));
130    assertThat(manifestIdentifier.getResDir()).isEqualTo(Fs.fileFromPath("/path/to/merged-resources"));
131    assertThat(manifestIdentifier.getAssetDir()).isEqualTo(Fs.fileFromPath("/path/to/merged-assets"));
132    assertThat(manifestIdentifier.getLibraries()).isEmpty();
133    assertThat(manifestIdentifier.getPackageName()).isEqualTo("another.package");
134  }
135
136  private List<String> stringify(Collection<ResourcePath> resourcePaths) {
137    List<String> resourcePathBases = new ArrayList<>();
138    for (ResourcePath resourcePath : resourcePaths) {
139      resourcePathBases.add(resourcePath.getResourceBase().toString());
140    }
141    return resourcePathBases;
142  }
143}
144