Skip to content

Commit 56811c9

Browse files
INTERNAL Range: Fixes Range type serialization to not allow NOT supported combinations (#4680)
* Range type serialization assumption to not allow NOT suported combinations * Fixing incorrect conflict resolution * Addressing the PR comments
1 parent 5948484 commit 56811c9

2 files changed

Lines changed: 121 additions & 4 deletions

File tree

Microsoft.Azure.Cosmos/src/Routing/RangeJsonConverter.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ namespace Microsoft.Azure.Cosmos.Routing
77
using System;
88
using Newtonsoft.Json;
99
using Newtonsoft.Json.Linq;
10-
using PartitionKeyRange = Documents.PartitionKeyRange;
1110

1211
internal sealed class RangeJsonConverter : JsonConverter
1312
{
1413
private static readonly string MinProperty = "min";
1514
private static readonly string MaxProperty = "max";
15+
private static readonly string MinInclusiveProperty = "isMinInclusive";
16+
private static readonly string MaxInclusiveProperty = "isMaxInclusive";
1617

1718
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
1819
{
@@ -25,6 +26,17 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
2526
serializer.Serialize(writer, range.Min);
2627
writer.WritePropertyName(MaxProperty);
2728
serializer.Serialize(writer, range.Max);
29+
if (!range.IsMinInclusive)
30+
{
31+
writer.WritePropertyName(MinInclusiveProperty);
32+
writer.WriteValue(false);
33+
}
34+
if (range.IsMaxInclusive)
35+
{
36+
writer.WritePropertyName(MaxInclusiveProperty);
37+
writer.WriteValue(true);
38+
}
39+
2840
writer.WriteEndObject();
2941
}
3042
catch (Exception ex)
@@ -38,10 +50,23 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
3850
try
3951
{
4052
JObject jsonObject = JObject.Load(reader);
53+
bool isMinInclusive = true;
54+
if (jsonObject.TryGetValue(MinInclusiveProperty, out JToken minInclusiveToken))
55+
{
56+
isMinInclusive = (bool)minInclusiveToken;
57+
}
58+
59+
bool isMaxInclusive = false;
60+
if (jsonObject.TryGetValue(MaxInclusiveProperty, out JToken maxInclusiveToken))
61+
{
62+
isMaxInclusive = (bool)maxInclusiveToken;
63+
}
64+
4165
return new Documents.Routing.Range<string>(
4266
jsonObject[MinProperty].Value<string>(),
4367
jsonObject[MaxProperty].Value<string>(),
44-
true, false);
68+
isMinInclusive,
69+
isMaxInclusive);
4570
}
4671
catch (Exception ex)
4772
{
@@ -51,7 +76,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
5176

5277
public override bool CanConvert(Type objectType)
5378
{
54-
return typeof(PartitionKeyRange).IsAssignableFrom(objectType);
79+
return typeof(Documents.Routing.Range<string>).IsAssignableFrom(objectType);
5580
}
5681
}
5782
}

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/FeedRange/FeedRangeTests.cs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ namespace Microsoft.Azure.Cosmos.Tests.FeedRange
1414
using Microsoft.Azure.Cosmos.Routing;
1515
using Moq;
1616
using Microsoft.Azure.Cosmos.Tracing;
17-
using System.Net.Http;
17+
using Newtonsoft.Json;
1818
using System.Text;
19+
using System.IO;
20+
using System.Net.Http;
21+
using Newtonsoft.Json.Linq;
1922

