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

Enable Native AOT testing in System.Text.Json. #86975

Merged
merged 3 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,15 @@ public static void Equal<T>(HashSet<T> expected, HashSet<T> actual)
}
}

/// <summary>Validates that the two sets contains the same elements. XUnit doesn't display the full collections.</summary>
public static void Equal<T>(ISet<T> expected, ISet<T> actual)
{
if (!actual.SetEquals(expected))
{
throw new XunitException($"Expected: {string.Join(", ", expected)}{Environment.NewLine}Actual: {string.Join(", ", actual)}");
}
}

/// <summary>
/// Validates that the actual collection contains same items as expected collection. If the test fails, this will display:
/// 1. Count if two collection count are different;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ public async Task WriteRootLevelAsyncEnumerable<TElement>(IEnumerable<TElement>
return;
}

JsonSerializerOptions options = new JsonSerializerOptions
{
DefaultBufferSize = bufferSize
};
JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false);
options.DefaultBufferSize = bufferSize;

string expectedJson = JsonSerializer.Serialize(source);
string expectedJson = JsonSerializer.Serialize(source, options);

using var stream = new Utf8MemoryStream();
var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
Expand All @@ -48,37 +46,10 @@ public async Task WriteNestedAsyncEnumerable<TElement>(IEnumerable<TElement> sou
return;
}

JsonSerializerOptions options = new JsonSerializerOptions
{
DefaultBufferSize = bufferSize
};
JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false);
options.DefaultBufferSize = bufferSize;

string expectedJson = JsonSerializer.Serialize(new { Data = source });

using var stream = new Utf8MemoryStream();
var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
await StreamingSerializer.SerializeWrapper(stream, new AsyncEnumerableDto<TElement> { Data = asyncEnumerable }, options);

JsonTestHelper.AssertJsonEqual(expectedJson, stream.AsString());
Assert.Equal(1, asyncEnumerable.TotalCreatedEnumerators);
Assert.Equal(1, asyncEnumerable.TotalDisposedEnumerators);
}

[Theory]
[MemberData(nameof(GetAsyncEnumerableSources))]
public async Task WriteNestedAsyncEnumerable_DTO<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
Copy link
Member Author

Choose a reason for hiding this comment

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

This test was identical to the one above, so I deleted it.

{
if (StreamingSerializer?.IsAsyncSerializer != true)
{
return;
}

JsonSerializerOptions options = new JsonSerializerOptions
{
DefaultBufferSize = bufferSize
};

string expectedJson = JsonSerializer.Serialize(new { Data = source });
string expectedJson = JsonSerializer.Serialize(new EnumerableDto<TElement> { Data = source }, options);

using var stream = new Utf8MemoryStream();
var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
Expand All @@ -100,11 +71,9 @@ public async Task WriteNestedAsyncEnumerable_Nullable<TElement>(IEnumerable<TEle

// Primarily tests the ability of NullableConverter to flow async serialization state

JsonSerializerOptions options = new JsonSerializerOptions
{
DefaultBufferSize = bufferSize,
IncludeFields = true,
};
JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false);
options.DefaultBufferSize = bufferSize;
options.IncludeFields = true;

string expectedJson = JsonSerializer.Serialize<(IEnumerable<TElement>, bool)?>((source, false), options);

Expand Down Expand Up @@ -164,11 +133,22 @@ async IAsyncEnumerable<int> CreateEnumerable([EnumeratorCancellation] Cancellati
Assert.Equal(1, longRunningEnumerable.TotalDisposedEnumerators);
}

public class EnumerableDto<TElement>
{
public IEnumerable<TElement> Data { get; set; }
}

public class AsyncEnumerableDto<TElement>
{
public IAsyncEnumerable<TElement> Data { get; set; }
}

public class EnumerableDtoWithTwoProperties<TElement>
{
public IEnumerable<TElement> Data1 { get; set; }
public IEnumerable<TElement> Data2 { get; set; }
}

public class AsyncEnumerableDtoWithTwoProperties<TElement>
{
public IAsyncEnumerable<TElement> Data1 { get; set; }
Expand All @@ -184,12 +164,10 @@ public async Task WriteSequentialNestedAsyncEnumerables<TElement>(IEnumerable<TE
return;
}

JsonSerializerOptions options = new JsonSerializerOptions
{
DefaultBufferSize = bufferSize
};
JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false);
options.DefaultBufferSize = bufferSize;

string expectedJson = JsonSerializer.Serialize(new { Data1 = source, Data2 = source });
string expectedJson = JsonSerializer.Serialize(new EnumerableDtoWithTwoProperties<TElement> { Data1 = source, Data2 = source }, options);

using var stream = new Utf8MemoryStream();
var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
Expand All @@ -209,13 +187,11 @@ public async Task WriteAsyncEnumerableOfAsyncEnumerables<TElement>(IEnumerable<T
return;
}

JsonSerializerOptions options = new JsonSerializerOptions
{
DefaultBufferSize = bufferSize
};
JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false);
options.DefaultBufferSize = bufferSize;

