blob: 73e87ceda41d70662750537d94b1e1ae8892ca0c [file] [log] [blame]
/*
* Copyright 2012-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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import com.facebook.buck.android.MergeAndroidResourcesStep.Resource;
import com.facebook.buck.util.BuckConstant;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.collect.SortedSetMultimap;
import org.junit.Test;
import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
public class MergeAndroidResourcesStepTest {
@Test
public void testGenerateRDotJavaForMultipleSymbolsFiles() throws IOException {
RDotTxtEntryBuilder entriesBuilder = new RDotTxtEntryBuilder();
// Merge everything into the same package space.
String sharedPackageName = "com.facebook.abc";
entriesBuilder.add(new RDotTxtEntry(sharedPackageName, "a-R.txt",
"int id a1 0x7f010001\n" +
"int id a2 0x7f010002\n" +
"int string a1 0x7f020001\n"));
entriesBuilder.add(new RDotTxtEntry(sharedPackageName, "b-R.txt",
"int id b1 0x7f010001\n" +
"int id b2 0x7f010002\n"));
entriesBuilder.add(new RDotTxtEntry(sharedPackageName, "c-R.txt",
"int attr c1 0x7f010001\n" +
"int[] styleable c1 { 0x7f010001 }\n"));
SortedSetMultimap<String, Resource> packageNameToResources =
MergeAndroidResourcesStep.sortSymbols(
entriesBuilder.buildReadableMapper(),
entriesBuilder.buildFilePathToPackageNameSet(),
true /* reenumerate */);
assertEquals(1, packageNameToResources.keySet().size());
SortedSet<Resource> resources = packageNameToResources.get(sharedPackageName);
assertEquals(7, resources.size());
Set<String> uniqueEntries = Sets.newHashSet();
for (Resource resource : resources) {
if (!resource.type.equals("styleable")) {
assertFalse("Duplicate ids should be fixed by renumerate=true; duplicate was: " +
resource.idValueToWrite, uniqueEntries.contains(resource.idValueToWrite));
uniqueEntries.add(resource.idValueToWrite);
}
}
assertEquals(6, uniqueEntries.size());
// All good, no need to further test whether we can write the Java file correctly...
}
@Test
public void testGenerateRDotJavaForOneSymbolsFile() {
String symbolsFile = BuckConstant.BIN_DIR +
"/android_res/com/facebook/http/__res_resources_text_symbols__/R.txt";
String rDotJavaPackage = "com.facebook";
final String outputTextSymbols =
"int id placeholder 0x7f020000\n" +
"int string debug_http_proxy_dialog_title 0x7f030004\n" +
"int string debug_http_proxy_hint 0x7f030005\n" +
"int string debug_http_proxy_summary 0x7f030003\n" +
"int string debug_http_proxy_title 0x7f030002\n" +
"int string debug_ssl_cert_check_summary 0x7f030001\n" +
"int string debug_ssl_cert_check_title 0x7f030000\n" +
"int styleable SherlockMenuItem_android_visible 4\n" +
"int[] styleable SherlockMenuView { 0x7f010026, 0x7f010027, 0x7f010028, 0x7f010029, 0x7f01002a, 0x7f01002b, 0x7f01002c, 0x7f01002d }\n";
RDotTxtEntryBuilder entriesBuilder = new RDotTxtEntryBuilder();
entriesBuilder.add(new RDotTxtEntry(rDotJavaPackage, symbolsFile, outputTextSymbols));
SortedSetMultimap<String, Resource> rDotJavaPackageToResources =
MergeAndroidResourcesStep.sortSymbols(
entriesBuilder.buildReadableMapper(),
entriesBuilder.buildFilePathToPackageNameSet(),
false /* reenumerate */);
assertEquals(1, rDotJavaPackageToResources.keySet().size());
// Verify all of the values in the resources collection.
SortedSet<Resource> resources = rDotJavaPackageToResources.get(rDotJavaPackage);
assertEquals(9, resources.size());
Iterator<Resource> iter = resources.iterator();
assertResource("int", "id", "placeholder", "0x7f020000", iter.next());
assertResource("int", "string", "debug_http_proxy_dialog_title", "0x7f030004", iter.next());
assertResource("int", "string", "debug_http_proxy_hint", "0x7f030005", iter.next());
assertResource("int", "string", "debug_http_proxy_summary", "0x7f030003", iter.next());
assertResource("int", "string", "debug_http_proxy_title", "0x7f030002", iter.next());
assertResource("int", "string", "debug_ssl_cert_check_summary", "0x7f030001", iter.next());
assertResource("int", "string", "debug_ssl_cert_check_title", "0x7f030000", iter.next());
assertResource("int", "styleable", "SherlockMenuItem_android_visible", "4", iter.next());
assertResource("int[]",
"styleable",
"SherlockMenuView",
"{ 0x7f010026, 0x7f010027, 0x7f010028, 0x7f010029, 0x7f01002a, 0x7f01002b, 0x7f01002c, 0x7f01002d }",
iter.next());
// Verify that the correct Java code is generated.
String javaCode = MergeAndroidResourcesStep.generateJavaCodeForPackageAndResources(
rDotJavaPackage, resources);
assertEquals(
"package com.facebook;\n" +
"\n" +
"public class R {\n" +
"\n" +
" public static class id {\n" +
" public static int placeholder=0x7f020000;\n" +
" }\n" +
"\n" +
" public static class string {\n" +
" public static int debug_http_proxy_dialog_title=0x7f030004;\n" +
" public static int debug_http_proxy_hint=0x7f030005;\n" +
" public static int debug_http_proxy_summary=0x7f030003;\n" +
" public static int debug_http_proxy_title=0x7f030002;\n" +
" public static int debug_ssl_cert_check_summary=0x7f030001;\n" +
" public static int debug_ssl_cert_check_title=0x7f030000;\n" +
" }\n" +
"\n" +
" public static class styleable {\n" +
" public static int SherlockMenuItem_android_visible=4;\n" +
" public static int[] SherlockMenuView={ 0x7f010026, 0x7f010027, 0x7f010028, 0x7f010029, 0x7f01002a, 0x7f01002b, 0x7f01002c, 0x7f01002d };\n" +
" }\n" +
"\n" +
"}\n",
javaCode);
}
@Test
public void testGenerateRDotJavaForEmptyResources() {
String packageName = "com.facebook";
String rDotJava = MergeAndroidResourcesStep.generateJavaCodeForPackageWithoutResources(
packageName);
assertEquals(
"package com.facebook;\n" +
"\n" +
"public class R {\n" +
"\n" +
"}\n",
rDotJava);
}
/**
* A special comparison for two {@link Resource} objects because {@link Resource#equals(Object)}
* does not compare all of the fields.
*/
private void assertResource(
String expectedIdType,
String expectedType,
String expectedName,
String expectedIdValue,
Resource observedResource) {
assertEquals(expectedIdType, observedResource.idType);
assertEquals(expectedType, observedResource.type);
assertEquals(expectedName, observedResource.name);
assertEquals(expectedIdValue, observedResource.originalIdValue);
}
// sortSymbols has a goofy API. This will help.
private static class RDotTxtEntryBuilder {
private final ImmutableMap.Builder<String, String> filePathToContents =
ImmutableMap.builder();
private final ImmutableMap.Builder<String, String> filePathToPackageName =
ImmutableMap.builder();
public RDotTxtEntryBuilder() {
}
public void add(RDotTxtEntry entry) {
filePathToContents.put(entry.filePath, entry.contents);
filePathToPackageName.put(entry.filePath, entry.packageName);
}
public Function<String, Readable> buildReadableMapper() {
final ImmutableMap<String, String> builtInstance = filePathToContents.build();
return new Function<String, Readable>() {
@Override
public Readable apply(String filePath) {
String content = builtInstance.get(filePath);
if (content == null) {
throw new RuntimeException("No content for " + filePath);
} else {
return new StringReader(content);
}
}
};
}
public Map<String, String> buildFilePathToPackageNameSet() {
return filePathToPackageName.build();
}
}
private static class RDotTxtEntry {
public String packageName;
public String filePath;
public String contents;
public RDotTxtEntry(String packageName, String filePath, String contents) {
this.packageName = packageName;
this.filePath = filePath;
this.contents = contents;
}
}
}