PatchReader { public PatchApplyPlan readPatchApplyPlan(InputStream in) throws IOException { @SuppressWarnings("resource") DataInputStream dataIn = new DataInputStream(in); byte[] expectedIdentifier = PatchConstants.IDENTIFIER.getBytes("US-ASCII"); byte[] actualIdentifier = new byte[expectedIdentifier.length]; dataIn.readFully(actualIdentifier); if (!Arrays.equals(expectedIdentifier, actualIdentifier)) { throw new PatchFormatException("Bad identifier"); } dataIn.skip(4); long deltaFriendlyOldFileSize = checkNonNegative( dataIn.readLong(), "delta-friendly old file size"); int numOldFileUncompressionInstructions = (int) checkNonNegative( dataIn.readInt(), "old file uncompression instruction count"); List<TypedRange<Void>> oldFileUncompressionPlan = new ArrayList<TypedRange<Void>>(numOldFileUncompressionInstructions); long lastReadOffset = -1; for (int x = 0; x < numOldFileUncompressionInstructions; x++) { long offset = checkNonNegative(dataIn.readLong(), "old file uncompression range offset"); long length = checkNonNegative(dataIn.readLong(), "old file uncompression range length"); if (offset < lastReadOffset) { throw new PatchFormatException("old file uncompression ranges out of order or overlapping"); } TypedRange<Void> range = new TypedRange<Void>(offset, length, null); oldFileUncompressionPlan.add(range); lastReadOffset = offset + length; } int numDeltaFriendlyNewFileRecompressionInstructions = dataIn.readInt(); checkNonNegative( numDeltaFriendlyNewFileRecompressionInstructions, "delta-friendly new file recompression instruction count"); List<TypedRange<JreDeflateParameters>> deltaFriendlyNewFileRecompressionPlan = new ArrayList<TypedRange<JreDeflateParameters>>( numDeltaFriendlyNewFileRecompressionInstructions); lastReadOffset = -1; for (int x = 0; x < numDeltaFriendlyNewFileRecompressionInstructions; x++) { long offset = checkNonNegative( dataIn.readLong(), "delta-friendly new file recompression range offset"); long length = checkNonNegative( dataIn.readLong(), "delta-friendly new file recompression range length"); if (offset < lastReadOffset) { throw new PatchFormatException( "delta-friendly new file recompression ranges out of order or overlapping"); } lastReadOffset = offset + length; checkRange( dataIn.readByte(), PatchConstants.CompatibilityWindowId.DEFAULT_DEFLATE.patchValue, PatchConstants.CompatibilityWindowId.DEFAULT_DEFLATE.patchValue, "compatibility window id"); int level = (int) checkRange(dataIn.readUnsignedByte(), 1, 9, "recompression level"); int strategy = (int) checkRange(dataIn.readUnsignedByte(), 0, 2, "recompression strategy"); int nowrapInt = (int) checkRange(dataIn.readUnsignedByte(), 0, 1, "recompression nowrap"); TypedRange<JreDeflateParameters> range = new TypedRange<JreDeflateParameters>( offset, length, JreDeflateParameters.of(level, strategy, nowrapInt == 0 ? false : true)); deltaFriendlyNewFileRecompressionPlan.add(range); } int numDeltaRecords = (int) checkRange(dataIn.readInt(), 1, 1, "num delta records"); List<DeltaDescriptor> deltaDescriptors = new ArrayList<DeltaDescriptor>(numDeltaRecords); for (int x = 0; x < numDeltaRecords; x++) { byte deltaFormatByte = (byte) checkRange( dataIn.readByte(), PatchConstants.DeltaFormat.BSDIFF.patchValue, PatchConstants.DeltaFormat.BSDIFF.patchValue, "delta format"); long deltaFriendlyOldFileWorkRangeOffset = checkNonNegative( dataIn.readLong(), "delta-friendly old file work range offset"); long deltaFriendlyOldFileWorkRangeLength = checkNonNegative( dataIn.readLong(), "delta-friendly old file work range length"); long deltaFriendlyNewFileWorkRangeOffset = checkNonNegative( dataIn.readLong(), "delta-friendly new file work range offset"); long deltaFriendlyNewFileWorkRangeLength = checkNonNegative( dataIn.readLong(), "delta-friendly new file work range length"); long deltaLength = checkNonNegative(dataIn.readLong(), "delta length"); DeltaDescriptor descriptor = new DeltaDescriptor( PatchConstants.DeltaFormat.fromPatchValue(deltaFormatByte), new TypedRange<Void>( deltaFriendlyOldFileWorkRangeOffset, deltaFriendlyOldFileWorkRangeLength, null), new TypedRange<Void>( deltaFriendlyNewFileWorkRangeOffset, deltaFriendlyNewFileWorkRangeLength, null), deltaLength); deltaDescriptors.add(descriptor); } return new PatchApplyPlan( Collections.unmodifiableList(oldFileUncompressionPlan), deltaFriendlyOldFileSize, Collections.unmodifiableList(deltaFriendlyNewFileRecompressionPlan), Collections.unmodifiableList(deltaDescriptors)); }  PatchApplyPlan readPatchApplyPlan(InputStream in);  }
@Test public void testReadPatchApplyPlan() throws IOException { PatchApplyPlan plan = new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); Assert.assertEquals(DELTA_FRIENDLY_OLD_FILE_SIZE, plan.getDeltaFriendlyOldFileSize()); Assert.assertEquals(OLD_DELTA_FRIENDLY_UNCOMPRESS_PLAN, plan.getOldFileUncompressionPlan()); Assert.assertEquals( NEW_DELTA_FRIENDLY_RECOMPRESS_PLAN, plan.getDeltaFriendlyNewFileRecompressionPlan()); Assert.assertEquals(DELTA_DESCRIPTORS, plan.getDeltaDescriptors()); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyNewFileRecompressionInstructionLength() throws IOException { corruption.corruptDeltaFriendlyNewFileRecompressionInstructionLength = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptCompatibilityWindowId() throws IOException { corruption.corruptCompatibilityWindowId = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptLevel() throws IOException { corruption.corruptLevel = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptStrategy() throws IOException { corruption.corruptStrategy = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptNowrap() throws IOException { corruption.corruptNowrap = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptNumDeltaRecords() throws IOException { corruption.corruptNumDeltaRecords = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaType() throws IOException { corruption.corruptDeltaType = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyOldFileWorkRangeOffset() throws IOException { corruption.corruptDeltaFriendlyOldFileWorkRangeOffset = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyOldFileWorkRangeLength() throws IOException { corruption.corruptDeltaFriendlyOldFileWorkRangeLength = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyNewFileWorkRangeOffset() throws IOException { corruption.corruptDeltaFriendlyNewFileWorkRangeOffset = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptIdentifier() throws IOException { corruption.corruptIdentifier = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyNewFileWorkRangeLength() throws IOException { corruption.corruptDeltaFriendlyNewFileWorkRangeLength = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_DeltaLength() throws IOException { corruption.corruptDeltaLength = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyOldFileSize() throws IOException { corruption.corruptDeltaFriendlyOldFileSize = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptOldFileUncompressionInstructionCount() throws IOException { corruption.corruptOldFileUncompressionInstructionCount = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptOldFileUncompressionInstructionOrder() throws IOException { corruption.corruptOldFileUncompressionInstructionOrder = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptOldFileUncompressionInstructionOffset() throws IOException { corruption.corruptOldFileUncompressionInstructionOffset = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptOldFileUncompressionInstructionLength() throws IOException { corruption.corruptOldFileUncompressionInstructionLength = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyNewFileRecompressionInstructionCount() throws IOException { corruption.corruptDeltaFriendlyNewFileRecompressionInstructionCount = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyNewFileRecompressionInstructionOrder() throws IOException { corruption.corruptDeltaFriendlyNewFileRecompressionInstructionOrder = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }
@Test(expected = PatchFormatException.class) public void testReadPatchApplyPlan_CorruptDeltaFriendlyNewFileRecompressionInstructionOffset() throws IOException { corruption.corruptDeltaFriendlyNewFileRecompressionInstructionOffset = true; new PatchReader().readPatchApplyPlan(new ByteArrayInputStream(writeTestPatch())); }