public void Diff_EfficientArrayDiffHugeArrays_NoStackOverflow()
        {
            const int ARRAY_SIZE = 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, ARRAY_SIZE);
            var right = hugeArrayFunc(ARRAY_SIZE / 2, ARRAY_SIZE);

            JToken diff   = null;
            var    thread = new Thread(() => diff = jdp.Diff(left, right), 128 * 2014);

            thread.Start();
            thread.Join();

            var restored = jdp.Patch(left, diff);

            Assert.That(JToken.DeepEquals(restored, right));
        }
Beispiel #2
0
        public void SimplePatchTest()
        {
            var a1 = new Authentication
            {
                AuthProperties = new Dictionary <string, string>
                {
                    { "Test", "value" }
                }
            };

            var a2 = new Authentication
            {
                AuthProperties = new Dictionary <string, string>
                {
                    { "Test", "value2" }
                }
            };

            var    jdp   = new JsonDiffPatch();
            var    left  = JToken.FromObject(a1);
            var    right = JToken.FromObject(a2);
            JToken patch = jdp.Diff(left, right);

            var output = jdp.Patch(left, patch);

            Assert.Equal(output.ToString(), right.ToString());
        }
Beispiel #3
0
        public static T Patch <T>(this T objOld, JToken patch)
        {
            var    jdp    = new JsonDiffPatch();
            JToken left   = JToken.FromObject(objOld);
            var    result = jdp.Patch(left, patch);

            return(result.ToObject <T>());
        }
Beispiel #4
0
        public static Result <T> Merge <T>(this JsonDiffPatch self, T originalObj, T variant1, T variant2)
        {
            var res = new Result <T>();

            res.original      = JToken.FromObject(originalObj);
            res.variant1      = JToken.FromObject(variant1);
            res.variant2      = JToken.FromObject(variant2);
            res.patch2        = self.Diff(res.original, res.variant2);
            res.mergeOf2Into1 = self.Patch(res.variant1, res.patch2);
            res.patch1        = self.Diff(res.original, res.variant1);
            res.mergeOf1Into2 = self.Patch(res.variant2, res.patch1);
            if (!JToken.DeepEquals(res.mergeOf2Into1, res.mergeOf1Into2))
            {
                res.conflicts = self.Diff(res.mergeOf1Into2, res.mergeOf2Into1);
            }
            return(res);
        }
        public void Patch_NestedComplexEditDifferentLeft_Success()
        {
            var jdp   = new JsonDiffPatch();
            var left  = JObject.Parse(@"{ ""i"": { ""1"" : 1, ""2"": 2 }, ""j"": [0, 2, 4], ""k"": [1] }");
            var right = JObject.Parse(@"{ ""i"": { ""1"" : 1, ""2"": 3 }, ""j"": [0, 2, 3], ""k"": null }");
            var patch = jdp.Diff(JObject.Parse(@"{ ""k"": { ""i"": [1] } }"), right);

            var patched = jdp.Patch(left, patch);

            Assert.AreEqual(right.ToString(), patched.ToString());
        }
		public void Patch_ObjectApplyDelete_Success()
		{
			var jdp = new JsonDiffPatch();
			var left = JObject.Parse(@"{ ""p"" : true }");
			var right = JObject.Parse(@"{ }");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch) as JObject;

			Assert.IsNotNull(patched, "Patched object");
			Assert.AreEqual(0, patched.Properties().Count(), "Property Deleted");
		}
Beispiel #7
0
        public void RelativePatch_NestedArrayAddRemove_Success()
        {
            var jdp = new JsonDiffPatch(new Options {
                ArrayDiff = ArrayDiffMode.Relative
            });
            var left  = JObject.Parse(@"{ ""p"" : { ""names"": [""Foo"", ""Bar""], ""numbers"": [5, 10] } }");
            var right = JObject.Parse(@"{ ""p"" : { ""names"": [""Foo"", ""Baz""], ""numbers"": [10, 5, 1] } }");

            var other = JObject.Parse(@"{ ""p"" : { ""names"": [""Bar"", ""Boop""], ""numbers"": [5, 10, 1] } }");

            var patch = jdp.Diff(left, right);

            var patched         = jdp.Patch(left, patch);
            var expectedPatched = JObject.Parse(@"{ ""p"" : { ""names"": [""Foo"", ""Baz""], ""numbers"": [5, 10, 1]} }");

            var patchedOther         = jdp.Patch(other, patch);
            var expectedPatchedOther = JObject.Parse(@"{ ""p"" : { ""names"": [""Boop"", ""Baz""], ""numbers"": [5, 10, 1]} }");

            Assert.True(JToken.DeepEquals(expectedPatched, patched));
            Assert.True(JToken.DeepEquals(expectedPatchedOther, patchedOther));
        }
        public void Patch_ObjectApplyDelete_Success()
        {
            var jdp   = new JsonDiffPatch();
            var left  = JObject.Parse(@"{ ""p"" : true }");
            var right = JObject.Parse(@"{ }");
            var patch = jdp.Diff(left, right);

            var patched = jdp.Patch(left, patch) as JObject;

            Assert.IsNotNull(patched, "Patched object");
            Assert.AreEqual(0, patched.Properties().Count(), "Property Deleted");
        }
