Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional tests for System.Text.Json #32705

Merged
merged 9 commits into from
Feb 29, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace System.Text.Json.Serialization
/// </summary>
internal abstract class JsonCollectionConverter<TCollection, TElement> : JsonResumableConverter<TCollection>
{
internal override ClassType ClassType => ClassType.Enumerable;
internal sealed override ClassType ClassType => ClassType.Enumerable;
internal override Type ElementType => typeof(TElement);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace System.Text.Json.Serialization
/// </summary>
internal abstract class JsonDictionaryConverter<T> : JsonResumableConverter<T>
{
internal override ClassType ClassType => ClassType.Dictionary;
internal sealed override ClassType ClassType => ClassType.Dictionary;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should seal the overrides in JsonCollectionConverter and JsonObjectConverter as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 02ab96b

protected internal abstract bool OnWriteResume(Utf8JsonWriter writer, T dictionary, JsonSerializerOptions options, ref WriteStack state);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace System.Text.Json.Serialization
/// </summary>
internal abstract class JsonObjectConverter<T> : JsonResumableConverter<T>
{
internal override ClassType ClassType => ClassType.Object;
internal sealed override ClassType ClassType => ClassType.Object;
internal sealed override Type? ElementType => null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public static partial class JsonSerializer
/// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken"/> which may be used to cancel the write operation.</param>
public static Task SerializeAsync<TValue>(Stream utf8Json, TValue value, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default)
{
if (utf8Json == null)
Copy link
Member

@ahsonkhan ahsonkhan Feb 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, thanks for the pointers to the docs code and example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw new ArgumentNullException(nameof(utf8Json));

return WriteAsyncCore(utf8Json, value, typeof(TValue), options, cancellationToken);
}

Expand Down Expand Up @@ -65,11 +68,6 @@ private static async Task WriteAsyncCore(Stream utf8Json, object? value, Type in
return;
}

if (inputType == null)
{
inputType = value.GetType();
}

WriteStack state = default;
state.InitializeRoot(inputType, options, supportContinuation: true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ namespace System.Text.Json.Serialization.Tests
public static partial class StreamTests
{
[Fact]
public static async Task NullArgumentFail()
public static async Task ReadNullArgumentFail()
{
await Assert.ThrowsAsync<ArgumentNullException>(async () => await JsonSerializer.DeserializeAsync<string>((Stream)null));
await Assert.ThrowsAsync<ArgumentNullException>(async () => await JsonSerializer.DeserializeAsync((Stream)null, (Type)null));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we are doing this, let's add all permutations. For example: have the stream parameter be null, but the type parameter be non-null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 7a6e0cb

await Assert.ThrowsAsync<ArgumentNullException>(async () => await JsonSerializer.DeserializeAsync((Stream)null, typeof(string)));
await Assert.ThrowsAsync<ArgumentNullException>(async () => await JsonSerializer.DeserializeAsync(new MemoryStream(), (Type)null));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ namespace System.Text.Json.Serialization.Tests
{
public static partial class StreamTests
{
[Fact]
public static async Task WriteNullArgumentFail()
{
await Assert.ThrowsAsync<ArgumentNullException>(async () => await JsonSerializer.SerializeAsync((Stream)null, 1));
await Assert.ThrowsAsync<ArgumentNullException>(async () => await JsonSerializer.SerializeAsync((Stream)null, 1, typeof(int)));
}

[Fact]
public static async Task VerifyValueFail()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,82 @@ public static void TestSingleStringsMultiSegment()
}
}

[Fact]
public static void TestMultiSegmentStringConversionToDateTime()
{
string jsonString = "\"1997-07-16\"";
string expectedString = "1997-07-16";
int expectedTokenLength = 10;
DateTime expectedDateTime = DateTime.Parse(expectedString);

byte[] utf8 = Encoding.UTF8.GetBytes(jsonString);

ReadOnlySequence<byte> sequence = JsonTestHelper.CreateSegments(utf8);

for (int j = 0; j < utf8.Length; j++)
{
var utf8JsonReader = new Utf8JsonReader(sequence.Slice(0, j), isFinalBlock: false, default);
ReadDateTimeHelper(ref utf8JsonReader, expectedDateTime, expectedTokenLength);

Assert.Equal(0, utf8JsonReader.TokenStartIndex);

long consumed = utf8JsonReader.BytesConsumed;
utf8JsonReader = new Utf8JsonReader(sequence.Slice(consumed), isFinalBlock: true, utf8JsonReader.CurrentState);
ReadDateTimeHelper(ref utf8JsonReader, expectedDateTime, expectedTokenLength);
}
}

private static void ReadDateTimeHelper(ref Utf8JsonReader jsonReader, DateTime expectedValue, long expectedTokenLength)
{
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonTokenType.String)
{
long tokenLength = jsonReader.HasValueSequence ? jsonReader.ValueSequence.Length : jsonReader.ValueSpan.Length;
Assert.Equal(expectedTokenLength, tokenLength);
Assert.Equal(expectedValue, jsonReader.GetDateTime());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We missed the asserts for TryGetDateTime and TryGetDateTimeOffset APIs.

}
}
}

[Fact]
public static void TestMultiSegmentStringConversionToDateTimeOffset()
{
string jsonString = "\"1997-07-16\"";
string expectedString = "1997-07-16";
int expectedTokenLength = 10;
DateTimeOffset expectedDateTimeOffset = DateTimeOffset.Parse(expectedString);

byte[] utf8 = Encoding.UTF8.GetBytes(jsonString);

ReadOnlySequence<byte> sequence = JsonTestHelper.CreateSegments(utf8);

for (int j = 0; j < utf8.Length; j++)
{
var utf8JsonReader = new Utf8JsonReader(sequence.Slice(0, j), isFinalBlock: false, default);
ReadDateTimeOffsetHelper(ref utf8JsonReader, expectedDateTimeOffset, expectedTokenLength);

Assert.Equal(0, utf8JsonReader.TokenStartIndex);

long consumed = utf8JsonReader.BytesConsumed;
utf8JsonReader = new Utf8JsonReader(sequence.Slice(consumed), isFinalBlock: true, utf8JsonReader.CurrentState);
ReadDateTimeOffsetHelper(ref utf8JsonReader, expectedDateTimeOffset, expectedTokenLength);
}
}

private static void ReadDateTimeOffsetHelper(ref Utf8JsonReader jsonReader, DateTimeOffset expectedValue, long expectedTokenLength)
{
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonTokenType.String)
{
long tokenLength = jsonReader.HasValueSequence ? jsonReader.ValueSequence.Length : jsonReader.ValueSpan.Length;
Assert.Equal(expectedTokenLength, tokenLength);
Assert.Equal(expectedValue, jsonReader.GetDateTimeOffset());
}
}
}

private static void SpanSequenceStatesAreEqualInvalidJson(byte[] dataUtf8, ReadOnlySequence<byte> sequence, int maxDepth, JsonCommentHandling commentHandling)
{
var stateSpan = new JsonReaderState(new JsonReaderOptions { CommentHandling = commentHandling, MaxDepth = maxDepth });
Expand Down