Skip to content

Commit 4042bc1

Browse files
ceeskaasnicelukebakken
authored andcommitted
Added UnitTest that exposes hanging dispose on a blocked connection
Added TimeOut to Abort call to prevent waiting forever in Dispose Upped timeout to 15 seconds to prevent false positives Use constants Add test name to connection name Clean up resources correctly in connection recovery tests
1 parent 39a9f2b commit 4042bc1

38 files changed

+284
-83
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ TestResult.xml
1919
/NuGet
2020
.vscode/
2121
*.lock.json
22-
api/
2322

2423
test.sh
2524
*.VisualState.xml

projects/RabbitMQ.Client/client/api/IConnectionExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public static class IConnectionExtensions
1919
/// </remarks>
2020
public static void Close(this IConnection connection)
2121
{
22-
connection.Close(Constants.ReplySuccess, "Goodbye", TimeSpan.FromSeconds(30), false);
22+
connection.Close(Constants.ReplySuccess, "Goodbye", InternalConstants.DefaultConnectionCloseTimeout, false);
2323
}
2424

2525
/// <summary>
@@ -37,7 +37,7 @@ public static void Close(this IConnection connection)
3737
/// </remarks>
3838
public static void Close(this IConnection connection, ushort reasonCode, string reasonText)
3939
{
40-
connection.Close(reasonCode, reasonText, TimeSpan.FromSeconds(30), false);
40+
connection.Close(reasonCode, reasonText, InternalConstants.DefaultConnectionCloseTimeout, false);
4141
}
4242