Beispiel #9
0
        public void RelativePatch_ArrayAddRemove_Success()
        {
            var jdp = new JsonDiffPatch(new Options {
                ArrayDiff = ArrayDiffMode.Relative
            });
            var left  = JObject.Parse(@"{ ""p"" : [1, 2, 3] }");
            var right = JObject.Parse(@"{ ""p"" : [2, 3, 4] }");

            var other = JObject.Parse(@"{ ""p"" : [2, 1, 6, 7] }");

            var patch = jdp.Diff(left, right);

            var patched         = jdp.Patch(left, patch);
            var expectedPatched = JObject.Parse(@"{ ""p"" : [2, 3, 4] }");

            var patchedOther         = jdp.Patch(other, patch);
            var expectedPatchedOther = JObject.Parse(@"{ ""p"" : [2, 6, 7, 4] }");

            Assert.True(JToken.DeepEquals(expectedPatched, patched));
            Assert.True(JToken.DeepEquals(expectedPatchedOther, patchedOther));
        }
        private async Task SnapshotAsync(CancellationToken cancellation)
        {
            var snapshotRevisionThreshold = _options.SnapshotRevisionThreshold;

            if (snapshotRevisionThreshold < 0)
            {
                snapshotRevisionThreshold = 20;
            }

            using (var scope = _serviceProvider.CreateScope())
            {
                var scopedServiceProvider = scope.ServiceProvider;
                var entityStorageEngine   = scopedServiceProvider.GetRequiredService <IEntityStorageEngine>();
                var enumerator            = default(IAsyncEnumerator <IStream>);
                try
                {
                    enumerator = _streamStore.OpenStreamsToSnapshotAsync(snapshotRevisionThreshold, cancellation).GetEnumerator();

                    while (await enumerator.MoveNext(cancellation))
                    {
                        var stream = enumerator.Current;

                        if (stream.Snapshot == null && !stream.Commits.Any())
                        {
                            continue;
                        }

                        var serializedEntity = default(JToken);

                        if (stream.Snapshot == null)
                        {
                            serializedEntity = StreamRoot;
                        }
                        else
                        {
                            serializedEntity = JToken.Parse(CompressionHelper.Unzip(stream.Snapshot.Payload as byte[]));
                        }

                        foreach (var commit in stream.Commits)
                        {
                            serializedEntity = _differ.Patch(serializedEntity, JToken.Parse(CompressionHelper.Unzip(commit.Body as byte[])));
                        }

                        await stream.AddSnapshotAsync(CompressionHelper.Zip(serializedEntity.ToString()), cancellation);
                    }
                }
                finally
                {
                    enumerator?.Dispose();
                }
            }
        }
