blob: e45f117580c0df982a2fc2f683e06c83cad3f8fd [file] [log] [blame]
/*
* Copyright (C) 2015 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.apkzlib.zip;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class ZipToolsTest {
@Parameterized.Parameter(0)
@Nullable
public String mZipFile;
@Parameterized.Parameter(1)
@Nullable
public List<String> mUnzipCommand;
@Parameterized.Parameter(2)
@Nullable
public String mUnzipLineRegex;
@Parameterized.Parameter(3)
public boolean mToolStoresDirectories;
@Parameterized.Parameter(4)
public String mName;
@Rule
@Nonnull
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@Parameterized.Parameters(name = "{4} {index}")
public static Iterable<Object[]> getConfigurations() {
return Arrays.asList(new Object[][] {
{
"linux-zip.zip",
ImmutableList.of("/usr/bin/unzip", "-v"),
"^\\s*(?<size>\\d+)\\s+(?:Stored|Defl:N).*\\s(?<name>\\S+)\\S*$",
true,
"Linux Zip"
},
{
"windows-7zip.zip",
ImmutableList.of("c:\\Program Files\\7-Zip\\7z.exe", "l"),
"^(?:\\S+\\s+){3}(?<size>\\d+)\\s+\\d+\\s+(?<name>\\S+)\\s*$",
true,
"Windows 7-Zip"
},
{
"windows-cf.zip",
ImmutableList.of(
"Cannot use compressed folders from cmd line to list zip contents"),
"",
false,
"Windows Compressed Folders"
}
});
}
private File cloneZipFile() throws Exception {
File zfile = mTemporaryFolder.newFile("file.zip");
Files.write(ZipTestUtils.rsrcBytes(mZipFile), zfile);
return zfile;
}
private static void assertFileInZip(@Nonnull ZFile zfile, @Nonnull String name) throws Exception {
StoredEntry root = zfile.get(name);
assertNotNull(root);
InputStream is = root.open();
byte[] inZipData = ByteStreams.toByteArray(is);
is.close();
byte[] inFileData = ZipTestUtils.rsrcBytes(name);
assertArrayEquals(inFileData, inZipData);
}
@Test
public void zfileReadsZipFile() throws Exception {
try (ZFile zf = new ZFile(cloneZipFile())) {
if (mToolStoresDirectories) {
assertEquals(6, zf.entries().size());
} else {
assertEquals(4, zf.entries().size());
}
assertFileInZip(zf, "root");
assertFileInZip(zf, "images/lena.png");
assertFileInZip(zf, "text-files/rfc2460.txt");
assertFileInZip(zf, "text-files/wikipedia.html");
}
}
@Test
public void toolReadsZfFile() throws Exception {
testReadZFile(false);
}
@Test
public void toolReadsAlignedZfFile() throws Exception {
testReadZFile(true);
}
private void testReadZFile(boolean align) throws Exception {
String unzipcmd = mUnzipCommand.get(0);
Assume.assumeTrue(new File(unzipcmd).canExecute());
ZFileOptions options = new ZFileOptions();
if (align) {
options.setAlignmentRule(AlignmentRules.constant(500));
}
File zfile = new File (mTemporaryFolder.getRoot(), "zfile.zip");
try (ZFile zf = new ZFile(zfile, options)) {
zf.add("root", new ByteArrayInputStream(ZipTestUtils.rsrcBytes("root")));
zf.add("images/", new ByteArrayInputStream(new byte[0]));
zf.add(
"images/lena.png",
new ByteArrayInputStream(ZipTestUtils.rsrcBytes("images/lena.png")));
zf.add("text-files/", new ByteArrayInputStream(new byte[0]));
zf.add(
"text-files/rfc2460.txt",
new ByteArrayInputStream(ZipTestUtils.rsrcBytes("text-files/rfc2460.txt")));
zf.add(
"text-files/wikipedia.html",
new ByteArrayInputStream(ZipTestUtils.rsrcBytes("text-files/wikipedia.html")));
}
List<String> command = Lists.newArrayList(mUnzipCommand);
command.add(zfile.getAbsolutePath());
ProcessBuilder pb = new ProcessBuilder(command);
Process proc = pb.start();
InputStream is = proc.getInputStream();
byte output[] = ByteStreams.toByteArray(is);
String text = new String(output, Charsets.US_ASCII);
String lines[] = text.split("\n");
Map<String, Integer> sizes = Maps.newHashMap();
for (String l : lines) {
Matcher m = Pattern.compile(mUnzipLineRegex).matcher(l);
if (m.matches()) {
String sizeTxt = m.group("size");
int size = Integer.parseInt(sizeTxt);
String name = m.group("name");
sizes.put(name, size);
}
}
assertEquals(6, sizes.size());
/*
* The "images" directory may show up as "images" or "images/".
*/
String imagesKey = "images/";
if (!sizes.containsKey(imagesKey)) {
imagesKey = "images";
}
assertTrue(sizes.containsKey(imagesKey));
assertEquals(0, sizes.get(imagesKey).intValue());
assertSize(new String[] { "images/", "images" }, 0, sizes);
assertSize(new String[] { "text-files/", "text-files"}, 0, sizes);
assertSize(new String[] { "root" }, ZipTestUtils.rsrcBytes("root").length, sizes);
assertSize(new String[] { "images/lena.png", "images\\lena.png" },
ZipTestUtils.rsrcBytes("images/lena.png").length, sizes);
assertSize(new String[] { "text-files/rfc2460.txt", "text-files\\rfc2460.txt" },
ZipTestUtils.rsrcBytes("text-files/rfc2460.txt").length, sizes);
assertSize(new String[] { "text-files/wikipedia.html", "text-files\\wikipedia.html" },
ZipTestUtils.rsrcBytes("text-files/wikipedia.html").length, sizes);
}
private static void assertSize(String[] names, long size, Map<String, Integer> sizes) {
for (String n : names) {
if (sizes.containsKey(n)) {
assertEquals((long) sizes.get(n), size);
return;
}
}
fail();
}
}