blob: 9a96e2d8d271072a3ef4d276e30ec98faca1c340 [file] [log] [blame]
/*
* Copyright 2014-present Facebook, Inc.
*
* 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.facebook.buck.android.aapt;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.facebook.buck.android.aapt.MiniAapt.ResourceParseException;
import com.facebook.buck.android.aapt.RDotTxtEntry.IdType;
import com.facebook.buck.android.aapt.RDotTxtEntry.RType;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import javax.xml.xpath.XPathExpressionException;
public class MiniAaptTest {
private static final ImmutableList<String> RESOURCES = ImmutableList.<String>builder().add(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<LinearLayout>",
"<Button android:id=\"@+id/button1\" ",
"android:layout_toLeftOf=\"@id/button2\" ",
"android:text=\"@string/text\" />",
"<Button android:id=\"@+id/button3\" ",
"style:attribute=\"@style/Buck.Theme\" ",
"android:background=\"@drawable/some_image\" />",
"<TextView android:id=\"@id/android:empty\" />",
"</LinearLayout>")
.build();
private final FakeProjectFilesystem filesystem = new FakeProjectFilesystem();
@Test
public void testFindingResourceIdsInXml()
throws IOException, XPathExpressionException, ResourceParseException {
filesystem.writeLinesToPath(RESOURCES, Paths.get("resource.xml"));
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.<Path>of());
ImmutableSet.Builder<RDotTxtEntry> references = ImmutableSet.builder();
aapt.processXmlFile(filesystem, Paths.get("resource.xml"), references);
Set<RDotTxtEntry> definitions = aapt.getResourceCollector().getResources();
assertEquals(
definitions,
ImmutableSet.<RDotTxtEntry>of(
new FakeRDotTxtEntry(IdType.INT, RType.ID, "button1"),
new FakeRDotTxtEntry(IdType.INT, RType.ID, "button3")));
assertEquals(
references.build(),
ImmutableSet.<RDotTxtEntry>of(
new FakeRDotTxtEntry(IdType.INT, RType.DRAWABLE, "some_image"),
new FakeRDotTxtEntry(IdType.INT, RType.STRING, "text"),
new FakeRDotTxtEntry(IdType.INT, RType.STYLE, "Buck_Theme"),
new FakeRDotTxtEntry(IdType.INT, RType.ID, "button2")));
}
@Test
public void testParsingFilesUnderValuesDirectory() throws IOException, ResourceParseException {
ImmutableList<String> lines = ImmutableList.<String>builder().add(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<resources>",
"<string name=\"hello\">Hello, <xliff:g id=\"name\">%s</xliff:g>!</string>",
"<plurals name=\"people\">",
" <item quantity=\"zero\">ignore1</item>",
" <item quantity=\"many\">ignore2</item>",
"</plurals>",
"<skip />",
"<integer name=\"number\">100</integer>",
"<dimen name=\"dimension\">100sp</dimen>",
"<declare-styleable name=\"MyNiceView\">",
" <attr name=\"titleText\" />",
" <attr name=\"subtitleText\" format=\"string\" />",
" <attr name=\"complexAttr\">",
" <enum name=\"shouldBeIgnored\" value=\"0\" />",
" <enum name=\"alsoIgnore\" value=\"1\" />",
" <flag name=\"uselessFlag\" value=\"0x00\" />",
" </attr>",
" <attr name=\"android:layout_gravity\" />",
" <item name=\"should_be_ignored\" />",
"</declare-styleable>",
"<eat-comment />",
"<item type=\"id\" name=\"some_id\" />",
"<style name=\"Widget.Theme\">",
" <item name=\"ignoreMe\" />",
"</style>",
"</resources>")
.build();
filesystem.writeLinesToPath(lines, Paths.get("values.xml"));
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.<Path>of());
aapt.processValuesFile(filesystem, Paths.get("values.xml"));
Set<RDotTxtEntry> definitions = aapt.getResourceCollector().getResources();
assertEquals(
definitions,
ImmutableSet.<RDotTxtEntry>of(
new FakeRDotTxtEntry(IdType.INT, RType.STRING, "hello"),
new FakeRDotTxtEntry(IdType.INT, RType.PLURALS, "people"),
new FakeRDotTxtEntry(IdType.INT, RType.INTEGER, "number"),
new FakeRDotTxtEntry(IdType.INT, RType.DIMEN, "dimension"),
new FakeRDotTxtEntry(IdType.INT_ARRAY, RType.STYLEABLE, "MyNiceView"),
new FakeRDotTxtEntry(IdType.INT, RType.STYLEABLE, "MyNiceView_titleText"),
new FakeRDotTxtEntry(IdType.INT, RType.STYLEABLE, "MyNiceView_subtitleText"),
new FakeRDotTxtEntry(IdType.INT, RType.STYLEABLE, "MyNiceView_complexAttr"),
new FakeRDotTxtEntry(IdType.INT, RType.STYLEABLE, "MyNiceView_android_layout_gravity"),
new FakeRDotTxtEntry(IdType.INT, RType.ATTR, "titleText"),
new FakeRDotTxtEntry(IdType.INT, RType.ATTR, "subtitleText"),
new FakeRDotTxtEntry(IdType.INT, RType.ATTR, "complexAttr"),
new FakeRDotTxtEntry(IdType.INT, RType.ID, "some_id"),
new FakeRDotTxtEntry(IdType.INT, RType.STYLE, "Widget_Theme")));
boolean foundElement = false;
for (RDotTxtEntry definition : definitions) {
if (definition.name.equals("MyNiceView")) {
assertEquals(
"{ 0x7f000000,0x7f000000,0x7f000000,0x7f000000 }",
definition.idValue);
foundElement = true;
}
}
assertTrue(foundElement);
}
@Test(expected = ResourceParseException.class)
public void testInvalidResourceType() throws IOException, ResourceParseException {
ImmutableList<String> lines = ImmutableList.<String>builder().add(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<resources>",
"<resourcetype name=\"number\">100</resourcetype>",
"</resources>")
.build();
filesystem.writeLinesToPath(lines, Paths.get("values.xml"));
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.<Path>of());
aapt.processValuesFile(filesystem, Paths.get("values.xml"));
}
@Test
public void testInvalidDefinition() throws XPathExpressionException, IOException {
ImmutableList<String> lines = ImmutableList.<String>builder().add(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<LinearLayout>",
"<Button android:id=\"@+string/button1\" ",
"android:layout_toLeftOf=\"@id/button2\" ",
"android:text=\"@string/text\" />",
"</LinearLayout>")
.build();
Path resource = Paths.get("resource.xml");
filesystem.writeLinesToPath(lines, resource);
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.<Path>of());
try {
aapt.processXmlFile(filesystem, resource, ImmutableSet.<RDotTxtEntry>builder());
fail("MiniAapt should throw parsing '@+string/button1'");
} catch (ResourceParseException e) {
assertThat(e.getMessage(), containsString("Invalid definition of a resource"));
}
}
@Test
public void testInvalidReference() throws IOException, XPathExpressionException {
ImmutableList<String> lines = ImmutableList.<String>builder().add(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<LinearLayout>",
"<Button android:id=\"@+id/button1\" ",
"android:layout_toLeftOf=\"@someresource/button2\" ",
"android:text=\"@string/text\" />",
"</LinearLayout>")
.build();
Path resource = Paths.get("resource.xml");
filesystem.writeLinesToPath(lines, resource);
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.<Path>of());
try {
aapt.processXmlFile(filesystem, resource, ImmutableSet.<RDotTxtEntry>builder());
fail("MiniAapt should throw parsing '@someresource/button2'");
} catch (ResourceParseException e) {
assertThat(e.getMessage(), containsString("Invalid reference '@someresource/button2'"));
}
}
@Test
public void testVerifyReferences()
throws IOException, XPathExpressionException, ResourceParseException {
filesystem.writeLinesToPath(RESOURCES, Paths.get("resource.xml"));
ImmutableList<String> rDotTxt = ImmutableList.of(
"int string text 0x07010001",
"int style Buck_Theme 0x07020001",
"int id button2 0x07030001");
Path depRTxt = Paths.get("dep/R.txt");
filesystem.writeLinesToPath(rDotTxt, depRTxt);
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.of(depRTxt));
ImmutableSet.Builder<RDotTxtEntry> references = ImmutableSet.builder();
aapt.processXmlFile(filesystem, Paths.get("resource.xml"), references);
Set<RDotTxtEntry> missing = aapt.verifyReferences(filesystem, references.build());
assertEquals(
ImmutableSet.<RDotTxtEntry>of(
new FakeRDotTxtEntry(IdType.INT, RType.DRAWABLE, "some_image")),
missing);
}
@Test
public void testProcessFileNamesInDirectory() throws IOException, ResourceParseException {
filesystem.touch(Paths.get("res/drawable/icon.png"));
filesystem.touch(Paths.get("res/drawable/another_icon.png.orig"));
filesystem.touch(Paths.get("res/drawable-ldpi/nine_patch.9.png"));
filesystem.touch(Paths.get("res/drawable-ldpi/.DS_Store"));
MiniAapt aapt = new MiniAapt(Paths.get("res"), Paths.get("R.txt"), ImmutableSet.<Path>of());
aapt.processFileNamesInDirectory(filesystem, Paths.get("res/drawable"));
aapt.processFileNamesInDirectory(filesystem, Paths.get("res/drawable-ldpi"));
assertEquals(
ImmutableSet.<RDotTxtEntry>of(
new FakeRDotTxtEntry(IdType.INT, RType.DRAWABLE, "icon"),
new FakeRDotTxtEntry(IdType.INT, RType.DRAWABLE, "nine_patch")),
aapt.getResourceCollector().getResources());
}
}