diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java index e0bdf8614a..9a4a1c10e5 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java @@ -26,6 +26,7 @@ import java.io.OutputStream; import java.io.Serializable; import java.util.Arrays; +import java.util.zip.CRC32; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import java.util.zip.ZipEntry; @@ -250,18 +251,38 @@ public void testInstrumentAll_Class() throws IOException { public void testInstrumentAll_Zip() throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ZipOutputStream zipout = new ZipOutputStream(buffer); - zipout.putNextEntry(new ZipEntry("Test.class")); + + // Compressed Entry + ZipEntry entry = new ZipEntry("TestCompressed.class"); + entry.setMethod(ZipEntry.DEFLATED); + zipout.putNextEntry(entry); + zipout.write(TargetLoader.getClassDataAsBytes(getClass())); + + // Uncompressed Entry + entry = new ZipEntry("TestUncompressed.class"); + entry.setMethod(ZipEntry.STORED); + entry.setSize(TargetLoader.getClassDataAsBytes(getClass()).length); + CRC32 crc = new CRC32(); + crc.update(TargetLoader.getClassDataAsBytes(getClass())); + entry.setCrc(crc.getValue()); + zipout.putNextEntry(entry); zipout.write(TargetLoader.getClassDataAsBytes(getClass())); + zipout.finish(); ByteArrayOutputStream out = new ByteArrayOutputStream(); int count = instrumenter.instrumentAll( new ByteArrayInputStream(buffer.toByteArray()), out, "Test"); - assertEquals(1, count); + assertEquals(2, count); ZipInputStream zipin = new ZipInputStream( new ByteArrayInputStream(out.toByteArray())); - assertEquals("Test.class", zipin.getNextEntry().getName()); + entry = zipin.getNextEntry(); + assertEquals("TestCompressed.class", entry.getName()); + assertEquals(ZipEntry.DEFLATED, entry.getMethod()); + entry = zipin.getNextEntry(); + assertEquals("TestUncompressed.class", entry.getName()); + assertEquals(ZipEntry.STORED, entry.getMethod()); assertNull(zipin.getNextEntry()); } diff --git a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java index e86f8276e9..e171bf5618 100644 --- a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java +++ b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.zip.CRC32; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import java.util.zip.ZipEntry; @@ -216,9 +217,27 @@ private int instrumentZip(final InputStream input, continue; } - zipout.putNextEntry(new ZipEntry(entryName)); - if (!signatureRemover.filterEntry(entryName, zipin, zipout)) { - count += instrumentAll(zipin, zipout, name + "@" + entryName); + final ZipEntry newEntry = new ZipEntry(entryName); + newEntry.setMethod(entry.getMethod()); + switch (entry.getMethod()) { + case ZipEntry.DEFLATED: + zipout.putNextEntry(newEntry); + count += filterOrInstrument(zipin, zipout, name, entryName); + break; + case ZipEntry.STORED: + // Uncompressed entries must be processed in-memory to calculate + // mandatory entry size and CRC + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + count += filterOrInstrument(zipin, buffer, name, entryName); + final byte[] bytes = buffer.toByteArray(); + newEntry.setSize(bytes.length); + newEntry.setCompressedSize(bytes.length); + newEntry.setCrc(crc(bytes)); + zipout.putNextEntry(newEntry); + zipout.write(bytes); + break; + default: + throw new AssertionError(entry.getMethod()); } zipout.closeEntry(); } @@ -226,6 +245,21 @@ private int instrumentZip(final InputStream input, return count; } + private int filterOrInstrument(final InputStream in, final OutputStream out, + final String name, final String entryName) throws IOException { + if (signatureRemover.filterEntry(entryName, in, out)) { + return 0; + } else { + return instrumentAll(in, out, name + "@" + entryName); + } + } + + private static long crc(final byte[] data) { + final CRC32 crc = new CRC32(); + crc.update(data); + return crc.getValue(); + } + private ZipEntry nextEntry(final ZipInputStream input, final String location) throws IOException { try { diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index e466f1c13f..9be7d5be05 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -37,6 +37,13 @@

New Features

(GitHub #1016). +

Fixed bugs

+ +

Non-functional Changes