Skip to content

Commit cf830aa

Browse files
committed
Minor change in integration tests
This uses the current time and a short uuid when creating test queues and exchanges. Copied from rabbitmq/rabbitmq-amqp-dotnet-client * Ensure unique toxic name because integration tests run in parallel per-TFM now. * Use unique queue names. * Update toxiproxy executables. * Collect toxiproxy server output on failure. * Add retries to starting a Toxiproxy instance.
1 parent a8dc8ce commit cf830aa

14 files changed

+104
-41
lines changed
401 KB
Binary file not shown.
-838 KB
Binary file not shown.

.github/workflows/build-test.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,7 @@ jobs:
6969
- name: Integration Tests
7070
timeout-minutes: 25
7171
run: |
72-
$tx = Start-Job -Verbose -ScriptBlock { & "${{ github.workspace }}\.ci\windows\toxiproxy\toxiproxy-server.exe" }; `
73-
Start-Sleep -Seconds 1; `
74-
Receive-Job -Job $tx; `
75-
& "${{ github.workspace }}\.ci\windows\toxiproxy\toxiproxy-cli.exe" list; `
72+
Start-Job -Verbose -ScriptBlock { & "${{ github.workspace }}\.ci\windows\toxiproxy\toxiproxy-server.exe" }; `
7673
dotnet test `
7774
--environment 'RABBITMQ_LONG_RUNNING_TESTS=true' `
7875
--environment "RABBITMQ_RABBITMQCTL_PATH=${{ steps.install-start-rabbitmq.outputs.path }}" `
@@ -82,7 +79,10 @@ jobs:
8279
"${{ github.workspace }}\projects\Test\Integration\Integration.csproj" --no-restore --no-build --logger 'console;verbosity=detailed'
8380
- name: Check for errors in RabbitMQ logs
8481
run: ${{ github.workspace }}\.ci\windows\gha-log-check.ps1
85-
- name: Maybe upload RabbitMQ logs
82+
- name: Maybe collect Toxiproxy logs
83+
if: failure()
84+
run: Get-Job | Where-Object { $_.HasMoreData } | Receive-Job | Out-File -Append -LiteralPath $env:APPDATA\RabbitMQ\log\toxiproxy-log.txt
85+
- name: Maybe upload RabbitMQ and Toxiproxy logs
8686
if: failure()
8787
uses: actions/upload-artifact@v4
8888
with:

projects/Test/Common/IntegrationFixture.cs

+18-12
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,9 @@ public abstract class IntegrationFixture : IAsyncLifetime
8484
public static readonly TimeSpan RecoveryInterval = TimeSpan.FromSeconds(2);
8585
public static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
8686
public static readonly TimeSpan RequestedConnectionTimeout = TimeSpan.FromSeconds(1);
87-
public static readonly Random S_Random;
8887

