Skip to content

Commit 9a80af1

Browse files
committed
添加测试代码
1 parent a632e2f commit 9a80af1

File tree

4 files changed

+326
-1
lines changed

4 files changed

+326
-1
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</PropertyGroup>
1010

1111
<PropertyGroup>
12-
<Version>0.0.1-preview-001</Version>
12+
<Version>0.0.1-preview-002</Version>
1313

1414
<Description>a network application framework for rapid development of maintainable protocol servers and clients. 一个用于快速开发可维护的协议的服务器和客户端的网络应用程序框架。</Description>
1515

src/Hoarwell/Transport/SocketServerConnectorFactory.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public async IAsyncEnumerable<IDuplexPipeConnector<Stream, Stream>> GetAsync([En
5858

5959
try
6060
{
61+
socket.Bind(endPoint);
62+
6163
//TODO backlog optionable
6264
socket.Listen(int.MaxValue);
6365
}
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
using System.Net;
2+
using Hoarwell.Client;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.DependencyInjection.Extensions;
5+
6+
namespace Hoarwell;
7+
8+
//TODO 复用重复的测试代码
9+
10+
[TestClass]
11+
public class CommunicationSocketServerBaseTest
12+
{
13+
#region Public 方法
14+
15+
[TestMethod]
16+
[DataRow(1)]
17+
[DataRow(2)]
18+
[DataRow(3)]
19+
[DataRow(4)]
20+
[DataRow(5)]
21+
[DataRow(6)]
22+
[DataRow(7)]
23+
[DataRow(8)]
24+
public async Task ShouldEchoSucceedAsync(int lengthDataSize)
25+
{
26+
var endpoint = IPEndPoint.Parse("127.0.0.1:12342");
27+
var serverRunnerInfo = await InitServer(endpoint, lengthDataSize);
28+
await serverRunnerInfo.Runner.StartAsync();
29+
30+
var clientRunnerInfo = await InitClient(endpoint, lengthDataSize);
31+
using var waiter = clientRunnerInfo.Runner.GetContextWaiter();
32+
await clientRunnerInfo.Runner.StartAsync();
33+
34+
try
35+
{
36+
var context = await waiter.Task;
37+
38+
var handler = context.Services.GetRequiredService<EchoDataClientMessageHandler>();
39+
40+
await context.WriteAndFlushAsync(new EchoData() { Id = 1, Message = "Hello" });
41+
42+
await handler.TaskCompletionSource.Task;
43+
}
44+
finally
45+
{
46+
await DisposeRunnerInfoAsync(clientRunnerInfo);
47+
await DisposeRunnerInfoAsync(serverRunnerInfo);
48+
}
49+
}
50+
51+
#endregion Public 方法
52+
53+
#region Private 方法
54+
55+
private async Task DisposeRunnerInfoAsync(RunnerInfo runnerInfo)
56+
{
57+
await runnerInfo.Runner.DisposeAsync();
58+
if (runnerInfo.ServiceProvider is IAsyncDisposable asyncDisposable)
59+
{
60+
await asyncDisposable.DisposeAsync();
61+
}
62+
}
63+
64+
private Task<RunnerInfo> InitClient(EndPoint endPoint, int lengthDataSize)
65+
{
66+
var services = new ServiceCollection();
67+
68+
var handler = new EchoDataClientMessageHandler(1);
69+
services.TryAddKeyedSingleton("Client", handler);
70+
services.TryAddSingleton(handler);
71+
72+
services.AddHoarwell("Client")
73+
.UseDefaultStreamApplication()
74+
.UseDefaultSocketTransportClient(options => options.EndPoints.Add(endPoint))
75+
.UseDefaultSerializer(serializerBuilder =>
76+
{
77+
#if NET7_0_OR_GREATER
78+
serializerBuilder.AddMessage<EchoData>();
79+
#else
80+
serializerBuilder.AddMessage(typeof(EchoData), ObjectBinaryParseHelper.WrapToParseAsObject<EchoData>(EchoData.TryParse));
81+
#endif
82+
})
83+
.UseDefaultTypeIdentifierAnalyzer(typeIdentifierAnalyzerBuilder =>
84+
{
85+
#if NET7_0_OR_GREATER
86+
typeIdentifierAnalyzerBuilder.AddMessage<EchoData>();
87+
#else
88+
typeIdentifierAnalyzerBuilder.AddMessage(typeof(EchoData), EchoData.TypeIdentifier.ToArray());
89+
#endif
90+
})
91+
.ConfigureInboundPipeline(pipelineBuilder =>
92+
{
93+
pipelineBuilder.UsePipeReaderAdaptMiddleware()
94+
.UseLengthFieldBasedFrameDecoder(lengthDataSize)
95+
.UseDefaultMessageDeserializer()
96+
.RunEndpoint(endpointBuilder =>
97+
{
98+
endpointBuilder.Handle<EchoData, EchoDataClientMessageHandler>(handler);
99+
});
100+
})
101+
.ConfigureOutboundPipeline(pipelineBuilder =>
102+
{
103+
pipelineBuilder.UseLengthFieldBasedFrameEncoder(lengthDataSize)
104+
.RunDefaultMessageSerializer();
105+
});
106+
107+
services.AddLogging();
108+
109+
var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions() { ValidateOnBuild = true, ValidateScopes = true });
110+
var applicationRunner = serviceProvider.GetRequiredKeyedService<IHoarwellApplicationRunner>("Client");
111+
112+
var result = new RunnerInfo(serviceProvider, applicationRunner);
113+
return Task.FromResult(result);
114+
}
115+
116+
private Task<RunnerInfo> InitServer(EndPoint endPoint, int lengthDataSize)
117+
{
118+
var services = new ServiceCollection();
119+
120+
services.AddHoarwell("Server")
121+
.UseDefaultStreamApplication()
122+
.UseDefaultSocketTransportServer(options => options.EndPoints.Add(endPoint))
123+
.UseDefaultSerializer(serializerBuilder =>
124+
{
125+
#if NET7_0_OR_GREATER
126+
serializerBuilder.AddMessage<EchoData>();
127+
#else
128+
serializerBuilder.AddMessage(typeof(EchoData), ObjectBinaryParseHelper.WrapToParseAsObject<EchoData>(EchoData.TryParse));
129+
#endif
130+
})
131+
.UseDefaultTypeIdentifierAnalyzer(typeIdentifierAnalyzerBuilder =>
132+
{
133+
#if NET7_0_OR_GREATER
134+
typeIdentifierAnalyzerBuilder.AddMessage<EchoData>();
135+
#else
136+
typeIdentifierAnalyzerBuilder.AddMessage(typeof(EchoData), EchoData.TypeIdentifier.ToArray());
137+
#endif
138+
})
139+
.ConfigureInboundPipeline(pipelineBuilder =>
140+
{
141+
pipelineBuilder.UsePipeReaderAdaptMiddleware()
142+
.UseLengthFieldBasedFrameDecoder(lengthDataSize)
143+
.UseDefaultMessageDeserializer()
144+
.RunEndpoint(endpointBuilder =>
145+
{
146+
endpointBuilder.Handle<EchoData, HoarwellEchoDataServerMessageHandler>();
147+
});
148+
})
149+
.ConfigureOutboundPipeline(pipelineBuilder =>
150+
{
151+
pipelineBuilder.UseLengthFieldBasedFrameEncoder(lengthDataSize)
152+
.RunDefaultMessageSerializer();
153+
});
154+
155+
services.AddLogging();
156+
157+
var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions() { ValidateOnBuild = true, ValidateScopes = true });
158+
var applicationRunner = serviceProvider.GetRequiredKeyedService<IHoarwellApplicationRunner>("Server");
159+
160+
var result = new RunnerInfo(serviceProvider, applicationRunner);
161+
return Task.FromResult(result);
162+
}
163+
164+
#endregion Private 方法
165+
166+
private record struct RunnerInfo(IServiceProvider ServiceProvider, IHoarwellApplicationRunner Runner);
167+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
using System.Net;
2+
using Hoarwell.Client;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.DependencyInjection.Extensions;
5+
6+
namespace Hoarwell;
7+
8+
[TestClass]
9+
public class CommunicationUint32FrameCodecBaseTest
10+
{
11+
#region Public 方法
12+
13+
[TestMethod]
14+
[DataRow(int.MaxValue)]
15+
public async Task ShouldEchoSucceedAsync(int lengthDataSize)
16+
{
17+
var endpoint = IPEndPoint.Parse("127.0.0.1:12342");
18+
var serverRunnerInfo = await InitServer(endpoint, lengthDataSize);
19+
await serverRunnerInfo.Runner.StartAsync();
20+
21+
var clientRunnerInfo = await InitClient(endpoint, lengthDataSize);
22+
using var waiter = clientRunnerInfo.Runner.GetContextWaiter();
23+
await clientRunnerInfo.Runner.StartAsync();
24+
25+
try
26+
{
27+
var context = await waiter.Task;
28+
29+
var handler = context.Services.GetRequiredService<EchoDataClientMessageHandler>();
30+
31+
await context.WriteAndFlushAsync(new EchoData() { Id = 1, Message = "Hello" });
32+
33+
await handler.TaskCompletionSource.Task;
34+
}
35+
finally
36+
{
37+
await DisposeRunnerInfoAsync(clientRunnerInfo);
38+
await DisposeRunnerInfoAsync(serverRunnerInfo);
39+
}
40+
}
41+
42+
#endregion Public 方法
43+
44+
#region Private 方法
45+
46+
private async Task DisposeRunnerInfoAsync(RunnerInfo runnerInfo)
47+
{
48+
await runnerInfo.Runner.DisposeAsync();
49+
if (runnerInfo.ServiceProvider is IAsyncDisposable asyncDisposable)
50+
{
51+
await asyncDisposable.DisposeAsync();
52+
}
53+
}
54+
55+
private Task<RunnerInfo> InitClient(EndPoint endPoint, int lengthDataSize)
56+
{
57+
var services = new ServiceCollection();
58+
59+
var handler = new EchoDataClientMessageHandler(1);
60+
services.TryAddKeyedSingleton("Client", handler);
61+
services.TryAddSingleton(handler);
62+
63+
services.AddHoarwell("Client")
64+
.UseDefaultApplication()
65+
.UseDefaultSocketTransportClient(options => options.EndPoints.Add(endPoint))
66+
.UseDefaultSerializer(serializerBuilder =>
67+
{
68+
#if NET7_0_OR_GREATER
69+
serializerBuilder.AddMessage<EchoData>();
70+
#else
71+
serializerBuilder.AddMessage(typeof(EchoData), ObjectBinaryParseHelper.WrapToParseAsObject<EchoData>(EchoData.TryParse));
72+
#endif
73+
})
74+
.UseDefaultTypeIdentifierAnalyzer(typeIdentifierAnalyzerBuilder =>
75+
{
76+
#if NET7_0_OR_GREATER
77+
typeIdentifierAnalyzerBuilder.AddMessage<EchoData>();
78+
#else
79+
typeIdentifierAnalyzerBuilder.AddMessage(typeof(EchoData), EchoData.TypeIdentifier.ToArray());
80+
#endif
81+
})
82+
.ConfigureInboundPipeline(pipelineBuilder =>
83+
{
84+
pipelineBuilder.UseUInt32LengthFieldBasedFrameDecoder()
85+
.UseDefaultMessageDeserializer()
86+
.RunEndpoint(endpointBuilder =>
87+
{
88+
endpointBuilder.Handle<EchoData, EchoDataClientMessageHandler>(handler);
89+
});
90+
})
91+
.ConfigureOutboundPipeline(pipelineBuilder =>
92+
{
93+
pipelineBuilder.UseUInt32LengthFieldBasedFrameEncoder()
94+
.RunDefaultMessageSerializer();
95+
});
96+
97+
services.AddLogging();
98+
99+
var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions() { ValidateOnBuild = true, ValidateScopes = true });
100+
var applicationRunner = serviceProvider.GetRequiredKeyedService<IHoarwellApplicationRunner>("Client");
101+
102+
var result = new RunnerInfo(serviceProvider, applicationRunner);
103+
return Task.FromResult(result);
104+
}
105+
106+
private Task<RunnerInfo> InitServer(EndPoint endPoint, int lengthDataSize)
107+
{
108+
var services = new ServiceCollection();
109+
110+
services.AddHoarwell("Server")
111+
.UseDefaultApplication()
112+
.UseAspNetCoreSocketTransportServer(options => options.EndPoints.Add(endPoint))
113+
.UseDefaultSerializer(serializerBuilder =>
114+
{
115+
#if NET7_0_OR_GREATER
116+
serializerBuilder.AddMessage<EchoData>();
117+
#else
118+
serializerBuilder.AddMessage(typeof(EchoData), ObjectBinaryParseHelper.WrapToParseAsObject<EchoData>(EchoData.TryParse));
119+
#endif
120+
})
121+
.UseDefaultTypeIdentifierAnalyzer(typeIdentifierAnalyzerBuilder =>
122+
{
123+
#if NET7_0_OR_GREATER
124+
typeIdentifierAnalyzerBuilder.AddMessage<EchoData>();
125+
#else
126+
typeIdentifierAnalyzerBuilder.AddMessage(typeof(EchoData), EchoData.TypeIdentifier.ToArray());
127+
#endif
128+
})
129+
.ConfigureInboundPipeline(pipelineBuilder =>
130+
{
131+
pipelineBuilder.UseUInt32LengthFieldBasedFrameDecoder()
132+
.UseDefaultMessageDeserializer()
133+
.RunEndpoint(endpointBuilder =>
134+
{
135+
endpointBuilder.Handle<EchoData, HoarwellEchoDataServerMessageHandler>();
136+
});
137+
})
138+
.ConfigureOutboundPipeline(pipelineBuilder =>
139+
{
140+
pipelineBuilder.UseUInt32LengthFieldBasedFrameEncoder()
141+
.RunDefaultMessageSerializer();
142+
});
143+
144+
services.AddLogging();
145+
146+
var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions() { ValidateOnBuild = true, ValidateScopes = true });
147+
var applicationRunner = serviceProvider.GetRequiredKeyedService<IHoarwellApplicationRunner>("Server");
148+
149+
var result = new RunnerInfo(serviceProvider, applicationRunner);
150+
return Task.FromResult(result);
151+
}
152+
153+
#endregion Private 方法
154+
155+
private record struct RunnerInfo(IServiceProvider ServiceProvider, IHoarwellApplicationRunner Runner);
156+
}

0 commit comments

Comments
 (0)