4343
/// <summary>
@@ -93,7 +93,7 @@ public static void Close(this IConnection connection, ushort reasonCode, string
9393
/// </remarks>
9494
public static void Abort(this IConnection connection)
9595
{
96-
connection.Close(Constants.ReplySuccess, "Connection close forced", TimeSpan.FromSeconds(5), true);
96+
connection.Close(Constants.ReplySuccess, "Connection close forced", InternalConstants.DefaultConnectionAbortTimeout, true);
9797
}
9898

9999
/// <summary>
@@ -111,7 +111,7 @@ public static void Abort(this IConnection connection)
111111
/// </remarks>
112112
public static void Abort(this IConnection connection, ushort reasonCode, string reasonText)
113113
{
114-
connection.Close(reasonCode, reasonText, TimeSpan.FromSeconds(5), true);
114+
connection.Close(reasonCode, reasonText, InternalConstants.DefaultConnectionAbortTimeout, true);
115115
}
116116

117117
/// <summary>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// This source code is dual-licensed under the Apache License, version
2+
// 2.0, and the Mozilla Public License, version 2.0.
3+
//
4+
// The APL v2.0:
5+
//
6+
//---------------------------------------------------------------------------
7+
// Copyright (c) 2007-2020 VMware, Inc.
8+
//
9+
// Licensed under the Apache License, Version 2.0 (the "License");
10+
// you may not use this file except in compliance with the License.
11+
// You may obtain a copy of the License at
12+
//
13+
// https://www.apache.org/licenses/LICENSE-2.0
14+
//
15+
// Unless required by applicable law or agreed to in writing, software
16+
// distributed under the License is distributed on an "AS IS" BASIS,
17+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
// See the License for the specific language governing permissions and
19+
// limitations under the License.
20+
//---------------------------------------------------------------------------
21+
//
22+
// The MPL v2.0:
23+
//
24+
//---------------------------------------------------------------------------
25+
// This Source Code Form is subject to the terms of the Mozilla Public
26+
// License, v. 2.0. If a copy of the MPL was not distributed with this
27+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
28+
//
29+
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
30+
//---------------------------------------------------------------------------
31+
32+
using System;
33+
34+
namespace RabbitMQ.Client
35+
{
36+
internal static class InternalConstants
37+
{
38+
internal static readonly TimeSpan DefaultConnectionAbortTimeout = TimeSpan.FromSeconds(5);
39+
internal static readonly TimeSpan DefaultConnectionCloseTimeout = TimeSpan.FromSeconds(30);
40+
}
41+
}

projects/RabbitMQ.Client/client/impl/AutorecoveringConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public void Dispose()
216216

217217
try
218218
{
219-
this.Abort();
219+
this.Abort(InternalConstants.DefaultConnectionAbortTimeout);
220220
}
221221
catch (Exception)
222222
{

projects/RabbitMQ.Client/client/impl/Connection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
namespace RabbitMQ.Client.Framing.Impl
4444
{
45-
#nullable enable
45+
#nullable enable
4646
internal sealed partial class Connection : IConnection
4747
{
4848
private bool _disposed;
@@ -410,7 +410,7 @@ public void Dispose()
410410

411411
try
412412
{
413-
this.Abort();
413+
this.Abort(InternalConstants.DefaultConnectionAbortTimeout);
414414
_mainLoopTask.Wait();
415415
}
416416
catch (OperationInterruptedException)

projects/RabbitMQ.Client/client/impl/ModelBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ protected void HandleConnectionStart(in IncomingCommand cmd)
742742
if (m_connectionStartCell is null)
743743
{
744744
var reason = new ShutdownEventArgs(ShutdownInitiator.Library, Constants.CommandInvalid, "Unexpected Connection.Start");
745-
Session.Connection.Close(reason, false, TimeSpan.FromSeconds(30));
745+
Session.Connection.Close(reason, false, InternalConstants.DefaultConnectionCloseTimeout);
746746
}
747747

748748
var method = new ConnectionStart(cmd.MethodBytes.Span);

projects/Unit/APIApproval.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
3030
//---------------------------------------------------------------------------
3131

32+
using System.Reflection;
3233
using System.Threading.Tasks;
3334

3435
using PublicApiGenerator;

projects/Unit/Fixtures.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,37 @@
3333

3434
using System;
3535
using System.Collections.Generic;
36-
using System.Text;
36+
using System.Reflection;
3737
using System.Threading;
38-
using RabbitMQ.Client.Framing;
38+
using System.Text;
3939
using RabbitMQ.Client.Framing.Impl;
4040

4141
using Xunit;
42-
43-
using static RabbitMQ.Client.Unit.RabbitMQCtl;
42+
using Xunit.Abstractions;
4443

4544
namespace RabbitMQ.Client.Unit
4645
{
47-
46+
[Collection("IntegrationFixture")]
4847
public class IntegrationFixture : IDisposable
4948
{
5049
internal IConnectionFactory _connFactory;
5150
internal IConnection _conn;
5251
internal IModel _model;
5352
internal Encoding _encoding = new UTF8Encoding();
53+
5454
public static TimeSpan RECOVERY_INTERVAL = TimeSpan.FromSeconds(2);
5555

56-
protected IntegrationFixture()
56+
protected readonly ITestOutputHelper _output;
57+
protected readonly string _testDisplayName;
58+
59+
public IntegrationFixture(ITestOutputHelper output)
5760
{
61+
_output = output;
62+
var type = _output.GetType();
63+
var testMember = type.GetField("test", BindingFlags.Instance | BindingFlags.NonPublic);
64+
var test = (ITest)testMember.GetValue(output);
65+
_testDisplayName = test.DisplayName;
66+
5867
SetUp();
5968
}
6069

@@ -71,6 +80,7 @@ public virtual void Dispose()
7180
{
7281
_model.Close();
7382
}
83+
7484
if (_conn.IsOpen)
7585
{
7686
_conn.Close();
@@ -105,7 +115,7 @@ internal AutorecoveringConnection CreateAutorecoveringConnection(TimeSpan interv
105115
AutomaticRecoveryEnabled = true,
106116
NetworkRecoveryInterval = interval
107117
};
108-
return (AutorecoveringConnection)cf.CreateConnection($"UNIT_CONN:{Guid.NewGuid()}");
118+
return (AutorecoveringConnection)cf.CreateConnection($"{_testDisplayName}:{Guid.NewGuid()}");
109119
}
110120

111121
internal AutorecoveringConnection CreateAutorecoveringConnection(TimeSpan interval, IList<string> hostnames)
@@ -118,7 +128,7 @@ internal AutorecoveringConnection CreateAutorecoveringConnection(TimeSpan interv
118128
RequestedConnectionTimeout = TimeSpan.FromSeconds(1),
119129
NetworkRecoveryInterval = interval
120130
};
121-
return (AutorecoveringConnection)cf.CreateConnection(hostnames, $"UNIT_CONN:{Guid.NewGuid()}");
131+
return (AutorecoveringConnection)cf.CreateConnection(hostnames, $"{_testDisplayName}:{Guid.NewGuid()}");
122132
}
123133

124134
internal AutorecoveringConnection CreateAutorecoveringConnection(IList<AmqpTcpEndpoint> endpoints)
@@ -131,7 +141,7 @@ internal AutorecoveringConnection CreateAutorecoveringConnection(IList<AmqpTcpEn
131141
RequestedConnectionTimeout = TimeSpan.FromSeconds(1),
132142
NetworkRecoveryInterval = RECOVERY_INTERVAL
133143
};
134-
return (AutorecoveringConnection)cf.CreateConnection(endpoints, $"UNIT_CONN:{Guid.NewGuid()}");
144+
return (AutorecoveringConnection)cf.CreateConnection(endpoints, $"{_testDisplayName}:{Guid.NewGuid()}");
135145
}
136146

137147
internal AutorecoveringConnection CreateAutorecoveringConnectionWithTopologyRecoveryDisabled()
@@ -142,7 +152,7 @@ internal AutorecoveringConnection CreateAutorecoveringConnectionWithTopologyReco
142152
TopologyRecoveryEnabled = false,
143153
NetworkRecoveryInterval = RECOVERY_INTERVAL
144154
};
145-
return (AutorecoveringConnection)cf.CreateConnection($"UNIT_CONN:{Guid.NewGuid()}");
155+
return (AutorecoveringConnection)cf.CreateConnection($"{_testDisplayName}:{Guid.NewGuid()}");
146156
}
147157

148158
internal IConnection CreateConnectionWithContinuationTimeout(bool automaticRecoveryEnabled, TimeSpan continuationTimeout)
@@ -152,7 +162,7 @@ internal IConnection CreateConnectionWithContinuationTimeout(bool automaticRecov
152162
AutomaticRecoveryEnabled = automaticRecoveryEnabled,
153163
ContinuationTimeout = continuationTimeout
154164
};
155-
return cf.CreateConnection($"UNIT_CONN:{Guid.NewGuid()}");
165+
return cf.CreateConnection($"{_testDisplayName}:{Guid.NewGuid()}");
156166
}
157167

158168
//

projects/Unit/RabbitMQCtl.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ public static void RestartRabbitMQ()
217217
StopRabbitMQ();
218218
Thread.Sleep(500);
219219
StartRabbitMQ();
220+
AwaitRabbitMQ();
220221
}
221222

