aboutsummaryrefslogtreecommitdiff
path: root/generator
diff options
context:
space:
mode:
Diffstat (limited to 'generator')
-rw-r--r--generator/src/main/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDiviner.java192
-rw-r--r--generator/src/main/java/com/google/archivepatcher/generator/FileByFileV1DeltaGenerator.java27
-rw-r--r--generator/src/main/java/com/google/archivepatcher/generator/MatchingOutputStream.java5
-rw-r--r--generator/src/main/java/com/google/archivepatcher/generator/PreDiffPlanner.java39
-rw-r--r--generator/src/main/java/com/google/archivepatcher/generator/RecommendationReason.java5
-rw-r--r--generator/src/test/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDivinerTest.java96
-rw-r--r--generator/src/test/java/com/google/archivepatcher/generator/PreDiffPlannerTest.java12
-rw-r--r--generator/src/test/java/com/google/archivepatcher/generator/bsdiff/BsDiffTest.java9
8 files changed, 183 insertions, 202 deletions
diff --git a/generator/src/main/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDiviner.java b/generator/src/main/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDiviner.java
index 636504d..d0c7a8b 100644
--- a/generator/src/main/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDiviner.java
+++ b/generator/src/main/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDiviner.java
@@ -14,10 +14,10 @@
package com.google.archivepatcher.generator;
+import com.google.archivepatcher.shared.ByteArrayInputStreamFactory;
import com.google.archivepatcher.shared.DefaultDeflateCompatibilityWindow;
import com.google.archivepatcher.shared.JreDeflateParameters;
import com.google.archivepatcher.shared.MultiViewInputStreamFactory;
-import com.google.archivepatcher.shared.RandomAccessFileInputStream;
import com.google.archivepatcher.shared.RandomAccessFileInputStreamFactory;
import java.io.File;
import java.io.IOException;
@@ -41,15 +41,13 @@ import java.util.zip.ZipException;
*/
public class DefaultDeflateCompressionDiviner {
- /**
- * The levels to try for each strategy, in the order to attempt them.
- */
- private final Map<Integer, List<Integer>> levelsByStrategy = getLevelsByStrategy();
+ /** The levels to try for each strategy, in the order to attempt them. */
+ private static final Map<Integer, List<Integer>> LEVELS_BY_STRATEGY = getLevelsByStrategy();
/**
* A simple struct that contains a {@link MinimalZipEntry} describing a specific entry from a zip
* archive along with an optional accompanying {@link JreDeflateParameters} describing the
- * original compression settings that were used to generate the compressed data in that entry.
+ * original compression settings that were used to generate the compressed delivery in that entry.
*/
public static class DivinationResult {
/**
@@ -91,17 +89,30 @@ public class DefaultDeflateCompressionDiviner {
* @see DivinationResult
*/
public List<DivinationResult> divineDeflateParameters(File archiveFile) throws IOException {
- List<DivinationResult> results = new ArrayList<DivinationResult>();
+ List<DivinationResult> results = new ArrayList<>();
for (MinimalZipEntry minimalZipEntry : MinimalZipArchive.listEntries(archiveFile)) {
JreDeflateParameters divinedParameters = null;
if (minimalZipEntry.isDeflateCompressed()) {
- // TODO(andrewhayden): Reuse streams to avoid churning file descriptors
- RandomAccessFileInputStreamFactory rafisFactory =
+ // TODO(pasc): Reuse streams to avoid churning file descriptors
+ MultiViewInputStreamFactory isFactory =
new RandomAccessFileInputStreamFactory(
archiveFile,
minimalZipEntry.getFileOffsetOfCompressedData(),
minimalZipEntry.getCompressedSize());
- divinedParameters = divineDeflateParameters(rafisFactory);
+
+ // Keep small entries in memory to avoid unnecessary file I/O.
+ if (minimalZipEntry.getCompressedSize() < (100 * 1024)) {
+ try (InputStream is = isFactory.newStream()) {
+ byte[] compressedBytes = new byte[(int) minimalZipEntry.getCompressedSize()];
+ is.read(compressedBytes);
+ divinedParameters =
+ divineDeflateParameters(new ByteArrayInputStreamFactory(compressedBytes));
+ } catch (Exception ignore) {
+ divinedParameters = null;
+ }
+ } else {
+ divinedParameters = divineDeflateParameters(isFactory);
+ }
}
results.add(new DivinationResult(minimalZipEntry, divinedParameters));
}
@@ -121,124 +132,103 @@ public class DefaultDeflateCompressionDiviner {
*
* @return such a mapping
*/
- protected Map<Integer, List<Integer>> getLevelsByStrategy() {
- final Map<Integer, List<Integer>> levelsByStrategy = new HashMap<Integer, List<Integer>>();
+ private static Map<Integer, List<Integer>> getLevelsByStrategy() {
+ final Map<Integer, List<Integer>> levelsByStrategy = new HashMap<>();
// The best order for the levels is simply the order of popularity in the world, which is
// expected to be default (6), maximum compression (9), and fastest (1).
// The rest of the levels are rarely encountered and their order is mostly irrelevant.
levelsByStrategy.put(0, Collections.unmodifiableList(Arrays.asList(6, 9, 1, 4, 2, 3, 5, 7, 8)));
levelsByStrategy.put(1, Collections.unmodifiableList(Arrays.asList(6, 9, 4, 5, 7, 8)));
+ // Strategy 2 does not have the concept of levels, so vacuously call it 1.
levelsByStrategy.put(2, Collections.singletonList(1));
return Collections.unmodifiableMap(levelsByStrategy);
}
/**
* Determines the original {@link JreDeflateParameters} that were used to compress a given piece
- * of deflated data.
+ * of deflated delivery.
+ *
* @param compressedDataInputStreamFactory a {@link MultiViewInputStreamFactory} that can provide
- * multiple independent {@link InputStream} instances for the compressed data; the streams
- * produced must support {@link InputStream#mark(int)} and it is recommended that
- * {@link RandomAccessFileInputStream} instances be provided for efficiency if a backing file is
- * available. The stream will be reset for each recompression attempt that is required.
- * @return the parameters that can be used to replicate the compressed data in the
- * {@link DefaultDeflateCompatibilityWindow}, if any; otherwise <code>null</code>. Note that
- * <code>null</code> is also returned in the case of <em>corrupt</em> zip data since, by
- * definition, it cannot be replicated via any combination of normal deflate parameters.
- * @throws IOException if there is a problem reading the data, i.e. if the file contents are
- * changed while reading
+ * multiple independent {@link InputStream} instances for the compressed delivery.
+ * @return the parameters that can be used to replicate the compressed delivery in the {@link
+ * DefaultDeflateCompatibilityWindow}, if any; otherwise <code>null</code>. Note that <code>
+ * null</code> is also returned in the case of <em>corrupt</em> zip delivery since, by definition,
+ * it cannot be replicated via any combination of normal deflate parameters.
+ * @throws IOException if there is a problem reading the delivery, i.e. if the file contents are
+ * changed while reading
*/
public JreDeflateParameters divineDeflateParameters(
- MultiViewInputStreamFactory<?> compressedDataInputStreamFactory) throws IOException {
- InputStream compressedDataIn = compressedDataInputStreamFactory.newStream();
- if (!compressedDataIn.markSupported()) {
- try {
- compressedDataIn.close();
- } catch (Exception ignored) {
- // Nothing to do.
- }
- throw new IllegalArgumentException("input stream must support mark(int)");
- }
-
- // Record the input stream position to return to it each time a prediction is needed.
- compressedDataIn.mark(0); // The argument to mark is ignored and irrelevant
+ MultiViewInputStreamFactory compressedDataInputStreamFactory) throws IOException {
+ byte[] copyBuffer = new byte[32 * 1024];
+ // Iterate over all relevant combinations of nowrap, strategy and level.
+ for (boolean nowrap : new boolean[] {true, false}) {
+ Inflater inflater = new Inflater(nowrap);
+ Deflater deflater = new Deflater(0, nowrap);
- // Make a copy of the stream for matching bytes of compressed input
- InputStream matchingCompressedDataIn = compressedDataInputStreamFactory.newStream();
- matchingCompressedDataIn.mark(0); // The argument to mark is ignored and irrelevant
-
- byte[] copyBuffer = new byte[32768];
- try {
- // Iterate over all relevant combinations of nowrap, strategy and level.
- for (boolean nowrap : new boolean[] {true, false}) {
- Inflater inflater = new Inflater(nowrap);
- Deflater deflater = new Deflater(0, nowrap);
- for (int strategy : new int[] {0, 1, 2}) {
- deflater.setStrategy(strategy);
- // Strategy 2 does not have the concept of levels, so vacuously call it 1.
- List<Integer> levelsToSearch = levelsByStrategy.get(strategy);
- for (int levelIndex = 0; levelIndex < levelsToSearch.size(); levelIndex++) {
- int level = levelsToSearch.get(levelIndex);
- deflater.setLevel(level);
- inflater.reset();
- deflater.reset();
- compressedDataIn.reset();
- matchingCompressedDataIn.reset();
- try {
- if (matches(
- compressedDataIn, inflater, deflater, matchingCompressedDataIn, copyBuffer)) {
- return JreDeflateParameters.of(level, strategy, nowrap);
- }
- } catch (ZipException e) {
- // Parse error in input. The only possibilities are corruption or the wrong nowrap.
- // Skip all remaining levels and strategies.
- levelIndex = levelsToSearch.size();
- strategy = 2;
+ strategy_loop:
+ for (int strategy : new int[] {0, 1, 2}) {
+ deflater.setStrategy(strategy);
+ for (int level : LEVELS_BY_STRATEGY.get(strategy)) {
+ deflater.setLevel(level);
+ inflater.reset();
+ deflater.reset();
+ try {
+ if (matches(inflater, deflater, compressedDataInputStreamFactory, copyBuffer)) {
+ end(inflater, deflater);
+ return JreDeflateParameters.of(level, strategy, nowrap);
}
- } // end of iteration on level
- } // end of iteration on strategy
- } // end of iteration on nowrap
- } finally {
- try {
- compressedDataIn.close();
- } catch (Exception ignored) {
- // Don't care.
- }
- try {
- matchingCompressedDataIn.close();
- } catch (Exception ignored) {
- // Don't care.
+ } catch (ZipException e) {
+ // Parse error in input. The only possibilities are corruption or the wrong nowrap.
+ // Skip all remaining levels and strategies.
+ break strategy_loop;
+ }
+ }
}
+ end(inflater, deflater);
}
return null;
}
/**
- * Check if the specified deflater will produce the same compressed data as the byte stream in
- * compressedDataIn and returns true if so.
- * @param compressedDataIn the stream of compressed data to read and reproduce
+ * Closes the (de)compressor and discards any unprocessed input. This method should be called when
+ * the (de)compressor is no longer being used. Once this method is called, the behavior
+ * De/Inflater is undefined.
+ *
+ * @see Inflater#end
+ * @see Deflater#end
+ */
+ private static void end(Inflater inflater, Deflater deflater) {
+ inflater.end();
+ deflater.end();
+ }
+
+ /**
+ * Checks whether the specified deflater will produce the same compressed delivery as the byte
+ * stream.
+ *
* @param inflater the inflater for uncompressing the stream
* @param deflater the deflater for recompressing the output of the inflater
- * @param matchingStreamInput an independent but identical view of the bytes in compressedDataIn
* @param copyBuffer buffer to use for copying bytes between the inflater and the deflater
* @return true if the specified deflater reproduces the bytes in compressedDataIn, otherwise
- * false
+ * false
* @throws IOException if anything goes wrong; in particular, {@link ZipException} is thrown if
- * there is a problem parsing compressedDataIn
+ * there is a problem parsing compressedDataIn
*/
private boolean matches(
- InputStream compressedDataIn,
Inflater inflater,
Deflater deflater,
- InputStream matchingStreamInput,
+ MultiViewInputStreamFactory compressedDataInputStreamFactory,
byte[] copyBuffer)
throws IOException {
- MatchingOutputStream matcher = new MatchingOutputStream(matchingStreamInput, 32768);
- // This stream will deliberately be left open because closing it would close the
- // underlying compressedDataIn stream, which is not desired.
- InflaterInputStream inflaterIn = new InflaterInputStream(compressedDataIn, inflater, 32768);
- DeflaterOutputStream out = new DeflaterOutputStream(matcher, deflater, 32768);
- int numRead = 0;
- try {
+
+ try (MatchingOutputStream matcher =
+ new MatchingOutputStream(
+ compressedDataInputStreamFactory.newStream(), copyBuffer.length);
+ InflaterInputStream inflaterIn =
+ new InflaterInputStream(
+ compressedDataInputStreamFactory.newStream(), inflater, copyBuffer.length);
+ DeflaterOutputStream out = new DeflaterOutputStream(matcher, deflater, copyBuffer.length)) {
+ int numRead;
while ((numRead = inflaterIn.read(copyBuffer)) >= 0) {
out.write(copyBuffer, 0, numRead);
}
@@ -247,19 +237,13 @@ public class DefaultDeflateCompressionDiviner {
out.finish();
out.flush();
matcher.expectEof();
- // At this point the data in the compressed output stream was a perfect match for the
- // data in the compressed input stream; the answer has been found.
+ // At this point the delivery in the compressed output stream was a perfect match for the
+ // delivery in the compressed input stream; the answer has been found.
return true;
} catch (MismatchException e) {
// Fast-fail case when the compressed output stream doesn't match the compressed input
// stream. These are not the parameters you're looking for!
- } finally {
- try {
- out.close();
- } catch (Exception ignored) {
- // Don't care.
- }
+ return false;
}
- return false;
}
}
diff --git a/generator/src/main/java/com/google/archivepatcher/generator/FileByFileV1DeltaGenerator.java b/generator/src/main/java/com/google/archivepatcher/generator/FileByFileV1DeltaGenerator.java
index 8c81761..c704811 100644
--- a/generator/src/main/java/com/google/archivepatcher/generator/FileByFileV1DeltaGenerator.java
+++ b/generator/src/main/java/com/google/archivepatcher/generator/FileByFileV1DeltaGenerator.java
@@ -93,6 +93,33 @@ public class FileByFileV1DeltaGenerator implements DeltaGenerator {
}
}
+ /**
+ * Generate a V1 patch pre diffing plan.
+ *
+ * @param oldFile the original old file to read (will not be modified)
+ * @param newFile the original new file to read (will not be modified)
+ * @return the plan
+ * @throws IOException if unable to complete the operation due to an I/O error
+ * @throws InterruptedException if any thread has interrupted the current thread
+ */
+ public PreDiffPlan generatePreDiffPlan(File oldFile, File newFile)
+ throws IOException, InterruptedException {
+ try (TempFileHolder deltaFriendlyOldFile = new TempFileHolder();
+ TempFileHolder deltaFriendlyNewFile = new TempFileHolder()) {
+ PreDiffExecutor.Builder builder =
+ new PreDiffExecutor.Builder()
+ .readingOriginalFiles(oldFile, newFile)
+ .writingDeltaFriendlyFiles(deltaFriendlyOldFile.file, deltaFriendlyNewFile.file);
+ for (RecommendationModifier modifier : recommendationModifiers) {
+ builder.withRecommendationModifier(modifier);
+ }
+
+ PreDiffExecutor executor = builder.build();
+
+ return executor.prepareForDiffing();
+ }
+ }
+
// Visible for testing only
protected DeltaGenerator getDeltaGenerator() {
return new BsDiffDeltaGenerator();
diff --git a/generator/src/main/java/com/google/archivepatcher/generator/MatchingOutputStream.java b/generator/src/main/java/com/google/archivepatcher/generator/MatchingOutputStream.java
index f1369d2..f3c5363 100644
--- a/generator/src/main/java/com/google/archivepatcher/generator/MatchingOutputStream.java
+++ b/generator/src/main/java/com/google/archivepatcher/generator/MatchingOutputStream.java
@@ -86,6 +86,11 @@ public class MatchingOutputStream extends OutputStream {
}
}
+ @Override
+ public void close() throws IOException {
+ expectedBytesStream.close();
+ }
+
/**
* Expects the end-of-file to be reached in the associated {@link InputStream}.
* @throws IOException if the end-of-file has not yet been reached in the associated
diff --git a/generator/src/main/java/com/google/archivepatcher/generator/PreDiffPlanner.java b/generator/src/main/java/com/google/archivepatcher/generator/PreDiffPlanner.java
index 6b2d1ee..7b037ea 100644
--- a/generator/src/main/java/com/google/archivepatcher/generator/PreDiffPlanner.java
+++ b/generator/src/main/java/com/google/archivepatcher/generator/PreDiffPlanner.java
@@ -199,6 +199,16 @@ class PreDiffPlanner {
throws IOException {
// Reject anything that is unsuitable for uncompressed diffing.
+ // Reason singled out in order to monitor unsupported versions of zlib.
+ if (unsuitableDeflate(newEntry)) {
+ return new QualifiedRecommendation(
+ oldEntry,
+ newEntry,
+ Recommendation.UNCOMPRESS_NEITHER,
+ RecommendationReason.DEFLATE_UNSUITABLE);
+ }
+
+ // Reject anything that is unsuitable for uncompressed diffing.
if (unsuitable(oldEntry, newEntry)) {
return new QualifiedRecommendation(
oldEntry,
@@ -257,7 +267,8 @@ class PreDiffPlanner {
/**
* Returns true if the entries are unsuitable for doing an uncompressed diff. This method returns
* true if either of the entries is compressed in an unsupported way (a non-deflate compression
- * algorithm) or if the new entry is compressed in a supported but unreproducible way.
+ * algorithm).
+ *
* @param oldEntry the entry in the old archive
* @param newEntry the entry in the new archive
* @return true if unsuitable
@@ -272,6 +283,18 @@ class PreDiffPlanner {
// The new entry is compressed in a way that is not supported. Same result as above.
return true;
}
+ return false;
+ }
+
+ /**
+ * Returns true if the entries are unsuitable for doing an uncompressed diff as a result of the
+ * new entry being compressed via deflate, with undivinable parameters. This could be the result
+ * of an unsupported version of zlib being used.
+ *
+ * @param newEntry the entry in the new archive
+ * @return true if unsuitable
+ */
+ private boolean unsuitableDeflate(MinimalZipEntry newEntry) {
JreDeflateParameters newJreDeflateParameters =
newArchiveJreDeflateParametersByPath.get(new ByteArrayHolder(newEntry.getFileNameBytes()));
if (newEntry.isDeflateCompressed() && newJreDeflateParameters == null) {
@@ -279,6 +302,7 @@ class PreDiffPlanner {
// new entry cannot be recompressed, so leave both old and new alone.
return true;
}
+
return false;
}
@@ -339,13 +363,16 @@ class PreDiffPlanner {
}
byte[] buffer = new byte[4096];
int numRead = 0;
- try (RandomAccessFileInputStream oldRafis =
- new RandomAccessFileInputStream(
- oldFile, oldEntry.getFileOffsetOfCompressedData(), oldEntry.getCompressedSize());
- RandomAccessFileInputStream newRafis =
+ try (RandomAccessFileInputStream newRafis =
new RandomAccessFileInputStream(
newFile, newEntry.getFileOffsetOfCompressedData(), newEntry.getCompressedSize());
- MatchingOutputStream matcher = new MatchingOutputStream(oldRafis, 4096)) {
+ MatchingOutputStream matcher =
+ new MatchingOutputStream(
+ new RandomAccessFileInputStream(
+ oldFile,
+ oldEntry.getFileOffsetOfCompressedData(),
+ oldEntry.getCompressedSize()),
+ 4096)) {
while ((numRead = newRafis.read(buffer)) >= 0) {
try {
matcher.write(buffer, 0, numRead);
diff --git a/generator/src/main/java/com/google/archivepatcher/generator/RecommendationReason.java b/generator/src/main/java/com/google/archivepatcher/generator/RecommendationReason.java
index 664944b..129428b 100644
--- a/generator/src/main/java/com/google/archivepatcher/generator/RecommendationReason.java
+++ b/generator/src/main/java/com/google/archivepatcher/generator/RecommendationReason.java
@@ -19,6 +19,11 @@ package com.google.archivepatcher.generator;
*/
public enum RecommendationReason {
/**
+ * The entry in the new file is compressed using deflate in a way that cannot be reliably
+ * reproduced. This could be caused by using an unsupported version of zlib.
+ */
+ DEFLATE_UNSUITABLE,
+ /**
* The entry in the new file is compressed in a way that cannot be reliably reproduced (or one of
* the entries is compressed using something other than deflate, but this is very uncommon).
*/
diff --git a/generator/src/test/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDivinerTest.java b/generator/src/test/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDivinerTest.java
index 057c790..c712a2b 100644
--- a/generator/src/test/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDivinerTest.java
+++ b/generator/src/test/java/com/google/archivepatcher/generator/DefaultDeflateCompressionDivinerTest.java
@@ -15,25 +15,22 @@
package com.google.archivepatcher.generator;
import com.google.archivepatcher.generator.DefaultDeflateCompressionDiviner.DivinationResult;
+import com.google.archivepatcher.shared.ByteArrayInputStreamFactory;
import com.google.archivepatcher.shared.DefaultDeflateCompatibilityWindow;
import com.google.archivepatcher.shared.DeflateCompressor;
import com.google.archivepatcher.shared.JreDeflateParameters;
-import com.google.archivepatcher.shared.MultiViewInputStreamFactory;
import com.google.archivepatcher.shared.UnitTestZipArchive;
import com.google.archivepatcher.shared.UnitTestZipEntry;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
/**
* Tests for {@link DefaultDeflateCompressionDiviner}.
@@ -47,7 +44,7 @@ public class DefaultDeflateCompressionDivinerTest {
private DefaultDeflateCompressionDiviner diviner = null;
/**
- * Test data written to the file.
+ * Test delivery written to the file.
*/
private byte[] testData = null;
@@ -58,10 +55,10 @@ public class DefaultDeflateCompressionDivinerTest {
}
/**
- * Deflates the test data using the specified parameters, storing them in a temp file and
+ * Deflates the test delivery using the specified parameters, storing them in a temp file and
* returns the temp file created.
* @param parameters the parameters to use for deflating
- * @return the temp file with the data
+ * @return the temp file with the delivery
*/
private byte[] deflate(JreDeflateParameters parameters) throws IOException {
DeflateCompressor compressor = new DeflateCompressor();
@@ -73,74 +70,10 @@ public class DefaultDeflateCompressionDivinerTest {
return buffer.toByteArray();
}
- private static class ByteArrayInputStreamFactory
- implements MultiViewInputStreamFactory<ByteArrayInputStream> {
- private final byte[] data;
- private final boolean supportMark;
- private final boolean dieOnClose;
-
- /**
- * Create a factory the returns streams on the specified data buffer, optionally supporting
- * {@link InputStream#mark(int)}.
- * @param data the data buffer to return streams for
- * @param supportMark whether or not to support marking
- * @param dieOnClose whether or not to throw nasty exceptions on close()
- */
- public ByteArrayInputStreamFactory(byte[] data, boolean supportMark, boolean dieOnClose) {
- this.data = data;
- this.supportMark = supportMark;
- this.dieOnClose = dieOnClose;
- }
-
- @Override
- public ByteArrayInputStream newStream() throws IOException {
- return new ByteArrayInputStream(data) {
- @Override
- public boolean markSupported() {
- return supportMark;
- }
-
- @Override
- public void close() throws IOException {
- if (dieOnClose) {
- throw new IOException("brainnnnnnnnnnssssss!");
- }
- super.close();
- }
- };
- }
- }
-
- @Test
- public void testDivineDeflateParameters_NoMarkInputStreamFactory() throws IOException {
- final JreDeflateParameters parameters = JreDeflateParameters.of(1, 0, true);
- final byte[] buffer = deflate(parameters);
- try {
- // The factory here will NOT support mark(int), which should cause failure. Also, throw
- // exceptions on close() to be extra rude.
- diviner.divineDeflateParameters(new ByteArrayInputStreamFactory(buffer, false, true));
- Assert.fail("operating without a markable stream");
- } catch (IllegalArgumentException expected) {
- // Correct!
- }
- }
-
- @Test
- public void testDivineDeflateParameters_BadCloseInputStreamFactory() throws IOException {
- final JreDeflateParameters parameters = JreDeflateParameters.of(1, 0, true);
- final byte[] buffer = deflate(parameters);
- // The factory here will produce streams that throw exceptions when close() is called.
- // These exceptions should be ignored.
- JreDeflateParameters result =
- diviner.divineDeflateParameters(new ByteArrayInputStreamFactory(buffer, true, true));
- Assert.assertEquals(result, parameters);
- }
-
@Test
public void testDivineDeflateParameters_JunkData() throws IOException {
final byte[] junk = new byte[] {0, 1, 2, 3, 4};
- Assert.assertNull(
- diviner.divineDeflateParameters(new ByteArrayInputStreamFactory(junk, true, false)));
+ Assert.assertNull(diviner.divineDeflateParameters(new ByteArrayInputStreamFactory(junk)));
}
@Test
@@ -150,14 +83,15 @@ public class DefaultDeflateCompressionDivinerTest {
for (int level : new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9}) {
JreDeflateParameters trueParameters = JreDeflateParameters.of(level, strategy, nowrap);
final byte[] buffer = deflate(trueParameters);
- ByteArrayInputStreamFactory factory =
- new ByteArrayInputStreamFactory(buffer, true, false);
- JreDeflateParameters divinedParameters = diviner.divineDeflateParameters(factory);
+ JreDeflateParameters divinedParameters =
+ diviner.divineDeflateParameters(new ByteArrayInputStreamFactory(buffer));
Assert.assertNotNull(divinedParameters);
// TODO(andrewhayden) make *CERTAIN 100%( that strategy doesn't matter for level < 4.
if (strategy == 1 && level <= 3) {
// Strategy 1 produces identical output at levels 1, 2 and 3.
- Assert.assertEquals(JreDeflateParameters.of(level, 0, nowrap), divinedParameters);
+ Assert.assertEquals(
+ /*expected=*/ JreDeflateParameters.of(level, 0, nowrap),
+ /*actual=*/ divinedParameters);
} else if (strategy == 2) {
// All levels are the same with strategy 2.
// TODO: Assert only one test gets done for this, should be the first level always.
diff --git a/generator/src/test/java/com/google/archivepatcher/generator/PreDiffPlannerTest.java b/generator/src/test/java/com/google/archivepatcher/generator/PreDiffPlannerTest.java
index 9ba39e5..38b4c6b 100644
--- a/generator/src/test/java/com/google/archivepatcher/generator/PreDiffPlannerTest.java
+++ b/generator/src/test/java/com/google/archivepatcher/generator/PreDiffPlannerTest.java
@@ -435,11 +435,13 @@ public class PreDiffPlannerTest {
// the plan for the new archive should be empty as well.
Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
- checkRecommendation(plan, new QualifiedRecommendation(
- findEntry(oldFile, ENTRY_A_STORED),
- findEntry(newFile, ENTRY_A_LEVEL_6),
- Recommendation.UNCOMPRESS_NEITHER,
- RecommendationReason.UNSUITABLE));
+ checkRecommendation(
+ plan,
+ new QualifiedRecommendation(
+ findEntry(oldFile, ENTRY_A_STORED),
+ findEntry(newFile, ENTRY_A_LEVEL_6),
+ Recommendation.UNCOMPRESS_NEITHER,
+ RecommendationReason.DEFLATE_UNSUITABLE));
}
@Test
diff --git a/generator/src/test/java/com/google/archivepatcher/generator/bsdiff/BsDiffTest.java b/generator/src/test/java/com/google/archivepatcher/generator/bsdiff/BsDiffTest.java
index 2a7d7ae..16d74af 100644
--- a/generator/src/test/java/com/google/archivepatcher/generator/bsdiff/BsDiffTest.java
+++ b/generator/src/test/java/com/google/archivepatcher/generator/bsdiff/BsDiffTest.java
@@ -15,17 +15,13 @@
package com.google.archivepatcher.generator.bsdiff;
import com.google.archivepatcher.generator.bsdiff.Matcher.NextMatch;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -254,6 +250,7 @@ public class BsDiffTest {
Assert.assertArrayEquals(actualPatch, expectedPatch);
}
+ @Test
public void generatePatchOnRealCompiledBinaryTest() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] oldData = readTestData("minimalBlobA.bin");