-
-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #899 from Cysharp/feature/NativeAotTests
Add unit tests for Native AOT
- Loading branch information
Showing
9 changed files
with
443 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
tests/MagicOnion.Client.NativeAot.Tests/IUnaryTestService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using MessagePack; | ||
|
||
namespace MagicOnion.Client.NativeAot.Tests; | ||
|
||
public interface IUnaryTestService : IService<IUnaryTestService> | ||
{ | ||
UnaryResult<int> TwoParametersReturnValueType(int arg1, string arg2); | ||
|
||
UnaryResult Enum(MyEnumValue value); | ||
UnaryResult<MyEnumValue> EnumReturn(); | ||
|
||
UnaryResult BuiltInGeneric(List<MyObject> arg); | ||
UnaryResult<Dictionary<MyObject, string>> BuiltInGenericReturn(); | ||
} | ||
|
||
public enum MyEnumValue | ||
{ | ||
A, | ||
B, | ||
C, | ||
} | ||
|
||
[MessagePackObject] | ||
public record MyObject([property: Key(0)] int Value); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] |
34 changes: 34 additions & 0 deletions
34
tests/MagicOnion.Client.NativeAot.Tests/MagicOnion.Client.NativeAot.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<Project Sdk="MSTest.Sdk/3.6.1"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net9.0</TargetFramework> | ||
<LangVersion>latest</LangVersion> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<OutputType>exe</OutputType> | ||
<PublishAot>true</PublishAot> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="..\MagicOnion.Client.Tests\ChannelAsyncStreamReader.cs" Link="Shared\ChannelAsyncStreamReader.cs" /> | ||
<Compile Include="..\MagicOnion.Client.Tests\ChannelClientStreamWriter.cs" Link="Shared\ChannelClientStreamWriter.cs" /> | ||
<Compile Include="..\MagicOnion.Client.Tests\MockAsyncStreamReader.cs" Link="Shared\MockAsyncStreamReader.cs" /> | ||
<Compile Include="..\MagicOnion.Client.Tests\MockClientStreamWriter.cs" Link="Shared\MockClientStreamWriter.cs" /> | ||
<Compile Include="..\MagicOnion.Client.Tests\MockSerializationContext.cs" Link="Shared\MockSerializationContext.cs" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\MagicOnion.Client\MagicOnion.Client.csproj" /> | ||
<ProjectReference Include="..\..\src\MagicOnion.Client.SourceGenerator\MagicOnion.Client.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" /> | ||
</ItemGroup> | ||
|
||
</Project> |
53 changes: 53 additions & 0 deletions
53
tests/MagicOnion.Client.NativeAot.Tests/MockCallInvoker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System.Buffers; | ||
using System.Threading.Channels; | ||
using Grpc.Core; | ||
using MagicOnion.Client.Tests; | ||
|
||
namespace MagicOnion.Client.NativeAot.Tests; | ||
|
||
public class MockCallInvoker : CallInvoker | ||
{ | ||
public List<byte[]> RequestPayloads { get; } = new(); | ||
public Channel<byte[]> ResponseChannel { get; } = Channel.CreateUnbounded<byte[]>(); | ||
|
||
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options, TRequest request) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options, TRequest request) | ||
{ | ||
var serializationContext = new MockSerializationContext(); | ||
method.RequestMarshaller.ContextualSerializer(request, serializationContext); | ||
RequestPayloads.Add(serializationContext.ToMemory().ToArray()); | ||
|
||
return new AsyncUnaryCall<TResponse>( | ||
ResponseChannel.Reader.ReadAsync().AsTask().ContinueWith(x => method.ResponseMarshaller.ContextualDeserializer(new MockDeserializationContext(x.Result))), | ||
Task.FromResult(Metadata.Empty), | ||
() => Status.DefaultSuccess, | ||
() => Metadata.Empty, | ||
() => { }); | ||
} | ||
|
||
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options, TRequest request) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
|
||
class MockDeserializationContext(byte[] payload) : DeserializationContext | ||
{ | ||
public override int PayloadLength => payload.Length; | ||
public override byte[] PayloadAsNewBuffer() => payload.ToArray(); | ||
public override ReadOnlySequence<byte> PayloadAsReadOnlySequence() => new ReadOnlySequence<byte>(payload); | ||
} |
159 changes: 159 additions & 0 deletions
159
tests/MagicOnion.Client.NativeAot.Tests/ResolverTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
using System.Buffers; | ||
using MessagePack.Resolvers; | ||
|
||
namespace MagicOnion.Client.NativeAot.Tests; | ||
|
||
// NOTE: This test uses a Resolver that contains code corresponding to the arguments and return values of IUnaryTestService. | ||
[TestClass] | ||
public sealed class ResolverTest | ||
{ | ||
static ResolverTest() | ||
{ | ||
// WORKAROUND: GeneratedAssemblyMessagePackResolverAttribute in MessagePack v3.1.1 does not consider trimming, causing type metadata to be removed. | ||
_ = typeof(MessagePack.GeneratedMessagePackResolver).GetFields(); | ||
} | ||
|
||
[TestMethod] | ||
public void MyObject() | ||
{ | ||
// Arrange | ||
var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
var arrayBufferWriter = new ArrayBufferWriter<byte>(); | ||
var writer = new MessagePackWriter(arrayBufferWriter); | ||
|
||
// Act | ||
var formatter = SourceGeneratedFormatterResolver.Instance.GetFormatter<MyObject>(); | ||
formatter?.Serialize(ref writer, new MyObject(12345), options); | ||
writer.Flush(); | ||
|
||
// Assert | ||
Assert.IsNotNull(formatter); | ||
Assert.AreEqual("0x91, 0xcd, 0x30, 0x39", string.Join(", ", arrayBufferWriter.WrittenMemory.ToArray().Select(x => $"0x{x:x2}"))); | ||
} | ||
|
||
[TestMethod] | ||
public void DynamicArgumentTuple() | ||
{ | ||
// Arrange | ||
var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
var arrayBufferWriter = new ArrayBufferWriter<byte>(); | ||
var writer = new MessagePackWriter(arrayBufferWriter); | ||
|
||
// Act | ||
var formatter = options.Resolver.GetFormatter<DynamicArgumentTuple<int, string>>(); | ||
formatter?.Serialize(ref writer, new DynamicArgumentTuple<int, string>(12345, "Hello world!"), options); | ||
writer.Flush(); | ||
|
||
// Assert | ||
Assert.IsNotNull(formatter); | ||
Assert.AreEqual("0x92, 0xcd, 0x30, 0x39, 0xac, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21", string.Join(", ", arrayBufferWriter.WrittenMemory.ToArray().Select(x => $"0x{x:x2}"))); | ||
} | ||
|
||
//[TestMethod] | ||
//public void DynamicArgumentTuple_Unknown() | ||
//{ | ||
// // Arrange | ||
// var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
|
||
// // Act | ||
// var formatter = options.Resolver.GetFormatter<DynamicArgumentTuple<int, string, object, bool, Uri, Guid, MyEnumValue>>(); | ||
|
||
// // Assert | ||
// Assert.IsNull(formatter); | ||
//} | ||
|
||
[TestMethod] | ||
public void Enum() | ||
{ | ||
// Arrange | ||
var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
var arrayBufferWriter = new ArrayBufferWriter<byte>(); | ||
var writer = new MessagePackWriter(arrayBufferWriter); | ||
|
||
// Act | ||
var formatter = options.Resolver.GetFormatter<MyEnumValue>(); | ||
formatter?.Serialize(ref writer, MyEnumValue.C, options); | ||
writer.Flush(); | ||
|
||
// Assert | ||
Assert.IsNotNull(formatter); | ||
Assert.AreEqual("0x02", string.Join(", ", arrayBufferWriter.WrittenMemory.ToArray().Select(x => $"0x{x:x2}"))); | ||
} | ||
|
||
//[TestMethod] | ||
//public void Enum_Unknown() | ||
//{ | ||
// // Arrange | ||
// var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
|
||
// // Act | ||
// var formatter = options.Resolver.GetFormatter<UnknownEnumValue>(); | ||
|
||
// // Assert | ||
// Assert.IsNull(formatter); | ||
//} | ||
|
||
[TestMethod] | ||
public void BuiltInGenerics_List() | ||
{ | ||
// Arrange | ||
var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
var arrayBufferWriter = new ArrayBufferWriter<byte>(); | ||
var writer = new MessagePackWriter(arrayBufferWriter); | ||
|
||
// Act | ||
var formatter = options.Resolver.GetFormatter<List<MyObject>>(); | ||
formatter?.Serialize(ref writer, [new MyObject(1), new MyObject(100), new MyObject(1000)], options); | ||
writer.Flush(); | ||
|
||
// Assert | ||
Assert.IsNotNull(formatter); | ||
Assert.AreEqual("0x93, 0x91, 0x01, 0x91, 0x64, 0x91, 0xcd, 0x03, 0xe8", string.Join(", ", arrayBufferWriter.WrittenMemory.ToArray().Select(x => $"0x{x:x2}"))); | ||
} | ||
|
||
[TestMethod] | ||
public void BuiltInGenerics_Dictionary() | ||
{ | ||
// Arrange | ||
var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
var arrayBufferWriter = new ArrayBufferWriter<byte>(); | ||
var writer = new MessagePackWriter(arrayBufferWriter); | ||
|
||
// Act | ||
var formatter = options.Resolver.GetFormatter<Dictionary<MyObject, string>>(); | ||
formatter?.Serialize(ref writer, new Dictionary<MyObject, string>() | ||
{ | ||
[new MyObject(12345)] = "Hello", | ||
[new MyObject(67890)] = "World", | ||
}, options); | ||
writer.Flush(); | ||
|
||
// Assert | ||
Assert.IsNotNull(formatter); | ||
Assert.AreEqual("0x82, 0x91, 0xcd, 0x30, 0x39, 0xa5, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x91, 0xce, 0x00, 0x01, 0x09, 0x32, 0xa5, 0x57, 0x6f, 0x72, 0x6c, 0x64", string.Join(", ", arrayBufferWriter.WrittenMemory.ToArray().Select(x => $"0x{x:x2}"))); | ||
} | ||
|
||
//[TestMethod] | ||
//public void BuiltInGenerics_Unknown() | ||
//{ | ||
// // Arrange | ||
// var options = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(MagicOnionClientGeneratedInitializer.Resolver, StandardResolver.Instance)); | ||
|
||
// // Act | ||
// var formatter1 = options.Resolver.GetFormatter<List<UnknownObject>>(); | ||
// var formatter2 = options.Resolver.GetFormatter<Dictionary<UnknownObject, string>>(); | ||
|
||
// // Assert | ||
// Assert.IsNull(formatter1); | ||
// Assert.IsNull(formatter2); | ||
//} | ||
|
||
class UnknownObject; | ||
|
||
enum UnknownEnumValue | ||
{ | ||
A, | ||
B, | ||
C, | ||
} | ||
} |
Oops, something went wrong.