diff --git a/Directory.Packages.props b/Directory.Packages.props index b0bf6262..4a017103 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -41,8 +41,8 @@ - - + + diff --git a/test/Nerdbank.MessagePack.Tests/ArraysOfPrimitivesTests.cs b/test/Nerdbank.MessagePack.TUnit/ArraysOfPrimitivesTests.cs similarity index 60% rename from test/Nerdbank.MessagePack.Tests/ArraysOfPrimitivesTests.cs rename to test/Nerdbank.MessagePack.TUnit/ArraysOfPrimitivesTests.cs index 77773f9d..faecbe6c 100644 --- a/test/Nerdbank.MessagePack.Tests/ArraysOfPrimitivesTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ArraysOfPrimitivesTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Numerics; -using System.Reflection; public partial class ArraysOfPrimitivesTests : MessagePackSerializerTestBase { @@ -12,8 +11,8 @@ public partial class ArraysOfPrimitivesTests : MessagePackSerializerTestBase private static readonly Random Random = new Random(); #endif - [Theory, PairwiseData] - public void BoolArray([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(byte))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void BoolArray(int length) { bool[]? values = null; if (length >= 0) @@ -26,8 +25,8 @@ public void BoolArray([CombinatorialMemberData(nameof(GetInterestingLengths), ty this.Roundtrip(values); } - [Theory, PairwiseData] - public void Boolean([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(byte))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Boolean(int length) { bool[]? values = null; if (length >= 0) @@ -40,40 +39,40 @@ public void Boolean([CombinatorialMemberData(nameof(GetInterestingLengths), type this.Roundtrip, Witness>(values); } - [Theory, PairwiseData] - public void Int8([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(sbyte))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Int8(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void Int16([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(short))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Int16(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void Int32([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(int))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Int32(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void Int64([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(long))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Int64(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void UInt8([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(byte))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void UInt8(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void UInt16([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(ushort))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void UInt16(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void UInt32([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(uint))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void UInt32(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void UInt64([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(ulong))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void UInt64(int length) => this.Roundtrip, Witness>(GetRandomValues(length)); - [Theory, PairwiseData] - public void Single([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(float))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Single(int length) { float[]? values = null; if (length >= 0) @@ -92,8 +91,8 @@ public void Single([CombinatorialMemberData(nameof(GetInterestingLengths), typeo this.Roundtrip, Witness>(values); } - [Theory, PairwiseData] - public void Double([CombinatorialMemberData(nameof(GetInterestingLengths), typeof(double))] int length) + [Test, MethodDataSource(typeof(GetInterestingLengthsHelper), nameof(GetInterestingLengthsHelper<>.Helper))] + public void Double(int length) { double[]? values = null; if (length >= 0) @@ -108,7 +107,7 @@ public void Double([CombinatorialMemberData(nameof(GetInterestingLengths), typeo this.Roundtrip, Witness>(values); } - [Fact] + [Test] public void LargeEnumerableOfInt() { // A very large enumerable so that it exceeds any default buffer sizes. @@ -138,13 +137,14 @@ public void LargeEnumerableOfInt() return values; } - private static int[] GetInterestingLengths(Type type) => (int[])typeof(ArraysOfPrimitivesTests).GetMethod(nameof(GetInterestingLengthsHelper), BindingFlags.NonPublic | BindingFlags.Static)!.MakeGenericMethod(type).Invoke(null, null)!; - + public static class GetInterestingLengthsHelper + { #if NET - private static int[] GetInterestingLengthsHelper() => [-1, 0, 4, Vector.Count - 1, Vector.Count, Vector.Count + 1, (Vector.Count * 2) + 2, 10_000]; + public static int[] Helper() => [-1, 0, 4, Vector.Count - 1, Vector.Count, Vector.Count + 1, (Vector.Count * 2) + 2, 10_000]; #else - private static int[] GetInterestingLengthsHelper() => [-1, 0, 4, 100, 10_000]; + public static int[] Helper() => [-1, 0, 4, 100, 10_000]; #endif + } [GenerateShapeFor] [GenerateShapeFor>] diff --git a/test/Nerdbank.MessagePack.Tests/AsyncSerializationTests.cs b/test/Nerdbank.MessagePack.TUnit/AsyncSerializationTests.cs similarity index 93% rename from test/Nerdbank.MessagePack.Tests/AsyncSerializationTests.cs rename to test/Nerdbank.MessagePack.TUnit/AsyncSerializationTests.cs index 05a0594e..aaeb3a91 100644 --- a/test/Nerdbank.MessagePack.Tests/AsyncSerializationTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/AsyncSerializationTests.cs @@ -1,18 +1,18 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -[Trait("AsyncSerialization", "true")] +[Property("AsyncSerialization", "true")] public partial class AsyncSerializationTests : MessagePackSerializerTestBase { private static readonly ReadOnlyMemory BigDataBlob = Enumerable.Range(0, 100).Select(n => (byte)(n % 256)).ToArray(); - [Fact] + [Test] public async Task RoundtripPoco() => await this.AssertRoundtripAsync(new Poco(1, 2)); - [Fact] + [Test] public async Task RoundtripPocoWithDefaultCtor() => await this.AssertRoundtripAsync(new PocoWithDefaultCtor { X = 1, Y = 2 }); - [Fact] + [Test] public async Task PocoDictionary() { DictionaryOfPocos value = new(new Dictionary @@ -25,7 +25,7 @@ public async Task PocoDictionary() await this.AssertRoundtripAsync(value); } - [Fact] + [Test] public async Task PrimitivesDictionary() { DictionaryOfPrimitives value = new(new Dictionary @@ -38,13 +38,13 @@ public async Task PrimitivesDictionary() await this.AssertRoundtripAsync(value); } - [Fact] + [Test] public async Task LargeArray() => await this.AssertRoundtripAsync(new ArrayOfPocos(Enumerable.Range(0, 1000).Select(i => new Poco(i, i)).ToArray())); /// /// Verifies that the array converter can handle async serialization when its elements are not async capable. /// - [Fact] + [Test] public async Task LargeArrayWithBigElements() { this.Serializer = this.Serializer with { Converters = [.. this.Serializer.Converters, new PocoNonAsyncConverter()] }; @@ -52,40 +52,40 @@ public async Task LargeArrayWithBigElements() await this.AssertRoundtripAsync(new ArrayOfPocos(Enumerable.Range(0, 1000).Select(i => new Poco(i, i) { DataBlob = BigDataBlob }).ToArray())); } - [Fact] + [Test] public async Task LargeList() => await this.AssertRoundtripAsync(new ListOfPocos(Enumerable.Range(0, 1000).Select(i => new Poco(i, i)).ToList())); - [Fact] + [Test] public async Task LargeImmutableArray() => await this.AssertRoundtripAsync(new ImmutableArrayOfPocos(Enumerable.Range(0, 1000).Select(i => new Poco(i, i)).ToImmutableArray())); - [Fact] + [Test] public async Task Null_Array() => await this.AssertRoundtripAsync(new ArrayOfPocos(null)); - [Fact] + [Test] public async Task Null() => await this.AssertRoundtripAsync(null); - [Fact] + [Test] public async Task ArrayOfInts() => await this.AssertRoundtripAsync(new ArrayOfPrimitives([1, 2, 3])); - [Fact] + [Test] public async Task ObjectAsArrayOfValues() => await this.AssertRoundtripAsync(new PocoAsArray(42)); - [Fact] + [Test] public async Task ObjectAsArrayOfValues_Null() => await this.AssertRoundtripAsync(null); - [Fact] + [Test] public async Task ObjectAsArrayOfValues_DefaultCtor() => await this.AssertRoundtripAsync(new PocoAsArrayWithDefaultCtor { Value = 42 }); - [Fact] + [Test] public async Task ObjectAsArrayOfValues_DefaultCtor_Null() => await this.AssertRoundtripAsync(null); - [Fact] + [Test] public async Task WithPreBuffering() { SpecialRecordConverter converter = new(); this.Serializer = this.Serializer with { Converters = [converter] }; var msgpack = new ReadOnlySequence( - this.Serializer.Serialize(new SpecialRecord { Property = 446 }, TestContext.Current.CancellationToken)); + this.Serializer.Serialize(new SpecialRecord { Property = 446 }, this.TimeoutToken)); // Verify that with a sufficiently low async buffer, the async paths are taken. this.Serializer = new() @@ -93,7 +93,7 @@ public async Task WithPreBuffering() MaxAsyncBuffer = 1, Converters = [converter], }; - await this.Serializer.DeserializeAsync(new FragmentedPipeReader(msgpack), TestContext.Current.CancellationToken); + await this.Serializer.DeserializeAsync(new FragmentedPipeReader(msgpack), this.TimeoutToken); Assert.Equal(1, converter.AsyncDeserializationCounter); // Verify that with a sufficiently high async buffer, the sync paths are taken. @@ -103,31 +103,31 @@ public async Task WithPreBuffering() MaxAsyncBuffer = 15, Converters = [converter], }; - await this.Serializer.DeserializeAsync(new FragmentedPipeReader(msgpack), TestContext.Current.CancellationToken); + await this.Serializer.DeserializeAsync(new FragmentedPipeReader(msgpack), this.TimeoutToken); Assert.Equal(0, converter.AsyncDeserializationCounter); } - [Fact] + [Test] public async Task DecodeLargeString() { string expected = new string('a', 100 * 1024); - ReadOnlySequence msgpack = new(this.Serializer.Serialize(expected, TestContext.Current.CancellationToken)); + ReadOnlySequence msgpack = new(this.Serializer.Serialize(expected, this.TimeoutToken)); FragmentedPipeReader pipeReader = new(msgpack, msgpack.GetPosition(0), msgpack.GetPosition(1), msgpack.GetPosition(512), msgpack.GetPosition(6000), msgpack.GetPosition(32 * 1024)); - string? actual = await this.Serializer.DeserializeAsync(pipeReader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(pipeReader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), this.TimeoutToken); Assert.Equal(expected, actual); } - [Fact] + [Test] public async Task DecodeEmptyString() { string expected = string.Empty; - ReadOnlySequence msgpack = new(this.Serializer.Serialize(expected, TestContext.Current.CancellationToken)); + ReadOnlySequence msgpack = new(this.Serializer.Serialize(expected, this.TimeoutToken)); FragmentedPipeReader pipeReader = new(msgpack, msgpack.GetPosition(0)); - string? actual = await this.Serializer.DeserializeAsync(pipeReader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(pipeReader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), this.TimeoutToken); Assert.Equal(expected, actual); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeAsyncAdvancesPipeReader(bool forceAsync) { this.Serializer = this.Serializer with { MaxAsyncBuffer = forceAsync ? 0 : 1024 }; @@ -140,11 +140,11 @@ public async Task DeserializeAsyncAdvancesPipeReader(bool forceAsync) PipeReader reader = PipeReader.Create(sequence); // Deserialize a value. It should advance the reader exactly across the msgpack structure. - int number = await this.Serializer.DeserializeAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), TestContext.Current.CancellationToken); + int number = await this.Serializer.DeserializeAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), this.TimeoutToken); Assert.Equal(42, number); // Verify that the reader is now positioned at the next byte. - ReadResult readResult = await reader.ReadAsync(TestContext.Current.CancellationToken); + ReadResult readResult = await reader.ReadAsync(this.TimeoutToken); Assert.True(readResult.IsCompleted); Assert.Equal("a"u8, readResult.Buffer.ToArray()); } diff --git a/test/Nerdbank.MessagePack.TUnit/BuiltInConverterTests.cs b/test/Nerdbank.MessagePack.TUnit/BuiltInConverterTests.cs new file mode 100644 index 00000000..3229fd35 --- /dev/null +++ b/test/Nerdbank.MessagePack.TUnit/BuiltInConverterTests.cs @@ -0,0 +1,472 @@ +// Copyright (c) Andrew Arnott. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Drawing; +using System.Globalization; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Text; + +public partial class BuiltInConverterTests : MessagePackSerializerTestBase +{ + private const string BadGuidFormatErrorMessage = "Not a recognized GUID format."; + + [Test] + public void SystemDrawingColor() => this.AssertRoundtrip(Color.FromArgb(1, 2, 3, 4)); + + [Test] + public void SystemDrawingPoint() => this.AssertRoundtrip(new Point(1, 1)); + + [Test] + public void ImmutableDictionary() => this.AssertRoundtrip(new HasImmutableDictionary() { Map = ImmutableDictionary.Empty.Add("a", 1) }); + +#if NET + + [Test] + public void Int128() + { + this.AssertRoundtrip(new HasInt128(0)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasInt128(long.MaxValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasInt128(long.MinValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasInt128(new Int128(1, 2))); + this.AssertType(MessagePackType.Extension); + + this.AssertRoundtrip(new HasInt128(System.Int128.MaxValue)); + this.AssertType(MessagePackType.Extension); + + this.AssertRoundtrip(new HasInt128(System.Int128.MinValue)); + this.AssertType(MessagePackType.Extension); + } + + /// + /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. + /// + /// + /// Note that while our mandates big endian encoding to match msgpack conventions, + /// The Bin encoding used by MessagePack-CSharp uses little-endian encoding. + /// + [Test] + public void Int128_FromBin() + { + Int128 value = new(1, 2); + Sequence seq = new(); + MessagePackWriter writer = new(seq); + writer.WriteMapHeader(1); + writer.Write(nameof(HasInt128.Value)); + writer.WriteBinHeader(128 / 8); + Span byteSpan = writer.GetSpan(128 / 8); + Assert.True(((IBinaryInteger)value).TryWriteLittleEndian(byteSpan, out int written)); + writer.Advance(written); + writer.Flush(); + + Assert.Equal(value, this.Serializer.Deserialize(seq, this.TimeoutToken)!.Value); + } + + [Test] + public void UInt128() + { + this.AssertRoundtrip(new HasUInt128(0)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasInt128(ulong.MaxValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasUInt128(new UInt128(1, 2))); + this.AssertType(MessagePackType.Extension); + + this.AssertRoundtrip(new HasUInt128(System.UInt128.MaxValue)); + this.AssertType(MessagePackType.Extension); + } + + /// + /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. + /// + /// + /// Note that while our mandates big endian encoding to match msgpack conventions, + /// The Bin encoding used by MessagePack-CSharp uses little-endian encoding. + /// + [Test] + public void UInt128_FromBin() + { + UInt128 value = new(1, 2); + Sequence seq = new(); + MessagePackWriter writer = new(seq); + writer.WriteMapHeader(1); + writer.Write(nameof(HasUInt128.Value)); + writer.WriteBinHeader(128 / 8); + Span byteSpan = writer.GetSpan(128 / 8); + Assert.True(((IBinaryInteger)value).TryWriteLittleEndian(byteSpan, out int written)); + writer.Advance(written); + writer.Flush(); + + Assert.Equal(value, this.Serializer.Deserialize(seq, this.TimeoutToken)!.Value); + } + +#endif + +#if NET9_0_OR_GREATER + + [Test] + public void OrderedDictionary() => this.AssertRoundtrip(new HasOrderedDictionary() { Map = { ['a'] = 1, ['b'] = 2, ['c'] = 3 } }); + +#endif + + [Test] + public void Decimal() + { + this.AssertRoundtrip(new HasDecimal(1.2m)); + this.AssertRoundtrip(new HasDecimal(new decimal(ulong.MaxValue) * 1000)); + this.AssertRoundtrip(new HasDecimal(new decimal(ulong.MaxValue) * -1000)); + + // Verify the actual encoding for one of these to lock it in. + MessagePackReader reader = new(this.lastRoundtrippedMsgpack); + Assert.Equal(1, reader.ReadMapHeader()); + reader.Skip(default); // property name + Extension decimalEncoding = reader.ReadExtension(); + Assert.Equal(this.Serializer.LibraryExtensionTypeCodes.Decimal, decimalEncoding.Header.TypeCode); + Assert.Equal("00-00-00-80-E7-03-00-00-18-FC-FF-FF-FF-FF-FF-FF", BitConverter.ToString(decimalEncoding.Data.ToArray())); + } + + /// + /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. + /// + [Test] + public void Decimal_FromBin() + { + Assert.SkipUnless(BitConverter.IsLittleEndian, "This test is written assuming little-endian."); + Span value = [new decimal(ulong.MaxValue) * -1000]; + Sequence seq = new(); + MessagePackWriter writer = new(seq); + writer.WriteMapHeader(1); + writer.Write(nameof(HasDecimal.Value)); + writer.Write(MemoryMarshal.Cast(value)); + writer.Flush(); + + Assert.Equal(value[0], this.Serializer.Deserialize(seq, this.TimeoutToken)!.Value); + } + + /// + /// Verifies that we can read values that use the UTF-8 encoding, which is what MessagePack-CSharp's default formatter uses. + /// + [Test] + public void Decimal_FromString() + { + decimal value = 1.2m; + Sequence seq = new(); + MessagePackWriter writer = new(seq); + writer.WriteMapHeader(1); + writer.Write(nameof(HasDecimal.Value)); + writer.Write(value.ToString(CultureInfo.InvariantCulture)); + writer.Flush(); + + Assert.Equal(value, this.Serializer.Deserialize(seq, this.TimeoutToken)!.Value); + } + + [Test] + public void BigInteger() + { + this.AssertRoundtrip(new HasBigInteger(1)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasBigInteger(ulong.MaxValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasBigInteger(ulong.MinValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasBigInteger(long.MaxValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasBigInteger(long.MinValue)); + this.AssertType(MessagePackType.Integer); + + this.AssertRoundtrip(new HasBigInteger(new BigInteger(ulong.MaxValue) * 3)); + this.AssertType(MessagePackType.Extension); + } + + /// + /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. + /// + [Test] + public void BigInteger_FromBin() + { + BigInteger value = new BigInteger(ulong.MaxValue) * 3; + Sequence seq = new(); + MessagePackWriter writer = new(seq); + writer.WriteMapHeader(1); + writer.Write(nameof(HasBigInteger.Value)); + writer.Write(value.ToByteArray()); // Always in LE order even on BE machines. + writer.Flush(); + + Assert.Equal(value, this.Serializer.Deserialize(seq, this.TimeoutToken)!.Value); + } + + [Test] + public void CultureInfo_Roundtrips() + { + Assert.Equal("fr-FR", this.Roundtrip(CultureInfo.GetCultureInfo("fr-FR"))?.Name); + Assert.Equal("es", this.Roundtrip(CultureInfo.GetCultureInfo("es"))?.Name); + } + + [Test] + public void CultureInfo_Encoding() + { + byte[] msgpack = this.Serializer.Serialize(CultureInfo.GetCultureInfo("es-ES"), this.TimeoutToken); + MessagePackReader reader = new(msgpack); + Assert.Equal("es-ES", reader.ReadString()); + } + + [Test] + public void EventArgs_Roundtrip() + { + Assert.NotNull(this.Roundtrip(new EventArgs())); + } + + [Test] + public void Encoding_Roundtrip() + { + Assert.Equal(Encoding.UTF8.WebName, this.Roundtrip(Encoding.UTF8)?.WebName); + } + + [Test] + public void Encoding_Encoding() + { + byte[] msgpack = this.Serializer.Serialize(Encoding.GetEncoding("utf-8"), this.TimeoutToken); + MessagePackReader reader = new(msgpack); + Assert.Equal("utf-8", reader.ReadString()); + } + + [Test, MatrixDataSource] + public void Guid_ParseAnyStringFormat(OptionalConverters.GuidStringFormat format, bool uppercase) + { + // Serialize the original with the specified format. + // Deserialize with any format besides the one we were expecting. + (Guid before, Guid after) = this.RoundtripModifiedGuid( + s => uppercase ? s.ToUpperInvariant() : s, + this.Serializer.WithGuidConverter(format), + this.Serializer.WithGuidConverter(format == OptionalConverters.GuidStringFormat.StringD ? OptionalConverters.GuidStringFormat.StringN : OptionalConverters.GuidStringFormat.StringD)); + + Assert.Equal(before, after); + } + + [Test, MatrixDataSource] + public void Guid_TruncatedInputs(OptionalConverters.GuidStringFormat format) + { + this.Serializer = this.Serializer.WithGuidConverter(format); + + bool empty = false; + int trimCount = 1; + while (!empty) + { + MessagePackSerializationException ex = Assert.Throws(() => this.RoundtripModifiedGuid(s => + { + empty = s.Length == trimCount; + return s[..^trimCount++]; + })); + Assert.Equal(BadGuidFormatErrorMessage, ex.GetBaseException().Message); + } + } + + [Test, MatrixDataSource] + public void Guid_MissingHexCharacter(OptionalConverters.GuidStringFormat format) + { + this.Serializer = this.Serializer.WithGuidConverter(format); + + // Remove a character that will be a hex character in any format. + MessagePackSerializationException ex = Assert.Throws(() => this.RoundtripModifiedGuid(s => s.Remove(6, 1))); + Console.WriteLine(ex.GetBaseException().Message); + Assert.Equal(BadGuidFormatErrorMessage, ex.GetBaseException().Message); + } + + /// + /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. + /// This tests interoperability with the default binary format. + /// + [Test] + public void Guid_FromBin() + { + Assert.SkipUnless(BitConverter.IsLittleEndian, "This test is written assuming little-endian."); + + Span valueSpan = [System.Guid.NewGuid()]; + Sequence seq = new(); + MessagePackWriter writer = new(seq); + writer.WriteMapHeader(1); + writer.Write(nameof(HasGuid.Value)); + + writer.Write(MemoryMarshal.Cast(valueSpan)); + writer.Flush(); + + Assert.Equal(valueSpan[0], this.Serializer.Deserialize(seq, this.TimeoutToken)!.Value); + } + + [Test] + public void DateTime() => this.AssertRoundtrip(new HasDateTime(System.DateTime.UtcNow)); + + [Test] + public void DateTime_Unspecified() + { + MessagePackSerializationException ex = Assert.Throws(() => + this.Serializer.Serialize(new HasDateTime(new System.DateTime(2000, 1, 1)), this.TimeoutToken)); + ArgumentException inner = Assert.IsType(ex.GetBaseException()); + Console.WriteLine(inner.Message); + } + + [Test] + [Arguments(DateTimeKind.Utc)] + [Arguments(DateTimeKind.Local)] + public void DateTime_Unspecified_UnderConfiguration(DateTimeKind kind) + { + this.Serializer = this.Serializer.WithAssumedDateTimeKind(kind); + DateTime original = new(2000, 1, 1); // Unspecified kind. + HasDateTime? deserialized = this.Roundtrip(new HasDateTime(original)); + + // Deserialized value should always be UTC. + Assert.Equal(System.DateTime.SpecifyKind(original, kind).ToUniversalTime(), deserialized?.Value); + Assert.Equal(DateTimeKind.Utc, deserialized?.Value.Kind); + } + + [Test, MatrixDataSource] + public void DateTime_HiFi(DateTimeKind kind) + { + this.Serializer = this.Serializer.WithHiFiDateTime(); + DateTime original = new(2000, 1, 1, 2, 3, 4, 567, kind); + HasDateTime? deserialized = this.Roundtrip(new HasDateTime(original)); + + // Deserialized value should have retained the Kind. + Assert.Equal(original.Kind, deserialized?.Value.Kind); + + // And in all other ways, be equal. + Assert.Equal(original, deserialized?.Value); + + // Verify the actual encoding for each case. + MessagePackReader reader = new(this.lastRoundtrippedMsgpack); + reader.ReadMapHeader(); + reader.ReadString(); // skip property name + if (kind == DateTimeKind.Utc) + { + // Standard encoding. + Assert.Equal(original, reader.ReadDateTime()); + } + else + { + // HiFi encoding. + Assert.Equal(2, reader.ReadArrayHeader()); + Assert.Equal(original.Ticks, reader.ReadInt64()); + Assert.Equal((int)original.Kind, reader.ReadInt32()); + } + } + + [Test] + public void DateTimeOffset() + { + this.AssertRoundtrip(new HasDateTimeOffset(System.DateTimeOffset.Now)); + + // Try specific offset values because CI/PR builds run on agents that run on the UTC time zone. + this.AssertRoundtrip(new HasDateTimeOffset(System.DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(4)))); + } + + [Test] + public void ByteArrayWithOldSpec() + { + byte[] original = [1, 2, 3]; + Sequence seq = new(); + MessagePackWriter writer = new(seq) { OldSpec = true }; + this.Serializer.Serialize(ref writer, original, this.TimeoutToken); + writer.Flush(); + + // Verify that the test is doing what we think it is. + MessagePackReader reader = new(seq); + Assert.Equal(MessagePackType.String, reader.NextMessagePackType); + + byte[]? deserialized = this.Serializer.Deserialize(seq, this.TimeoutToken); + Assert.Equal(original, deserialized); + } + + [Test] + public void Extension() => this.AssertRoundtrip(new Extension(15, new byte[] { 1, 2, 3 })); + + private (Guid Before, Guid After) RoundtripModifiedGuid(Func modifier, MessagePackSerializer? serializer = null, MessagePackSerializer? deserializer = null) + { + serializer ??= this.Serializer; + deserializer ??= this.Serializer; + + Guid original = System.Guid.NewGuid(); + Console.WriteLine($"Randomly generated guid: {original}"); + byte[] msgpack = serializer.Serialize(original, this.TimeoutToken); + msgpack = this.Serializer.Serialize( + modifier(this.Serializer.Deserialize(msgpack, this.TimeoutToken)!), + this.TimeoutToken); + this.LogMsgPack(msgpack); + Guid deserialized = deserializer.Deserialize(msgpack, this.TimeoutToken); + return (original, deserialized); + } + + private void AssertType(MessagePackType expectedType) + { + MessagePackReader reader = new(this.lastRoundtrippedMsgpack); + reader.ReadMapHeader(); + reader.ReadString(); + Assert.Equal(expectedType, reader.NextMessagePackType); + } + + [GenerateShape] + public partial class HasImmutableDictionary : IEquatable + { + public ImmutableDictionary Map { get; set; } = ImmutableDictionary.Empty; + + public bool Equals(HasImmutableDictionary? other) => StructuralEquality.Equal(this.Map, other?.Map); + } + +#if NET + + [GenerateShape] + public partial record HasInt128(Int128 Value); + + [GenerateShape] + public partial record HasUInt128(UInt128 Value); + +#endif + +#if NET9_0_OR_GREATER + + [GenerateShape] + public partial class HasOrderedDictionary : IEquatable + { + public OrderedDictionary Map { get; set; } = new(); + + public bool Equals(HasOrderedDictionary? other) => StructuralEquality.Equal((IReadOnlyList>)this.Map, other?.Map); + } + +#endif + + [GenerateShape] + public partial record HasDecimal(decimal Value); + + [GenerateShape] + public partial record HasBigInteger(BigInteger Value); + + [GenerateShape] + public partial record HasGuid(Guid Value); + + [GenerateShape] + public partial record HasDateTime(DateTime Value); + + [GenerateShape] + public partial record HasDateTimeOffset(DateTimeOffset Value); + + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + private partial class Witness; +} diff --git a/test/Nerdbank.MessagePack.Tests/ConvertToJsonTests.cs b/test/Nerdbank.MessagePack.TUnit/ConvertToJsonTests.cs similarity index 96% rename from test/Nerdbank.MessagePack.Tests/ConvertToJsonTests.cs rename to test/Nerdbank.MessagePack.TUnit/ConvertToJsonTests.cs index ae5ee294..7008373f 100644 --- a/test/Nerdbank.MessagePack.Tests/ConvertToJsonTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ConvertToJsonTests.cs @@ -6,25 +6,25 @@ public partial class ConvertToJsonTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void Null() => this.AssertConvertToJson("null", null); - [Fact] + [Test] public void Simple() => this.AssertConvertToJson(@"{""Seeds"":3,""Is"":true,""Number"":1.2}", new Primitives(3, true, 1.2)); - [Fact] + [Test] public void Simple2() => this.AssertConvertToJson(@"{""Seeds"":-3,""Is"":true,""Number"":-0.3}", new Primitives(-3, true, -0.3)); - [Fact] + [Test] public void Array() => this.AssertConvertToJson(@"{""IntArray"":[1,2,3]}", new ArrayWrapper(1, 2, 3)); /// /// Verifies the behavior of the simpler method that takes a buffer and returns a string. /// - [Fact] + [Test] public void Sequence() => Assert.Equal("null", this.Serializer.ConvertToJson(new([0xc0]))); - [Fact] + [Test] public void Guid_LittleEndian() { Guid guid = Guid.NewGuid(); @@ -35,7 +35,7 @@ public void Guid_LittleEndian() new GuidWrapper(guid)); } - [Fact] + [Test] public void BigInteger() { BigInteger value = new BigInteger(ulong.MaxValue) * 3; @@ -46,7 +46,7 @@ public void BigInteger() new BigIntegerWrapper(value)); } - [Fact] + [Test] public void Decimal() { decimal value = new decimal(ulong.MaxValue) * 3; @@ -58,7 +58,7 @@ public void Decimal() } #if NET - [Fact] + [Test] public void Int128() { foreach (Int128 value in new[] { System.Int128.MinValue, 0, System.Int128.MaxValue }) @@ -71,7 +71,7 @@ public void Int128() } } - [Fact] + [Test] public void UInt128() { foreach (UInt128 value in new[] { System.UInt128.MinValue, System.UInt128.MaxValue }) @@ -85,7 +85,7 @@ public void UInt128() } #endif - [Fact] + [Test] public void Indented_Object_Tabs() { this.AssertConvertToJson( @@ -100,7 +100,7 @@ public void Indented_Object_Tabs() new() { Indentation = "\t" }); } - [Fact] + [Test] public void Indented_Object_Spaces() { this.AssertConvertToJson( @@ -115,7 +115,7 @@ public void Indented_Object_Spaces() new() { Indentation = " " }); } - [Fact] + [Test] public void Indented_Array() { this.AssertConvertToJson( @@ -132,7 +132,7 @@ public void Indented_Array() new() { Indentation = "\t" }); } - [Fact] + [Test] public void Indented_TrailingCommas_Array() { this.AssertConvertToJson5( @@ -152,7 +152,7 @@ public void Indented_TrailingCommas_Array() /// /// Asserts that trailing commas are not added when we're not using newlines anyway. /// - [Fact] + [Test] public void TrailingCommas_IgnoredWithoutIndentation() { this.AssertConvertToJson( @@ -163,7 +163,7 @@ public void TrailingCommas_IgnoredWithoutIndentation() new() { TrailingCommas = true }); } - [Fact] + [Test] public void Indented_TrailingCommas() { this.AssertConvertToJson5( @@ -178,7 +178,7 @@ public void Indented_TrailingCommas() new() { Indentation = "\t", TrailingCommas = true }); } - [Fact] + [Test] public void Indented_NestingObject() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -209,7 +209,7 @@ private void AssertConvertToJson([StringSyntax("json")] string expected, T? v #endif { string json = this.ConvertToJson(value, options); - this.Logger.WriteLine(json); + Console.WriteLine(json); Assert.Equal(expected, json); } @@ -219,7 +219,7 @@ private void AssertConvertToJson5([StringSyntax("json5")] string expected, T? #endif { string json = this.ConvertToJson(value, options); - this.Logger.WriteLine(json); + Console.WriteLine(json); Assert.Equal(expected, json); } diff --git a/test/Nerdbank.MessagePack.Tests/CustomConverterFactoryTests.cs b/test/Nerdbank.MessagePack.TUnit/CustomConverterFactoryTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/CustomConverterFactoryTests.cs rename to test/Nerdbank.MessagePack.TUnit/CustomConverterFactoryTests.cs index 220eef1c..93289380 100644 --- a/test/Nerdbank.MessagePack.Tests/CustomConverterFactoryTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/CustomConverterFactoryTests.cs @@ -11,7 +11,7 @@ internal partial interface IMarshaledInterface Task DoSomethingAsync(); } - [Fact] + [Test] public void CustomUnionSerializer() { this.Serializer = this.Serializer with { ConverterFactories = [new CustomUnionConverterFactory()] }; @@ -29,7 +29,7 @@ public void CustomUnionSerializer() Assert.True(bAsB.CustomSerialized); } - [Fact] + [Test] public void MarshaledInterfaceSerializer() { this.Serializer = this.Serializer with { ConverterFactories = [new MarshaledObjectConverterFactory()] }; @@ -39,8 +39,8 @@ public void MarshaledInterfaceSerializer() Assert.IsType(proxy); } - [Fact] - [Trait("ReferencePreservation", "true")] + [Test] + [Property("ReferencePreservation", "true")] public void FactoryWithReferencePreservation() { this.Serializer = this.Serializer with @@ -59,7 +59,7 @@ public void FactoryWithReferencePreservation() Assert.True(deserialized[0].CustomSerialized); } - [Fact] + [Test] public void GetSubConverterFromContext() { this.Serializer = this.Serializer with { ConverterFactories = [new DoubleArrayWrapperFactory()] }; diff --git a/test/Nerdbank.MessagePack.Tests/CustomConverterTests.cs b/test/Nerdbank.MessagePack.TUnit/CustomConverterTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/CustomConverterTests.cs rename to test/Nerdbank.MessagePack.TUnit/CustomConverterTests.cs index 7e2bb860..5dd8aeda 100644 --- a/test/Nerdbank.MessagePack.Tests/CustomConverterTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/CustomConverterTests.cs @@ -6,20 +6,20 @@ public partial class CustomConverterTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void ConverterThatDelegates() { this.AssertRoundtrip(new CustomType { InternalProperty = "Hello, World!" }); } - [Fact] + [Test] public void AttributedTypeWorksAfterFirstSerialization() { this.AssertRoundtrip(new Tree(3)); this.AssertRoundtrip(new CustomType { InternalProperty = "Hello, World!" }); } - [Fact] + [Test] public void RegisterWorksAfterFirstSerialization() { this.AssertRoundtrip(new Tree(3)); @@ -33,21 +33,21 @@ public void RegisterWorksAfterFirstSerialization() Assert.Equal(2, treeConverter.InvocationCount); } - [Fact] + [Test] public void UseNonGenericSubConverters_ShapeProvider() { this.Serializer = this.Serializer with { Converters = [new CustomTypeConverterNonGenericTypeShapeProvider()] }; this.AssertRoundtrip(new CustomType { InternalProperty = "Hello, World!" }); } - [Fact] + [Test] public void UseNonGenericSubConverters_Shape() { this.Serializer = this.Serializer with { Converters = [new CustomTypeConverterNonGenericTypeShape()] }; this.AssertRoundtrip(new CustomType { InternalProperty = "Hello, World!" }); } - [Fact] + [Test] public void StatefulConverters() { SerializationContext modifiedStarterContext = this.Serializer.StartingContext; @@ -66,14 +66,14 @@ public void StatefulConverters() Assert.Null(this.Serializer.StartingContext["SHOULDVANISH"]); } - [Fact] + [Test] public void GenericDataAndGenericConverterByOpenGenericAttribute() { GenericData? deserialized = this.Roundtrip, Witness>(new GenericData { Value = "Hello, World!" }); Assert.Equal("Hello, World!11", deserialized?.Value); } - [Fact] + [Test] public void GenericDataAndGenericConverterByClosedGenericRuntimeRegistration() { this.Serializer = this.Serializer with { Converters = [new GenericDataConverter2()] }; @@ -81,7 +81,7 @@ public void GenericDataAndGenericConverterByClosedGenericRuntimeRegistration() Assert.Equal("Hello, World!22", deserialized?.Value); } - [Fact] + [Test] public void GenericDataAndGenericConverterByOpenGenericRuntimeRegistration() { this.Serializer = this.Serializer with { ConverterTypes = [typeof(GenericDataConverter2<>)] }; @@ -89,7 +89,7 @@ public void GenericDataAndGenericConverterByOpenGenericRuntimeRegistration() Assert.Equal("Hello, World!22", deserialized?.Value); } - [Fact] + [Test] public void GenericDataAndNonGenericConverterByRuntimeRegistration() { this.Serializer = this.Serializer with { ConverterTypes = [typeof(GenericDataConverterNonGeneric)] }; @@ -101,7 +101,7 @@ public void GenericDataAndNonGenericConverterByRuntimeRegistration() Assert.Equal("Hello, World!11", deserialized2?.Value); } - [Fact] + [Test] public void NonGenericRuntimeRegistrationOfConverterByType() { this.Serializer = this.Serializer with { ConverterTypes = [typeof(TreeConverterPlus2)] }; @@ -109,15 +109,15 @@ public void NonGenericRuntimeRegistrationOfConverterByType() Assert.Equal(5, deserialized?.FruitCount); } - [Fact] + [Test] public void GenericDataAndGenericConverterByOpenGenericRuntimeRegistration_NotAssociated() { this.Serializer = this.Serializer with { ConverterTypes = [typeof(GenericDataConverter3<>)] }; - MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Serialize, Witness>(new GenericData { Value = "Hello, World!" }, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.Message); + MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Serialize, Witness>(new GenericData { Value = "Hello, World!" }, this.TimeoutToken)); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void ConverterWithConverterContextConstructor() { this.Serializer = this.Serializer with { ConverterTypes = [typeof(TreeConverterWithConverterContext)] }; diff --git a/test/Nerdbank.MessagePack.Tests/CustomEnumerableTypes.cs b/test/Nerdbank.MessagePack.TUnit/CustomEnumerableTypes.cs similarity index 99% rename from test/Nerdbank.MessagePack.Tests/CustomEnumerableTypes.cs rename to test/Nerdbank.MessagePack.TUnit/CustomEnumerableTypes.cs index 00dfb94d..a2a3b801 100644 --- a/test/Nerdbank.MessagePack.Tests/CustomEnumerableTypes.cs +++ b/test/Nerdbank.MessagePack.TUnit/CustomEnumerableTypes.cs @@ -3,7 +3,7 @@ public partial class CustomEnumerableTypes : MessagePackSerializerTestBase { - [Fact] + [Test] public void CustomListOfIntDerivedCollection() { ListOfInt list = new() { 1, 2, 3 }; diff --git a/test/Nerdbank.MessagePack.Tests/DerivedTypeDuckTypingTests.cs b/test/Nerdbank.MessagePack.TUnit/DerivedTypeDuckTypingTests.cs similarity index 88% rename from test/Nerdbank.MessagePack.Tests/DerivedTypeDuckTypingTests.cs rename to test/Nerdbank.MessagePack.TUnit/DerivedTypeDuckTypingTests.cs index 25019430..79053a01 100644 --- a/test/Nerdbank.MessagePack.Tests/DerivedTypeDuckTypingTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/DerivedTypeDuckTypingTests.cs @@ -9,16 +9,24 @@ public DerivedTypeDuckTypingTests() { this.Serializer = this.Serializer with { +#if NET + DerivedTypeUnions = [ + new DerivedTypeDuckTyping( + TypeShapeResolver.Resolve(), + TypeShapeResolver.Resolve(), + TypeShapeResolver.Resolve()), +#else DerivedTypeUnions = [ new DerivedTypeDuckTyping( TypeShapeResolver.ResolveDynamicOrThrow(), TypeShapeResolver.ResolveDynamicOrThrow(), TypeShapeResolver.ResolveDynamicOrThrow()), +#endif ], }; } - [Fact] + [Test] public void RequiredPropertyDistinction_Roundtrip() { this.AssertRoundtrip(new Dog("Buddy", 5)); diff --git a/test/Nerdbank.MessagePack.Tests/DerivedTypeMappingTests.cs b/test/Nerdbank.MessagePack.TUnit/DerivedTypeMappingTests.cs similarity index 94% rename from test/Nerdbank.MessagePack.Tests/DerivedTypeMappingTests.cs rename to test/Nerdbank.MessagePack.TUnit/DerivedTypeMappingTests.cs index b35642b4..d1d45641 100644 --- a/test/Nerdbank.MessagePack.Tests/DerivedTypeMappingTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/DerivedTypeMappingTests.cs @@ -1,9 +1,9 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -public partial class DerivedTypeMappingTests(ITestOutputHelper logger) +public partial class DerivedTypeMappingTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void NonUniqueAliasesRejected_Integers() { DerivedShapeMapping mapping = new(); @@ -14,10 +14,10 @@ public void NonUniqueAliasesRejected_Integers() mapping.Add(1, Witness.GeneratedTypeShapeProvider); ArgumentException ex = Assert.Throws(() => mapping.Add(1, Witness.GeneratedTypeShapeProvider)); #endif - logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void NonUniqueAliasesRejected_Strings() { DerivedShapeMapping mapping = new(); @@ -28,10 +28,10 @@ public void NonUniqueAliasesRejected_Strings() mapping.Add("A", Witness.GeneratedTypeShapeProvider); ArgumentException ex = Assert.Throws(() => mapping.Add("A", Witness.GeneratedTypeShapeProvider)); #endif - logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void NonUniqueTypesRejected_Integers() { DerivedShapeMapping mapping = new(); @@ -42,10 +42,10 @@ public void NonUniqueTypesRejected_Integers() mapping.Add(1, Witness.GeneratedTypeShapeProvider); ArgumentException ex = Assert.Throws(() => mapping.Add(2, Witness.GeneratedTypeShapeProvider)); #endif - logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void NonUniqueTypesRejected_Strings() { DerivedShapeMapping mapping = new(); @@ -56,10 +56,10 @@ public void NonUniqueTypesRejected_Strings() mapping.Add("A", Witness.GeneratedTypeShapeProvider); ArgumentException ex = Assert.Throws(() => mapping.Add(2, Witness.GeneratedTypeShapeProvider)); #endif - logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void NonUniquePairsRejected_Integers() { DerivedShapeMapping mapping = new(); @@ -70,10 +70,10 @@ public void NonUniquePairsRejected_Integers() mapping.Add(1, Witness.GeneratedTypeShapeProvider); ArgumentException ex = Assert.Throws(() => mapping.Add(1, Witness.GeneratedTypeShapeProvider)); #endif - logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void NonUniquePairsRejected_Strings() { DerivedShapeMapping mapping = new(); @@ -84,10 +84,10 @@ public void NonUniquePairsRejected_Strings() mapping.Add("A", Witness.GeneratedTypeShapeProvider); ArgumentException ex = Assert.Throws(() => mapping.Add("A", Witness.GeneratedTypeShapeProvider)); #endif - logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void ObjectInitializerSyntax() { DerivedTypeMapping mapping = new(Witness.GeneratedTypeShapeProvider) @@ -100,7 +100,7 @@ public void ObjectInitializerSyntax() Assert.Equal(typeof(MyDerivedB), mapping["B"]); } - [Fact] + [Test] public void DictionaryInitializerSyntax() { DerivedTypeMapping mapping = new(Witness.GeneratedTypeShapeProvider) @@ -113,7 +113,7 @@ public void DictionaryInitializerSyntax() Assert.Equal(typeof(MyDerivedB), mapping["B"]); } - [Fact] + [Test] public void ObjectInitializerSyntax_NonUniqueTypes() { Assert.Throws(() => @@ -126,7 +126,7 @@ public void ObjectInitializerSyntax_NonUniqueTypes() }); } - [Fact] + [Test] public void ObjectInitializerSyntax_NonUniqueAlias() { Assert.Throws(() => @@ -139,7 +139,7 @@ public void ObjectInitializerSyntax_NonUniqueAlias() }); } - [Fact] + [Test] public void DictionaryInitializerSyntax_NonUniqueTypes() { Assert.Throws(() => @@ -152,7 +152,7 @@ public void DictionaryInitializerSyntax_NonUniqueTypes() }); } - [Fact] + [Test] public void DictionaryInitializerSyntax_AddTypeAgainAfterImplicitRemoval() { DerivedTypeMapping mapping = new(Witness.GeneratedTypeShapeProvider) @@ -166,7 +166,7 @@ public void DictionaryInitializerSyntax_AddTypeAgainAfterImplicitRemoval() Assert.Equal(typeof(MyDerivedA), mapping["A"]); } - [Fact] + [Test] public void DerivedShapeMapping_DisabledTests() { var union = DerivedTypeUnion.CreateDisabled(typeof(MyBase)); @@ -174,7 +174,7 @@ public void DerivedShapeMapping_DisabledTests() Assert.Same(typeof(MyBase), union.BaseType); } - [Fact] + [Test] [SuppressMessage("Assertions", "xUnit2013:Do not use equality check to check for collection size.", Justification = "The whole point of this test is to ensure that the Count property matches what the enumerator would produce.")] public void EnumerateMappings() { @@ -187,7 +187,7 @@ public void EnumerateMappings() Assert.Equal(serializer.DerivedTypeUnions.Count, serializer.DerivedTypeUnions.Count()); } - [Fact] + [Test] public void ShapeMappingFrozenAfterAdding() { DerivedShapeMapping mapping = new(); @@ -209,7 +209,7 @@ public void ShapeMappingFrozenAfterAdding() #endif } - [Fact] + [Test] public void TypeMappingFrozenAfterAdding() { DerivedTypeMapping mapping = new(Witness.GeneratedTypeShapeProvider) diff --git a/test/Nerdbank.MessagePack.Tests/DerivedTypeTests.cs b/test/Nerdbank.MessagePack.TUnit/DerivedTypeTests.cs similarity index 96% rename from test/Nerdbank.MessagePack.Tests/DerivedTypeTests.cs rename to test/Nerdbank.MessagePack.TUnit/DerivedTypeTests.cs index 14af0e31..67e17cb2 100644 --- a/test/Nerdbank.MessagePack.Tests/DerivedTypeTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/DerivedTypeTests.cs @@ -3,7 +3,7 @@ public partial class DerivedTypeTests : MessagePackSerializerTestBase { - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task BaseType(bool async) { BaseClass value = new() { BaseClassProperty = 5 }; @@ -17,7 +17,7 @@ public async Task BaseType(bool async) Assert.Equal(nameof(BaseClass.BaseClassProperty), reader.ReadString()); } - [Fact] + [Test] public void BaseTypeExplicitIdentifier() { BaseTypeExplicitBase? result = this.Roundtrip(new BaseTypeExplicitBase()); @@ -34,7 +34,7 @@ public void BaseTypeExplicitIdentifier() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void BaseTypeExplicitIdentifier_RuntimeMapping() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -52,7 +52,7 @@ public void BaseTypeExplicitIdentifier_RuntimeMapping() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void DerivedAType() { ReadOnlySequence msgpack = this.AssertRoundtrip(new DerivedA { BaseClassProperty = 5, DerivedAProperty = 6 }); @@ -67,7 +67,7 @@ public void DerivedAType() Assert.True(reader.End); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DerivedA_AsBaseType(bool async) { var value = new DerivedA { BaseClassProperty = 5, DerivedAProperty = 6 }; @@ -81,26 +81,26 @@ public async Task DerivedA_AsBaseType(bool async) } } - [Fact] + [Test] public void DerivedAA_AsBaseType() => this.AssertRoundtrip(new DerivedAA { BaseClassProperty = 5, DerivedAProperty = 6 }); - [Fact] + [Test] public void DerivedB_AsBaseType() => this.AssertRoundtrip(new DerivedB(10) { BaseClassProperty = 5 }); - [Fact] + [Test] public void EnumerableDerived_BaseType() { // This is a lossy operation. Only the collection elements are serialized, // and the class cannot be deserialized because the constructor doesn't take a collection. EnumerableDerived value = new(3) { BaseClassProperty = 5 }; - byte[] msgpack = this.Serializer.Serialize(value, TestContext.Current.CancellationToken); - this.Logger.WriteLine(this.Serializer.ConvertToJson(msgpack)); + byte[] msgpack = this.Serializer.Serialize(value, this.TimeoutToken); + Console.WriteLine(this.Serializer.ConvertToJson(msgpack)); } - [Fact] + [Test] public void ClosedGenericDerived_BaseType() => this.AssertRoundtrip(new DerivedGeneric(5) { BaseClassProperty = 10 }); - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Null(bool async) { if (async) @@ -113,7 +113,7 @@ public async Task Null(bool async) } } - [Fact] + [Test] public void UnrecognizedAlias() { Sequence sequence = new(); @@ -123,11 +123,11 @@ public void UnrecognizedAlias() writer.WriteMapHeader(0); writer.Flush(); - MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.Message); + MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Deserialize(sequence, this.TimeoutToken)); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void UnrecognizedArraySize() { Sequence sequence = new(); @@ -138,18 +138,18 @@ public void UnrecognizedArraySize() writer.WriteNil(); writer.Flush(); - MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.Message); + MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Deserialize(sequence, this.TimeoutToken)); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void UnknownDerivedType() { BaseClass? result = this.Roundtrip(new UnknownDerived()); Assert.IsType(result); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public void UnknownDerivedType_PrefersClosestMatch(bool runtimeMapping) { if (runtimeMapping) @@ -165,7 +165,7 @@ public void UnknownDerivedType_PrefersClosestMatch(bool runtimeMapping) Assert.IsType(this.Roundtrip(new DerivedAAUnknown())); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MixedAliasTypes(bool async) { MixedAliasBase value = new MixedAliasDerivedA(); @@ -181,7 +181,7 @@ public async Task MixedAliasTypes(bool async) Assert.Equal(10, reader.ReadInt32()); } - [Fact] + [Test] public void ImpliedAlias() { ReadOnlySequence msgpack = this.AssertRoundtrip(new ImpliedAliasDerived()); @@ -190,7 +190,7 @@ public void ImpliedAlias() Assert.Equal(typeof(ImpliedAliasDerived).Name, reader.ReadString()); } - [Fact] + [Test] public void RecursiveSubTypes() { // If it were to work, this is how we expect it to work: @@ -202,7 +202,7 @@ public void RecursiveSubTypes() Assert.Equal(13, reader.ReadInt32()); } - [Fact] + [Test] public void RuntimeRegistration_Integers() { DerivedShapeMapping mapping = new(); @@ -220,7 +220,7 @@ public void RuntimeRegistration_Integers() this.AssertRoundtrip(new DynamicallyRegisteredDerivedB()); } - [Fact] + [Test] public void RuntimeRegistration_Strings() { DerivedShapeMapping mapping = new(); @@ -238,7 +238,7 @@ public void RuntimeRegistration_Strings() this.AssertRoundtrip(new DynamicallyRegisteredDerivedB()); } - [Fact] + [Test] public void RuntimeRegistration_OverridesStatic() { DerivedShapeMapping mapping = new(); @@ -265,7 +265,7 @@ public void RuntimeRegistration_OverridesStatic() /// /// Verify that an empty mapping is allowed and produces the schema that allows for sub-types to be added in the future. /// - [Fact] + [Test] public void RuntimeRegistration_EmptyMapping() { DerivedShapeMapping mapping = new(); @@ -277,7 +277,7 @@ public void RuntimeRegistration_EmptyMapping() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void CustomConverter_InvokedAsUnionCase_WhenSetAsRuntimeConverter() { this.Serializer = this.Serializer with { Converters = [new BaseClassCustomConverter()] }; @@ -289,7 +289,7 @@ public void CustomConverter_InvokedAsUnionCase_WhenSetAsRuntimeConverter() this.AssertRoundtrip(new BaseTypeWithCustomConverterAttributeDerived { BaseClassProperty = 8, DerivedAProperty = 10 }); } - [Fact] + [Test] public void CustomConverter_InvokedAsUnionCase_WhenSetViaConverterAttribute() { this.AssertRoundtrip(new() { BaseClassProperty = 5 }); @@ -299,7 +299,7 @@ public void CustomConverter_InvokedAsUnionCase_WhenSetViaConverterAttribute() this.AssertRoundtrip(new BaseTypeWithCustomConverterAttributeDerived { BaseClassProperty = 8, DerivedAProperty = 10 }); } - [Fact] + [Test] public void CustomConverter_InvokedAsUnionCase_WhenSetViaConverterAttributeOnMember() { this.AssertRoundtrip(new() { Value = new BaseClass { BaseClassProperty = 5 } }); @@ -312,7 +312,7 @@ public void CustomConverter_InvokedAsUnionCase_WhenSetViaConverterAttributeOnMem Assert.Equal(new HasUnionMemberWithMemberAttribute { Value = new BaseClass { BaseClassProperty = 8 } }, deserialized); } - [Fact] + [Test] public void DisableAttributeUnionAtRuntime() { this.Serializer = this.Serializer with diff --git a/test/Nerdbank.MessagePack.Tests/DeserializeDefaultValueTests.cs b/test/Nerdbank.MessagePack.TUnit/DeserializeDefaultValueTests.cs similarity index 91% rename from test/Nerdbank.MessagePack.Tests/DeserializeDefaultValueTests.cs rename to test/Nerdbank.MessagePack.TUnit/DeserializeDefaultValueTests.cs index dc2c532d..316d5ebb 100644 --- a/test/Nerdbank.MessagePack.Tests/DeserializeDefaultValueTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/DeserializeDefaultValueTests.cs @@ -7,19 +7,19 @@ public partial class DeserializeDefaultValueTests : MessagePackSerializerTestBas private static readonly ReadOnlySequence EmptyMsgPackMap = CreateEmptyMap(); private static readonly ReadOnlySequence EmptyMsgPackArray = CreateEmptyArray(); - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task NullValueRejectedForNonNullableRequiredProperty(bool async) { await this.ExpectDeserializationThrowsAsync(NullMessageMsgPackMap, async, MessagePackSerializationException.ErrorCode.DisallowedNullValue); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task NullValueRejectedForNonNullableOptionalProperty(bool async) { await this.ExpectDeserializationThrowsAsync(NullMessageMsgPackMap, async, MessagePackSerializationException.ErrorCode.DisallowedNullValue); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task NullValueAllowedForNonNullableOptionalProperty_WithFlag(bool async) { this.Serializer = this.Serializer with { DeserializeDefaultValues = DeserializeDefaultValuesPolicy.AllowNullValuesForNonNullableProperties }; @@ -28,7 +28,7 @@ public async Task NullValueAllowedForNonNullableOptionalProperty_WithFlag(bool a Assert.Null(deserialized.Message); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task NullValueAllowedForNonNullableRequiredProperty_WithFlag(bool async) { this.Serializer = this.Serializer with { DeserializeDefaultValues = DeserializeDefaultValuesPolicy.AllowNullValuesForNonNullableProperties }; @@ -37,25 +37,25 @@ public async Task NullValueAllowedForNonNullableRequiredProperty_WithFlag(bool a Assert.Null(deserialized.Message); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task RejectMissingValueForNonNullableRequiredProperty(bool async) { await this.ExpectDeserializationThrowsAsync(EmptyMsgPackMap, async, MessagePackSerializationException.ErrorCode.MissingRequiredProperty); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task RejectMissingValueForNonNullableRequiredProperty_KeyedMap(bool async) { await this.ExpectDeserializationThrowsAsync(EmptyMsgPackMap, async, MessagePackSerializationException.ErrorCode.MissingRequiredProperty); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task RejectMissingValueForNonNullableRequiredProperty_KeyedArray(bool async) { await this.ExpectDeserializationThrowsAsync(EmptyMsgPackArray, async, MessagePackSerializationException.ErrorCode.MissingRequiredProperty); } - [Fact] + [Test] public async Task RejectMissingValueForRequiredPropertyFromVeryLargeType() { Sequence seq = new(); @@ -73,7 +73,7 @@ public async Task RejectMissingValueForRequiredPropertyFromVeryLargeType() Assert.Contains("P64, P65, P66", ex.Message); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MissingValueAllowedForNonNullableOptionalProperty(bool async) { OptionalNonNullProperty? deserialized = await this.DeserializeMaybeAsync(EmptyMsgPackMap, async); @@ -81,7 +81,7 @@ public async Task MissingValueAllowedForNonNullableOptionalProperty(bool async) Assert.Equal(string.Empty, deserialized.Message); // When omitted, the default value is the empty string for this particular property. } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MissingValueAllowedForNonNullableRequiredProperty_WithFlag(bool async) { this.Serializer = this.Serializer with { DeserializeDefaultValues = DeserializeDefaultValuesPolicy.AllowMissingValuesForRequiredProperties }; @@ -125,8 +125,8 @@ private static ReadOnlySequence CreateEmptyArray() #endif { return async - ? await this.Serializer.DeserializeAsync(new MemoryStream(msgpack.ToArray()), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(new MemoryStream(msgpack.ToArray()), this.TimeoutToken) + : this.Serializer.Deserialize(msgpack, this.TimeoutToken); } private async ValueTask ExpectDeserializationThrowsAsync(ReadOnlySequence msgpack, bool async, MessagePackSerializationException.ErrorCode expectedCause) @@ -135,9 +135,9 @@ private async ValueTask ExpectDeserialization #endif { MessagePackSerializationException ex = async - ? await Assert.ThrowsAsync(() => this.Serializer.DeserializeAsync(new MemoryStream(msgpack.ToArray()), TestContext.Current.CancellationToken).AsTask()) - : Assert.Throws(() => this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.GetBaseException().Message); + ? await Assert.ThrowsAsync(() => this.Serializer.DeserializeAsync(new MemoryStream(msgpack.ToArray()), this.TimeoutToken).AsTask()) + : Assert.Throws(() => this.Serializer.Deserialize(msgpack, this.TimeoutToken)); + Console.WriteLine(ex.GetBaseException().Message); MessagePackSerializationException rootCauseException = Assert.IsType(ex.GetBaseException()); Assert.Equal(expectedCause, rootCauseException.Code); diff --git a/test/Nerdbank.MessagePack.Tests/DeserializePathTests.cs b/test/Nerdbank.MessagePack.TUnit/DeserializePathTests.cs similarity index 78% rename from test/Nerdbank.MessagePack.Tests/DeserializePathTests.cs rename to test/Nerdbank.MessagePack.TUnit/DeserializePathTests.cs index 041581a0..086ae09b 100644 --- a/test/Nerdbank.MessagePack.Tests/DeserializePathTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/DeserializePathTests.cs @@ -11,110 +11,110 @@ public enum TestEnum } // Test deserializing the root object. - [Fact] + [Test] public void RootObject() { OuterContainer container = new(new(5)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c); - OuterContainer? result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + OuterContainer? result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.NotNull(result); Assert.Equal(5, result.Inner?.Value); } - [Fact] + [Test] public void OneStepObject() { OuterContainer container = new(new(5)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!); - InnerValue? result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + InnerValue? result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.NotNull(result); Assert.Equal(5, result.Value); } // Test deserializing a primitive at the end of a non-empty path. - [Fact] + [Test] public void NestedPrimitive() { OuterContainer container = new(new(42)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value); - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(42, result); } // Test deserializing an object at the end of a non-empty path. - [Fact] + [Test] public void NestedObject() { ThreeLevelContainer container = new(new(new(99))); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Middle!.Inner!); - InnerValue? result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + InnerValue? result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.NotNull(result); Assert.Equal(99, result.Value); } // Test deserializing a collection at the end of a non-empty path. - [Fact] + [Test] public void Collection() { ContainerWithCollection container = new([1, 2, 3]); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values!); - int[]? result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int[]? result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal([1, 2, 3], result!); } // Test deserializing an enum at the end of a non-empty path. - [Fact] + [Test] public void Enum() { ContainerWithEnum container = new(TestEnum.Value2); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Status); - TestEnum result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + TestEnum result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(TestEnum.Value2, result); } // Test deserializing a null value. - [Fact] + [Test] public void NullValue() { OuterContainer container = new(null); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); - InnerValue? result = this.Serializer.DeserializePath(msgpack, new(c => c.Inner), TestContext.Current.CancellationToken); + InnerValue? result = this.Serializer.DeserializePath(msgpack, new(c => c.Inner), this.TimeoutToken); Assert.Null(result); } // Test throwing when the path is not found. - [Theory, PairwiseData] + [Test, MatrixDataSource] public void MemberPathNotFound_Throws(bool nullRoot) { OuterContainer? container = nullRoot ? null : new(null); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value) @@ -123,9 +123,9 @@ public void MemberPathNotFound_Throws(bool nullRoot) }; MessagePackSerializationException ex = Assert.Throws(() => - this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken)); + this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken)); - this.Logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); if (nullRoot) { Assert.Matches(@"\Wc(?!\.Inner)", ex.Message); @@ -137,11 +137,11 @@ public void MemberPathNotFound_Throws(bool nullRoot) } // Test getting default value when the path is not found. - [Theory, PairwiseData] + [Test, MatrixDataSource] public void MemberPathNotFound_ReturnsDefault(bool nullRoot) { OuterContainer? container = nullRoot ? null : new OuterContainer(null); - byte[] msgpack = this.Serializer.Serialize(container as OuterContainer, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container as OuterContainer, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value) @@ -149,16 +149,16 @@ public void MemberPathNotFound_ReturnsDefault(bool nullRoot) DefaultForUndiscoverablePath = true, }; - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(0, result); } // Test throwing when the path is not found. - [Fact] + [Test] public void IndexPathNotFound_Throws() { - byte[] msgpack = this.Serializer.Serialize(new ContainerWithCollection(null), TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(new ContainerWithCollection(null), this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values![2]) @@ -167,17 +167,17 @@ public void IndexPathNotFound_Throws() }; MessagePackSerializationException ex = Assert.Throws(() => - this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken)); + this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken)); - this.Logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); Assert.Matches(@"\Wc\.Values(?!\[)", ex.Message); } // Test getting default value when the path is not found. - [Fact] + [Test] public void IndexPathNotFound_ReturnsDefault() { - byte[] msgpack = this.Serializer.Serialize(new ContainerWithCollection(null), TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(new ContainerWithCollection(null), this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values![2]) @@ -185,176 +185,176 @@ public void IndexPathNotFound_ReturnsDefault() DefaultForUndiscoverablePath = true, }; - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(0, result); } // Test step through array indexer - [Fact] + [Test] public void ThroughArray() { ContainerByArray container = new([null, new(10), new(20)]); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values[1]!.Value); - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(10, result); } // Test step through dictionary - [Fact] + [Test] public void ThroughDictionary() { ContainerByDictionary container = new(new() { ["a"] = null, ["b"] = new(15) }); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values["b"]!.Value); - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(15, result); } // Test step through dictionary with custom key - [Fact] + [Test] public void ThroughDictionaryCustomKey() { ContainerByDictionaryCustomKey container = new(new() { [new CustomKey(5)] = null, [new CustomKey(3)] = new(25) }); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); CustomKey key = new(3); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values[key]!.Value); - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(25, result); } // Test step through ImmutableArray indexer - [Fact] + [Test] public void ThroughImmutableArray() { ContainerByImmutableArray container = new([null, new(30), new(40)]); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Values[2]!.Value); - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(40, result); } // Test with keyed properties (array format) - [Fact] + [Test] public void KeyedProperties() { KeyedContainer container = new() { Before = "a", Value = new(50), After = "b" }; - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Value!.Value); - int result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(50, result); } // Test overloads with ReadOnlyMemory - [Fact] + [Test] public void ReadOnlyMemory_Overload() { OuterContainer container = new(new(7)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value); - int result = this.Serializer.DeserializePath(msgpack.AsMemory(), options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(msgpack.AsMemory(), options, this.TimeoutToken); Assert.Equal(7, result); } // Test overloads with ReadOnlySequence - [Fact] + [Test] public void ReadOnlySequence_Overload() { OuterContainer container = new(new(8)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); ReadOnlySequence sequence = new(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value); - int result = this.Serializer.DeserializePath(sequence, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(sequence, options, this.TimeoutToken); Assert.Equal(8, result); } // Test overloads with Stream - [Fact] + [Test] public void Stream_Overload() { OuterContainer container = new(new(9)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); using MemoryStream stream = new(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value); - int result = this.Serializer.DeserializePath(stream, options, TestContext.Current.CancellationToken); + int result = this.Serializer.DeserializePath(stream, options, this.TimeoutToken); Assert.Equal(9, result); } // Test with reference preservation disabled - [Trait("ReferencePreservation", "true")] - [Fact] + [Property("ReferencePreservation", "true")] + [Test] public void ReferencesPreserved_NotSupported() { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.RejectCycles }; OuterContainer container = new(new(12)); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); MessagePackSerializer.DeserializePathOptions options = new(c => c.Inner!.Value); NotSupportedException ex = Assert.Throws(() => - this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.Message); + this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken)); + Console.WriteLine(ex.Message); } // Test with complex path through multiple levels - [Fact] + [Test] public void ComplexPath() { ComplexContainer container = new(new(new() { ["key1"] = [1, 2, 3], ["key2"] = [4, 5, 6] })); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Outer!.Values["key2"]![1]); - short result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + short result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(5, result); } // Test deserializing string value - [Fact] + [Test] public void StringValue() { ContainerWithString container = new("hello world"); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Text!); - string? result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + string? result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal("hello world", result); } // Test deserializing struct value type - [Fact] + [Test] public void StructValue() { ContainerWithStruct container = new(new StructRecord(100, "test")); - byte[] msgpack = this.Serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(container, this.TimeoutToken); this.LogMsgPack(msgpack); MessagePackSerializer.DeserializePathOptions options = new(c => c.Data); - StructRecord result = this.Serializer.DeserializePath(msgpack, options, TestContext.Current.CancellationToken); + StructRecord result = this.Serializer.DeserializePath(msgpack, options, this.TimeoutToken); Assert.Equal(100, result.Id); Assert.Equal("test", result.Name); diff --git a/test/Nerdbank.MessagePack.Tests/DoubleAssignmentTests.cs b/test/Nerdbank.MessagePack.TUnit/DoubleAssignmentTests.cs similarity index 92% rename from test/Nerdbank.MessagePack.Tests/DoubleAssignmentTests.cs rename to test/Nerdbank.MessagePack.TUnit/DoubleAssignmentTests.cs index 92ab7dd0..8fb9f67c 100644 --- a/test/Nerdbank.MessagePack.Tests/DoubleAssignmentTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/DoubleAssignmentTests.cs @@ -3,7 +3,7 @@ public partial class DoubleAssignmentTests : MessagePackSerializerTestBase { - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MapNoArgState_Collision(bool async) { Sequence seq = new(); @@ -20,7 +20,7 @@ public async Task MapNoArgState_Collision(bool async) await this.ExpectDeserializationThrowsAsync(seq, async); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MapWithArgState_Collision(bool async) { Sequence seq = new(); @@ -37,7 +37,7 @@ public async Task MapWithArgState_Collision(bool async) await this.ExpectDeserializationThrowsAsync(seq, async); } - [Fact] + [Test] public async Task VeryLargeType_Collision() { Sequence seq = new(); @@ -55,7 +55,7 @@ public async Task VeryLargeType_Collision() Assert.Contains("P2", ex.Message); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task ArrayNoArgState_Collision(bool async) { Sequence seq = new(); @@ -75,7 +75,7 @@ public async Task ArrayNoArgState_Collision(bool async) await this.ExpectDeserializationThrowsAsync(seq, async); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task ArrayWithArgState_Collision(bool async) { Sequence seq = new(); @@ -101,9 +101,9 @@ private async ValueTask ExpectDeserialization #endif { MessagePackSerializationException ex = async - ? await Assert.ThrowsAsync(() => this.Serializer.DeserializeAsync(new MemoryStream(msgpack.ToArray()), TestContext.Current.CancellationToken).AsTask()) - : Assert.Throws(() => this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.GetBaseException().Message); + ? await Assert.ThrowsAsync(() => this.Serializer.DeserializeAsync(new MemoryStream(msgpack.ToArray()), this.TimeoutToken).AsTask()) + : Assert.Throws(() => this.Serializer.Deserialize(msgpack, this.TimeoutToken)); + Console.WriteLine(ex.GetBaseException().Message); MessagePackSerializationException rootCauseException = Assert.IsType(ex.GetBaseException()); Assert.Equal(MessagePackSerializationException.ErrorCode.DoublePropertyAssignment, rootCauseException.Code); return rootCauseException; diff --git a/test/Nerdbank.MessagePack.Tests/ExtensionTests.cs b/test/Nerdbank.MessagePack.TUnit/ExtensionTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/ExtensionTests.cs rename to test/Nerdbank.MessagePack.TUnit/ExtensionTests.cs index 28958f88..a5b0f7ce 100644 --- a/test/Nerdbank.MessagePack.Tests/ExtensionTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ExtensionTests.cs @@ -8,7 +8,7 @@ public class ExtensionTests private Extension ext2 = new(2, new byte[] { 1, 2, 3, 4, 5 }); private Extension ext3 = new(1, new byte[] { 1, 2, 4, 5 }); - [Fact] + [Test] public void Equality() { Assert.Equal(this.ext1a, this.ext1b); @@ -16,7 +16,7 @@ public void Equality() Assert.NotEqual(this.ext1a, this.ext3); } - [Fact] + [Test] public void GetHashCode_Overridden() { Assert.Equal(this.ext1a.GetHashCode(), this.ext1b.GetHashCode()); @@ -24,7 +24,7 @@ public void GetHashCode_Overridden() Assert.NotEqual(this.ext1a.GetHashCode(), this.ext3.GetHashCode()); } - [Fact] + [Test] public void GetSecureHashCode_StructuralEquality() { // The secure hash code should be the same for two structurally equal extensions. diff --git a/test/Nerdbank.MessagePack.Tests/FragmentedPipeReader.cs b/test/Nerdbank.MessagePack.TUnit/FragmentedPipeReader.cs similarity index 100% rename from test/Nerdbank.MessagePack.Tests/FragmentedPipeReader.cs rename to test/Nerdbank.MessagePack.TUnit/FragmentedPipeReader.cs diff --git a/test/Nerdbank.MessagePack.Tests/IgnoreKeyAttributesTests.cs b/test/Nerdbank.MessagePack.TUnit/IgnoreKeyAttributesTests.cs similarity index 97% rename from test/Nerdbank.MessagePack.Tests/IgnoreKeyAttributesTests.cs rename to test/Nerdbank.MessagePack.TUnit/IgnoreKeyAttributesTests.cs index fc57e5f5..8d0dec58 100644 --- a/test/Nerdbank.MessagePack.Tests/IgnoreKeyAttributesTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/IgnoreKeyAttributesTests.cs @@ -1,10 +1,10 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -[Trait("IgnoreKeyAttributes", "true")] +[Property("IgnoreKeyAttributes", "true")] public partial class IgnoreKeyAttributesTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void ObjectWithKeyAttributesBecomesMap() { this.Serializer = this.Serializer with { IgnoreKeyAttributes = true }; @@ -15,7 +15,7 @@ public void ObjectWithKeyAttributesBecomesMap() Assert.Equal(2, reader.ReadMapHeader()); } - [Fact] + [Test] public void ObjectWithKeyAttributesBecomesArray_WhenIgnoreKeyAttributesIsFalse() { this.Serializer = this.Serializer with { IgnoreKeyAttributes = false }; @@ -26,7 +26,7 @@ public void ObjectWithKeyAttributesBecomesArray_WhenIgnoreKeyAttributesIsFalse() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void IgnoreKeyAttributes_WithPerfOverSchemaStability_ProducesArray() { // When both are true, PerfOverSchemaStability still produces arrays, @@ -43,7 +43,7 @@ public void IgnoreKeyAttributes_WithPerfOverSchemaStability_ProducesArray() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void ObjectWithoutKeyAttributes_NotAffectedByIgnoreKeyAttributes() { this.Serializer = this.Serializer with { IgnoreKeyAttributes = true }; @@ -54,7 +54,7 @@ public void ObjectWithoutKeyAttributes_NotAffectedByIgnoreKeyAttributes() Assert.Equal(2, reader.ReadMapHeader()); } - [Fact] + [Test] public void ComplexObject_WithNestedKeyAttributes() { this.Serializer = this.Serializer with { IgnoreKeyAttributes = true }; diff --git a/test/Nerdbank.MessagePack.Tests/InternedBuffersTests.cs b/test/Nerdbank.MessagePack.TUnit/InternedBuffersTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/InternedBuffersTests.cs rename to test/Nerdbank.MessagePack.TUnit/InternedBuffersTests.cs index 5e715d47..6a566eb5 100644 --- a/test/Nerdbank.MessagePack.Tests/InternedBuffersTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/InternedBuffersTests.cs @@ -9,26 +9,26 @@ public class InternedBuffersTests { private readonly InternedBuffers intern = new(); - [Fact] + [Test] public void EqualSpansProduceRefEqualMemory() { Assert.True(this.intern.Intern([1, 2, 3]).Span == this.intern.Intern([1, 2, 3]).Span); } - [Fact] + [Test] public void NonEqualSpansProduceUniqueMemory() { Assert.False(this.intern.Intern([1, 2, 4]).Span == this.intern.Intern([1, 2, 3]).Span); } - [Fact] + [Test] public void InterningStoredInIsolation() { InternedBuffers intern2 = new(); Assert.False(this.intern.Intern([1, 2, 3]).Span == intern2.Intern([1, 2, 3]).Span); } - [Fact] + [Test] public void InternSeveralBuffers() { // This verifies that several buffers can be interned and retrieved at once. @@ -47,7 +47,7 @@ public void InternSeveralBuffers() Assert.True(memory1.Span == memory1b.Span); } - [Fact] + [Test] public void BuffersAreWeaklyRetained() { WeakReference weakRef = Helper(); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackAsyncReaderTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackAsyncReaderTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/MessagePackAsyncReaderTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackAsyncReaderTests.cs index 6b4a3a74..b73684c5 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackAsyncReaderTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackAsyncReaderTests.cs @@ -3,7 +3,7 @@ public class MessagePackAsyncReaderTests { - [Fact] + [Test] public async Task BufferNextStructureAsync_IncompleteBuffer() { Sequence seq = new(); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackAsyncWriterTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackAsyncWriterTests.cs similarity index 82% rename from test/Nerdbank.MessagePack.Tests/MessagePackAsyncWriterTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackAsyncWriterTests.cs index d48318ef..3c73d2a6 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackAsyncWriterTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackAsyncWriterTests.cs @@ -1,12 +1,9 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Diagnostics.CodeAnalysis; -using System.IO.Pipelines; - public class MessagePackAsyncWriterTests { - [Fact] + [Test] public void WriteVeryLargeData() { MessagePackAsyncWriter writer = new(PipeWriter.Create(Stream.Null)); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackConverterAttributeTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackConverterAttributeTests.cs similarity index 97% rename from test/Nerdbank.MessagePack.Tests/MessagePackConverterAttributeTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackConverterAttributeTests.cs index 063b5a87..e9264b8b 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackConverterAttributeTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackConverterAttributeTests.cs @@ -11,13 +11,13 @@ public enum MyEnum Value2 = 2, } - [Fact] + [Test] public void CustomTypeWithConverter() { this.AssertRoundtrip(new CustomType() { InternalProperty = "some value" }); } - [Fact] + [Test] public void TypeWithCustomConvertedMembers() { var instance = new TypeWithCustomMembers() @@ -38,18 +38,18 @@ public void TypeWithCustomConvertedMembers() Assert.Equal(96, reader.ReadInt32()); } - [Fact] + [Test] public void GenericConverterOnMemberOfGenericType() { this.AssertRoundtrip(new Container() { Value = new(42) }); } - [Fact] + [Test] public void EnumWithCustomConverter() { MyEnum value = MyEnum.Value2; - byte[] msgpack = this.Serializer.Serialize(value, TestContext.Current.CancellationToken); - MyEnum deserializedValue = this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(value, this.TimeoutToken); + MyEnum deserializedValue = this.Serializer.Deserialize(msgpack, this.TimeoutToken); Assert.Equal(value, deserializedValue); MessagePackReader reader = new(msgpack); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackNamingPolicyTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackNamingPolicyTests.cs similarity index 59% rename from test/Nerdbank.MessagePack.Tests/MessagePackNamingPolicyTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackNamingPolicyTests.cs index 70ea4774..cccbeaea 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackNamingPolicyTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackNamingPolicyTests.cs @@ -9,135 +9,135 @@ /// public class MessagePackNamingPolicyTests { - [Theory] - [InlineData("urlValue", "URLValue")] - [InlineData("url", "URL")] - [InlineData("id", "ID")] - [InlineData("i", "I")] - [InlineData("", "")] - [InlineData("😀葛🀄", "😀葛🀄")] // Surrogate pairs - [InlineData("άλφαΒήταΓάμμα", "ΆλφαΒήταΓάμμα")] // Non-ascii letters - [InlineData("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize - [InlineData("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates - [InlineData("person", "Person")] - [InlineData("iPhone", "iPhone")] - [InlineData("iPhone", "IPhone")] - [InlineData("iPhone", "I Phone")] - [InlineData("iPhone", "I Phone")] - [InlineData("iPhone", " IPhone")] - [InlineData("iPhone", " IPhone ")] - [InlineData("isCia", "IsCIA")] - [InlineData("vmQ", "VmQ")] - [InlineData("xml2Json", "Xml2Json")] - [InlineData("snAkEcAsE", "SnAkEcAsE")] - [InlineData("snA__kEcAsE", "SnA__kEcAsE")] - [InlineData("snA__kEcAsE", "SnA__ kEcAsE")] - [InlineData("already_snake_case_", "already_snake_case_ ")] - [InlineData("isJsonProperty", "IsJSONProperty")] - [InlineData("shouting_case", "SHOUTING_CASE")] - [InlineData("9999-12-31T23:59:59.9999999Z", "9999-12-31T23:59:59.9999999Z")] - [InlineData("hi!!thisIsText.timeToTest.", "Hi!! This is text. Time to test.")] - [InlineData("building", "BUILDING")] - [InlineData("buildingProperty", "BUILDING Property")] - [InlineData("buildingProperty", "Building Property")] - [InlineData("buildingProperty", "BUILDING PROPERTY")] + [Test] + [Arguments("urlValue", "URLValue")] + [Arguments("url", "URL")] + [Arguments("id", "ID")] + [Arguments("i", "I")] + [Arguments("", "")] + [Arguments("😀葛🀄", "😀葛🀄")] // Surrogate pairs + [Arguments("άλφαΒήταΓάμμα", "ΆλφαΒήταΓάμμα")] // Non-ascii letters + [Arguments("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize + [Arguments("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates + [Arguments("person", "Person")] + [Arguments("iPhone", "iPhone")] + [Arguments("iPhone", "IPhone")] + [Arguments("iPhone", "I Phone")] + [Arguments("iPhone", "I Phone")] + [Arguments("iPhone", " IPhone")] + [Arguments("iPhone", " IPhone ")] + [Arguments("isCia", "IsCIA")] + [Arguments("vmQ", "VmQ")] + [Arguments("xml2Json", "Xml2Json")] + [Arguments("snAkEcAsE", "SnAkEcAsE")] + [Arguments("snA__kEcAsE", "SnA__kEcAsE")] + [Arguments("snA__kEcAsE", "SnA__ kEcAsE")] + [Arguments("already_snake_case_", "already_snake_case_ ")] + [Arguments("isJsonProperty", "IsJSONProperty")] + [Arguments("shouting_case", "SHOUTING_CASE")] + [Arguments("9999-12-31T23:59:59.9999999Z", "9999-12-31T23:59:59.9999999Z")] + [Arguments("hi!!thisIsText.timeToTest.", "Hi!! This is text. Time to test.")] + [Arguments("building", "BUILDING")] + [Arguments("buildingProperty", "BUILDING Property")] + [Arguments("buildingProperty", "Building Property")] + [Arguments("buildingProperty", "BUILDING PROPERTY")] public void CamelCaseNamingPolicy(string expected, string input) { string actual = MessagePackNamingPolicy.CamelCase.ConvertName(input); Assert.Equal(expected, actual); } - [Theory] - [InlineData("PropertyName", "propertyName")] - [InlineData("PropertyName", "propertyNAME")] - [InlineData("UrlValue", "urlValue")] - [InlineData("Url", "url")] - [InlineData("Id", "id")] - [InlineData("I", "i")] - [InlineData("Person", "person")] - [InlineData("IPhone", "iPhone")] - [InlineData("IPhone", "i Phone")] - [InlineData("MyUrl", "myURL")] - [InlineData("MyUrlValue", "myURLValue")] - [InlineData("AlreadyPascal", "AlreadyPascal")] - [InlineData("This_is_a_test", "THIS_IS_A_TEST")] - [InlineData("ThisIsATest", "thisIsATest")] - [InlineData("Sha512Hash", "SHA512Hash")] - [InlineData("MyProperty", "My Property")] - [InlineData("", " ")] - [InlineData("", "")] + [Test] + [Arguments("PropertyName", "propertyName")] + [Arguments("PropertyName", "propertyNAME")] + [Arguments("UrlValue", "urlValue")] + [Arguments("Url", "url")] + [Arguments("Id", "id")] + [Arguments("I", "i")] + [Arguments("Person", "person")] + [Arguments("IPhone", "iPhone")] + [Arguments("IPhone", "i Phone")] + [Arguments("MyUrl", "myURL")] + [Arguments("MyUrlValue", "myURLValue")] + [Arguments("AlreadyPascal", "AlreadyPascal")] + [Arguments("This_is_a_test", "THIS_IS_A_TEST")] + [Arguments("ThisIsATest", "thisIsATest")] + [Arguments("Sha512Hash", "SHA512Hash")] + [Arguments("MyProperty", "My Property")] + [Arguments("", " ")] + [Arguments("", "")] public void PascalCaseNamingPolicy(string expected, string input) { string actual = MessagePackNamingPolicy.PascalCase.ConvertName(input); Assert.Equal(expected, actual); } - [Fact] + [Test] public void CamelCaseNullNameThrows() { Assert.Throws(() => MessagePackNamingPolicy.CamelCase.ConvertName(null!)); } - [Theory] - [InlineData("xml_http_request", "XMLHttpRequest")] - [InlineData("sha512_hash_algorithm", "SHA512HashAlgorithm")] - [InlineData("i18n", "i18n")] - [InlineData("i18n_policy", "I18nPolicy")] - [InlineData("7samurai", "7samurai")] - [InlineData("camel_case", "camelCase")] - [InlineData("camel_case", "CamelCase")] - [InlineData("snake_case", "snake_case")] - [InlineData("snake_case", "SNAKE_CASE")] - [InlineData("kebab-case", "kebab-case")] - [InlineData("kebab-case", "KEBAB-CASE")] - [InlineData("double_space", "double space")] - [InlineData("double__underscore", "double__underscore")] - [InlineData("double--dash", "double--dash")] - [InlineData("abc", "abc")] - [InlineData("ab_c", "abC")] - [InlineData("a_bc", "aBc")] - [InlineData("a_bc", "aBC")] - [InlineData("a_bc", "ABc")] - [InlineData("abc", "ABC")] - [InlineData("abc123def456", "abc123def456")] - [InlineData("abc123_def456", "abc123Def456")] - [InlineData("abc123_def456", "abc123DEF456")] - [InlineData("abc123_def456", "ABC123DEF456")] - [InlineData("abc123def456", "ABC123def456")] - [InlineData("abc123def456", "Abc123def456")] - [InlineData("abc", " abc")] - [InlineData("abc", "abc ")] - [InlineData("abc", " abc ")] - [InlineData("abc", " Abc ")] - [InlineData("7ab7", " 7ab7 ")] - [InlineData("abc_def", " abc def ")] - [InlineData("abc_def", " abc def ")] - [InlineData("abc_def", " abc def ")] - [InlineData("abc_7ef", " abc 7ef ")] - [InlineData("ab7_def", " ab7 def ")] - [InlineData("_abc", "_abc")] - [InlineData("", "")] - [InlineData("😀葛🀄", "😀葛🀄")] // Surrogate pairs - [InlineData("άλφα_βήτα_γάμμα", "ΆλφαΒήταΓάμμα")] // Non-ascii letters - [InlineData("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize - [InlineData("𐐀abc_def𐐨abc😀def𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] - [InlineData("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates - [InlineData("a%", "a%")] - [InlineData("_?#-", "_?#-")] - [InlineData("?!?", "? ! ?")] - [InlineData("$type", "$type")] - [InlineData("abc%def", "abc%def")] - [InlineData("__abc__def__", "__abc__def__")] - [InlineData("_abc_abc_abc", "_abcAbc_abc")] - [InlineData("abc???def", "ABC???def")] - [InlineData("ab_cd-_-de_f", "ABCd - _ - DE f")] - [InlineData( + [Test] + [Arguments("xml_http_request", "XMLHttpRequest")] + [Arguments("sha512_hash_algorithm", "SHA512HashAlgorithm")] + [Arguments("i18n", "i18n")] + [Arguments("i18n_policy", "I18nPolicy")] + [Arguments("7samurai", "7samurai")] + [Arguments("camel_case", "camelCase")] + [Arguments("camel_case", "CamelCase")] + [Arguments("snake_case", "snake_case")] + [Arguments("snake_case", "SNAKE_CASE")] + [Arguments("kebab-case", "kebab-case")] + [Arguments("kebab-case", "KEBAB-CASE")] + [Arguments("double_space", "double space")] + [Arguments("double__underscore", "double__underscore")] + [Arguments("double--dash", "double--dash")] + [Arguments("abc", "abc")] + [Arguments("ab_c", "abC")] + [Arguments("a_bc", "aBc")] + [Arguments("a_bc", "aBC")] + [Arguments("a_bc", "ABc")] + [Arguments("abc", "ABC")] + [Arguments("abc123def456", "abc123def456")] + [Arguments("abc123_def456", "abc123Def456")] + [Arguments("abc123_def456", "abc123DEF456")] + [Arguments("abc123_def456", "ABC123DEF456")] + [Arguments("abc123def456", "ABC123def456")] + [Arguments("abc123def456", "Abc123def456")] + [Arguments("abc", " abc")] + [Arguments("abc", "abc ")] + [Arguments("abc", " abc ")] + [Arguments("abc", " Abc ")] + [Arguments("7ab7", " 7ab7 ")] + [Arguments("abc_def", " abc def ")] + [Arguments("abc_def", " abc def ")] + [Arguments("abc_def", " abc def ")] + [Arguments("abc_7ef", " abc 7ef ")] + [Arguments("ab7_def", " ab7 def ")] + [Arguments("_abc", "_abc")] + [Arguments("", "")] + [Arguments("😀葛🀄", "😀葛🀄")] // Surrogate pairs + [Arguments("άλφα_βήτα_γάμμα", "ΆλφαΒήταΓάμμα")] // Non-ascii letters + [Arguments("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize + [Arguments("𐐀abc_def𐐨abc😀def𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] + [Arguments("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates + [Arguments("a%", "a%")] + [Arguments("_?#-", "_?#-")] + [Arguments("?!?", "? ! ?")] + [Arguments("$type", "$type")] + [Arguments("abc%def", "abc%def")] + [Arguments("__abc__def__", "__abc__def__")] + [Arguments("_abc_abc_abc", "_abcAbc_abc")] + [Arguments("abc???def", "ABC???def")] + [Arguments("ab_cd-_-de_f", "ABCd - _ - DE f")] + [Arguments( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "a_haaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "a_towel_it_says_is_about_the_most_massively_useful_thing_an_interstellar_hitchhiker_can_have_partly_it_has_great_practical_value_you_can_wrap_it_around_you_for_warmth_as_you_bound_across_the_cold_moons_of_jaglan_beta_you_can_lie_on_it_on_the_brilliant_marble_sanded_beaches_of_santraginus_v_inhaling_the_heady_sea_vapors_you_can_sleep_under_it_beneath_the_stars_which_shine_so_redly_on_the_desert_world_of_kakrafoon_use_it_to_sail_a_miniraft_down_the_slow_heavy_river_moth_wet_it_for_use_in_hand_to_hand_combat_wrap_it_round_your_head_to_ward_off_noxious_fumes_or_avoid_the_gaze_of_the_ravenous_bugblatter_beast_of_traal_a_mind_bogglingly_stupid_animal_it_assumes_that_if_you_cant_see_it_it_cant_see_you_daft_as_a_brush_but_very_very_ravenous_you_can_wave_your_towel_in_emergencies_as_a_distress_signal_and_of_course_dry_yourself_of_with_it_if_it_still_seems_to_be_clean_enough", "ATowelItSaysIsAboutTheMostMassivelyUsefulThingAnInterstellarHitchhikerCanHave_PartlyItHasGreatPracticalValue_YouCanWrapItAroundYouForWarmthAsYouBoundAcrossTheColdMoonsOfJaglanBeta_YouCanLieOnItOnTheBrilliantMarbleSandedBeachesOfSantraginusVInhalingTheHeadySeaVapors_YouCanSleepUnderItBeneathTheStarsWhichShineSoRedlyOnTheDesertWorldOfKakrafoon_UseItToSailAMiniraftDownTheSlowHeavyRiverMoth_WetItForUseInHandToHandCombat_WrapItRoundYourHeadToWardOffNoxiousFumesOrAvoidTheGazeOfTheRavenousBugblatterBeastOfTraalAMindBogglinglyStupidAnimal_ItAssumesThatIfYouCantSeeItItCantSeeYouDaftAsABrushButVeryVeryRavenous_YouCanWaveYourTowelInEmergenciesAsADistressSignalAndOfCourseDryYourselfOfWithItIfItStillSeemsToBeCleanEnough")] public void SnakeLowerCaseNamingPolicy(string expected, string input) @@ -146,66 +146,66 @@ public void SnakeLowerCaseNamingPolicy(string expected, string input) Assert.Equal(expected, actual); } - [Theory] - [InlineData("XML_HTTP_REQUEST", "XMLHttpRequest")] - [InlineData("SHA512_HASH_ALGORITHM", "SHA512HashAlgorithm")] - [InlineData("I18N", "i18n")] - [InlineData("I18N_POLICY", "I18nPolicy")] - [InlineData("7SAMURAI", "7samurai")] - [InlineData("CAMEL_CASE", "camelCase")] - [InlineData("CAMEL_CASE", "CamelCase")] - [InlineData("SNAKE_CASE", "snake_case")] - [InlineData("SNAKE_CASE", "SNAKE_CASE")] - [InlineData("KEBAB-CASE", "kebab-case")] - [InlineData("KEBAB-CASE", "KEBAB-CASE")] - [InlineData("DOUBLE_SPACE", "double space")] - [InlineData("DOUBLE__UNDERSCORE", "double__underscore")] - [InlineData("DOUBLE--DASH", "double--dash")] - [InlineData("ABC", "abc")] - [InlineData("AB_C", "abC")] - [InlineData("A_BC", "aBc")] - [InlineData("A_BC", "aBC")] - [InlineData("A_BC", "ABc")] - [InlineData("ABC", "ABC")] - [InlineData("ABC123DEF456", "abc123def456")] - [InlineData("ABC123_DEF456", "abc123Def456")] - [InlineData("ABC123_DEF456", "abc123DEF456")] - [InlineData("ABC123_DEF456", "ABC123DEF456")] - [InlineData("ABC123DEF456", "ABC123def456")] - [InlineData("ABC123DEF456", "Abc123def456")] - [InlineData("ABC", " ABC")] - [InlineData("ABC", "ABC ")] - [InlineData("ABC", " ABC ")] - [InlineData("ABC", " Abc ")] - [InlineData("7AB7", " 7ab7 ")] - [InlineData("ABC_DEF", " ABC def ")] - [InlineData("ABC_DEF", " abc def ")] - [InlineData("ABC_DEF", " abc def ")] - [InlineData("ABC_7EF", " abc 7ef ")] - [InlineData("AB7_DEF", " ab7 def ")] - [InlineData("_ABC", "_abc")] - [InlineData("", "")] - [InlineData("😀葛🀄", "😀葛🀄")] // Surrogate pairs - [InlineData("ΆΛΦΑ_ΒΉΤΑ_ΓΆΜΜΑ", "ΆλφαΒήταΓάμμα")] // Non-ascii letters - [InlineData("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize - [InlineData("𐐀ABC_DEF𐐨ABC😀DEF𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] - [InlineData("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates - [InlineData("A%", "a%")] - [InlineData("_?#-", "_?#-")] - [InlineData("?!?", "? ! ?")] - [InlineData("$TYPE", "$type")] - [InlineData("ABC%DEF", "abc%def")] - [InlineData("__ABC__DEF__", "__abc__def__")] - [InlineData("_ABC_ABC_ABC", "_abcAbc_abc")] - [InlineData("ABC???DEF", "ABC???def")] - [InlineData("AB_CD-_-DE_F", "ABCd - _ - DE f")] - [InlineData( + [Test] + [Arguments("XML_HTTP_REQUEST", "XMLHttpRequest")] + [Arguments("SHA512_HASH_ALGORITHM", "SHA512HashAlgorithm")] + [Arguments("I18N", "i18n")] + [Arguments("I18N_POLICY", "I18nPolicy")] + [Arguments("7SAMURAI", "7samurai")] + [Arguments("CAMEL_CASE", "camelCase")] + [Arguments("CAMEL_CASE", "CamelCase")] + [Arguments("SNAKE_CASE", "snake_case")] + [Arguments("SNAKE_CASE", "SNAKE_CASE")] + [Arguments("KEBAB-CASE", "kebab-case")] + [Arguments("KEBAB-CASE", "KEBAB-CASE")] + [Arguments("DOUBLE_SPACE", "double space")] + [Arguments("DOUBLE__UNDERSCORE", "double__underscore")] + [Arguments("DOUBLE--DASH", "double--dash")] + [Arguments("ABC", "abc")] + [Arguments("AB_C", "abC")] + [Arguments("A_BC", "aBc")] + [Arguments("A_BC", "aBC")] + [Arguments("A_BC", "ABc")] + [Arguments("ABC", "ABC")] + [Arguments("ABC123DEF456", "abc123def456")] + [Arguments("ABC123_DEF456", "abc123Def456")] + [Arguments("ABC123_DEF456", "abc123DEF456")] + [Arguments("ABC123_DEF456", "ABC123DEF456")] + [Arguments("ABC123DEF456", "ABC123def456")] + [Arguments("ABC123DEF456", "Abc123def456")] + [Arguments("ABC", " ABC")] + [Arguments("ABC", "ABC ")] + [Arguments("ABC", " ABC ")] + [Arguments("ABC", " Abc ")] + [Arguments("7AB7", " 7ab7 ")] + [Arguments("ABC_DEF", " ABC def ")] + [Arguments("ABC_DEF", " abc def ")] + [Arguments("ABC_DEF", " abc def ")] + [Arguments("ABC_7EF", " abc 7ef ")] + [Arguments("AB7_DEF", " ab7 def ")] + [Arguments("_ABC", "_abc")] + [Arguments("", "")] + [Arguments("😀葛🀄", "😀葛🀄")] // Surrogate pairs + [Arguments("ΆΛΦΑ_ΒΉΤΑ_ΓΆΜΜΑ", "ΆλφαΒήταΓάμμα")] // Non-ascii letters + [Arguments("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize + [Arguments("𐐀ABC_DEF𐐨ABC😀DEF𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] + [Arguments("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates + [Arguments("A%", "a%")] + [Arguments("_?#-", "_?#-")] + [Arguments("?!?", "? ! ?")] + [Arguments("$TYPE", "$type")] + [Arguments("ABC%DEF", "abc%def")] + [Arguments("__ABC__DEF__", "__abc__def__")] + [Arguments("_ABC_ABC_ABC", "_abcAbc_abc")] + [Arguments("ABC???DEF", "ABC???def")] + [Arguments("AB_CD-_-DE_F", "ABCd - _ - DE f")] + [Arguments( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "A_HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "aHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "A_TOWEL_IT_SAYS_IS_ABOUT_THE_MOST_MASSIVELY_USEFUL_THING_AN_INTERSTELLAR_HITCHHIKER_CAN_HAVE_PARTLY_IT_HAS_GREAT_PRACTICAL_VALUE_YOU_CAN_WRAP_IT_AROUND_YOU_FOR_WARMTH_AS_YOU_BOUND_ACROSS_THE_COLD_MOONS_OF_JAGLAN_BETA_YOU_CAN_LIE_ON_IT_ON_THE_BRILLIANT_MARBLE_SANDED_BEACHES_OF_SANTRAGINUS_V_INHALING_THE_HEADY_SEA_VAPORS_YOU_CAN_SLEEP_UNDER_IT_BENEATH_THE_STARS_WHICH_SHINE_SO_REDLY_ON_THE_DESERT_WORLD_OF_KAKRAFOON_USE_IT_TO_SAIL_A_MINIRAFT_DOWN_THE_SLOW_HEAVY_RIVER_MOTH_WET_IT_FOR_USE_IN_HAND_TO_HAND_COMBAT_WRAP_IT_ROUND_YOUR_HEAD_TO_WARD_OFF_NOXIOUS_FUMES_OR_AVOID_THE_GAZE_OF_THE_RAVENOUS_BUGBLATTER_BEAST_OF_TRAAL_A_MIND_BOGGLINGLY_STUPID_ANIMAL_IT_ASSUMES_THAT_IF_YOU_CANT_SEE_IT_IT_CANT_SEE_YOU_DAFT_AS_A_BRUSH_BUT_VERY_VERY_RAVENOUS_YOU_CAN_WAVE_YOUR_TOWEL_IN_EMERGENCIES_AS_A_DISTRESS_SIGNAL_AND_OF_COURSE_DRY_YOURSELF_OF_WITH_IT_IF_IT_STILL_SEEMS_TO_BE_CLEAN_ENOUGH", "ATowelItSaysIsAboutTheMostMassivelyUsefulThingAnInterstellarHitchhikerCanHave_PartlyItHasGreatPracticalValue_YouCanWrapItAroundYouForWarmthAsYouBoundAcrossTheColdMoonsOfJaglanBeta_YouCanLieOnItOnTheBrilliantMarbleSandedBeachesOfSantraginusVInhalingTheHeadySeaVapors_YouCanSleepUnderItBeneathTheStarsWhichShineSoRedlyOnTheDesertWorldOfKakrafoon_UseItToSailAMiniraftDownTheSlowHeavyRiverMoth_WetItForUseInHandToHandCombat_WrapItRoundYourHeadToWardOffNoxiousFumesOrAvoidTheGazeOfTheRavenousBugblatterBeastOfTraalAMindBogglinglyStupidAnimal_ItAssumesThatIfYouCantSeeItItCantSeeYouDaftAsABrushButVeryVeryRavenous_YouCanWaveYourTowelInEmergenciesAsADistressSignalAndOfCourseDryYourselfOfWithItIfItStillSeemsToBeCleanEnough")] public void SnakeUpperCaseNamingPolicy(string expected, string input) @@ -214,66 +214,66 @@ public void SnakeUpperCaseNamingPolicy(string expected, string input) Assert.Equal(expected, actual); } - [Theory] - [InlineData("xml-http-request", "XMLHttpRequest")] - [InlineData("sha512-hash-algorithm", "SHA512HashAlgorithm")] - [InlineData("i18n", "i18n")] - [InlineData("i18n-policy", "I18nPolicy")] - [InlineData("7samurai", "7samurai")] - [InlineData("camel-case", "camelCase")] - [InlineData("camel-case", "CamelCase")] - [InlineData("snake_case", "snake_case")] - [InlineData("snake_case", "SNAKE_CASE")] - [InlineData("kebab-case", "kebab-case")] - [InlineData("kebab-case", "KEBAB-CASE")] - [InlineData("double-space", "double space")] - [InlineData("double__underscore", "double__underscore")] - [InlineData("double--dash", "double--dash")] - [InlineData("abc", "abc")] - [InlineData("ab-c", "abC")] - [InlineData("a-bc", "aBc")] - [InlineData("a-bc", "aBC")] - [InlineData("a-bc", "ABc")] - [InlineData("abc", "ABC")] - [InlineData("abc123def456", "abc123def456")] - [InlineData("abc123-def456", "abc123Def456")] - [InlineData("abc123-def456", "abc123DEF456")] - [InlineData("abc123-def456", "ABC123DEF456")] - [InlineData("abc123def456", "ABC123def456")] - [InlineData("abc123def456", "Abc123def456")] - [InlineData("abc", " abc")] - [InlineData("abc", "abc ")] - [InlineData("abc", " abc ")] - [InlineData("abc", " Abc ")] - [InlineData("7ab7", " 7ab7 ")] - [InlineData("abc-def", " abc def ")] - [InlineData("abc-def", " abc def ")] - [InlineData("abc-def", " abc def ")] - [InlineData("abc-7ef", " abc 7ef ")] - [InlineData("ab7-def", " ab7 def ")] - [InlineData("-abc", "-abc")] - [InlineData("", "")] - [InlineData("😀葛🀄", "😀葛🀄")] // Surrogate pairs - [InlineData("άλφα-βήτα-γάμμα", "ΆλφαΒήταΓάμμα")] // Non-ascii letters - [InlineData("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize - [InlineData("𐐀abc-def𐐨abc😀def𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] - [InlineData("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates - [InlineData("a%", "a%")] - [InlineData("-?#_", "-?#_")] - [InlineData("?!?", "? ! ?")] - [InlineData("$type", "$type")] - [InlineData("abc%def", "abc%def")] - [InlineData("--abc--def--", "--abc--def--")] - [InlineData("-abc-abc-abc", "-abcAbc-abc")] - [InlineData("abc???def", "ABC???def")] - [InlineData("ab-cd-_-de-f", "ABCd - _ - DE f")] - [InlineData( + [Test] + [Arguments("xml-http-request", "XMLHttpRequest")] + [Arguments("sha512-hash-algorithm", "SHA512HashAlgorithm")] + [Arguments("i18n", "i18n")] + [Arguments("i18n-policy", "I18nPolicy")] + [Arguments("7samurai", "7samurai")] + [Arguments("camel-case", "camelCase")] + [Arguments("camel-case", "CamelCase")] + [Arguments("snake_case", "snake_case")] + [Arguments("snake_case", "SNAKE_CASE")] + [Arguments("kebab-case", "kebab-case")] + [Arguments("kebab-case", "KEBAB-CASE")] + [Arguments("double-space", "double space")] + [Arguments("double__underscore", "double__underscore")] + [Arguments("double--dash", "double--dash")] + [Arguments("abc", "abc")] + [Arguments("ab-c", "abC")] + [Arguments("a-bc", "aBc")] + [Arguments("a-bc", "aBC")] + [Arguments("a-bc", "ABc")] + [Arguments("abc", "ABC")] + [Arguments("abc123def456", "abc123def456")] + [Arguments("abc123-def456", "abc123Def456")] + [Arguments("abc123-def456", "abc123DEF456")] + [Arguments("abc123-def456", "ABC123DEF456")] + [Arguments("abc123def456", "ABC123def456")] + [Arguments("abc123def456", "Abc123def456")] + [Arguments("abc", " abc")] + [Arguments("abc", "abc ")] + [Arguments("abc", " abc ")] + [Arguments("abc", " Abc ")] + [Arguments("7ab7", " 7ab7 ")] + [Arguments("abc-def", " abc def ")] + [Arguments("abc-def", " abc def ")] + [Arguments("abc-def", " abc def ")] + [Arguments("abc-7ef", " abc 7ef ")] + [Arguments("ab7-def", " ab7 def ")] + [Arguments("-abc", "-abc")] + [Arguments("", "")] + [Arguments("😀葛🀄", "😀葛🀄")] // Surrogate pairs + [Arguments("άλφα-βήτα-γάμμα", "ΆλφαΒήταΓάμμα")] // Non-ascii letters + [Arguments("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize + [Arguments("𐐀abc-def𐐨abc😀def𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] + [Arguments("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates + [Arguments("a%", "a%")] + [Arguments("-?#_", "-?#_")] + [Arguments("?!?", "? ! ?")] + [Arguments("$type", "$type")] + [Arguments("abc%def", "abc%def")] + [Arguments("--abc--def--", "--abc--def--")] + [Arguments("-abc-abc-abc", "-abcAbc-abc")] + [Arguments("abc???def", "ABC???def")] + [Arguments("ab-cd-_-de-f", "ABCd - _ - DE f")] + [Arguments( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "a-haaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "a-towel-it-says-is-about-the-most-massively-useful-thing-an-interstellar-hitchhiker-can-have_partly-it-has-great-practical-value_you-can-wrap-it-around-you-for-warmth-as-you-bound-across-the-cold-moons-of-jaglan-beta_you-can-lie-on-it-on-the-brilliant-marble-sanded-beaches-of-santraginus-v-inhaling-the-heady-sea-vapors_you-can-sleep-under-it-beneath-the-stars-which-shine-so-redly-on-the-desert-world-of-kakrafoon_use-it-to-sail-a-miniraft-down-the-slow-heavy-river-moth_wet-it-for-use-in-hand-to-hand-combat_wrap-it-round-your-head-to-ward-off-noxious-fumes-or-avoid-the-gaze-of-the-ravenous-bugblatter-beast-of-traal-a-mind-bogglingly-stupid-animal_it-assumes-that-if-you-cant-see-it-it-cant-see-you-daft-as-a-brush-but-very-very-ravenous_you-can-wave-your-towel-in-emergencies-as-a-distress-signal-and-of-course-dry-yourself-of-with-it-if-it-still-seems-to-be-clean-enough", "ATowelItSaysIsAboutTheMostMassivelyUsefulThingAnInterstellarHitchhikerCanHave_PartlyItHasGreatPracticalValue_YouCanWrapItAroundYouForWarmthAsYouBoundAcrossTheColdMoonsOfJaglanBeta_YouCanLieOnItOnTheBrilliantMarbleSandedBeachesOfSantraginusVInhalingTheHeadySeaVapors_YouCanSleepUnderItBeneathTheStarsWhichShineSoRedlyOnTheDesertWorldOfKakrafoon_UseItToSailAMiniraftDownTheSlowHeavyRiverMoth_WetItForUseInHandToHandCombat_WrapItRoundYourHeadToWardOffNoxiousFumesOrAvoidTheGazeOfTheRavenousBugblatterBeastOfTraalAMindBogglinglyStupidAnimal_ItAssumesThatIfYouCantSeeItItCantSeeYouDaftAsABrushButVeryVeryRavenous_YouCanWaveYourTowelInEmergenciesAsADistressSignalAndOfCourseDryYourselfOfWithItIfItStillSeemsToBeCleanEnough")] public void KebabLowerCaseNamingPolicy(string expected, string input) @@ -282,66 +282,66 @@ public void KebabLowerCaseNamingPolicy(string expected, string input) Assert.Equal(expected, actual); } - [Theory] - [InlineData("XML-HTTP-REQUEST", "XMLHttpRequest")] - [InlineData("SHA512-HASH-ALGORITHM", "SHA512HashAlgorithm")] - [InlineData("I18N", "i18n")] - [InlineData("I18N-POLICY", "I18nPolicy")] - [InlineData("7SAMURAI", "7samurai")] - [InlineData("CAMEL-CASE", "camelCase")] - [InlineData("CAMEL-CASE", "CamelCase")] - [InlineData("SNAKE_CASE", "snake_case")] - [InlineData("SNAKE_CASE", "SNAKE_CASE")] - [InlineData("KEBAB-CASE", "kebab-case")] - [InlineData("KEBAB-CASE", "KEBAB-CASE")] - [InlineData("DOUBLE-SPACE", "double space")] - [InlineData("DOUBLE__UNDERSCORE", "double__underscore")] - [InlineData("DOUBLE--DASH", "double--dash")] - [InlineData("ABC", "abc")] - [InlineData("AB-C", "abC")] - [InlineData("A-BC", "aBc")] - [InlineData("A-BC", "aBC")] - [InlineData("A-BC", "ABc")] - [InlineData("ABC", "ABC")] - [InlineData("ABC123DEF456", "abc123def456")] - [InlineData("ABC123-DEF456", "abc123Def456")] - [InlineData("ABC123-DEF456", "abc123DEF456")] - [InlineData("ABC123-DEF456", "ABC123DEF456")] - [InlineData("ABC123DEF456", "ABC123def456")] - [InlineData("ABC123DEF456", "Abc123def456")] - [InlineData("ABC", " ABC")] - [InlineData("ABC", "ABC ")] - [InlineData("ABC", " ABC ")] - [InlineData("ABC", " Abc ")] - [InlineData("7AB7", " 7ab7 ")] - [InlineData("ABC-DEF", " ABC def ")] - [InlineData("ABC-DEF", " abc def ")] - [InlineData("ABC-DEF", " abc def ")] - [InlineData("ABC-7EF", " abc 7ef ")] - [InlineData("AB7-DEF", " ab7 def ")] - [InlineData("-ABC", "-abc")] - [InlineData("", "")] - [InlineData("😀葛🀄", "😀葛🀄")] // Surrogate pairs - [InlineData("ΆΛΦΑ-ΒΉΤΑ-ΓΆΜΜΑ", "ΆλφαΒήταΓάμμα")] // Non-ascii letters - [InlineData("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize - [InlineData("𐐀ABC-DEF𐐨ABC😀DEF𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] - [InlineData("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates - [InlineData("A%", "a%")] - [InlineData("-?#_", "-?#_")] - [InlineData("?!?", "? ! ?")] - [InlineData("$TYPE", "$type")] - [InlineData("ABC%DEF", "abc%def")] - [InlineData("--ABC--DEF--", "--abc--def--")] - [InlineData("-ABC-ABC-ABC", "-abcAbc-abc")] - [InlineData("ABC???DEF", "ABC???def")] - [InlineData("AB-CD-_-DE-F", "ABCd - _ - DE f")] - [InlineData( + [Test] + [Arguments("XML-HTTP-REQUEST", "XMLHttpRequest")] + [Arguments("SHA512-HASH-ALGORITHM", "SHA512HashAlgorithm")] + [Arguments("I18N", "i18n")] + [Arguments("I18N-POLICY", "I18nPolicy")] + [Arguments("7SAMURAI", "7samurai")] + [Arguments("CAMEL-CASE", "camelCase")] + [Arguments("CAMEL-CASE", "CamelCase")] + [Arguments("SNAKE_CASE", "snake_case")] + [Arguments("SNAKE_CASE", "SNAKE_CASE")] + [Arguments("KEBAB-CASE", "kebab-case")] + [Arguments("KEBAB-CASE", "KEBAB-CASE")] + [Arguments("DOUBLE-SPACE", "double space")] + [Arguments("DOUBLE__UNDERSCORE", "double__underscore")] + [Arguments("DOUBLE--DASH", "double--dash")] + [Arguments("ABC", "abc")] + [Arguments("AB-C", "abC")] + [Arguments("A-BC", "aBc")] + [Arguments("A-BC", "aBC")] + [Arguments("A-BC", "ABc")] + [Arguments("ABC", "ABC")] + [Arguments("ABC123DEF456", "abc123def456")] + [Arguments("ABC123-DEF456", "abc123Def456")] + [Arguments("ABC123-DEF456", "abc123DEF456")] + [Arguments("ABC123-DEF456", "ABC123DEF456")] + [Arguments("ABC123DEF456", "ABC123def456")] + [Arguments("ABC123DEF456", "Abc123def456")] + [Arguments("ABC", " ABC")] + [Arguments("ABC", "ABC ")] + [Arguments("ABC", " ABC ")] + [Arguments("ABC", " Abc ")] + [Arguments("7AB7", " 7ab7 ")] + [Arguments("ABC-DEF", " ABC def ")] + [Arguments("ABC-DEF", " abc def ")] + [Arguments("ABC-DEF", " abc def ")] + [Arguments("ABC-7EF", " abc 7ef ")] + [Arguments("AB7-DEF", " ab7 def ")] + [Arguments("-ABC", "-abc")] + [Arguments("", "")] + [Arguments("😀葛🀄", "😀葛🀄")] // Surrogate pairs + [Arguments("ΆΛΦΑ-ΒΉΤΑ-ΓΆΜΜΑ", "ΆλφαΒήταΓάμμα")] // Non-ascii letters + [Arguments("𐐀𐐨𐐨𐐀𐐨𐐨", "𐐀𐐨𐐨𐐀𐐨𐐨")] // Surrogate pair letters don't normalize + [Arguments("𐐀ABC-DEF𐐨ABC😀DEF𐐀", "𐐀AbcDef𐐨Abc😀Def𐐀")] + [Arguments("\ude00\ud83d", "\ude00\ud83d")] // Unpaired surrogates + [Arguments("A%", "a%")] + [Arguments("-?#_", "-?#_")] + [Arguments("?!?", "? ! ?")] + [Arguments("$TYPE", "$type")] + [Arguments("ABC%DEF", "abc%def")] + [Arguments("--ABC--DEF--", "--abc--def--")] + [Arguments("-ABC-ABC-ABC", "-abcAbc-abc")] + [Arguments("ABC???DEF", "ABC???def")] + [Arguments("AB-CD-_-DE-F", "ABCd - _ - DE f")] + [Arguments( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "A-HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "aHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - [InlineData( + [Arguments( "A-TOWEL-IT-SAYS-IS-ABOUT-THE-MOST-MASSIVELY-USEFUL-THING-AN-INTERSTELLAR-HITCHHIKER-CAN-HAVE_PARTLY-IT-HAS-GREAT-PRACTICAL-VALUE_YOU-CAN-WRAP-IT-AROUND-YOU-FOR-WARMTH-AS-YOU-BOUND-ACROSS-THE-COLD-MOONS-OF-JAGLAN-BETA_YOU-CAN-LIE-ON-IT-ON-THE-BRILLIANT-MARBLE-SANDED-BEACHES-OF-SANTRAGINUS-V-INHALING-THE-HEADY-SEA-VAPORS_YOU-CAN-SLEEP-UNDER-IT-BENEATH-THE-STARS-WHICH-SHINE-SO-REDLY-ON-THE-DESERT-WORLD-OF-KAKRAFOON_USE-IT-TO-SAIL-A-MINIRAFT-DOWN-THE-SLOW-HEAVY-RIVER-MOTH_WET-IT-FOR-USE-IN-HAND-TO-HAND-COMBAT_WRAP-IT-ROUND-YOUR-HEAD-TO-WARD-OFF-NOXIOUS-FUMES-OR-AVOID-THE-GAZE-OF-THE-RAVENOUS-BUGBLATTER-BEAST-OF-TRAAL-A-MIND-BOGGLINGLY-STUPID-ANIMAL_IT-ASSUMES-THAT-IF-YOU-CANT-SEE-IT-IT-CANT-SEE-YOU-DAFT-AS-A-BRUSH-BUT-VERY-VERY-RAVENOUS_YOU-CAN-WAVE-YOUR-TOWEL-IN-EMERGENCIES-AS-A-DISTRESS-SIGNAL-AND-OF-COURSE-DRY-YOURSELF-OF-WITH-IT-IF-IT-STILL-SEEMS-TO-BE-CLEAN-ENOUGH", "ATowelItSaysIsAboutTheMostMassivelyUsefulThingAnInterstellarHitchhikerCanHave_PartlyItHasGreatPracticalValue_YouCanWrapItAroundYouForWarmthAsYouBoundAcrossTheColdMoonsOfJaglanBeta_YouCanLieOnItOnTheBrilliantMarbleSandedBeachesOfSantraginusVInhalingTheHeadySeaVapors_YouCanSleepUnderItBeneathTheStarsWhichShineSoRedlyOnTheDesertWorldOfKakrafoon_UseItToSailAMiniraftDownTheSlowHeavyRiverMoth_WetItForUseInHandToHandCombat_WrapItRoundYourHeadToWardOffNoxiousFumesOrAvoidTheGazeOfTheRavenousBugblatterBeastOfTraalAMindBogglinglyStupidAnimal_ItAssumesThatIfYouCantSeeItItCantSeeYouDaftAsABrushButVeryVeryRavenous_YouCanWaveYourTowelInEmergenciesAsADistressSignalAndOfCourseDryYourselfOfWithItIfItStillSeemsToBeCleanEnough")] public void KebabUpperCaseNamingPolicy(string expected, string input) diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadInt.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadInt.cs similarity index 93% rename from test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadInt.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadInt.cs index 5fca6219..d8037479 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadInt.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadInt.cs @@ -138,12 +138,12 @@ public partial class MessagePackReaderTests (unchecked((Int64)0x8000000000000000), Encode((ref MessagePackWriter w) => w.WriteInt64(-9223372036854775808))), }; - [Fact] + [Test] public void ReadByte_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= Byte.MaxValue && value >= Byte.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadByte()); @@ -157,18 +157,18 @@ public void ReadByte_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadByte_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadByte()); } - [Fact] + [Test] public void ReadUInt16_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= UInt16.MaxValue && value >= UInt16.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadUInt16()); @@ -182,18 +182,18 @@ public void ReadUInt16_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadUInt16_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadUInt16()); } - [Fact] + [Test] public void ReadUInt32_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= UInt32.MaxValue && value >= UInt32.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadUInt32()); @@ -207,18 +207,18 @@ public void ReadUInt32_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadUInt32_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadUInt32()); } - [Fact] + [Test] public void ReadUInt64_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= UInt64.MaxValue && value >= UInt64.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadUInt64()); @@ -232,18 +232,18 @@ public void ReadUInt64_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadUInt64_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadUInt64()); } - [Fact] + [Test] public void ReadSByte_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= SByte.MaxValue && value >= SByte.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadSByte()); @@ -257,18 +257,18 @@ public void ReadSByte_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadSByte_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadSByte()); } - [Fact] + [Test] public void ReadInt16_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= Int16.MaxValue && value >= Int16.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadInt16()); @@ -282,18 +282,18 @@ public void ReadInt16_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadInt16_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadInt16()); } - [Fact] + [Test] public void ReadInt32_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= Int32.MaxValue && value >= Int32.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadInt32()); @@ -307,18 +307,18 @@ public void ReadInt32_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadInt32_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadInt32()); } - [Fact] + [Test] public void ReadInt64_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= Int64.MaxValue && value >= Int64.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).ReadInt64()); @@ -332,7 +332,7 @@ public void ReadInt64_ReadVariousLengthsAndMagnitudes() } } - [Fact] + [Test] public void ReadInt64_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).ReadInt64()); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadInt.tt b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadInt.tt similarity index 97% rename from test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadInt.tt rename to test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadInt.tt index 1d6c515f..31336bd6 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadInt.tt +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadInt.tt @@ -110,12 +110,12 @@ string GetMinValue(Type intType) => $"0x{intType.GetField(nameof(int.MinValue)). }; <# foreach (Type t1 in allTypes) { #> - [Fact] + [Test] public void Read<#=t1.Name#>_ReadVariousLengthsAndMagnitudes() { foreach ((BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); if (value <= <#=t1.Name#>.MaxValue && value >= <#=t1.Name#>.MinValue) { Assert.Equal(value, new MessagePackReader(encoded).Read<#=t1.Name#>()); @@ -129,7 +129,7 @@ string GetMinValue(Type intType) => $"0x{intType.GetField(nameof(int.MinValue)). } } - [Fact] + [Test] public void Read<#=t1.Name#>_ThrowsOnUnexpectedCode() { Assert.Throws(() => new MessagePackReader(StringEncodedAsFixStr).Read<#=t1.Name#>()); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadString.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadString.cs similarity index 99% rename from test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadString.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadString.cs index 6b8c1db5..9b65df61 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.ReadString.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.ReadString.cs @@ -3,7 +3,7 @@ public partial class MessagePackReaderTests { - [Fact] + [Test] public void ReadString_HandlesSingleSegment() { ReadOnlySequence seq = this.BuildSequence(new[] @@ -17,7 +17,7 @@ public void ReadString_HandlesSingleSegment() Assert.Equal("AB", result); } - [Fact] + [Test] public void ReadString_HandlesMultipleSegments() { ReadOnlySequence seq = this.BuildSequence( diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.cs similarity index 96% rename from test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.cs index 990f0f0a..c6cbb069 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackReaderTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackReaderTests.cs @@ -9,13 +9,6 @@ public partial class MessagePackReaderTests private const byte BytePositiveValue = 3; private static readonly ReadOnlySequence StringEncodedAsFixStr = Encode((ref MessagePackWriter w) => w.Write("hi")); - private readonly ITestOutputHelper logger; - - public MessagePackReaderTests(ITestOutputHelper logger) - { - this.logger = logger; - } - private delegate void RangeChecker(ref MessagePackReader reader); private delegate void ReaderOperation(ref MessagePackReader reader); @@ -24,24 +17,24 @@ public MessagePackReaderTests(ITestOutputHelper logger) private delegate void WriterEncoder(ref MessagePackWriter writer); - [Fact] + [Test] public void ReadSingle_ReadIntegersOfVariousLengthsAndMagnitudes() { foreach ((System.Numerics.BigInteger value, ReadOnlySequence encoded) in this.integersOfInterest) { - this.logger.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); + Console.WriteLine("Decoding 0x{0:x} from {1}", value, MessagePackCode.ToFormatName(encoded.First.Span[0])); Assert.Equal((float)(double)value, new MessagePackReader(encoded).ReadSingle()); } } - [Fact] + [Test] public void ReadSingle_CanReadDouble() { var reader = new MessagePackReader(Encode((ref MessagePackWriter w) => w.Write(1.23))); Assert.Equal(1.23f, reader.ReadSingle()); } - [Fact] + [Test] public void ReadArrayHeader_MitigatesLargeAllocations() { var sequence = new Sequence(); @@ -56,7 +49,7 @@ public void ReadArrayHeader_MitigatesLargeAllocations() }); } - [Fact] + [Test] public void TryReadArrayHeader() { var sequence = new Sequence(); @@ -73,7 +66,7 @@ public void TryReadArrayHeader() Assert.Equal(expectedCount, actualCount); } - [Fact] + [Test] public void ReadMapHeader_MitigatesLargeAllocations() { var sequence = new Sequence(); @@ -88,7 +81,7 @@ public void ReadMapHeader_MitigatesLargeAllocations() }); } - [Fact] + [Test] public void TryReadMapHeader() { var sequence = new Sequence(); @@ -105,31 +98,31 @@ public void TryReadMapHeader() Assert.Equal(expectedCount, actualCount); } - [Fact] + [Test] public void TryReadMapHeader_Ranges() { this.AssertCodeRange((ref MessagePackReader r) => r.TryReadMapHeader(out _), c => c is >= MessagePackCode.MinFixMap and <= MessagePackCode.MaxFixMap, c => c is MessagePackCode.Map16 or MessagePackCode.Map32); } - [Fact] + [Test] public void TryReadArrayHeader_Ranges() { this.AssertCodeRange((ref MessagePackReader r) => r.TryReadArrayHeader(out _), c => c is >= MessagePackCode.MinFixArray and <= MessagePackCode.MaxFixArray, c => c is MessagePackCode.Array16 or MessagePackCode.Array32); } - [Fact] + [Test] public void TryReadString_Ranges() { this.AssertCodeRange((ref MessagePackReader r) => r.TryReadStringSpan(out _), c => c is MessagePackCode.Nil, c => c is (>= MessagePackCode.MinFixStr and <= MessagePackCode.MaxFixStr) or MessagePackCode.Str8 or MessagePackCode.Str16 or MessagePackCode.Str32); } - [Fact] + [Test] public void TryReadInt_Ranges() { this.AssertCodeRange((ref MessagePackReader r) => r.ReadInt32(), c => c is (>= MessagePackCode.MinFixInt and <= MessagePackCode.MaxFixInt) or (>= MessagePackCode.MinNegativeFixInt and <= MessagePackCode.MaxNegativeFixInt), c => c is MessagePackCode.Int64 or MessagePackCode.Int32 or MessagePackCode.Int16 or MessagePackCode.Int8 or MessagePackCode.UInt64 or MessagePackCode.UInt32 or MessagePackCode.UInt16 or MessagePackCode.UInt8); } - [Fact] + [Test] public void ReadExtensionHeader_MitigatesLargeAllocations() { var sequence = new Sequence(); @@ -148,7 +141,7 @@ public void ReadExtensionHeader_MitigatesLargeAllocations() reader.ReadExtensionHeader(); } - [Fact] + [Test] public void TryReadExtensionHeader() { var sequence = new Sequence(); @@ -165,7 +158,7 @@ public void TryReadExtensionHeader() Assert.Equal(expectedExtensionHeader, actualExtensionHeader); } - [Fact] + [Test] public void TryReadStringSpan_Fragmented() { var contiguousSequence = new Sequence(); @@ -188,7 +181,7 @@ public void TryReadStringSpan_Fragmented() Assert.Equal([1, 2, 3], actualSequence.Value.ToArray()); } - [Fact] + [Test] public void TryReadStringSpan_Contiguous() { var sequence = new Sequence(); @@ -203,7 +196,7 @@ public void TryReadStringSpan_Contiguous() Assert.True(reader.End); } - [Fact] + [Test] public void TryReadStringSpan_Nil() { var sequence = new Sequence(); @@ -217,7 +210,7 @@ public void TryReadStringSpan_Nil() Assert.Equal(sequence.AsReadOnlySequence.Start, reader.Position); } - [Fact] + [Test] public void TryReadStringSpan_WrongType() { var sequence = new Sequence(); @@ -232,7 +225,7 @@ public void TryReadStringSpan_WrongType() }); } - [Fact] + [Test] public void ReadStringSpan_Fragmented() { var contiguousSequence = new Sequence(); @@ -249,7 +242,7 @@ public void ReadStringSpan_Fragmented() Assert.Equal([1, 2, 3], span.ToArray()); } - [Fact] + [Test] public void ReadStringSpan_Contiguous() { var sequence = new Sequence(); @@ -264,7 +257,7 @@ public void ReadStringSpan_Contiguous() Assert.True(reader.End); } - [Fact] + [Test] public void ReadStringSpan_Nil() { var sequence = new Sequence(); @@ -279,7 +272,7 @@ public void ReadStringSpan_Nil() }); } - [Fact] + [Test] public void ReadStringSpan_WrongType() { var sequence = new Sequence(); @@ -294,7 +287,7 @@ public void ReadStringSpan_WrongType() }); } - [Fact] + [Test] public void ReadString_MultibyteChars() { var reader = new MessagePackReader(TestConstants.MsgPackEncodedMultibyteCharString); @@ -302,7 +295,7 @@ public void ReadString_MultibyteChars() Assert.Equal(TestConstants.MultibyteCharString, actual); } - [Fact] + [Test] public void ReadRaw() { var sequence = new Sequence(); @@ -329,7 +322,7 @@ public void ReadRaw() Assert.True(reader.End); } - [Fact] + [Test] public void Read_CheckOperations_WithNoBytesLeft() { ReadOnlySequence partialMessage = default; @@ -343,7 +336,7 @@ public void Read_CheckOperations_WithNoBytesLeft() AssertThrowsEndOfStreamException(partialMessage, (ref MessagePackReader reader) => reader.IsNil); } - [Fact] + [Test] public void Read_WithInsufficientBytesLeft() { void AssertIncomplete(WriterEncoder encoder, ReadOperation decoder, bool validMsgPack = true) @@ -390,7 +383,7 @@ void AssertIncomplete(WriterEncoder encoder, ReadOperation decoder, bool v AssertIncomplete((ref MessagePackWriter writer) => writer.Write(0xff), (ref MessagePackReader reader) => reader.ReadUInt64()); } - [Fact] + [Test] public void CreatePeekReader() { var reader = new MessagePackReader(StringEncodedAsFixStr); @@ -491,14 +484,14 @@ private void AssertCodeRange(RangeChecker predicate, Func isOneByteR if (expectedMatch != actual) { - this.logger.WriteLine($"Byte 0x{code:x2} was {actual} but was expected to be {expectedMatch}."); + Console.WriteLine($"Byte 0x{code:x2} was {actual} but was expected to be {expectedMatch}."); mismatch = true; } } catch (Exception ex) { mismatch = true; - this.logger.WriteLine($"Byte 0x{code:x2} threw an exception: {ex}"); + Console.WriteLine($"Byte 0x{code:x2} threw an exception: {ex}"); } } diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackSerializationExceptionTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackSerializationExceptionTests.cs similarity index 97% rename from test/Nerdbank.MessagePack.Tests/MessagePackSerializationExceptionTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackSerializationExceptionTests.cs index 225ffff6..388a192a 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackSerializationExceptionTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackSerializationExceptionTests.cs @@ -3,13 +3,13 @@ public class MessagePackSerializationExceptionTests { - [Fact] + [Test] public void Code_Default() { Assert.Equal(MessagePackSerializationException.ErrorCode.Unspecified, new MessagePackSerializationException().Code); } - [Fact] + [Test] public void Code_Inherited() { Assert.Equal( diff --git a/test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTestBase.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTestBase.cs index 3a75cd93..ceacc5cd 100644 --- a/test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTestBase.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTestBase.cs @@ -114,6 +114,8 @@ protected static string SchemaToString(JsonObject schema) return schemaString; } + protected void Log(string message) => Console.WriteLine(message); + protected ReadOnlySequence AssertRoundtrip(T? value) #if NET where T : IShapeable diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackSerializerTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTests.cs similarity index 92% rename from test/Nerdbank.MessagePack.Tests/MessagePackSerializerTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTests.cs index 3ad99359..cff249cb 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackSerializerTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackSerializerTests.cs @@ -17,7 +17,7 @@ public enum SomeEnum /// Verifies that properties are independent on each instance of /// of properties on other instances. /// - [Fact] + [Test] public void PropertiesAreIndependent() { this.Serializer = this.Serializer with { SerializeEnumValuesByName = true }; @@ -28,50 +28,50 @@ public void PropertiesAreIndependent() Assert.True(s2.SerializeEnumValuesByName); } - [Fact] + [Test] public void SimpleNull() => this.AssertRoundtrip(null); - [Fact] + [Test] public void SimplePoco() => this.AssertRoundtrip(new Fruit { Seeds = 18 }); - [Fact] + [Test] public void NoProperties() => this.AssertRoundtrip(new EmptyClass()); - [Fact] + [Test] public void AllIntTypes() => this.AssertRoundtrip(new IntRichPoco { Int8 = -1, Int16 = -2, Int32 = -3, Int64 = -4, UInt8 = 1, UInt16 = 2, UInt32 = 3, UInt64 = 4 }); - [Fact] + [Test] public void SimpleRecordClass() => this.AssertRoundtrip(new RecordClass(42) { Weight = 5, ChildNumber = 2 }); - [Fact] + [Test] public void ClassWithDefaultCtorWithInitProperty() => this.AssertRoundtrip(new DefaultCtorWithInitProperty { Age = 42 }); - [Fact] + [Test] public void RecordWithOtherPrimitives() => this.AssertRoundtrip(new OtherPrimitiveTypes("hello", true, 0.1f, 0.2)); - [Fact] + [Test] public void NullableStruct_Null() => this.AssertRoundtrip(new RecordWithNullableStruct(null)); - [Fact] + [Test] public void NullableStruct_NotNull() => this.AssertRoundtrip(new RecordWithNullableStruct(3)); - [Fact] + [Test] public void Dictionary() => this.AssertRoundtrip(new ClassWithDictionary { StringInt = new() { { "a", 1 }, { "b", 2 } } }); - [Fact] + [Test] public void Dictionary_Null() => this.AssertRoundtrip(new ClassWithDictionary { StringInt = null }); - [Fact] + [Test] public void ImmutableDictionary() => this.AssertRoundtrip(new ClassWithImmutableDictionary { StringInt = ImmutableDictionary.Empty.Add("a", 1) }); - [Fact] + [Test] public void Array() => this.AssertRoundtrip(new ClassWithArray { IntArray = [1, 2, 3] }); - [Fact] + [Test] public void Array_Null() => this.AssertRoundtrip(new ClassWithArray { IntArray = null }); #pragma warning disable SA1500 // Braces for multi-line statements should not share line - [Theory, PairwiseData] + [Test, MatrixDataSource] public void MultidimensionalArray(MultiDimensionalArrayFormat format) { this.Serializer = this.Serializer with { MultiDimensionalArrayFormat = format }; @@ -105,7 +105,7 @@ public void MultidimensionalArray(MultiDimensionalArrayFormat format) } #pragma warning restore SA1500 // Braces for multi-line statements should not share line - [Fact] + [Test] public void MultidimensionalArray_Null() { try @@ -118,25 +118,25 @@ public void MultidimensionalArray_Null() } } - [Fact] + [Test] public void Enumerable() => this.AssertRoundtrip(new ClassWithEnumerable { IntEnum = [1, 2, 3] }); - [Fact] + [Test] public void Enumerable_Null() => this.AssertRoundtrip(new ClassWithEnumerable { IntEnum = null }); - [Fact] + [Test] public void Enum() => this.AssertRoundtrip(new HasEnum(SomeEnum.B)); - [Fact] + [Test] public void SerializeUnannotatedViaWitness() => this.AssertRoundtrip(new UnannotatedPoco { Value = 42 }); - [Fact] + [Test] public void SerializeGraphWithAnnotationOnlyAtBase() => this.AssertRoundtrip(new ReferencesUnannotatedPoco { Poco = new UnannotatedPoco { Value = 42 } }); - [Fact] + [Test] public void PrivateFields() => this.AssertRoundtrip(new InternalRecordWithPrivateField { PrivateFieldAccessor = 42, PrivatePropertyAccessor = 43 }); - [Fact] + [Test] public void ReadOnlyPropertiesNotSerialized() { RecordWithReadOnlyProperties obj = new(1, 2); @@ -147,19 +147,19 @@ public void ReadOnlyPropertiesNotSerialized() Assert.Equal(2, reader.ReadMapHeader()); } - [Fact] + [Test] public void ReadOnlyPropertiesNotSerialized_NoCtor() { RecordWithReadOnlyProperties_NoConstructor obj = new(1, 2); - byte[] msgpack = this.Serializer.Serialize(obj, TestContext.Current.CancellationToken); - this.Logger.WriteLine(this.Serializer.ConvertToJson(msgpack)); + byte[] msgpack = this.Serializer.Serialize(obj, this.TimeoutToken); + Console.WriteLine(this.Serializer.ConvertToJson(msgpack)); MessagePackReader reader = new(msgpack); // The Sum field should not be serialized. Assert.Equal(2, reader.ReadMapHeader()); } - [Fact] + [Test] public void ReadOnlyPropertiesNotSerialized_Keyed() { RecordWithReadOnlyPropertiesKeyed obj = new(1, 2); @@ -170,13 +170,13 @@ public void ReadOnlyPropertiesNotSerialized_Keyed() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void SystemObject() { Assert.NotNull(this.Roundtrip(new object())); } - [Fact] + [Test] public async Task ReadOnlyCollectionProperties() { var testData = new ClassWithReadOnlyCollectionProperties @@ -188,7 +188,7 @@ public async Task ReadOnlyCollectionProperties() await this.AssertRoundtripAsync(testData); } - [Fact] + [Test] public async Task ReadOnlyCollectionPropertiesWithCtor() { var testData = new ClassWithReadOnlyCollectionPropertiesAndCtor(["c"]); @@ -196,7 +196,7 @@ public async Task ReadOnlyCollectionPropertiesWithCtor() await this.AssertRoundtripAsync(testData); } - [Fact] + [Test] public async Task ReadOnlyCollectionKeyedPropertiesWithCtor() { var testData = new ClassWithReadOnlyCollectionKeyedPropertiesAndCtor(["c"]); @@ -204,16 +204,16 @@ public async Task ReadOnlyCollectionKeyedPropertiesWithCtor() await this.AssertRoundtripAsync(testData); } - [Fact] + [Test] public void ReadOnlyObjectProperty_IsNotSerialized() { ClassWithReadOnlyObjectProperty obj = new() { AgeAccessor = 15 }; - byte[] msgpack = this.Serializer.Serialize(obj, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(obj, this.TimeoutToken); MessagePackReader reader = new(msgpack); Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void ReadOnlyObjectPropertyWithCtorParameter_IsSerialized() { ClassWithReadOnlyObjectPropertyAndCtorParam obj = new(15); @@ -223,12 +223,12 @@ public void ReadOnlyObjectPropertyWithCtorParameter_IsSerialized() /// /// Verifies that an unexpected nil value doesn't disturb deserializing readonly collections. /// - [Fact] + [Test] public async Task ReadOnlyCollectionProperties_Nil() { ReadOnlySequence sequence = PrepareSequence(); - this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); - await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), TestContext.Current.CancellationToken); + this.Serializer.Deserialize(sequence, this.TimeoutToken); + await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), this.TimeoutToken); Sequence PrepareSequence() { @@ -244,7 +244,7 @@ Sequence PrepareSequence() } } - [Fact] + [Test] public void PropertiesWithCaseOnlySerializedNameDifferencesMutableCanRoundtrip() { RecordWithMutablePropertiesWithSerializedNamesUniqueOnlyInCapitalization original = new() @@ -255,7 +255,7 @@ public void PropertiesWithCaseOnlySerializedNameDifferencesMutableCanRoundtrip() this.AssertRoundtrip(original); } - [Fact] + [Test] public void PropertiesWithCaseOnlySerializedNameDifferencesCanRoundtrip() { RecordWithPropertiesWithSerializedNamesUniqueOnlyInCapitalization original = new() @@ -266,14 +266,14 @@ public void PropertiesWithCaseOnlySerializedNameDifferencesCanRoundtrip() this.AssertRoundtrip(original); } - [Fact] + [Test] public void PropertiesWithCaseOnlySerializedNameDifferencesAndCtorCanRoundtrip() { RecordWithPropertiesWithSerializedNamesUniqueOnlyInCapitalizationAndCtor original = new(1, 2); this.AssertRoundtrip(original); } - [Fact] + [Test] public void ByteArraySerializedOptimally() { ReadOnlySequence msgpack = this.AssertRoundtrip([1, 2, 3]); @@ -282,7 +282,7 @@ public void ByteArraySerializedOptimally() Assert.NotNull(reader.ReadBytes()); } - [Fact] + [Test] public void ByteMemorySerializedOptimally() { Memory original = new byte[] { 1, 2, 3 }; @@ -293,7 +293,7 @@ public void ByteMemorySerializedOptimally() Assert.NotNull(reader.ReadBytes()); } - [Fact] + [Test] public void ByteReadOnlyMemorySerializedOptimally() { ReadOnlyMemory original = new byte[] { 1, 2, 3 }; @@ -304,121 +304,121 @@ public void ByteReadOnlyMemorySerializedOptimally() Assert.NotNull(reader.ReadBytes()); } - [Fact] + [Test] public void ByteArrayCanDeserializeSuboptimally() { Sequence sequence = GetByteArrayAsActualMsgPackArray(); - byte[]? result = this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); + byte[]? result = this.Serializer.Deserialize(sequence, this.TimeoutToken); Assert.NotNull(result); Assert.Equal([1, 2, 3], result); } - [Fact] + [Test] public void ByteMemoryCanDeserializeSuboptimally() { Sequence sequence = GetByteArrayAsActualMsgPackArray(); - Memory result = this.Serializer.Deserialize, Witness>(sequence, TestContext.Current.CancellationToken); + Memory result = this.Serializer.Deserialize, Witness>(sequence, this.TimeoutToken); Assert.Equal([1, 2, 3], result.ToArray()); } - [Fact] + [Test] public void ByteReadOnlyMemoryCanDeserializeSuboptimally() { Sequence sequence = GetByteArrayAsActualMsgPackArray(); - ReadOnlyMemory result = this.Serializer.Deserialize, Witness>(sequence, TestContext.Current.CancellationToken); + ReadOnlyMemory result = this.Serializer.Deserialize, Witness>(sequence, this.TimeoutToken); Assert.Equal([1, 2, 3], result.ToArray()); } - [Fact] + [Test] public void CustomConverterVsBuiltIn_TopLevel() { this.Serializer = this.Serializer with { Converters = [new CustomStringConverter()] }; - byte[] msgpack = this.Serializer.Serialize("Hello", TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize("Hello", this.TimeoutToken); this.LogMsgPack(msgpack); - Assert.Equal("HelloWR", this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)); + Assert.Equal("HelloWR", this.Serializer.Deserialize(msgpack, this.TimeoutToken)); } - [Fact] + [Test] public void CustomConverterVsBuiltIn_SubLevel() { this.Serializer = this.Serializer with { Converters = [new CustomStringConverter()] }; - byte[] msgpack = this.Serializer.Serialize(new OtherPrimitiveTypes("Hello", false, 0, 0), TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(new OtherPrimitiveTypes("Hello", false, 0, 0), this.TimeoutToken); this.LogMsgPack(msgpack); - Assert.Equal("HelloWR", this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)?.AString); + Assert.Equal("HelloWR", this.Serializer.Deserialize(msgpack, this.TimeoutToken)?.AString); } - [Fact] + [Test] public void SerializeObject_DeserializeObject() { Fruit value = new() { Seeds = 5 }; Sequence seq = new(); MessagePackWriter writer = new(seq); - this.Serializer.SerializeObject(ref writer, value, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)), TestContext.Current.CancellationToken); + this.Serializer.SerializeObject(ref writer, value, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)), this.TimeoutToken); writer.Flush(); this.LogMsgPack(seq); MessagePackReader reader = new(seq); - Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(ref reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)), TestContext.Current.CancellationToken); + Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(ref reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)), this.TimeoutToken); Assert.Equal(value, deserialized); } - [Fact] + [Test] public void SerializeObject_ByteArray() { Fruit value = new() { Seeds = 5 }; ITypeShape shape = Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)); - byte[] serialized = this.Serializer.SerializeObject(value, shape, TestContext.Current.CancellationToken); - Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(serialized, shape, TestContext.Current.CancellationToken); + byte[] serialized = this.Serializer.SerializeObject(value, shape, this.TimeoutToken); + Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(serialized, shape, this.TimeoutToken); Assert.Equal(value, deserialized); } - [Fact] + [Test] public void SerializeObject_IBufferWriter() { Fruit value = new() { Seeds = 5 }; ITypeShape shape = Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)); var bufferWriter = new Sequence(); - this.Serializer.SerializeObject(bufferWriter, value, shape, TestContext.Current.CancellationToken); - Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(bufferWriter.AsReadOnlySequence, shape, TestContext.Current.CancellationToken); + this.Serializer.SerializeObject(bufferWriter, value, shape, this.TimeoutToken); + Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(bufferWriter.AsReadOnlySequence, shape, this.TimeoutToken); Assert.Equal(value, deserialized); } - [Fact] + [Test] public void SerializeObject_Stream() { Fruit value = new() { Seeds = 5 }; ITypeShape shape = Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)); var stream = new MemoryStream(); - this.Serializer.SerializeObject(stream, value, shape, TestContext.Current.CancellationToken); + this.Serializer.SerializeObject(stream, value, shape, this.TimeoutToken); stream.Position = 0; - Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(stream, shape, TestContext.Current.CancellationToken); + Fruit? deserialized = (Fruit?)this.Serializer.DeserializeObject(stream, shape, this.TimeoutToken); Assert.Equal(value, deserialized); } - [Fact] + [Test] public async Task SerializeObjectAsync_Stream() { Fruit value = new() { Seeds = 5 }; ITypeShape shape = Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(typeof(Fruit)); var stream = new MemoryStream(); - await this.Serializer.SerializeObjectAsync(stream, value, shape, TestContext.Current.CancellationToken); + await this.Serializer.SerializeObjectAsync(stream, value, shape, this.TimeoutToken); stream.Position = 0; - Fruit? deserialized = (Fruit?)await this.Serializer.DeserializeObjectAsync(stream, shape, TestContext.Current.CancellationToken); + Fruit? deserialized = (Fruit?)await this.Serializer.DeserializeObjectAsync(stream, shape, this.TimeoutToken); Assert.Equal(value, deserialized); } - [Fact] + [Test] public void CtorParameterNameMatchesSerializedInsteadOfDeclaredName_Roundtrips() { this.AssertRoundtrip(new TypeWithConstructorParameterMatchingSerializedPropertyName(2)); } - [Fact] + [Test] public void CtorParameterNameMatchesSerializedInsteadOfDeclaredName_DefaultValueWorks() { Sequence seq = new(); @@ -427,18 +427,18 @@ public void CtorParameterNameMatchesSerializedInsteadOfDeclaredName_DefaultValue writer.Flush(); TypeWithConstructorParameterMatchingSerializedPropertyName? deserialized = - this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken); + this.Serializer.Deserialize(seq, this.TimeoutToken); Assert.NotNull(deserialized); Assert.Equal(8, deserialized.Marshaled); } - [Fact] + [Test] public void ClassWithIndexerCanBeSerialized() { this.AssertRoundtrip(new ClassWithIndexer { Member = 3 }); } - [Fact] + [Test] public void TupleSerializedAsArray() { ReadOnlySequence msgpack = this.AssertRoundtrip, Witness>(new(1, true)); @@ -446,7 +446,7 @@ public void TupleSerializedAsArray() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void ValueTupleSerializedAsArray() { ReadOnlySequence msgpack = this.AssertRoundtrip<(int, bool), Witness>(new(1, true)); @@ -454,7 +454,7 @@ public void ValueTupleSerializedAsArray() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void IImmutableList() { IImmutableList list = ImmutableList.Create(1, 2, 3); @@ -466,11 +466,11 @@ public void IImmutableList() /// /// Regression test for issue 416. /// - [Fact] + [Test] public void WriteLargeStringToStream() { string value = new string('x', 100 * 1024); - this.Serializer.Serialize(Stream.Null, value, TestContext.Current.CancellationToken); + this.Serializer.Serialize(Stream.Null, value, this.TimeoutToken); } /// @@ -480,28 +480,28 @@ public void WriteLargeStringToStream() /// Object-keys are not supported both because they leave nothing to be serialized and because they cannot be securely hashed. /// Manual verification of the logged output should confirm that the exception message is helpful. /// - [Fact] + [Test] public void ObjectKeyedCollections() { - byte[] msgpack = this.Serializer.Serialize(new Dictionary(), TestContext.Current.CancellationToken); - MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)); + byte[] msgpack = this.Serializer.Serialize(new Dictionary(), this.TimeoutToken); + MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Deserialize(msgpack, this.TimeoutToken)); NotSupportedException innerException = Assert.IsType(ex.GetBaseException()); - this.Logger.WriteLine(innerException.Message); + Console.WriteLine(innerException.Message); - msgpack = this.Serializer.Serialize, Witness>(new Dictionary(), TestContext.Current.CancellationToken); - ex = Assert.Throws(() => this.Serializer.Deserialize, Witness>(msgpack, TestContext.Current.CancellationToken)); + msgpack = this.Serializer.Serialize, Witness>(new Dictionary(), this.TimeoutToken); + ex = Assert.Throws(() => this.Serializer.Deserialize, Witness>(msgpack, this.TimeoutToken)); innerException = Assert.IsType(ex.GetBaseException()); - this.Logger.WriteLine(innerException.Message); + Console.WriteLine(innerException.Message); - msgpack = this.Serializer.Serialize, Witness>(new HashSet(), TestContext.Current.CancellationToken); - ex = Assert.Throws(() => this.Serializer.Deserialize, Witness>(msgpack, TestContext.Current.CancellationToken)); + msgpack = this.Serializer.Serialize, Witness>(new HashSet(), this.TimeoutToken); + ex = Assert.Throws(() => this.Serializer.Deserialize, Witness>(msgpack, this.TimeoutToken)); innerException = Assert.IsType(ex.GetBaseException()); - this.Logger.WriteLine(innerException.Message); + Console.WriteLine(innerException.Message); - this.Logger.WriteLine(ex.ToString()); + Console.WriteLine(ex.ToString()); } - [Fact] + [Test] public void CustomDictionaryWithCustomConverter() { HasCustomDictionary original = new(new CustomDictionary { { "a", 1 }, { "b", 2 } }); @@ -517,7 +517,7 @@ public void CustomDictionaryWithCustomConverter() Assert.Equal(2 * 2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void CustomListWithCustomConverter() { HasCustomList original = new(new CustomList { "hi" }); @@ -533,7 +533,7 @@ public void CustomListWithCustomConverter() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void CustomConverterOnParameter() { HasCustomConverterOnParameter original = new(10); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackStreamingReaderTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackStreamingReaderTests.cs similarity index 97% rename from test/Nerdbank.MessagePack.Tests/MessagePackStreamingReaderTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackStreamingReaderTests.cs index 4f091099..57901564 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackStreamingReaderTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackStreamingReaderTests.cs @@ -4,11 +4,11 @@ using System.Text; using DecodeResult = Nerdbank.MessagePack.MessagePackPrimitives.DecodeResult; -public class MessagePackStreamingReaderTests(ITestOutputHelper logger) +public class MessagePackStreamingReaderTests { private static readonly ReadOnlySequence ArrayOf3Bools = CreateMsgPackArrayOf3Bools(); - [Fact] + [Test] public void ReadIncompleteBuffer() { MessagePackStreamingReader incompleteReader = new(ArrayOf3Bools.Slice(0, 2)); @@ -19,7 +19,7 @@ public void ReadIncompleteBuffer() Assert.Equal(DecodeResult.InsufficientBuffer, incompleteReader.TryRead(out boolean)); } - [Fact] + [Test] public async Task ReplenishBufferAsync_AddsMoreBytesOnce() { // Arrange the reader to have an incomplete buffer and that upon request it will get the rest of it. @@ -42,7 +42,7 @@ public async Task ReplenishBufferAsync_AddsMoreBytesOnce() Assert.Equal(DecodeResult.InsufficientBuffer, incompleteReader.TryReadNil()); } - [Fact] + [Test] public async Task ReplenishBufferAsync_AddsMoreBytes_ThenCompletes() { // Arrange the reader to have an incomplete buffer and that upon request it will get the rest of it. @@ -68,7 +68,7 @@ public async Task ReplenishBufferAsync_AddsMoreBytes_ThenCompletes() Assert.Equal(DecodeResult.EmptyBuffer, incompleteReader.TryReadNil()); } - [Fact] + [Test] public async Task SkipIncrementally() { Sequence seq = new(); @@ -115,10 +115,10 @@ public async Task SkipIncrementally() Assert.False(boolValue); Assert.Equal(ros.End, reader.Position); - logger.WriteLine($"Fetched {fetchCount} times (for a sequence that is {ros.Length} bytes long.)"); + Console.WriteLine($"Fetched {fetchCount} times (for a sequence that is {ros.Length} bytes long.)"); } - [Fact] + [Test] public async Task TryRead_Extension() { Extension originalExtension = new(1, new byte[] { 1, 2, 3 }); @@ -142,7 +142,7 @@ public async Task TryRead_Extension() Assert.Equal(originalExtension, deserializedExtension); } - [Fact] + [Test] public async Task TryReadBinary() { byte[] originalData = [1, 2, 3]; @@ -166,7 +166,7 @@ public async Task TryReadBinary() Assert.Equal(originalData, deserializedData.ToArray()); } - [Fact] + [Test] public async Task TryRead_String() { string originalData = "hello"; @@ -190,7 +190,7 @@ public async Task TryRead_String() Assert.Equal(originalData, deserializedString); } - [Fact] + [Test] public async Task TryReadStringSequence() { string originalData = "hello"; @@ -214,7 +214,7 @@ public async Task TryReadStringSequence() Assert.Equal(originalData, Encoding.UTF8.GetString(deserializedString.ToArray())); } - [Fact] + [Test] public async Task TryReadStringSpan() { string originalData = "hello"; diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackStringTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackStringTests.cs similarity index 81% rename from test/Nerdbank.MessagePack.Tests/MessagePackStringTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackStringTests.cs index 0ba36ab7..4da3fca1 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackStringTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackStringTests.cs @@ -1,11 +1,9 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -public partial class MessagePackStringTests +public partial class MessagePackStringTests : MessagePackSerializerTestBase { - private static readonly MessagePackSerializer Serializer = new(); - - [Fact] + [Test] public void CtorAndProperties() { MessagePackString msgpackString = new("abc"); @@ -14,7 +12,7 @@ public void CtorAndProperties() Assert.Equal([MessagePackCode.MinFixStr | 3, .. "abc"u8], msgpackString.MsgPack.ToArray()); } - [Fact] + [Test] public void IsMatch_Span() { MessagePackString msgpackString = new("abc"); @@ -24,7 +22,7 @@ public void IsMatch_Span() Assert.False(msgpackString.IsMatch("def"u8)); } - [Fact] + [Test] public void IsMatch_Sequence_Contiguous() { MessagePackString msgpackString = new("abc"); @@ -34,7 +32,7 @@ public void IsMatch_Sequence_Contiguous() Assert.False(msgpackString.IsMatch(ContiguousSequence("def"u8))); } - [Fact] + [Test] public void IsMatch_Sequence_NonContiguous() { MessagePackString msgpackString = new("abc"); @@ -54,14 +52,14 @@ public void IsMatch_Sequence_NonContiguous() Assert.False(msgpackString.IsMatch(SplitSequence("def"u8, 2))); } - [Fact] + [Test] public void TryRead() { - MessagePackReader matchingReaderContiguous = new(Serializer.Serialize("abc", TestContext.Current.CancellationToken)); - MessagePackReader matchingReaderFragmented = new(SplitSequence(Serializer.Serialize("abc", TestContext.Current.CancellationToken), 2)); - MessagePackReader mismatchingReader = new(Serializer.Serialize("def", TestContext.Current.CancellationToken)); - MessagePackReader nilReader = new(Serializer.Serialize(null, TestContext.Current.CancellationToken)); - MessagePackReader intReader = new(Serializer.Serialize(3, TestContext.Current.CancellationToken)); + MessagePackReader matchingReaderContiguous = new(this.Serializer.Serialize("abc", this.TimeoutToken)); + MessagePackReader matchingReaderFragmented = new(SplitSequence(this.Serializer.Serialize("abc", this.TimeoutToken), 2)); + MessagePackReader mismatchingReader = new(this.Serializer.Serialize("def", this.TimeoutToken)); + MessagePackReader nilReader = new(this.Serializer.Serialize(null, this.TimeoutToken)); + MessagePackReader intReader = new(this.Serializer.Serialize(3, this.TimeoutToken)); MessagePackString msgpackString = new("abc"); @@ -75,7 +73,7 @@ public void TryRead() Assert.False(intReader.End); } - [Fact] + [Test] public void Equals_GetHashCode() { MessagePackString abc1 = new("abc"); diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackValueTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackValueTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/MessagePackValueTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackValueTests.cs index 8c7b4a19..59053f19 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackValueTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackValueTests.cs @@ -6,14 +6,14 @@ public class MessagePackValueTests { - [Fact] + [Test] public void StructSize() { // This test is here to ensure that the struct doesn't grow unexpectedly. Assert.Equal(24, Unsafe.SizeOf()); } - [Fact] + [Test] public void ByteConversion() { // Test normal value @@ -29,7 +29,7 @@ public void ByteConversion() Assert.Equal(byte.MaxValue, (byte)token); } - [Fact] + [Test] public void SByteConversion() { // Test normal value @@ -45,7 +45,7 @@ public void SByteConversion() Assert.Equal(sbyte.MaxValue, (sbyte)token); } - [Fact] + [Test] public void UShortConversion() { // Test normal value @@ -61,7 +61,7 @@ public void UShortConversion() Assert.Equal(ushort.MaxValue, (ushort)token); } - [Fact] + [Test] public void ShortConversion() { // Test normal value @@ -77,7 +77,7 @@ public void ShortConversion() Assert.Equal(short.MaxValue, (short)token); } - [Fact] + [Test] public void UIntConversion() { // Test normal value @@ -93,7 +93,7 @@ public void UIntConversion() Assert.Equal(uint.MaxValue, (uint)token); } - [Fact] + [Test] public void IntConversion() { // Test normal value @@ -109,7 +109,7 @@ public void IntConversion() Assert.Equal(int.MaxValue, (int)token); } - [Fact] + [Test] public void ULongConversion() { // Test normal value @@ -125,7 +125,7 @@ public void ULongConversion() Assert.Equal(ulong.MaxValue, (ulong)token); } - [Fact] + [Test] public void LongConversion() { // Test normal value @@ -141,7 +141,7 @@ public void LongConversion() Assert.Equal(long.MaxValue, (long)token); } - [Fact] + [Test] public void ByteConversion_Overflow() { // Test overflow @@ -152,7 +152,7 @@ public void ByteConversion_Overflow() Assert.Throws(() => (byte)token); } - [Fact] + [Test] public void SByteConversion_Overflow() { // Test overflow @@ -163,7 +163,7 @@ public void SByteConversion_Overflow() Assert.Throws(() => (sbyte)token); } - [Fact] + [Test] public void UShortConversion_Overflow() { // Test overflow @@ -174,7 +174,7 @@ public void UShortConversion_Overflow() Assert.Throws(() => (ushort)token); } - [Fact] + [Test] public void ShortConversion_Overflow() { // Test overflow @@ -185,7 +185,7 @@ public void ShortConversion_Overflow() Assert.Throws(() => (short)token); } - [Fact] + [Test] public void UIntConversion_Overflow() { // Test overflow @@ -196,7 +196,7 @@ public void UIntConversion_Overflow() Assert.Throws(() => (uint)token); } - [Fact] + [Test] public void IntConversion_Overflow() { // Test overflow @@ -207,7 +207,7 @@ public void IntConversion_Overflow() Assert.Throws(() => (int)token); } - [Fact] + [Test] public void ULongConversion_Overflow() { // Test overflow for ulong (only negative values can overflow) @@ -215,7 +215,7 @@ public void ULongConversion_Overflow() Assert.Throws(() => (ulong)token); } - [Fact] + [Test] public void LongConversion_Overflow() { // Since MessagePackToken uses long/ulong internally, @@ -224,7 +224,7 @@ public void LongConversion_Overflow() Assert.Throws(() => (long)token); } - [Fact] + [Test] public void BooleanConversion() { // Test normal value @@ -236,7 +236,7 @@ public void BooleanConversion() Assert.False((bool)token); } - [Fact] + [Test] public void FloatConversion() { // Test normal value @@ -270,7 +270,7 @@ public void FloatConversion() Assert.Equal(float.NegativeInfinity, (float)token); } - [Fact] + [Test] public void DoubleConversion() { // Test normal value @@ -308,7 +308,7 @@ public void DoubleConversion() Assert.Equal(double.NegativeInfinity, (double)token); } - [Fact] + [Test] public void FloatConversion_Overflow() { // Test overflow @@ -321,7 +321,7 @@ public void FloatConversion_Overflow() Assert.True(float.IsNegativeInfinity((float)token)); } - [Fact] + [Test] public void DoubleConversion_Overflow() { // There's no value larger than double in MessagePackToken @@ -330,7 +330,7 @@ public void DoubleConversion_Overflow() Assert.Throws(() => (double)token); } - [Fact] + [Test] public void StringConversion() { // Test normal value @@ -347,7 +347,7 @@ public void StringConversion() Assert.Throws(() => (string?)token); } - [Fact] + [Test] public void BinaryConversion() { // Test normal value @@ -360,7 +360,7 @@ public void BinaryConversion() Assert.Throws(() => (ReadOnlyMemory)token); } - [Fact] + [Test] public void ArrayConversion() { MessagePackValue token = new MessagePackValue[] { "Hi", "Bye" }; @@ -373,7 +373,7 @@ public void ArrayConversion() Assert.Throws(() => (ReadOnlyMemory)token); } - [Fact] + [Test] public void MapConversion() { MessagePackValue token = new Dictionary @@ -390,7 +390,7 @@ public void MapConversion() Assert.Throws(() => (ReadOnlyMemory)token); } - [Fact] + [Test] public void MapConversion_Frozen() { MessagePackValue token = new Dictionary @@ -407,7 +407,7 @@ public void MapConversion_Frozen() Assert.Throws(() => (ReadOnlyMemory)token); } - [Fact] + [Test] public void ExtensionConversion() { MessagePackValue token = new Extension(-5, (byte[])[1, 2, 3]); @@ -420,7 +420,7 @@ public void ExtensionConversion() Assert.Throws(() => (Extension)token); } - [Fact] + [Test] public void DateTimeConversion() { MessagePackValue token = new DateTime(2025, 01, 12, 1, 1, 1, DateTimeKind.Utc); @@ -433,7 +433,7 @@ public void DateTimeConversion() Assert.Throws(() => (DateTime)token); } - [Fact] + [Test] public void ToString_Tests() { Assert.Equal("null", new MessagePackValue(null).ToString()); @@ -451,7 +451,7 @@ public void ToString_Tests() Assert.Equal("01/12/2025 01:01:01", new MessagePackValue(new DateTime(2025, 01, 12, 1, 1, 1, DateTimeKind.Utc)).ToString()); } - [Fact] + [Test] public void Equality() { MessagePackValue left = 5, right = "hi"; @@ -459,7 +459,7 @@ public void Equality() Assert.NotEqual(left.GetHashCode(), right.GetHashCode()); } - [Fact] + [Test] public void GetHashCode_Shallow_Deep() { MessagePackValue v1a = new MessagePackValue[] { 1, 2, 3 }; diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackWriterExtensions.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackWriterExtensions.cs similarity index 100% rename from test/Nerdbank.MessagePack.Tests/MessagePackWriterExtensions.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackWriterExtensions.cs diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackWriterTests.cs b/test/Nerdbank.MessagePack.TUnit/MessagePackWriterTests.cs similarity index 92% rename from test/Nerdbank.MessagePack.Tests/MessagePackWriterTests.cs rename to test/Nerdbank.MessagePack.TUnit/MessagePackWriterTests.cs index 579aa66e..676bf842 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackWriterTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/MessagePackWriterTests.cs @@ -6,18 +6,11 @@ public class MessagePackWriterTests { - private readonly ITestOutputHelper logger; - - public MessagePackWriterTests(ITestOutputHelper logger) - { - this.logger = logger; - } - /// /// Verifies that /// accepts a span that came from stackalloc. /// - [Fact] + [Test] public unsafe void WriteRaw_StackAllocatedSpan() { var sequence = new Sequence(); @@ -38,7 +31,7 @@ public unsafe void WriteRaw_StackAllocatedSpan() Assert.Equal(2, written[7]); } - [Fact] + [Test] public void Write_ByteArray_null() { var sequence = new Sequence(); @@ -49,7 +42,7 @@ public void Write_ByteArray_null() Assert.True(reader.TryReadNil()); } - [Fact] + [Test] public void Write_ByteArray() { var sequence = new Sequence(); @@ -61,7 +54,7 @@ public void Write_ByteArray() Assert.Equal(buffer, reader.ReadBytes()?.ToArray()); } - [Fact] + [Test] public void Write_String_null() { var sequence = new Sequence(); @@ -72,7 +65,7 @@ public void Write_String_null() Assert.True(reader.TryReadNil()); } - [Fact] + [Test] public void Write_String() { var sequence = new Sequence(); @@ -84,7 +77,7 @@ public void Write_String() Assert.Equal(expected, reader.ReadString()); } - [Fact] + [Test] public void Write_String_MultibyteChars() { var sequence = new Sequence(); @@ -92,11 +85,11 @@ public void Write_String_MultibyteChars() writer.Write(TestConstants.MultibyteCharString); writer.Flush(); - this.logger.WriteLine("Written bytes: [{0}]", string.Join(", ", sequence.AsReadOnlySequence.ToArray().Select(b => string.Format(CultureInfo.InvariantCulture, "0x{0:x2}", b)))); + Console.WriteLine("Written bytes: [{0}]", string.Join(", ", sequence.AsReadOnlySequence.ToArray().Select(b => string.Format(CultureInfo.InvariantCulture, "0x{0:x2}", b)))); Assert.Equal(TestConstants.MsgPackEncodedMultibyteCharString.ToArray(), sequence.AsReadOnlySequence.ToArray()); } - [Fact] + [Test] public void WriteStringHeader() { var sequence = new Sequence(); @@ -110,7 +103,7 @@ public void WriteStringHeader() Assert.Equal("hello", reader.ReadString()); } - [Fact] + [Test] public void Write_MessagePackString() { MessagePackString msgpackString = new("abc"); @@ -123,7 +116,7 @@ public void Write_MessagePackString() Assert.Equal("abc", reader.ReadString()); } - [Fact] + [Test] public void WriteBinHeader() { var sequence = new Sequence(); @@ -136,7 +129,7 @@ public void WriteBinHeader() Assert.Equal(new byte[] { 1, 2, 3, 4, 5 }, reader.ReadBytes()?.ToArray()); } - [Fact] + [Test] public void WriteExtensionHeader_NegativeExtension() { var sequence = new Sequence(); @@ -155,7 +148,7 @@ public void WriteExtensionHeader_NegativeExtension() Assert.Equal(header.Length, readHeader.Length); } - [Fact] + [Test] public void TryWriteWithBuggyWriter() { Assert.Throws(() => @@ -165,7 +158,7 @@ public void TryWriteWithBuggyWriter() }); } - [Fact] + [Test] public void WriteVeryLargeData() { Sequence sequence = new(); diff --git a/test/Nerdbank.MessagePack.Tests/NamingPolicyApplicationTests.cs b/test/Nerdbank.MessagePack.TUnit/NamingPolicyApplicationTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/NamingPolicyApplicationTests.cs rename to test/Nerdbank.MessagePack.TUnit/NamingPolicyApplicationTests.cs index eecb18e5..38288e56 100644 --- a/test/Nerdbank.MessagePack.Tests/NamingPolicyApplicationTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/NamingPolicyApplicationTests.cs @@ -8,34 +8,34 @@ public NamingPolicyApplicationTests() this.Serializer = this.Serializer with { PropertyNamingPolicy = MessagePackNamingPolicy.CamelCase }; } - [Fact] + [Test] public void Roundtrip_NonDefaultCtor() => this.AssertRoundtrip(new NonDefaultCtor("hi", "bye")); - [Fact] + [Test] public void Roundtrip_DefaultCtor() => this.AssertRoundtrip(new DefaultCtor { SomeProperty = "hi", AnotherProperty = "bye" }); - [Fact] + [Test] public void Roundtrip_KeyedProperties() => this.AssertRoundtrip(new KeyedProperties { SomeProperty = "hi" }); - [Fact] + [Test] public void PolicyAppliedToInferredPropertyNames_DefaultCtor() { this.PolicyAppliedToInferredPropertyNamesHelper(new DefaultCtor { SomeProperty = "hi", AnotherProperty = "bye" }); } - [Fact] + [Test] public void PolicyAppliedToInferredPropertyNames_NonDefaultCtor() { this.PolicyAppliedToInferredPropertyNamesHelper(new NonDefaultCtor("hi", "bye")); } - [Fact] + [Test] public void PolicyNotAppliedToExplicitPropertyNames_DefaultCtor() { this.PolicyNotAppliedToExplicitPropertyNamesHelper(new DefaultCtor { SomeProperty = "hi", AnotherProperty = "bye" }); } - [Fact] + [Test] public void PolicyNotAppliedToExplicitPropertyNames_NonDefaultCtor() { this.PolicyNotAppliedToExplicitPropertyNamesHelper(new NonDefaultCtor("hi", "bye")); diff --git a/test/Nerdbank.MessagePack.TUnit/NativeAOTTests.cs b/test/Nerdbank.MessagePack.TUnit/NativeAOTTests.cs deleted file mode 100644 index fd6ab20b..00000000 --- a/test/Nerdbank.MessagePack.TUnit/NativeAOTTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Andrew Arnott. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -public partial class NativeAOTTests -{ - [Test] - public async Task FirstAOTTest() - { - Tree tree = new() - { - Fruits = [new Fruit(3), new Fruit(5)], - }; - - MessagePackSerializer serializer = new(); - - byte[] bytes = serializer.Serialize(tree); - - Console.WriteLine(serializer.ConvertToJson(bytes)); - - // synchronous deserialization - Tree deserializedTree = serializer.Deserialize(bytes)!; - Console.WriteLine($"Tree with {deserializedTree.Fruits.Count} fruit."); - - // "async" enumerating deserialization using an expression tree. - MessagePackSerializer.StreamingEnumerationOptions options = new(t => t.Fruits); - await foreach (Fruit? fruit in serializer.DeserializePathEnumerableAsync(PipeReader.Create(new(bytes)), options)) - { - Console.WriteLine($" Fruit with {fruit?.Seeds} seeds"); - } - } - - [GenerateShape] - public partial class Tree - { - public List Fruits { get; set; } = []; - } - - public partial record Fruit(int Seeds); -} diff --git a/test/Nerdbank.MessagePack.TUnit/Nerdbank.MessagePack.TUnit.csproj b/test/Nerdbank.MessagePack.TUnit/Nerdbank.MessagePack.TUnit.csproj index f693c688..db255405 100644 --- a/test/Nerdbank.MessagePack.TUnit/Nerdbank.MessagePack.TUnit.csproj +++ b/test/Nerdbank.MessagePack.TUnit/Nerdbank.MessagePack.TUnit.csproj @@ -1,9 +1,12 @@ - + + net8.0;net9.0;net10.0 Exe + false + $(DefineConstants);TUnit + true - $(TargetFrameworks);net472 $(RuntimeIdentifiers);win-x86 @@ -22,6 +25,23 @@ + + + TextTemplatingFileGenerator + MessagePackReaderTests.ReadInt.cs + + + + + + True + True + MessagePackReaderTests.ReadInt.tt + + + + + diff --git a/test/Nerdbank.MessagePack.Tests/ObjectsAsArraysTests.cs b/test/Nerdbank.MessagePack.TUnit/ObjectsAsArraysTests.cs similarity index 89% rename from test/Nerdbank.MessagePack.Tests/ObjectsAsArraysTests.cs rename to test/Nerdbank.MessagePack.TUnit/ObjectsAsArraysTests.cs index 76efa89d..94becc50 100644 --- a/test/Nerdbank.MessagePack.Tests/ObjectsAsArraysTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ObjectsAsArraysTests.cs @@ -3,7 +3,7 @@ public partial class ObjectsAsArraysTests : MessagePackSerializerTestBase { - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Person_Roundtrip(bool async) { var person = new Person { FirstName = "Andrew", LastName = "Arnott" }; @@ -17,21 +17,21 @@ public async Task Person_Roundtrip(bool async) } } - [Fact] + [Test] public void PersonWithDefaultConstructor_Roundtrip() => this.AssertRoundtrip(new PersonWithDefaultConstructor { FirstName = "Andrew", LastName = "Arnott" }); - [Fact] + [Test] public void Null() => this.AssertRoundtrip(null); - [Fact] + [Test] public void Null_DefaultCtro() => this.AssertRoundtrip(null); - [Fact] + [Test] public void Person_SerializesAsArray() { Person person = new() { FirstName = "Andrew", LastName = "Arnott" }; Sequence buffer = new(); - this.Serializer.Serialize(buffer, person, TestContext.Current.CancellationToken); + this.Serializer.Serialize(buffer, person, this.TimeoutToken); this.LogMsgPack(buffer); MessagePackReader reader = new(buffer); @@ -41,12 +41,12 @@ public void Person_SerializesAsArray() Assert.Equal("Arnott", reader.ReadString()); Assert.True(reader.End); - Person? deserialized = this.Serializer.Deserialize(buffer, TestContext.Current.CancellationToken); + Person? deserialized = this.Serializer.Deserialize(buffer, this.TimeoutToken); Assert.Equal(person, deserialized); } - [Trait("ShouldSerialize", "true")] - [Theory, PairwiseData] + [Property("ShouldSerialize", "true")] + [Test, MatrixDataSource] public async Task Person_WithoutLastName(bool async) { this.Serializer = this.Serializer with @@ -63,8 +63,8 @@ public async Task Person_WithoutLastName(bool async) Assert.Equal(1, reader.ReadArrayHeader()); } - [Trait("ShouldSerialize", "true")] - [Theory, PairwiseData] + [Property("ShouldSerialize", "true")] + [Test, MatrixDataSource] public async Task Person_WithoutFirstName(bool async) { this.Serializer = this.Serializer with @@ -81,8 +81,8 @@ public async Task Person_WithoutFirstName(bool async) Assert.Equal(1, reader.ReadMapHeader()); } - [Trait("ShouldSerialize", "true")] - [Theory, PairwiseData] + [Property("ShouldSerialize", "true")] + [Test, MatrixDataSource] public async Task Person_AllDefaultValues(bool async) { this.Serializer = this.Serializer with @@ -99,7 +99,7 @@ public async Task Person_AllDefaultValues(bool async) Assert.Equal(0, reader.ReadArrayHeader()); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Person_UnexpectedlyLongArray(bool async) { Sequence sequence = new(); @@ -112,12 +112,12 @@ public async Task Person_UnexpectedlyLongArray(bool async) writer.Flush(); Person? person = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), this.TimeoutToken) + : this.Serializer.Deserialize(sequence, this.TimeoutToken); Assert.Equal(new Person { FirstName = "A", LastName = "B" }, person); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Person_UnknownIndexesInMap(bool async) { Sequence sequence = new(); @@ -135,12 +135,12 @@ public async Task Person_UnknownIndexesInMap(bool async) writer.Flush(); Person? person = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), this.TimeoutToken) + : this.Serializer.Deserialize(sequence, this.TimeoutToken); Assert.Equal(new Person { FirstName = "A", LastName = "B" }, person); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task PersonWithDefaultConstructor_WithoutLastName(bool async) { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -153,7 +153,7 @@ public async Task PersonWithDefaultConstructor_WithoutLastName(bool async) Assert.Equal(1, reader.ReadArrayHeader()); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task PersonWithDefaultConstructor_WithoutFirstName(bool async) { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -166,11 +166,13 @@ public async Task PersonWithDefaultConstructor_WithoutFirstName(bool async) Assert.Equal(1, reader.ReadMapHeader()); } - [Trait("ShouldSerialize", "true")] - [Theory, PairwiseData] - public async Task PersonWithDefaultConstructor_AllDefaultValues( - bool async, - [CombinatorialValues(SerializeDefaultValuesPolicy.Always, SerializeDefaultValuesPolicy.Never)] SerializeDefaultValuesPolicy serializeDefaultValues) + [Property("ShouldSerialize", "true")] + [Test] + [Arguments(true, SerializeDefaultValuesPolicy.Always)] + [Arguments(false, SerializeDefaultValuesPolicy.Always)] + [Arguments(true, SerializeDefaultValuesPolicy.Never)] + [Arguments(false, SerializeDefaultValuesPolicy.Never)] + public async Task PersonWithDefaultConstructor_AllDefaultValues(bool async, SerializeDefaultValuesPolicy serializeDefaultValues) { // The most compact representation of this is a map of length 1. // Verify that this is what the converter chose, iff we're in that mode. @@ -182,7 +184,7 @@ public async Task PersonWithDefaultConstructor_AllDefaultValues( Assert.Equal(serializeDefaultValues == SerializeDefaultValuesPolicy.Always ? 3 : 0, reader.ReadArrayHeader()); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task PersonWithDefaultConstructor_UnexpectedlyLongArray(bool async) { Sequence sequence = new(); @@ -195,12 +197,12 @@ public async Task PersonWithDefaultConstructor_UnexpectedlyLongArray(bool async) writer.Flush(); PersonWithDefaultConstructor? person = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), this.TimeoutToken) + : this.Serializer.Deserialize(sequence, this.TimeoutToken); Assert.Equal(new PersonWithDefaultConstructor { FirstName = "A", LastName = "B" }, person); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task PersonWithDefaultConstructor_UnknownIndexesInMap(bool async) { Sequence sequence = new(); @@ -218,12 +220,12 @@ public async Task PersonWithDefaultConstructor_UnknownIndexesInMap(bool async) writer.Flush(); PersonWithDefaultConstructor? person = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(sequence), this.TimeoutToken) + : this.Serializer.Deserialize(sequence, this.TimeoutToken); Assert.Equal(new PersonWithDefaultConstructor { FirstName = "A", LastName = "B" }, person); } - [Fact] + [Test] public async Task AsyncAndSyncPropertyMix() { FamilyWithAsyncProperties family = new() @@ -239,8 +241,8 @@ public async Task AsyncAndSyncPropertyMix() Assert.Equal(5, reader.ReadArrayHeader()); } - [Trait("ShouldSerialize", "true")] - [Fact] + [Property("ShouldSerialize", "true")] + [Test] public async Task AsyncAndSyncPropertyMix_AsMap() { this.Serializer = this.Serializer with @@ -263,7 +265,7 @@ public async Task AsyncAndSyncPropertyMix_AsMap() Assert.Equal(1, reader.ReadMapHeader()); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task AsyncAndSyncPropertyMix_ReadMapFromNonContiguousBuffer(bool breakBeforeIndex) { this.Serializer = this.Serializer with @@ -292,7 +294,7 @@ public async Task AsyncAndSyncPropertyMix_ReadMapFromNonContiguousBuffer(bool br writer.Flush(); long positionAfterIndex = sequence.Length; - this.Serializer.Serialize(ref writer, expectedFamily.FirstChild, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, expectedFamily.FirstChild, this.TimeoutToken); writer.Flush(); this.LogMsgPack(sequence); @@ -309,12 +311,12 @@ public async Task AsyncAndSyncPropertyMix_ReadMapFromNonContiguousBuffer(bool br // Deserialize, through a pipe that lets us control the buffer segments. FragmentedPipeReader pipeReader = new(sequence, sequence.AsReadOnlySequence.GetPosition(splitPosition)); - FamilyWithAsyncProperties? family = await this.Serializer.DeserializeAsync(pipeReader, TestContext.Current.CancellationToken); + FamilyWithAsyncProperties? family = await this.Serializer.DeserializeAsync(pipeReader, this.TimeoutToken); Assert.Equal(expectedFamily, family); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task AsyncAndSyncPropertyMix_ReadMapFromNonContiguousBuffer_DefaultCtor(bool breakBeforeIndex) { FamilyWithAsyncPropertiesWithDefaultCtor expectedFamily = new() @@ -338,7 +340,7 @@ public async Task AsyncAndSyncPropertyMix_ReadMapFromNonContiguousBuffer_Default writer.Flush(); long positionAfterIndex = sequence.Length; - this.Serializer.Serialize(ref writer, expectedFamily.FirstChild, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, expectedFamily.FirstChild, this.TimeoutToken); writer.Flush(); this.LogMsgPack(sequence); @@ -355,12 +357,12 @@ public async Task AsyncAndSyncPropertyMix_ReadMapFromNonContiguousBuffer_Default // Deserialize, through a pipe that lets us control the buffer segments. FragmentedPipeReader pipeReader = new(sequence, sequence.AsReadOnlySequence.GetPosition(splitPosition)); - FamilyWithAsyncPropertiesWithDefaultCtor? family = await this.Serializer.DeserializeAsync(pipeReader, TestContext.Current.CancellationToken); + FamilyWithAsyncPropertiesWithDefaultCtor? family = await this.Serializer.DeserializeAsync(pipeReader, this.TimeoutToken); Assert.Equal(expectedFamily, family); } - [Fact] + [Test] public void PropertyGettersIgnored() { ClassWithUnserializedPropertyGetters obj = new() { Value = true }; @@ -369,17 +371,17 @@ public void PropertyGettersIgnored() Assert.Equal(1, reader.ReadArrayHeader()); } - [Fact] + [Test] public void PropertyGetterWithCtorParamAndMissingKey() { ClassWithPropertyGettersWithCtorParamAndMissingKey obj = new("hi") { Value = true }; // We expect this to throw because a qualified property is not attributed with KeyAttribute. - MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Serialize(obj, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.Message); + MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Serialize(obj, this.TimeoutToken)); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void PropertyGetterWithCtorParam() { ClassWithPropertyGettersWithCtorParam obj = new(true); diff --git a/test/Nerdbank.MessagePack.Tests/ObjectsAsMapTests.cs b/test/Nerdbank.MessagePack.TUnit/ObjectsAsMapTests.cs similarity index 90% rename from test/Nerdbank.MessagePack.Tests/ObjectsAsMapTests.cs rename to test/Nerdbank.MessagePack.TUnit/ObjectsAsMapTests.cs index 1198a523..511bf71a 100644 --- a/test/Nerdbank.MessagePack.Tests/ObjectsAsMapTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ObjectsAsMapTests.cs @@ -5,12 +5,12 @@ public partial class ObjectsAsMapTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void PropertyWithAlteredName() { Person person = new Person { FirstName = "Andrew", LastName = "Arnott" }; Sequence buffer = new(); - this.Serializer.Serialize(buffer, person, TestContext.Current.CancellationToken); + this.Serializer.Serialize(buffer, person, this.TimeoutToken); this.LogMsgPack(buffer); MessagePackReader reader = new(buffer); @@ -20,13 +20,13 @@ public void PropertyWithAlteredName() Assert.Equal("last_name", reader.ReadString()); Assert.Equal("Arnott", reader.ReadString()); - Assert.Equal(person, this.Serializer.Deserialize(buffer, TestContext.Current.CancellationToken)); + Assert.Equal(person, this.Serializer.Deserialize(buffer, this.TimeoutToken)); } - [Fact] + [Test] public void PropertyAndConstructorNameCaseMismatch() => this.AssertRoundtrip(new ClassWithConstructorParameterNameMatchTest("Andrew")); - [Fact] + [Test] public void PropertyGettersIgnored() { ClassWithUnserializedPropertyGetters obj = new() { Value = true }; @@ -35,7 +35,7 @@ public void PropertyGettersIgnored() Assert.Equal(1, reader.ReadMapHeader()); } - [Fact] + [Test] public async Task FetchRequiredBetweenPropertyAndItsSyncValue() { Sequence seq = new(); @@ -50,11 +50,11 @@ public async Task FetchRequiredBetweenPropertyAndItsSyncValue() writer.Flush(); FragmentedPipeReader reader = new(seq.AsReadOnlySequence, breakPosition); - PersonWithAge? person = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + PersonWithAge? person = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal(1, person?.Age); } - [Fact] + [Test] public async Task FetchRequiredBetweenPropertyAndItsSyncValue_DefaultCtor() { Sequence seq = new(); @@ -69,11 +69,11 @@ public async Task FetchRequiredBetweenPropertyAndItsSyncValue_DefaultCtor() writer.Flush(); FragmentedPipeReader reader = new(seq.AsReadOnlySequence, breakPosition); - PersonWithAgeDefaultCtor? person = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + PersonWithAgeDefaultCtor? person = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal(1, person?.Age); } - [Fact] + [Test] public void DeserializeLongerPropertyNameThanDeclared() { Sequence seq = new(); @@ -82,7 +82,7 @@ public void DeserializeLongerPropertyNameThanDeclared() writer.Write("VeryLongPropertyName"); writer.Write(42); writer.Flush(); - OptionalPropertyWithShortName? obj = this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken); + OptionalPropertyWithShortName? obj = this.Serializer.Deserialize(seq, this.TimeoutToken); Assert.NotNull(obj); } diff --git a/test/Nerdbank.MessagePack.Tests/OddShapeTests.cs b/test/Nerdbank.MessagePack.TUnit/OddShapeTests.cs similarity index 92% rename from test/Nerdbank.MessagePack.Tests/OddShapeTests.cs rename to test/Nerdbank.MessagePack.TUnit/OddShapeTests.cs index 37ebd644..e59a9269 100644 --- a/test/Nerdbank.MessagePack.Tests/OddShapeTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/OddShapeTests.cs @@ -12,13 +12,13 @@ public partial class OddShapeTests : MessagePackSerializerTestBase /// constructor parameters do not align with its settable properties, which is not supported by the serialization /// framework. /// - [Fact] + [Test] public void OddShapeWithParameterAndPropertyMismatch() { ClassWithParameterAndPropertyMismatch instance = new(42) { Comparer = 1 }; - MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Serialize(instance, TestContext.Current.CancellationToken)); + MessagePackSerializationException ex = Assert.Throws(() => this.Serializer.Serialize(instance, this.TimeoutToken)); NotSupportedException baseException = Assert.IsType(ex.GetBaseException()); - this.Logger.WriteLine(baseException.Message); + Console.WriteLine(baseException.Message); } [GenerateShape] diff --git a/test/Nerdbank.MessagePack.Tests/OptionalConvertersTests.cs b/test/Nerdbank.MessagePack.TUnit/OptionalConvertersTests.cs similarity index 93% rename from test/Nerdbank.MessagePack.Tests/OptionalConvertersTests.cs rename to test/Nerdbank.MessagePack.TUnit/OptionalConvertersTests.cs index f65b3f1c..20c9448e 100644 --- a/test/Nerdbank.MessagePack.Tests/OptionalConvertersTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/OptionalConvertersTests.cs @@ -3,21 +3,21 @@ public partial class OptionalConvertersTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void NullCheck() { Assert.Throws("serializer", () => OptionalConverters.WithSystemTextJsonConverters(null!)); Assert.Throws("serializer", () => OptionalConverters.WithGuidConverter(null!, OptionalConverters.GuidStringFormat.StringN)); } - [Fact] + [Test] public void DoubleAddThrows() { this.Serializer = this.Serializer.WithGuidConverter(OptionalConverters.GuidStringFormat.StringD); Assert.Throws(() => this.Serializer.WithGuidConverter(OptionalConverters.GuidStringFormat.StringN)); } - [Fact] + [Test] public void WithAssumedDateTimeKind_InvalidInputs() { // The valid inputs are tested in the BuiltInConverterTests class. @@ -26,23 +26,23 @@ public void WithAssumedDateTimeKind_InvalidInputs() Assert.Throws("kind", () => OptionalConverters.WithAssumedDateTimeKind(this.Serializer, DateTimeKind.Unspecified)); } - [Fact] + [Test] public void WithAssumedDateTimeKind_Twice() { ArgumentException ex = Assert.Throws( () => this.Serializer .WithAssumedDateTimeKind(DateTimeKind.Local) .WithAssumedDateTimeKind(DateTimeKind.Utc)); - this.Logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Fact] + [Test] public void WithHiFiDateTime_Twice() { ArgumentException ex = Assert.Throws( () => this.Serializer .WithHiFiDateTime() .WithHiFiDateTime()); - this.Logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } } diff --git a/test/Nerdbank.MessagePack.Tests/PerfOverSchemaStabilityTests.cs b/test/Nerdbank.MessagePack.TUnit/PerfOverSchemaStabilityTests.cs similarity index 96% rename from test/Nerdbank.MessagePack.Tests/PerfOverSchemaStabilityTests.cs rename to test/Nerdbank.MessagePack.TUnit/PerfOverSchemaStabilityTests.cs index 97b24a74..c5ec0fae 100644 --- a/test/Nerdbank.MessagePack.Tests/PerfOverSchemaStabilityTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/PerfOverSchemaStabilityTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -[Trait("PerfOverSchemaStability", "true")] +[Property("PerfOverSchemaStability", "true")] public partial class PerfOverSchemaStabilityTests : MessagePackSerializerTestBase { public PerfOverSchemaStabilityTests() @@ -9,7 +9,7 @@ public PerfOverSchemaStabilityTests() this.Serializer = this.Serializer with { PerfOverSchemaStability = true }; } - [Fact] + [Test] public void ObjectMapBecomesArray() { ReadOnlySequence msgpack = this.AssertRoundtrip(new RecordWithoutKeyAttributes("Andrew", 99)); @@ -17,7 +17,7 @@ public void ObjectMapBecomesArray() Assert.Equal(2, reader.ReadArrayHeader()); } - [Fact] + [Test] public void DerivedTypeIdentifierIsInt() { ReadOnlySequence msgpack = this.AssertRoundtrip(new Horse("Andrew", 99)); diff --git a/test/Nerdbank.MessagePack.Tests/PrimitivesDerializationTests.cs b/test/Nerdbank.MessagePack.TUnit/PrimitivesDerializationTests.cs similarity index 84% rename from test/Nerdbank.MessagePack.Tests/PrimitivesDerializationTests.cs rename to test/Nerdbank.MessagePack.TUnit/PrimitivesDerializationTests.cs index 120aa0e0..be6fbbb9 100644 --- a/test/Nerdbank.MessagePack.Tests/PrimitivesDerializationTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/PrimitivesDerializationTests.cs @@ -4,7 +4,15 @@ using System.Collections; using System.Numerics; -public partial class PrimitivesDerializationTests : MessagePackSerializerTestBase +#if !TUnit +using TestAttribute = Xunit.FactAttribute; +#endif + +public +#if !TUnit + abstract +#endif + partial class PrimitivesDerializationTests : MessagePackSerializerTestBase { #if NET protected static readonly ReadOnlyMemory ExpectedKeys = new object[] { "Prop1", "Prop2", "nestedArray", 45UL, -45L, "nestedObject", "decimal", "bigint", "guid", "i128", "u128" }; @@ -30,7 +38,7 @@ public partial class PrimitivesDerializationTests : MessagePackSerializerTestBas private static readonly UInt128 ExpectedUInt128 = new(15, 20); #endif - [Fact] + [Test] public void PositiveIntKeyStretching() { IDictionary deserialized = this.DeserializePrimitives(); @@ -43,7 +51,7 @@ public void PositiveIntKeyStretching() Assert.IsType(deserialized[45u]); } - [Fact] + [Test] public void NegativeIntKeyStretching() { IDictionary deserialized = this.DeserializePrimitives(); @@ -53,14 +61,14 @@ public void NegativeIntKeyStretching() Assert.IsType(deserialized[(short)-45]); } - [Fact] + [Test] public void SimpleValuesByIndex() { IDictionary deserialized = this.DeserializePrimitives(); Assert.Equal(new byte[] { 1, 2, 3 }, deserialized[45]); } - [Fact] + [Test] public void Keys() { // C# doesn't offer a way to call this method like other languages would, so we'll call it directly. @@ -68,14 +76,14 @@ public void Keys() Assert.Equal(ExpectedKeys.ToArray(), deserialized.Keys); } - [Fact] + [Test] public void ReachIntoMap() { IDictionary deserialized = this.DeserializePrimitives(); Assert.Equal("nestedValue", ((IDictionary)deserialized["nestedObject"]!)["nestedProp"]); } - [Fact] + [Test] public void IReadOnlyDictionary() { IDictionary deserialized = this.DeserializePrimitives(); @@ -104,7 +112,7 @@ public void IReadOnlyDictionary() Assert.Equal(dict.Count, dict.Values.Count()); } - [Fact] + [Test] public void IDictionaryOfKV() { IDictionary deserialized = this.DeserializePrimitives(); @@ -151,13 +159,13 @@ public void IDictionaryOfKV() Assert.Equal(dict.Count, dict.Values.Count()); } - [Fact] + [Test] public void Enumerate_Dictionary() { IDictionary deserialized = this.DeserializePrimitives(); foreach (KeyValuePair pair in deserialized) { - this.Logger.WriteLine($"{pair.Key} ({pair.Key.GetType().Name}) = {deserialized[pair.Key]}"); + this.Log($"{pair.Key} ({pair.Key.GetType().Name}) = {deserialized[pair.Key]}"); } IEnumerator enumerator = ((IEnumerable)deserialized).GetEnumerator(); @@ -170,7 +178,7 @@ public void Enumerate_Dictionary() Assert.False(enumerator.MoveNext()); } - [Fact] + [Test] public void Extension_Primitives() { IDictionary deserialized = this.DeserializePrimitives(); @@ -183,25 +191,25 @@ public void Extension_Primitives() #endif } - [Fact] + [Test] public void MissingMembers_Indexer() { IDictionary deserialized = this.DeserializePrimitives(); - this.Logger.WriteLine(Assert.Throws(() => deserialized[88]).Message); + this.Log(Assert.Throws(() => deserialized[88]).Message); } - [Fact] + [Test] public void WritingNotAllowed_Indexer() { IDictionary deserialized = this.DeserializePrimitives(); - this.Logger.WriteLine(Assert.Throws(() => deserialized["doesNotExist"] = "hi").Message); - this.Logger.WriteLine(Assert.Throws(() => deserialized["nestedObject"] = "hi").Message); + this.Log(Assert.Throws(() => deserialized["doesNotExist"] = "hi").Message); + this.Log(Assert.Throws(() => deserialized["nestedObject"] = "hi").Message); } protected virtual IDictionary DeserializePrimitives() { MessagePackReader reader = this.ConstructReader(); - object? deserialized = this.Serializer.DeserializePrimitives(ref reader, TestContext.Current.CancellationToken); + object? deserialized = this.Serializer.DeserializePrimitives(ref reader, this.TimeoutToken); Assert.NotNull(deserialized); return (IDictionary)deserialized; } @@ -216,46 +224,46 @@ protected MessagePackReader ConstructReader() MessagePackWriter writer = new(seq); writer.WriteMapHeader(ExpectedKeys.Length); writer.Write("Prop1"); - this.Serializer.Serialize(ref writer, "Value1", TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, "Value1", this.TimeoutToken); writer.Write("Prop2"); - this.Serializer.Serialize(ref writer, 42, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, 42, this.TimeoutToken); writer.Write("nestedArray"); writer.WriteArrayHeader(5); - this.Serializer.Serialize(ref writer, true, TestContext.Current.CancellationToken); - this.Serializer.Serialize(ref writer, 3.5, TestContext.Current.CancellationToken); - this.Serializer.Serialize(ref writer, new Extension(15, new byte[] { 1, 2, 3 }), TestContext.Current.CancellationToken); - this.Serializer.Serialize(ref writer, ExpectedDateTime, TestContext.Current.CancellationToken); - this.Serializer.Serialize(ref writer, ExpectedDateTimeUnspecifiedKind, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, true, this.TimeoutToken); + this.Serializer.Serialize(ref writer, 3.5, this.TimeoutToken); + this.Serializer.Serialize(ref writer, new Extension(15, new byte[] { 1, 2, 3 }), this.TimeoutToken); + this.Serializer.Serialize(ref writer, ExpectedDateTime, this.TimeoutToken); + this.Serializer.Serialize(ref writer, ExpectedDateTimeUnspecifiedKind, this.TimeoutToken); writer.Write(45); // int key for stretching tests - this.Serializer.Serialize(ref writer, (byte[])[1, 2, 3], TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, (byte[])[1, 2, 3], this.TimeoutToken); writer.Write(-45); // negative int key for stretching tests - this.Serializer.Serialize(ref writer, false, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, false, this.TimeoutToken); writer.Write("nestedObject"); writer.WriteMapHeader(1); writer.Write("nestedProp"); - this.Serializer.Serialize(ref writer, "nestedValue", TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, "nestedValue", this.TimeoutToken); writer.Write("decimal"); - this.Serializer.Serialize(ref writer, ExpectedDecimal, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, ExpectedDecimal, this.TimeoutToken); writer.Write("bigint"); - this.Serializer.Serialize(ref writer, ExpectedBigInteger, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, ExpectedBigInteger, this.TimeoutToken); writer.Write("guid"); - this.Serializer.Serialize(ref writer, ExpectedGuid, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, ExpectedGuid, this.TimeoutToken); #if NET writer.Write("i128"); - this.Serializer.Serialize(ref writer, ExpectedInt128, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, ExpectedInt128, this.TimeoutToken); writer.Write("u128"); - this.Serializer.Serialize(ref writer, ExpectedUInt128, TestContext.Current.CancellationToken); + this.Serializer.Serialize(ref writer, ExpectedUInt128, this.TimeoutToken); #endif writer.Flush(); - this.Logger.WriteLine(this.Serializer.ConvertToJson(seq)); + this.Log(this.Serializer.ConvertToJson(seq)); return new MessagePackReader(seq); } @@ -263,6 +271,7 @@ protected MessagePackReader ConstructReader() [GenerateShapeFor] [GenerateShapeFor] #endif + [GenerateShapeFor] [GenerateShapeFor] [GenerateShapeFor] [GenerateShapeFor] diff --git a/test/Nerdbank.MessagePack.Tests/RawMessagePackTests.cs b/test/Nerdbank.MessagePack.TUnit/RawMessagePackTests.cs similarity index 90% rename from test/Nerdbank.MessagePack.Tests/RawMessagePackTests.cs rename to test/Nerdbank.MessagePack.TUnit/RawMessagePackTests.cs index 74f37463..738b6ffd 100644 --- a/test/Nerdbank.MessagePack.Tests/RawMessagePackTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/RawMessagePackTests.cs @@ -3,14 +3,14 @@ public partial class RawMessagePackTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void DefaultCtor() { RawMessagePack raw = default; Assert.True(raw.MsgPack.IsEmpty); } - [Fact] + [Test] public void CtorWithSequence() { Sequence bytes = new(); @@ -19,37 +19,37 @@ public void CtorWithSequence() Assert.Equal(bytes, raw.MsgPack); } - [Fact] + [Test] public void DeferredSerialization() { DeferredData userData = new() { UserString = "Hello, World!" }; - Envelope envelope = new() { Deferred = (RawMessagePack)this.Serializer.Serialize(userData, TestContext.Current.CancellationToken) }; + Envelope envelope = new() { Deferred = (RawMessagePack)this.Serializer.Serialize(userData, this.TimeoutToken) }; Envelope? deserializedEnvelope = this.Roundtrip(envelope); Assert.NotNull(deserializedEnvelope); Assert.Equal(envelope, deserializedEnvelope); Assert.True(deserializedEnvelope.Deferred.IsOwned); - DeferredData? deserializedUserData = this.Serializer.Deserialize(deserializedEnvelope.Deferred, TestContext.Current.CancellationToken); + DeferredData? deserializedUserData = this.Serializer.Deserialize(deserializedEnvelope.Deferred, this.TimeoutToken); Assert.Equal(userData, deserializedUserData); } - [Fact] + [Test] public async Task DeferredSerializationAsync() { DeferredData userData = new() { UserString = "Hello, World!" }; - Envelope envelope = new() { Deferred = (RawMessagePack)this.Serializer.Serialize(userData, TestContext.Current.CancellationToken) }; + Envelope envelope = new() { Deferred = (RawMessagePack)this.Serializer.Serialize(userData, this.TimeoutToken) }; Envelope? deserializedEnvelope = await this.RoundtripAsync(envelope); Assert.NotNull(deserializedEnvelope); Assert.Equal(envelope, deserializedEnvelope); Assert.True(deserializedEnvelope.Deferred.IsOwned); - DeferredData? deserializedUserData = this.Serializer.Deserialize(deserializedEnvelope.Deferred, TestContext.Current.CancellationToken); + DeferredData? deserializedUserData = this.Serializer.Deserialize(deserializedEnvelope.Deferred, this.TimeoutToken); Assert.Equal(userData, deserializedUserData); } - [Fact] + [Test] public void Equality() { RawMessagePack empty1 = default; @@ -75,7 +75,7 @@ public void Equality() Assert.True(fragmentedMsgPack1.Equals(fragmentedMsgPack2)); } - [Fact] + [Test] public void ToOwned_Empty() { RawMessagePack msgpack = new(default); @@ -84,7 +84,7 @@ public void ToOwned_Empty() Assert.True(owned.IsOwned); } - [Fact] + [Test] public void ToOwned_NonEmpty() { // Verify that we consider an initial version to be borrowed. @@ -104,7 +104,7 @@ public void ToOwned_NonEmpty() Assert.Equal(owned.MsgPack, reowned.MsgPack); } - [Fact] + [Test] public void ToString_Overridden() { Assert.Equal("", default(RawMessagePack).ToString()); diff --git a/test/Nerdbank.MessagePack.Tests/ReferencePreservationTests.cs b/test/Nerdbank.MessagePack.TUnit/ReferencePreservationTests.cs similarity index 95% rename from test/Nerdbank.MessagePack.Tests/ReferencePreservationTests.cs rename to test/Nerdbank.MessagePack.TUnit/ReferencePreservationTests.cs index df4e5fc9..e9d4710e 100644 --- a/test/Nerdbank.MessagePack.Tests/ReferencePreservationTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ReferencePreservationTests.cs @@ -3,7 +3,7 @@ #pragma warning disable NBMsgPack051 // This test multi-targets -[Trait("ReferencePreservation", "true")] +[Property("ReferencePreservation", "true")] public partial class ReferencePreservationTests : MessagePackSerializerTestBase { public ReferencePreservationTests() @@ -11,7 +11,7 @@ public ReferencePreservationTests() this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.RejectCycles }; } - [Fact] + [Test] public void ObjectReferencePreservation() { object value = new(); @@ -29,8 +29,8 @@ public void ObjectReferencePreservation() Assert.NotSame(deserializedRoot.Value3, deserializedRoot.Value1); } - [Trait("AsyncSerialization", "true")] - [Fact] + [Property("AsyncSerialization", "true")] + [Test] public async Task AsyncSerialization() { CustomType o = new(); @@ -41,7 +41,7 @@ public async Task AsyncSerialization() Assert.Null(deserializedArray[2]); } - [Fact] + [Test] public void CustomConverterByAttributeSkippedByReferencePreservation() { CustomType2 value = new() { Message = "test" }; @@ -51,7 +51,7 @@ public void CustomConverterByAttributeSkippedByReferencePreservation() Assert.Same(deserializedArray[0], deserializedArray[1]); } - [Fact] + [Test] public void CustomConverterByRegistrationSkippedByReferencePreservation() { this.Serializer = this.Serializer with { Converters = [new CustomTypeConverter()] }; @@ -65,7 +65,7 @@ public void CustomConverterByRegistrationSkippedByReferencePreservation() Assert.Equal(value, deserializedArray[0]); } - [Fact] + [Test] public void CustomConverterByRegistrationSkippedByReferencePreservation_Reconfigured() { this.Serializer = this.Serializer with @@ -85,7 +85,7 @@ public void CustomConverterByRegistrationSkippedByReferencePreservation_Reconfig Assert.Equal(value, deserializedArray[0]); } - [Fact] + [Test] public void CustomConverterGetsReferencePreservingPrimitiveConverter() { string stringValue = "test"; @@ -96,7 +96,7 @@ public void CustomConverterGetsReferencePreservingPrimitiveConverter() Assert.Same(deserializedArray[0].Message, deserializedArray[1].Message); } - [Fact] + [Test] public void CustomConverterGetsReferencePreservingNonPrimitiveConverter() { CustomType inner = new() { Message = "Hi" }; @@ -108,7 +108,7 @@ public void CustomConverterGetsReferencePreservingNonPrimitiveConverter() Assert.Same(deserialized[0].Value, deserialized[1].Value); } - [Fact] + [Test] public void StringReferencePreservation() { string city = "New York"; @@ -128,7 +128,7 @@ public void StringReferencePreservation() Assert.Same(deserializedRoot.City, deserializedRoot.State); } - [Fact] + [Test] public void DictionaryReferencePreservation() { Dictionary dict = new() { ["a"] = 1, ["b"] = 2 }; @@ -137,7 +137,7 @@ public void DictionaryReferencePreservation() Assert.Same(deserializedArray[0], deserializedArray[1]); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public void ReferenceConsolidationWhenInterningIsOn(bool interning) { this.Serializer = this.Serializer with { InternStrings = interning }; @@ -167,7 +167,7 @@ public void ReferenceConsolidationWhenInterningIsOn(bool interning) /// This is important because the two objects with equal value in the object graph before serialization could me mutated independently. /// A round-trip through serialization should not combine these into a single reference or mutation of one would affect its appearance elsewhere in the graph. /// - [Fact] + [Test] public void ReferenceDistinctionBetweenEquivalentValuesIsPreserved() { CustomType2[] array = [new() { Message = "test" }, new() { Message = "test" }]; @@ -179,7 +179,7 @@ public void ReferenceDistinctionBetweenEquivalentValuesIsPreserved() /// /// Verifies that the extension type code used for object references can be customized. /// - [Fact] + [Test] public void CustomExtensionTypeCode() { this.Serializer = this.Serializer with @@ -193,7 +193,7 @@ public void CustomExtensionTypeCode() object value = new(); RecordWithObjects root = new() { Value1 = value, Value2 = value }; Sequence sequence = new(); - this.Serializer.Serialize(sequence, root, TestContext.Current.CancellationToken); + this.Serializer.Serialize(sequence, root, this.TimeoutToken); this.LogMsgPack(sequence); MessagePackReader reader = new(sequence); @@ -203,12 +203,12 @@ public void CustomExtensionTypeCode() reader.Skip(this.Serializer.StartingContext); // Value2 name Assert.Equal(100, reader.ReadExtensionHeader().TypeCode); - RecordWithObjects? deserializedRoot = this.Serializer.Deserialize(sequence, TestContext.Current.CancellationToken); + RecordWithObjects? deserializedRoot = this.Serializer.Deserialize(sequence, this.TimeoutToken); Assert.NotNull(deserializedRoot); Assert.Same(deserializedRoot.Value1, deserializedRoot.Value2); } - [Fact] + [Test] public void DerivedTypeShapes_StaticRegistration() { BaseRecord baseInstance = new BaseRecord(); @@ -224,11 +224,15 @@ public void DerivedTypeShapes_StaticRegistration() Assert.Same(deserialized[2], deserialized[3]); } - [Fact] + [Test] public void DerivedTypeShapes_DynamicRegistration() { DerivedShapeMapping mapping = new DerivedShapeMapping(); +#if NET + mapping.Add(1); +#else mapping.AddSourceGenerated(1); +#endif this.Serializer = this.Serializer with { DerivedTypeUnions = [mapping] }; BaseRecord baseInstance = new BaseRecord(); @@ -244,7 +248,7 @@ public void DerivedTypeShapes_DynamicRegistration() Assert.Same(deserialized[2], deserialized[3]); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_Rejected_DuringSerialization(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.RejectCycles }; @@ -253,37 +257,37 @@ public async Task CyclicReference_Rejected_DuringSerialization(bool async) if (async) { - await Assert.ThrowsAsync(async () => await this.Serializer.SerializeAsync(Stream.Null, first, TestContext.Current.CancellationToken)); + await Assert.ThrowsAsync(async () => await this.Serializer.SerializeAsync(Stream.Null, first, this.TimeoutToken)); } else { - Assert.Throws(() => this.Serializer.Serialize(first, TestContext.Current.CancellationToken)); + Assert.Throws(() => this.Serializer.Serialize(first, this.TimeoutToken)); } } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_Rejected_DuringDeserialization(bool async) { // First, compose a msgpack buffer that contains cycles. this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; SinglyLinkedListNode first = new(); first.Next = first; - byte[] msgpack = this.Serializer.Serialize(first, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(first, this.TimeoutToken); // Now reconfigure the serializer to reject cycles and attempt to deserialize. this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.RejectCycles }; if (async) { - await Assert.ThrowsAsync(async () => await this.Serializer.DeserializeAsync(PipeReader.Create(new(msgpack)), TestContext.Current.CancellationToken)); + await Assert.ThrowsAsync(async () => await this.Serializer.DeserializeAsync(PipeReader.Create(new(msgpack)), this.TimeoutToken)); } else { - Assert.Throws(() => this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)); + Assert.Throws(() => this.Serializer.Deserialize(msgpack, this.TimeoutToken)); } } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_ReferenceSelf(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -294,7 +298,7 @@ public async Task CyclicReference_ReferenceSelf(bool async) Assert.Same(deserializedRoot, deserializedRoot.Next); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_Minimal(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -308,7 +312,7 @@ public async Task CyclicReference_Minimal(bool async) Assert.Same(deserializedRoot, deserializedRoot.Next?.Next); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_Minimal_WithKeys(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -322,7 +326,7 @@ public async Task CyclicReference_Minimal_WithKeys(bool async) Assert.Same(deserializedRoot, deserializedRoot.Next?.Next); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_Multistep(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -338,7 +342,7 @@ public async Task CyclicReference_Multistep(bool async) Assert.Same(deserializedRoot, deserializedRoot.Next?.Next?.Next); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_OrderRequirementSatisfied(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -353,7 +357,7 @@ public async Task CyclicReference_OrderRequirementSatisfied(bool async) Assert.Same(deserializedRoot, deserializedRoot.Second?.First); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_OrderRequirementNotSatisfied(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -382,7 +386,7 @@ public async Task CyclicReference_OrderRequirementNotSatisfied(bool async) ////Assert.Same(deserializedRoot, deserializedRoot.First.Second); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_DoublyLinkedList(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -414,7 +418,7 @@ public async Task CyclicReference_DoublyLinkedList(bool async) Assert.Same(b, c.Previous); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_InvolvingStruct(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -427,7 +431,7 @@ public async Task CyclicReference_InvolvingStruct(bool async) Assert.Same(deserialized, deserialized.Struct.Object); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_ManyTypes(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; @@ -453,7 +457,7 @@ public async Task CyclicReference_ManyTypes(bool async) Assert.Same(deserialized, deserialized.Optional?.Item1); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task CyclicReference_Union(bool async) { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.AllowCycles }; diff --git a/test/Nerdbank.MessagePack.Tests/SecureKeyCollectionsTests.cs b/test/Nerdbank.MessagePack.TUnit/SecureKeyCollectionsTests.cs similarity index 78% rename from test/Nerdbank.MessagePack.Tests/SecureKeyCollectionsTests.cs rename to test/Nerdbank.MessagePack.TUnit/SecureKeyCollectionsTests.cs index 2fc70328..3e4a142f 100644 --- a/test/Nerdbank.MessagePack.Tests/SecureKeyCollectionsTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/SecureKeyCollectionsTests.cs @@ -3,7 +3,7 @@ public partial class SecureKeyCollectionsTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void CanSerializeDictionariesWithEmptyKeys_ButNotDeserialize() { MessagePackSerializer serializer = new MessagePackSerializer().WithObjectConverter(); @@ -14,19 +14,19 @@ public void CanSerializeDictionariesWithEmptyKeys_ButNotDeserialize() // Serialization should succeed because although we cannot create an equality comparer, // that only limits our ability to deserialize, not serialize. - byte[] payload = serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] payload = serializer.Serialize(container, this.TimeoutToken); // Deserialization should fail because the FilterKey type has an 'object' property which is not supported. - MessagePackSerializationException ex = Assert.Throws(() => serializer.Deserialize(payload, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.ToString()); + MessagePackSerializationException ex = Assert.Throws(() => serializer.Deserialize(payload, this.TimeoutToken)); + Console.WriteLine(ex.ToString()); Assert.IsType(ex.GetBaseException()); // Deserialization with primitives should work fine though. MessagePackReader reader = new(payload); - Assert.NotNull(serializer.DeserializePrimitives(ref reader, TestContext.Current.CancellationToken)); + Assert.NotNull(serializer.DeserializePrimitives(ref reader, this.TimeoutToken)); } - [Fact] + [Test] public void CanSerializeSetsWithEmptyKeys_ButNotDeserialize() { MessagePackSerializer serializer = new MessagePackSerializer().WithObjectConverter(); @@ -37,19 +37,19 @@ public void CanSerializeSetsWithEmptyKeys_ButNotDeserialize() // Serialization should succeed because although we cannot create an equality comparer, // that only limits our ability to deserialize, not serialize. - byte[] payload = serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] payload = serializer.Serialize(container, this.TimeoutToken); // Deserialization should fail because the FilterKey type has an 'object' property which is not supported. - MessagePackSerializationException ex = Assert.Throws(() => serializer.Deserialize(payload, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.ToString()); + MessagePackSerializationException ex = Assert.Throws(() => serializer.Deserialize(payload, this.TimeoutToken)); + Console.WriteLine(ex.ToString()); Assert.IsType(ex.GetBaseException()); // Deserialization with primitives should work fine though. MessagePackReader reader = new(payload); - Assert.NotNull(serializer.DeserializePrimitives(ref reader, TestContext.Current.CancellationToken)); + Assert.NotNull(serializer.DeserializePrimitives(ref reader, this.TimeoutToken)); } - [Fact] + [Test] public void CanSerializeDictionariesWithEmptyKeys_AndDeserializeWithGetterOnlyCollection() { MessagePackSerializer serializer = new MessagePackSerializer().WithObjectConverter(); @@ -57,18 +57,18 @@ public void CanSerializeDictionariesWithEmptyKeys_AndDeserializeWithGetterOnlyCo // Serialization should succeed because although we cannot create an equality comparer, // that only limits our ability to deserialize, not serialize. - byte[] payload = serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] payload = serializer.Serialize(container, this.TimeoutToken); // Deserialization should also succeed because we never have to or get to initialize the keyed collection ourselves. - HasDictionaryWithIndirectObjectKeyGetterOnly? deserialized = serializer.Deserialize(payload, TestContext.Current.CancellationToken); + HasDictionaryWithIndirectObjectKeyGetterOnly? deserialized = serializer.Deserialize(payload, this.TimeoutToken); Assert.NotNull(deserialized); // Deserialization with primitives should work fine too. MessagePackReader reader = new(payload); - Assert.NotNull(serializer.DeserializePrimitives(ref reader, TestContext.Current.CancellationToken)); + Assert.NotNull(serializer.DeserializePrimitives(ref reader, this.TimeoutToken)); } - [Fact] + [Test] public void CanSerializeSetsWithEmptyKeys_AndDeserializeWithGetterOnlyCollection() { MessagePackSerializer serializer = new MessagePackSerializer().WithObjectConverter(); @@ -76,15 +76,15 @@ public void CanSerializeSetsWithEmptyKeys_AndDeserializeWithGetterOnlyCollection // Serialization should succeed because although we cannot create an equality comparer, // that only limits our ability to deserialize, not serialize. - byte[] payload = serializer.Serialize(container, TestContext.Current.CancellationToken); + byte[] payload = serializer.Serialize(container, this.TimeoutToken); // Deserialization should also succeed because we never have to or get to initialize the keyed collection ourselves. - HasHashSetWithIndirectObjectKeyGetterOnly? deserialized = serializer.Deserialize(payload, TestContext.Current.CancellationToken); + HasHashSetWithIndirectObjectKeyGetterOnly? deserialized = serializer.Deserialize(payload, this.TimeoutToken); Assert.NotNull(deserialized); // Deserialization with primitives should work fine too. MessagePackReader reader = new(payload); - Assert.NotNull(serializer.DeserializePrimitives(ref reader, TestContext.Current.CancellationToken)); + Assert.NotNull(serializer.DeserializePrimitives(ref reader, this.TimeoutToken)); } [GenerateShape] diff --git a/test/Nerdbank.MessagePack.Tests/SecurityTests.cs b/test/Nerdbank.MessagePack.TUnit/SecurityTests.cs similarity index 84% rename from test/Nerdbank.MessagePack.Tests/SecurityTests.cs rename to test/Nerdbank.MessagePack.TUnit/SecurityTests.cs index 2ee97c55..8815b3ab 100644 --- a/test/Nerdbank.MessagePack.Tests/SecurityTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/SecurityTests.cs @@ -8,7 +8,7 @@ public partial class SecurityTests : MessagePackSerializerTestBase /// /// Verifies that the serializer will guard against stack overflow attacks for map-formatted objects. /// - [Fact] + [Test] public void StackGuard_ObjectMap_Serialize() { // Prepare a very deep structure, designed to blow the stack. @@ -16,13 +16,13 @@ public void StackGuard_ObjectMap_Serialize() // Try serializing that structure. This should throw for security reasons. Sequence buffer = new(); - Assert.Throws(() => this.Serializer.Serialize(buffer, outer, TestContext.Current.CancellationToken)); + Assert.Throws(() => this.Serializer.Serialize(buffer, outer, this.TimeoutToken)); } /// /// Verifies that the serializer will allow depths within the prescribed limit. /// - [Fact] + [Test] public void StackGuard_ObjectMap_Serialize_WithinLimit() { // Prepare a very deep structure, designed to blow the stack. @@ -30,36 +30,36 @@ public void StackGuard_ObjectMap_Serialize_WithinLimit() // Try serializing that structure. This should throw for security reasons. Sequence buffer = new(); - this.Serializer.Serialize(buffer, outer, TestContext.Current.CancellationToken); + this.Serializer.Serialize(buffer, outer, this.TimeoutToken); } /// /// Verifies that the deserializer will guard against stack overflow attacks for map-formatted objects. /// - [Fact] + [Test] public void StackGuard_ObjectMap_Deserialize() { // Prepare a very deep structure, designed to blow the stack. ReadOnlySequence buffer = this.FormatDeepMsgPackMap(this.Serializer.StartingContext.MaxDepth + 1); // Try deserializing that structure. This should throw for security reasons. - Assert.Throws(() => this.Serializer.Deserialize(buffer, TestContext.Current.CancellationToken)); + Assert.Throws(() => this.Serializer.Deserialize(buffer, this.TimeoutToken)); } /// /// Verifies that the deserializer will allow depths within the prescribed limit. /// - [Fact] + [Test] public void StackGuard_ObjectMap_Deserialize_WithinLimit() { // Prepare a very deep structure, designed to blow the stack. ReadOnlySequence buffer = this.FormatDeepMsgPackMap(this.Serializer.StartingContext.MaxDepth); // Try deserializing that structure. This should throw for security reasons. - this.Serializer.Deserialize(buffer, TestContext.Current.CancellationToken); + this.Serializer.Deserialize(buffer, this.TimeoutToken); } - [Fact] + [Test] public void ManualHashCollisionResistance() { // This doesn't really test for hash collision resistance directly. @@ -71,7 +71,7 @@ public void ManualHashCollisionResistance() }); } - [Fact] + [Test] public void ComparerProvider_CanBeOverridden() { this.Serializer = this.Serializer with { ComparerProvider = null }; @@ -86,10 +86,10 @@ public void ComparerProvider_CanBeOverridden() KeyedCollections? deserializedData = this.Roundtrip(testData); Assert.NotNull(deserializedData); - this.Logger.WriteLine(deserializedData.StringSet.Comparer.GetType().FullName!); - this.Logger.WriteLine(deserializedData.StringDictionary.Comparer.GetType().FullName!); - this.Logger.WriteLine(deserializedData.FruitSet.Comparer.GetType().FullName!); - this.Logger.WriteLine(deserializedData.FruitDictionary.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.StringSet.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.StringDictionary.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.FruitSet.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.FruitDictionary.Comparer.GetType().FullName!); Assert.Equal(EqualityComparer.Default, deserializedData.StringSet.Comparer); Assert.Equal(EqualityComparer.Default, deserializedData.StringDictionary.Comparer); @@ -100,7 +100,7 @@ public void ComparerProvider_CanBeOverridden() /// /// Verifies that the dictionaries created by the deserializer use collision resistant key hashes. /// - [Fact] + [Test] public void ComparerProvider_CollisionResistantDefault() { KeyedCollections testData = new() @@ -113,10 +113,10 @@ public void ComparerProvider_CollisionResistantDefault() KeyedCollections? deserializedData = this.Roundtrip(testData); Assert.NotNull(deserializedData); - this.Logger.WriteLine(deserializedData.StringSet.Comparer.GetType().FullName!); - this.Logger.WriteLine(deserializedData.StringDictionary.Comparer.GetType().FullName!); - this.Logger.WriteLine(deserializedData.FruitSet.Comparer.GetType().FullName!); - this.Logger.WriteLine(deserializedData.FruitDictionary.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.StringSet.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.StringDictionary.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.FruitSet.Comparer.GetType().FullName!); + Console.WriteLine(deserializedData.FruitDictionary.Comparer.GetType().FullName!); Assert.NotEqual(EqualityComparer.Default, deserializedData.StringSet.Comparer); Assert.NotEqual(EqualityComparer.Default, deserializedData.StringDictionary.Comparer); @@ -124,7 +124,7 @@ public void ComparerProvider_CollisionResistantDefault() Assert.NotEqual(EqualityComparer.Default, deserializedData.FruitDictionary.Comparer); } - [Fact] + [Test] public void DeserializerThrowsOnKeyCollisions() { // This test is designed to ensure that the deserializer throws an exception when it encounters a key collision. @@ -139,8 +139,8 @@ public void DeserializerThrowsOnKeyCollisions() writer.Write("value2"); writer.Flush(); MessagePackSerializationException ex = Assert.Throws( - () => this.Serializer.Deserialize, Witness>(seq, TestContext.Current.CancellationToken)); - this.Logger.WriteLine(ex.GetBaseException().Message); + () => this.Serializer.Deserialize, Witness>(seq, this.TimeoutToken)); + Console.WriteLine(ex.GetBaseException().Message); } private Nested ConstructDeepObjectGraph(int depth) diff --git a/test/Nerdbank.MessagePack.Tests/SerializationCallbackTests.cs b/test/Nerdbank.MessagePack.TUnit/SerializationCallbackTests.cs similarity index 85% rename from test/Nerdbank.MessagePack.Tests/SerializationCallbackTests.cs rename to test/Nerdbank.MessagePack.TUnit/SerializationCallbackTests.cs index 902e7fa0..140a4f6a 100644 --- a/test/Nerdbank.MessagePack.Tests/SerializationCallbackTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/SerializationCallbackTests.cs @@ -8,16 +8,16 @@ public partial class SerializationCallbackTests : MessagePackSerializerTestBase private readonly BusyClassArray objectAsArray = new() { Name = "Alice" }; private readonly BusyClassMap objectAsMap = new() { Name = "Alice" }; - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Serialize_ObjectAsArray(bool async) { if (async) { - await this.Serializer.SerializeAsync(Stream.Null, this.objectAsArray, TestContext.Current.CancellationToken); + await this.Serializer.SerializeAsync(Stream.Null, this.objectAsArray, this.TimeoutToken); } else { - this.Serializer.Serialize(this.objectAsArray, TestContext.Current.CancellationToken); + this.Serializer.Serialize(this.objectAsArray, this.TimeoutToken); } Assert.Equal(1, this.objectAsArray.OnBeforeSerializeCounter); @@ -26,16 +26,16 @@ public async Task Serialize_ObjectAsArray(bool async) Assert.Equal(0, this.objectAsArray.OnAfterDeserializeCounter); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Serialize_ObjectAsMap(bool async) { if (async) { - await this.Serializer.SerializeAsync(Stream.Null, this.objectAsMap, TestContext.Current.CancellationToken); + await this.Serializer.SerializeAsync(Stream.Null, this.objectAsMap, this.TimeoutToken); } else { - this.Serializer.Serialize(this.objectAsMap, TestContext.Current.CancellationToken); + this.Serializer.Serialize(this.objectAsMap, this.TimeoutToken); } Assert.Equal(1, this.objectAsMap.OnBeforeSerializeCounter); @@ -44,12 +44,12 @@ public async Task Serialize_ObjectAsMap(bool async) Assert.Equal(0, this.objectAsMap.OnAfterDeserializeCounter); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Deserialize_ObjectAsArray(bool async) { BusyClassArray? obj = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsArrayMsgPack)), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(ObjectAsArrayMsgPack, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsArrayMsgPack)), this.TimeoutToken) + : this.Serializer.Deserialize(ObjectAsArrayMsgPack, this.TimeoutToken); Assert.NotNull(obj); Assert.Equal(0, obj.OnBeforeSerializeCounter); @@ -58,12 +58,12 @@ public async Task Deserialize_ObjectAsArray(bool async) Assert.Equal(1, obj.OnAfterDeserializeCounter); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Deserialize_ObjectAsMap(bool async) { BusyClassMap? obj = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsMapMsgPack)), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(ObjectAsMapMsgPack, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsMapMsgPack)), this.TimeoutToken) + : this.Serializer.Deserialize(ObjectAsMapMsgPack, this.TimeoutToken); Assert.NotNull(obj); Assert.Equal(0, obj.OnBeforeSerializeCounter); @@ -72,12 +72,12 @@ public async Task Deserialize_ObjectAsMap(bool async) Assert.Equal(1, obj.OnAfterDeserializeCounter); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Deserialize_ObjectAsArray_Init(bool async) { BusyClassArray? obj = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsArrayMsgPack)), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(ObjectAsArrayMsgPack, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsArrayMsgPack)), this.TimeoutToken) + : this.Serializer.Deserialize(ObjectAsArrayMsgPack, this.TimeoutToken); Assert.NotNull(obj); Assert.Equal(0, obj.OnBeforeSerializeCounter); @@ -86,12 +86,12 @@ public async Task Deserialize_ObjectAsArray_Init(bool async) Assert.Equal(1, obj.OnAfterDeserializeCounter); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task Deserialize_ObjectAsMap_Init(bool async) { BusyClassMap? obj = async - ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsMapMsgPack)), TestContext.Current.CancellationToken) - : this.Serializer.Deserialize(ObjectAsMapMsgPack, TestContext.Current.CancellationToken); + ? await this.Serializer.DeserializeAsync(PipeReader.Create(new(ObjectAsMapMsgPack)), this.TimeoutToken) + : this.Serializer.Deserialize(ObjectAsMapMsgPack, this.TimeoutToken); Assert.NotNull(obj); Assert.Equal(0, obj.OnBeforeSerializeCounter); diff --git a/test/Nerdbank.MessagePack.Tests/SerializationContextTests.cs b/test/Nerdbank.MessagePack.TUnit/SerializationContextTests.cs similarity index 97% rename from test/Nerdbank.MessagePack.Tests/SerializationContextTests.cs rename to test/Nerdbank.MessagePack.TUnit/SerializationContextTests.cs index aaa6e4f6..a56b04d9 100644 --- a/test/Nerdbank.MessagePack.Tests/SerializationContextTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/SerializationContextTests.cs @@ -10,14 +10,14 @@ public partial class SerializationContextTests /// /// Verifies that the method throws when not within a serialization operation. /// - [Fact] + [Test] public void GetConverterThrows() { SerializationContext context = new(); Assert.Throws(() => context.GetConverter()); } - [Fact] + [Test] public void DepthStep_ThrowsOnCancellation() { CancellationTokenSource cts = new(); @@ -27,7 +27,7 @@ public void DepthStep_ThrowsOnCancellation() Assert.Throws(context.DepthStep); } - [Fact] + [Test] public void DepthStep_ThrowsOnStackDepth() { SerializationContext context = new() { MaxDepth = 2 }; @@ -36,7 +36,7 @@ public void DepthStep_ThrowsOnStackDepth() Assert.Throws(context.DepthStep); } - [Fact] + [Test] public void StateDictionary_Add_Remove() { SerializationContext context = new() @@ -50,14 +50,14 @@ public void StateDictionary_Add_Remove() Assert.Null(context["first"]); } - [Fact] + [Test] public void StateDictionary_NonExistent() { SerializationContext context = new(); Assert.Null(context["DOESnotEXIST"]); } - [Fact] + [Test] public void StateDictionary_PersistentCollection() { SerializationContext original = new() diff --git a/test/Nerdbank.MessagePack.Tests/SerializationRejectsFunctionsTests.cs b/test/Nerdbank.MessagePack.TUnit/SerializationRejectsFunctionsTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/SerializationRejectsFunctionsTests.cs rename to test/Nerdbank.MessagePack.TUnit/SerializationRejectsFunctionsTests.cs index 31fa533b..f7180acd 100644 --- a/test/Nerdbank.MessagePack.Tests/SerializationRejectsFunctionsTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/SerializationRejectsFunctionsTests.cs @@ -3,7 +3,7 @@ public partial class SerializationRejectsFunctionsTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void UnserializedDelegateTypesDoNotBreakSerialization() { this.AssertRoundtrip(new TypeWithUnserializedPropertyWithFunctionProperty { SimpleProperty = 42 }); diff --git a/test/Nerdbank.MessagePack.Tests/SharedTestTypes.cs b/test/Nerdbank.MessagePack.TUnit/SharedTestTypes.cs similarity index 100% rename from test/Nerdbank.MessagePack.Tests/SharedTestTypes.cs rename to test/Nerdbank.MessagePack.TUnit/SharedTestTypes.cs diff --git a/test/Nerdbank.MessagePack.Tests/ShouldSerializeTests.cs b/test/Nerdbank.MessagePack.TUnit/ShouldSerializeTests.cs similarity index 94% rename from test/Nerdbank.MessagePack.Tests/ShouldSerializeTests.cs rename to test/Nerdbank.MessagePack.TUnit/ShouldSerializeTests.cs index 0aea60e3..61d4eb93 100644 --- a/test/Nerdbank.MessagePack.Tests/ShouldSerializeTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/ShouldSerializeTests.cs @@ -3,7 +3,7 @@ using System.ComponentModel; -[Trait("ShouldSerialize", "true")] +[Property("ShouldSerialize", "true")] public partial class ShouldSerializeTests : MessagePackSerializerTestBase { public ShouldSerializeTests() @@ -29,7 +29,7 @@ public static IEnumerable AllPolicies } } - [Fact] + [Test] public void Person_AllDefaults() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -40,7 +40,7 @@ public void Person_AllDefaults() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public async Task Person_AllDefaultsAsync() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -51,7 +51,7 @@ public async Task Person_AllDefaultsAsync() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void PersonWithPrimaryConstructor_AllDefaultsByType() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Never }; @@ -64,7 +64,7 @@ public void PersonWithPrimaryConstructor_AllDefaultsByType() Assert.True(reader.TryReadNil()); } - [Fact] + [Test] public void PersonWithPrimaryConstructor_AllDefaultsByExplicitDefault() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Never }; @@ -75,7 +75,7 @@ public void PersonWithPrimaryConstructor_AllDefaultsByExplicitDefault() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void SerializeDefaultValues() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Always }; @@ -86,7 +86,7 @@ public void SerializeDefaultValues() Assert.Equal(Person.PropertyCount, reader.ReadMapHeader()); } - [Fact] + [Test] public void PersonWithName() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -98,7 +98,7 @@ public void PersonWithName() Assert.Equal(nameof(Person.Name), reader.ReadString()); } - [Fact] + [Test] public void PersonWithAge() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -110,7 +110,7 @@ public void PersonWithAge() Assert.Equal(nameof(Person.Age), reader.ReadString()); } - [Fact] + [Test] public void Person_DifferentFavoriteColor() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -122,7 +122,7 @@ public void Person_DifferentFavoriteColor() Assert.Equal(nameof(Person.FavoriteColor), reader.ReadString()); } - [Fact] + [Test] public void PersonWithPrimaryConstructor_DifferentFavoriteColor() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Never }; @@ -133,7 +133,7 @@ public void PersonWithPrimaryConstructor_DifferentFavoriteColor() Assert.Equal(nameof(Person.FavoriteColor), reader.ReadString()); } - [Fact] + [Test] public void Person_NoFavoriteColor() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -145,7 +145,7 @@ public void Person_NoFavoriteColor() Assert.True(reader.TryReadNil()); } - [Fact] + [Test] public void PersonWithPrimaryConstructor_NoFavoriteColor() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Never }; @@ -157,7 +157,7 @@ public void PersonWithPrimaryConstructor_NoFavoriteColor() Assert.True(reader.TryReadNil()); } - [Fact] + [Test] public void RenamedPropertyMatchedWithCtorDefaultParameter_AllDefaults() { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -169,7 +169,7 @@ public void RenamedPropertyMatchedWithCtorDefaultParameter_AllDefaults() Assert.Equal(0, reader.ReadMapHeader()); } - [Fact] + [Test] public void RenamedPropertyMatchedWithCtorDefaultParameter_ChangedName() { CtorWithRenamedProperty obj = new("Gal"); @@ -179,7 +179,7 @@ public void RenamedPropertyMatchedWithCtorDefaultParameter_ChangedName() Assert.Equal(1, reader.ReadMapHeader()); } - [Fact] + [Test] public void RenamedPropertyMatchedWithCtorDefaultParameter_NullName() { CtorWithRenamedProperty obj = new(null); @@ -189,9 +189,8 @@ public void RenamedPropertyMatchedWithCtorDefaultParameter_NullName() Assert.Equal(1, reader.ReadMapHeader()); } - [Theory] - [PairwiseData] - public void Flags_OnMembersOfAllKinds([CombinatorialMemberData(nameof(AllPolicies))] SerializeDefaultValuesPolicy policy) + [Test, MethodDataSource(nameof(AllPolicies))] + public void Flags_OnMembersOfAllKinds(SerializeDefaultValuesPolicy policy) { this.Serializer = this.Serializer with { SerializeDefaultValues = policy }; @@ -235,9 +234,9 @@ public void Flags_OnMembersOfAllKinds([CombinatorialMemberData(nameof(AllPolicie } } - [Theory] - [InlineData(SerializeDefaultValuesPolicy.Never)] - [InlineData(SerializeDefaultValuesPolicy.Required)] + [Test] + [Arguments(SerializeDefaultValuesPolicy.Never)] + [Arguments(SerializeDefaultValuesPolicy.Required)] public void Flags_OnRequiredAndOptionalParameters(SerializeDefaultValuesPolicy policy) { this.Serializer = this.Serializer with { SerializeDefaultValues = policy }; @@ -259,10 +258,10 @@ public void Flags_OnRequiredAndOptionalParameters(SerializeDefaultValuesPolicy p } } - [Theory] - [InlineData(SerializeDefaultValuesPolicy.Never)] - [InlineData(SerializeDefaultValuesPolicy.Required)] - [InlineData(SerializeDefaultValuesPolicy.Always)] + [Test] + [Arguments(SerializeDefaultValuesPolicy.Never)] + [Arguments(SerializeDefaultValuesPolicy.Required)] + [Arguments(SerializeDefaultValuesPolicy.Always)] public void PropertyWithNonDefaultInitializer_PreservesValue(SerializeDefaultValuesPolicy policy) { this.Serializer = this.Serializer with { SerializeDefaultValues = policy }; diff --git a/test/Nerdbank.MessagePack.Tests/StreamTests.cs b/test/Nerdbank.MessagePack.TUnit/StreamTests.cs similarity index 72% rename from test/Nerdbank.MessagePack.Tests/StreamTests.cs rename to test/Nerdbank.MessagePack.TUnit/StreamTests.cs index 57bf048f..72e107bc 100644 --- a/test/Nerdbank.MessagePack.Tests/StreamTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/StreamTests.cs @@ -3,7 +3,7 @@ public partial class StreamTests : MessagePackSerializerTestBase { - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task SerializeWithStreamAsync(bool memoryStream) { Person person = new("Andrew", "Arnott"); @@ -14,15 +14,15 @@ public async Task SerializeWithStreamAsync(bool memoryStream) stream = new MonitoringStream(stream); } - await this.Serializer.SerializeAsync(stream, person, TestContext.Current.CancellationToken); + await this.Serializer.SerializeAsync(stream, person, this.TimeoutToken); stream.Position = 0; - Person? deserialized = await this.Serializer.DeserializeAsync(stream, TestContext.Current.CancellationToken); + Person? deserialized = await this.Serializer.DeserializeAsync(stream, this.TimeoutToken); Assert.Equal(person, deserialized); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public void SerializeWithStream(bool memoryStream) { Person person = new("Andrew", "Arnott"); @@ -33,13 +33,13 @@ public void SerializeWithStream(bool memoryStream) stream = new MonitoringStream(stream); } - this.Serializer.Serialize(stream, person, TestContext.Current.CancellationToken); + this.Serializer.Serialize(stream, person, this.TimeoutToken); stream.Position = 0; - Person? deserialized = this.Serializer.Deserialize(stream, TestContext.Current.CancellationToken); + Person? deserialized = this.Serializer.Deserialize(stream, this.TimeoutToken); } - [Fact] + [Test] public void Deserialize_FromMemoryStreamAtNonZeroPosition() { // Create test data @@ -48,20 +48,20 @@ public void Deserialize_FromMemoryStreamAtNonZeroPosition() // Serialize both persons to a MemoryStream MemoryStream stream = new(); - this.Serializer.Serialize(stream, person1, TestContext.Current.CancellationToken); + this.Serializer.Serialize(stream, person1, this.TimeoutToken); long person2Position = stream.Position; - this.Serializer.Serialize(stream, person2, TestContext.Current.CancellationToken); + this.Serializer.Serialize(stream, person2, this.TimeoutToken); // Reset to position of second person and deserialize stream.Position = person2Position; - Person? deserialized = this.Serializer.Deserialize(stream, TestContext.Current.CancellationToken); + Person? deserialized = this.Serializer.Deserialize(stream, this.TimeoutToken); // Should get the second person, not the first Assert.Equal(person2, deserialized); Assert.NotEqual(person1, deserialized); } - [Fact] + [Test] public async Task DeserializeAsync_FromMemoryStreamAtNonZeroPosition() { // Create test data @@ -70,13 +70,13 @@ public async Task DeserializeAsync_FromMemoryStreamAtNonZeroPosition() // Serialize both persons to a MemoryStream MemoryStream stream = new(); - await this.Serializer.SerializeAsync(stream, person1, TestContext.Current.CancellationToken); + await this.Serializer.SerializeAsync(stream, person1, this.TimeoutToken); long person2Position = stream.Position; - await this.Serializer.SerializeAsync(stream, person2, TestContext.Current.CancellationToken); + await this.Serializer.SerializeAsync(stream, person2, this.TimeoutToken); // Reset to position of second person and deserialize stream.Position = person2Position; - Person? deserialized = await this.Serializer.DeserializeAsync(stream, TestContext.Current.CancellationToken); + Person? deserialized = await this.Serializer.DeserializeAsync(stream, this.TimeoutToken); // Should get the second person, not the first Assert.Equal(person2, deserialized); diff --git a/test/Nerdbank.MessagePack.Tests/StreamingEnumerableTests.cs b/test/Nerdbank.MessagePack.TUnit/StreamingEnumerableTests.cs similarity index 83% rename from test/Nerdbank.MessagePack.Tests/StreamingEnumerableTests.cs rename to test/Nerdbank.MessagePack.TUnit/StreamingEnumerableTests.cs index b9d6b7d0..e52e1f27 100644 --- a/test/Nerdbank.MessagePack.Tests/StreamingEnumerableTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/StreamingEnumerableTests.cs @@ -1,13 +1,13 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -[Trait("AsyncSerialization", "true")] +[Property("AsyncSerialization", "true")] public partial class StreamingEnumerableTests : MessagePackSerializerTestBase { /// /// Streams multiple elements with no array envelope. /// - [Fact] + [Test] public async Task DeserializeEnumerableAsync_TopLevel_PipeReader() { using Sequence sequence = new(); @@ -21,10 +21,10 @@ public async Task DeserializeEnumerableAsync_TopLevel_PipeReader() int readCount = 0; PipeReader reader = PipeReader.Create(sequence); - await foreach (int current in this.Serializer.DeserializeEnumerableAsync(reader, TestContext.Current.CancellationToken)) + await foreach (int current in this.Serializer.DeserializeEnumerableAsync(reader, this.TimeoutToken)) { readCount++; - this.Logger.WriteLine(current.ToString()); + Console.WriteLine(current.ToString()); } Assert.Equal(10, readCount); @@ -33,11 +33,11 @@ public async Task DeserializeEnumerableAsync_TopLevel_PipeReader() /// /// Streams multiple elements with no array envelope. /// - [Fact] + [Test] public async Task DeserializeEnumerableAsync_TopLevel_Empty() { PipeReader reader = PipeReader.Create(new([])); - await foreach (int current in this.Serializer.DeserializeEnumerableAsync(reader, TestContext.Current.CancellationToken)) + await foreach (int current in this.Serializer.DeserializeEnumerableAsync(reader, this.TimeoutToken)) { Assert.Fail("No items should have been read."); } @@ -46,7 +46,7 @@ public async Task DeserializeEnumerableAsync_TopLevel_Empty() /// /// Streams multiple elements with no array envelope. /// - [Fact] + [Test] public async Task DeserializeEnumerableAsync_TopLevel_Stream() { using Sequence sequence = new(); @@ -60,10 +60,10 @@ public async Task DeserializeEnumerableAsync_TopLevel_Stream() int readCount = 0; MemoryStream reader = new(sequence.AsReadOnlySequence.ToArray()); - await foreach (int current in this.Serializer.DeserializeEnumerableAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), TestContext.Current.CancellationToken)) + await foreach (int current in this.Serializer.DeserializeEnumerableAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), this.TimeoutToken)) { readCount++; - this.Logger.WriteLine(current.ToString()); + Console.WriteLine(current.ToString()); } Assert.Equal(10, readCount); @@ -73,7 +73,7 @@ public async Task DeserializeEnumerableAsync_TopLevel_Stream() /// Verifies that there is no hang due to double reads. /// /// Regression test for this user-filed bug. - [Fact] + [Test] public async Task DeserializeEnumerableAsync_TopLevel_ReadItAll() { using Sequence sequence = new(); @@ -86,9 +86,9 @@ public async Task DeserializeEnumerableAsync_TopLevel_ReadItAll() FragmentedPipeReader reader = new(sequence, breakPosition); List realizedList = []; - await foreach (int value in this.Serializer.DeserializeEnumerableAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), TestContext.Current.CancellationToken)) + await foreach (int value in this.Serializer.DeserializeEnumerableAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), this.TimeoutToken)) { - this.Logger.WriteLine($"Received {value}"); + Console.WriteLine($"Received {value}"); realizedList.Add(value); Assert.Equal(realizedList.Count, value); if (realizedList.Count == 2) @@ -105,7 +105,7 @@ public async Task DeserializeEnumerableAsync_TopLevel_ReadItAll() /// Verifies that there is no hang due to double reads. /// /// Regression test for this user-filed bug. - [Fact] + [Test] public async Task DeserializeEnumerableAsync_TopLevel_Fragmented() { using Sequence sequence = new(); @@ -123,9 +123,9 @@ public async Task DeserializeEnumerableAsync_TopLevel_Fragmented() FragmentedPipeReader reader = new(sequence, breakPosition1, breakPosition2); List realizedList = []; - await foreach (int value in this.Serializer.DeserializeEnumerableAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), TestContext.Current.CancellationToken)) + await foreach (int value in this.Serializer.DeserializeEnumerableAsync(reader, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow(), this.TimeoutToken)) { - this.Logger.WriteLine($"Received {value}"); + Console.WriteLine($"Received {value}"); realizedList.Add(value); Assert.Equal(realizedList.Count, value); if (realizedList.Count == 2) @@ -145,7 +145,7 @@ public async Task DeserializeEnumerableAsync_TopLevel_Fragmented() /// /// Streams elements of a top-level msgpack array. /// - [Fact] + [Test] public async Task DeserializeEnumerableAsync_Array() { using Sequence sequence = new(); @@ -161,26 +161,26 @@ public async Task DeserializeEnumerableAsync_Array() int readCount = 0; PipeReader reader = PipeReader.Create(sequence); MessagePackSerializer.StreamingEnumerationOptions options = new(a => a); - await foreach (int current in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int current in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { readCount++; - this.Logger.WriteLine(current.ToString()); + Console.WriteLine(current.ToString()); } Assert.Equal(10, readCount); } - [Fact] + [Test] public async Task DeserializeEnumerableAsync_AsyncElementConverter() { SimpleStreamingContainerKeyed[] array = [new(), new()]; - byte[] msgpack = this.Serializer.Serialize(array, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(array, this.TimeoutToken); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(new(msgpack)); MessagePackSerializer.StreamingEnumerationOptions options = new(a => a); List actual = new(); - await foreach (SimpleStreamingContainerKeyed? item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (SimpleStreamingContainerKeyed? item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { actual.Add(item); } @@ -188,13 +188,13 @@ public async Task DeserializeEnumerableAsync_AsyncElementConverter() Assert.Equal(2, actual.Count); } - [Trait("ReferencePreservation", "true")] - [Fact] + [Property("ReferencePreservation", "true")] + [Test] public async Task DeserializeEnumerableAsync_ReferencesPreserved() { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.RejectCycles }; SimpleStreamingContainerKeyed original = new(); - byte[] msgpack = this.Serializer.Serialize([original, original], TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize([original, original], this.TimeoutToken); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(new(msgpack)); @@ -202,7 +202,7 @@ public async Task DeserializeEnumerableAsync_ReferencesPreserved() List actual = new(); NotSupportedException ex = await Assert.ThrowsAsync(async delegate { - await foreach (SimpleStreamingContainerKeyed? item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (SimpleStreamingContainerKeyed? item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { actual.Add(item); } @@ -210,16 +210,16 @@ public async Task DeserializeEnumerableAsync_ReferencesPreserved() Assert.Equal(2, actual.Count); Assert.Same(actual[0], actual[1]); }); - this.Logger.WriteLine(ex.Message); + Console.WriteLine(ex.Message); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers(bool leaveOpen) { OuterStreamingContainer container = new(new(true, [1, 2, 3], true)); Sequence msgpack = new(); - msgpack.Append(this.Serializer.Serialize(container, TestContext.Current.CancellationToken)); - msgpack.Append(this.Serializer.Serialize("hi", TestContext.Current.CancellationToken)); + msgpack.Append(this.Serializer.Serialize(container, this.TimeoutToken)); + msgpack.Append(this.Serializer.Serialize("hi", this.TimeoutToken)); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(msgpack); @@ -228,7 +228,7 @@ public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers(bool le { LeaveOpen = leaveOpen, }; - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Equal(count++ + 1, item); } @@ -238,18 +238,18 @@ public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers(bool le if (leaveOpen) { // Verify correct positioning by deserializing the next top-level structure in the pipe. - string? actual = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal("hi", actual); } } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers_Keyed(bool leaveOpen, bool asMap) { SimpleStreamingContainerKeyed container = new() { Before = asMap ? null : "a", Values = [1, 2, 3], After = asMap ? null : "b" }; Sequence msgpack = new(); - msgpack.Append(this.Serializer.Serialize(container, TestContext.Current.CancellationToken)); - msgpack.Append(this.Serializer.Serialize("hi", TestContext.Current.CancellationToken)); + msgpack.Append(this.Serializer.Serialize(container, this.TimeoutToken)); + msgpack.Append(this.Serializer.Serialize("hi", this.TimeoutToken)); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(msgpack); @@ -258,7 +258,7 @@ public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers_Keyed(b { LeaveOpen = leaveOpen, }; - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Equal(count++ + 1, item); } @@ -268,7 +268,7 @@ public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers_Keyed(b if (leaveOpen) { // Verify correct positioning by deserializing the next top-level structure in the pipe. - string? actual = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal("hi", actual); } } @@ -277,13 +277,13 @@ public async Task DeserializeEnumerableAsync_SequenceWithinTwoContainers_Keyed(b /// Verifies handling when the specified path includes an array indexer. /// /// Whether to the reader should be positioned at the next element. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_StepThroughArray(bool leaveOpen) { OuterStreamingContainerByArray container = new([null, new(true, [1, 2, 3], false), new(true, [1], false)]); Sequence msgpack = new(); - msgpack.Append(this.Serializer.Serialize(container, TestContext.Current.CancellationToken)); - msgpack.Append(this.Serializer.Serialize("hi", TestContext.Current.CancellationToken)); + msgpack.Append(this.Serializer.Serialize(container, this.TimeoutToken)); + msgpack.Append(this.Serializer.Serialize("hi", this.TimeoutToken)); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(msgpack); @@ -292,7 +292,7 @@ public async Task DeserializeEnumerableAsync_StepThroughArray(bool leaveOpen) { LeaveOpen = leaveOpen, }; - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Equal(count++ + 1, item); } @@ -302,7 +302,7 @@ public async Task DeserializeEnumerableAsync_StepThroughArray(bool leaveOpen) if (leaveOpen) { // Verify correct positioning by deserializing the next top-level structure in the pipe. - string? actual = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal("hi", actual); } } @@ -311,13 +311,13 @@ public async Task DeserializeEnumerableAsync_StepThroughArray(bool leaveOpen) /// Verifies handling when the specified path includes an indexer. /// /// Whether to the reader should be positioned at the next element. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_StepThroughImmutableArray(bool leaveOpen) { OuterStreamingContainerByImmutableArray container = new([null, new(true, [1, 2, 3], false), new(true, [1], false)]); Sequence msgpack = new(); - msgpack.Append(this.Serializer.Serialize(container, TestContext.Current.CancellationToken)); - msgpack.Append(this.Serializer.Serialize("hi", TestContext.Current.CancellationToken)); + msgpack.Append(this.Serializer.Serialize(container, this.TimeoutToken)); + msgpack.Append(this.Serializer.Serialize("hi", this.TimeoutToken)); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(msgpack); @@ -326,7 +326,7 @@ public async Task DeserializeEnumerableAsync_StepThroughImmutableArray(bool leav { LeaveOpen = leaveOpen, }; - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Equal(count++ + 1, item); } @@ -336,7 +336,7 @@ public async Task DeserializeEnumerableAsync_StepThroughImmutableArray(bool leav if (leaveOpen) { // Verify correct positioning by deserializing the next top-level structure in the pipe. - string? actual = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal("hi", actual); } } @@ -345,13 +345,13 @@ public async Task DeserializeEnumerableAsync_StepThroughImmutableArray(bool leav /// Verifies handling when the specified path includes an indexer. /// /// Whether to the reader should be positioned at the next element. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_StepThroughDictionary(bool leaveOpen) { OuterStreamingContainerByDictionary container = new(new() { ["a"] = null, ["b"] = new(true, [1, 2, 3], false) }); Sequence msgpack = new(); - msgpack.Append(this.Serializer.Serialize(container, TestContext.Current.CancellationToken)); - msgpack.Append(this.Serializer.Serialize("hi", TestContext.Current.CancellationToken)); + msgpack.Append(this.Serializer.Serialize(container, this.TimeoutToken)); + msgpack.Append(this.Serializer.Serialize("hi", this.TimeoutToken)); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(msgpack); @@ -360,7 +360,7 @@ public async Task DeserializeEnumerableAsync_StepThroughDictionary(bool leaveOpe { LeaveOpen = leaveOpen, }; - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Equal(count++ + 1, item); } @@ -370,7 +370,7 @@ public async Task DeserializeEnumerableAsync_StepThroughDictionary(bool leaveOpe if (leaveOpen) { // Verify correct positioning by deserializing the next top-level structure in the pipe. - string? actual = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal("hi", actual); } } @@ -379,13 +379,13 @@ public async Task DeserializeEnumerableAsync_StepThroughDictionary(bool leaveOpe /// Verifies handling when the specified path includes an indexer. /// /// Whether to the reader should be positioned at the next element. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_StepThroughDictionaryCustomKey(bool leaveOpen) { OuterStreamingContainerByDictionaryCustomKey container = new(new() { [new CustomKey(5)] = null, [new CustomKey(3)] = new(true, [1, 2, 3], false) }); Sequence msgpack = new(); - msgpack.Append(this.Serializer.Serialize(container, TestContext.Current.CancellationToken)); - msgpack.Append(this.Serializer.Serialize("hi", TestContext.Current.CancellationToken)); + msgpack.Append(this.Serializer.Serialize(container, this.TimeoutToken)); + msgpack.Append(this.Serializer.Serialize("hi", this.TimeoutToken)); this.LogMsgPack(msgpack); PipeReader reader = PipeReader.Create(msgpack); @@ -395,7 +395,7 @@ public async Task DeserializeEnumerableAsync_StepThroughDictionaryCustomKey(bool { LeaveOpen = leaveOpen, }; - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Equal(count++ + 1, item); } @@ -405,7 +405,7 @@ public async Task DeserializeEnumerableAsync_StepThroughDictionaryCustomKey(bool if (leaveOpen) { // Verify correct positioning by deserializing the next top-level structure in the pipe. - string? actual = await this.Serializer.DeserializeAsync(reader, TestContext.Current.CancellationToken); + string? actual = await this.Serializer.DeserializeAsync(reader, this.TimeoutToken); Assert.Equal("hi", actual); } } @@ -414,10 +414,10 @@ public async Task DeserializeEnumerableAsync_StepThroughDictionaryCustomKey(bool /// Verifies handling when the specified path turns out to be a null value. /// /// A value indicating whether we're verifying behavior that prefers an empty sequence over throwing when a null is encountered. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_NullRoot(bool preferEmptySequence) { - byte[] msgpack = this.Serializer.Serialize(null, TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(null, this.TimeoutToken); MessagePackSerializer.StreamingEnumerationOptions options = new(c => c.Inner!.Values!) { EmptySequenceForUndiscoverablePath = preferEmptySequence, @@ -425,7 +425,7 @@ public async Task DeserializeEnumerableAsync_NullRoot(bool preferEmptySequence) PipeReader reader = PipeReader.Create(new(msgpack)); try { - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Fail("Should not have received any items."); } @@ -434,7 +434,7 @@ public async Task DeserializeEnumerableAsync_NullRoot(bool preferEmptySequence) } catch (MessagePackSerializationException ex) { - this.Logger.WriteLine(ex.ToString()); + Console.WriteLine(ex.ToString()); Assert.False(preferEmptySequence, "Should not have thrown an exception."); Assert.Matches(@"\Wc(?!\.Inner)", ex.Message); } @@ -444,10 +444,10 @@ public async Task DeserializeEnumerableAsync_NullRoot(bool preferEmptySequence) /// Verifies handling when the specified path turns out to be a null value. /// /// A value indicating whether we're verifying behavior that prefers an empty sequence over throwing when a null is encountered. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_NullMidPath(bool preferEmptySequence) { - byte[] msgpack = this.Serializer.Serialize(new OuterStreamingContainer(null), TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(new OuterStreamingContainer(null), this.TimeoutToken); MessagePackSerializer.StreamingEnumerationOptions options = new(c => c.Inner!.Values!) { EmptySequenceForUndiscoverablePath = preferEmptySequence, @@ -455,7 +455,7 @@ public async Task DeserializeEnumerableAsync_NullMidPath(bool preferEmptySequenc PipeReader reader = PipeReader.Create(new(msgpack)); try { - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Fail("Should not have received any items."); } @@ -464,7 +464,7 @@ public async Task DeserializeEnumerableAsync_NullMidPath(bool preferEmptySequenc } catch (MessagePackSerializationException ex) { - this.Logger.WriteLine(ex.ToString()); + Console.WriteLine(ex.ToString()); Assert.False(preferEmptySequence, "Should not have thrown an exception."); Assert.Matches(@"\Wc\.Inner(?!\.Values)", ex.Message); } @@ -474,10 +474,10 @@ public async Task DeserializeEnumerableAsync_NullMidPath(bool preferEmptySequenc /// Verifies handling when the specified path turns out to be a null value. /// /// A value indicating whether we're verifying behavior that prefers an empty sequence over throwing when a null is encountered. - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task DeserializeEnumerableAsync_NullSequenceMember(bool preferEmptySequence) { - byte[] msgpack = this.Serializer.Serialize(new OuterStreamingContainer(new(true, null, false)), TestContext.Current.CancellationToken); + byte[] msgpack = this.Serializer.Serialize(new OuterStreamingContainer(new(true, null, false)), this.TimeoutToken); MessagePackSerializer.StreamingEnumerationOptions options = new(c => c.Inner!.Values!) { EmptySequenceForUndiscoverablePath = preferEmptySequence, @@ -485,7 +485,7 @@ public async Task DeserializeEnumerableAsync_NullSequenceMember(bool preferEmpty PipeReader reader = PipeReader.Create(new(msgpack)); try { - await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, TestContext.Current.CancellationToken)) + await foreach (int item in this.Serializer.DeserializePathEnumerableAsync(reader, options, this.TimeoutToken)) { Assert.Fail("Should not have received any items."); } @@ -494,7 +494,7 @@ public async Task DeserializeEnumerableAsync_NullSequenceMember(bool preferEmpty } catch (MessagePackSerializationException ex) { - this.Logger.WriteLine(ex.ToString()); + Console.WriteLine(ex.ToString()); Assert.False(preferEmptySequence, "Should not have thrown an exception."); Assert.Matches(@"\Wc\.Inner\.Values", ex.Message); } diff --git a/test/Nerdbank.MessagePack.Tests/StringInterningTests.cs b/test/Nerdbank.MessagePack.TUnit/StringInterningTests.cs similarity index 91% rename from test/Nerdbank.MessagePack.Tests/StringInterningTests.cs rename to test/Nerdbank.MessagePack.TUnit/StringInterningTests.cs index e8e901c5..26783c6b 100644 --- a/test/Nerdbank.MessagePack.Tests/StringInterningTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/StringInterningTests.cs @@ -8,10 +8,10 @@ public StringInterningTests() this.Serializer = this.Serializer with { InternStrings = true }; } - [Fact] + [Test] public void InternStringsDefault() => Assert.False(new MessagePackSerializer().InternStrings); - [Fact] + [Test] public void NoInterning() { this.Serializer = this.Serializer with { InternStrings = false }; @@ -20,7 +20,7 @@ public void NoInterning() Assert.NotSame(deserialized[0], deserialized[1]); } - [Fact] + [Test] public void Interning() { this.Serializer = this.Serializer with { InternStrings = true }; @@ -34,23 +34,23 @@ public void Interning() Assert.Same(deserialized[0], deserialized2[0]); } - [Fact] + [Test] public void Null() => this.Roundtrip(null); - [Fact] + [Test] public void Empty() => this.Roundtrip(string.Empty); - [Fact] + [Test] public void VeryLargeString() => this.Roundtrip(new string('a', 100_000)); - [Fact] + [Test] public void Fragmented() { - ReadOnlyMemory buffer = this.Serializer.Serialize("abc", TestContext.Current.CancellationToken); + ReadOnlyMemory buffer = this.Serializer.Serialize("abc", this.TimeoutToken); Sequence seq = new(); seq.Append(buffer[..^1]); seq.Append(buffer[^1..]); - string? deserialized = this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken); + string? deserialized = this.Serializer.Deserialize(seq, this.TimeoutToken); Assert.Equal("abc", deserialized); } diff --git a/test/Nerdbank.MessagePack.Tests/StructuralEquality.cs b/test/Nerdbank.MessagePack.TUnit/StructuralEquality.cs similarity index 100% rename from test/Nerdbank.MessagePack.Tests/StructuralEquality.cs rename to test/Nerdbank.MessagePack.TUnit/StructuralEquality.cs diff --git a/test/Nerdbank.MessagePack.TUnit/StructuralEqualityComparerTests.cs b/test/Nerdbank.MessagePack.TUnit/StructuralEqualityComparerTests.cs new file mode 100644 index 00000000..9fec9596 --- /dev/null +++ b/test/Nerdbank.MessagePack.TUnit/StructuralEqualityComparerTests.cs @@ -0,0 +1,245 @@ +// Copyright (c) Andrew Arnott. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if !NET +#pragma warning disable CS8604 // Possible null reference argument. +#pragma warning disable CS8767 // null ref annotations +#endif + +using System.Numerics; + +public abstract partial class StructuralEqualityComparerTests +{ + internal enum FruitKind + { + Apple, + Banana, + } + + [Test] + public void Boolean() => this.AssertEqualityComparerBehavior([true], [false]); + + [Test] + public void BigInteger() => this.AssertEqualityComparerBehavior([new BigInteger(5), new BigInteger(5)], [new BigInteger(10)]); + + [Test] + public void CustomType_Tree() => this.AssertEqualityComparerBehavior( + [new Tree([new Fruit(3, "Red"), new Fruit(4, "Green")], 4, FruitKind.Apple), new Tree([new Fruit(3, "Red"), new Fruit(4, "Green")], 4, FruitKind.Apple)], + [ + new Tree([new Fruit(3, "Red"), new Fruit(4, "Yellow")], 4, FruitKind.Apple), + new Tree([new Fruit(3, "Red"), new Fruit(4, "Green")], 4, FruitKind.Banana), + new Tree([new Fruit(4, "Red")], 4, FruitKind.Banana), + new Tree([new Fruit(3, "Yellow")], 4, FruitKind.Apple)]); + + [Test] + public void CustomType_Fruit() => this.AssertEqualityComparerBehavior( + [new Fruit(3, "Red"), new Fruit(3, "Red")], + [new Fruit(4, "Red"), new Fruit(3, "Yellow")]); + + [Test] + public abstract void CustomHash(); + + [Test] + public void CustomHashingAndEquality() => this.AssertEqualityComparerBehavior( + [new CustomHasher(), new CustomHasher()], + [new CustomHasher() { SpecialCode = 33 }]); + + [Test] + public void ReadOnlyMemoryOfByte() => this.AssertEqualityComparerBehavior( + [new HaveReadOnlyMemoryOfByte(new byte[] { 1, 2 }), new HaveReadOnlyMemoryOfByte(new byte[] { 1, 2 })], + [new HaveReadOnlyMemoryOfByte(new byte[] { 1, 3 }), new HaveReadOnlyMemoryOfByte(new byte[] { 1, 2, 3 })]); + + [Test] + public void ReadOnlySequenceOfByte() => this.AssertEqualityComparerBehavior( + [new HaveReadOnlySequenceOfByte(new([1, 2])), new HaveReadOnlySequenceOfByte(new([1, 2]))], + [new HaveReadOnlySequenceOfByte(new([1, 3])), new HaveReadOnlySequenceOfByte(new([1, 2, 3]))]); + + [Test] + public void DerivedTypeEquality() + { + SomeBaseType.Derived1 derived1A = new(42); + SomeBaseType.Derived1 derived1B = new(42); + SomeBaseType.Derived1 derived1C = new(43); + SomeBaseType.Derived2 derived2A = new(42); + SomeBaseType.Derived3 derived3 = new(); + SomeBaseType.Derived4 derived4 = new(); + + this.AssertEqualityComparerBehavior( + [derived1A, derived1B], + [derived1C, derived2A, derived3, derived4]); + } + + protected IEqualityComparer GetEqualityComparer() +#if NET + where TProvider : IShapeable => this.GetEqualityComparer(TProvider.GetTypeShape()); +#else + => this.GetEqualityComparer(TypeShapeResolver.ResolveDynamicOrThrow()); +#endif + + protected IEqualityComparer GetEqualityComparer() +#if NET + where T : IShapeable => this.GetEqualityComparer(T.GetTypeShape()); +#else + => this.GetEqualityComparer(Witness.GeneratedTypeShapeProvider.GetTypeShape()); +#endif + + protected abstract IEqualityComparer GetEqualityComparer(ITypeShape shape); + + /// + private void AssertEqualityComparerBehavior(T[] equivalent, T[] different) +#if NET + where T : notnull, IShapeable => this.AssertEqualityComparerBehavior(equivalent, different); +#else + where T : notnull => this.AssertEqualityComparerBehavior(equivalent, different); +#endif + + /// + /// Asserts that hash codes and equality checks match or mismatch for various values. + /// + /// The type of the values to be tested. + /// The witness type for the data type. + /// An array of values that should all be considered equivalent. + /// An array of values that are each distinct from any of the values in the array. + private void AssertEqualityComparerBehavior(T[] equivalent, T[] different) +#if NET + where TProvider : IShapeable +#endif + where T : notnull + { + IEqualityComparer eq = this.GetEqualityComparer(); + + Console.WriteLine("Testing values that are expected to be equal:"); + foreach (T valueA in equivalent) + { + int valueAHashCode = eq.GetHashCode(valueA); + Console.WriteLine($"{valueA} hash code: {valueAHashCode}"); + + foreach (T valueB in equivalent) + { + int valueBHashCode = eq.GetHashCode(valueB); + Console.WriteLine($"{valueB} hash code: {valueBHashCode}"); + Assert.True(eq.Equals(valueA, valueB)); + Assert.Equal(valueAHashCode, valueBHashCode); + } + } + + Console.WriteLine("Testing values that are expected to be different:"); + T baseline = equivalent[0]; + int baselineHashCode = eq.GetHashCode(baseline); + foreach (T differentValue in different) + { + int differentValueHashCode = eq.GetHashCode(differentValue); + Console.WriteLine($"{differentValue} hash code: {differentValueHashCode}"); + Assert.False(eq.Equals(equivalent[0], differentValue)); + Assert.NotEqual(baselineHashCode, differentValueHashCode); + } + } + + [InheritsTests] + public class DefaultStructural : StructuralEqualityComparerTests + { + [Test] + public override void CustomHash() + { + CustomHasher obj = new(); + Assert.Equal(obj.SpecialCode, this.GetEqualityComparer().GetHashCode(obj)); + } + + protected override IEqualityComparer GetEqualityComparer(ITypeShape shape) + => StructuralEqualityComparer.GetDefault(shape); + } + + [InheritsTests] + public class HashCollisionResistant : StructuralEqualityComparerTests + { + [Test] + public override void CustomHash() + { + CustomHasher obj = new(); + Assert.Equal(obj.SpecialCode * 2, this.GetEqualityComparer().GetHashCode(obj)); + } + + protected override IEqualityComparer GetEqualityComparer(ITypeShape shape) + => StructuralEqualityComparer.GetHashCollisionResistant(shape); + } + + [GenerateShapeFor] + [GenerateShapeFor] + [GenerateShapeFor] + internal partial class Witness; + + [GenerateShape] + internal partial class Tree(Fruit[] fruits, int height, FruitKind kind) + { + public Fruit[] Fruits => fruits; + + public int Height => height; + + public FruitKind Kind => kind; + + public override string ToString() => $"{kind} tree with {fruits.Length} fruits and height {height}"; + } + + [GenerateShape] + internal partial class Fruit(int weight, string color) + { + public int Weight => weight; + + public string Color => color; + + public override string ToString() => $"Fruit weighing {weight} and color {color}"; + } + + [GenerateShape] + internal partial class HaveReadOnlyMemoryOfByte(ReadOnlyMemory buffer) + { + public ReadOnlyMemory Buffer => buffer; + } + + [GenerateShape] + internal partial class HaveReadOnlySequenceOfByte(ReadOnlySequence buffer) + { + public ReadOnlySequence Buffer => buffer; + } + + [GenerateShape] + internal partial class CustomHasher : IStructuralSecureEqualityComparer + { + // This is internal on purpose, so that PolyType will ignore the property for purposes of equality + // and hashing, and tests will only pass if the custom hash and equality methods on this class are used. + internal int SpecialCode { get; set; } = 42; + + public bool StructuralEquals(CustomHasher? other) => other is not null && this.SpecialCode == other.SpecialCode; + + public long GetSecureHashCode() => this.SpecialCode * 2; + + public override int GetHashCode() => this.SpecialCode; + } + + [GenerateShape] + [DerivedTypeShape(typeof(Derived1))] + [DerivedTypeShape(typeof(Derived2))] + [DerivedTypeShape(typeof(Derived3))] + [DerivedTypeShape(typeof(Derived4))] + internal abstract partial record SomeBaseType + { + internal record Derived1(int Value) : SomeBaseType; + + internal record Derived2(int Value) : SomeBaseType; + + internal record Derived3 : SomeBaseType; + + [TypeShape(Marshaler = typeof(Marshaler))] + internal record Derived4 : SomeBaseType + { + internal class Marshaler : IMarshaler + { + public Surrogate? Marshal(Derived4? value) => value is null ? null : default(Surrogate); + + public Derived4? Unmarshal(Surrogate? value) => value is null ? null : new Derived4(); + + internal struct Surrogate; + } + } + } +} diff --git a/test/Nerdbank.MessagePack.TUnit/SurrogateTests.OriginalType.cs b/test/Nerdbank.MessagePack.TUnit/SurrogateTests.OriginalType.cs new file mode 100644 index 00000000..068a633a --- /dev/null +++ b/test/Nerdbank.MessagePack.TUnit/SurrogateTests.OriginalType.cs @@ -0,0 +1,35 @@ +// Copyright (c) Andrew Arnott. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +public partial class SurrogateTests +{ + [GenerateShape(Marshaler = typeof(Marshaler))] + internal partial class OriginalType + { + private readonly int a; + private readonly int b; + + internal OriginalType(int a, int b) + { + this.a = a; + this.b = b; + } + + public int Sum => this.a + this.b; + + internal int GetA() => this.a; + + internal int GetB() => this.b; + + internal record struct MarshaledType(int A, int B); + + internal class Marshaler : IMarshaler + { + public OriginalType? Unmarshal(MarshaledType? surrogate) + => surrogate.HasValue ? new(surrogate.Value.A, surrogate.Value.B) : null; + + public MarshaledType? Marshal(OriginalType? value) + => value is null ? null : new(value.a, value.b); + } + } +} diff --git a/test/Nerdbank.MessagePack.Tests/SurrogateTests.cs b/test/Nerdbank.MessagePack.TUnit/SurrogateTests.cs similarity index 88% rename from test/Nerdbank.MessagePack.Tests/SurrogateTests.cs rename to test/Nerdbank.MessagePack.TUnit/SurrogateTests.cs index 527da200..bbc7d810 100644 --- a/test/Nerdbank.MessagePack.Tests/SurrogateTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/SurrogateTests.cs @@ -1,10 +1,10 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -[Trait("Surrogates", "true")] +[Property("Surrogates", "true")] public partial class SurrogateTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void NonNullReference() { OriginalType? deserialized = this.Roundtrip(new OriginalType(1, 2)); @@ -12,14 +12,14 @@ public void NonNullReference() Assert.Equal(3, deserialized.Sum); } - [Fact] + [Test] public void NullReference() { OriginalType? deserialized = this.Roundtrip(null); Assert.Null(deserialized); } - [Fact] + [Test] public async Task NonNullReference_Async() { OriginalType? deserialized = await this.RoundtripAsync(new OriginalType(1, 2)); @@ -27,15 +27,15 @@ public async Task NonNullReference_Async() Assert.Equal(3, deserialized.Sum); } - [Fact] + [Test] public async Task NullReference_Async() { OriginalType? deserialized = await this.RoundtripAsync(null); Assert.Null(deserialized); } - [Fact] - [Trait("ReferencePreservation", "true")] + [Test] + [Property("ReferencePreservation", "true")] public void ReferencePreservation() { this.Serializer = this.Serializer with { PreserveReferences = ReferencePreservationMode.RejectCycles }; @@ -45,7 +45,7 @@ public void ReferencePreservation() Assert.Same(deserializedArray[0], deserializedArray[1]); } - [Fact] + [Test] public void GenericMarshaler() { OpenGenericDataType? deserialized = this.Roundtrip, Witness>(new OpenGenericDataType { Value = 42 }); @@ -53,7 +53,7 @@ public void GenericMarshaler() Assert.Equal(42, deserialized.Value); } - [Fact] + [Test] public void SurrogateIgnoredWithCustomConverterByInstanceRegistration() { this.Serializer = this.Serializer with { Converters = [new OriginalTypeConverter()] }; @@ -66,7 +66,7 @@ public void SurrogateIgnoredWithCustomConverterByInstanceRegistration() Assert.Equal(8, deserialized?.GetB()); } - [Fact] + [Test] public void SurrogateIgnoredWithCustomConverterByTypeRegistration() { this.Serializer = this.Serializer with { ConverterTypes = [typeof(OriginalTypeConverter)] }; @@ -79,7 +79,7 @@ public void SurrogateIgnoredWithCustomConverterByTypeRegistration() Assert.Equal(8, deserialized?.GetB()); } - [Fact] + [Test] public void SurrogateIgnoredWithCustomConverterByFactoryRegistration() { this.Serializer = this.Serializer with { ConverterFactories = [new OriginalTypeConverterFactory()] }; @@ -92,7 +92,7 @@ public void SurrogateIgnoredWithCustomConverterByFactoryRegistration() Assert.Equal(8, deserialized?.GetB()); } - [Fact] + [Test] public void SurrogateIgnoredWithCustomConverterByAttribute() { OriginalTypeWithSurrogateAndConverter obj = new(3, 5); @@ -103,36 +103,6 @@ public void SurrogateIgnoredWithCustomConverterByAttribute() Assert.Equal(5, deserialized?.GetB()); } - [GenerateShape(Marshaler = typeof(Marshaler))] - internal partial class OriginalType - { - private int a; - private int b; - - internal OriginalType(int a, int b) - { - this.a = a; - this.b = b; - } - - public int Sum => this.a + this.b; - - internal int GetA() => this.a; - - internal int GetB() => this.b; - - internal record struct MarshaledType(int A, int B); - - internal class Marshaler : IMarshaler - { - public OriginalType? Unmarshal(MarshaledType? surrogate) - => surrogate.HasValue ? new(surrogate.Value.A, surrogate.Value.B) : null; - - public MarshaledType? Marshal(OriginalType? value) - => value is null ? null : new(value.a, value.b); - } - } - [GenerateShape(Marshaler = typeof(Marshaler))] [MessagePackConverter(typeof(Converter))] internal partial class OriginalTypeWithSurrogateAndConverter diff --git a/test/Nerdbank.MessagePack.Tests/TestConstants.cs b/test/Nerdbank.MessagePack.TUnit/TestConstants.cs similarity index 100% rename from test/Nerdbank.MessagePack.Tests/TestConstants.cs rename to test/Nerdbank.MessagePack.TUnit/TestConstants.cs diff --git a/test/Nerdbank.MessagePack.Tests/UseComparerTests.cs b/test/Nerdbank.MessagePack.TUnit/UseComparerTests.cs similarity index 98% rename from test/Nerdbank.MessagePack.Tests/UseComparerTests.cs rename to test/Nerdbank.MessagePack.TUnit/UseComparerTests.cs index acff8dc8..2c08ca10 100644 --- a/test/Nerdbank.MessagePack.Tests/UseComparerTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/UseComparerTests.cs @@ -5,49 +5,49 @@ public partial class UseComparerTests : MessagePackSerializerTestBase { - [Fact] + [Test] public void EqualityComparerByStaticMember() { var deserialized = this.Roundtrip(new UsesStaticEqualityComparer()); Assert.Same(StringComparer.OrdinalIgnoreCase, deserialized?.StringInt.Comparer); } - [Fact] + [Test] public void ComparerByStaticMember() { var deserialized = this.Roundtrip(new UsesStaticComparer()); Assert.Same(StringComparer.OrdinalIgnoreCase, deserialized?.StringInt.Comparer); } - [Fact] + [Test] public void EqualityComparerByInstanceMember() { var deserialized = this.Roundtrip(new UsesInstanceEqualityComparer()); Assert.Same(StringComparer.OrdinalIgnoreCase, deserialized?.StringInt.Comparer); } - [Fact] + [Test] public void ComparerByInstanceMember() { var deserialized = this.Roundtrip(new UsesInstanceComparer()); Assert.Same(StringComparer.OrdinalIgnoreCase, deserialized?.StringInt.Comparer); } - [Fact] + [Test] public void EqualityComparerByType() { var deserialized = this.Roundtrip(new UsesInstanceEqualityComparer()); Assert.Same(StringComparer.OrdinalIgnoreCase, deserialized?.StringInt.Comparer); } - [Fact] + [Test] public void ComparerByType() { var deserialized = this.Roundtrip(new UsesInstanceComparer()); Assert.Same(StringComparer.OrdinalIgnoreCase, deserialized?.StringInt.Comparer); } - [Fact] + [Test] public void ComparerOnParameter() { var deserialized = this.Roundtrip(new ComparerOnConstructorParameter(new())); diff --git a/test/Nerdbank.MessagePack.Tests/VersionSafeSerializationTests.cs b/test/Nerdbank.MessagePack.TUnit/VersionSafeSerializationTests.cs similarity index 93% rename from test/Nerdbank.MessagePack.Tests/VersionSafeSerializationTests.cs rename to test/Nerdbank.MessagePack.TUnit/VersionSafeSerializationTests.cs index 966b863e..0cf59db1 100644 --- a/test/Nerdbank.MessagePack.Tests/VersionSafeSerializationTests.cs +++ b/test/Nerdbank.MessagePack.TUnit/VersionSafeSerializationTests.cs @@ -3,7 +3,7 @@ public partial class VersionSafeSerializationTests : MessagePackSerializerTestBase { - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MapObject(bool async) { MapModelV2 originalV2 = new() @@ -35,7 +35,7 @@ public async Task MapObject(bool async) Assert.Equal(originalV2.Age, restoredV2.Age); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task MapObject_NonDefaultCtor(bool async) { MapModelV2NonDefaultCtor originalV2 = new() @@ -67,7 +67,7 @@ public async Task MapObject_NonDefaultCtor(bool async) Assert.Equal(originalV2.Age, restoredV2.Age); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task ArrayObject(bool async, bool forceMap) { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -105,7 +105,7 @@ public async Task ArrayObject(bool async, bool forceMap) Assert.Equal(originalV2.ForceMap, restoredV2.ForceMap); } - [Theory, PairwiseData] + [Test, MatrixDataSource] public async Task ArrayObject_NonDefaultCtor(bool async, bool forceMap) { this.Serializer = this.Serializer with { SerializeDefaultValues = SerializeDefaultValuesPolicy.Required }; @@ -143,7 +143,7 @@ public async Task ArrayObject_NonDefaultCtor(bool async, bool forceMap) Assert.Equal(originalV2.ForceMap, restoredV2.ForceMap); } - [Fact] + [Test] public void StructWithVersionSafety() { Sequence seq = new(); @@ -177,12 +177,12 @@ private async ValueTask SerializeMaybeAsync(T value, bool async) // Wrap the MemoryStream to hide its type to avoid the library taking a 'fast path'. using MemoryStream ms = new(); using MonitoringStream wrapper = new(ms); - await this.Serializer.SerializeAsync(wrapper, value, TestContext.Current.CancellationToken); + await this.Serializer.SerializeAsync(wrapper, value, this.TimeoutToken); return ms.ToArray(); } else { - return this.Serializer.Serialize(value, TestContext.Current.CancellationToken); + return this.Serializer.Serialize(value, this.TimeoutToken); } } @@ -196,11 +196,11 @@ private async ValueTask SerializeMaybeAsync(T value, bool async) // Wrap the MemoryStream to hide its type to avoid the library taking a 'fast path'. using MemoryStream ms = new(data); using MonitoringStream wrapper = new(ms); - return await this.Serializer.DeserializeAsync(ms, TestContext.Current.CancellationToken); + return await this.Serializer.DeserializeAsync(ms, this.TimeoutToken); } else { - return this.Serializer.Deserialize(data, TestContext.Current.CancellationToken); + return this.Serializer.Deserialize(data, this.TimeoutToken); } } @@ -210,8 +210,8 @@ private RawMessagePack ReverseRoundtrip(RawMessagePack raw) #endif { this.LogMsgPack(raw); - T? value = this.Serializer.Deserialize(raw, TestContext.Current.CancellationToken); - RawMessagePack result = (RawMessagePack)this.Serializer.Serialize(value, TestContext.Current.CancellationToken); + T? value = this.Serializer.Deserialize(raw, this.TimeoutToken); + RawMessagePack result = (RawMessagePack)this.Serializer.Serialize(value, this.TimeoutToken); this.LogMsgPack(result); return result; } diff --git a/test/Nerdbank.MessagePack.Tests/BuiltInConverterTests.cs b/test/Nerdbank.MessagePack.Tests/BuiltInConverterTests.cs index 122116f2..19e884f2 100644 --- a/test/Nerdbank.MessagePack.Tests/BuiltInConverterTests.cs +++ b/test/Nerdbank.MessagePack.Tests/BuiltInConverterTests.cs @@ -1,492 +1,31 @@ // Copyright (c) Andrew Arnott. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Drawing; -using System.Globalization; -using System.Numerics; -using System.Runtime.InteropServices; -using System.Text; - public partial class BuiltInConverterTests : MessagePackSerializerTestBase { - private const string BadGuidFormatErrorMessage = "Not a recognized GUID format."; - - [Fact] - public void SystemDrawingColor() => this.AssertRoundtrip(Color.FromArgb(1, 2, 3, 4)); - - [Fact] - public void SystemDrawingPoint() => this.AssertRoundtrip(new Point(1, 1)); - - [Fact] - public void ImmutableDictionary() => this.AssertRoundtrip(new HasImmutableDictionary() { Map = ImmutableDictionary.Empty.Add("a", 1) }); - -#if NET - - [Fact] - public void Int128() - { - this.AssertRoundtrip(new HasInt128(0)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasInt128(long.MaxValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasInt128(long.MinValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasInt128(new Int128(1, 2))); - this.AssertType(MessagePackType.Extension); - - this.AssertRoundtrip(new HasInt128(System.Int128.MaxValue)); - this.AssertType(MessagePackType.Extension); - - this.AssertRoundtrip(new HasInt128(System.Int128.MinValue)); - this.AssertType(MessagePackType.Extension); - } - - /// - /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. - /// - /// - /// Note that while our mandates big endian encoding to match msgpack conventions, - /// The Bin encoding used by MessagePack-CSharp uses little-endian encoding. - /// - [Fact] - public void Int128_FromBin() - { - Int128 value = new(1, 2); - Sequence seq = new(); - MessagePackWriter writer = new(seq); - writer.WriteMapHeader(1); - writer.Write(nameof(HasInt128.Value)); - writer.WriteBinHeader(128 / 8); - Span byteSpan = writer.GetSpan(128 / 8); - Assert.True(((IBinaryInteger)value).TryWriteLittleEndian(byteSpan, out int written)); - writer.Advance(written); - writer.Flush(); - - Assert.Equal(value, this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken)!.Value); - } - - [Fact] - public void UInt128() - { - this.AssertRoundtrip(new HasUInt128(0)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasInt128(ulong.MaxValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasUInt128(new UInt128(1, 2))); - this.AssertType(MessagePackType.Extension); - - this.AssertRoundtrip(new HasUInt128(System.UInt128.MaxValue)); - this.AssertType(MessagePackType.Extension); - } - - /// - /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. - /// - /// - /// Note that while our mandates big endian encoding to match msgpack conventions, - /// The Bin encoding used by MessagePack-CSharp uses little-endian encoding. - /// - [Fact] - public void UInt128_FromBin() - { - UInt128 value = new(1, 2); - Sequence seq = new(); - MessagePackWriter writer = new(seq); - writer.WriteMapHeader(1); - writer.Write(nameof(HasUInt128.Value)); - writer.WriteBinHeader(128 / 8); - Span byteSpan = writer.GetSpan(128 / 8); - Assert.True(((IBinaryInteger)value).TryWriteLittleEndian(byteSpan, out int written)); - writer.Advance(written); - writer.Flush(); - - Assert.Equal(value, this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken)!.Value); - } - -#endif - -#if NET9_0_OR_GREATER - - [Fact] - public void OrderedDictionary() => this.AssertRoundtrip(new HasOrderedDictionary() { Map = { ['a'] = 1, ['b'] = 2, ['c'] = 3 } }); - -#endif - - [Fact] - public void Decimal() - { - this.AssertRoundtrip(new HasDecimal(1.2m)); - this.AssertRoundtrip(new HasDecimal(new decimal(ulong.MaxValue) * 1000)); - this.AssertRoundtrip(new HasDecimal(new decimal(ulong.MaxValue) * -1000)); - - // Verify the actual encoding for one of these to lock it in. - MessagePackReader reader = new(this.lastRoundtrippedMsgpack); - Assert.Equal(1, reader.ReadMapHeader()); - reader.Skip(default); // property name - Extension decimalEncoding = reader.ReadExtension(); - Assert.Equal(this.Serializer.LibraryExtensionTypeCodes.Decimal, decimalEncoding.Header.TypeCode); - Assert.Equal("00-00-00-80-E7-03-00-00-18-FC-FF-FF-FF-FF-FF-FF", BitConverter.ToString(decimalEncoding.Data.ToArray())); - } - - /// - /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. - /// - [Fact] - public void Decimal_FromBin() - { - Assert.SkipUnless(BitConverter.IsLittleEndian, "This test is written assuming little-endian."); - Span value = [new decimal(ulong.MaxValue) * -1000]; - Sequence seq = new(); - MessagePackWriter writer = new(seq); - writer.WriteMapHeader(1); - writer.Write(nameof(HasDecimal.Value)); - writer.Write(MemoryMarshal.Cast(value)); - writer.Flush(); - - Assert.Equal(value[0], this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken)!.Value); - } - - /// - /// Verifies that we can read values that use the UTF-8 encoding, which is what MessagePack-CSharp's default formatter uses. - /// - [Fact] - public void Decimal_FromString() - { - decimal value = 1.2m; - Sequence seq = new(); - MessagePackWriter writer = new(seq); - writer.WriteMapHeader(1); - writer.Write(nameof(HasDecimal.Value)); - writer.Write(value.ToString(CultureInfo.InvariantCulture)); - writer.Flush(); - - Assert.Equal(value, this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken)!.Value); - } - - [Fact] - public void BigInteger() - { - this.AssertRoundtrip(new HasBigInteger(1)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasBigInteger(ulong.MaxValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasBigInteger(ulong.MinValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasBigInteger(long.MaxValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasBigInteger(long.MinValue)); - this.AssertType(MessagePackType.Integer); - - this.AssertRoundtrip(new HasBigInteger(new BigInteger(ulong.MaxValue) * 3)); - this.AssertType(MessagePackType.Extension); - } - - /// - /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. - /// - [Fact] - public void BigInteger_FromBin() - { - BigInteger value = new BigInteger(ulong.MaxValue) * 3; - Sequence seq = new(); - MessagePackWriter writer = new(seq); - writer.WriteMapHeader(1); - writer.Write(nameof(HasBigInteger.Value)); - writer.Write(value.ToByteArray()); // Always in LE order even on BE machines. - writer.Flush(); - - Assert.Equal(value, this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken)!.Value); - } - [Fact] public void Guid() { // Test that Guid serialization works by default (using binary format) Guid value = System.Guid.NewGuid(); - this.Logger.WriteLine($"Randomly generated guid: {value}"); + Console.WriteLine($"Randomly generated guid: {value}"); ReadOnlySequence msgpack = this.AssertRoundtrip(new HasGuid(value)); Assert.True(this.DataMatchesSchema(msgpack, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow())); } - [Fact] - public void CultureInfo_Roundtrips() - { - Assert.Equal("fr-FR", this.Roundtrip(CultureInfo.GetCultureInfo("fr-FR"))?.Name); - Assert.Equal("es", this.Roundtrip(CultureInfo.GetCultureInfo("es"))?.Name); - } - - [Fact] - public void CultureInfo_Encoding() - { - byte[] msgpack = this.Serializer.Serialize(CultureInfo.GetCultureInfo("es-ES"), TestContext.Current.CancellationToken); - MessagePackReader reader = new(msgpack); - Assert.Equal("es-ES", reader.ReadString()); - } - - [Fact] - public void EventArgs_Roundtrip() - { - Assert.NotNull(this.Roundtrip(new EventArgs())); - } - - [Fact] - public void Encoding_Roundtrip() - { - Assert.Equal(Encoding.UTF8.WebName, this.Roundtrip(Encoding.UTF8)?.WebName); - } - - [Fact] - public void Encoding_Encoding() - { - byte[] msgpack = this.Serializer.Serialize(Encoding.GetEncoding("utf-8"), TestContext.Current.CancellationToken); - MessagePackReader reader = new(msgpack); - Assert.Equal("utf-8", reader.ReadString()); - } - [Theory, PairwiseData] public void Guid_StringFormats(OptionalConverters.GuidStringFormat format) { this.Serializer = this.Serializer.WithGuidConverter(format); Guid value = System.Guid.NewGuid(); - this.Logger.WriteLine($"Randomly generated guid: {value}"); + Console.WriteLine($"Randomly generated guid: {value}"); ReadOnlySequence msgpack = this.AssertRoundtrip(new HasGuid(value)); Assert.True(this.DataMatchesSchema(msgpack, Witness.GeneratedTypeShapeProvider.GetTypeShapeOrThrow())); } - [Theory, PairwiseData] - public void Guid_ParseAnyStringFormat(OptionalConverters.GuidStringFormat format, bool uppercase) - { - // Serialize the original with the specified format. - // Deserialize with any format besides the one we were expecting. - (Guid before, Guid after) = this.RoundtripModifiedGuid( - s => uppercase ? s.ToUpperInvariant() : s, - this.Serializer.WithGuidConverter(format), - this.Serializer.WithGuidConverter(format == OptionalConverters.GuidStringFormat.StringD ? OptionalConverters.GuidStringFormat.StringN : OptionalConverters.GuidStringFormat.StringD)); - - Assert.Equal(before, after); - } - - [Theory, PairwiseData] - public void Guid_TruncatedInputs(OptionalConverters.GuidStringFormat format) - { - this.Serializer = this.Serializer.WithGuidConverter(format); - - bool empty = false; - int trimCount = 1; - while (!empty) - { - MessagePackSerializationException ex = Assert.Throws(() => this.RoundtripModifiedGuid(s => - { - empty = s.Length == trimCount; - return s[..^trimCount++]; - })); - Assert.Equal(BadGuidFormatErrorMessage, ex.GetBaseException().Message); - } - } - - [Theory, PairwiseData] - public void Guid_MissingHexCharacter(OptionalConverters.GuidStringFormat format) - { - this.Serializer = this.Serializer.WithGuidConverter(format); - - // Remove a character that will be a hex character in any format. - MessagePackSerializationException ex = Assert.Throws(() => this.RoundtripModifiedGuid(s => s.Remove(6, 1))); - this.Logger.WriteLine(ex.GetBaseException().Message); - Assert.Equal(BadGuidFormatErrorMessage, ex.GetBaseException().Message); - } - - /// - /// Verifies that we can read values that use the Bin header, which is what MessagePack-CSharp's "native" formatter uses. - /// This tests interoperability with the default binary format. - /// - [Fact] - public void Guid_FromBin() - { - Assert.SkipUnless(BitConverter.IsLittleEndian, "This test is written assuming little-endian."); - - Span valueSpan = [System.Guid.NewGuid()]; - Sequence seq = new(); - MessagePackWriter writer = new(seq); - writer.WriteMapHeader(1); - writer.Write(nameof(HasGuid.Value)); - - writer.Write(MemoryMarshal.Cast(valueSpan)); - writer.Flush(); - - Assert.Equal(valueSpan[0], this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken)!.Value); - } - - [Fact] - public void DateTime() => this.AssertRoundtrip(new HasDateTime(System.DateTime.UtcNow)); - - [Fact] - public void DateTime_Unspecified() - { - MessagePackSerializationException ex = Assert.Throws(() => - this.Serializer.Serialize(new HasDateTime(new System.DateTime(2000, 1, 1)), TestContext.Current.CancellationToken)); - ArgumentException inner = Assert.IsType(ex.GetBaseException()); - this.Logger.WriteLine(inner.Message); - } - - [Theory] - [InlineData(DateTimeKind.Utc)] - [InlineData(DateTimeKind.Local)] - public void DateTime_Unspecified_UnderConfiguration(DateTimeKind kind) - { - this.Serializer = this.Serializer.WithAssumedDateTimeKind(kind); - DateTime original = new(2000, 1, 1); // Unspecified kind. - HasDateTime? deserialized = this.Roundtrip(new HasDateTime(original)); - - // Deserialized value should always be UTC. - Assert.Equal(System.DateTime.SpecifyKind(original, kind).ToUniversalTime(), deserialized?.Value); - Assert.Equal(DateTimeKind.Utc, deserialized?.Value.Kind); - } - - [Theory, PairwiseData] - public void DateTime_HiFi(DateTimeKind kind) - { - this.Serializer = this.Serializer.WithHiFiDateTime(); - DateTime original = new(2000, 1, 1, 2, 3, 4, 567, kind); - HasDateTime? deserialized = this.Roundtrip(new HasDateTime(original)); - - // Deserialized value should have retained the Kind. - Assert.Equal(original.Kind, deserialized?.Value.Kind); - - // And in all other ways, be equal. - Assert.Equal(original, deserialized?.Value); - - // Verify the actual encoding for each case. - MessagePackReader reader = new(this.lastRoundtrippedMsgpack); - reader.ReadMapHeader(); - reader.ReadString(); // skip property name - if (kind == DateTimeKind.Utc) - { - // Standard encoding. - Assert.Equal(original, reader.ReadDateTime()); - } - else - { - // HiFi encoding. - Assert.Equal(2, reader.ReadArrayHeader()); - Assert.Equal(original.Ticks, reader.ReadInt64()); - Assert.Equal((int)original.Kind, reader.ReadInt32()); - } - } - - [Fact] - public void DateTimeOffset() - { - this.AssertRoundtrip(new HasDateTimeOffset(System.DateTimeOffset.Now)); - - // Try specific offset values because CI/PR builds run on agents that run on the UTC time zone. - this.AssertRoundtrip(new HasDateTimeOffset(System.DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(4)))); - } - - [Fact] - public void ByteArrayWithOldSpec() - { - byte[] original = [1, 2, 3]; - Sequence seq = new(); - MessagePackWriter writer = new(seq) { OldSpec = true }; - this.Serializer.Serialize(ref writer, original, TestContext.Current.CancellationToken); - writer.Flush(); - - // Verify that the test is doing what we think it is. - MessagePackReader reader = new(seq); - Assert.Equal(MessagePackType.String, reader.NextMessagePackType); - - byte[]? deserialized = this.Serializer.Deserialize(seq, TestContext.Current.CancellationToken); - Assert.Equal(original, deserialized); - } - - [Fact] - public void Extension() => this.AssertRoundtrip(new Extension(15, new byte[] { 1, 2, 3 })); - - private (Guid Before, Guid After) RoundtripModifiedGuid(Func modifier, MessagePackSerializer? serializer = null, MessagePackSerializer? deserializer = null) - { - serializer ??= this.Serializer; - deserializer ??= this.Serializer; - - Guid original = System.Guid.NewGuid(); - this.Logger.WriteLine($"Randomly generated guid: {original}"); - byte[] msgpack = serializer.Serialize(original, TestContext.Current.CancellationToken); - msgpack = this.Serializer.Serialize( - modifier(this.Serializer.Deserialize(msgpack, TestContext.Current.CancellationToken)!), - TestContext.Current.CancellationToken); - this.LogMsgPack(msgpack); - Guid deserialized = deserializer.Deserialize(msgpack, TestContext.Current.CancellationToken); - return (original, deserialized); - } - - private void AssertType(MessagePackType expectedType) - { - MessagePackReader reader = new(this.lastRoundtrippedMsgpack); - reader.ReadMapHeader(); - reader.ReadString(); - Assert.Equal(expectedType, reader.NextMessagePackType); - } - - [GenerateShape] - public partial class HasImmutableDictionary : IEquatable - { - public ImmutableDictionary Map { get; set; } = ImmutableDictionary.Empty; - - public bool Equals(HasImmutableDictionary? other) => StructuralEquality.Equal(this.Map, other?.Map); - } - -#if NET - - [GenerateShape] - public partial record HasInt128(Int128 Value); - - [GenerateShape] - public partial record HasUInt128(UInt128 Value); - -#endif - -#if NET9_0_OR_GREATER - - [GenerateShape] - public partial class HasOrderedDictionary : IEquatable - { - public OrderedDictionary Map { get; set; } = new(); - - public bool Equals(HasOrderedDictionary? other) => StructuralEquality.Equal((IReadOnlyList>)this.Map, other?.Map); - } - -#endif - - [GenerateShape] - public partial record HasDecimal(decimal Value); - - [GenerateShape] - public partial record HasBigInteger(BigInteger Value); - [GenerateShape] public partial record HasGuid(Guid Value); - [GenerateShape] - public partial record HasDateTime(DateTime Value); - - [GenerateShape] - public partial record HasDateTimeOffset(DateTimeOffset Value); - - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] + [GenerateShapeFor] private partial class Witness; } diff --git a/test/Nerdbank.MessagePack.Tests/MessagePackSerializerTestBase.cs b/test/Nerdbank.MessagePack.Tests/MessagePackSerializerTestBase.cs index 9c48bfe1..349d6985 100644 --- a/test/Nerdbank.MessagePack.Tests/MessagePackSerializerTestBase.cs +++ b/test/Nerdbank.MessagePack.Tests/MessagePackSerializerTestBase.cs @@ -33,6 +33,8 @@ public MessagePackSerializerTestBase() protected MessagePackSerializer Serializer { get; set; } + protected CancellationToken TimeoutToken => TestContext.Current.CancellationToken; + protected ITestOutputHelper Logger => TestContext.Current.TestOutputHelper ?? throw new InvalidOperationException("No logger available."); public static string GetFullMessage(Exception ex) @@ -114,6 +116,8 @@ protected static string SchemaToString(JsonObject schema) return schemaString; } + protected void Log(string message) => this.Logger.WriteLine(message); + protected ReadOnlySequence AssertRoundtrip(T? value) #if NET where T : IShapeable diff --git a/test/Nerdbank.MessagePack.Tests/Nerdbank.MessagePack.Tests.csproj b/test/Nerdbank.MessagePack.Tests/Nerdbank.MessagePack.Tests.csproj index b308772d..b99842fe 100644 --- a/test/Nerdbank.MessagePack.Tests/Nerdbank.MessagePack.Tests.csproj +++ b/test/Nerdbank.MessagePack.Tests/Nerdbank.MessagePack.Tests.csproj @@ -22,25 +22,10 @@ - - - TextTemplatingFileGenerator - MessagePackReaderTests.ReadInt.cs - - - - - - True - True - MessagePackReaderTests.ReadInt.tt - - - $([System.IO.Path]::Combine('$(MSBuildProjectDirectory)','Resources','KnownGoodSchemas')) @@ -48,7 +33,8 @@ - + + diff --git a/test/Nerdbank.MessagePack.Tests/StructuralEqualityComparerTests.cs b/test/Nerdbank.MessagePack.Tests/StructuralEqualityComparerTests.cs index ed6d4344..5d6fd95d 100644 --- a/test/Nerdbank.MessagePack.Tests/StructuralEqualityComparerTests.cs +++ b/test/Nerdbank.MessagePack.Tests/StructuralEqualityComparerTests.cs @@ -6,71 +6,11 @@ #pragma warning disable CS8767 // null ref annotations #endif -using System.Numerics; using PolyType.Tests; using Xunit.Sdk; -public abstract partial class StructuralEqualityComparerTests(ITestOutputHelper logger) +public abstract partial class StructuralEqualityComparerTests { - internal enum FruitKind - { - Apple, - Banana, - } - - [Fact] - public void Boolean() => this.AssertEqualityComparerBehavior([true], [false]); - - [Fact] - public void BigInteger() => this.AssertEqualityComparerBehavior([new BigInteger(5), new BigInteger(5)], [new BigInteger(10)]); - - [Fact] - public void CustomType_Tree() => this.AssertEqualityComparerBehavior( - [new Tree([new Fruit(3, "Red"), new Fruit(4, "Green")], 4, FruitKind.Apple), new Tree([new Fruit(3, "Red"), new Fruit(4, "Green")], 4, FruitKind.Apple)], - [ - new Tree([new Fruit(3, "Red"), new Fruit(4, "Yellow")], 4, FruitKind.Apple), - new Tree([new Fruit(3, "Red"), new Fruit(4, "Green")], 4, FruitKind.Banana), - new Tree([new Fruit(4, "Red")], 4, FruitKind.Banana), - new Tree([new Fruit(3, "Yellow")], 4, FruitKind.Apple)]); - - [Fact] - public void CustomType_Fruit() => this.AssertEqualityComparerBehavior( - [new Fruit(3, "Red"), new Fruit(3, "Red")], - [new Fruit(4, "Red"), new Fruit(3, "Yellow")]); - - [Fact] - public abstract void CustomHash(); - - [Fact] - public void CustomHashingAndEquality() => this.AssertEqualityComparerBehavior( - [new CustomHasher(), new CustomHasher()], - [new CustomHasher() { SpecialCode = 33 }]); - - [Fact] - public void ReadOnlyMemoryOfByte() => this.AssertEqualityComparerBehavior( - [new HaveReadOnlyMemoryOfByte(new byte[] { 1, 2 }), new HaveReadOnlyMemoryOfByte(new byte[] { 1, 2 })], - [new HaveReadOnlyMemoryOfByte(new byte[] { 1, 3 }), new HaveReadOnlyMemoryOfByte(new byte[] { 1, 2, 3 })]); - - [Fact] - public void ReadOnlySequenceOfByte() => this.AssertEqualityComparerBehavior( - [new HaveReadOnlySequenceOfByte(new([1, 2])), new HaveReadOnlySequenceOfByte(new([1, 2]))], - [new HaveReadOnlySequenceOfByte(new([1, 3])), new HaveReadOnlySequenceOfByte(new([1, 2, 3]))]); - - [Fact] - public void DerivedTypeEquality() - { - SomeBaseType.Derived1 derived1A = new(42); - SomeBaseType.Derived1 derived1B = new(42); - SomeBaseType.Derived1 derived1C = new(43); - SomeBaseType.Derived2 derived2A = new(42); - SomeBaseType.Derived3 derived3 = new(); - SomeBaseType.Derived4 derived4 = new(); - - this.AssertEqualityComparerBehavior( - [derived1A, derived1B], - [derived1C, derived2A, derived3, derived4]); - } - [Theory] [MemberData(nameof(TestTypes.GetTestCases), MemberType = typeof(TestTypes))] #if NET @@ -128,175 +68,5 @@ public void GetHashCode_Exhaustive(TestCase testCase) } } - protected IEqualityComparer GetEqualityComparer() -#if NET - where TProvider : IShapeable => this.GetEqualityComparer(TProvider.GetTypeShape()); -#else - => this.GetEqualityComparer(TypeShapeResolver.ResolveDynamicOrThrow()); -#endif - - protected IEqualityComparer GetEqualityComparer() -#if NET - where T : IShapeable => this.GetEqualityComparer(T.GetTypeShape()); -#else - => this.GetEqualityComparer(Witness.GeneratedTypeShapeProvider.GetTypeShape()); -#endif - protected abstract IEqualityComparer GetEqualityComparer(ITypeShape shape); - - /// - private void AssertEqualityComparerBehavior(T[] equivalent, T[] different) -#if NET - where T : notnull, IShapeable => this.AssertEqualityComparerBehavior(equivalent, different); -#else - where T : notnull => this.AssertEqualityComparerBehavior(equivalent, different); -#endif - - /// - /// Asserts that hash codes and equality checks match or mismatch for various values. - /// - /// The type of the values to be tested. - /// The witness type for the data type. - /// An array of values that should all be considered equivalent. - /// An array of values that are each distinct from any of the values in the array. - private void AssertEqualityComparerBehavior(T[] equivalent, T[] different) -#if NET - where TProvider : IShapeable -#endif - where T : notnull - { - IEqualityComparer eq = this.GetEqualityComparer(); - - logger.WriteLine("Testing values that are expected to be equal:"); - foreach (T valueA in equivalent) - { - int valueAHashCode = eq.GetHashCode(valueA); - logger.WriteLine($"{valueA} hash code: {valueAHashCode}"); - - foreach (T valueB in equivalent) - { - int valueBHashCode = eq.GetHashCode(valueB); - logger.WriteLine($"{valueB} hash code: {valueBHashCode}"); - Assert.True(eq.Equals(valueA, valueB)); - Assert.Equal(valueAHashCode, valueBHashCode); - } - } - - logger.WriteLine("Testing values that are expected to be different:"); - T baseline = equivalent[0]; - int baselineHashCode = eq.GetHashCode(baseline); - foreach (T differentValue in different) - { - int differentValueHashCode = eq.GetHashCode(differentValue); - logger.WriteLine($"{differentValue} hash code: {differentValueHashCode}"); - Assert.False(eq.Equals(equivalent[0], differentValue)); - Assert.NotEqual(baselineHashCode, differentValueHashCode); - } - } - - public class DefaultStructural(ITestOutputHelper logger) : StructuralEqualityComparerTests(logger) - { - [Fact] - public override void CustomHash() - { - CustomHasher obj = new(); - Assert.Equal(obj.SpecialCode, this.GetEqualityComparer().GetHashCode(obj)); - } - - protected override IEqualityComparer GetEqualityComparer(ITypeShape shape) - => StructuralEqualityComparer.GetDefault(shape); - } - - public class HashCollisionResistant(ITestOutputHelper logger) : StructuralEqualityComparerTests(logger) - { - [Fact] - public override void CustomHash() - { - CustomHasher obj = new(); - Assert.Equal(obj.SpecialCode * 2, this.GetEqualityComparer().GetHashCode(obj)); - } - - protected override IEqualityComparer GetEqualityComparer(ITypeShape shape) - => StructuralEqualityComparer.GetHashCollisionResistant(shape); - } - - [GenerateShapeFor] - [GenerateShapeFor] - [GenerateShapeFor] - internal partial class Witness; - - [GenerateShape] - internal partial class Tree(Fruit[] fruits, int height, FruitKind kind) - { - public Fruit[] Fruits => fruits; - - public int Height => height; - - public FruitKind Kind => kind; - - public override string ToString() => $"{kind} tree with {fruits.Length} fruits and height {height}"; - } - - [GenerateShape] - internal partial class Fruit(int weight, string color) - { - public int Weight => weight; - - public string Color => color; - - public override string ToString() => $"Fruit weighing {weight} and color {color}"; - } - - [GenerateShape] - internal partial class HaveReadOnlyMemoryOfByte(ReadOnlyMemory buffer) - { - public ReadOnlyMemory Buffer => buffer; - } - - [GenerateShape] - internal partial class HaveReadOnlySequenceOfByte(ReadOnlySequence buffer) - { - public ReadOnlySequence Buffer => buffer; - } - - [GenerateShape] - internal partial class CustomHasher : IStructuralSecureEqualityComparer - { - // This is internal on purpose, so that PolyType will ignore the property for purposes of equality - // and hashing, and tests will only pass if the custom hash and equality methods on this class are used. - internal int SpecialCode { get; set; } = 42; - - public bool StructuralEquals(CustomHasher? other) => other is not null && this.SpecialCode == other.SpecialCode; - - public long GetSecureHashCode() => this.SpecialCode * 2; - - public override int GetHashCode() => this.SpecialCode; - } - - [GenerateShape] - [DerivedTypeShape(typeof(Derived1))] - [DerivedTypeShape(typeof(Derived2))] - [DerivedTypeShape(typeof(Derived3))] - [DerivedTypeShape(typeof(Derived4))] - internal abstract partial record SomeBaseType - { - internal record Derived1(int Value) : SomeBaseType; - - internal record Derived2(int Value) : SomeBaseType; - - internal record Derived3 : SomeBaseType; - - [TypeShape(Marshaler = typeof(Marshaler))] - internal record Derived4 : SomeBaseType - { - internal class Marshaler : IMarshaler - { - public Surrogate? Marshal(Derived4? value) => value is null ? null : default(Surrogate); - - public Derived4? Unmarshal(Surrogate? value) => value is null ? null : new Derived4(); - - internal struct Surrogate; - } - } - } }