blob: 1e917ad71254aacf3cb08c241a210cff114a7dd6 [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 static org.junit.Assert.assertTrue;
import com.facebook.buck.dalvik.ZipSplitter;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.io.CharStreams;
import org.easymock.EasyMock;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class SplitZipStepTest {
@Rule
public TemporaryFolder tempDir = new TemporaryFolder();
@Test
public void testMetaList() throws IOException {
File outJar = tempDir.newFile("test.jar");
ZipOutputStream zipOut = new ZipOutputStream(
new BufferedOutputStream(new FileOutputStream(outJar)));
Map<String, String> fileToClassName = ImmutableMap.of(
"com/facebook/foo.class", "com.facebook.foo",
"bar.class", "bar");
try {
for (String entry : fileToClassName.keySet()) {
zipOut.putNextEntry(new ZipEntry(entry));
zipOut.write(new byte[] { 0 });
}
} finally {
zipOut.close();
}
StringWriter stringWriter = new StringWriter();
BufferedWriter writer = new BufferedWriter(stringWriter);
try {
SplitZipStep.writeMetaList(writer, ImmutableList.of(outJar), DexStore.JAR);
} finally {
writer.close();
}
List<String> lines = CharStreams.readLines(new StringReader(stringWriter.toString()));
assertEquals(1, lines.size());
String line = Iterables.getFirst(lines, null);
String[] data = line.split(" ");
assertEquals(3, data.length);
// Note that we cannot test data[1] (the hash) because zip files change their hash each
// time they are written due to timestamps written into the file.
assertEquals(SmartDexingStep.transformInputToDexOutput(outJar.getName(), DexStore.JAR), data[0]);
assertTrue(String.format("Unexpected class: %s", data[2]),
fileToClassName.values().contains(data[2]));
}
@Test
public void testRequiredInPrimaryZipPredicate() throws IOException {
Path primaryDexClassesFile = Paths.get("the/manifest.txt");
SplitZipStep splitZipStep = new SplitZipStep(
/* inputPathsToSplit */ ImmutableSet.<String>of(),
/* secondaryJarMetaPath */ "",
/* primaryJarPath */ "",
/* secondaryJarDir */ "",
/* secondaryJarPattern */ "",
/* primaryDexSubstrings */ ImmutableSet.of("List"),
Optional.of(primaryDexClassesFile),
ZipSplitter.DexSplitStrategy.MAXIMIZE_PRIMARY_DEX_SIZE,
DexStore.JAR,
/* pathToReportDir */ "",
/* useLinearAllocSplitDex */ true,
/* linearAllocHardLimit */ 4 * 1024 * 1024);
List<String> linesInManifestFile = ImmutableList.of(
"com/google/common/collect/ImmutableSortedSet.class",
" com/google/common/collect/ImmutableSet.class",
"# com/google/common/collect/ImmutableMap.class"
);
ProjectFilesystem projectFilesystem = EasyMock.createMock(ProjectFilesystem.class);
EasyMock.expect(projectFilesystem.readLines(primaryDexClassesFile))
.andReturn(linesInManifestFile);
ExecutionContext context = EasyMock.createMock(ExecutionContext.class);
EasyMock.expect(context.getProjectFilesystem()).andReturn(projectFilesystem);
EasyMock.replay(projectFilesystem, context);
Predicate<String> requiredInPrimaryZipPredicate = splitZipStep
.createRequiredInPrimaryZipPredicate(context);
assertTrue(
"All non-.class files should be accepted.",
requiredInPrimaryZipPredicate.apply("apples.txt"));
assertTrue(
"com/google/common/collect/ImmutableSortedSet.class is listed in the manifest verbatim.",
requiredInPrimaryZipPredicate.apply("com/google/common/collect/ImmutableSortedSet.class"));
assertTrue(
"com/google/common/collect/ImmutableSet.class is in the manifest with whitespace.",
requiredInPrimaryZipPredicate.apply("com/google/common/collect/ImmutableSet.class"));
assertFalse(
"com/google/common/collect/ImmutableSet.class cannot have whitespace as param.",
requiredInPrimaryZipPredicate.apply(" com/google/common/collect/ImmutableSet.class"));
assertFalse(
"com/google/common/collect/ImmutableMap.class is commented out.",
requiredInPrimaryZipPredicate.apply("com/google/common/collect/ImmutableMap.class"));
assertFalse(
"com/google/common/collect/Iterables.class is not even mentioned.",
requiredInPrimaryZipPredicate.apply("com/google/common/collect/Iterables.class"));
assertTrue(
"java/awt/List.class matches the substring 'List'.",
requiredInPrimaryZipPredicate.apply("java/awt/List.class"));
assertFalse(
"Substring matching is case-sensitive.",
requiredInPrimaryZipPredicate.apply("shiny/Glistener.class"));
EasyMock.verify(projectFilesystem, context);
}
@Test
public void testClassFilePattern() {
assertTrue(SplitZipStep.classFilePattern.matcher(
"com/facebook/orca/threads/ParticipantInfo.class").matches());
assertTrue(SplitZipStep.classFilePattern.matcher(
"com/facebook/orca/threads/ParticipantInfo$1.class").matches());
}
}