public void ShouldTellIfContentsAreDifferent() { var leftArray = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // AQIDBAUGBwgJCgsM var rightArray = new byte[] { 1, 2, 3, 7, 6, 5, 4, 8, 9, 10, 11, 13 }; // AQIDBwYFBAgJCgsN var left = Convert.ToBase64String(leftArray); var right = Convert.ToBase64String(rightArray); var record = new DiffRecord { Left = left, Right = right }; _sut.RefreshDiff(record); record.Analysis.Should().NotBeNull(); record.Analysis.EqualSize.Should().BeTrue(); record.Analysis.EqualContent.Should().BeFalse(); record.Analysis.Offsets.Count.Should().Be(4); record.Analysis.Offsets.Should().BeEquivalentTo( new DiffRecord.DiffOffset { IsEqual = true, Length = 3 }, new DiffRecord.DiffOffset { IsEqual = false, Length = 4 }, new DiffRecord.DiffOffset { IsEqual = true, Length = 4 }, new DiffRecord.DiffOffset { IsEqual = false, Length = 1 }); }
public void ShouldNotAcceptInvalidBase64() { var record = new DiffRecord { Left = "not-valid", Right = "not-valid" }; _sut.Invoking(s => s.RefreshDiff(record)).Should().Throw <FormatException>(); }
public void ShouldIgnoreIncompleteRecord() { var record = new DiffRecord { Left = "something", Right = null }; _sut.RefreshDiff(record); record.Analysis.Should().BeNull(); }
public void A_ShouldSaveARecord() { var record = new DiffRecord { Id = _id, Left = "left", Right = "right" }; var result = _sut.Save(record); result.Should().BeTrue(); }
public void ShouldTellIfContentsAreEqual() { var array = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var base64 = Convert.ToBase64String(array); var record = new DiffRecord { Left = base64, Right = base64 }; _sut.RefreshDiff(record); record.Analysis.Should().NotBeNull(); record.Analysis.EqualSize.Should().BeTrue(); record.Analysis.EqualContent.Should().BeTrue(); }
/// <summary> /// Updates diff results into a <see cref="DiffRecord"/>, regardless if it already exists or not. /// </summary> /// <param name="diffRecord">The <see cref="DiffRecord"/> instance to be updated.</param> /// <remarks> /// Pre-conditions (otherwise this method will silently exit):<br/> /// - <see cref="DiffRecord.IsComplete"/> == true<br/> /// - <see cref="DiffRecord.Left"/> and <see cref="DiffRecord.Right"/> must have same length. /// </remarks> public void RefreshDiff(DiffRecord diffRecord) { if (diffRecord == null) { return; } diffRecord.Analysis = null; if (!diffRecord.IsComplete) { return; } var left = Convert.FromBase64String(diffRecord.Left); var right = Convert.FromBase64String(diffRecord.Right); var analysis = new DiffRecord.DiffAnalysis(); var equalSize = analysis.EqualSize = left.Length == right.Length; analysis.EqualContent = !equalSize; if (!equalSize) { return; } // This is a naive implementation of a diff. It will search both streams at the same time, // at each byte, and return informations about equal and distinct windows, at THE SAME POSITION. // For a proper difference algorithm in C#, refer to http://www.mathertel.de/Diff/ DiffRecord.DiffOffset currOffset = null; var offsets = new List <DiffRecord.DiffOffset>(); using (var leftStream = new MemoryStream(left)) using (var leftReader = new StreamReader(leftStream)) using (var rightStream = new MemoryStream(right)) using (var rightReader = new StreamReader(rightStream)) { while (true) { var l = leftReader.Read(); var r = rightReader.Read(); if (l < 0 || r < 0) { if (currOffset != null) { offsets.Add(currOffset); } break; } var inSync = l == r; if (currOffset != null && (currOffset.IsEqual != inSync && currOffset.Length > 0)) { offsets.Add(currOffset); currOffset = null; } if (currOffset == null) { currOffset = new DiffRecord.DiffOffset { IsEqual = inSync }; } currOffset.Length++; } } analysis.EqualContent = offsets.Count == 1 && offsets[0].IsEqual; if (!analysis.EqualContent) { analysis.Offsets = offsets; } diffRecord.Analysis = analysis; }
/// <summary> /// Saves a <see cref="DiffRecord"/> into LocalDB. /// </summary> /// <param name="record">A <see cref="DiffRecord"/> instance.</param> public bool Save(DiffRecord record) => _col.Upsert(record);