const int OuterEnumerableCount = 5;
string expectedJson = JsonSerializer.Serialize(Enumerable.Repeat(source, OuterEnumerableCount));
string expectedJson = JsonSerializer.Serialize(Enumerable.Repeat(source, OuterEnumerableCount), options);

var innerAsyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
var outerAsyncEnumerable =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,20 +617,19 @@ public async Task ReadNullableGenericStructISetWithNullJson()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
public async Task ReadISetTOfHashSetT()
{
ISet<HashSet<int>> result = await Serializer.DeserializeWrapper<ISet<HashSet<int>>>(@"[[1,2],[3,4]]");

if (result.First().Contains(1))
{
Assert.Equal(new HashSet<int> { 1, 2 }, result.First());
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
Assert.Equal(new HashSet<int> { 3, 4 }, result.Last());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, result.First());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, result.Last());
}
else
{
Assert.Equal(new HashSet<int> { 3, 4 }, result.First());
Assert.Equal(new HashSet<int> { 1, 2 }, result.Last());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, result.First());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, result.Last());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,6 @@ public async Task GenericStructISetWrapperT()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
public async Task WriteISetTOfISetT()
{
ISet<ISet<int>> input = new HashSet<ISet<int>>
Expand Down Expand Up @@ -433,7 +432,6 @@ public async Task WriteISetTOfISetT()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
public async Task WriteISetTOfHashSetT()
{
ISet<HashSet<int>> input = new HashSet<HashSet<int>>
Expand All @@ -449,13 +447,13 @@ public async Task WriteISetTOfHashSetT()

if (input.First().Contains(1))
{
Assert.Equal(new HashSet<int> { 1, 2 }, input.First());
Assert.Equal(new HashSet<int> { 3, 4 }, input.Last());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, input.First());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, input.Last());
}
else
{
Assert.Equal(new HashSet<int> { 3, 4 }, input.First());
Assert.Equal(new HashSet<int> { 1, 2 }, input.Last());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, input.First());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, input.Last());
}
}

Expand Down Expand Up @@ -649,13 +647,13 @@ public async Task WriteHashSetTOfHashSetT()

if (input.First().Contains(1))
{
Assert.Equal(new HashSet<int> { 1, 2 }, input.First());
Assert.Equal(new HashSet<int> { 3, 4 }, input.Last());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, input.First());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, input.Last());
}
else
{
Assert.Equal(new HashSet<int> { 3, 4 }, input.First());
Assert.Equal(new HashSet<int> { 1, 2 }, input.Last());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, input.First());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, input.Last());
}

