Skip to content

Commit c1245f1

Browse files
Complete implementation: handle long numeric strings in patch operation paths
Co-authored-by: NaluTripician <27316859+NaluTripician@users.noreply.github.com>
1 parent 2e4a92a commit c1245f1

7 files changed

Lines changed: 130 additions & 208 deletions

File tree

Microsoft.Azure.Cosmos/src/Patch/PatchOperationsJsonConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public override void WriteJson(
9191
if (operation.OperationType == PatchOperationType.Move)
9292
{
9393
writer.WritePropertyName(PatchConstants.PropertyNames.From);
94-
writer.WriteValue(operation.From);
94+
writer.WriteValue(PatchPathHelper.ProcessPath(operation.From));
9595
}
9696
else if (operation.TrySerializeValueParameter(this.userSerializer, out Stream valueStream))
9797
{
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.Azure.Cosmos;
4+
using Microsoft.VisualStudio.TestTools.UnitTesting;
5+
6+
namespace Microsoft.Azure.Cosmos.Tests
7+
{
8+
/// <summary>
9+
/// Tests for the fix to handle long numeric strings in patch operation paths
10+
/// </summary>
11+
[TestClass]
12+
public class PatchOperationLongNumericPathTests
13+
{
14+
[TestMethod]
15+
public void TestLongNumericStringInPath_EscapedCorrectly()
16+
{
17+
// Test the exact scenario from the issue
18+
var longNumericString = "12345678901234567890"; // 20 characters - should be escaped
19+
var processedPath = PatchPathHelper.ProcessPath($"/strings/{longNumericString}");
20+
21+
Assert.AreEqual($"/strings/[\"{longNumericString}\"]", processedPath);
22+
}
23+
24+
[TestMethod]
25+
public void TestVeryLongNumericStringInPath_EscapedCorrectly()
26+
{
27+
// Test with an even longer numeric string
28+
var veryLongNumericString = "123456789012345678901234567890"; // 30 characters
29+
var processedPath = PatchPathHelper.ProcessPath($"/strings/{veryLongNumericString}");
30+
31+
Assert.AreEqual($"/strings/[\"{veryLongNumericString}\"]", processedPath);
32+
}
33+
34+
[TestMethod]
35+
public void TestShortNumericStringInPath_NotEscaped()
36+
{
37+
// Test with a short numeric string (should not be escaped)
38+
var shortNumericString = "123456789"; // 9 characters
39+
var processedPath = PatchPathHelper.ProcessPath($"/strings/{shortNumericString}");
40+
41+
Assert.AreEqual($"/strings/{shortNumericString}", processedPath);
42+
}
43+
44+
[TestMethod]
45+
public void TestBoundaryNumericStringInPath_NotEscaped()
46+
{
47+
// Test with a numeric string at the boundary (19 characters - should not be escaped)
48+
var boundaryNumericString = "1234567890123456789"; // 19 characters
49+
var processedPath = PatchPathHelper.ProcessPath($"/strings/{boundaryNumericString}");
50+
51+
Assert.AreEqual($"/strings/{boundaryNumericString}", processedPath);
52+
}
53+
54+
[TestMethod]
55+
public void TestMixedAlphaNumericStringInPath_NotEscaped()
56+
{
57+
// Test with mixed alphanumeric string (should not be escaped regardless of length)
58+
var mixedString = "abc123456789012345678901234567890def";
59+
var processedPath = PatchPathHelper.ProcessPath($"/strings/{mixedString}");
60+
61+
Assert.AreEqual($"/strings/{mixedString}", processedPath);
62+
}
63+
64+
[TestMethod]
65+
public void TestMultipleSegmentsWithLongNumeric_OnlyLongNumericEscaped()
66+
{
67+
// Test with multiple segments where only the long numeric one should be escaped
68+
var path = "/strings/12345678901234567890/nested/123456789";
69+
var processedPath = PatchPathHelper.ProcessPath(path);
70+
71+
Assert.AreEqual("/strings/[\"12345678901234567890\"]/nested/123456789", processedPath);
72+
}
73+
74+
[TestMethod]
75+
public void TestMultipleLongNumericSegments_AllEscaped()
76+
{
77+
// Test with multiple long numeric segments
78+
var path = "/data/12345678901234567890/items/987654321098765432109876543210";
79+
var processedPath = PatchPathHelper.ProcessPath(path);
80+
81+
Assert.AreEqual("/data/[\"12345678901234567890\"]/items/[\"987654321098765432109876543210\"]", processedPath);
82+
}
83+
84+
[TestMethod]
85+
public void TestPatchOperationsWithLongNumericPaths_CreatedSuccessfully()
86+
{
87+
// Test that patch operations can be created with long numeric paths
88+
var longNumericString = "12345678901234567890";
89+
90+
var addOperation = PatchOperation.Add($"/strings/{longNumericString}", "test_value");
91+
var replaceOperation = PatchOperation.Replace($"/data/{longNumericString}", "new_value");
92+
var removeOperation = PatchOperation.Remove($"/items/{longNumericString}");
93+
94+
Assert.AreEqual($"/strings/{longNumericString}", addOperation.Path);
95+
Assert.AreEqual($"/data/{longNumericString}", replaceOperation.Path);
96+
Assert.AreEqual($"/items/{longNumericString}", removeOperation.Path);
97+
}
98+
99+
[TestMethod]
100+
public void TestEdgeCases_HandledCorrectly()
101+
{
102+
// Test edge cases
103+
Assert.AreEqual("", PatchPathHelper.ProcessPath(""));
104+
Assert.AreEqual("/", PatchPathHelper.ProcessPath("/"));
105+
Assert.AreEqual(null, PatchPathHelper.ProcessPath(null));
106+
Assert.AreEqual("/[\"12345678901234567890\"]", PatchPathHelper.ProcessPath("/12345678901234567890"));
107+
}
108+
109+
[TestMethod]
110+
public void TestMoveOperationWithLongNumericPaths_BothPathsEscaped()
111+
{
112+
// Test that move operations escape both 'from' and 'path' when they contain long numeric strings
113+
var longNumericString1 = "12345678901234567890";
114+
var longNumericString2 = "98765432109876543210";
115+
116+
var moveOperation = PatchOperation.Move($"/source/{longNumericString1}", $"/target/{longNumericString2}");
117+
118+
Assert.AreEqual($"/target/{longNumericString2}", moveOperation.Path);
119+
Assert.AreEqual($"/source/{longNumericString1}", moveOperation.From);
120+
121+
// Test that the helper processes both paths correctly
122+
var processedPath = PatchPathHelper.ProcessPath(moveOperation.Path);
123+
var processedFrom = PatchPathHelper.ProcessPath(moveOperation.From);
124+
125+
Assert.AreEqual($"/target/[\"{longNumericString2}\"]", processedPath);
126+
Assert.AreEqual($"/source/[\"{longNumericString1}\"]", processedFrom);
127+
}
128+
}
129+
}

TestPatchHelper/Program.cs

Lines changed: 0 additions & 74 deletions
This file was deleted.

TestPatchHelper/TestPatchHelper.csproj

Lines changed: 0 additions & 14 deletions
This file was deleted.

test_patch_debug.cs

Lines changed: 0 additions & 47 deletions
This file was deleted.

test_patch_helper.cs

Lines changed: 0 additions & 41 deletions
This file was deleted.

test_patch_repro.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)