Skip to content

Commit

Permalink
Merge pull request #301 from ali-ince/1.6-flaky-tests
Browse files Browse the repository at this point in the history
Couple of test improvements
  • Loading branch information
zhenlineo authored May 2, 2018
2 parents 18ce8c5 + a88ff80 commit 0c7c592
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Neo4j.Driver.IntegrationTests.Internals
{
public class ProcessBasedCommandRunner : ShellCommandRunner
{
private const int DefaultTimeOut = 2 * 60 * 1000; // 2 minutes
private const int DefaultTimeOut = 4 * 60 * 1000; // 4 minutes

private List<string> _stdOut;
private StringBuilder _stdErr;
Expand Down
10 changes: 5 additions & 5 deletions Neo4j.Driver/Neo4j.Driver.Metrics/ConnectionPoolMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ internal class ConnectionPoolMetrics : IConnectionPoolMetrics, IConnectionPoolLi
private long _timedOutToAcquire;

public int Creating => _creating;
public long Created => _created;
public long FailedToCreate => _failedToCreate;
public long Created => Interlocked.Read(ref _created);
public long FailedToCreate => Interlocked.Read(ref _failedToCreate);

public int Closing => _closing;
public long Closed => _closed;
public long Closed => Interlocked.Read(ref _closed);

public int Acquiring => _acquiring;
public long Acquired => _acquired;
public long TimedOutToAcquire => _timedOutToAcquire;
public long Acquired => Interlocked.Read(ref _acquired);
public long TimedOutToAcquire => Interlocked.Read(ref _timedOutToAcquire);

public string UniqueName { get; }

Expand Down
6 changes: 2 additions & 4 deletions Neo4j.Driver/Neo4j.Driver.Metrics/DefaultMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ public IConnectionPoolListener CreateConnectionPoolListener(Uri poolUri, IConnec
var poolMetrics = new ConnectionPoolMetrics(poolUri, pool, acquisitionTimeout);
var key = poolMetrics.UniqueName;

_poolMetrics.AddOrUpdate(key, poolMetrics, (oldKey, oldValue) => poolMetrics);
return poolMetrics;
return (IConnectionPoolListener) _poolMetrics.GetOrAdd(key, poolMetrics);
}

public IConnectionListener CreateConnectionListener(Uri poolUri)
Expand All @@ -51,8 +50,7 @@ public IConnectionListener CreateConnectionListener(Uri poolUri)
var connMetrics = new ConnectionMetrics(poolUri, connectionTimeout);
var key = connMetrics.UniqueName;

_connMetrics.AddOrUpdate(key, connMetrics, (oldKey, oldValue) => connMetrics);
return connMetrics;
return (IConnectionListener) _connMetrics.GetOrAdd(key, connMetrics);
}

public IDictionary<string, IConnectionPoolMetrics> ConnectionPoolMetrics => new ReadOnlyDictionary<string, IConnectionPoolMetrics>(_poolMetrics);
Expand Down
53 changes: 26 additions & 27 deletions Neo4j.Driver/Neo4j.Driver.Tests/Connector/TcpSocketClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,18 @@ public class ConnectSocketAsyncMethod
[Fact]
public async Task ShouldThrowExceptionIfConnectionTimedOut()
{
using (var tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
tcpServer.Bind(new IPEndPoint(IPAddress.Loopback, 9999));

var client = new TcpSocketClientWithDisposeDetection(
new SocketSettings {ConnectionTimeout = TimeSpan.FromSeconds(0)});
var client = new TcpSocketClientWithDisposeDetection(
new SocketSettings {ConnectionTimeout = TimeSpan.FromSeconds(1)});

var exception = await Record.ExceptionAsync(
() => client.ConnectSocketAsync(IPAddress.Parse("127.0.0.1"), 9999));
exception.Should().BeOfType<OperationCanceledException>(exception.ToString());
exception.Message.Should().Be("Failed to connect to server 127.0.0.1:9999 within 0ms.");
client.DisposeCalled.Should().BeTrue();
}
// ReSharper disable once PossibleNullReferenceException
// use non-routable IP address to mimic a connect timeout
// https://stackoverflow.com/questions/100841/artificially-create-a-connection-timeout-error
var exception = await Record.ExceptionAsync(
() => client.ConnectSocketAsync(IPAddress.Parse("192.168.0.0"), 9999));
exception.Should().NotBeNull();
exception.Should().BeOfType<OperationCanceledException>(exception.ToString());
exception.Message.Should().Be("Failed to connect to server 192.168.0.0:9999 within 1000ms.");
client.DisposeCalled.Should().BeTrue();
}

[Fact]
Expand All @@ -77,6 +76,7 @@ public async Task ShouldBeAbleToConnectAgainIfFirstFailed()
var client = new TcpSocketClient(socketSettings);

// We fail to connect the first time as there is no server to connect to
// ReSharper disable once PossibleNullReferenceException
var exception = await Record.ExceptionAsync(
async()=> await client.ConnectSocketAsync(IPAddress.Parse("127.0.0.1"), 20003));
// start a server on port 20003
Expand All @@ -101,22 +101,21 @@ public class ConnectAsyncMethod
[Fact]
public async Task ShouldThrowExceptionIfConnectionTimedOut()
{
using (var tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
tcpServer.Bind(new IPEndPoint(IPAddress.Loopback, 9998));
var client = new TcpSocketClient(new SocketSettings {ConnectionTimeout = TimeSpan.FromSeconds(1)});

var client = new TcpSocketClient(new SocketSettings {ConnectionTimeout = TimeSpan.FromSeconds(0)});

var exception = await Record.ExceptionAsync(
() => client.ConnectAsync(new Uri("bolt://127.0.0.1:9998")));
exception.Should().BeOfType<IOException>();
exception.Message.Should().Be(
"Failed to connect to server 'bolt://127.0.0.1:9998/' via IP addresses'[127.0.0.1]' at port '9998'.");

var baseException = exception.GetBaseException();
baseException.Should().BeOfType<OperationCanceledException>(exception.ToString());
baseException.Message.Should().Be("Failed to connect to server 127.0.0.1:9998 within 0ms.");
}
// ReSharper disable once PossibleNullReferenceException
// use non-routable IP address to mimic a connect timeout
// https://stackoverflow.com/questions/100841/artificially-create-a-connection-timeout-error
var exception = await Record.ExceptionAsync(
() => client.ConnectAsync(new Uri("bolt://192.168.0.0:9998")));
exception.Should().NotBeNull();
exception.Should().BeOfType<IOException>();
exception.Message.Should().Be(
"Failed to connect to server 'bolt://192.168.0.0:9998/' via IP addresses'[192.168.0.0]' at port '9998'.");

var baseException = exception.GetBaseException();
baseException.Should().BeOfType<OperationCanceledException>(exception.ToString());
baseException.Message.Should().Be("Failed to connect to server 192.168.0.0:9998 within 1000ms.");
}
}