2023
[TestClass]
2124
public class FeedRangeTests
@@ -275,5 +278,94 @@ public async Task GetFeedRangesThrowsCosmosException()
275278
Assert.IsTrue(invokedPkRanges);
276279
}
277280
}
281+
282+
/// <summary>
283+
/// RangeJsonConverter accepts only (minInclusive=True, maxInclusive=False) combination
284+
/// In its serialization its not including minInclusive, maxInclusive combination
285+
/// but on deserialization setting them to (true, false
286+
///
287+
/// All other combinations should throw an exception
288+
/// </summary>
289+
[TestMethod]
290+
[DataRow(false, true)]
291+
[DataRow(false, false)]
292+
[DataRow(true, true)]
293+
[DataRow(true, false)]
294+
[Owner("kirankk")]
295+
public void FeedRangeEpk_SerializationValidation(bool minInclusive, bool maxInclusive)
296+
{
297+
Documents.Routing.Range<string> range = new Documents.Routing.Range<string>("", "FF", minInclusive, maxInclusive);
298+
RangeJsonConverter rangeConverter = new RangeJsonConverter();
299+
300+
using StringWriter sw = new StringWriter();
301+
using JsonWriter writer = new JsonTextWriter(sw);
302+
{
303+
JsonSerializer jsonSerializer = new JsonSerializer();
304+
rangeConverter.WriteJson(writer, range, jsonSerializer);
305+
writer.Flush();
306+
sw.Flush();
307+
308+
JObject parsedJson = JObject.Parse(sw.ToString());
309+
Assert.AreEqual(true, parsedJson.ContainsKey("min"));
310+
Assert.AreEqual(string.Empty, parsedJson["min"]);
311+
Assert.AreEqual(true, parsedJson.ContainsKey("max"));
312+
Assert.AreEqual("FF", parsedJson["max"]);
313+
Assert.AreEqual(!minInclusive, parsedJson.ContainsKey("isMinInclusive"));
314+
Assert.AreEqual(maxInclusive, parsedJson.ContainsKey("isMaxInclusive"));
315+
if (!minInclusive)
316+
{
317+
Assert.AreEqual(false, parsedJson["isMinInclusive"]);
318+
}
319+
320+
if (maxInclusive)
321+
{
322+
Assert.AreEqual(true, parsedJson["isMaxInclusive"]);
323+
}
324+
}
325+
}
326+
327+
[TestMethod]
328+
[DataRow(false, true)]
329+
[DataRow(false, false)]
330+
[DataRow(true, true)]
331+
[DataRow(true, false)]
332+
[Owner("kirankk")]
333+
public void FeedRangeEpk_SerdeValdation(bool minInclusive, bool maxInclusive)
334+
{
335+
Documents.Routing.Range<string> range = new Documents.Routing.Range<string>("", "FF", minInclusive, maxInclusive);
336+
RangeJsonConverter rangeConverter = new RangeJsonConverter();
337+
338+
using StringWriter sw = new StringWriter();
339+
using JsonWriter writer = new JsonTextWriter(sw);
340+
{
341+
JsonSerializer jsonSerializer = new JsonSerializer();
342+
343+
rangeConverter.WriteJson(writer, range, jsonSerializer);
344+
345+
string serializedJson = sw.ToString();
346+
System.Diagnostics.Trace.TraceInformation(serializedJson);
347+
348+
using TextReader reader = new StringReader(serializedJson);
349+
using JsonReader jsonReader = new JsonTextReader(reader);
350+
Documents.Routing.Range<string> rangeDeserialized = (Documents.Routing.Range<string>)rangeConverter.ReadJson(jsonReader, typeof(Documents.Routing.Range<string>), null, jsonSerializer);
351+
Assert.IsTrue(range.Equals(rangeDeserialized), serializedJson);
352+
}
353+
}
354+
355+
[TestMethod]
356+
[Owner("kirankk")]
357+
public void FeedRangeEpk_BackwardComptibility()
358+
{
359+
string testJson = @"{""min"":"""",""max"":""FF""}";
360+
System.Diagnostics.Trace.TraceInformation(testJson);
361+
RangeJsonConverter rangeConverter = new RangeJsonConverter();
362+
363+
using TextReader reader = new StringReader(testJson);
364+
using JsonReader jsonReader = new JsonTextReader(reader);
365+
Documents.Routing.Range<string> rangeDeserialized = (Documents.Routing.Range<string>)rangeConverter.ReadJson(jsonReader, typeof(Documents.Routing.Range<string>), null, new JsonSerializer());
366+
367+
Assert.IsTrue(rangeDeserialized.IsMinInclusive);
368+
Assert.IsFalse(rangeDeserialized.IsMaxInclusive);
369+
}
278370
}
279371
}

0 commit comments

Comments
 (0)