feat: implement object hash

based on pull request #52
fixes #54, #42
pull/58/head
Mathias Kolb 2021-09-08 12:30:08 +02:00
parent 8f91145d61
commit dd7ace5338
2 changed files with 333 additions and 317 deletions

View File

@ -1,316 +1,332 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
namespace JsonDiffPatchDotNet.UnitTests
{
[TestFixture]
public class DiffUnitTests
{
[Test]
public void Diff_EmptyObjects_EmptyPatch()
{
var jdp = new JsonDiffPatch();
var empty = JObject.Parse(@"{}");
JToken result = jdp.Diff(empty, empty);
Assert.IsNull(result);
}
[Test]
public void Diff_EqualBooleanProperty_NoDiff()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{""p"": true }");
var right = JObject.Parse(@"{""p"": true }");
JToken result = jdp.Diff(left, right);
Assert.IsNull(result);
}
[Test]
public void Diff_DiffBooleanProperty_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{""p"": true }");
var right = JObject.Parse(@"{""p"": false }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(2, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.IsTrue(((JArray)obj.Property("p").Value)[0].ToObject<bool>(), "Array Old Value");
Assert.IsFalse(((JArray)obj.Property("p").Value)[1].ToObject<bool>(), "Array New Value");
}
[Test]
public void Diff_BooleanPropertyDeleted_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{ ""p"": true }");
var right = JObject.Parse(@"{ }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(3, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.IsTrue(((JArray)obj.Property("p").Value)[0].ToObject<bool>(), "Array Old Value");
Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[1].ToObject<int>(), "Array New Value");
Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[2].ToObject<int>(), "Array Deleted Indicator");
}
[Test]
public void Diff_BooleanPropertyAdded_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{ }");
var right = JObject.Parse(@"{ ""p"": true }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(1, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.IsTrue(((JArray)obj.Property("p").Value)[0].ToObject<bool>(), "Array Added Value");
}
[Test]
public void Diff_EfficientStringDiff_ValidPatch()
{
var jdp = new JsonDiffPatch(new Options { TextDiff = TextDiffMode.Efficient });
var left = JObject.Parse(@"{ ""p"": ""lp.Value.ToString().Length > _options.MinEfficientTextDiffLength"" }");
var right = JObject.Parse(@"{ ""p"": ""blah1"" }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(3, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.AreEqual("@@ -1,64 +1,5 @@\n-lp.Value.ToString().Length %3e _options.MinEfficientTextDiffLength\n+blah1\n", ((JArray)obj.Property("p").Value)[0].ToString(), "Array Added Value");
Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[1].ToObject<int>(), "Array Added Value");
Assert.AreEqual(2, ((JArray)obj.Property("p").Value)[2].ToObject<int>(), "Array String Diff Indicator");
}
[Test]
public void Diff_EfficientStringDiff_NoChanges()
{
var jdp = new JsonDiffPatch(new Options { TextDiff = TextDiffMode.Efficient });
var left = JObject.Parse(@"{ ""p"": ""lp.Value.ToString().Length > _options.MinEfficientTextDiffLength"" }");
var right = JObject.Parse(@"{ ""p"": ""lp.Value.ToString().Length > _options.MinEfficientTextDiffLength"" }");
JToken result = jdp.Diff(left, right);
Assert.IsNull(result, "No Changes");
}
[Test]
public void Diff_LeftNull_Exception()
{
var jdp = new JsonDiffPatch();
var obj = JObject.Parse(@"{ }");
JToken result = jdp.Diff(null, obj);
Assert.AreEqual(JTokenType.Array, result.Type);
}
[Test]
public void Diff_RightNull_Exception()
{
var jdp = new JsonDiffPatch();
var obj = JObject.Parse(@"{ }");
JToken result = jdp.Diff(obj, null);
Assert.AreEqual(JTokenType.Array, result.Type);
}
[Test]
public void Diff_EfficientArrayDiffSame_NullDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var array = JToken.Parse(@"[1,2,3]");
JToken diff = jdp.Diff(array, array);
Assert.IsNull(diff);
}
[Test]
public void Diff_EfficientArrayDiffDifferentHeadRemoved_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[2,3,4]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["_0"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentTailRemoved_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[1,2,3]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["_3"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentHeadAdded_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[0,1,2,3,4]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["0"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentTailAdded_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[1,2,3,4,5]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["4"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentHeadTailAdded_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[0,1,2,3,4,5]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(3, diff.Properties().Count());
Assert.IsNotNull(diff["0"]);
Assert.IsNotNull(diff["5"]);
}
[Test]
public void Diff_EfficientArrayDiffSameLengthNested_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient, ObjectHash = (jObj) => jObj["Id"].Value<string>() });
var left = JToken.Parse(@"[1,2,{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":false},4]");
var right = JToken.Parse(@"[1,2,{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":true},4]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["2"]);
}
[Test]
public void Diff_EfficientArrayDiffWithComplexObject_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient, ObjectHash = (jObj) => jObj["Id"].Value<string>() });
//var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":false}, {""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC9"", ""p"":true}]");
var right = JToken.Parse(@"[{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":true}, {""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC10"", ""p"":false}]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(4, diff.Properties().Count());
}
[Test]
public void Diff_EfficientArrayDiffSameWithObject_NoDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"
{
""@context"": [
""http://www.w3.org/ns/csvw"",
{
""@language"": ""en"",
""@base"": ""http://example.org""
}
]
}");
var right = left.DeepClone();
JToken diff = jdp.Diff(left, right);
Assert.IsNull(diff);
}
[Test]
public void Diff_EfficientArrayDiffHugeArrays_NoStackOverflow()
{
const int arraySize = 1000;
Func<int, int, JToken> hugeArrayFunc = (startIndex, count) =>
{
var builder = new StringBuilder("[");
foreach (var i in Enumerable.Range(startIndex, count))
{
builder.Append($"{i},");
}
builder.Append("]");
return JToken.Parse(builder.ToString());
};
var jdp = new JsonDiffPatch();
var left = hugeArrayFunc(0, arraySize);
var right = hugeArrayFunc(arraySize / 2, arraySize);
JToken diff = jdp.Diff(left, right);
var restored = jdp.Patch(left, diff);
Assert.That(JToken.DeepEquals(restored, right));
}
[Test]
public void Diff_IntStringDiff_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JToken.Parse(@"1");
var right = JToken.Parse(@"""hello""");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Array, result.Type);
JArray array = (JArray)result;
Assert.AreEqual(2, array.Count);
Assert.AreEqual(left, array[0]);
Assert.AreEqual(right, array[1]);
}
}
}
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
namespace JsonDiffPatchDotNet.UnitTests
{
[TestFixture]
public class DiffUnitTests
{
[Test]
public void Diff_EmptyObjects_EmptyPatch()
{
var jdp = new JsonDiffPatch();
var empty = JObject.Parse(@"{}");
JToken result = jdp.Diff(empty, empty);
Assert.IsNull(result);
}
[Test]
public void Diff_EqualBooleanProperty_NoDiff()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{""p"": true }");
var right = JObject.Parse(@"{""p"": true }");
JToken result = jdp.Diff(left, right);
Assert.IsNull(result);
}
[Test]
public void Diff_DiffBooleanProperty_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{""p"": true }");
var right = JObject.Parse(@"{""p"": false }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(2, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.IsTrue(((JArray)obj.Property("p").Value)[0].ToObject<bool>(), "Array Old Value");
Assert.IsFalse(((JArray)obj.Property("p").Value)[1].ToObject<bool>(), "Array New Value");
}
[Test]
public void Diff_BooleanPropertyDeleted_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{ ""p"": true }");
var right = JObject.Parse(@"{ }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(3, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.IsTrue(((JArray)obj.Property("p").Value)[0].ToObject<bool>(), "Array Old Value");
Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[1].ToObject<int>(), "Array New Value");
Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[2].ToObject<int>(), "Array Deleted Indicator");
}
[Test]
public void Diff_BooleanPropertyAdded_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JObject.Parse(@"{ }");
var right = JObject.Parse(@"{ ""p"": true }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(1, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.IsTrue(((JArray)obj.Property("p").Value)[0].ToObject<bool>(), "Array Added Value");
}
[Test]
public void Diff_EfficientStringDiff_ValidPatch()
{
var jdp = new JsonDiffPatch(new Options { TextDiff = TextDiffMode.Efficient });
var left = JObject.Parse(@"{ ""p"": ""lp.Value.ToString().Length > _options.MinEfficientTextDiffLength"" }");
var right = JObject.Parse(@"{ ""p"": ""blah1"" }");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Object, result.Type);
JObject obj = (JObject)result;
Assert.IsNotNull(obj.Property("p"), "Property Name");
Assert.AreEqual(JTokenType.Array, obj.Property("p").Value.Type, "Array Value");
Assert.AreEqual(3, ((JArray)obj.Property("p").Value).Count, "Array Length");
Assert.AreEqual("@@ -1,64 +1,5 @@\n-lp.Value.ToString().Length %3e _options.MinEfficientTextDiffLength\n+blah1\n", ((JArray)obj.Property("p").Value)[0].ToString(), "Array Added Value");
Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[1].ToObject<int>(), "Array Added Value");
Assert.AreEqual(2, ((JArray)obj.Property("p").Value)[2].ToObject<int>(), "Array String Diff Indicator");
}
[Test]
public void Diff_EfficientStringDiff_NoChanges()
{
var jdp = new JsonDiffPatch(new Options { TextDiff = TextDiffMode.Efficient });
var left = JObject.Parse(@"{ ""p"": ""lp.Value.ToString().Length > _options.MinEfficientTextDiffLength"" }");
var right = JObject.Parse(@"{ ""p"": ""lp.Value.ToString().Length > _options.MinEfficientTextDiffLength"" }");
JToken result = jdp.Diff(left, right);
Assert.IsNull(result, "No Changes");
}
[Test]
public void Diff_LeftNull_Exception()
{
var jdp = new JsonDiffPatch();
var obj = JObject.Parse(@"{ }");
JToken result = jdp.Diff(null, obj);
Assert.AreEqual(JTokenType.Array, result.Type);
}
[Test]
public void Diff_RightNull_Exception()
{
var jdp = new JsonDiffPatch();
var obj = JObject.Parse(@"{ }");
JToken result = jdp.Diff(obj, null);
Assert.AreEqual(JTokenType.Array, result.Type);
}
[Test]
public void Diff_EfficientArrayDiffSame_NullDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var array = JToken.Parse(@"[1,2,3]");
JToken diff = jdp.Diff(array, array);
Assert.IsNull(diff);
}
[Test]
public void Diff_EfficientArrayDiffDifferentHeadRemoved_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[2,3,4]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["_0"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentTailRemoved_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[1,2,3]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["_3"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentHeadAdded_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[0,1,2,3,4]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["0"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentTailAdded_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[1,2,3,4,5]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["4"]);
}
[Test]
public void Diff_EfficientArrayDiffDifferentHeadTailAdded_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[1,2,3,4]");
var right = JToken.Parse(@"[0,1,2,3,4,5]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(3, diff.Properties().Count());
Assert.IsNotNull(diff["0"]);
Assert.IsNotNull(diff["5"]);
}
[Test]
public void Diff_EfficientArrayDiffSameLengthNested_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient, ObjectHash = (jObj) => jObj["Id"].Value<string>() });
var left = JToken.Parse(@"[1,2,{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":false},4]");
var right = JToken.Parse(@"[1,2,{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":true},4]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(2, diff.Properties().Count());
Assert.IsNotNull(diff["2"]);
}
[Test]
public void Diff_EfficientArrayDiffWithComplexObject_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient, ObjectHash = (jObj) => jObj["Id"].Value<string>() });
//var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"[{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":false}, {""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC9"", ""p"":true}]");
var right = JToken.Parse(@"[{""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC8"", ""p"":true}, {""Id"" : ""F12B21EF-F57D-4958-ADDC-A3F52EC25EC10"", ""p"":false}]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(4, diff.Properties().Count());
}
[Test]
public void Diff_EfficientArrayDiffWithComplexObjectHash_ValidDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient, ObjectHash = (jObj) => jObj["Id"].Value<string>() });
var left = JToken.Parse(@"[{""Id"": ""22ff56c7-2307-414b-8a3a-9bf1cdba2095"",""city"":""São Paulo""},{""Id"":""3fca9cdb-dd9b-4b7c-afc1-587751e25bd6"",""city"":""abc""},{""Id"":""1fe6a0f9-3974-427f-81cb-6004748cb179"",""city"":""xyz""}]");
var right = JToken.Parse(@"[{""Id"":""3fca9cdb-dd9b-4b7c-afc1-587751e25bd6"",""city"":""abc""},{""Id"":""1fe6a0f9-3974-427f-81cb-6004748cb179"",""city"":""xyz""}, {""Id"":""3fca9cdb-dd9b-4b7c-afc1-587751e25b44"",""city"":""new""}]");
JObject diff = jdp.Diff(left, right) as JObject;
Assert.IsNotNull(diff);
Assert.AreEqual(3, diff.Properties().Count());
Assert.IsNotNull(diff["_0"]);
Assert.IsNotNull(diff["2"]);
Assert.AreEqual(((JArray)diff["2"])[0].Value<string>("city"), "new");
}
[Test]
public void Diff_EfficientArrayDiffSameWithObject_NoDiff()
{
var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
var left = JToken.Parse(@"
{
""@context"": [
""http://www.w3.org/ns/csvw"",
{
""@language"": ""en"",
""@base"": ""http://example.org""
}
]
}");
var right = left.DeepClone();
JToken diff = jdp.Diff(left, right);
Assert.IsNull(diff);
}
[Test]
public void Diff_EfficientArrayDiffHugeArrays_NoStackOverflow()
{
const int arraySize = 1000;
Func<int, int, JToken> hugeArrayFunc = (startIndex, count) =>
{
var builder = new StringBuilder("[");
foreach (var i in Enumerable.Range(startIndex, count))
{
builder.Append($"{i},");
}
builder.Append("]");
return JToken.Parse(builder.ToString());
};
var jdp = new JsonDiffPatch();
var left = hugeArrayFunc(0, arraySize);
var right = hugeArrayFunc(arraySize / 2, arraySize);
JToken diff = jdp.Diff(left, right);
var restored = jdp.Patch(left, diff);
Assert.That(JToken.DeepEquals(restored, right));
}
[Test]
public void Diff_IntStringDiff_ValidPatch()
{
var jdp = new JsonDiffPatch();
var left = JToken.Parse(@"1");
var right = JToken.Parse(@"""hello""");
JToken result = jdp.Diff(left, right);
Assert.AreEqual(JTokenType.Array, result.Type);
JArray array = (JArray)result;
Assert.AreEqual(2, array.Count);
Assert.AreEqual(left, array[0]);
Assert.AreEqual(right, array[1]);
}
}
}

View File

@ -384,8 +384,8 @@ namespace JsonDiffPatchDotNet
int commonHead = 0;
int commonTail = 0;
if (itemMatch.Match(left, right))
return null;
if (JToken.DeepEquals(left, right))
return null;
var childContext = new List<JToken>();