Expand Down
1 change: 0 additions & 1 deletion Neo4j.Driver/Neo4j.Driver.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{622A94AD-BC4D-4162-AE43-A5CA055F24FC}"
ProjectSection(SolutionItems) = preProject
..\LICENSE = ..\LICENSE
Neo4j.Driver.nuspec = Neo4j.Driver.nuspec
..\NOTICE = ..\NOTICE
..\README.md = ..\README.md
EndProjectSection
Expand Down
49 changes: 21 additions & 28 deletions Neo4j.Driver/Neo4j.Driver/Internal/Connector/TcpSocketClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,38 +212,31 @@ internal async Task ConnectSocketAsync(IPAddress address, int port)
{
InitClient();

var tcs = new TaskCompletionSource<bool>();
using (var cts = new CancellationTokenSource(_connectionTimeout))
{
using (cts.Token.Register(() => tcs.SetResult(true)))
{
#if NET452
var connectTask = Task.Factory.FromAsync(_client.BeginConnect, _client.EndConnect, address, port, null);
var connectTask = Task.Factory.FromAsync(_client.BeginConnect, _client.EndConnect, address, port, null);
#else
var connectTask = _client.ConnectAsync(address, port);
var connectTask = _client.ConnectAsync(address, port);
#endif
var finishedTask = await Task.WhenAny(connectTask, tcs.Task).ConfigureAwait(false);
if (connectTask != finishedTask) // timed out
{
try
{
// close client immediately when failed to connect within timeout
await DisconnectAsync().ConfigureAwait(false);
}
catch (Exception e)
{
_logger?.Error($"Failed to close connect to the server {address}:{port}" +
$" after connection timed out {_connectionTimeout.TotalMilliseconds}ms" +
$" due to error: {e.Message}.", e);
}

throw new OperationCanceledException(
$"Failed to connect to server {address}:{port} within {_connectionTimeout.TotalMilliseconds}ms.", cts.Token);
}

await connectTask.ConfigureAwait(false);
var finishedTask = await Task.WhenAny(connectTask, Task.Delay(_connectionTimeout)).ConfigureAwait(false);
if (connectTask != finishedTask) // timed out
{
try
{
// close client immediately when failed to connect within timeout
await DisconnectAsync().ConfigureAwait(false);
}
catch (Exception e)
{
_logger?.Error($"Failed to close connect to the server {address}:{port}" +
$" after connection timed out {_connectionTimeout.TotalMilliseconds}ms" +
$" due to error: {e.Message}.", e);
}

throw new OperationCanceledException(
$"Failed to connect to server {address}:{port} within {_connectionTimeout.TotalMilliseconds}ms.");
}

await connectTask.ConfigureAwait(false);
}

public virtual void Disconnect()
Expand Down Expand Up @@ -274,7 +267,7 @@ public virtual Task DisconnectAsync()
t =>
{
_client.Dispose();
_stream.Dispose();
_stream?.Dispose();

_client = null;
_stream = null;
Expand Down

0 comments on commit 0c7c592

Please sign in to comment.