public static byte[] CreatePatchFor(string filename1, string filename2) { // Compute hashes HashBlock[] hashBlocksFromReceiver; using (FileStream sourceStream = File.Open(filename1, FileMode.Open)) { hashBlocksFromReceiver = new HashBlockGenerator(new RollingChecksum(), new HashAlgorithmWrapper<MD5>(MD5.Create()), blockSize).ProcessStream(sourceStream).ToArray(); } // Compute deltas MemoryStream deltaStream = new MemoryStream(); using (FileStream fileStream = File.Open(filename2, FileMode.Open)) { DeltaGenerator deltaGen = new DeltaGenerator(new RollingChecksum(), new HashAlgorithmWrapper<MD5>(MD5.Create())); deltaGen.Initialize(blockSize, hashBlocksFromReceiver); IEnumerable<IDelta> deltas = deltaGen.GetDeltas(fileStream); deltaGen.Statistics.Dump(); fileStream.Seek(0, SeekOrigin.Begin); DeltaStreamer streamer = new DeltaStreamer(); streamer.Send(deltas, fileStream, deltaStream); } return deltaStream.ToArray(); }
public void Receive_throws_for_unseekable_inputStream() { var inputStreamMock = new Mock<MemoryStream>(MockBehavior.Strict); inputStreamMock.SetupGet(x => x.CanSeek).Returns(false); var streamer = new DeltaStreamer(); streamer.Receive(new MemoryStream(), inputStreamMock.Object, new MemoryStream()); }
static void Main(string[] args) { int blockSize = 512; // Compute hashes IEnumerable<HashBlock> hashBlocksFromReceiver; using (FileStream sourceStream = File.Open("../../dest.bmp", FileMode.Open)) { hashBlocksFromReceiver = new HashBlockGenerator(new RollingChecksum(), new HashAlgorithmWrapper<MD5>(MD5.Create()), blockSize).ProcessStream(sourceStream).ToArray(); } // Stream the hash blocks var hashBlockStream = new MemoryStream(); HashBlockStreamer.Stream(hashBlocksFromReceiver, hashBlockStream); // Receive the hash block stream hashBlockStream.Seek(0, SeekOrigin.Begin); Console.Out.WriteLine("Hash block stream length: {0}", hashBlockStream.Length); hashBlocksFromReceiver = HashBlockStreamer.Destream(hashBlockStream); // Compute deltas var deltaStream = new MemoryStream(); using (FileStream fileStream = File.Open("../../source.bmp", FileMode.Open)) { var deltaGen = new DeltaGenerator(new RollingChecksum(), new HashAlgorithmWrapper<MD5>(MD5.Create())); deltaGen.Initialize(blockSize, hashBlocksFromReceiver); IEnumerable<IDelta> deltas = deltaGen.GetDeltas(fileStream); deltaGen.Statistics.Dump(); fileStream.Seek(0, SeekOrigin.Begin); var streamer = new DeltaStreamer(); streamer.Send(deltas, fileStream, deltaStream); Console.Out.WriteLine("Delta stream length: {0}", deltaStream.Length); } // Rewind the delta stream (obviously wouldn't apply from a network pipe) deltaStream.Seek(0, SeekOrigin.Begin); // Reconstruct file using (FileStream sourceStream = File.Open("../../dest.bmp", FileMode.Open)) { using (FileStream outStream = File.Open("../../reconstructed.bmp", FileMode.Create)) { var streamer = new DeltaStreamer(); streamer.Receive(deltaStream, sourceStream, outStream); outStream.Close(); } } }
public void Receive_copies_data_from_inputStream() { var deltaStream = new MemoryStream(); deltaStream.WriteByte(DeltaStreamer.DeltaStreamConstants.COPY_BLOCK_START_MARKER); deltaStream.WriteLong(4); // Start the copy from byte four deltaStream.WriteInt(10); // Copy 10 bytes deltaStream.Seek(0, SeekOrigin.Begin); var inputStream = new MemoryStream(); // Must have 4 + 10 bytes for (int i = 0; i < 20; ++i) inputStream.WriteByte((byte) (255 - i)); inputStream.Seek(0, SeekOrigin.Begin); var outputStream = new MemoryStream(); var streamer = new DeltaStreamer(); streamer.Receive(deltaStream, inputStream, outputStream); Assert.AreEqual(10, outputStream.Length); outputStream.GetBuffer().Take(14).SequenceEqual(inputStream.GetBuffer().Skip(3).Take(14)); }
public void Receive_throws_for_illegal_command_byte() { var streamer = new DeltaStreamer(); streamer.Receive(new MemoryStream(new[] { (byte) 'G' }), new MemoryStream(), new MemoryStream()); }
public void StreamChunkSize_setter_throws_exception_for_zero_chunk_size() { var streamer = new DeltaStreamer(); streamer.StreamChunkSize = 0; }
public void StreamChunkSize_setter_throws_exception_for_negative_chunk_size() { var streamer = new DeltaStreamer(); streamer.StreamChunkSize = -1; }
public void Send_will_seek_past_input_data_for_copy_delta() { var deltas = new[] {new CopyDelta {Offset = 0, Length = 1234}}; var dataStreamMock = new Mock<MemoryStream>(MockBehavior.Strict); dataStreamMock.Setup(x => x.Seek( It.Is<long>(o => o == 1234), It.Is<SeekOrigin>(o => o == SeekOrigin.Current))) .Returns(1234); dataStreamMock.SetupGet(x => x.CanSeek).Returns(true); var streamer = new DeltaStreamer(); streamer.Send(deltas, dataStreamMock.Object, new MemoryStream()); dataStreamMock.VerifyAll(); }
public void Send_will_read_all_chunks_from_stream_for_byte_delta() { var streamer = new DeltaStreamer(); int chunkSize = 10; streamer.StreamChunkSize = chunkSize; var deltas = new[] {new ByteDelta {Offset = 0, Length = 100}}; var dataStreamMock = new Mock<MemoryStream>(); int totalLengthRead = 0; dataStreamMock.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())) .Returns((byte[] buf, int offset, int length) => { totalLengthRead += length; return length; }); streamer.Send(deltas, dataStreamMock.Object, new MemoryStream()); Assert.AreEqual(100, totalLengthRead); }
public void Send_has_correct_length_for_byte_delta() { var streamer = new DeltaStreamer(); var deltas = new[] {new ByteDelta {Offset = 0, Length = 4}}; var dataStream = new MemoryStream(Encoding.ASCII.GetBytes("TEST")); var outStream = new MemoryStream(); streamer.Send(deltas, dataStream, outStream); Assert.AreEqual(4, BitConverter.ToInt32(outStream.GetBuffer(), 1)); }
public void Send_starts_with_new_command_for_byte_delta() { var streamer = new DeltaStreamer(); var deltas = new[] {new ByteDelta {Offset = 0, Length = 4}}; var dataStream = new MemoryStream(Encoding.ASCII.GetBytes("TEST")); var outStream = new MemoryStream(); streamer.Send(deltas, dataStream, outStream); Assert.AreEqual(DeltaStreamer.DeltaStreamConstants.NEW_BLOCK_START_MARKER, outStream.GetBuffer()[0]); }
public void Receive_writes_new_bytes_from_deltaStream() { var deltaStream = new MemoryStream(); deltaStream.WriteByte(DeltaStreamer.DeltaStreamConstants.NEW_BLOCK_START_MARKER); deltaStream.WriteInt(10); // Write 10 bytes for (int i = 0; i < 10; ++i) deltaStream.WriteByte((byte) (200 - i)); deltaStream.Seek(0, SeekOrigin.Begin); var inputStream = new MemoryStream(); // empty var outputStream = new MemoryStream(); var streamer = new DeltaStreamer(); streamer.Receive(deltaStream, inputStream, outputStream); Assert.AreEqual(10, outputStream.Length); outputStream.GetBuffer().Take(10).SequenceEqual(deltaStream.GetBuffer().Skip(5).Take(10)); }
public void Send_throws_for_null_deltas() { var streamer = new DeltaStreamer(); streamer.Send(null, new MemoryStream(), new MemoryStream()); }
public void Send_throws_for_inputStream_with_insufficient_data_for_byte_delta() { var deltas = new[] {new ByteDelta {Offset = 0, Length = 3}}; var dataStream = new MemoryStream(new byte[2]); var streamer = new DeltaStreamer(); streamer.Send(deltas, dataStream, new MemoryStream()); }
public void Send_throws_for_inputStream_without_forward_seekability_for_copy_delta() { var deltas = new[] {new CopyDelta {Offset = 0, Length = 1234}}; var dataStreamMock = new Mock<MemoryStream>(MockBehavior.Strict); dataStreamMock.SetupGet(x => x.CanSeek).Returns(false); var streamer = new DeltaStreamer(); streamer.Send(deltas, dataStreamMock.Object, new MemoryStream()); }
public void Send_throws_for_empty_delta_array() { var deltas = new List<IDelta>(); var streamer = new DeltaStreamer(); streamer.Send(deltas, new MemoryStream(), new MemoryStream()); }
public void Send_throws_for_delta_out_of_inputStream_bounds_for_byte_delta() { var deltas = new[] {new ByteDelta {Offset = 3, Length = 3}}; var dataStream = new MemoryStream(new byte[2]); var streamer = new DeltaStreamer(); streamer.Send(deltas, dataStream, new MemoryStream()); }
public void Receive_throws_for_null_outputStream() { var streamer = new DeltaStreamer(); streamer.Receive(null, new MemoryStream(), new MemoryStream()); }
public void Send_has_correct_offset_for_copy_delta() { var streamer = new DeltaStreamer(); var deltas = new[] {new CopyDelta {Offset = 42, Length = 24}}; var outStream = new MemoryStream(); streamer.Send(deltas, new MemoryStream(), outStream); Assert.AreEqual(42, BitConverter.ToInt64(outStream.GetBuffer(), 1)); }
public void Send_starts_with_copy_command_for_copy_delta() { var streamer = new DeltaStreamer(); var deltas = new[] {new CopyDelta {Offset = 42, Length = 24}}; var outStream = new MemoryStream(); streamer.Send(deltas, new MemoryStream(), outStream); Assert.AreEqual(DeltaStreamer.DeltaStreamConstants.COPY_BLOCK_START_MARKER, outStream.GetBuffer()[0]); }
public static void ApplyPatch(string filename, Action<string, int> progressCallback) { using (FileStream fs = File.OpenRead(filename)) { using (ZipFile zf = new ZipFile(fs)) { progressCallback(Program.resourceManager.GetString("unpacking_patch_info"), 0); List<FileEntry> entryes = ParsePatchInfo(ExtractData(zf, "patch_info.txt")); for (int i = 0; i < entryes.Count; i++) { int percent = (int)(((float)i / entryes.Count) * 100); FileEntry entry = entryes[i]; string entryFilename = Path.Combine(Program.targetDirectory, entry.filename); if (entry.type == FileEntry.EntryType.Removed) { progressCallback(string.Format(Program.resourceManager.GetString("deleting_file"), entry.filename), percent); if (File.Exists(entryFilename)) File.Delete(entryFilename); } if (entry.type == FileEntry.EntryType.Added) { progressCallback(string.Format(Program.resourceManager.GetString("adding_file"), entry.filename), percent); ExtractFile(zf, entry.filename, entryFilename); } if (entry.type == FileEntry.EntryType.Modified) { progressCallback(string.Format(Program.resourceManager.GetString("checking_file"), entry.filename), percent); string md5_old = GetMD5HashFromFile(entryFilename); if (entry.md5Old != md5_old) throw new PatcherException(string.Format(Program.resourceManager.GetString("invalid_patch"), entryFilename)); string patched_file = Path.GetTempFileName(); progressCallback(string.Format(Program.resourceManager.GetString("patching_file"), entry.filename), percent); using (FileStream sourceStream = File.Open(entryFilename, FileMode.Open)) { using (FileStream outStream = File.Open(patched_file, FileMode.Create)) { DeltaStreamer streamer = new DeltaStreamer(); streamer.Receive(ExtractStream(zf, entry.filename), sourceStream, outStream); outStream.Close(); } } progressCallback(string.Format(Program.resourceManager.GetString("copying_file"), entry.filename), percent); File.Copy(patched_file, entryFilename, true); File.Delete(patched_file); } if (entry.type == FileEntry.EntryType.Added || entry.type == FileEntry.EntryType.Modified) { progressCallback(string.Format(Program.resourceManager.GetString("checking_file"), entry.filename), percent); string md5New = GetMD5HashFromFile(entryFilename); if (entry.md5New != md5New) throw new PatcherException(string.Format(Program.resourceManager.GetString("patch_broke_client"), entryFilename)); } } } } }
public void Send_throws_for_null_output_stream() { var streamer = new DeltaStreamer(); streamer.Send(new ByteDelta[10], new MemoryStream(), null); }
public void Send_will_chunk_data_reads_into_provided_sizes_for_byte_delta() { var streamer = new DeltaStreamer(); int chunkSize = 10; streamer.StreamChunkSize = chunkSize; var deltas = new[] {new ByteDelta {Offset = 0, Length = 100}}; var dataStreamMock = new Mock<MemoryStream>(); dataStreamMock.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())) .Returns((byte[] buf, int offset, int length) => { if (length > chunkSize) Assert.Fail("Invalid read size"); return length; }); streamer.Send(deltas, dataStreamMock.Object, new MemoryStream()); }
public void Send_has_correct_data_for_byte_delta() { var streamer = new DeltaStreamer(); streamer.StreamChunkSize = 2; var deltas = new[] {new ByteDelta {Offset = 0, Length = 4}}; var dataStream = new MemoryStream(Encoding.ASCII.GetBytes("TEST")); var outStream = new MemoryStream(); streamer.Send(deltas, dataStream, outStream); Assert.IsTrue(Encoding.ASCII.GetBytes("TEST").SequenceEqual(outStream.GetBuffer().Skip(5).Take(4))); }