222223
public static void StopRabbitMQ()

projects/Unit/TestAsyncConsumerExceptions.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,18 @@
3636
using RabbitMQ.Client.Events;
3737

3838
using Xunit;
39+
using Xunit.Abstractions;
3940

4041
namespace RabbitMQ.Client.Unit
4142
{
42-
4343
public class TestAsyncConsumerExceptions : IntegrationFixture
4444
{
4545
private static readonly Exception TestException = new Exception("oops");
4646

47+
public TestAsyncConsumerExceptions(ITestOutputHelper output) : base(output)
48+
{
49+
}
50+
4751
protected void TestExceptionHandlingWith(IBasicConsumer consumer,
4852
Action<IModel, string, IBasicConsumer, string> action)
4953
{

projects/Unit/TestBasicGet.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,16 @@
3232
using RabbitMQ.Client.Exceptions;
3333

3434
using Xunit;
35+
using Xunit.Abstractions;
3536

3637
namespace RabbitMQ.Client.Unit
3738
{
38-
3939
public class TestBasicGet : IntegrationFixture
4040
{
41+
public TestBasicGet(ITestOutputHelper output) : base(output)
42+
{
43+
}
44+
4145
[Fact]
4246
public void TestBasicGetWithClosedChannel()
4347
{

projects/Unit/TestBlockingCell.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838

3939
namespace RabbitMQ.Client.Unit
4040
{
41-
4241
public class TestBlockingCell : TimingFixture
4342
{
4443
internal class DelayedSetter<T>

projects/Unit/TestChannelSoftErrors.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@
3333
using RabbitMQ.Client.Exceptions;
3434

3535
using Xunit;
36+
using Xunit.Abstractions;
3637

3738
namespace RabbitMQ.Client.Unit
3839
{
39-
4040
public class TestChannelSoftErrors : IntegrationFixture
4141
{
42+
public TestChannelSoftErrors(ITestOutputHelper output) : base(output)
43+
{
44+
}
45+
4246
[Fact]
4347
public void TestBindOnNonExistingQueue()
4448
{

projects/Unit/TestConcurrentAccessWithSharedConnection.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
using System.Threading.Tasks;
3636

3737
using Xunit;
38+
using Xunit.Abstractions;
3839

3940
namespace RabbitMQ.Client.Unit
4041
{
@@ -45,6 +46,10 @@ public class TestConcurrentAccessWithSharedConnection : IntegrationFixture
4546
internal CountdownEvent _latch;
4647
internal TimeSpan _completionTimeout = TimeSpan.FromSeconds(90);
4748

49+
public TestConcurrentAccessWithSharedConnection(ITestOutputHelper output) : base(output)
50+
{
51+
}
52+
4853
protected override void SetUp()
4954
{
5055
base.SetUp();

projects/Unit/TestConfirmSelect.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@
3030
//---------------------------------------------------------------------------
3131

3232
using Xunit;
33+
using Xunit.Abstractions;
3334

3435
namespace RabbitMQ.Client.Unit
3536
{
36-
3737
public class TestConfirmSelect : IntegrationFixture
3838
{
39+
public TestConfirmSelect(ITestOutputHelper output) : base(output)
40+
{
41+
}
3942

4043
[Fact]
4144
public void TestConfirmSelectIdempotency()

0 commit comments

Comments
 (0)