mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-16 07:12:27 +02:00
* Move to Central Package Management. Allows us to store NuGet package versions all in one place. Yay! * Update NuGet packages and fix code for changes. Notable: Changes to ILVerify. Npgsql doesn't need hacks for inet anymore, now we need hacks to make the old code work with this new reality. NUnit's analyzers are already complaining and I didn't even update it to 4.x yet. TerraFX changed to GetLastSystemError so error handling had to be changed. Buncha APIs have more NRT annotations. * Remove dotnet-eng NuGet package source. I genuinely don't know what this was for, and Central Package Management starts throwing warnings about it, so YEET. * Fix double loading of assemblies due to ALC shenanigans. Due to how the "sideloading" code for the ModLoader was set up, it would first try to load Microsoft.Extensions.Primitives from next to the content dll. But we already have that library in Robust! Chaos ensues. We now try to forcibly prioritize loading from the default ALC first to avoid this. * Remove Robust.Physics project. Never used. * Remove erroneous NVorbis reference. Should be VorbisPizza and otherwise wasn't used. * Sandbox fixes * Remove unused unit test package references. Castle.Core and NUnit.ConsoleRunner. * Update NUnit to 4.0.1 This requires replacing all the old assertion methods because they removed them 🥲 * Mute CA1416 (platform check) errors TerraFX started annotating APIs with this and I can't be arsed to entertain this analyzer so out it goes. * Fine ya cranky, no more CPM for Robust.Client.Injectors * Changelog * Oh so that's what dotnet-eng was used for. Yeah ok that makes sense. * Central package management for remaining 2 robust projects * Ok that was a bad idea let's just use NUnit 3 on the analyzer test project * Oh right forgot to remove this one * Update to a newer version of RemoteExecutor * Disable RemoteExecutor test https://github.com/dotnet/arcade/issues/8483 Yeah this package is not well maintained and clearly we can't rely on it. * Fix immutable list serialization
632 lines
22 KiB
C#
632 lines
22 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using NUnit.Framework;
|
|
using Robust.Shared.Serialization.Manager;
|
|
using Robust.Shared.Serialization.Manager.Exceptions;
|
|
using Robust.Shared.Serialization.Markdown;
|
|
using Robust.Shared.Serialization.Markdown.Mapping;
|
|
using Robust.Shared.Serialization.Markdown.Sequence;
|
|
using Robust.Shared.Serialization.Markdown.Value;
|
|
|
|
namespace Robust.UnitTesting.Shared.Serialization.SerializationTests;
|
|
|
|
[TestFixture]
|
|
public sealed partial class ManagerTests : SerializationTest
|
|
{
|
|
/*
|
|
legend: NT => Nullable Type
|
|
RT => Not Nullable Type
|
|
NV => Null Value
|
|
RV => Regular Value
|
|
NS => Null source (copyto)
|
|
NT => Null target (copyto)
|
|
|
|
for each [write|read|copyto|copycreate]
|
|
for each testcase except copyto, do: NT_NV
|
|
NT_RV
|
|
RT_NV //only possible for class
|
|
RT_RV
|
|
for copyto, do: NT_NS_NT
|
|
NT_NS_RT
|
|
NT_RS_NT
|
|
NT_RS_RT
|
|
RT_NS_NT //only possible for class
|
|
RT_NS_RT //only possible for class
|
|
RT_RS_NT //only possible for class
|
|
RT_RS_RT
|
|
testcases: array
|
|
ISelfSerialize (only read/write)
|
|
DataDefinitionSameType (struct, class)
|
|
TypeSerializer (struct, reference)
|
|
ContextTypeSerializer (struct, reference)
|
|
enum
|
|
|
|
todo DataDefinitionBaseType (struct, class) //means: should use !type
|
|
todo returnsource (copy, createcopy)
|
|
todo test the generic variants too
|
|
|
|
//todo figure out a way to tell which serializer we used for (create)copy
|
|
|
|
//todo datarecords
|
|
//todo validate & pushcomposition
|
|
//todo prioritytests ([copybyref] <> null <> custom <> regular <> array/enum <> datadef)
|
|
*/
|
|
|
|
#region DataSources
|
|
|
|
public static IEnumerable<object[]> ReadWriteTypesClass => new[]
|
|
{
|
|
new []
|
|
{
|
|
new object[]
|
|
{
|
|
new ValueDataNode("testValue"),
|
|
() => new SelfSerializeClass { TestValue = "testValue" },
|
|
() => new SelfSerializeClass { TestValue = "anotherTestValue" },
|
|
false,
|
|
new Func<SelfSerializeClass, object>[] { x => x.TestValue }
|
|
}, //ISelfSerialize
|
|
new object[]
|
|
{
|
|
new MappingDataNode(new Dictionary<DataNode, DataNode>
|
|
{
|
|
{ new ValueDataNode("one"), new ValueDataNode("valueOne") },
|
|
{ new ValueDataNode("two"), new SequenceDataNode("2", "3") },
|
|
}){Tag = $"!type:{nameof(DataDefClass)}"},
|
|
() => (IDataDefBaseInterface)new DataDefClass
|
|
{
|
|
OneValue = "valueOne",
|
|
TwoValue = new List<int> { 2, 3 }
|
|
},
|
|
() => (IDataDefBaseInterface)new DataDefClass
|
|
{
|
|
OneValue = "anotherValueOne",
|
|
TwoValue = new List<int> { 3, 4 }
|
|
},
|
|
false,
|
|
new Func<IDataDefBaseInterface, object>[]
|
|
{
|
|
x => ((DataDefClass)x).OneValue,
|
|
x => ((DataDefClass)x).TwoValue,
|
|
}
|
|
}, //DataDefinitionBaseType
|
|
},
|
|
TestableTypesClass
|
|
}.SelectMany(x => x);
|
|
|
|
public static IEnumerable<object[]> TestableTypesClass => new[]
|
|
{
|
|
new object[]
|
|
{
|
|
new SequenceDataNode("1", "2", "3"),
|
|
() => new[] { 1, 2, 3 },
|
|
() => new[] { 3, 4, 5 },
|
|
false,
|
|
new Func<int[], object>[]
|
|
{
|
|
x => x[0],
|
|
x => x[1],
|
|
x => x[2],
|
|
}
|
|
}, //array
|
|
new object[]
|
|
{
|
|
new MappingDataNode(new Dictionary<DataNode, DataNode>
|
|
{
|
|
{ new ValueDataNode("one"), new ValueDataNode("valueOne") },
|
|
{ new ValueDataNode("two"), new SequenceDataNode("2", "3") },
|
|
}),
|
|
() => new DataDefClass
|
|
{
|
|
OneValue = "valueOne",
|
|
TwoValue = new List<int> { 2, 3 }
|
|
},
|
|
() => new DataDefClass
|
|
{
|
|
OneValue = "anotherValueOne",
|
|
TwoValue = new List<int> { 3, 4 }
|
|
},
|
|
false,
|
|
new Func<DataDefClass, object>[]
|
|
{
|
|
x => x.OneValue,
|
|
x => x.TwoValue,
|
|
}
|
|
}, //DataDefSameType
|
|
new object[]
|
|
{
|
|
SerializerRanDataNode,
|
|
SerializerClass.SerializerReturn,
|
|
SerializerClass.SerializerReturnAlt,
|
|
false,
|
|
new Func<SerializerClass, object>[]
|
|
{
|
|
x => x.OneValue,
|
|
x => x.TwoValue,
|
|
}
|
|
}, //TypeSerializer
|
|
new object[]
|
|
{
|
|
SerializerRanCustomDataNode,
|
|
SerializerClass.SerializerCustomReturn,
|
|
SerializerClass.SerializerCustomReturnAlt,
|
|
true,
|
|
new Func<SerializerClass, object>[]
|
|
{
|
|
x => x.OneValue,
|
|
x => x.TwoValue,
|
|
}
|
|
}, //CustomTypeSerializer
|
|
};
|
|
|
|
public static IEnumerable<object[]> ReadWriteTypesStruct => new[]
|
|
{
|
|
new object[][]
|
|
{
|
|
new object[]
|
|
{
|
|
new ValueDataNode("testValue"),
|
|
() => new SelfSerializeStruct { TestValue = "testValue" },
|
|
() => new SelfSerializeStruct { TestValue = "anotherTestValue" },
|
|
false,
|
|
new Func<SelfSerializeStruct, object>[] { x => x.TestValue }
|
|
}, //ISelfSerialize
|
|
/*new object[]
|
|
{
|
|
new MappingDataNode(new Dictionary<DataNode, DataNode>
|
|
{
|
|
{ new ValueDataNode("one"), new ValueDataNode("valueOne") },
|
|
{ new ValueDataNode("two"), new SequenceDataNode("2", "3") },
|
|
}){Tag = $"!type:{nameof(DataDefStruct)}"},
|
|
() => new DataDefStruct
|
|
{
|
|
OneValue = "valueOne",
|
|
TwoValue = new List<int> { 2, 3 }
|
|
} as IDataDefBaseInterface,
|
|
() => new DataDefStruct
|
|
{
|
|
OneValue = "anotherValueOne",
|
|
TwoValue = new List<int> { 3, 4 }
|
|
} as IDataDefBaseInterface,
|
|
false,
|
|
new Func<IDataDefBaseInterface, object>[]
|
|
{
|
|
x => ((DataDefStruct)x).OneValue,
|
|
x => ((DataDefStruct)x).TwoValue,
|
|
}
|
|
}, //DataDefinitionBaseType*/
|
|
},
|
|
TestableTypesStruct
|
|
}.SelectMany(x => x!);
|
|
|
|
public static IEnumerable<object[]> TestableTypesStruct => new object[][]
|
|
{
|
|
new object[]
|
|
{
|
|
new MappingDataNode(new Dictionary<DataNode, DataNode>()
|
|
{
|
|
{ new ValueDataNode("one"), new ValueDataNode("valueOne") },
|
|
{ new ValueDataNode("two"), new SequenceDataNode("2", "3") },
|
|
}),
|
|
() => new DataDefStruct
|
|
{
|
|
OneValue = "valueOne",
|
|
TwoValue = new List<int> { 2, 3 }
|
|
},
|
|
() => new DataDefStruct
|
|
{
|
|
OneValue = "anotherValueOne",
|
|
TwoValue = new List<int> { 3, 4 }
|
|
},
|
|
false,
|
|
new Func<DataDefStruct, object>[]
|
|
{
|
|
x => x.OneValue,
|
|
x => x.TwoValue,
|
|
}
|
|
}, //DataDefSameType
|
|
new object[]
|
|
{
|
|
SerializerRanDataNode,
|
|
SerializerStruct.SerializerReturn,
|
|
SerializerStruct.SerializerReturnAlt,
|
|
false,
|
|
new Func<SerializerStruct, object>[]
|
|
{
|
|
x => x.OneValue,
|
|
x => x.TwoValue,
|
|
}
|
|
}, //TypeSerializer
|
|
new object[]
|
|
{
|
|
SerializerRanCustomDataNode,
|
|
SerializerStruct.SerializerCustomReturn,
|
|
SerializerStruct.SerializerCustomReturnAlt,
|
|
true,
|
|
new Func<SerializerStruct, object>[]
|
|
{
|
|
x => x.OneValue,
|
|
x => x.TwoValue,
|
|
}
|
|
}, //CustomTypeSerializer
|
|
new object[]
|
|
{
|
|
new ValueDataNode("C"),
|
|
() => TestEnum.C,
|
|
() => TestEnum.B,
|
|
false,
|
|
new Func<TestEnum, object>[]{ x => x }
|
|
}
|
|
};
|
|
|
|
public static IEnumerable<object[]> TestableTypesAll =>
|
|
new[] { TestableTypesClass, TestableTypesStruct }.SelectMany(x => x);
|
|
|
|
public static IEnumerable<object[]> ReadWriteTypesAll =>
|
|
new[] { ReadWriteTypesClass, ReadWriteTypesStruct }.SelectMany(x => x);
|
|
|
|
#endregion
|
|
|
|
#region Write
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesStruct))]
|
|
public void Write_NT_NV_Struct<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____)
|
|
where T : struct
|
|
{
|
|
var resNode = Serialization.WriteValue<T?>(null, context: Context(useContext));
|
|
Assert.That(resNode.IsNull);
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesClass))]
|
|
public void Write_NT_NV_Class<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____)
|
|
where T : class
|
|
{
|
|
var resNode = Serialization.WriteValue<T?>(null, context: Context(useContext));
|
|
Assert.That(resNode.IsNull);
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesStruct))]
|
|
public void Write_NT_RV_Struct<T>(DataNode intendedNode, Func<T> value, Func<T> _, bool useContext, object[] __) where T : struct
|
|
{
|
|
var resNode = Serialization.WriteValue<T?>(value(), context: Context(useContext));
|
|
Assert.That(resNode.Equals(intendedNode));
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesClass))]
|
|
public void Write_NT_RV_Class<T>(DataNode intendedNode, Func<T> value, Func<T> _, bool useContext, object[] __) where T : class
|
|
{
|
|
var resNode = Serialization.WriteValue<T?>(value(), context: Context(useContext));
|
|
Assert.That(resNode.Equals(intendedNode));
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesClass))]
|
|
public void Write_RT_NV_Class<T>(DataNode intendedNode, Func<T> value, Func<T> altValue, bool useContext, object[] _) where T : class
|
|
{
|
|
Assert.That(() => Serialization.WriteValue<T>(null!, context: Context(useContext), notNullableOverride: true), Throws.TypeOf<NullNotAllowedException>());
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesAll))]
|
|
public void Write_RT_RV<T>(DataNode intendedNode, Func<T> value, Func<T> altValue, bool useContext, object[] _)
|
|
{
|
|
var resNode = Serialization.WriteValue<T>(value(), context: Context(useContext));
|
|
Assert.That(resNode.Equals(intendedNode));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Read
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesStruct))]
|
|
public void Read_NT_NV_Struct<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____) where T : struct
|
|
{
|
|
var val = Serialization.Read<T?>(ValueDataNode.Null(), context: Context(useContext));
|
|
Assert.That(val, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesClass))]
|
|
public void Read_NT_NV_Class<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____) where T : class
|
|
{
|
|
var val = Serialization.Read<T?>(ValueDataNode.Null(), context: Context(useContext));
|
|
Assert.That(val, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesStruct))]
|
|
public void Read_NT_RV_Struct<T>(DataNode node, Func<T> value, Func<T> _, bool useContext, object[] valueExtractors) where T : struct
|
|
{
|
|
var val = Serialization.Read<T?>(node, context: Context(useContext));
|
|
Assert.That(val, Is.Not.Null);
|
|
AssertEqual(val!.Value, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesClass))]
|
|
public void Read_NT_RV_Class<T>(DataNode node, Func<T> value, Func<T> _, bool useContext, object[] valueExtractors) where T : class
|
|
{
|
|
var val = Serialization.Read<T?>(node, context: Context(useContext));
|
|
Assert.That(val, Is.Not.Null);
|
|
AssertEqual(val!, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesAll))]
|
|
public void Read_RT_NV<T>(DataNode node, Func<T> _, Func<T> __, bool useContext, object[] ___)
|
|
{
|
|
Assert.That(() => Serialization.Read<T>(ValueDataNode.Null(), context: Context(useContext), notNullableOverride: true),
|
|
Throws.TypeOf<NullNotAllowedException>());
|
|
}
|
|
|
|
[TestCaseSource(nameof(ReadWriteTypesAll))]
|
|
public void Read_RT_RV<T>(DataNode node, Func<T> value, Func<T> __, bool useContext, object[] valueExtractors)
|
|
{
|
|
var val = Serialization.Read<T>(node, context: Context(useContext));
|
|
AssertEqual(val!, value(), valueExtractors);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CopyTo
|
|
|
|
[TestCaseSource(nameof(TestableTypesStruct))]
|
|
public void CopyTo_NT_NS_NT_Struct<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____)
|
|
where T : struct
|
|
{
|
|
T? target = null;
|
|
Serialization.CopyTo<T?>(null, ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_NT_NS_NT_Class<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____)
|
|
where T : class
|
|
{
|
|
T? target = null;
|
|
Serialization.CopyTo<T?>(null, ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesStruct))]
|
|
public void CopyTo_NT_NS_RT_Struct<T>(DataNode _, Func<T> value, Func<T> __, bool useContext, object[] ___)
|
|
where T : struct
|
|
{
|
|
T? target = value();
|
|
Serialization.CopyTo<T?>(null, ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_NT_NS_RT_Class<T>(DataNode _, Func<T> value, Func<T> __, bool useContext, object[] ___)
|
|
where T : class
|
|
{
|
|
T? target = value();
|
|
Serialization.CopyTo<T?>(null, ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesStruct))]
|
|
public void CopyTo_NT_RS_NT_Struct<T>(DataNode _, Func<T> value, Func<T> __, bool useContext,
|
|
object[] valueExtractors) where T : struct
|
|
{
|
|
T? target = null;
|
|
Serialization.CopyTo<T?>(value(), ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Not.Null);
|
|
AssertEqual(target!.Value, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_NT_RS_NT_Class<T>(DataNode _, Func<T> value, Func<T> __, bool useContext,
|
|
object[] valueExtractors) where T : class
|
|
{
|
|
T? target = null;
|
|
Serialization.CopyTo<T?>(value(), ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Not.Null);
|
|
AssertEqual(target!, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesStruct))]
|
|
public void CopyTo_NT_RS_RT_Struct<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors) where T : struct
|
|
{
|
|
T? target = altValue();
|
|
Serialization.CopyTo<T?>(value(), ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Not.Null);
|
|
AssertEqual(target!.Value, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_NT_RS_RT_Class<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors) where T : class
|
|
{
|
|
T? target = altValue();
|
|
Serialization.CopyTo<T?>(value(), ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Not.Null);
|
|
AssertEqual(target!, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_RT_NS_NT_Class<T>(DataNode _, Func<T> __, Func<T> ___, bool useContext, object[] ____)
|
|
where T : class
|
|
{
|
|
T target = null!;
|
|
Assert.That(() => { Serialization.CopyTo(null!, ref target, context: Context(useContext), notNullableOverride: true); },
|
|
Throws.TypeOf<NullNotAllowedException>());
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_RT_NS_RT_Class<T>(DataNode _, Func<T> value, Func<T> __, bool useContext, object[] ___)
|
|
where T : class
|
|
{
|
|
T? target = value();
|
|
Assert.That(() => { Serialization.CopyTo<T>(null!, ref target, context: Context(useContext), notNullableOverride: true); },
|
|
Throws.TypeOf<NullNotAllowedException>());
|
|
}
|
|
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CopyTo_RT_RS_NT_Class<T>(DataNode _, Func<T> value, Func<T> ___, bool useContext,
|
|
object[] valueExtractors) where T : class
|
|
{
|
|
T target = null!;
|
|
Serialization.CopyTo(value(), ref target, context: Context(useContext));
|
|
Assert.That(target, Is.Not.Null);
|
|
AssertEqual(target!, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesAll))]
|
|
public void CopyTo_RT_RS_RT<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors)
|
|
{
|
|
var target = altValue();
|
|
Serialization.CopyTo(value(), ref target, context: Context(useContext));
|
|
AssertEqual(target!, value(), valueExtractors);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CreateCopy
|
|
|
|
[TestCaseSource(nameof(TestableTypesStruct))]
|
|
public void CreateCopy_NT_NV_Struct<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors) where T : struct
|
|
{
|
|
var copy = Serialization.CreateCopy<T?>(null, context: Context(useContext));
|
|
Assert.That(copy, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CreateCopy_NT_NV_Class<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors) where T : class
|
|
{
|
|
var copy = Serialization.CreateCopy<T?>(null, context: Context(useContext));
|
|
Assert.That(copy, Is.Null);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesAll))]
|
|
public void CreateCopy_NT_RV<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors)
|
|
{
|
|
var copy = Serialization.CreateCopy<T?>(value(), context: Context(useContext));
|
|
Assert.That(copy, Is.Not.Null);
|
|
AssertEqual(copy!, value(), valueExtractors);
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesClass))]
|
|
public void CreateCopy_RT_NV_Class<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors) where T : class
|
|
{
|
|
Assert.That(() =>
|
|
{
|
|
var __ = Serialization.CreateCopy<T>(null!, context: Context(useContext), notNullableOverride: true);
|
|
}, Throws.TypeOf<NullNotAllowedException>());
|
|
}
|
|
|
|
[TestCaseSource(nameof(TestableTypesAll))]
|
|
public void CreateCopy_RT_RV<T>(DataNode _, Func<T> value, Func<T> altValue, bool useContext,
|
|
object[] valueExtractors)
|
|
{
|
|
var copy = Serialization.CreateCopy<T>(value(), context: Context(useContext));
|
|
AssertEqual(copy, value(), valueExtractors);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CopyByRef
|
|
|
|
[Test]
|
|
public void CopyTo_CopyByRef_Class()
|
|
{
|
|
CopyByRefTestClass target = null!;
|
|
var source = new CopyByRefTestClass();
|
|
Serialization.CopyTo(source, ref target, notNullableOverride: true);
|
|
Assert.That(target, Is.Not.Null);
|
|
Assert.That(target!, Is.SameAs(source));
|
|
}
|
|
|
|
[Test]
|
|
public void CopyTo_CopyByRef_NV_Class()
|
|
{
|
|
CopyByRefTestClass? target = null;
|
|
Serialization.CopyTo(null, ref target);
|
|
Assert.That(target, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void CreateCopy_CopyByRef_Class()
|
|
{
|
|
var source = new CopyByRefTestClass();
|
|
var copy = Serialization.CreateCopy(source, notNullableOverride: true);
|
|
Assert.That(copy, Is.SameAs(source));
|
|
}
|
|
|
|
[Test]
|
|
public void CreateCopy_CopyByRef_NV_Class()
|
|
{
|
|
var copy = Serialization.CreateCopy<CopyByRefTestClass?>(null);
|
|
Assert.That(copy, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void CopyTo_CopyByRef_Struct()
|
|
{
|
|
CopyByRefTestStruct? target = null;
|
|
var source = new CopyByRefTestStruct{ID = 5};
|
|
Serialization.CopyTo(source, ref target);
|
|
Assert.That(target, Is.Not.Null);
|
|
Assert.That(target!.Value.ID, Is.EqualTo(source.ID));
|
|
}
|
|
|
|
[Test]
|
|
public void CopyTo_CopyByRef_NV_Struct()
|
|
{
|
|
CopyByRefTestStruct? target = null;
|
|
Serialization.CopyTo(null, ref target);
|
|
Assert.That(target, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void CreateCopy_CopyByRef_Struct()
|
|
{
|
|
var source = new CopyByRefTestStruct{ID = 5};
|
|
var copy = Serialization.CreateCopy(source);
|
|
Assert.That(copy.ID, Is.EqualTo(source.ID));
|
|
}
|
|
|
|
[Test]
|
|
public void CreateCopy_CopyByRef_NV_Struct()
|
|
{
|
|
var copy = Serialization.CreateCopy<CopyByRefTestStruct?>(null);
|
|
Assert.That(copy, Is.Null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void AssertEqual<T>(T a, T b, object[] valueExtractors)
|
|
{
|
|
Assert.Multiple(() =>
|
|
{
|
|
foreach (var extractor in valueExtractors.Cast<Func<T, object>>())
|
|
{
|
|
var objA = extractor(a);
|
|
var objB = extractor(b);
|
|
|
|
Assert.That(objA.GetType(), Is.EqualTo(objB.GetType()));
|
|
|
|
if (objA is not List<int> listA)
|
|
{
|
|
Assert.That(extractor(a).Equals(extractor(b)));
|
|
continue;
|
|
}
|
|
|
|
var listB = (List<int>)objB;
|
|
|
|
Assert.That(listA, Has.Count.EqualTo(listB.Count));
|
|
|
|
for (int i = 0; i < listA.Count; i++)
|
|
{
|
|
Assert.That(listA[i], Is.EqualTo(listB[i]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private ISerializationContext? Context(bool useContext) => useContext ? this : null;
|
|
}
|