Skip to content

Commit b102eba

Browse files
committed
add tests for #107
1 parent c19e8bf commit b102eba

File tree

1 file changed

+121
-0
lines changed
  • tests/protobuf-net.Grpc.Test.Integration/Issues

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
using Grpc.Core;
2+
using ProtoBuf.Grpc.Client;
3+
using ProtoBuf.Grpc.Configuration;
4+
using ProtoBuf.Grpc.Server;
5+
using ProtoBuf.Meta;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
using System.Runtime.Serialization;
10+
using System.ServiceModel;
11+
using System.Threading.Tasks;
12+
using Xunit;
13+
using Xunit.Abstractions;
14+
15+
namespace protobuf_net.Grpc.Test.Integration.Issues
16+
{
17+
public class Issue107 : IClassFixture<Issue107.MyServer<Issue107.Derived<string>>>
18+
{
19+
20+
public abstract class MyServerBase // exists purely for .cctor init timing reasons
21+
{
22+
static MyServerBase()
23+
{
24+
RuntimeTypeModel.Default[typeof(Base<string>)].AddSubType(42, typeof(Derived<string>));
25+
}
26+
}
27+
public class MyServer<T> : MyServerBase, IDisposable, ICalculatorService<T>
28+
{
29+
Server _server;
30+
public MyServer()
31+
{
32+
_server = new Server
33+
{
34+
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
35+
};
36+
_server.Services.AddCodeFirst(this, interceptors: new[] { SimpleRpcExceptionsInterceptor.Instance });
37+
_server.Start();
38+
}
39+
public int Port { get; } = PortManager.GetNextPort();
40+
41+
void IDisposable.Dispose() => _ = _server.ShutdownAsync();
42+
43+
async IAsyncEnumerable<T> ICalculatorService<T>.Duplex(IAsyncEnumerable<T> input)
44+
{
45+
await foreach (var value in input)
46+
{
47+
yield return value;
48+
}
49+
}
50+
}
51+
52+
private readonly MyServer<Derived<string>> _server;
53+
private readonly ITestOutputHelper _log;
54+
private void Log(string message) => _log?.WriteLine(message);
55+
private int Port => _server.Port;
56+
public Issue107(ITestOutputHelper log, MyServer<Derived<string>> server)
57+
{
58+
_log = log;
59+
_server = server;
60+
}
61+
62+
[Fact]
63+
public void IsSubTypeConfigured()
64+
{
65+
var subType = Assert.Single(RuntimeTypeModel.Default[typeof(Base<string>)].GetSubtypes());
66+
Assert.Equal(42, subType.FieldNumber);
67+
Assert.Equal(typeof(Derived<string>), subType.DerivedType.Type);
68+
}
69+
70+
[Fact]
71+
public async Task GenericsTest()
72+
{
73+
Channel channel = new Channel("localhost", Port, ChannelCredentials.Insecure);
74+
var calculator = channel.CreateGrpcService<ICalculatorService<Derived<string>>>();
75+
76+
var input = new[] { "1", "2" };
77+
var inputString = string.Join(",", input);
78+
Log($"Sending: {inputString}");
79+
80+
var stream = calculator.Duplex(ToAsyncEnumerable(input.Select(x => new Derived<string> { Value = x })));
81+
82+
var output = await ToArrayAsync(stream);
83+
var outputString = string.Join(",", output.Select(x => x.Value));
84+
Log($"Received: {inputString}");
85+
Assert.Equal(inputString, outputString);
86+
}
87+
88+
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
89+
async static IAsyncEnumerable<T> ToAsyncEnumerable<T>(IEnumerable<T> source)
90+
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
91+
{
92+
foreach (var item in source)
93+
yield return item;
94+
}
95+
async static ValueTask<T[]> ToArrayAsync<T>(IAsyncEnumerable<T> source)
96+
{
97+
var list = new List<T>();
98+
await foreach (var item in source.ConfigureAwait(false))
99+
list.Add(item);
100+
return list.ToArray();
101+
}
102+
103+
[DataContract]
104+
public class Derived<T> : Base<T>
105+
{
106+
}
107+
108+
[DataContract]
109+
public class Base<T>
110+
{
111+
[DataMember(Order = 1)]
112+
public T Value { get; set; }
113+
}
114+
115+
[ServiceContract]
116+
public interface ICalculatorService<T>
117+
{
118+
IAsyncEnumerable<T> Duplex(IAsyncEnumerable<T> input);
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)