Beispiel #11
0
        public void ComplexPatchTest()
        {
            var obj1 = JsonConvert.DeserializeObject <Workspace>("{\"id\":\"d89c9279-1e45-41a7-9330-c35429509856\",\"parentId\":\"root\",\"Name\":\"magic\",\"Methods\":[\"GET\",\"POST\",\"PUT\",\"DELETE\",\"HEAD\",\"OPTIONS\",\"PATCH\",\"MERGE\",\"COPY\"],\"OpenItemIds\":[\"62b0aa85-9d5c-4fc2-b4cd-d2e80558e08e\",\"7c4a8648-24e1-48e0-b2f9-2e30ab8f2b36\"],\"TempItems\":[],\"Items\":[{\"id\":\"7c4a8648-24e1-48e0-b2f9-2e30ab8f2b36\",\"parentId\":null,\"IsTemporary\":false,\"Properties\":{\"RequestPivotIndex\":0},\"Url\":{\"Base\":\"\",\"Queries\":[]},\"Auth\":{\"AuthType\":0,\"AuthProperties\":{}},\"Body\":{\"BodyType\":0,\"JsonBody\":null,\"XmlBody\":null,\"TextBody\":null,\"FormEncodedData\":[],\"FormDataList\":[],\"BinaryFilePath\":null},\"MockData\":{\"Body\":null,\"StatusCode\":200,\"ContentType\":\"application/json\"},\"Children\":[],\"Headers\":[],\"ChainingRules\":[],\"Type\":1,\"Name\":\"My request\",\"IsExpanded\":false,\"Method\":\"GET\",\"Response\":null},{\"id\":\"fa796649-43a2-4dfb-8a87-01b46382ab14\",\"parentId\":null,\"IsTemporary\":false,\"Properties\":{},\"Url\":{\"Base\":null,\"Queries\":[]},\"Auth\":{\"AuthType\":0,\"AuthProperties\":null},\"Body\":{\"BodyType\":0,\"JsonBody\":null,\"XmlBody\":null,\"TextBody\":null,\"FormEncodedData\":[],\"FormDataList\":[],\"BinaryFilePath\":null},\"MockData\":{\"Body\":null,\"StatusCode\":200,\"ContentType\":\"application/json\"},\"Children\":[{\"id\":\"62b0aa85-9d5c-4fc2-b4cd-d2e80558e08e\",\"parentId\":null,\"IsTemporary\":false,\"Properties\":{\"RequestPivotIndex\":0},\"Url\":{\"Base\":\"44444444444444444444444444444444444?\",\"Queries\":[{\"Key\":\"3333\",\"Value\":\"232424\",\"Enabled\":true,\"Private\":false,\"Type\":0}]},\"Auth\":{\"AuthType\":2,\"AuthProperties\":{\"BasicUsername\":\"asdf\",\"BasicPassword\":\"asdf\",\"DigestUsername\":\"asdf\",\"DigestPassword\":\"asdf\",\"BearerToken\":\"asdf\",\"OAuth2GrantType\":\"authorization_code\",\"OAuth2AccessTokenUrl\":\"asf\",\"OAuth2ClientSecret\":\"asdf\",\"OAuth1ConsumerSecret\":\"asdf\",\"OAuth1ConsumerKey\":\"asdf\"}},\"Body\":{\"BodyType\":0,\"JsonBody\":null,\"XmlBody\":null,\"TextBody\":null,\"FormEncodedData\":[],\"FormDataList\":[],\"BinaryFilePath\":null},\"MockData\":{\"Body\":\"{salfaslkdfj}\",\"StatusCode\":200,\"ContentType\":\"application/json\"},\"Children\":[],\"Headers\":[],\"ChainingRules\":[],\"Type\":1,\"Name\":\"234234\",\"IsExpanded\":false,\"Method\":\"GET\",\"Response\":null}],\"Headers\":[],\"ChainingRules\":[],\"Type\":2,\"Name\":\"Untitled\",\"IsExpanded\":true,\"Method\":\"GET\",\"Response\":null}],\"HistoryItems\":[],\"Environments\":[{\"id\":null,\"parentId\":null,\"Name\":\"Base\",\"EnvironmentType\":1,\"Variables\":[{\"Key\":\"env\",\"Value\":\"value\",\"Enabled\":true,\"Private\":false,\"Type\":3}]}],\"Cookies\":null}");
            var obj2 = JsonConvert.DeserializeObject <Workspace>("{\"id\":\"d89c9279-1e45-41a7-9330-c35429509856\",\"parentId\":\"daniel\",\"Name\":\"magic\",\"Methods\":[\"GET\",\"POST\",\"PUT\",\"DELETE\",\"HEAD\",\"OPTIONS\",\"PATCH\",\"MERGE\",\"COPY\"],\"OpenItemIds\":[\"62b0aa85-9d5c-4fc2-b4cd-d2e80558e08e\",\"7c4a8648-24e1-48e0-b2f9-2e30ab8f2b36\"],\"TempItems\":[],\"Items\":[{\"id\":\"7c4a8648-24e1-48e0-b2f9-2e30ab8f2b36\",\"parentId\":null,\"IsTemporary\":false,\"Properties\":{\"RequestPivotIndex\":1},\"Url\":{\"Base\":\"\",\"Queries\":[]},\"Auth\":{\"AuthType\":0,\"AuthProperties\":{}},\"Body\":{\"BodyType\":0,\"JsonBody\":null,\"XmlBody\":null,\"TextBody\":null,\"FormEncodedData\":[],\"FormDataList\":[],\"BinaryFilePath\":null},\"MockData\":{\"Body\":null,\"StatusCode\":200,\"ContentType\":\"application/json\"},\"Children\":[],\"Headers\":[],\"ChainingRules\":[],\"Type\":1,\"Name\":\"My request\",\"IsExpanded\":false,\"Method\":\"GET\",\"Response\":null},{\"id\":\"fa796649-43a2-4dfb-8a87-01b46382ab14\",\"parentId\":null,\"IsTemporary\":false,\"Properties\":{},\"Url\":{\"Base\":null,\"Queries\":[]},\"Auth\":{\"AuthType\":0,\"AuthProperties\":null},\"Body\":{\"BodyType\":0,\"JsonBody\":null,\"XmlBody\":null,\"TextBody\":null,\"FormEncodedData\":[],\"FormDataList\":[],\"BinaryFilePath\":null},\"MockData\":{\"Body\":null,\"StatusCode\":200,\"ContentType\":\"application/json\"},\"Children\":[{\"id\":\"62b0aa85-9d5c-4fc2-b4cd-d2e80558e08e\",\"parentId\":null,\"IsTemporary\":false,\"Properties\":{\"RequestPivotIndex\":0},\"Url\":{\"Base\":\"44444444444444444444444444444444444?\",\"Queries\":[{\"Key\":\"123456\",\"Value\":\"alllllll\",\"Enabled\":false,\"Private\":false,\"Type\":0}]},\"Auth\":{\"AuthType\":2,\"AuthProperties\":{\"BasicUsername\":\"asdf\",\"BasicPassword\":\"asdf\",\"DigestUsername\":\"asdf\",\"DigestPassword\":\"asdf\",\"BearerToken\":\"asdf\",\"OAuth2GrantType\":\"authorization_code\",\"OAuth2AccessTokenUrl\":\"asf\",\"OAuth2ClientSecret\":\"asdf\",\"OAuth1ConsumerSecret\":\"asdf\",\"OAuth1ConsumerKey\":\"asdf\"}},\"Body\":{\"BodyType\":0,\"JsonBody\":null,\"XmlBody\":null,\"TextBody\":null,\"FormEncodedData\":[],\"FormDataList\":[],\"BinaryFilePath\":null},\"MockData\":{\"Body\":\"{salfaslkdfj}\",\"StatusCode\":200,\"ContentType\":\"application/json\"},\"Children\":[],\"Headers\":[],\"ChainingRules\":[],\"Type\":1,\"Name\":\"234234\",\"IsExpanded\":false,\"Method\":\"GET\",\"Response\":null}],\"Headers\":[],\"ChainingRules\":[],\"Type\":2,\"Name\":\"Untitled\",\"IsExpanded\":true,\"Method\":\"GET\",\"Response\":null}],\"HistoryItems\":[],\"Environments\":[{\"id\":null,\"parentId\":null,\"Name\":\"Base\",\"EnvironmentType\":1,\"Variables\":[{\"Key\":\"env\",\"Value\":\"value\",\"Enabled\":true,\"Private\":false,\"Type\":3}]}],\"Cookies\":null}");

            var    jdp    = new JsonDiffPatch();
            var    left   = JToken.FromObject(obj1);
            var    right  = JToken.FromObject(obj2);
            JToken patch  = jdp.Diff(left, right);
            var    output = jdp.Patch(left, patch);

            Assert.Equal(output.ToString(), right.ToString());
        }
		public void Patch_ObjectApplyEditText_Success()
		{
			var jdp = new JsonDiffPatch();
			var left = JObject.Parse(@"{ ""p"" : ""bla1h111111111111112312weldjidjoijfoiewjfoiefjefijfoejoijfiwoejfiewjfiwejfowjwifewjfejdewdwdewqwertyqwertifwiejifoiwfei"" }");
			var right = JObject.Parse(@"{ ""p"" : ""blah1"" }");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch) as JObject;

			Assert.IsNotNull(patched, "Patched object");
			Assert.AreEqual(1, patched.Properties().Count(), "Property");
			Assert.AreEqual(JTokenType.String, patched.Property("p").Value.Type, "String Type");
			Assert.AreEqual("blah1", patched.Property("p").Value.ToString(), "String value");
		}
		public void Patch_ObjectApplyEdit_Success()
		{
			var jdp = new JsonDiffPatch();
			var left = JObject.Parse(@"{ ""p"" : false }");
			var right = JObject.Parse(@"{ ""p"" : true }");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch) as JObject;

			Assert.IsNotNull(patched, "Patched object");
			Assert.AreEqual(1, patched.Properties().Count(), "Property");
			Assert.AreEqual(JTokenType.Boolean, patched.Property("p").Value.Type);
			Assert.IsTrue(patched.Property("p").Value.ToObject<bool>(), "Patched Property");
		}
