aboutsummaryrefslogtreecommitdiff
path: root/builder/src/test
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2012-12-10 14:59:50 -0800
committerXavier Ducrohet <xav@android.com>2012-12-19 18:58:16 -0800
commit86fe65512d1230aafd9cb974b733f6fd09ac15ce (patch)
tree93af6083035fda4c76400be8e67eea8477cce6aa /builder/src/test
parentcca0ebcf9848a905e1c1ed5139af6d3f64866657 (diff)
downloadbuild-86fe65512d1230aafd9cb974b733f6fd09ac15ce.tar.gz
Incremental resource merger support.
First a ChangeManager (and associated classes) that detects changed files across build runs. This is to be replaced by Gradle once this information is given to the tasks. Then, a rewrite of ResourceMerger and ResourceSet to allow saving a post run state, and reloading it on the next run, to allow for incremental updates of the merged resource folder by only updating the resources that changed, were removed or were added. Finally a change to the BaseTask to support incremental tasks and provide some default support that actual tasks can use or not. The BaseTask will do some first checks to figure out if incremental runs are supported by the class or by the current state, and call one of two methods to do either full run or incremental run. The MergerResourceTask is changed to use this, and its incremental method does a bit more checking and reverts to full run when it cannot do an incremental run. Finally a bunch of tests to ensure this works fine. Change-Id: I3808e2d57aa45882eaf1030e16b092ecd58d9729
Diffstat (limited to 'builder/src/test')
-rw-r--r--builder/src/test/java/com/android/builder/VariantConfigurationTest.java2
-rw-r--r--builder/src/test/java/com/android/builder/resources/BaseTestCase.java49
-rw-r--r--builder/src/test/java/com/android/builder/resources/NoteUtilsTest.java118
-rw-r--r--builder/src/test/java/com/android/builder/resources/ResourceMergerTest.java715
-rw-r--r--builder/src/test/java/com/android/builder/resources/ResourceSetTest.java15
-rw-r--r--builder/src/test/java/com/android/builder/resources/ValueResourceParserTest.java17
-rw-r--r--builder/src/test/resources/testData/baseMerge/merger.xml93
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/new_overlay.pngbin0 -> 97 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/removed_overlay.pngbin0 -> 98 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/touched.pngbin0 -> 98 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/untouched.pngbin0 -> 98 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/merger.xml18
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/new_overlay.pngbin0 -> 97 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable-hdpi/new_alternate.pngbin0 -> 98 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable/new_overlay.pngbin0 -> 98 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable-ldpi/removed.pngbin0 -> 97 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/new_overlay.pngbin0 -> 97 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/removed_overlay.pngbin0 -> 97 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/touched.pngbin0 -> 97 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/untouched.pngbin0 -> 98 bytes
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues/main/values/values.xml6
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues/merger.xml19
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues/overlay/values-fr/values.xml4
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues/overlay/values/values.xml4
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues/resOut/values-en/values.xml4
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues/resOut/values/values.xml7
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues2/main/values/values.xml5
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues2/merger.xml18
-rw-r--r--builder/src/test/resources/testData/incMergeData/basicValues2/resOut/values/values.xml5
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/alias_replaced_by_file.xml14
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/main.xml14
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/main/values/values.xml5
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/merger.xml12
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/file_replaced_by_alias.xml14
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/main.xml14
-rw-r--r--builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/values/values.xml5
36 files changed, 1126 insertions, 51 deletions
diff --git a/builder/src/test/java/com/android/builder/VariantConfigurationTest.java b/builder/src/test/java/com/android/builder/VariantConfigurationTest.java
index 5ee482a..47dd863 100644
--- a/builder/src/test/java/com/android/builder/VariantConfigurationTest.java
+++ b/builder/src/test/java/com/android/builder/VariantConfigurationTest.java
@@ -35,6 +35,7 @@ public class VariantConfigurationTest extends TestCase {
mPackageName = packageName;
}
+ @Override
public String getPackage(File manifestFile) {
return mPackageName;
}
@@ -44,6 +45,7 @@ public class VariantConfigurationTest extends TestCase {
return 0;
}
+ @Override
public String getVersionName(File manifestFile) {
return "1.0";
}
diff --git a/builder/src/test/java/com/android/builder/resources/BaseTestCase.java b/builder/src/test/java/com/android/builder/resources/BaseTestCase.java
index ac9f788..b536ca7 100644
--- a/builder/src/test/java/com/android/builder/resources/BaseTestCase.java
+++ b/builder/src/test/java/com/android/builder/resources/BaseTestCase.java
@@ -16,10 +16,12 @@
package com.android.builder.resources;
+import com.google.common.collect.ListMultimap;
import junit.framework.TestCase;
import java.io.File;
-import java.util.Map;
+import java.io.IOException;
+import java.util.List;
public abstract class BaseTestCase extends TestCase {
@@ -31,11 +33,48 @@ public abstract class BaseTestCase extends TestCase {
return root;
}
- protected void verifyResources(ResourceSet resourceSet, String... resourceKeys) {
- Map<String, Resource> map = resourceSet.getResourceMap();
+ protected static File getCanonicalRoot(String name) throws IOException {
+ File root = getRoot(name);
+ return root.getCanonicalFile();
+ }
+
+ protected void verifyResourceExists(ResourceMap resourceMap, String... resourceKeys) {
+ ListMultimap<String, Resource> map = resourceMap.getResourceMap();
+
+ for (String resKey : resourceKeys) {
+ List<Resource> resources = map.get(resKey);
+ assertTrue("resource '" + resKey + "' is missing!", resources.size() > 0);
+ }
+ }
+
+ /**
+ * Compares two resource maps.
+ *
+ * if <var>fullCompare</var> is <code>true</code> then it'll make sure the multimaps contains
+ * the same number of items, otherwise it'll only checks that each resource key is present
+ * in both maps.
+ *
+ * @param resourceMap1
+ * @param resourceMap2
+ * @param fullCompare
+ */
+ protected void compareResourceMaps(ResourceMap resourceMap1, ResourceMap resourceMap2,
+ boolean fullCompare) {
+ assertEquals(resourceMap1.size(), resourceMap2.size());
- for (String res : resourceKeys) {
- assertNotNull("resource '" + res + "' is missing!", map.get(res));
+ // compare the resources are all the same
+ ListMultimap<String, Resource> map1 = resourceMap1.getResourceMap();
+ ListMultimap<String, Resource> map2 = resourceMap2.getResourceMap();
+ for (String key : map1.keySet()) {
+ List<Resource> items1 = map1.get(key);
+ List<Resource> items2 = map2.get(key);
+ if (fullCompare) {
+ assertEquals("Wrong size for " + key, items1.size(), items2.size());
+ } else {
+ boolean map1HasItem = items1.size() > 0;
+ boolean map2HasItem = items2.size() > 0;
+ assertEquals("resource " + key + " missing from one map", map1HasItem, map2HasItem);
+ }
}
}
}
diff --git a/builder/src/test/java/com/android/builder/resources/NoteUtilsTest.java b/builder/src/test/java/com/android/builder/resources/NoteUtilsTest.java
new file mode 100644
index 0000000..1bcd083
--- /dev/null
+++ b/builder/src/test/java/com/android/builder/resources/NoteUtilsTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 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.builder.resources;
+
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class NoteUtilsTest extends TestCase {
+
+ public void testBasicAttributes() throws Exception {
+ Document document = createDocument();
+
+ // create two nodes
+ Node node1 = document.createElement("N1");
+ Node node2 = document.createElement("N2");
+
+ NodeUtils.addAttribute(document, node1, null, "foo", "bar");
+ NodeUtils.addAttribute(document, node2, null, "foo", "bar");
+ assertTrue(NodeUtils.compareAttributes(node1.getAttributes(), node2.getAttributes()));
+
+ NodeUtils.addAttribute(document, node1, null, "foo2", "bar2");
+ assertFalse(NodeUtils.compareAttributes(node1.getAttributes(), node2.getAttributes()));
+
+ NodeUtils.addAttribute(document, node2, null, "foo2", "bar");
+ assertFalse(NodeUtils.compareAttributes(node1.getAttributes(), node2.getAttributes()));
+ }
+
+ public void testNamespaceAttributes() throws Exception {
+ Document document = createDocument();
+
+ // create two nodes
+ Node node1 = document.createElement("N1");
+ Node node2 = document.createElement("N2");
+
+ NodeUtils.addAttribute(document, node1, "http://some.uri/", "foo", "bar");
+ NodeUtils.addAttribute(document, node2, "http://some.uri/", "foo", "bar");
+ assertTrue(NodeUtils.compareAttributes(node1.getAttributes(), node2.getAttributes()));
+
+ NodeUtils.addAttribute(document, node1, "http://some.uri/", "foo2", "bar2");
+ NodeUtils.addAttribute(document, node2, "http://some.other.uri/", "foo2", "bar2");
+ assertFalse(NodeUtils.compareAttributes(node1.getAttributes(), node2.getAttributes()));
+ }
+
+ public void testNodesWithChildrenNodes() throws Exception {
+ Document document = createDocument();
+
+ // create two nodes
+ Node node1 = document.createElement("some-node");
+ Node node2 = document.createElement("some-node");
+
+ Node child1a = document.createElement("child1");
+ Node child1b = document.createElement("child2");
+ node1.appendChild(child1a).appendChild(child1b);
+
+ Node child2a = document.createElement("child1");
+ Node child2b = document.createElement("child2");
+ node2.appendChild(child2a).appendChild(child2b);
+
+ assertTrue(NodeUtils.compareElementNode(node1, node2));
+ }
+
+ public void testAdoptNode() throws Exception {
+ Document document = createDocument();
+ Node rootNode = document.createElement("root");
+ document.appendChild(rootNode);
+
+ // create a single s
+ Node node = document.createElement("some-node");
+
+ // add some children
+ Node child1 = document.createElement("child1");
+ Node child2 = document.createElement("child2");
+ node.appendChild(child1).appendChild(child2);
+
+ // add some attributes
+ NodeUtils.addAttribute(document, node, null, "foo", "bar");
+ NodeUtils.addAttribute(document, node, "http://some.uri", "foo2", "bar2");
+ NodeUtils.addAttribute(document, child1, "http://some.other.uri", "blah", "test");
+ NodeUtils.addAttribute(document, child2, "http://another.uri", "blah", "test");
+
+ // create the other document to receive the adopted node. It must have a root node.
+ Document document2 = createDocument();
+ rootNode = document2.createElement("root");
+ document2.appendChild(rootNode);
+
+ assertTrue(NodeUtils.compareElementNode(node, NodeUtils.adoptNode(document2, node)));
+ }
+
+ private static Document createDocument() throws ParserConfigurationException {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setValidating(false);
+ factory.setIgnoringComments(true);
+ DocumentBuilder builder;
+
+ builder = factory.newDocumentBuilder();
+ return builder.newDocument();
+ }
+}
diff --git a/builder/src/test/java/com/android/builder/resources/ResourceMergerTest.java b/builder/src/test/java/com/android/builder/resources/ResourceMergerTest.java
index 6b856e2..c26f47d 100644
--- a/builder/src/test/java/com/android/builder/resources/ResourceMergerTest.java
+++ b/builder/src/test/java/com/android/builder/resources/ResourceMergerTest.java
@@ -16,26 +16,38 @@
package com.android.builder.resources;
+import com.android.resources.ResourceFolderType;
+import com.android.resources.ResourceType;
+import com.google.common.base.Charsets;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Maps;
import com.google.common.io.Files;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
public class ResourceMergerTest extends BaseTestCase {
- private static ResourceSet sMergedSet = null;
+ private static ResourceMerger sResourceMerger = null;
public void testMergeByCount() throws Exception {
- ResourceSet mergedSet = getMergedSet();
+ ResourceMerger merger = getResourceMerger();
- assertEquals(25, mergedSet.getSize());
+ assertEquals(25, merger.size());
}
public void testMergedResourcesByName() throws Exception {
- ResourceSet mergedSet = getMergedSet();
+ ResourceMerger merger = getResourceMerger();
- verifyResources(mergedSet,
+ verifyResourceExists(merger,
"drawable/icon",
"drawable-ldpi/icon",
"drawable/icon2",
@@ -64,73 +76,712 @@ public class ResourceMergerTest extends BaseTestCase {
}
public void testReplacedLayout() throws Exception {
- ResourceSet mergedSet = getMergedSet();
+ ResourceMerger merger = getResourceMerger();
+ ListMultimap<String, Resource> mergedMap = merger.getResourceMap();
+
+ List<Resource> values = mergedMap.get("layout/main");
+
+ // the overlay means there's 2 versions of this resource.
+ assertEquals(2, values.size());
+ Resource mainLayout = values.get(1);
- Resource mainLayout = mergedSet.getResourceMap().get("layout/main");
ResourceFile sourceFile = mainLayout.getSource();
assertTrue(sourceFile.getFile().getAbsolutePath().endsWith("overlay/layout/main.xml"));
}
public void testReplacedAlias() throws Exception {
- ResourceSet mergedSet = getMergedSet();
+ ResourceMerger merger = getResourceMerger();
+ ListMultimap<String, Resource> mergedMap = merger.getResourceMap();
+
+
+ List<Resource> values = mergedMap.get("layout/alias_replaced_by_file");
+
+ // the overlay means there's 2 versions of this resource.
+ assertEquals(2, values.size());
+ Resource layout = values.get(1);
- Resource layout = mergedSet.getResourceMap().get("layout/alias_replaced_by_file");
// since it's replaced by a file, there's no node.
assertNull(layout.getValue());
}
public void testReplacedFile() throws Exception {
- ResourceSet mergedSet = getMergedSet();
+ ResourceMerger merger = getResourceMerger();
+ ListMultimap<String, Resource> mergedMap = merger.getResourceMap();
+
+ List<Resource> values = mergedMap.get("layout/file_replaced_by_alias");
+
+ // the overlay means there's 2 versions of this resource.
+ assertEquals(2, values.size());
+ Resource layout = values.get(1);
- Resource layout = mergedSet.getResourceMap().get("layout/file_replaced_by_alias");
// since it's replaced by a file, there's no node.
assertNotNull(layout.getValue());
}
public void testMergeWrite() throws Exception {
- ResourceSet mergedSet = getMergedSet();
+ ResourceMerger merger = getResourceMerger();
- File folder = getWrittenSet();
+ File folder = getWrittenResources();
- ResourceSet writtenSet = new ResourceSet();
+ ResourceSet writtenSet = new ResourceSet("unused");
writtenSet.addSource(folder);
+ writtenSet.loadFromFiles();
- // compare the two sets.
- assertEquals(mergedSet.getSize(), writtenSet.getSize());
+ // compare the two maps, but not using the full map as the set loaded from the output
+ // won't contains all versions of each Resource item.
+ compareResourceMaps(merger, writtenSet, false /*full compare*/);
+ }
- // compare the resources are all the same
- Map<String, Resource> map = writtenSet.getResourceMap();
- for (Resource item : mergedSet.getResources()) {
- assertNotNull(map.get(item.getKey()));
+ public void testMergeBlob() throws Exception {
+ ResourceMerger merger = getResourceMerger();
+
+ File folder = Files.createTempDir();
+ merger.writeBlobTo(folder);
+
+ ResourceMerger loadedMerger = new ResourceMerger();
+ loadedMerger.loadFromBlob(folder);
+
+ compareResourceMaps(merger, loadedMerger, true /*full compare*/);
+ }
+
+ /**
+ * Tests the path replacement in the merger.xml file loaded from testData/
+ * @throws Exception
+ */
+ public void testLoadingTestPathReplacement() throws Exception {
+ File root = getRoot("baseMerge");
+ File fakeRoot = getMergedBlobFolder(root);
+
+ ResourceMerger resourceMerger = new ResourceMerger();
+ resourceMerger.loadFromBlob(fakeRoot);
+
+ List<ResourceSet> sets = resourceMerger.getResourceSets();
+ for (ResourceSet set : sets) {
+ List<File> sourceFiles = set.getSourceFiles();
+
+ // there should only be one
+ assertEquals(1, sourceFiles.size());
+
+ File sourceFile = sourceFiles.get(0);
+ assertTrue(String.format("File %s is located in %s", sourceFile, root),
+ sourceFile.getAbsolutePath().startsWith(root.getAbsolutePath()));
}
}
- private static ResourceSet getMergedSet() throws DuplicateResourceException {
- if (sMergedSet == null) {
+ public void testUpdateWithBasicFiles() throws Exception {
+ File root = getIncMergeRoot("basicFiles");
+ File fakeRoot = getMergedBlobFolder(root);
+ ResourceMerger resourceMerger = new ResourceMerger();
+ resourceMerger.loadFromBlob(fakeRoot);
+
+ List<ResourceSet> sets = resourceMerger.getResourceSets();
+ assertEquals(2, sets.size());
+
+ // ----------------
+ // first set is the main one, no change here
+ ResourceSet mainSet = sets.get(0);
+ File mainBase = new File(root, "main");
+ File mainDrawable = new File(mainBase, "drawable");
+ File mainDrawableLdpi = new File(mainBase, "drawable-ldpi");
+
+ // touched/removed files:
+ File mainDrawableTouched = new File(mainDrawable, "touched.png");
+ mainSet.updateWith(mainBase, mainDrawableTouched, FileStatus.CHANGED);
+
+ File mainDrawableRemoved = new File(mainDrawable, "removed.png");
+ mainSet.updateWith(mainBase, mainDrawableRemoved, FileStatus.REMOVED);
+
+ File mainDrawableLdpiRemoved = new File(mainDrawableLdpi, "removed.png");
+ mainSet.updateWith(mainBase, mainDrawableLdpiRemoved, FileStatus.REMOVED);
+
+ // ----------------
+ // second set is the overlay one
+ ResourceSet overlaySet = sets.get(1);
+ File overlayBase = new File(root, "overlay");
+ File overlayDrawable = new File(overlayBase, "drawable");
+ File overlayDrawableHdpi = new File(overlayBase, "drawable-hdpi");
+
+ // new/removed files:
+ File overlayDrawableNewOverlay = new File(overlayDrawable, "new_overlay.png");
+ overlaySet.updateWith(overlayBase, overlayDrawableNewOverlay, FileStatus.NEW);
+
+ File overlayDrawableRemovedOverlay = new File(overlayDrawable, "removed_overlay.png");
+ overlaySet.updateWith(overlayBase, overlayDrawableRemovedOverlay, FileStatus.REMOVED);
+
+ File overlayDrawableHdpiNewAlternate = new File(overlayDrawableHdpi, "new_alternate.png");
+ overlaySet.updateWith(overlayBase, overlayDrawableHdpiNewAlternate, FileStatus.NEW);
+
+ // validate for duplicates
+ resourceMerger.validateResourceSets();
+
+ // check the content.
+ ListMultimap<String, Resource> mergedMap = resourceMerger.getResourceMap();
+
+ // check unchanged file is WRITTEN
+ List<Resource> drawableUntouched = mergedMap.get("drawable/untouched");
+ assertEquals(1, drawableUntouched.size());
+ assertTrue(drawableUntouched.get(0).isWritten());
+ assertFalse(drawableUntouched.get(0).isTouched());
+ assertFalse(drawableUntouched.get(0).isRemoved());
+
+ // check replaced file is TOUCHED
+ List<Resource> drawableTouched = mergedMap.get("drawable/touched");
+ assertEquals(1, drawableTouched.size());
+ assertTrue(drawableTouched.get(0).isWritten());
+ assertTrue(drawableTouched.get(0).isTouched());
+ assertFalse(drawableTouched.get(0).isRemoved());
+
+ // check removed file is REMOVED
+ List<Resource> drawableRemoved = mergedMap.get("drawable/removed");
+ assertEquals(1, drawableRemoved.size());
+ assertTrue(drawableRemoved.get(0).isWritten());
+ assertTrue(drawableRemoved.get(0).isRemoved());
+
+ // check new overlay: two objects, last one is TOUCHED
+ List<Resource> drawableNewOverlay = mergedMap.get("drawable/new_overlay");
+ assertEquals(2, drawableNewOverlay.size());
+ Resource newOverlay = drawableNewOverlay.get(1);
+ assertEquals(overlayDrawableNewOverlay, newOverlay.getSource().getFile());
+ assertFalse(newOverlay.isWritten());
+ assertTrue(newOverlay.isTouched());
+
+ // check new alternate: one objects, last one is TOUCHED
+ List<Resource> drawableHdpiNewAlternate = mergedMap.get("drawable-hdpi/new_alternate");
+ assertEquals(1, drawableHdpiNewAlternate.size());
+ Resource newAlternate = drawableHdpiNewAlternate.get(0);
+ assertEquals(overlayDrawableHdpiNewAlternate, newAlternate.getSource().getFile());
+ assertFalse(newAlternate.isWritten());
+ assertTrue(newAlternate.isTouched());
+
+ // write and check the result of writeResourceFolder
+ // copy the current resOut which serves as pre incremental update state.
+ File resFolder = getFolderCopy(new File(root, "resOut"));
+
+ // write the content of the resource merger.
+ resourceMerger.writeResourceFolder(resFolder);
+
+ // Check the content.
+ checkImageColor(new File(resFolder, "drawable" + File.separator + "touched.png"),
+ (int) 0xFF00FF00);
+ checkImageColor(new File(resFolder, "drawable" + File.separator + "untouched.png"),
+ (int) 0xFF00FF00);
+ checkImageColor(new File(resFolder, "drawable" + File.separator + "new_overlay.png"),
+ (int) 0xFF00FF00);
+ checkImageColor(new File(resFolder, "drawable" + File.separator + "removed_overlay.png"),
+ (int) 0xFF00FF00);
+ checkImageColor(new File(resFolder, "drawable-hdpi" + File.separator + "new_alternate.png"),
+ (int) 0xFF00FF00);
+ assertFalse(new File(resFolder, "drawable-ldpi" + File.separator + "removed.png").isFile());
+ }
+
+ public void testUpdateWithBasicValues() throws Exception {
+ File root = getIncMergeRoot("basicValues");
+ File fakeRoot = getMergedBlobFolder(root);
+ ResourceMerger resourceMerger = new ResourceMerger();
+ resourceMerger.loadFromBlob(fakeRoot);
+
+ List<ResourceSet> sets = resourceMerger.getResourceSets();
+ assertEquals(2, sets.size());
+
+ // ----------------
+ // first set is the main one, no change here
+ ResourceSet mainSet = sets.get(0);
+ File mainBase = new File(root, "main");
+ File mainValues = new File(mainBase, "values");
+ File mainValuesEn = new File(mainBase, "values-en");
+
+ // touched file:
+ File mainValuesTouched = new File(mainValues, "values.xml");
+ mainSet.updateWith(mainBase, mainValuesTouched, FileStatus.CHANGED);
+
+ // removed files
+ File mainValuesEnRemoved = new File(mainValuesEn, "values.xml");
+ mainSet.updateWith(mainBase, mainValuesEnRemoved, FileStatus.REMOVED);
+
+ // ----------------
+ // second set is the overlay one
+ ResourceSet overlaySet = sets.get(1);
+ File overlayBase = new File(root, "overlay");
+ File overlayValues = new File(overlayBase, "values");
+ File overlayValuesFr = new File(overlayBase, "values-fr");
+
+ // new files:
+ File overlayValuesNew = new File(overlayValues, "values.xml");
+ overlaySet.updateWith(overlayBase, overlayValuesNew, FileStatus.NEW);
+ File overlayValuesFrNew = new File(overlayValuesFr, "values.xml");
+ overlaySet.updateWith(overlayBase, overlayValuesFrNew, FileStatus.NEW);
+
+ // validate for duplicates
+ resourceMerger.validateResourceSets();
+
+ // check the content.
+ ListMultimap<String, Resource> mergedMap = resourceMerger.getResourceMap();
+
+ // check unchanged string is WRITTEN
+ List<Resource> valuesUntouched = mergedMap.get("string/untouched");
+ assertEquals(1, valuesUntouched.size());
+ assertTrue(valuesUntouched.get(0).isWritten());
+ assertFalse(valuesUntouched.get(0).isTouched());
+ assertFalse(valuesUntouched.get(0).isRemoved());
+
+ // check replaced file is TOUCHED
+ List<Resource> valuesTouched = mergedMap.get("string/touched");
+ assertEquals(1, valuesTouched.size());
+ assertTrue(valuesTouched.get(0).isWritten());
+ assertTrue(valuesTouched.get(0).isTouched());
+ assertFalse(valuesTouched.get(0).isRemoved());
+
+ // check removed file is REMOVED
+ List<Resource> valuesRemoved = mergedMap.get("string/removed");
+ assertEquals(1, valuesRemoved.size());
+ assertTrue(valuesRemoved.get(0).isWritten());
+ assertTrue(valuesRemoved.get(0).isRemoved());
+
+ valuesRemoved = mergedMap.get("string-en/removed");
+ assertEquals(1, valuesRemoved.size());
+ assertTrue(valuesRemoved.get(0).isWritten());
+ assertTrue(valuesRemoved.get(0).isRemoved());
+
+ // check new overlay: two objects, last one is TOUCHED
+ List<Resource> valuesNewOverlay = mergedMap.get("string/new_overlay");
+ assertEquals(2, valuesNewOverlay.size());
+ Resource newOverlay = valuesNewOverlay.get(1);
+ assertFalse(newOverlay.isWritten());
+ assertTrue(newOverlay.isTouched());
+
+ // check new alternate: one objects, last one is TOUCHED
+ List<Resource> valuesFrNewAlternate = mergedMap.get("string-fr/new_alternate");
+ assertEquals(1, valuesFrNewAlternate.size());
+ Resource newAlternate = valuesFrNewAlternate.get(0);
+ assertFalse(newAlternate.isWritten());
+ assertTrue(newAlternate.isTouched());
+
+ // write and check the result of writeResourceFolder
+ // copy the current resOut which serves as pre incremental update state.
+ File resFolder = getFolderCopy(new File(root, "resOut"));
+
+ // write the content of the resource merger.
+ resourceMerger.writeResourceFolder(resFolder);
+
+ // Check the content.
+ // values/values.xml
+ Map<String, String> map = quickStringOnlyValueFileParser(
+ new File(resFolder, "values" + File.separator + "values.xml"));
+ assertEquals("untouched", map.get("untouched"));
+ assertEquals("touched", map.get("touched"));
+ assertEquals("new_overlay", map.get("new_overlay"));
+
+ // values/values-fr.xml
+ map = quickStringOnlyValueFileParser(
+ new File(resFolder, "values-fr" + File.separator + "values.xml"));
+ assertEquals("new_alternate", map.get("new_alternate"));
+
+ // deleted values-en/values.xml
+ assertFalse(new File(resFolder, "values-en" + File.separator + "values.xml").isFile());
+ }
+
+ public void testUpdateWithBasicValues2() throws Exception {
+ File root = getIncMergeRoot("basicValues2");
+ File fakeRoot = getMergedBlobFolder(root);
+ ResourceMerger resourceMerger = new ResourceMerger();
+ resourceMerger.loadFromBlob(fakeRoot);
+
+ List<ResourceSet> sets = resourceMerger.getResourceSets();
+ assertEquals(2, sets.size());
+
+ // ----------------
+ // first set is the main one, no change here
+ ResourceSet mainSet = sets.get(0);
+ File mainBase = new File(root, "main");
+ File mainValues = new File(mainBase, "values");
+
+ // ----------------
+ // second set is the overlay one
+ ResourceSet overlaySet = sets.get(1);
+ File overlayBase = new File(root, "overlay");
+ File overlayValues = new File(overlayBase, "values");
+
+ // new files:
+ File overlayValuesNew = new File(overlayValues, "values.xml");
+ overlaySet.updateWith(overlayBase, overlayValuesNew, FileStatus.REMOVED);
+
+ // validate for duplicates
+ resourceMerger.validateResourceSets();
+
+ // check the content.
+ ListMultimap<String, Resource> mergedMap = resourceMerger.getResourceMap();
+
+ // check unchanged string is WRITTEN
+ List<Resource> valuesUntouched = mergedMap.get("string/untouched");
+ assertEquals(1, valuesUntouched.size());
+ assertTrue(valuesUntouched.get(0).isWritten());
+ assertFalse(valuesUntouched.get(0).isTouched());
+ assertFalse(valuesUntouched.get(0).isRemoved());
+
+ // check removed_overlay is present twice.
+ List<Resource> valuesRemovedOverlay = mergedMap.get("string/removed_overlay");
+ assertEquals(2, valuesRemovedOverlay.size());
+ // first is untouched
+ assertFalse(valuesRemovedOverlay.get(0).isWritten());
+ assertFalse(valuesRemovedOverlay.get(0).isTouched());
+ assertFalse(valuesRemovedOverlay.get(0).isRemoved());
+ // other is removed
+ assertTrue(valuesRemovedOverlay.get(1).isWritten());
+ assertFalse(valuesRemovedOverlay.get(1).isTouched());
+ assertTrue(valuesRemovedOverlay.get(1).isRemoved());
+
+ // write and check the result of writeResourceFolder
+ // copy the current resOut which serves as pre incremental update state.
+ File resFolder = getFolderCopy(new File(root, "resOut"));
+
+ // write the content of the resource merger.
+ resourceMerger.writeResourceFolder(resFolder);
+
+ // Check the content.
+ // values/values.xml
+ Map<String, String> map = quickStringOnlyValueFileParser(
+ new File(resFolder, "values" + File.separator + "values.xml"));
+ assertEquals("untouched", map.get("untouched"));
+ assertEquals("untouched", map.get("removed_overlay"));
+ }
+
+ public void testUpdateWithFilesVsValues() throws Exception {
+ File root = getIncMergeRoot("filesVsValues");
+ File fakeRoot = getMergedBlobFolder(root);
+ ResourceMerger resourceMerger = new ResourceMerger();
+ resourceMerger.loadFromBlob(fakeRoot);
+
+ List<ResourceSet> sets = resourceMerger.getResourceSets();
+ assertEquals(1, sets.size());
+
+ // ----------------
+ // Load the main set
+ ResourceSet mainSet = sets.get(0);
+ File mainBase = new File(root, "main");
+ File mainValues = new File(mainBase, ResourceFolderType.VALUES.getName());
+ File mainLayout = new File(mainBase, ResourceFolderType.LAYOUT.getName());
+
+ // touched file:
+ File mainValuesTouched = new File(mainValues, "values.xml");
+ mainSet.updateWith(mainBase, mainValuesTouched, FileStatus.CHANGED);
+
+ // new file:
+ File mainLayoutNew = new File(mainLayout, "alias_replaced_by_file.xml");
+ mainSet.updateWith(mainBase, mainLayoutNew, FileStatus.NEW);
+
+ // removed file
+ File mainLayoutRemoved = new File(mainLayout, "file_replaced_by_alias.xml");
+ mainSet.updateWith(mainBase, mainLayoutRemoved, FileStatus.REMOVED);
+
+ // validate for duplicates
+ resourceMerger.validateResourceSets();
+
+ // check the content.
+ ListMultimap<String, Resource> mergedMap = resourceMerger.getResourceMap();
+
+ // check layout/main is unchanged
+ List<Resource> layoutMain = mergedMap.get("layout/main");
+ assertEquals(1, layoutMain.size());
+ assertTrue(layoutMain.get(0).isWritten());
+ assertFalse(layoutMain.get(0).isTouched());
+ assertFalse(layoutMain.get(0).isRemoved());
+
+ // check file_replaced_by_alias has 2 version, 2nd is TOUCHED, and contains a Node
+ List<Resource> layoutReplacedByAlias = mergedMap.get("layout/file_replaced_by_alias");
+ assertEquals(2, layoutReplacedByAlias.size());
+ // 1st one is removed version, as it already existed in the item multimap
+ Resource replacedByAlias = layoutReplacedByAlias.get(0);
+ assertTrue(replacedByAlias.isWritten());
+ assertFalse(replacedByAlias.isTouched());
+ assertTrue(replacedByAlias.isRemoved());
+ assertNull(replacedByAlias.getValue());
+ assertEquals("file_replaced_by_alias.xml", replacedByAlias.getSource().getFile().getName());
+ // 2nd version is the new one
+ replacedByAlias = layoutReplacedByAlias.get(1);
+ assertFalse(replacedByAlias.isWritten());
+ assertTrue(replacedByAlias.isTouched());
+ assertFalse(replacedByAlias.isRemoved());
+ assertNotNull(replacedByAlias.getValue());
+ assertEquals("values.xml", replacedByAlias.getSource().getFile().getName());
+
+ // check alias_replaced_by_file has 2 version, 2nd is TOUCHED, and contains a Node
+ List<Resource> layoutReplacedByFile = mergedMap.get("layout/alias_replaced_by_file");
+ // 1st one is removed version, as it already existed in the item multimap
+ assertEquals(2, layoutReplacedByFile.size());
+ Resource replacedByFile = layoutReplacedByFile.get(0);
+ assertTrue(replacedByFile.isWritten());
+ assertFalse(replacedByFile.isTouched());
+ assertTrue(replacedByFile.isRemoved());
+ assertNotNull(replacedByFile.getValue());
+ assertEquals("values.xml", replacedByFile.getSource().getFile().getName());
+ // 2nd version is the new one
+ replacedByFile = layoutReplacedByFile.get(1);
+ assertFalse(replacedByFile.isWritten());
+ assertTrue(replacedByFile.isTouched());
+ assertFalse(replacedByFile.isRemoved());
+ assertNull(replacedByFile.getValue());
+ assertEquals("alias_replaced_by_file.xml", replacedByFile.getSource().getFile().getName());
+
+ // write and check the result of writeResourceFolder
+ // copy the current resOut which serves as pre incremental update state.
+ File resFolder = getFolderCopy(new File(root, "resOut"));
+
+ // write the content of the resource merger.
+ resourceMerger.writeResourceFolder(resFolder);
+
+ // deleted layout/file_replaced_by_alias.xml
+ assertFalse(new File(resFolder, "layout" + File.separator + "file_replaced_by_alias.xml")
+ .isFile());
+ // new file layout/alias_replaced_by_file.xml
+ assertTrue(new File(resFolder, "layout" + File.separator + "alias_replaced_by_file.xml")
+ .isFile());
+
+ // quick load of the values file
+ File valuesFile = new File(resFolder, "values" + File.separator + "values.xml");
+ assertTrue(valuesFile.isFile());
+ String content = Files.toString(valuesFile, Charsets.UTF_8);
+ assertTrue(content.contains("name=\"file_replaced_by_alias\""));
+ assertFalse(content.contains("name=\"alias_replaced_by_file\""));
+ }
+
+ public void testCheckValidUpdate() throws Exception {
+ // first merger
+ ResourceMerger merger1 = createMerger(new String[][] {
+ new String[] { "main", "/main/res1", "/main/res2" },
+ new String[] { "overlay", "/overlay/res1", "/overlay/res2" },
+ });
+
+ // 2nd merger with different order source files in sets.
+ ResourceMerger merger2 = createMerger(new String[][] {
+ new String[] { "main", "/main/res2", "/main/res1" },
+ new String[] { "overlay", "/overlay/res1", "/overlay/res2" },
+ });
+
+ assertTrue(merger1.checkValidUpdate(merger2.getResourceSets()));
+
+ // write merger1 on disk to test writing empty ResourceSets.
+ File folder = Files.createTempDir();
+ merger1.writeBlobTo(folder);
+
+ // reload it
+ ResourceMerger loadedMerger = new ResourceMerger();
+ loadedMerger.loadFromBlob(folder);
+
+ assertTrue(loadedMerger.checkValidUpdate(merger1.getResourceSets()));
+ }
+
+ public void testCheckValidUpdateFail() throws Exception {
+ // Test with removed overlay
+ ResourceMerger merger1 = createMerger(new String[][] {
+ new String[] { "main", "/main/res1", "/main/res2" },
+ new String[] { "overlay", "/overlay/res1", "/overlay/res2" },
+ });
+
+ // 2nd merger with different order source files in sets.
+ ResourceMerger merger2 = createMerger(new String[][] {
+ new String[] { "main", "/main/res2", "/main/res1" },
+ });
+
+ assertFalse(merger1.checkValidUpdate(merger2.getResourceSets()));
+
+ // Test with different overlays
+ merger1 = createMerger(new String[][] {
+ new String[] { "main", "/main/res1", "/main/res2" },
+ new String[] { "overlay", "/overlay/res1", "/overlay/res2" },
+ });
+
+ // 2nd merger with different order source files in sets.
+ merger2 = createMerger(new String[][] {
+ new String[] { "main", "/main/res2", "/main/res1" },
+ new String[] { "overlay2", "/overlay2/res1", "/overlay2/res2" },
+ });
+
+ assertFalse(merger1.checkValidUpdate(merger2.getResourceSets()));
+
+ // Test with different overlays
+ merger1 = createMerger(new String[][] {
+ new String[] { "main", "/main/res1", "/main/res2" },
+ new String[] { "overlay1", "/overlay1/res1", "/overlay1/res2" },
+ new String[] { "overlay2", "/overlay2/res1", "/overlay2/res2" },
+ });
+
+ // 2nd merger with different order source files in sets.
+ merger2 = createMerger(new String[][] {
+ new String[] { "main", "/main/res2", "/main/res1" },
+ new String[] { "overlay2", "/overlay2/res1", "/overlay2/res2" },
+ new String[] { "overlay1", "/overlay1/res1", "/overlay1/res2" },
+ });
+
+ assertFalse(merger1.checkValidUpdate(merger2.getResourceSets()));
+
+ // Test with different source files
+ merger1 = createMerger(new String[][] {
+ new String[] { "main", "/main/res1", "/main/res2" },
+ });
+
+ // 2nd merger with different order source files in sets.
+ merger2 = createMerger(new String[][] {
+ new String[] { "main", "/main/res1" },
+ });
+
+ assertFalse(merger1.checkValidUpdate(merger2.getResourceSets()));
+ }
+
+ private static ResourceMerger createMerger(String[][] data) {
+ ResourceMerger merger = new ResourceMerger();
+ for (String[] setData : data) {
+ ResourceSet set = new ResourceSet(setData[0]);
+ merger.addResourceSet(set);
+ for (int i = 1, n = setData.length; i < n; i++) {
+ set.addSource(new File(setData[i]));
+ }
+ }
+
+ return merger;
+ }
+
+ private static ResourceMerger getResourceMerger()
+ throws DuplicateResourceException, IOException {
+ if (sResourceMerger == null) {
File root = getRoot("baseMerge");
ResourceSet res = ResourceSetTest.getBaseResourceSet();
- ResourceSet overlay = new ResourceSet();
+ ResourceSet overlay = new ResourceSet("overlay");
overlay.addSource(new File(root, "overlay"));
+ overlay.loadFromFiles();
- ResourceMerger merger = new ResourceMerger();
- merger.addResourceSet(res);
- merger.addResourceSet(overlay);
-
- sMergedSet = merger.getMergedSet();
+ sResourceMerger = new ResourceMerger();
+ sResourceMerger.addResourceSet(res);
+ sResourceMerger.addResourceSet(overlay);
}
- return sMergedSet;
+ return sResourceMerger;
}
- private static File getWrittenSet() throws DuplicateResourceException, IOException {
- ResourceSet mergedSet = getMergedSet();
+ private static File getWrittenResources() throws DuplicateResourceException, IOException {
+ ResourceMerger resourceMerger = getResourceMerger();
File folder = Files.createTempDir();
- mergedSet.writeTo(folder);
+ resourceMerger.writeResourceFolder(folder);
return folder;
}
+
+ /**
+ * Returns a folder containing a merger blob data for the given test data folder.
+ *
+ * This is to work around the fact that the merger blob data contains full path, but we don't
+ * know where this project is located on the drive. This rewrites the blob to contain the
+ * actual folder.
+ * (The blobs written in the test data contains placeholders for the path root and path
+ * separators)
+ *
+ * @param folder
+ * @return
+ * @throws IOException
+ */
+ private static File getMergedBlobFolder(File folder) throws IOException {
+ File originalMerger = new File(folder, ResourceMerger.FN_MERGER_XML);
+
+ String content = Files.toString(originalMerger, Charsets.UTF_8);
+
+ // search and replace $TOP$ with the root
+ content = content.replaceAll(
+ "\\$TOP\\$", folder.getAbsolutePath()).replaceAll("\\$SEP\\$", File.separator);
+
+ File tempFolder = Files.createTempDir();
+ Files.write(content, new File(tempFolder, ResourceMerger.FN_MERGER_XML), Charsets.UTF_8);
+
+ return tempFolder;
+ }
+
+ private File getIncMergeRoot(String name) throws IOException {
+ File root = getCanonicalRoot("incMergeData");
+ return new File(root, name);
+ }
+
+ private static File getFolderCopy(File folder) throws IOException {
+ File dest = Files.createTempDir();
+ copyFolder(folder, dest);
+ return dest;
+ }
+
+ private static void copyFolder(File from, File to) throws IOException {
+ if (from.isFile()) {
+ Files.copy(from, to);
+ } else if (from.isDirectory()) {
+ if (!to.exists()) {
+ to.mkdirs();
+ }
+
+ File[] children = from.listFiles();
+ if (children != null) {
+ for (File f : children) {
+ copyFolder(f, new File(to, f.getName()));
+ }
+ }
+ }
+ }
+
+ private static void checkImageColor(File file, int expectedColor) throws IOException {
+ assertTrue("File '" + file.getAbsolutePath() + "' does not exist.", file.isFile());
+
+ BufferedImage image = ImageIO.read(file);
+ int rgb = image.getRGB(0, 0);
+ assertEquals(String.format("Expected: 0x%08X, actual: 0x%08X for file %s",
+ expectedColor, rgb, file),
+ expectedColor, rgb);
+ }
+
+ private static Map<String, String> quickStringOnlyValueFileParser(File file)
+ throws IOException {
+ Map<String, String> result = Maps.newHashMap();
+
+ Document document = ValueResourceParser.parseDocument(file);
+
+ // get the root node
+ Node rootNode = document.getDocumentElement();
+ if (rootNode == null) {
+ return Collections.emptyMap();
+ }
+
+ NodeList nodes = rootNode.getChildNodes();
+
+ for (int i = 0, n = nodes.getLength(); i < n; i++) {
+ Node node = nodes.item(i);
+
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ continue;
+ }
+
+ ResourceType type = ValueResourceParser.getType(node);
+ if (type != ResourceType.STRING) {
+ throw new IllegalArgumentException("Only String resources supported.");
+ }
+ String name = ValueResourceParser.getName(node);
+
+ String value = null;
+
+ NodeList nodeList = node.getChildNodes();
+ nodeLoop: for (int ii = 0, nn = nodes.getLength(); ii < nn; ii++) {
+ Node subNode = nodeList.item(ii);
+
+ switch (subNode.getNodeType()) {
+ case Node.COMMENT_NODE:
+ break;
+ case Node.TEXT_NODE:
+ value = subNode.getNodeValue().trim(); // TODO: remove trim.
+ break nodeLoop;
+ case Node.ELEMENT_NODE:
+ break;
+ }
+ }
+
+ result.put(name, value != null ? value : "");
+ }
+
+ return result;
+ }
}
diff --git a/builder/src/test/java/com/android/builder/resources/ResourceSetTest.java b/builder/src/test/java/com/android/builder/resources/ResourceSetTest.java
index bcc7b88..9c0efa1 100644
--- a/builder/src/test/java/com/android/builder/resources/ResourceSetTest.java
+++ b/builder/src/test/java/com/android/builder/resources/ResourceSetTest.java
@@ -17,6 +17,7 @@
package com.android.builder.resources;
import java.io.File;
+import java.io.IOException;
public class ResourceSetTest extends BaseTestCase {
@@ -24,13 +25,13 @@ public class ResourceSetTest extends BaseTestCase {
public void testBaseResourceSetByCount() throws Exception {
ResourceSet resourceSet = getBaseResourceSet();
- assertEquals(23, resourceSet.getSize());
+ assertEquals(23, resourceSet.size());
}
public void testBaseResourceSetByName() throws Exception {
ResourceSet resourceSet = getBaseResourceSet();
- verifyResources(resourceSet,
+ verifyResourceExists(resourceSet,
"drawable/icon",
"drawable/patch",
"raw/foo",
@@ -60,11 +61,12 @@ public class ResourceSetTest extends BaseTestCase {
public void testDupResourceSet() throws Exception {
File root = getRoot("dupResourceSet");
- ResourceSet set = new ResourceSet();
+ ResourceSet set = new ResourceSet("main");
set.addSource(new File(root, "res1"));
+ set.addSource(new File(root, "res2"));
boolean gotException = false;
try {
- set.addSource(new File(root, "res2"));
+ set.loadFromFiles();
} catch (DuplicateResourceException e) {
gotException = true;
}
@@ -72,12 +74,13 @@ public class ResourceSetTest extends BaseTestCase {
assertTrue(gotException);
}
- static ResourceSet getBaseResourceSet() throws DuplicateResourceException {
+ static ResourceSet getBaseResourceSet() throws DuplicateResourceException, IOException {
if (sBaseResourceSet == null) {
File root = getRoot("baseResourceSet");
- sBaseResourceSet = new ResourceSet();
+ sBaseResourceSet = new ResourceSet("main");
sBaseResourceSet.addSource(root);
+ sBaseResourceSet.loadFromFiles();
}
return sBaseResourceSet;
diff --git a/builder/src/test/java/com/android/builder/resources/ValueResourceParserTest.java b/builder/src/test/java/com/android/builder/resources/ValueResourceParserTest.java
index dbd31a5..022b5d7 100644
--- a/builder/src/test/java/com/android/builder/resources/ValueResourceParserTest.java
+++ b/builder/src/test/java/com/android/builder/resources/ValueResourceParserTest.java
@@ -19,7 +19,7 @@ package com.android.builder.resources;
import com.google.common.collect.Maps;
import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
@@ -37,11 +37,9 @@ public class ValueResourceParserTest extends BaseTestCase {
public void testParsedResourcesByName() throws Exception {
List<Resource> resources = getParsedResources();
-
- // convert to a map
- Map<String, Resource> map = Maps.newHashMapWithExpectedSize(resources.size());
- for (Resource r : resources) {
- map.put(r.getKey(), r);
+ Map<String, Resource> resourceMap = Maps.newHashMapWithExpectedSize(resources.size());
+ for (Resource item : resources) {
+ resourceMap.put(item.getKey(), item);
}
String[] resourceNames = new String[] {
@@ -65,11 +63,11 @@ public class ValueResourceParserTest extends BaseTestCase {
};
for (String name : resourceNames) {
- assertNotNull(name, map.get(name));
+ assertNotNull(name, resourceMap.get(name));
}
}
- private static List<Resource> getParsedResources() throws FileNotFoundException {
+ private static List<Resource> getParsedResources() throws IOException {
if (sResources == null) {
File root = getRoot("baseResourceSet");
File values = new File(root, "values");
@@ -77,6 +75,9 @@ public class ValueResourceParserTest extends BaseTestCase {
ValueResourceParser parser = new ValueResourceParser(valuesXml);
sResources = parser.parseFile();
+
+ // create a fake resource file to allow calling Resource.getKey()
+ new ResourceFile(valuesXml, sResources, "");
}
return sResources;
diff --git a/builder/src/test/resources/testData/baseMerge/merger.xml b/builder/src/test/resources/testData/baseMerge/merger.xml
new file mode 100644
index 0000000..18613c4
--- /dev/null
+++ b/builder/src/test/resources/testData/baseMerge/merger.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merger xmlns:ns1="urn:oasis:names:tc:xliff:document:1.2">
+ <resourceSet config="main">
+ <source path="$TOP$$SEP$baseResourceSet">
+ <file name="icon" path="$TOP$$SEP$baseResourceSet$SEP$drawable$SEP$icon.png" qualifiers="" type="drawable"/>
+ <file name="patch" path="$TOP$$SEP$baseResourceSet$SEP$drawable$SEP$patch.9.png" qualifiers="" type="drawable"/>
+ <file name="file_replaced_by_alias" path="$TOP$$SEP$baseResourceSet$SEP$layout$SEP$file_replaced_by_alias.xml" qualifiers="" type="layout"/>
+ <file name="main" path="$TOP$$SEP$baseResourceSet$SEP$layout$SEP$main.xml" qualifiers="" type="layout"/>
+ <file name="foo" path="$TOP$$SEP$baseResourceSet$SEP$raw$SEP$foo.dat" qualifiers="" type="raw"/>
+ <file path="$TOP$$SEP$baseResourceSet$SEP$values$SEP$values.xml" qualifiers="">
+ <dimen name="dimen">164dp</dimen>
+ <integer name="integer">75</integer>
+ <color name="color">#00000000</color>
+ <drawable name="color_drawable">#ffffffff</drawable>
+ <declare-styleable name="declare_styleable">
+
+ <!-- ============== -->
+ <!-- Generic styles -->
+ <!-- ============== -->
+ <eat-comment/>
+
+ <!-- Default color of foreground imagery. -->
+ <attr format="color" name="blah"/>
+
+ <!-- Default color of foreground imagery on an inverted background. -->
+ <attr name="android:colorForegroundInverse"/>
+
+ </declare-styleable>
+ <style name="style">
+ <item name="android:singleLine">true</item>
+ <item name="android:textAppearance">@style$SEP$TextAppearance.WindowTitle</item>
+ <item name="android:shadowColor">#BB000000</item>
+ <item name="android:shadowRadius">2.75</item>
+ </style>
+ <string name="styled_string">Forgot your username or password\?\nVisit<b>google.com$SEP$accounts$SEP$recovery</b>.</string>
+ <attr format="dimension" name="dimen_attr"/>
+ <string-array name="string_array" translatable="false">
+ <item/>
+ <!-- 0 -->
+ <item/>
+ <!-- 1 -->
+ <item>ABC</item>
+ <!-- 2 -->
+ <item>DEF</item>
+ <!-- 3 -->
+ <item>GHI</item>
+ <!-- 4 -->
+ <item>JKL</item>
+ <!-- 5 -->
+ <item>MNO</item>
+ <!-- 6 -->
+ <item>PQRS</item>
+ <!-- 7 -->
+ <item>TUV</item>
+ <!-- 8 -->
+ <item>WXYZ</item>
+ <!-- 9 -->
+ </string-array>
+ <item name="alias_replaced_by_file" type="layout">@layout$SEP$ref </item>
+ <string name="basic_string">basic_string</string>
+ <string name="xliff_string"><ns1:g example="123" id="number">%1$s</ns1:g><ns1:g example="KB" id="unit">%2$s</ns1:g></string>
+ <attr name="enum_attr">
+ <enum name="normal" value="0"/>
+ <enum name="sans" value="1"/>
+ <enum name="serif" value="2"/>
+ <enum name="monospace" value="3"/>
+ </attr>
+ <item name="item_id" type="id"/>
+ <item name="layout_ref" type="layout">@layout$SEP$ref</item>
+ <drawable name="drawable_ref">@drawable$SEP$stat_notify_sync_anim0</drawable>
+ <attr format="string" name="string_attr"/>
+ <attr name="flag_attr">
+ <flag name="normal" value="0"/>
+ <flag name="bold" value="1"/>
+ <flag name="italic" value="2"/>
+ </attr>
+ </file>
+ </source>
+ </resourceSet>
+ <resourceSet config="overlay">
+ <source path="$TOP$$SEP$baseMerge$SEP$overlay">
+ <file name="icon2" path="$TOP$$SEP$baseMerge$SEP$overlay$SEP$drawable$SEP$icon2.png" qualifiers="" type="drawable"/>
+ <file name="icon" path="$TOP$$SEP$baseMerge$SEP$overlay$SEP$drawable-ldpi$SEP$icon.png" qualifiers="ldpi" type="drawable"/>
+ <file name="alias_replaced_by_file" path="$TOP$$SEP$baseMerge$SEP$overlay$SEP$layout$SEP$alias_replaced_by_file.xml" qualifiers="" type="layout"/>
+ <file name="main" path="$TOP$$SEP$baseMerge$SEP$overlay$SEP$layout$SEP$main.xml" qualifiers="" type="layout"/>
+ <file path="$TOP$$SEP$baseMerge$SEP$overlay$SEP$values$SEP$values.xml" qualifiers="">
+ <color name="color">#FFFFFFFF</color>
+ <item name="file_replaced_by_alias" type="layout">@layout$SEP$ref</item>
+ <string name="basic_string">overlay_string</string>
+ </file>
+ </source>
+ </resourceSet>
+</merger>
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/new_overlay.png b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/new_overlay.png
new file mode 100644
index 0000000..b55e544
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/new_overlay.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/removed_overlay.png b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/removed_overlay.png
new file mode 100644
index 0000000..47e1adf
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/removed_overlay.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/touched.png b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/touched.png
new file mode 100644
index 0000000..47e1adf
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/touched.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/untouched.png b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/untouched.png
new file mode 100644
index 0000000..47e1adf
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/main/drawable/untouched.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/merger.xml b/builder/src/test/resources/testData/incMergeData/basicFiles/merger.xml
new file mode 100644
index 0000000..6f4a3cb
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/merger.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merger>
+ <resourceSet config="main">
+ <source path="$TOP$$SEP$main">
+ <file name="untouched" path="$TOP$$SEP$main$SEP$drawable$SEP$untouched.png" qualifiers="" type="drawable"/>
+ <file name="touched" path="$TOP$$SEP$main$SEP$drawable$SEP$touched.png" qualifiers="" type="drawable"/>
+ <file name="new_overlay" path="$TOP$$SEP$main$SEP$drawable$SEP$new_overlay.png" qualifiers="" type="drawable"/>
+ <file name="removed" path="$TOP$$SEP$main$SEP$drawable$SEP$removed.png" qualifiers="" type="drawable"/>
+ <file name="removed" path="$TOP$$SEP$main$SEP$drawable-ldpi$SEP$removed.png" qualifiers="ldpi" type="drawable"/>
+ <file name="removed_overlay" path="$TOP$$SEP$main$SEP$drawable$SEP$removed_overlay.png" qualifiers="" type="drawable"/>
+ </source>
+ </resourceSet>
+ <resourceSet config="overlay">
+ <source path="$TOP$$SEP$overlay">
+ <file name="removed_overlay" path="$TOP$$SEP$overlay$SEP$drawable$SEP$removed_overlay.png" qualifiers="" type="drawable"/>
+ </source>
+ </resourceSet>
+</merger>
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/new_overlay.png b/builder/src/test/resources/testData/incMergeData/basicFiles/new_overlay.png
new file mode 100644
index 0000000..b55e544
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/new_overlay.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable-hdpi/new_alternate.png b/builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable-hdpi/new_alternate.png
new file mode 100644
index 0000000..47e1adf
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable-hdpi/new_alternate.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable/new_overlay.png b/builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable/new_overlay.png
new file mode 100644
index 0000000..47e1adf
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/overlay/drawable/new_overlay.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable-ldpi/removed.png b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable-ldpi/removed.png
new file mode 100644
index 0000000..b55e544
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable-ldpi/removed.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/new_overlay.png b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/new_overlay.png
new file mode 100644
index 0000000..b55e544
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/new_overlay.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/removed_overlay.png b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/removed_overlay.png
new file mode 100644
index 0000000..b55e544
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/removed_overlay.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/touched.png b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/touched.png
new file mode 100644
index 0000000..b55e544
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/touched.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/untouched.png b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/untouched.png
new file mode 100644
index 0000000..47e1adf
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicFiles/resOut/drawable/untouched.png
Binary files differ
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues/main/values/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues/main/values/values.xml
new file mode 100644
index 0000000..32c8031
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues/main/values/values.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="untouched">untouched</string>
+ <string name="touched">touched</string>
+ <string name="new_overlay">old_overlay</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues/merger.xml b/builder/src/test/resources/testData/incMergeData/basicValues/merger.xml
new file mode 100644
index 0000000..79980b2
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues/merger.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merger>
+ <resourceSet config="main">
+ <source path="$TOP$$SEP$main">
+ <file path="$TOP$$SEP$main$SEP$values$SEP$values.xml" qualifiers="">
+ <string name="untouched">untouched</string>
+ <string name="touched">untouched</string>
+ <string name="removed">removed</string>
+ <string name="new_overlay">old_overlay</string>
+ </file>
+ <file path="$TOP$$SEP$main$SEP$values-en$SEP$values.xml" qualifiers="en">
+ <string name="removed">removed</string>
+ </file>
+ </source>
+ </resourceSet>
+ <resourceSet config="overlay">
+ <source path="$TOP$$SEP$overlay" />
+ </resourceSet>
+</merger>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues/overlay/values-fr/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues/overlay/values-fr/values.xml
new file mode 100644
index 0000000..dcfcbdd
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues/overlay/values-fr/values.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="new_alternate">new_alternate</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues/overlay/values/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues/overlay/values/values.xml
new file mode 100644
index 0000000..78e296c
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues/overlay/values/values.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="new_overlay">new_overlay</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues/resOut/values-en/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues/resOut/values-en/values.xml
new file mode 100644
index 0000000..b6be59a
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues/resOut/values-en/values.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="removed">removed</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues/resOut/values/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues/resOut/values/values.xml
new file mode 100644
index 0000000..a3ccf6b
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues/resOut/values/values.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="untouched">untouched</string>
+ <string name="touched">untouched</string>
+ <string name="removed">removed</string>
+ <string name="new_overlay">old_overlay</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues2/main/values/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues2/main/values/values.xml
new file mode 100644
index 0000000..7a0a153
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues2/main/values/values.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="untouched">untouched</string>
+ <string name="removed_overlay">untouched</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues2/merger.xml b/builder/src/test/resources/testData/incMergeData/basicValues2/merger.xml
new file mode 100644
index 0000000..33f4356
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues2/merger.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merger>
+ <resourceSet config="main">
+ <source path="$TOP$$SEP$main">
+ <file path="$TOP$$SEP$main$SEP$values$SEP$values.xml" qualifiers="">
+ <string name="untouched">untouched</string>
+ <string name="removed_overlay">untouched</string>
+ </file>
+ </source>
+ </resourceSet>
+ <resourceSet config="overlay">
+ <source path="$TOP$$SEP$overlay">
+ <file path="$TOP$$SEP$overlay$SEP$values$SEP$values.xml" qualifiers="">
+ <string name="removed_overlay">overlay</string>
+ </file>
+ </source>
+ </resourceSet>
+</merger>
diff --git a/builder/src/test/resources/testData/incMergeData/basicValues2/resOut/values/values.xml b/builder/src/test/resources/testData/incMergeData/basicValues2/resOut/values/values.xml
new file mode 100644
index 0000000..a0e41d1
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/basicValues2/resOut/values/values.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="untouched">untouched</string>
+ <string name="removed_overlay">overlay</string>
+</resources>
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/alias_replaced_by_file.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/alias_replaced_by_file.xml
new file mode 100644
index 0000000..b199751
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/alias_replaced_by_file.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Test App - Basic"
+ android:id="@+id/text"
+ />
+</LinearLayout>
+
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/main.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/main.xml
new file mode 100644
index 0000000..b199751
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/main/layout/main.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Test App - Basic"
+ android:id="@+id/text"
+ />
+</LinearLayout>
+
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/main/values/values.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/main/values/values.xml
new file mode 100644
index 0000000..028b828
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/main/values/values.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item type="layout" name="file_replaced_by_alias">@layout/main</item>
+</resources>
+
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/merger.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/merger.xml
new file mode 100644
index 0000000..c2cd240
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/merger.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merger>
+ <resourceSet config="main">
+ <source path="$TOP$$SEP$main">
+ <file name="main" path="$TOP$$SEP$main$SEP$layout$SEP$main.xml" qualifiers="" type="layout"/>
+ <file name="file_replaced_by_alias" path="$TOP$$SEP$main$SEP$layout$SEP$file_replaced_by_alias.xml" qualifiers="" type="layout"/>
+ <file path="$TOP$$SEP$main$SEP$values$SEP$values.xml" qualifiers="">
+ <item type="layout" name="alias_replaced_by_file">@layout/main</item>
+ </file>
+ </source>
+ </resourceSet>
+</merger>
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/file_replaced_by_alias.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/file_replaced_by_alias.xml
new file mode 100644
index 0000000..b199751
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/file_replaced_by_alias.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Test App - Basic"
+ android:id="@+id/text"
+ />
+</LinearLayout>
+
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/main.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/main.xml
new file mode 100644
index 0000000..b199751
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/layout/main.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Test App - Basic"
+ android:id="@+id/text"
+ />
+</LinearLayout>
+
diff --git a/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/values/values.xml b/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/values/values.xml
new file mode 100644
index 0000000..1fbc46e
--- /dev/null
+++ b/builder/src/test/resources/testData/incMergeData/filesVsValues/resOut/values/values.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item type="layout" name="alias_replaced_by_file">@layout/main</item>
+</resources>
+