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 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 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());
        }
Beispiel #4
0
        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());
        }
        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_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 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]);
        }
Beispiel #10
0
        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();
                }
            }
        }
Beispiel #11
0
        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]);
        }
Beispiel #12
0
        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());
        }
Beispiel #13
0
        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));
        }
Beispiel #14
0
        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)));
        }
Beispiel #15
0
        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();
        }
Beispiel #16
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));
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        public void Receive_throws_for_null_outputStream()
        {
            var streamer = new DeltaStreamer();

            streamer.Receive(null, new MemoryStream(), new MemoryStream());
        }
Beispiel #19
0
        public void StreamChunkSize_setter_throws_exception_for_zero_chunk_size()
        {
            var streamer = new DeltaStreamer();

            streamer.StreamChunkSize = 0;
        }
Beispiel #20
0
        public void StreamChunkSize_setter_throws_exception_for_negative_chunk_size()
        {
            var streamer = new DeltaStreamer();

            streamer.StreamChunkSize = -1;
        }
Beispiel #21
0
        public void Send_throws_for_null_deltas()
        {
            var streamer = new DeltaStreamer();

            streamer.Send(null, new MemoryStream(), new MemoryStream());
        }
Beispiel #22
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));
                            }
                        }
                    }
                }
            }
        }
Beispiel #23
0
        public void Send_throws_for_null_output_stream()
        {
            var streamer = new DeltaStreamer();

            streamer.Send(new ByteDelta[10], new MemoryStream(), null);
        }
Beispiel #24
0
        public static void ApplyPatch(string filename, Action <string, int> progressCallback)
        {
            using (FileStream fs = File.OpenRead(filename))
            {
                using (ZipFile zf = new ZipFile(fs))
                {
                    progressCallback(App.resourceManager.GetString("unpacking_patch_info"), 0);

                    List <FileEntry> entries = ParsePatchInfo(ExtractData(zf, "patch_info.txt"));

                    for (int i = 0; i < entries.Count; i++)
                    {
                        int       percent       = (int)(((float)i / entries.Count) * 100);
                        FileEntry entry         = entries[i];
                        string    entryFilename = Path.Combine(App.targetDirectory, entry.filename);
                        Debug.WriteLine(entryFilename);
                        // these files are skipped, maybe skip these in the patch builder instead?
                        if (entryFilename.Contains("Launcher") || entryFilename.Contains("version.txt"))
                        {
                            continue;
                        }

                        if (entry.type == FileEntry.EntryType.Removed)
                        {
                            progressCallback(String.Format(App.resourceManager.GetString("deleting_file"), entry.filename), percent);

                            if (File.Exists(entryFilename))
                            {
                                File.Delete(entryFilename);
                            }
                        }

                        if (entry.type == FileEntry.EntryType.Added)
                        {
                            progressCallback(String.Format(App.resourceManager.GetString("adding_file"), entry.filename), percent);

                            ExtractFile(zf, entry.filename, entryFilename);
                        }

                        if (entry.type == FileEntry.EntryType.Modified)
                        {
                            progressCallback(String.Format(App.resourceManager.GetString("checking_file"), entry.filename), percent);

                            if (checkMD5s)
                            {
                                string md5_old = GetMD5HashFromFile(entryFilename);
                                if (entry.md5Old != md5_old)
                                {
                                    throw new PatcherException(String.Format(App.resourceManager.GetString("invalid_patch"), entryFilename));
                                }
                            }

                            string patched_file = Path.GetTempFileName();

                            progressCallback(String.Format(App.resourceManager.GetString("patching_file"), entry.filename), percent);

                            try
                            {
                                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();
                                    }
                                }
                            }
                            catch (DirectoryNotFoundException ex)
                            {
                                throw new PatcherException(ex.Message);
                            }

                            progressCallback(string.Format(App.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(App.resourceManager.GetString("checking_file"), entry.filename), percent);

                            if (checkMD5s)
                            {
                                string md5New = GetMD5HashFromFile(entryFilename);
                                if (entry.md5New != md5New)
                                {
                                    throw new PatcherException(string.Format(App.resourceManager.GetString("patch_broke_client"), entryFilename));
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #25
0
        public void Receive_throws_for_illegal_command_byte()
        {
            var streamer = new DeltaStreamer();

            streamer.Receive(new MemoryStream(new[] { (byte)'G' }), new MemoryStream(), new MemoryStream());
        }