Beispiel #14
0
        public void RelativePatch_ArrayAddRemoveObject_Success()
        {
            var jdp = new JsonDiffPatch(new Options {
                ArrayDiff = ArrayDiffMode.Relative
            });
            var left  = JObject.Parse(@"{ ""p"" : [ {""x"": 5}, {""x"": 10} ] }");
            var right = JObject.Parse(@"{ ""p"" : [ {""x"": 10}, {""x"": 15}, {""x"": 18} ] }");

            var other = JObject.Parse(@"{ ""p"" : [ {""x"": 15}, {""x"": 20} ] }");

            var patch = jdp.Diff(left, right);

            var patched         = jdp.Patch(left, patch);
            var expectedPatched = JObject.Parse(@"{ ""p"" : [ {""x"": 10}, {""x"": 15}, {""x"": 18} ] }");

            var patchedOther         = jdp.Patch(other, patch);
            var expectedPatchedOther = JObject.Parse(@"{ ""p"" : [ {""x"": 15}, {""x"": 20}, {""x"": 18}] }");

            Assert.True(JToken.DeepEquals(expectedPatched, patched));
            var j = patchedOther.ToString();

            Assert.True(JToken.DeepEquals(expectedPatchedOther, patchedOther));
        }
Beispiel #15
0
        public void Test1()
        {
            var jdp = new JsonDiffPatch();
            //var left = JToken.Parse(@"{ ""key"": false, ""text"" :""The program '[3572] dotnet.exe: Program Trace' has exited with code 0 (0x0)."" }");

            var left  = JToken.Parse(@"{}");
            var right = JToken.Parse(@"{ ""key"": true, ""text"" :""The program dotnet '[3572] : Program Traces' has exited with code 0 (0x0)."" }");

            JToken patch = jdp.Diff(left, right);

            Console.WriteLine(patch.ToString());

            var output = jdp.Patch(left, patch);

            Console.WriteLine(output.ToString());
        }
        private void CalculatePatch(string originalEntity, AuditEntity auditEntity)
        {
            var jdp = new JsonDiffPatch();

            foreach (var patch in GetPatches(auditEntity.Application, auditEntity.EntityId, auditEntity.EntityType))
            {
                originalEntity = jdp.Patch(originalEntity, patch);
            }

            var left     = JToken.Parse(originalEntity);
            var right    = JToken.Parse(auditEntity.Entity);
            var newPatch = jdp.Diff(left, right);

            auditEntity.Entity = null;
            auditEntity.Patch  = newPatch.ToString(Formatting.None);
        }
