Skip to content

Commit bb1961b

Browse files
authored
Fix issue with sub-type length mismatch (#102)
* add failing tests for #100 * consume pb-net 3.0.1; fix #100
1 parent 000c1a2 commit bb1961b

File tree

2 files changed

+164
-1
lines changed

2 files changed

+164
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
using Grpc.Core;
2+
using ProtoBuf;
3+
using ProtoBuf.Grpc.Configuration;
4+
using System;
5+
using System.Threading.Tasks;
6+
using ProtoBuf.Grpc.Server;
7+
using Xunit;
8+
using ProtoBuf.Grpc.Client;
9+
using Xunit.Abstractions;
10+
using ProtoBuf.Meta;
11+
using System.Buffers;
12+
using Xunit.Sdk;
13+
using System.IO;
14+
using System.Runtime.InteropServices;
15+
16+
#nullable disable
17+
18+
namespace protobuf_net.Grpc.Test.Integration.Issues
19+
{
20+
public class Issue100 : IClassFixture<Issue100.Issue100ServerFixture>
21+
{
22+
#if !NET472 // need ABW
23+
[Fact]
24+
public async Task MeasuredSerialize()
25+
{
26+
var obj = await _server.GetTestInstance();
27+
var ms = new MemoryStream();
28+
Serializer.Serialize(ms, obj); // regular serialize
29+
Assert.Equal(14, ms.Length);
30+
var expected = BitConverter.ToString(ms.GetBuffer(), 0, (int)ms.Length);
31+
Log(expected);
32+
Assert.Equal("0A-0C-0A-05-0A-03-64-65-66-12-03-61-62-63", expected);
33+
34+
/*
35+
Field #1: 0A String Length = 12, Hex = 0C, UTF8 = " defabc"
36+
As sub-object :
37+
Field #1: 0A String Length = 5, Hex = 0C, UTF8 = " def"
38+
As sub-object :
39+
Field #1: 0A String Length = 3, Hex = 0C, UTF8 = "def"
40+
Field #2: 65 String Length = 3, Hex = 66, UTF8 = "abc"
41+
*/
42+
43+
44+
// now try measured
45+
if ((object)RuntimeTypeModel.Default is IMeasuredProtoOutput<IBufferWriter<byte>> writer)
46+
{
47+
using var measured = writer.Measure(obj);
48+
Assert.Equal(ms.Length, measured.Length);
49+
50+
var abw = new ArrayBufferWriter<byte>();
51+
writer.Serialize(measured, abw);
52+
Assert.Equal(ms.Length, abw.WrittenCount);
53+
54+
var mem = abw.WrittenMemory;
55+
Assert.True(MemoryMarshal.TryGetArray(mem, out var segment));
56+
var actual = BitConverter.ToString(segment.Array, segment.Offset, segment.Count);
57+
Log(actual);
58+
Assert.Equal(expected, actual);
59+
}
60+
}
61+
#endif
62+
63+
const int Port = 12315;
64+
65+
[Service]
66+
public interface ITest
67+
{
68+
ValueTask<TestObject> GetTestInstance();
69+
}
70+
71+
72+
private readonly ITestOutputHelper _log;
73+
ITest _server;
74+
private void Log(string message) => _log?.WriteLine(message);
75+
76+
77+
public Issue100(Issue100ServerFixture server, ITestOutputHelper log)
78+
{
79+
_server = server;
80+
_log = log;
81+
GrpcClientFactory.AllowUnencryptedHttp2 = true;
82+
}
83+
84+
public class Issue100ServerFixture : ITest, IAsyncDisposable
85+
{
86+
public ValueTask DisposeAsync() => new ValueTask(_server.KillAsync());
87+
88+
private readonly Server? _server;
89+
public Issue100ServerFixture()
90+
{
91+
_server = new Server
92+
{
93+
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
94+
};
95+
_server.Services.AddCodeFirst(this);
96+
_server.Start();
97+
}
98+
ValueTask<TestObject> ITest.GetTestInstance()
99+
{
100+
var obj = new TestObject
101+
{
102+
Test = new TestThingy { SomeText = "abc", SomeText2 = "def" }
103+
};
104+
return new ValueTask<TestObject>(obj);
105+
}
106+
}
107+
108+
[Fact]
109+
public async Task Issue100_UnmanagedClient()
110+
{
111+
var channel = new Channel("localhost", Port, ChannelCredentials.Insecure);
112+
try
113+
{
114+
var client = channel.CreateGrpcService<ITest>();
115+
var obj = await client.GetTestInstance();
116+
Assert.Equal("abc", obj.Test.SomeText);
117+
Assert.Equal("def", obj.Test.SomeText2);
118+
}
119+
finally
120+
{
121+
await channel.ShutdownAsync();
122+
}
123+
}
124+
125+
#if NETCOREAPP3_1
126+
[Fact]
127+
public async Task Issue100_ManagedClient()
128+
{
129+
using var http = global::Grpc.Net.Client.GrpcChannel.ForAddress($"http://localhost:{Port}");
130+
var client = http.CreateGrpcService<ITest>();
131+
var obj = await client.GetTestInstance();
132+
Assert.Equal("abc", obj.Test.SomeText);
133+
Assert.Equal("def", obj.Test.SomeText2);
134+
}
135+
#endif
136+
137+
138+
[ProtoContract]
139+
public class TestObject
140+
{
141+
[ProtoMember(1)]
142+
public TestThingy Test { get; set; }
143+
}
144+
145+
[ProtoContract]
146+
[ProtoInclude(1, typeof(TestThingy))]
147+
public abstract class TestBase
148+
{
149+
[ProtoMember(2)]
150+
public string SomeText { get; set; }
151+
152+
public abstract string SomeText2 { get; set; }
153+
}
154+
155+
[ProtoContract]
156+
public class TestThingy : TestBase
157+
{
158+
[ProtoMember(1)]
159+
public override string SomeText2 { get; set; }
160+
}
161+
}
162+
}

tests/protobuf-net.Grpc.Test.IntegrationUpLevel/protobuf-net.Grpc.Test.IntegrationUpLevel.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<ItemGroup>
1313
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
14-
<PackageReference Include="protobuf-net" Version="3.0.0-alpha.154" />
14+
<PackageReference Include="protobuf-net" Version="3.0.1" />
1515
<PackageReference Include="System.Collections.Immutable" Version="1.7.1" />
1616
<PackageReference Include="xunit" Version="2.4.1" />
1717
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
@@ -22,6 +22,7 @@
2222

2323
<ItemGroup>
2424
<Compile Include="..\protobuf-net.Grpc.Test.Integration\*.cs" />
25+
<Compile Include="..\protobuf-net.Grpc.Test.Integration\Issues\**\*.cs" />
2526
<ProjectReference Include="..\..\src\protobuf-net.Grpc.Native\protobuf-net.Grpc.Native.csproj" />
2627
<ProjectReference Include="..\..\src\protobuf-net.Grpc\protobuf-net.Grpc.csproj" />
2728
</ItemGroup>

0 commit comments

Comments
 (0)