Skip to content

Commit

Permalink
Test static initialization with JsonTypeInfo (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
krwq committed Jun 22, 2022
1 parent 91bdc9e commit bb32820
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/libraries/System.Text.Json/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@
<value>The requested operation requires an element of type '{0}', but the target element has type '{1}'.</value>
</data>
<data name="TypeInfoResolverImmutable" xml:space="preserve">
<value>Default TypeInfoResolver and custom TypeInfoResolver after first usage cannot be changed.</value>
<value>Default TypeInfoResolver and custom TypeInfoResolver cannot be changed after first usage.</value>
</data>
<data name="TypeInfoImmutable" xml:space="preserve">
<value>JsonTypeInfo cannot be changed after first usage.</value>
Expand Down Expand Up @@ -662,4 +662,7 @@
<data name="JsonPropertyInfoBoundToDifferentParent" xml:space="preserve">
<value>JsonPropertyInfo with name '{0}' for type '{1}' is already bound to different JsonTypeInfo.</value>
</data>
<data name="JsonTypeInfoUsedButTypeInfoResolverNotSet" xml:space="preserve">
<value>Using JsonTypeInfo for serialization is not possible when TypeInfoResolver has not been set.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,12 @@ internal void InitializeForReflectionSerializer()
private JsonTypeInfo? GetTypeInfoInternal(Type type)
{
IJsonTypeInfoResolver? resolver = _effectiveJsonTypeInfoResolver ?? _typeInfoResolver;

if (resolver == null)
{
ThrowHelper.ThrowInvalidOperationException_JsonTypeInfoUsedButTypeInfoResolverNotSet();
}

JsonTypeInfo? info = resolver?.GetTypeInfo(type, this);

if (info != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ public static void ThrowInvalidOperationException_ResolverTypeInfoOptionsNotComp
throw new InvalidOperationException(SR.ResolverTypeInfoOptionsNotCompatible);
}

[DoesNotReturn]
public static void ThrowInvalidOperationException_JsonTypeInfoUsedButTypeInfoResolverNotSet()
{
throw new InvalidOperationException(SR.JsonTypeInfoUsedButTypeInfoResolverNotSet);
}

[DoesNotReturn]
public static void ThrowInvalidOperationException_SerializationConverterOnAttributeInvalid(Type classType, MemberInfo? memberInfo)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using System.Text.Json.Serialization.Metadata;
using System.Threading.Tasks;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Text.Json.Serialization.Tests
Expand Down Expand Up @@ -178,6 +179,79 @@ public static void ModifiersAreCalledAndModifyTypeInfos()
Assert.True(secondModifierCalled);
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void StaticInitialization_SerializationWithJsonTypeInfoWithoutSettingTypeInfoResolverThrows()
{
RemoteExecutor.Invoke(static () =>
{
JsonSerializerOptions o = new();
DefaultJsonTypeInfoResolver r = new();
// note: TypeInfoResolver not set
JsonTypeInfo<SomeClass> ti = (JsonTypeInfo<SomeClass>)r.GetTypeInfo(typeof(SomeClass), o);
SomeClass obj = new()
{
ObjProp = "test",
IntProp = 42,
};
// TODO: reasses if this is expected behavior
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(obj, ti));
}).Dispose();
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void StaticInitialization_DeserializationWithJsonTypeInfoWithoutSettingTypeInfoResolverThrows()
{
RemoteExecutor.Invoke(static () =>
{
JsonSerializerOptions o = new();
DefaultJsonTypeInfoResolver r = new();
// note: TypeInfoResolver not set
JsonTypeInfo<SomeClass> ti = (JsonTypeInfo<SomeClass>)r.GetTypeInfo(typeof(SomeClass), o);
// TODO: reasses if this is expected behavior
string json = """{"ObjProp":"test","IntProp":42}""";
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize(json, ti));
}).Dispose();
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void StaticInitialization_SerializationWithJsonTypeInfoWhenTypeInfoResolverSetIsPossible()
{
RemoteExecutor.Invoke(static () =>
{
JsonSerializerOptions o = new();
DefaultJsonTypeInfoResolver r = new();
o.TypeInfoResolver = r;
JsonTypeInfo<SomeClass> ti = (JsonTypeInfo<SomeClass>)r.GetTypeInfo(typeof(SomeClass), o);
SomeClass obj = new()
{
ObjProp = "test",
IntProp = 42,
};
string json = JsonSerializer.Serialize(obj, ti);
Assert.Equal("""{"ObjProp":"test","IntProp":42}""", json);
}).Dispose();
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void StaticInitialization_DeserializationWithJsonTypeInfoWhenTypeInfoResolverSetIsPossible()
{
RemoteExecutor.Invoke(static () =>
{
JsonSerializerOptions o = new();
DefaultJsonTypeInfoResolver r = new();
o.TypeInfoResolver = r;
JsonTypeInfo<SomeClass> ti = (JsonTypeInfo<SomeClass>)r.GetTypeInfo(typeof(SomeClass), o);
string json = """{"ObjProp":"test","IntProp":42}""";
SomeClass deserialized = JsonSerializer.Deserialize(json, ti);
Assert.IsType<JsonElement>(deserialized.ObjProp);
Assert.Equal("test", ((JsonElement)deserialized.ObjProp).GetString());
Assert.Equal(42, deserialized.IntProp);
}).Dispose();
}

private static void InvokeGeneric(Type type, string methodName, params object[] args)
{
typeof(DefaultJsonTypeInfoResolverTests)
Expand Down

0 comments on commit bb32820

Please sign in to comment.