GenericHashSetWrapper<StringHashSetWrapper> input2 = new GenericHashSetWrapper<StringHashSetWrapper>(new List<StringHashSetWrapper>
Expand Down Expand Up @@ -696,7 +694,6 @@ public async Task WriteHashSetTOfArray()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
public async Task WriteArrayOfHashSetT()
{
HashSet<int>[] input = new HashSet<int>[2];
Expand All @@ -707,8 +704,8 @@ public async Task WriteArrayOfHashSetT()

// Because order isn't guaranteed, roundtrip data to ensure write was accurate.
input = await Serializer.DeserializeWrapper<HashSet<int>[]>(json);
Assert.Equal(new HashSet<int> { 1, 2 }, input.First());
Assert.Equal(new HashSet<int> { 3, 4 }, input.Last());
AssertExtensions.Equal(new HashSet<int> { 1, 2 }, input.First());
AssertExtensions.Equal(new HashSet<int> { 3, 4 }, input.Last());
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async Task SerializeObject(Type type, JsonSerializerOptions options)
async Task RunTestAsync(Type type)
{
// Use local options to avoid obtaining already cached metadata from the default options.
var options = new JsonSerializerOptions();
JsonSerializerOptions options = Serializer.CreateOptions();

const int ThreadCount = 8;
const int ConcurrentTestsCount = 4;
Expand Down Expand Up @@ -90,7 +90,7 @@ async Task RunTestAsync(Type type)
public async Task PropertyCacheWithMinInputsFirst()
{
// Use local options to avoid obtaining already cached metadata from the default options.
var options = new JsonSerializerOptions();
JsonSerializerOptions options = Serializer.CreateOptions();

string json = "{}";
await Serializer.DeserializeWrapper<ObjWCtorMixedParams>(json, options);
Expand All @@ -107,7 +107,7 @@ public async Task PropertyCacheWithMinInputsFirst()
public async Task PropertyCacheWithMinInputsLast()
{
// Use local options to avoid obtaining already cached metadata from the default options.
var options = new JsonSerializerOptions();
JsonSerializerOptions options = Serializer.CreateOptions();

ObjWCtorMixedParams testObj = ObjWCtorMixedParams.GetInstance();
testObj.Verify();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,7 @@ public async Task InvalidJsonFails()
await Assert.ThrowsAsync<JsonException>(() => Serializer.DeserializeWrapper<Point_2D_Struct>("{true"));
}

#if !BUILDING_SOURCE_GENERATOR_TESTS // Anonymous types not supported in source gen
Copy link
Member Author

Choose a reason for hiding this comment

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

The test is hardcoding reflection, so I'm just disabling it for source gen.

[Fact]
public void AnonymousObject()
{
Expand Down Expand Up @@ -1087,6 +1088,7 @@ public void AnonymousObject_NamingPolicy()
// Verify match with naming policy
Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj));
}
#endif

public record MyRecord(int Prop);

Expand Down Expand Up @@ -1329,29 +1331,29 @@ public class ClassWithIgnoredSameType
}

[Fact]
public void StructWithPropertyInit_DeseralizeEmptyObject()
public async Task StructWithPropertyInit_DeseralizeEmptyObject()
{
string json = @"{}";
var obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
var obj = await Serializer.DeserializeWrapper<StructWithPropertyInit>(json);
Assert.Equal(42, obj.A);
Assert.Equal(0, obj.B);
}

[Fact]
public void StructWithPropertyInit_OverrideInitedProperty()
public async Task StructWithPropertyInit_OverrideInitedProperty()
{
string json = @"{""A"":43}";
var obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
var obj = await Serializer.DeserializeWrapper<StructWithPropertyInit>(json);
Assert.Equal(43, obj.A);
Assert.Equal(0, obj.B);

json = @"{""A"":0,""B"":44}";
obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
obj = await Serializer.DeserializeWrapper<StructWithPropertyInit>(json);
Assert.Equal(0, obj.A);
Assert.Equal(44, obj.B);

json = @"{""B"":45}";
obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
obj = await Serializer.DeserializeWrapper<StructWithPropertyInit>(json);
Assert.Equal(42, obj.A); // JSON doesn't set A property so it's expected to be 42
Assert.Equal(45, obj.B);
}
Expand All @@ -1364,10 +1366,10 @@ public struct StructWithPropertyInit
}

[Fact]
public void StructWithFieldInit_DeseralizeEmptyObject()
public async Task StructWithFieldInit_DeseralizeEmptyObject()
{
string json = @"{}";
var obj = JsonSerializer.Deserialize<StructWithFieldInit>(json);
var obj = await Serializer.DeserializeWrapper<StructWithFieldInit>(json);
Assert.Equal(0, obj.A);
Assert.Equal(42, obj.B);
}
Expand All @@ -1380,10 +1382,10 @@ public struct StructWithFieldInit
}

[Fact]
public void StructWithExplicitParameterlessCtor_DeseralizeEmptyObject()
public async Task StructWithExplicitParameterlessCtor_DeseralizeEmptyObject()
{
string json = @"{}";
var obj = JsonSerializer.Deserialize<StructWithExplicitParameterlessCtor>(json);
var obj = await Serializer.DeserializeWrapper<StructWithExplicitParameterlessCtor>(json);
Assert.Equal(42, obj.A);
}

Expand Down Expand Up @@ -1431,18 +1433,17 @@ public async Task TestClassWithDefaultCtorParams()
JsonTestHelper.AssertJsonEqual(json, await Serializer.SerializeWrapper(obj));
}

#if FIXED // https://github.com/dotnet/roslyn/issues/66900
[Fact]
public async Task TestClassWithManyConstructorParameters()
{
ClassWithManyConstructorParameters value = ClassWithManyConstructorParameters.Create();
string json = JsonSerializer.Serialize(value);
string json = await Serializer.SerializeWrapper(value);

ClassWithManyConstructorParameters result = await Serializer.DeserializeWrapper<ClassWithManyConstructorParameters>(json);

Assert.Equal(value, result); // Type is C# record that implements structural equality.
}
#endif

public class ClassWithDefaultCtorParams
{
public Point_2D_Struct_WithAttribute Struct { get; }
Expand Down Expand Up @@ -1543,6 +1544,7 @@ public class ClassWithDefaultCtorParams
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/79311", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))]
public async Task TestTypeWithEnumParameters()
{
// Regression test for https://github.com/dotnet/runtime/issues/68647
Expand Down