aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipWriterTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipWriterTest.java')
-rw-r--r--src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipWriterTest.java373
1 files changed, 373 insertions, 0 deletions
diff --git a/src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipWriterTest.java b/src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipWriterTest.java
new file mode 100644
index 0000000000..e58a90c923
--- /dev/null
+++ b/src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipWriterTest.java
@@ -0,0 +1,373 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.google.devtools.build.zip;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.primitives.Bytes;
+import com.google.devtools.build.zip.ZipFileEntry.Compression;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Random;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+@RunWith(JUnit4.class)
+public class ZipWriterTest {
+ @Rule public TemporaryFolder tmp = new TemporaryFolder();
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private Random rand;
+ private Calendar cal;
+ private CRC32 crc;
+ private Deflater deflater;
+ private File test;
+
+ @Before public void setup() throws IOException {
+ rand = new Random();
+ cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.YEAR, rand.nextInt(128) + 1980); // Zip files have 7-bit year resolution.
+ cal.set(Calendar.MONTH, rand.nextInt(12));
+ cal.set(Calendar.DAY_OF_MONTH, rand.nextInt(29));
+ cal.set(Calendar.HOUR_OF_DAY, rand.nextInt(24));
+ cal.set(Calendar.MINUTE, rand.nextInt(60));
+ cal.set(Calendar.SECOND, rand.nextInt(30) * 2); // Zip files have 2 second resolution.
+
+ crc = new CRC32();
+ deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
+ test = tmp.newFile("test.zip");
+ }
+
+ @Test public void testEmpty() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ }
+
+ try (ZipFile zipFile = new ZipFile(test)) {
+ assertThat(zipFile.entries().hasMoreElements()).isFalse();
+ }
+ }
+
+ @Test public void testComment() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ writer.setComment("test comment");
+ }
+
+ try (ZipFile zipFile = new ZipFile(test)) {
+ assertThat(zipFile.entries().hasMoreElements()).isFalse();
+ assertThat(zipFile.getComment()).isEqualTo("test comment");
+ }
+ }
+
+ @Test public void testFileDataBeforeEntry() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ thrown.expect(ZipException.class);
+ thrown.expectMessage("Cannot write zip contents without first setting a ZipEntry or starting"
+ + " a prefix file.");
+ writer.write(new byte[] { 0xf, 0xa, 0xb });
+ }
+
+ try (ZipFile zipFile = new ZipFile(test)) {
+ assertThat(zipFile.entries().hasMoreElements()).isFalse();
+ }
+ }
+
+ @Test public void testSingleEntry() throws IOException {
+ ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8);
+ byte[] content = "content".getBytes(UTF_8);
+ crc.update(content);
+ ZipFileEntry entry = new ZipFileEntry("foo");
+ entry.setMethod(Compression.STORED);
+ entry.setSize(content.length);
+ entry.setCompressedSize(content.length);
+ entry.setCrc(crc.getValue());
+ entry.setTime(cal.getTimeInMillis());
+
+ writer.putNextEntry(entry);
+ writer.write(content);
+ writer.closeEntry();
+ writer.close();
+
+ byte[] buf = new byte[128];
+ try (ZipFile zipFile = new ZipFile(test)) {
+ ZipEntry foo = zipFile.getEntry("foo");
+ assertThat(foo.getMethod()).isEqualTo(ZipEntry.STORED);
+ assertThat(foo.getSize()).isEqualTo(content.length);
+ assertThat(foo.getCompressedSize()).isEqualTo(content.length);
+ assertThat(foo.getCrc()).isEqualTo(crc.getValue());
+ assertThat(foo.getTime()).isEqualTo(cal.getTimeInMillis());
+ zipFile.getInputStream(foo).read(buf);
+ assertThat(Bytes.indexOf(buf, content)).isEqualTo(0);
+ }
+ }
+
+ @Test public void testMultipleEntry() throws IOException {
+ ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8);
+ writer.setComment("file comment");
+
+ byte[] fooContent = "content".getBytes(UTF_8);
+ crc.update(fooContent);
+ long fooCrc = crc.getValue();
+ ZipFileEntry rawFoo = new ZipFileEntry("foo");
+ rawFoo.setMethod(Compression.STORED);
+ rawFoo.setSize(fooContent.length);
+ rawFoo.setCompressedSize(fooContent.length);
+ rawFoo.setCrc(crc.getValue());
+ rawFoo.setTime(cal.getTimeInMillis());
+ rawFoo.setComment("foo comment");
+
+ writer.putNextEntry(rawFoo);
+ writer.write(fooContent);
+ writer.closeEntry();
+
+ byte[] barContent = "stuff".getBytes(UTF_8);
+ byte[] deflatedBarContent = new byte[128];
+ crc.reset();
+ crc.update(barContent);
+ long barCrc = crc.getValue();
+ deflater.setInput(barContent);
+ deflater.finish();
+ int deflatedSize = deflater.deflate(deflatedBarContent);
+ ZipFileEntry rawBar = new ZipFileEntry("bar");
+ rawBar.setMethod(Compression.DEFLATED);
+ rawBar.setSize(barContent.length);
+ rawBar.setCompressedSize(deflatedSize);
+ rawBar.setCrc(barCrc);
+ rawBar.setTime(cal.getTimeInMillis());
+
+ writer.putNextEntry(rawBar);
+ writer.write(deflatedBarContent, 0, deflatedSize);
+ writer.closeEntry();
+
+ writer.close();
+
+ byte[] buf = new byte[128];
+ try (ZipFile zipFile = new ZipFile(test)) {
+ assertThat(zipFile.getComment()).isEqualTo("file comment");
+
+ ZipEntry foo = zipFile.getEntry("foo");
+ assertThat(foo.getMethod()).isEqualTo(ZipEntry.STORED);
+ assertThat(foo.getSize()).isEqualTo(fooContent.length);
+ assertThat(foo.getCompressedSize()).isEqualTo(fooContent.length);
+ assertThat(foo.getCrc()).isEqualTo(fooCrc);
+ assertThat(foo.getTime()).isEqualTo(cal.getTimeInMillis());
+ assertThat(foo.getComment()).isEqualTo("foo comment");
+ zipFile.getInputStream(foo).read(buf);
+ assertThat(Bytes.indexOf(buf, fooContent)).isEqualTo(0);
+
+ ZipEntry bar = zipFile.getEntry("bar");
+ assertThat(bar.getMethod()).isEqualTo(ZipEntry.DEFLATED);
+ assertThat(bar.getSize()).isEqualTo(barContent.length);
+ assertThat(bar.getCompressedSize()).isEqualTo(deflatedSize);
+ assertThat(bar.getCrc()).isEqualTo(barCrc);
+ assertThat(bar.getTime()).isEqualTo(cal.getTimeInMillis());
+ zipFile.getInputStream(bar).read(buf);
+ assertThat(Bytes.indexOf(buf, barContent)).isEqualTo(0);
+ }
+ }
+
+ @Test public void testWrongSizeContent() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ byte[] content = "content".getBytes(UTF_8);
+ crc.update(content);
+ ZipFileEntry entry = new ZipFileEntry("foo");
+ entry.setMethod(Compression.STORED);
+ entry.setSize(content.length);
+ entry.setCompressedSize(content.length);
+ entry.setCrc(crc.getValue());
+ entry.setTime(cal.getTimeInMillis());
+
+ writer.putNextEntry(entry);
+ writer.write("some other content".getBytes(UTF_8));
+ thrown.expect(ZipException.class);
+ thrown.expectMessage("Number of bytes written for the entry");
+ writer.closeEntry();
+ }
+ }
+
+ @Test public void testRawZipEntry() throws IOException {
+ ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8);
+ byte[] content = "content".getBytes(UTF_8);
+ crc.update(content);
+ ZipFileEntry entry = new ZipFileEntry("foo");
+ entry.setVersion((short) 1);
+ entry.setVersionNeeded((short) 2);
+ entry.setMethod(Compression.STORED);
+ entry.setSize(content.length);
+ entry.setCompressedSize(content.length);
+ entry.setCrc(crc.getValue());
+ entry.setTime(cal.getTimeInMillis());
+ entry.setFlags(ZipUtil.get16(new byte[]{ 0x08, 0x00 }, 0));
+ entry.setInternalAttributes(ZipUtil.get16(new byte[]{ 0x34, 0x12 }, 0));
+ entry.setExternalAttributes(ZipUtil.get32(new byte[]{ 0x0a, 0x09, 0x78, 0x56 }, 0));
+ entry.setLocalHeaderOffset(rand.nextInt(Integer.MAX_VALUE));
+
+ writer.putNextEntry(entry);
+ writer.write(content);
+ writer.closeEntry();
+ writer.close();
+
+ byte[] buf = new byte[128];
+ try (ZipFile zipFile = new ZipFile(test)) {
+ ZipEntry foo = zipFile.getEntry("foo");
+ assertThat(foo.getMethod()).isEqualTo(ZipEntry.STORED);
+ assertThat(foo.getSize()).isEqualTo(content.length);
+ assertThat(foo.getCompressedSize()).isEqualTo(content.length);
+ assertThat(foo.getCrc()).isEqualTo(crc.getValue());
+ assertThat(foo.getTime()).isEqualTo(cal.getTimeInMillis());
+ zipFile.getInputStream(foo).read(buf);
+ assertThat(Bytes.indexOf(buf, content)).isEqualTo(0);
+ }
+
+ try (ZipReader zipFile = new ZipReader(test)) {
+ ZipFileEntry foo = zipFile.getEntry("foo");
+ // Versions should be increased to minimum required for STORED compression.
+ assertThat(foo.getVersion()).isEqualTo((short) 0xa);
+ assertThat(foo.getVersionNeeded()).isEqualTo((short) 0xa);
+ assertThat(foo.getFlags()).isEqualTo((short) 0); // Data descriptor bit should be cleared.
+ assertThat(foo.getInternalAttributes()).isEqualTo((short) 4660);
+ assertThat(foo.getExternalAttributes()).isEqualTo(1450707210);
+ }
+ }
+
+ @Test public void testPrefixFile() throws IOException, InterruptedException {
+ ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8);
+
+ writer.startPrefixFile();
+ writer.write("#!/bin/bash\necho 'hello world'\n".getBytes(UTF_8));
+ writer.endPrefixFile();
+
+ byte[] content = "content".getBytes(UTF_8);
+ crc.update(content);
+ ZipFileEntry entry = new ZipFileEntry("foo");
+ entry.setMethod(Compression.STORED);
+ entry.setSize(content.length);
+ entry.setCompressedSize(content.length);
+ entry.setCrc(crc.getValue());
+ entry.setTime(cal.getTimeInMillis());
+
+ writer.putNextEntry(entry);
+ writer.write(content);
+ writer.closeEntry();
+ writer.close();
+
+ byte[] buf = new byte[128];
+ try (ZipFile zipFile = new ZipFile(test)) {
+ ZipEntry foo = zipFile.getEntry("foo");
+ assertThat(foo.getMethod()).isEqualTo(ZipEntry.STORED);
+ assertThat(foo.getSize()).isEqualTo(content.length);
+ assertThat(foo.getCompressedSize()).isEqualTo(content.length);
+ assertThat(foo.getCrc()).isEqualTo(crc.getValue());
+ assertThat(foo.getTime()).isEqualTo(cal.getTimeInMillis());
+ zipFile.getInputStream(foo).read(buf);
+ assertThat(Bytes.indexOf(buf, content)).isEqualTo(0);
+ }
+
+ Process pr = new ProcessBuilder("chmod", "750", test.getAbsolutePath()).start();
+ pr.waitFor();
+ pr = new ProcessBuilder(test.getAbsolutePath()).start();
+ pr.getInputStream().read(buf);
+ pr.waitFor();
+ assertThat(Bytes.indexOf(buf, "hello world".getBytes(UTF_8))).isEqualTo(0);
+ }
+
+ @Test public void testPrefixFileAfterZip() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ byte[] content = "content".getBytes(UTF_8);
+ crc.update(content);
+ ZipFileEntry entry = new ZipFileEntry("foo");
+ entry.setMethod(Compression.STORED);
+ entry.setSize(content.length);
+ entry.setCompressedSize(content.length);
+ entry.setCrc(crc.getValue());
+ entry.setTime(cal.getTimeInMillis());
+
+ writer.putNextEntry(entry);
+ thrown.expect(ZipException.class);
+ thrown.expectMessage("Cannot add a prefix file after the zip contents have been started.");
+ writer.startPrefixFile();
+ writer.write("#!/bin/bash\necho 'hello world'\n".getBytes(UTF_8));
+ writer.endPrefixFile();
+ }
+ }
+
+ @Test public void testPrefixAfterFinish() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ writer.finish();
+ thrown.expect(IllegalStateException.class);
+ writer.startPrefixFile();
+ writer.write("#!/bin/bash\necho 'hello world'\n".getBytes(UTF_8));
+ writer.endPrefixFile();
+ }
+ }
+
+ @Test public void testPutEntryAfterFinish() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ writer.finish();
+ thrown.expect(IllegalStateException.class);
+ writer.putNextEntry(new ZipFileEntry("foo"));
+ }
+ }
+
+ @Test public void testCloseEntryAfterFinish() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ byte[] content = "content".getBytes(UTF_8);
+ crc.update(content);
+ ZipFileEntry entry = new ZipFileEntry("foo");
+ entry.setMethod(Compression.STORED);
+ entry.setSize(content.length);
+ entry.setCompressedSize(content.length);
+ entry.setCrc(crc.getValue());
+ entry.setTime(cal.getTimeInMillis());
+
+ writer.putNextEntry(entry);
+ writer.write(content);
+ writer.finish();
+ thrown.expect(IllegalStateException.class);
+ writer.closeEntry();
+ }
+ }
+
+ @Test public void testFinishAfterFinish() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ writer.finish();
+ thrown.expect(IllegalStateException.class);
+ writer.finish();
+ }
+ }
+
+ @Test public void testWriteAfterFinish() throws IOException {
+ try (ZipWriter writer = new ZipWriter(new FileOutputStream(test), UTF_8)) {
+ writer.finish();
+ thrown.expect(IllegalStateException.class);
+ writer.write("content".getBytes(UTF_8));
+ }
+ }
+}