Skip to content

Commit a230f01

Browse files
committed
RPC test cleanup
Addresses test flakes due to using not-quite-unique queue names.
1 parent afa3c82 commit a230f01

File tree

1 file changed

+136
-101
lines changed

1 file changed

+136
-101
lines changed

Tests/Rpc/RpcServerTests.cs

Lines changed: 136 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,46 @@ namespace Tests.Rpc
1515
{
1616
public class RpcServerTests(ITestOutputHelper testOutputHelper) : IntegrationTest(testOutputHelper)
1717
{
18+
private string _requestQueueName = string.Empty;
19+
private string _replyToName = $"queueReplyTo-{Now}-{Guid.NewGuid()}";
20+
private string _correlationId = $"my-correlation-id-{Guid.NewGuid()}";
21+
22+
public override async Task InitializeAsync()
23+
{
24+
await base.InitializeAsync();
25+
26+
Assert.NotNull(_management);
27+
28+
IQueueInfo requestQueueInfo = await _management.Queue(_requestQueueName)
29+
.Exclusive(true)
30+
.AutoDelete(true)
31+
.DeclareAsync();
32+
33+
Assert.Equal(_requestQueueName, requestQueueInfo.Name());
34+
_requestQueueName = requestQueueInfo.Name();
35+
}
36+
1837
[Fact]
1938
public async Task MockRpcServerPingPong()
2039
{
2140
Assert.NotNull(_connection);
22-
Assert.NotNull(_management);
23-
await _management.Queue(_queueName).Exclusive(true).AutoDelete(true).DeclareAsync();
2441
TaskCompletionSource<IMessage> tcs = CreateTaskCompletionSource<IMessage>();
25-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
42+
43+
Task<IMessage> RpcHandler(IRpcServer.IContext context, IMessage request)
2644
{
27-
var reply = context.Message("pong");
45+
IMessage reply = context.Message("pong");
2846
tcs.SetResult(reply);
2947
return Task.FromResult(reply);
30-
}).RequestQueue(_queueName).BuildAsync();
31-
Assert.NotNull(rpcServer);
32-
IPublisher p = await _connection.PublisherBuilder().Queue(_queueName).BuildAsync();
48+
}
49+
50+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
51+
.Handler(RpcHandler)
52+
.RequestQueue(_requestQueueName)
53+
.BuildAsync();
54+
55+
IPublisher p = await _connection.PublisherBuilder()
56+
.Queue(_requestQueueName)
57+
.BuildAsync();
3358

3459
await p.PublishAsync(new AmqpMessage("test"));
3560
IMessage m = await WhenTcsCompletes(tcs);
@@ -41,15 +66,21 @@ public async Task MockRpcServerPingPong()
4166
public async Task RpcServerValidateStateChange()
4267
{
4368
Assert.NotNull(_connection);
44-
Assert.NotNull(_management);
69+
4570
List<(State, State)> states = [];
46-
await _management.Queue(_queueName).Exclusive(true).AutoDelete(true).DeclareAsync();
4771
TaskCompletionSource<int> tcs = CreateTaskCompletionSource<int>();
48-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
72+
73+
static Task<IMessage> RpcHandler(IRpcServer.IContext context, IMessage request)
4974
{
50-
var m = context.Message(request.Body());
75+
IMessage m = context.Message(request.Body());
5176
return Task.FromResult(m);
52-
}).RequestQueue(_queueName).BuildAsync();
77+
}
78+
79+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
80+
.Handler(RpcHandler)
81+
.RequestQueue(_requestQueueName)
82+
.BuildAsync();
83+
5384
rpcServer.ChangeState += (sender, fromState, toState, e) =>
5485
{
5586
states.Add((fromState, toState));
@@ -58,8 +89,9 @@ public async Task RpcServerValidateStateChange()
5889
tcs.SetResult(states.Count);
5990
}
6091
};
61-
Assert.NotNull(rpcServer);
92+
6293
await rpcServer.CloseAsync();
94+
6395
int count = await WhenTcsCompletes(tcs);
6496
Assert.Equal(2, count);
6597
Assert.Equal(State.Open, states[0].Item1);
@@ -76,33 +108,38 @@ public async Task SimulateRpcCommunicationWithAPublisherShouldSuccess()
76108
{
77109
Assert.NotNull(_connection);
78110
Assert.NotNull(_management);
79-
string requestQueue = _queueName;
80-
await _management.Queue(requestQueue).Exclusive(true).AutoDelete(true).DeclareAsync();
81-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
82-
{
83-
var reply = context.Message("pong");
84-
return Task.FromResult(reply);
85-
}).RequestQueue(requestQueue).BuildAsync();
86111