Beispiel #17
0
        public async Task <string> GetDiff(
            IHistoryRepository historyRepository, string type, string id, string data)
        {
            var historyList = await historyRepository.FindByElementIdAsync(id, type);

            historyList = historyList.Reverse();
            var    jdp   = new JsonDiffPatch();
            string patch = @"{}";

            foreach (var history in historyList)
            {
                patch = jdp.Patch(patch, history.Diff);
            }
            var output = jdp.Diff(patch, data);

            return(output);
        }
Beispiel #18
0
        public void DiffyPatch()
        {
            JsonDiffPatch jsonDiff = new JsonDiffPatch();
            JToken        x        = JObject.Parse(File.ReadAllText(@"D:\20170824precios.json"));
            JToken        y        = JObject.Parse(File.ReadAllText(@"D:\20170825precios.json"));
            JToken        diff     = jsonDiff.Diff(x, y);
            JToken        patch    = jsonDiff.Patch(x, diff);

            try
            {
                File.WriteAllText(jsonFilesDirectory + "diff.json", JsonConvert.SerializeObject(diff, Formatting.Indented));
                File.WriteAllText(jsonFilesDirectory + "patch.json", JsonConvert.SerializeObject(patch, Formatting.Indented));
            }
            catch (Exception)
            {
                throw;
            }
        }
