diff --git a/Src/JsonDiffPatchDotNet.UnitTests/DiffUnitTests.cs b/Src/JsonDiffPatchDotNet.UnitTests/DiffUnitTests.cs index c43c090..ab23c28 100644 --- a/Src/JsonDiffPatchDotNet.UnitTests/DiffUnitTests.cs +++ b/Src/JsonDiffPatchDotNet.UnitTests/DiffUnitTests.cs @@ -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(), "Array Old Value"); - Assert.IsFalse(((JArray)obj.Property("p").Value)[1].ToObject(), "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(), "Array Old Value"); - Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[1].ToObject(), "Array New Value"); - Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[2].ToObject(), "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(), "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(), "Array Added Value"); - Assert.AreEqual(2, ((JArray)obj.Property("p").Value)[2].ToObject(), "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() }); - 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() }); - //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 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(), "Array Old Value"); + Assert.IsFalse(((JArray)obj.Property("p").Value)[1].ToObject(), "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(), "Array Old Value"); + Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[1].ToObject(), "Array New Value"); + Assert.AreEqual(0, ((JArray)obj.Property("p").Value)[2].ToObject(), "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(), "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(), "Array Added Value"); + Assert.AreEqual(2, ((JArray)obj.Property("p").Value)[2].ToObject(), "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() }); + 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() }); + //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() }); + 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("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 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]); + } + } +} diff --git a/Src/JsonDiffPatchDotNet/JsonDiffPatch.cs b/Src/JsonDiffPatchDotNet/JsonDiffPatch.cs index 9acb448..7d66c29 100644 --- a/Src/JsonDiffPatchDotNet/JsonDiffPatch.cs +++ b/Src/JsonDiffPatchDotNet/JsonDiffPatch.cs @@ -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();