87-
Assert.NotNull(rpcServer);
88-
string queueReplyTo = $"queueReplyTo-{Now}";
89-
IQueueSpecification spec = _management.Queue(queueReplyTo).Exclusive(true).AutoDelete(true);
90-
await spec.DeclareAsync();
112+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
113+
.Handler(PongRpcHandler)
114+
.RequestQueue(_requestQueueName)
115+
.BuildAsync();
116+
117+
IQueueSpecification replyQueueSpec = _management.Queue(_replyToName)
118+
.Exclusive(true)
119+
.AutoDelete(true);
120+
await replyQueueSpec.DeclareAsync();
121+
91122
TaskCompletionSource<IMessage> tcs = CreateTaskCompletionSource<IMessage>();
92123

93-
IConsumer consumer = await _connection.ConsumerBuilder().Queue(queueReplyTo).MessageHandler(
94-
(context, message) =>
95-
{
96-
context.Accept();
97-
tcs.SetResult(message);
98-
return Task.CompletedTask;
99-
}).BuildAndStartAsync();
124+
Task MessageHandler(IContext context, IMessage message)
125+
{
126+
context.Accept();
127+
tcs.SetResult(message);
128+
return Task.CompletedTask;
129+
}
100130

101-
IPublisher publisher = await _connection.PublisherBuilder().Queue(requestQueue).BuildAsync();
102-
Assert.NotNull(publisher);
103-
AddressBuilder addressBuilder = new();
131+
IConsumer consumer = await _connection.ConsumerBuilder()
132+
.Queue(replyQueueSpec)
133+
.MessageHandler(MessageHandler)
134+
.BuildAndStartAsync();
135+
136+
IPublisher publisher = await _connection.PublisherBuilder()
137+
.Queue(_requestQueueName)
138+
.BuildAsync();
104139

105-
IMessage message = new AmqpMessage("test").ReplyTo(addressBuilder.Queue(queueReplyTo).Address());
140+
AddressBuilder addressBuilder = new();
141+
string replyToAddress = addressBuilder.Queue(replyQueueSpec).Address();
142+
IMessage message = new AmqpMessage("test").ReplyTo(replyToAddress);
106143
PublishResult pr = await publisher.PublishAsync(message);
107144
Assert.Equal(OutcomeState.Accepted, pr.Outcome.State);
108145

@@ -123,17 +160,15 @@ public async Task RpcServerClientPingPongWithDefault()
123160
{
124161
Assert.NotNull(_connection);
125162
Assert.NotNull(_management);
126-
string requestQueue = _queueName;
127-
await _management.Queue(requestQueue).Exclusive(true).AutoDelete(true).DeclareAsync();
128-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
129-
{
130-
var reply = context.Message("pong");
131-
return Task.FromResult(reply);
132-
}).RequestQueue(_queueName).BuildAsync();
133-
Assert.NotNull(rpcServer);
134163

135-
IRpcClient rpcClient = await _connection.RpcClientBuilder().RequestAddress()
136-
.Queue(requestQueue)
164+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
165+
.Handler(PongRpcHandler)
166+
.RequestQueue(_requestQueueName)
167+
.BuildAsync();
168+
169+
IRpcClient rpcClient = await _connection.RpcClientBuilder()
170+
.RequestAddress()
171+
.Queue(_requestQueueName)
137172
.RpcClient()
138173
.BuildAsync();
139174

@@ -153,27 +188,22 @@ public async Task RpcServerClientPingPongWithCustomReplyToQueueAndCorrelationIdS
153188
{
154189
Assert.NotNull(_connection);
155190
Assert.NotNull(_management);
156-
string requestQueue = _queueName;
157-
await _management.Queue(requestQueue).Exclusive(true).AutoDelete(true).DeclareAsync();
158-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
159-
{
160-
var reply = context.Message("pong");
161-
return Task.FromResult(reply);
162-
}).RequestQueue(_queueName)
163-
.BuildAsync();
164-
Assert.NotNull(rpcServer);
165191

166-
// custom replyTo queue
167-
IQueueInfo replyTo =
168-
await _management.Queue($"replyTo-{Now}").Exclusive(true).AutoDelete(true).DeclareAsync();
192+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
193+
.Handler(PongRpcHandler)
194+
.RequestQueue(_requestQueueName)
195+
.BuildAsync();
169196