Beispiel #19
0
        public async System.Threading.Tasks.Task SaveAsync(string content, string id, string userId, CheckPointType checkPointType)
        {
            var history = await _historyService.GetHistoryAsync(id);

            var jsonDiffPatch = new JsonDiffPatch();
            var left          = JToken.Parse("{}");

            if (history == null)
            {
                history = new HistoryDbModel()
                {
                    CheckPoints = new List <CheckPoint>(),
                    ElementId   = id,
                };
            }
            else
            {
                foreach (var checkpoint in history.CheckPoints)
                {
                    var patch = JToken.Parse(checkpoint.Patch);
                    left = jsonDiffPatch.Patch(left, patch);
                }
            }

            var checkPoint = new CheckPoint()
            {
                Id             = Guid.NewGuid().ToString(),
                UserId         = userId,
                CheckPointType = checkPointType,
                Hash           = Hash(content)
            };

            var lastRight = JToken.Parse(content);

            checkPoint.Patch = jsonDiffPatch.Diff(left, lastRight).ToString();
            await _historyService.AddAsync(id, checkPoint);
        }
		public void Patch_NullLeft_Exception()
		{
			var jdp = new JsonDiffPatch();
			var patch = JToken.Parse(@"[true]");

			JToken result = jdp.Patch(null, patch);

			Assert.IsNotNull(result);
			Assert.AreEqual(JTokenType.Boolean, result.Type);
			Assert.AreEqual(true, result.ToObject<bool>());
		}
		public void Patch_ArrayPatchRemove_Success()
		{
			var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
			var left = JToken.Parse(@"[1,2,3]");
			var right = JToken.Parse(@"[1,2]");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch);

			Assert.AreEqual(right.ToString(), patched.ToString());
		}
		public void Patch_ArrayPatchModify_Success()
		{
			var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
			var left = JToken.Parse(@"[1,3,{""p"":false}]");
			var right = JToken.Parse(@"[1,4,{""p"": [1] }]");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch);

			Assert.AreEqual(right.ToString(), patched.ToString());
		}
		public void Patch_ArrayPatchComplex_Success()
		{
			var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
			var left = JToken.Parse(@"{""p"": [1,2,[1],false,""11111"",3,{""p"":false},10,10] }");
			var right = JToken.Parse(@"{""p"": [1,2,[1,3],false,""11112"",3,{""p"":true},10,10] }");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch);

			Assert.AreEqual(right.ToString(), patched.ToString());
		}
		public void Patch_ArrayPatchMoving_Success()
		{
			var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
			var left = JToken.Parse(@"[0,1,2,3,4,5,6,7,8,9,10]");
			var right = JToken.Parse(@"[10,0,1,7,2,4,5,6,88,9,3]");
			var patch = JToken.Parse(@"{ ""8"": [88], ""_t"": ""a"", ""_3"": ["""", 10, 3], ""_7"": ["""", 3, 3], ""_8"": [8, 0, 0], ""_10"": ["""", 0, 3] }");

			var patched = jdp.Patch(left, patch);

			Assert.AreEqual(right.ToString(), patched.ToString());
		}
		public void Patch_ArrayPatchMoveDeletingNonConsecutive_Success()
		{
			var jdp = new JsonDiffPatch(new Options { ArrayDiff = ArrayDiffMode.Efficient });
			var left = JToken.Parse(@"[0,1,3,4,5]");
			var right = JToken.Parse(@"[0,5,3]");
			var patch = JToken.Parse(@"{""_t"": ""a"", ""_1"": [ 1, 0, 0], ""_3"": [4,0, 0],""_4"": [ """", 1, 3 ]}");

			var patched = jdp.Patch(left, patch);

			Assert.AreEqual(right.ToString(), patched.ToString());
		}
		public void Patch_NestedComplexEdit_Success()
		{
			var jdp = new JsonDiffPatch();
			var left = JObject.Parse(@"{ ""i"": { ""1"" : 1, ""2"": 2 }, ""j"": [0, 2, 4], ""k"": [1] }");
			var right = JObject.Parse(@"{ ""i"": { ""1"" : 1, ""2"": 3 }, ""j"": [0, 2, 3], ""k"": null }");
			var patch = jdp.Diff(left, right);

			var patched = jdp.Patch(left, patch);

			Assert.AreEqual(right.ToString(), patched.ToString());
		}