8988
static IntegrationFixture()
9089
{
91-
92-
#if NET
93-
S_Random = Random.Shared;
94-
#else
95-
S_Random = new Random();
96-
#endif
9790
s_isRunningInCI = InitIsRunningInCI();
9891
s_isVerbose = InitIsVerbose();
9992

@@ -450,12 +443,19 @@ protected async Task WithTemporaryChannelAsync(Func<IChannel, Task> action)
450443

451444
protected string GenerateExchangeName()
452445
{
453-
return $"{_testDisplayName}-exchange-{Guid.NewGuid()}";
446+
return $"{_testDisplayName}-exchange-{Now}-{GenerateShortUuid()}";
454447
}
455448

456-
protected string GenerateQueueName()
449+
protected string GenerateQueueName(bool useGuid = false)
457450
{
458-
return $"{_testDisplayName}-queue-{Guid.NewGuid()}";
451+
if (useGuid)
452+
{
453+
return $"{_testDisplayName}-queue-{Now}-{Guid.NewGuid()}";
454+
}
455+
else
456+
{
457+
return $"{_testDisplayName}-queue-{Now}-{GenerateShortUuid()}";
458+
}
459459
}
460460

461461
protected Task WithTemporaryNonExclusiveQueueAsync(Func<IChannel, string, Task> action)
@@ -540,7 +540,7 @@ protected ConnectionFactory CreateConnectionFactory(
540540
{
541541
return new ConnectionFactory
542542
{
543-
ClientProvidedName = $"{_testDisplayName}:{Util.Now}:{GetConnectionIdx()}",
543+
ClientProvidedName = $"{_testDisplayName}:{Now}:{GetConnectionIdx()}",
544544
ContinuationTimeout = WaitSpan,
545545
HandshakeContinuationTimeout = WaitSpan,
546546
ConsumerDispatchConcurrency = consumerDispatchConcurrency
@@ -631,10 +631,16 @@ protected static string GetUniqueString(ushort length)
631631
protected static byte[] GetRandomBody(ushort size = 1024)
632632
{
633633
byte[] body = new byte[size];
634-
S_Random.NextBytes(body);
634+
Util.S_Random.NextBytes(body);
635635
return body;
636636
}
637637

638+
protected static string Now => Util.Now;
639+
640+
protected static string GenerateShortUuid() => Util.GenerateShortUuid();
641+
642+
protected static int RandomNext(int min, int max) => Util.S_Random.Next(min, max);
643+
638644
protected static Task WaitForRecoveryAsync(IConnection conn)
639645
{
640646
TaskCompletionSource<bool> tcs = PrepareForRecovery((AutorecoveringConnection)conn);

projects/Test/Common/Util.cs

+22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ namespace Test
1010
{
1111
public class Util : IDisposable
1212
{
13+
#if NET
14+
private static readonly Random s_random = Random.Shared;
15+
#else
16+
[ThreadStatic]
17+
private static Random s_random;
18+
#endif
19+
1320
private readonly ITestOutputHelper _output;
1421
private readonly ManagementClient _managementClient;
1522
private static readonly bool s_isWindows = false;
@@ -41,6 +48,21 @@ public Util(ITestOutputHelper output, string managementUsername, string manageme
4148
_managementClient = new ManagementClient(managementUri, managementUsername, managementPassword);
4249
}
4350

51+
public static Random S_Random
52+
{
53+
get
54+
{
55+
#if NET
56+
return s_random;
57+
#else
58+
s_random ??= new Random();
59+
return s_random;
60+
#endif
61+
}
62+
}
63+
64+
public static string GenerateShortUuid() => S_Random.Next().ToString("x");
65+
4466
public static string Now => DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
4567

4668
public static bool IsWindows => s_isWindows;

projects/Test/Integration/ConnectionRecovery/TestQueueRecovery.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task TestQueueRecoveryWithManyQueues()
5252
int n = 1024;
5353
for (int i = 0; i < n; i++)
5454
{
55-
QueueDeclareOk q = await _channel.QueueDeclareAsync(GenerateQueueName(), false, false, false);
55+
QueueDeclareOk q = await _channel.QueueDeclareAsync(GenerateQueueName(useGuid: true), false, false, false);
5656
qs.Add(q.QueueName);
5757
}
5858
await CloseAndWaitForRecoveryAsync();

projects/Test/Integration/TestAsyncConsumer.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ await _channel.BasicPublishAsync(exchange: string.Empty, routingKey: queueName,
703703

704704
private async Task ValidateConsumerDispatchConcurrency()
705705
{
706-
ushort expectedConsumerDispatchConcurrency = (ushort)S_Random.Next(3, 10);
706+
ushort expectedConsumerDispatchConcurrency = (ushort)RandomNext(3, 10);
707707
AutorecoveringChannel autorecoveringChannel = (AutorecoveringChannel)_channel;
708708
Assert.Equal(ConsumerDispatchConcurrency, autorecoveringChannel.ConsumerDispatcher.Concurrency);
709709
Assert.Equal(_consumerDispatchConcurrency, autorecoveringChannel.ConsumerDispatcher.Concurrency);

projects/Test/Integration/TestConcurrentAccessBase.cs.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected async Task TestConcurrentOperationsAsync(Func<Task> action, int iterat
5454
{
5555
for (int j = 0; j < iterations; j++)
5656
{
57-
await Task.Delay(S_Random.Next(1, 10));
57+
await Task.Delay(RandomNext(1, 10));
5858
tasks.Add(action());
5959
}
6060
}

projects/Test/Integration/TestConnectionRecoveryWithoutSetup.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public async Task TestConsumerWorkServiceRecovery()
114114
await using AutorecoveringConnection c = await CreateAutorecoveringConnectionAsync();
115115
await using (IChannel ch = await c.CreateChannelAsync())
116116
{
117-
string q = (await ch.QueueDeclareAsync("dotnet-client.recovery.consumer_work_pool1",
117+
string q = (await ch.QueueDeclareAsync(GenerateQueueName(),
118118
false, false, false)).QueueName;
119119
var cons = new AsyncEventingBasicConsumer(ch);
120120
await ch.BasicConsumeAsync(q, true, cons);
@@ -143,7 +143,7 @@ public async Task TestConsumerWorkServiceRecovery()
143143
[Fact]
144144
public async Task TestConsumerRecoveryOnClientNamedQueueWithOneRecovery()
145145
{
146-
const string q0 = "dotnet-client.recovery.queue1";
146+
string q0 = GenerateQueueName();
147147
// connection #1
148148
await using AutorecoveringConnection c = await CreateAutorecoveringConnectionAsync();
149149
await using (IChannel ch = await c.CreateChannelAsync())
@@ -364,8 +364,7 @@ public async Task TestTopologyRecoveryConsumerFilter()
364364
[Fact]
365365
public async Task TestRecoveryWithTopologyDisabled()
366366
{
367-
string queueName = GenerateQueueName() + "-dotnet-client.test.recovery.q2";
368-
367+
string queueName = GenerateQueueName();
369368
await using AutorecoveringConnection conn = await CreateAutorecoveringConnectionWithTopologyRecoveryDisabledAsync();
370369
await using (IChannel ch = await conn.CreateChannelAsync())
371370
{

projects/Test/Integration/TestExchangeDeclare.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ async Task f()
6262
{
6363
try
6464
{
65-
await Task.Delay(S_Random.Next(5, 50));
65+
await Task.Delay(RandomNext(5, 50));
6666
string exchangeName = GenerateExchangeName();
6767
await _channel.ExchangeDeclareAsync(exchange: exchangeName, type: "fanout", false, false);
6868
await _channel.ExchangeBindAsync(destination: ex_destination, source: exchangeName, routingKey: "unused");
@@ -87,7 +87,7 @@ async Task f()
8787
{
8888
try
8989
{
90-
await Task.Delay(S_Random.Next(5, 50));
90+
await Task.Delay(RandomNext(5, 50));
9191
await _channel.ExchangeUnbindAsync(destination: ex_destination, source: exchangeName, routingKey: "unused",
9292
noWait: false, arguments: null);
9393
await _channel.ExchangeDeleteAsync(exchange: exchangeName, ifUnused: false);

projects/Test/Integration/TestFloodPublishing.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ public async Task TestUnthrottledFloodPublishing()
125125

126126
Assert.True(_conn.IsOpen);
127127
Assert.False(sawUnexpectedShutdown);
128-
_output.WriteLine("[INFO] published {0} messages in {1}", publishCount, stopwatch.Elapsed);
128+
if (IsVerbose)
129+
{
130+
_output.WriteLine("[INFO] published {0} messages in {1}", publishCount, stopwatch.Elapsed);
131+
}
129132
}
130133

131134
[Fact]

projects/Test/Integration/TestQueueDeclare.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ async Task f()
103103
{
104104
// sleep for a random amount of time to increase the chances
105105
// of thread interleaving. MK.
106-
await Task.Delay(S_Random.Next(5, 50));
106+
await Task.Delay(RandomNext(5, 50));
107107
string queueName = GenerateQueueName();
108108
QueueDeclareOk r = await _channel.QueueDeclareAsync(queue: queueName,
109109
durable: false, exclusive: true, autoDelete: false);
@@ -136,7 +136,7 @@ async Task f()
136136
string qname = q;
137137
try
138138
{
139-
await Task.Delay(S_Random.Next(5, 50));
139+
await Task.Delay(RandomNext(5, 50));
140140

141141
QueueDeclareOk r = await _channel.QueueDeclarePassiveAsync(qname);
142142
Assert.Equal(qname, r.QueueName);
@@ -176,7 +176,7 @@ public async Task TestConcurrentQueueDeclare()
176176
{
177177
// sleep for a random amount of time to increase the chances
178178
// of thread interleaving. MK.
179-
await Task.Delay(S_Random.Next(5, 50));
179+
await Task.Delay(RandomNext(5, 50));
180180
string q = GenerateQueueName();
181181
await _channel.QueueDeclareAsync(q, false, false, false);
182182
queueNames.Add(q);
@@ -201,7 +201,7 @@ public async Task TestConcurrentQueueDeclare()
201201
{
202202
try
203203
{
204-
await Task.Delay(S_Random.Next(5, 50));
204+
await Task.Delay(RandomNext(5, 50));
205205
await _channel.QueueDeleteAsync(queueName);
206206
}
207207
catch (NotSupportedException e)

projects/Test/Integration/TestToxiproxy.cs

+15-7
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,11 @@ public async Task TestThatStoppedSocketResultsInHeartbeatTimeout()
221221

222222
Assert.True(await tcs.Task);
223223

224-
var timeoutToxic = new TimeoutToxic();
224+
string toxicName = $"rmq-localhost-timeout-{Now}-{GenerateShortUuid()}";
225+
var timeoutToxic = new TimeoutToxic
226+
{
227+
Name = toxicName
228+
};
225229
timeoutToxic.Attributes.Timeout = 0;
226230
timeoutToxic.Toxicity = 1.0;
227231

@@ -271,9 +275,11 @@ public async Task TestTcpReset_GH1464()
271275

272276
Assert.True(await channelCreatedTcs.Task);
273277

274-
const string toxicName = "rmq-localhost-reset_peer";
275-
var resetPeerToxic = new ResetPeerToxic();
276-
resetPeerToxic.Name = toxicName;
278+
string toxicName = $"rmq-localhost-reset_peer-{Now}-{GenerateShortUuid()}";
279+
var resetPeerToxic = new ResetPeerToxic
280+
{
281+
Name = toxicName
282+
};
277283
resetPeerToxic.Attributes.Timeout = 500;
278284
resetPeerToxic.Toxicity = 1.0;
279285

@@ -354,9 +360,11 @@ public async Task TestPublisherConfirmationThrottling()
354360

355361
await channelCreatedTcs.Task;
356362

357-
const string toxicName = "rmq-localhost-bandwidth";
358-
var bandwidthToxic = new BandwidthToxic();
359-
bandwidthToxic.Name = toxicName;
363+
string toxicName = $"rmq-localhost-bandwidth-{Now}-{GenerateShortUuid()}";
364+
var bandwidthToxic = new BandwidthToxic
365+
{
366+
Name = toxicName
367+
};
360368
bandwidthToxic.Attributes.Rate = 0;
361369
bandwidthToxic.Toxicity = 1.0;
362370
bandwidthToxic.Stream = ToxicDirection.DownStream;

projects/Test/Integration/ToxiproxyManager.cs

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
using System;
2+
using System.Globalization;
23
using System.Net;
34
using System.Threading;
45
using System.Threading.Tasks;
6+
using Test;
57
using Toxiproxy.Net;
68
using Toxiproxy.Net.Toxics;
79

810
namespace Integration
911
{
1012
public class ToxiproxyManager : IDisposable
1113
{
12-
private const string ProxyNamePrefix = "rmq-";
14+
private const string ProxyNamePrefix = "rmq";
1315
private const ushort ProxyPortStart = 55669;
1416
private static int s_proxyPort = ProxyPortStart;
1517

@@ -68,7 +70,8 @@ public ToxiproxyManager(string testDisplayName, bool isRunningInCI, bool isWindo
6870

6971
public async Task InitializeAsync()
7072
{
71-
_proxy.Name = $"{ProxyNamePrefix}{_testDisplayName}";
73+
string proxyName = $"{ProxyNamePrefix}-{_testDisplayName}-{Util.Now}-{Util.GenerateShortUuid()}";
74+
_proxy.Name = proxyName;
7275

7376
try
7477
{
@@ -78,7 +81,29 @@ public async Task InitializeAsync()
7881
{
7982
}
8083

81-
await _proxyClient.AddAsync(_proxy);
84+
ushort retryCount = 5;
85+
do
86+
{
87+
try
88+
{
89+
await _proxyClient.AddAsync(_proxy);
90+
return;
91+
}
92+
catch (Exception ex)
93+
{
94+
if (retryCount == 0)
95+
{
96+
throw;
97+
}
98+
else
99+
{
100+
string now = DateTime.Now.ToString("o", CultureInfo.InvariantCulture);
101+
Console.Error.WriteLine("{0} [ERROR] error initializing proxy '{1}': {2}", now, proxyName, ex);
102+
}
103+
}
104+
--retryCount;
105+
await Task.Delay(TimeSpan.FromSeconds(1));
106+
} while (retryCount >= 0);
82107
}
83108

84109
public Task<T> AddToxicAsync<T>(T toxic) where T : ToxicBase

0 commit comments

Comments
 (0)