170-
// custom correlationId supplier
171-
const string correlationId = "my-correlation-id";
197+
IQueueInfo replyTo = await _management.Queue(_replyToName)
198+
.Exclusive(true)
199+
.AutoDelete(true)
200+
.DeclareAsync();
172201

173-
IRpcClient rpcClient = await _connection.RpcClientBuilder().RequestAddress()
174-
.Queue(requestQueue)
202+
IRpcClient rpcClient = await _connection.RpcClientBuilder()
203+
.RequestAddress()
204+
.Queue(_requestQueueName)
175205
.RpcClient()
176-
.CorrelationIdSupplier(() => correlationId)
206+
.CorrelationIdSupplier(() => _correlationId)
177207
.CorrelationIdExtractor(message => message.CorrelationId())
178208
.ReplyToQueue(replyTo.Name())
179209
.BuildAsync();
@@ -182,7 +212,7 @@ public async Task RpcServerClientPingPongWithCustomReplyToQueueAndCorrelationIdS
182212

183213
IMessage response = await rpcClient.PublishAsync(message);
184214
Assert.Equal("pong", response.Body());
185-
Assert.Equal(correlationId, response.CorrelationId());
215+
Assert.Equal(_correlationId, response.CorrelationId());
186216
await rpcClient.CloseAsync();
187217
await rpcServer.CloseAsync();
188218
}
@@ -199,34 +229,29 @@ public async Task RpcServerClientOverridingTheRequestAndResponsePostProcessor()
199229
{
200230
Assert.NotNull(_connection);
201231
Assert.NotNull(_management);
202-
string requestQueue = _queueName;
203-
await _management.Queue(requestQueue).Exclusive(true).AutoDelete(true).DeclareAsync();
204-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
205-
{
206-
var reply = context.Message("pong");
207-
return Task.FromResult(reply);
208-
}).RequestQueue(_queueName)
209-
//come from the client
232+
233+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
234+
.Handler(PongRpcHandler)
235+
.RequestQueue(_requestQueueName)
210236
.CorrelationIdExtractor(message => message.Property("correlationId"))
211-
// replace the correlation id location with Application properties
212237
.ReplyPostProcessor((reply, replyCorrelationId) => reply.Property("correlationId",
213238
replyCorrelationId.ToString() ?? throw new InvalidOperationException()))
214239
.BuildAsync();
215-
Assert.NotNull(rpcServer);
216240

217-
IQueueInfo replyTo =
218-
await _management.Queue($"replyTo-{Now}").Exclusive(true).AutoDelete(true).DeclareAsync();
241+
IQueueInfo replyTo = await _management.Queue(_replyToName)
242+
.Exclusive(true)
243+
.AutoDelete(true)
244+
.DeclareAsync();
219245

220-
// custom correlationId supplier
221-
const string correlationId = "my-correlation-id";
222246
int correlationIdCounter = 0;
223247

224-
IRpcClient rpcClient = await _connection.RpcClientBuilder().RequestAddress()
225-
.Queue(requestQueue)
248+
IRpcClient rpcClient = await _connection.RpcClientBuilder()
249+
.RequestAddress()
250+
.Queue(_requestQueueName)
226251
.RpcClient()
227252
.ReplyToQueue(replyTo.Name())
228253
// replace the correlation id creation with a custom function
229-
.CorrelationIdSupplier(() => $"{correlationId}_{Interlocked.Increment(ref correlationIdCounter)}")
254+
.CorrelationIdSupplier(() => $"{_correlationId}_{Interlocked.Increment(ref correlationIdCounter)}")
230255
// The server will reply with the correlation id in application properties
231256
.CorrelationIdExtractor(message => message.Property("correlationId"))
232257
// The client will use application properties to set the correlation id
@@ -244,8 +269,8 @@ public async Task RpcServerClientOverridingTheRequestAndResponsePostProcessor()
244269
IMessage response = await rpcClient.PublishAsync(message);
245270
Assert.Equal("pong", response.Body());
246271
// the server replies with the correlation id in the application properties
247-
Assert.Equal($"{correlationId}_{i}", response.Property("correlationId"));
248-
Assert.Equal($"{correlationId}_{i}", response.Properties()["correlationId"]);
272+
Assert.Equal($"{_correlationId}_{i}", response.Property("correlationId"));
273+
Assert.Equal($"{_correlationId}_{i}", response.Properties()["correlationId"]);
249274
Assert.Single(response.Properties());
250275
i++;
251276
}
@@ -259,18 +284,16 @@ public async Task RpcClientMultiThreadShouldBeSafe()
259284
{
260285
Assert.NotNull(_connection);
261286
Assert.NotNull(_management);
262-
263-
string requestQueue = _queueName;
264-
265-
await _management.Queue(requestQueue).Exclusive(true).AutoDelete(true).DeclareAsync();
266287
const int messagesToSend = 99;
288+
267289
TaskCompletionSource<bool> tcs = CreateTaskCompletionSource();
268290
List<IMessage> messagesReceived = [];
269-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler((context, request) =>
291+
292+
Task<IMessage> RpcHandler(IRpcServer.IContext context, IMessage request)
270293
{
271294
try
272295
{
273-
var reply = context.Message("pong");
296+
IMessage reply = context.Message("pong");
274297
messagesReceived.Add(request);
275298
return Task.FromResult(reply);
276299
}
@@ -281,17 +304,19 @@ public async Task RpcClientMultiThreadShouldBeSafe()
281304
tcs.SetResult(true);
282305
}
283306
}
284-
}).RequestQueue(requestQueue).BuildAsync();
307+
}
285308

286-
Assert.NotNull(rpcServer);
309+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
310+
.Handler(RpcHandler)
311+
.RequestQueue(_requestQueueName)
312+
.BuildAsync();
287313

288314
IRpcClient rpcClient = await _connection.RpcClientBuilder().RequestAddress()
289-
.Queue(requestQueue)
315+
.Queue(_requestQueueName)
290316
.RpcClient()
291317
.BuildAsync();
292318

293319
List<Task> tasks = [];
294-
295320
// we simulate a multi-thread environment
296321
// where multiple threads send messages to the server
297322
// and the server replies to each message in a consistent way
@@ -332,25 +357,29 @@ public async Task RpcClientShouldRaiseTimeoutError()
332357
{
333358
Assert.NotNull(_connection);
334359
Assert.NotNull(_management);
335-
string requestQueue = _queueName;
336-
await _management.Queue(requestQueue).Exclusive(true).AutoDelete(true).DeclareAsync();
337-
IRpcServer rpcServer = await _connection.RpcServerBuilder().Handler(async (context, request) =>
360+
361+
static async Task<IMessage> RpcHandler(IRpcServer.IContext context, IMessage request)
338362
{
339363
IMessage reply = context.Message("pong");
340364
object millisecondsToWait = request.Property("wait");
341365
await Task.Delay(TimeSpan.FromMilliseconds((int)millisecondsToWait));
342366
return reply;
343-
}).RequestQueue(_queueName).BuildAsync();
344-
Assert.NotNull(rpcServer);
367+
}
345368

346-
IRpcClient rpcClient = await _connection.RpcClientBuilder().RequestAddress()
347-
.Queue(requestQueue)
369+
IRpcServer rpcServer = await _connection.RpcServerBuilder()
370+
.Handler(RpcHandler)
371+
.RequestQueue(_requestQueueName)
372+
.BuildAsync();
373+
374+
IRpcClient rpcClient = await _connection.RpcClientBuilder()
375+
.RequestAddress()
376+
.Queue(_requestQueueName)
348377
.RpcClient()
349378
.Timeout(TimeSpan.FromMilliseconds(300))
350379
.BuildAsync();
351380

352-
IMessage reply = await rpcClient.PublishAsync(
353-
new AmqpMessage("ping").Property("wait", 1));
381+
IMessage msg = new AmqpMessage("ping").Property("wait", 1);
382+
IMessage reply = await rpcClient.PublishAsync(msg);
354383
Assert.Equal("pong", reply.Body());
355384

356385
await Assert.ThrowsAsync<TimeoutException>(() => rpcClient.PublishAsync(
@@ -359,5 +388,11 @@ await Assert.ThrowsAsync<TimeoutException>(() => rpcClient.PublishAsync(
359388
await rpcClient.CloseAsync();
360389
await rpcServer.CloseAsync();
361390
}
391+
392+
private static Task<IMessage> PongRpcHandler(IRpcServer.IContext context, IMessage request)
393+
{
394+
IMessage reply = context.Message("pong");
395+
return Task.FromResult(reply);
396+
}
362397
}
363398
}

0 commit comments

Comments
 (0)