From a63cdc6fa5e584016bfafeff202bf3b40c497eac Mon Sep 17 00:00:00 2001 From: grant lodge <6323995+thelonelyvulpes@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:38:49 +0000 Subject: [PATCH] Update code base remove warnings. (#685) * remove warnings. * few more tidyings --- .../Direct/AuthenticationIT.cs | 47 +- .../Direct/BoltV4IT.cs | 95 +--- .../Direct/BookmarkIT.cs | 113 ++-- .../Direct/CertificateTrustIT.cs | 55 +- .../Direct/CypherParametersIT.cs | 325 +++++------ .../Direct/DirectDriverTestBase.cs | 25 +- .../Direct/DriverIT.cs | 177 +++--- .../Direct/EncryptionIT.cs | 39 +- .../Direct/ErrorIT.cs | 86 +-- .../Direct/NestedQueriesIT.cs | 408 ++++++-------- .../Direct/ResultIT.cs | 24 +- .../Direct/SessionIT.cs | 338 +++++------- .../Direct/TransactionIT.cs | 516 +++++++----------- .../Examples.cs | 164 ++---- .../ExamplesAsync.cs | 14 +- .../ExamplesRx.cs | 11 +- .../Extensions/CollectionExtensions.cs | 7 +- .../Extensions/DatabaseExtensions.cs | 34 +- .../Extensions/SessionExtensions.cs | 2 +- .../Internals/BoltStubServer.cs | 2 +- .../Internals/BoltkitHelper.cs | 17 +- .../CausalClusterIntegrationTestFixture.cs | 66 +++ .../CcIntegrationCollection.cs} | 25 +- .../Internals/CertificateUtils.cs | 17 +- .../Internals/Cluster/CausalCluster.cs | 55 +- .../Internals/Cluster/ExistingCluster.cs | 2 +- .../ExternalBoltkitClusterInstaller.cs | 8 +- .../Internals/Cluster/SingleInstance.cs | 13 +- .../Internals/IInstaller.cs | 6 - .../Internals/IShellCommandRunner.cs | 11 +- .../Internals/IntegrationTestAttribute.cs | 48 +- .../Internals/IntegrationTestFixture.cs | 109 +--- .../Internals/ProcessBasedCommandRunner.cs | 36 +- .../SaIntegrationCollection.cs} | 27 +- .../Internals/ShellCommandRunnerTests.cs | 2 +- ...Installation.cs => DefaultInstallation.cs} | 28 +- .../StandAlone/ExternalBoltkitInstaller.cs | 8 +- .../StandAlone/LocalStandAloneInstance.cs | 34 +- ...o4jSettingsHelper.cs => SettingsHelper.cs} | 52 +- .../Internals/StandAlone/StandAlone.cs | 61 +-- .../Neo4j.Driver.Tests.Integration.csproj | 52 +- .../Reactive/AbstractRxIT.cs | 44 +- .../Reactive/NavigationIT.cs | 71 +-- .../Reactive/NestedQueriesIT.cs | 19 +- .../Reactive/SessionIT.cs | 21 +- .../Reactive/SummaryIT.cs | 152 ++---- .../Reactive/TransactionIT.cs | 73 ++- .../Routing/BoltV4IT.cs | 95 ++-- .../Routing/RoutingDriverAsyncIT.cs | 82 +-- .../Routing/RoutingDriverIT.cs | 128 ++--- .../Routing/RoutingDriverTestBase.cs | 35 +- .../Stress/Async/AsyncFailingCommand.cs | 47 -- .../Stress/Async/AsyncFailingCommandInTx.cs | 56 -- .../Stress/Async/AsyncFailingCommandTxFunc.cs | 2 +- .../Stress/Async/AsyncReadCommand.cs | 48 -- .../Stress/Async/AsyncReadCommandInTx.cs | 61 --- .../Stress/Async/AsyncReadCommandTxFunc.cs | 2 +- .../Stress/Async/AsyncWriteCommand.cs | 69 --- .../Stress/Async/AsyncWriteCommandInTx.cs | 77 --- .../Stress/Async/AsyncWriteCommandTxFunc.cs | 2 +- .../AsyncWriteCommandUsingReadSession.cs | 56 -- .../AsyncWriteCommandUsingReadSessionInTx.cs | 64 --- ...AsyncWriteCommandUsingReadSessionTxFunc.cs | 2 +- .../Stress/Async/AsyncWrongCommand.cs | 50 -- .../Stress/Async/AsyncWrongCommandInTx.cs | 61 --- .../Stress/Async/AsyncWrongCommandTxFunc.cs | 2 +- .../Stress/AsyncCommand.cs | 22 +- .../Blocking/BlockingFailingCommandInTx.cs | 41 -- .../Blocking/BlockingFailingCommandTxFunc.cs | 2 +- .../Stress/Blocking/BlockingReadCommand.cs | 40 -- .../Blocking/BlockingReadCommandInTx.cs | 44 -- .../Blocking/BlockingReadCommandTxFunc.cs | 2 +- .../Stress/Blocking/BlockingWriteCommand.cs | 65 --- .../Blocking/BlockingWriteCommandInTx.cs | 67 --- .../Blocking/BlockingWriteCommandTxFunc.cs | 2 +- .../BlockingWriteCommandUsingReadSession.cs | 50 -- ...lockingWriteCommandUsingReadSessionInTx.cs | 51 -- ...ckingWriteCommandUsingReadSessionTxFunc.cs | 2 +- .../Blocking/BlockingWrongCommandInTx.cs | 39 -- .../Blocking/BlockingWrongCommandTxFunc.cs | 2 +- .../Stress/BlockingCommand.cs | 26 +- .../Stress/CausalClusterStressTests.cs | 6 +- .../Stress/Reactive/RxFailingCommand.cs | 52 -- .../Stress/Reactive/RxFailingCommandInTx.cs | 2 +- .../Stress/Reactive/RxReadCommand.cs | 51 -- .../Stress/Reactive/RxReadCommandInTx.cs | 2 +- .../Stress/Reactive/RxWriteCommand.cs | 67 --- .../Stress/Reactive/RxWriteCommandInTx.cs | 2 +- .../RxWriteCommandUsingReadSession.cs | 50 -- .../RxWriteCommandUsingReadSessionInTx.cs | 59 -- .../Stress/Reactive/RxWrongCommand.cs | 52 -- .../Stress/Reactive/RxWrongCommandInTx.cs | 2 +- .../Stress/RxCommand.cs | 8 +- .../Stress/SingleInstanceStressTests.cs | 4 +- .../Stress/StressTest.cs | 6 +- .../Stub/AccessModeTests.cs | 223 +++----- .../Stub/DirectDriverTests.cs | 168 ++---- .../Stub/MultiDatabasesTests.cs | 317 ++++------- .../Stub/ResultStreamingTests.cs | 139 ++--- .../Stub/RoutingDriverTests.cs | 90 +-- .../Stub/TransactionTests.cs | 180 +++--- .../Types/PointsIT.cs | 38 +- .../Types/TemporalTypesIT.cs | 39 +- Neo4j.Driver/Neo4j.Driver/AuthTokens.cs | 2 +- .../FluentQueries/ExecutableQuery.cs | 4 +- Neo4j.Driver/Neo4j.Driver/IResultCursor.cs | 4 +- .../Internal/AsyncSessionResourceManager.cs | 1 + Neo4j.Driver/Neo4j.Driver/Neo4jException.cs | 5 + Neo4j.Driver/Neo4j.Driver/SessionConfig.cs | 6 +- 109 files changed, 1945 insertions(+), 4567 deletions(-) create mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CausalClusterIntegrationTestFixture.cs rename Neo4j.Driver/Neo4j.Driver.Tests.Integration/{Stress/Blocking/BlockingWrongCommand.cs => Internals/CcIntegrationCollection.cs} (52%) rename Neo4j.Driver/Neo4j.Driver.Tests.Integration/{Stress/Blocking/BlockingFailingCommand.cs => Internals/SaIntegrationCollection.cs} (50%) rename Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/{Neo4jDefaultInstallation.cs => DefaultInstallation.cs} (72%) rename Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/{Neo4jSettingsHelper.cs => SettingsHelper.cs} (57%) delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSession.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSession.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommand.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSession.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSessionInTx.cs delete mode 100644 Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommand.cs diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/AuthenticationIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/AuthenticationIT.cs index bee5d3720..16e3337e1 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/AuthenticationIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/AuthenticationIT.cs @@ -19,13 +19,14 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class AuthenticationIT : DirectDriverTestBase +public sealed class AuthenticationIT : DirectDriverTestBase { public AuthenticationIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) @@ -35,24 +36,15 @@ public AuthenticationIT(ITestOutputHelper output, StandAloneIntegrationTestFixtu [RequireServerFact] public async Task AuthenticationErrorIfWrongAuthToken() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthTokens.Basic("fake", "fake"))) - { - var session = driver.AsyncSession(); - try - { - var exc = await Record.ExceptionAsync(() => session.RunAsync("Return 1")); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthTokens.Basic("fake", "fake")); + await using var session = driver.AsyncSession(); + var exc = await Record.ExceptionAsync(() => session.RunAsync("Return 1")); - exc.Should() - .BeOfType() - .Which - .Message.Should() - .Contain("The client is unauthorized due to authentication failure."); - } - finally - { - await session.CloseAsync(); - } - } + exc.Should() + .BeOfType() + .Which + .Message.Should() + .Contain("The client is unauthorized due to authentication failure."); } [RequireServerFact] @@ -96,21 +88,12 @@ public async Task ShouldCreateCustomAuthTokenWithAdditionalParameters() private static async Task VerifyConnectivity(Uri address, IAuthToken token) { - using (var driver = GraphDatabase.Driver(address, token)) - { - var session = driver.AsyncSession(); + await using var driver = GraphDatabase.Driver(address, token); + await using var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("RETURN 2 as Number"); - var records = await cursor.ToListAsync(r => r["Number"].As()); + var cursor = await session.RunAsync("RETURN 2 as Number"); + var records = await cursor.ToListAsync(r => r["Number"].As()); - records.Should().BeEquivalentTo(2); - } - finally - { - await session.CloseAsync(); - } - } + records.Should().BeEquivalentTo(2); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BoltV4IT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BoltV4IT.cs index e7f28b701..db22c93ee 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BoltV4IT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BoltV4IT.cs @@ -15,18 +15,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Threading.Tasks; using FluentAssertions; using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal.Util; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; -using static Neo4j.Driver.IntegrationTests.DatabaseExtensions; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Extensions.DatabaseExtensions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class BoltV4IT : DirectDriverTestBase +public sealed class BoltV4IT : DirectDriverTestBase { public BoltV4IT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) @@ -122,7 +121,7 @@ public async Task ShouldReturnDatabaseInfoForDefaultDatabaseInTxFunc() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldReturnDatabaseInfoForDefaultDatabaseWhenSpecifiedInTxFunc() { - Console.WriteLine($"Version = {ServerVersion.From(BoltkitHelper.ServerVersion())}"); + Output.WriteLine($"Version = {ServerVersion.From(BoltkitHelper.ServerVersion())}"); await VerifyDatabaseNameOnSummaryTxFunc("neo4j", "neo4j"); } @@ -210,83 +209,49 @@ public void ShouldThrowWhenDatabaseIsSpecifiedInTxFunc() private async Task VerifyDatabaseNameOnSummary(string name, string expected) { - var session = Server.Driver.AsyncSession( - o => - { - if (!string.IsNullOrEmpty(name)) - { - o.WithDatabase(name); - } - }); + await using var session = Server.Driver.AsyncSession(o => { ConfigureDb(o, name); }); - try - { - var cursor = await session.RunAsync("RETURN 1"); - var summary = await cursor.ConsumeAsync(); + var cursor = await session.RunAsync("RETURN 1"); + var summary = await cursor.ConsumeAsync(); - summary.Database.Should().NotBeNull(); - summary.Database.Name.Should().Be(expected); - } - finally - { - await session.CloseAsync(); - } + summary.Database.Should().NotBeNull(); + summary.Database.Name.Should().Be(expected); } private async Task VerifyDatabaseNameOnSummaryTx(string name, string expected) { - var session = Server.Driver.AsyncSession( - o => - { - if (!string.IsNullOrEmpty(name)) - { - o.WithDatabase(name); - } - }); + await using var session = Server.Driver.AsyncSession(o => { ConfigureDb(o, name); }); - try - { - var txc = await session.BeginTransactionAsync(); - var cursor = await txc.RunAsync("RETURN 1"); - var summary = await cursor.ConsumeAsync(); + var txc = await session.BeginTransactionAsync(); + var cursor = await txc.RunAsync("RETURN 1"); + var summary = await cursor.ConsumeAsync(); - summary.Database.Should().NotBeNull(); - summary.Database.Name.Should().Be(expected); + summary.Database.Should().NotBeNull(); + summary.Database.Name.Should().Be(expected); - await txc.CommitAsync(); - } - finally + await txc.CommitAsync(); + } + + private static void ConfigureDb(SessionConfigBuilder o, string name) + { + if (!string.IsNullOrEmpty(name)) { - await session.CloseAsync(); + o.WithDatabase(name); } } private async Task VerifyDatabaseNameOnSummaryTxFunc(string name, string expected) { - var session = Server.Driver.AsyncSession( - o => + await using var session = Server.Driver.AsyncSession(o => { ConfigureDb(o, name); }); + + var summary = await session.ExecuteReadAsync( + async txc => { - if (!string.IsNullOrEmpty(name)) - { - o.WithDatabase(name); - } + var cursor = await txc.RunAsync("RETURN 1"); + return await cursor.ConsumeAsync(); }); - try - { - var summary = await session.ReadTransactionAsync( - async txc => - { - var cursor = await txc.RunAsync("RETURN 1"); - return await cursor.ConsumeAsync(); - }); - - summary.Database.Should().NotBeNull(); - summary.Database.Name.Should().Be(expected); - } - finally - { - await session.CloseAsync(); - } + summary.Database.Should().NotBeNull(); + summary.Database.Name.Should().Be(expected); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BookmarkIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BookmarkIT.cs index d865a9ff4..d99be835a 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BookmarkIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/BookmarkIT.cs @@ -17,15 +17,14 @@ using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class BookmarkIT : DirectDriverTestBase +public sealed class BookmarkIT : DirectDriverTestBase { - private const string BookmarkHeader = "neo4j:bookmark:v1:tx"; - public BookmarkIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { } @@ -35,81 +34,60 @@ public BookmarkIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fix [RequireServerFact("3.1.0", VersionComparison.GreaterThanOrEqualTo)] public async Task ShouldContainLastBookmarkAfterTx() { - var session = Driver.AsyncSession(); + await using var session = Driver.AsyncSession(); - try - { - session.LastBookmark.Should().BeNull(); + session.LastBookmarks.Should().BeNull(); - await CreateNodeInTx(session, 1); + await CreateNodeInTx(session, 1); - session.LastBookmark.Should().NotBeNull(); - session.LastBookmark.Values.Should().NotBeEmpty(); - } - finally - { - await session.CloseAsync(); - } + session.LastBookmarks.Should().NotBeNull(); + session.LastBookmarks.Values.Should().NotBeEmpty(); } [RequireServerFact("3.1.0", VersionComparison.GreaterThanOrEqualTo)] public async Task BookmarkUnchangedAfterRolledBackTx() { - var session = Driver.AsyncSession(); - try - { - await CreateNodeInTx(session, 1); + await using var session = Driver.AsyncSession(); + await CreateNodeInTx(session, 1); - var bookmark = session.LastBookmark; - bookmark.Should().NotBeNull(); - bookmark.Values.Should().NotBeEmpty(); + var bookmark = session.LastBookmarks; + bookmark.Should().NotBeNull(); + bookmark.Values.Should().NotBeEmpty(); - var tx = await session.BeginTransactionAsync(); - try - { - await tx.RunAsync("CREATE (a:Person)"); - } - finally - { - await tx.RollbackAsync(); - } - - session.LastBookmark.Should().Be(bookmark); + var tx = await session.BeginTransactionAsync(); + try + { + await tx.RunAsync("CREATE (a:Person)"); } finally { - await session.CloseAsync(); + await tx.RollbackAsync(); } + + session.LastBookmarks.Should().Be(bookmark); } [RequireServerFact("3.1.0", VersionComparison.GreaterThanOrEqualTo)] public async Task BookmarkUnchangedAfterTxFailure() { - var session = Driver.AsyncSession(); - try - { - await CreateNodeInTx(session, 1); + await using var session = Driver.AsyncSession(); + await CreateNodeInTx(session, 1); - var bookmark = session.LastBookmark; - bookmark.Should().NotBeNull(); - bookmark.Values.Should().NotBeEmpty(); + var bookmark = session.LastBookmarks; + bookmark.Should().NotBeNull(); + bookmark.Values.Should().NotBeEmpty(); - var tx = await session.BeginTransactionAsync(); - var exc = await Record.ExceptionAsync( - async () => - { - await tx.RunAsync("RETURN"); - await tx.CommitAsync(); - }); + var tx = await session.BeginTransactionAsync(); + var exc = await Record.ExceptionAsync( + async () => + { + await tx.RunAsync("RETURN"); + await tx.CommitAsync(); + }); - exc.Should().BeOfType(); + exc.Should().BeOfType(); - session.LastBookmark.Should().Be(bookmark); - } - finally - { - await session.CloseAsync(); - } + session.LastBookmarks.Should().Be(bookmark); } private static async Task CreateNodeInTx(IAsyncSession session, int id) @@ -126,29 +104,4 @@ private static async Task CreateNodeInTx(IAsyncSession session, int id) throw; } } - - private static async Task CountNodeInTx(IDriver driver, int id, Bookmarks bookmarks = null) - { - var session = driver.AsyncSession(o => o.WithBookmarks(bookmarks)); - try - { - var tx = await session.BeginTransactionAsync(); - try - { - var cursor = await tx.RunAsync("MATCH (a:Person {id: $id}) RETURN a", new { id }); - var records = await cursor.ToListAsync(); - await tx.CommitAsync(); - return records.Count; - } - catch - { - await tx.RollbackAsync(); - throw; - } - } - finally - { - await session.CloseAsync(); - } - } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CertificateTrustIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CertificateTrustIT.cs index 173c65511..d8a63a8af 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CertificateTrustIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CertificateTrustIT.cs @@ -28,7 +28,7 @@ namespace Neo4j.Driver.IntegrationTests.Direct; -public class CertificateTrustIT : IClassFixture +public sealed class CertificateTrustIT : IClassFixture { public CertificateTrustIT(CertificateTrustIntegrationTestFixture fixture) { @@ -36,8 +36,8 @@ public CertificateTrustIT(CertificateTrustIntegrationTestFixture fixture) Pkcs12 = fixture.Pkcs12; } - public StandAlone Server { get; } - public Pkcs12Store Pkcs12 { get; } + private StandAlone Server { get; } + private Pkcs12Store Pkcs12 { get; } [ShouldNotRunInTestKitFact] public async Task CertificateTrustManager_ShouldTrust() @@ -155,21 +155,12 @@ private async Task VerifySuccess( private async Task TestConnectivity(Uri target, Config config) { - using (var driver = SetupWithCustomResolver(target, config)) - { - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("RETURN 1"); - var records = await cursor.ToListAsync(r => r[0].As()); + await using var driver = SetupWithCustomResolver(target, config); + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1"); + var records = await cursor.ToListAsync(r => r[0].As()); - records.Should().BeEquivalentTo(1); - } - finally - { - await session.CloseAsync(); - } - } + records.Should().BeEquivalentTo(1); } private IDriver SetupWithCustomResolver(Uri overridenUri, Config config) @@ -189,7 +180,7 @@ private IDriver SetupWithCustomResolver(Uri overridenUri, Config config) return GraphDatabase.CreateDriver(overridenUri, config, connectionFactory, connectionSettings); } - private class CustomHostResolver : IHostResolver + private sealed class CustomHostResolver : IHostResolver { private readonly IHostResolver _original; private readonly Uri _target; @@ -214,8 +205,6 @@ public Task ResolveAsync(string hostname) // ReSharper disable once ClassNeverInstantiated.Global public class CertificateTrustIntegrationTestFixture : IDisposable { - private bool _disposed; - public CertificateTrustIntegrationTestFixture() { if (!BoltkitHelper.ServerAvailable()) @@ -247,30 +236,8 @@ public CertificateTrustIntegrationTestFixture() public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~CertificateTrustIntegrationTestFixture() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - //Dispose managed state (managed objects). - StandAlone?.Dispose(); - StandAlone?.UpdateCertificate(Pkcs12); - } - - _disposed = true; + StandAlone?.Dispose(); + StandAlone?.UpdateCertificate(Pkcs12); } } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CypherParametersIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CypherParametersIT.cs index d0304a6ec..ff7ba4ce4 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CypherParametersIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/CypherParametersIT.cs @@ -19,11 +19,12 @@ using System.Linq; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class CypherParametersIT : DirectDriverTestBase +public sealed class CypherParametersIT : DirectDriverTestBase { public CypherParametersIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) @@ -35,248 +36,178 @@ public CypherParametersIT(ITestOutputHelper output, StandAloneIntegrationTestFix [RequireServerFact] public async Task ShouldHandleStringLiteral() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("CREATE (n:Person { name: 'Johan' })"); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync("MATCH (n:Person) WHERE n.name = $name RETURN n", new { name = "Johan" }); - var list = await cursor.ToListAsync(x => x["n"].As()); - list.Should().HaveCount(1); - - var node = list.First(); - node.Should().NotBeNull(); - node.Labels.Should().Contain("Person"); - node.Properties.Should().HaveCount(1); - node.Properties.Should().Contain(new KeyValuePair("name", "Johan")); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync("CREATE (n:Person { name: 'Johan' })"); + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync("MATCH (n:Person) WHERE n.name = $name RETURN n", new { name = "Johan" }); + var list = await cursor.ToListAsync(x => x["n"].As()); + list.Should().HaveCount(1); + + var node = list.First(); + node.Should().NotBeNull(); + node.Labels.Should().Contain("Person"); + node.Properties.Should().HaveCount(1); + node.Properties.Should().Contain(new KeyValuePair("name", "Johan")); } [RequireServerFact] public async Task ShouldHandleRegularExpression() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("CREATE (n:Person { name: 'Johan' })"); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync( - "MATCH (n:Person) WHERE n.name =~ $regex RETURN n.name", - new { regex = ".*h.*" }); - - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Johan"); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync("CREATE (n:Person { name: 'Johan' })"); + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync( + "MATCH (n:Person) WHERE n.name =~ $regex RETURN n.name", + new { regex = ".*h.*" }); + + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Johan"); } [RequireServerFact] public async Task ShouldHandleCaseSensitiveStringPatternMatching() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("CREATE (n:Person { name: 'Michael' })"); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync("CREATE (n:Person { name: 'michael' })"); - summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync( - "MATCH (n:Person) WHERE n.name STARTS WITH $name RETURN n.name", - new { name = "Michael" }); - - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Michael"); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync("CREATE (n:Person { name: 'Michael' })"); + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync("CREATE (n:Person { name: 'michael' })"); + summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync( + "MATCH (n:Person) WHERE n.name STARTS WITH $name RETURN n.name", + new { name = "Michael" }); + + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Michael"); } [RequireServerFact] public async Task ShouldHandleCreateNodeWithProperties() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync( - "CREATE ($props)", - new { props = new { name = "Andres", position = "Developer" } }); - - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync("MATCH (n) WHERE n.position = 'Developer' RETURN n.name"); - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Andres"); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync( + "CREATE ($props)", + new { props = new { name = "Andres", position = "Developer" } }); + + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync("MATCH (n) WHERE n.position = 'Developer' RETURN n.name"); + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Andres"); } [RequireServerFact] public async Task ShouldHandleCreateMultipleNodesWithProperties() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync( - "UNWIND $props AS properties CREATE(n:Person) SET n = properties", - new + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync( + "UNWIND $props AS properties CREATE(n:Person) SET n = properties", + new + { + props = new object[] { - props = new object[] - { - new { awesome = true, name = "Andres", position = "Developer" }, - new { children = 3, name = "Michael", position = "Developer" } - } - }); - - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(2); - - cursor = await session.RunAsync("MATCH (n) WHERE n.position = 'Developer' RETURN n.name"); - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Andres", "Michael"); - } - finally - { - await session.CloseAsync(); - } + new { awesome = true, name = "Andres", position = "Developer" }, + new { children = 3, name = "Michael", position = "Developer" } + } + }); + + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(2); + + cursor = await session.RunAsync("MATCH (n) WHERE n.position = 'Developer' RETURN n.name"); + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Andres", "Michael"); } [RequireServerFact] public async Task ShouldHandleSettingAllPropertiesOnANode() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("CREATE (n:Person { name: 'Michaela' })"); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync( - "MATCH (n:Person) WHERE n.name = 'Michaela' SET n = $props", - new { props = new { name = "Andres", position = "Developer" } }); - - summary = await cursor.ConsumeAsync(); - summary.Counters.PropertiesSet.Should().Be(2); - - cursor = await session.RunAsync( - "MATCH (n:Person) WHERE n.name = $name RETURN n.position", - new { name = "Andres" }); - - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Developer"); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync("CREATE (n:Person { name: 'Michaela' })"); + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync( + "MATCH (n:Person) WHERE n.name = 'Michaela' SET n = $props", + new { props = new { name = "Andres", position = "Developer" } }); + + summary = await cursor.ConsumeAsync(); + summary.Counters.PropertiesSet.Should().Be(2); + + cursor = await session.RunAsync( + "MATCH (n:Person) WHERE n.name = $name RETURN n.position", + new { name = "Andres" }); + + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Developer"); } [RequireServerFact] public async Task ShouldHandleSkipAndLimit() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync( - "UNWIND range(1,1000) as number RETURN number SKIP $skip LIMIT $limit", - new { skip = 100, limit = 1 }); - - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().AllBeEquivalentTo(101); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync( + "UNWIND range(1,1000) as number RETURN number SKIP $skip LIMIT $limit", + new { skip = 100, limit = 1 }); + + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().AllBeEquivalentTo(101); } [RequireServerFact] public async Task ShouldHandleNodeId() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("CREATE (n:Person { name: 'Michaela' }) RETURN id(n)"); - var id = await cursor.SingleAsync(r => r[0].As()); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(1); - - cursor = await session.RunAsync("MATCH (n) WHERE id(n) = $id RETURN n.name", new { id }); - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Michaela"); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync("CREATE (n:Person { name: 'Michaela' }) RETURN id(n)"); + var id = await cursor.SingleAsync(r => r[0].As()); + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(1); + + cursor = await session.RunAsync("MATCH (n) WHERE id(n) = $id RETURN n.name", new { id }); + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Michaela"); } [RequireServerFact] public async Task ShouldHandleMultipleNodeIds() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync( - "UNWIND $props AS properties CREATE(n:Person) SET n = properties RETURN id(n)", - new + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync( + "UNWIND $props AS properties CREATE(n:Person) SET n = properties RETURN id(n)", + new + { + props = new List { - props = new List - { - new { name = "Johan" }, - new { name = "Michaela" }, - new { name = "Andres" } - } - }); - - var ids = await cursor.ToListAsync(r => r[0].As()); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(3); - - cursor = await session.RunAsync("MATCH (n) WHERE id(n) IN $idList RETURN n.name", new { idList = ids }); - var list = await cursor.ToListAsync(r => r[0].As()); - list.Should().BeEquivalentTo("Johan", "Michaela", "Andres"); - } - finally - { - await session.CloseAsync(); - } + new { name = "Johan" }, + new { name = "Michaela" }, + new { name = "Andres" } + } + }); + + var ids = await cursor.ToListAsync(r => r[0].As()); + var summary = await cursor.ConsumeAsync(); + summary.Counters.NodesCreated.Should().Be(3); + + cursor = await session.RunAsync("MATCH (n) WHERE id(n) IN $idList RETURN n.name", new { idList = ids }); + var list = await cursor.ToListAsync(r => r[0].As()); + list.Should().BeEquivalentTo("Johan", "Michaela", "Andres"); } [RequireServerFact] public async Task ShouldHandleCallingProcedures() { - var session = Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("CALL dbms.queryJmx($query) yield name", new { query = "*:*" }); - var names = await cursor.ToListAsync(r => r[0].As()); - - names.Should().HaveCount(c => c > 0); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var cursor = await session.RunAsync("CALL dbms.queryJmx($query) yield name", new { query = "*:*" }); + var names = await cursor.ToListAsync(r => r[0].As()); + + names.Should().HaveCount(c => c > 0); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DirectDriverTestBase.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DirectDriverTestBase.cs index 6864d3361..7a78808b1 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DirectDriverTestBase.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DirectDriverTestBase.cs @@ -22,7 +22,7 @@ namespace Neo4j.Driver.IntegrationTests.Direct; -[Collection(SAIntegrationCollection.CollectionName)] +[Collection(SaIntegrationCollection.CollectionName)] public abstract class DirectDriverTestBase : IDisposable { private bool _disposed; @@ -42,27 +42,14 @@ protected DirectDriverTestBase(ITestOutputHelper output, StandAloneIntegrationTe public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~DirectDriverTestBase() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) + switch (_disposed) { - using (var session = Server.Driver.Session()) + case true: return; + case false: { + using var session = Server.Driver.Session(); session.Run("MATCH (n) DETACH DELETE n").Consume(); + break; } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DriverIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DriverIT.cs index 5fe7795ca..8582546f8 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DriverIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/DriverIT.cs @@ -28,7 +28,7 @@ namespace Neo4j.Driver.IntegrationTests.Direct; -public class DriverIT : DirectDriverTestBase +public sealed class DriverIT : DirectDriverTestBase { public DriverIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { @@ -41,108 +41,71 @@ public async Task ShouldPackAndUnpackBytes() var byteArray = PackStreamBitConverter.GetBytes("hello, world"); // When - var session = Server.Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync( - "CREATE (a {value: $value}) RETURN a.value", - new Dictionary { { "value", byteArray } }); + await using var session = Server.Driver.AsyncSession(); + var cursor = await session.RunAsync( + "CREATE (a {value: $value}) RETURN a.value", + new Dictionary { { "value", byteArray } }); - var value = await cursor.SingleAsync(r => r["a.value"].As()); + var value = await cursor.SingleAsync(r => r["a.value"].As()); - // Then - value.Should().BeEquivalentTo(byteArray); - } - finally - { - await session.CloseAsync(); - } + // Then + value.Should().BeEquivalentTo(byteArray); } [RequireServerWithIPv6Fact("3.1.0", VersionComparison.GreaterThanOrEqualTo)] public async Task ShouldConnectIPv6AddressIfEnabled() { - using (var driver = GraphDatabase.Driver( - "bolt://[::1]:7687", - AuthToken, - o => o.WithIpv6Enabled(true))) - { - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("RETURN 1"); - var result = await cursor.SingleAsync(r => r[0].As()); + await using var driver = GraphDatabase.Driver( + "bolt://[::1]:7687", + AuthToken, + o => o.WithIpv6Enabled(true)); - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } - } + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1"); + var result = await cursor.SingleAsync(r => r[0].As()); + + result.Should().Be(1); } [RequireServerFact("3.1.0", VersionComparison.GreaterThanOrEqualTo)] public async Task ShouldNotConnectIPv6AddressIfDisabled() { - using (var driver = GraphDatabase.Driver( - "bolt://[::1]:7687", - AuthToken, - o => o.WithIpv6Enabled(false))) - { - var session = driver.AsyncSession(); - try - { - var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + await using var driver = GraphDatabase.Driver( + "bolt://[::1]:7687", + AuthToken, + o => o.WithIpv6Enabled(false)); - exc.GetBaseException().Should().BeOfType(); - exc.GetBaseException().Message.Should().Contain("This protocol version is not supported"); - } - finally - { - await session.CloseAsync(); - } - } + await using var session = driver.AsyncSession(); + var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + + exc.Should().NotBeNull(); + exc!.GetBaseException().Should().BeOfType(); + exc.GetBaseException().Message.Should().Contain("This protocol version is not supported"); } [RequireServerFact] public async Task ShouldConnectIPv4AddressIfIpv6Disabled() { - var session = Server.Driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("RETURN 1"); - var result = await cursor.SingleAsync(r => r[0].As()); + await using var session = Server.Driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1"); + var result = await cursor.SingleAsync(r => r[0].As()); - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } + result.Should().Be(1); } [RequireServerWithIPv6Fact] public async Task ShouldConnectIPv4AddressIfIpv6Enabled() { - using (var driver = GraphDatabase.Driver( - Neo4jDefaultInstallation.BoltUri, - AuthToken, - o => o.WithIpv6Enabled(true))) - { - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("RETURN 1"); - var result = await cursor.SingleAsync(r => r[0].As()); + await using var driver = GraphDatabase.Driver( + DefaultInstallation.BoltUri, + AuthToken, + o => o.WithIpv6Enabled(true)); - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } - } + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1"); + var result = await cursor.SingleAsync(r => r[0].As()); + + result.Should().Be(1); } [RequireServerTheory] @@ -151,41 +114,33 @@ public async Task ShouldConnectIPv4AddressIfIpv6Enabled() public async Task ShouldCloseAgedIdleConnections(int sessionCount) { // Given - using (var driver = GraphDatabase.Driver( - Neo4jDefaultInstallation.BoltUri, - AuthToken, - o => - { - o.WithMetricsEnabled(true); - o.WithConnectionIdleTimeout(TimeSpan.Zero); // enable but always timeout idle connections - })) - { - // When - for (var i = 0; i < sessionCount; i++) + await using var driver = GraphDatabase.Driver( + DefaultInstallation.BoltUri, + AuthToken, + o => { - // should not reuse the same connection as it should timeout - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("RETURN 1"); - var result = await cursor.SingleAsync(r => r[0].As()); - - result.Should().Be(1); - - Thread.Sleep(1); // block to let the timer aware the timeout - } - finally - { - await session.CloseAsync(); - } - } - - // Then - var metrics = ((Internal.Driver)driver).GetMetrics(); - var m = metrics.ConnectionPoolMetrics.Single().Value; - Output.WriteLine(m.ToString()); - m.Created.Should().Be(sessionCount); - m.Created.Should().Be(m.Closed + 1); + o.WithMetricsEnabled(true); + o.WithConnectionIdleTimeout(TimeSpan.Zero); // enable but always timeout idle connections + }); + + // When + for (var i = 0; i < sessionCount; i++) + { + // should not reuse the same connection as it should timeout + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1"); + var result = await cursor.SingleAsync(r => r[0].As()); + + result.Should().Be(1); + + Thread.Sleep(1); // block to let the timer aware the timeout } + + // Then + var metrics = ((Internal.Driver)driver).GetMetrics(); + var m = metrics.ConnectionPoolMetrics.Single().Value; + Output.WriteLine(m.ToString()); + m.Created.Should().Be(sessionCount); + m.Created.Should().Be(m.Closed + 1); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/EncryptionIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/EncryptionIT.cs index 8d938f18d..e8f4e49fb 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/EncryptionIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/EncryptionIT.cs @@ -18,55 +18,46 @@ using System; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class EncryptionIT : DirectDriverTestBase +public sealed class EncryptionIT : DirectDriverTestBase { public EncryptionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { } - [ShouldNotRunInTestKit_RequireServerFactAttribute] + [ShouldNotRunInTestKitRequireServerFact] public async Task ShouldBeAbleToConnectWithInsecureConfig() { - using (var driver = GraphDatabase.Driver( - ServerEndPoint, - AuthToken, - o => o - .WithEncryptionLevel(EncryptionLevel.Encrypted) - .WithTrustManager(TrustManager.CreateInsecure()))) - { - await VerifyConnectivity(driver); - } + await using var driver = GraphDatabase.Driver( + ServerEndPoint, + AuthToken, + o => o + .WithEncryptionLevel(EncryptionLevel.Encrypted) + .WithTrustManager(TrustManager.CreateInsecure())); + + await VerifyConnectivity(driver); } - [ShouldNotRunInTestKit_RequireServerFactAttribute] + [ShouldNotRunInTestKitRequireServerFact] public async Task ShouldBeAbleToConnectUsingInsecureUri() { var builder = new UriBuilder("bolt+ssc", ServerEndPoint.Host, ServerEndPoint.Port); - using (var driver = GraphDatabase.Driver(builder.Uri, AuthToken)) - { - await VerifyConnectivity(driver); - } + await using var driver = GraphDatabase.Driver(builder.Uri, AuthToken); + await VerifyConnectivity(driver); } private static async Task VerifyConnectivity(IDriver driver) { - var session = driver.AsyncSession(); + await using var session = driver.AsyncSession(); - try - { var cursor = await session.RunAsync("RETURN 2 as Number"); var records = await cursor.ToListAsync(r => r["Number"].As()); records.Should().BeEquivalentTo(2); - } - finally - { - await session.CloseAsync(); - } } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ErrorIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ErrorIT.cs index b3ad555c8..d835f5432 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ErrorIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ErrorIT.cs @@ -24,7 +24,7 @@ namespace Neo4j.Driver.IntegrationTests.Direct; -public class ErrorIT : DirectDriverTestBase +public sealed class ErrorIT : DirectDriverTestBase { public ErrorIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { @@ -35,95 +35,65 @@ public ErrorIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixtur [RequireServerFact] public async Task ErrorToRunSessionInTransaction() { - var session = Driver.AsyncSession(); + await using var session = Driver.AsyncSession(); + var tx = await session.BeginTransactionAsync(); try { - var tx = await session.BeginTransactionAsync(); - try - { - var ex = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + var ex = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - ex.Should() - .BeOfType() - .Which - .Message.Should() - .StartWith("Attempting to nest transactions"); - } - finally - { - await tx.RollbackAsync(); - } + ex.Should() + .BeOfType() + .Which + .Message.Should() + .StartWith("Attempting to nest transactions"); } finally { - await session.CloseAsync(); + await tx.RollbackAsync(); } } [RequireServerFact] public async Task ErrorToRunTransactionInTransaction() { - var session = Driver.AsyncSession(); + await using var session = Driver.AsyncSession(); + var tx = await session.BeginTransactionAsync(); try { - var tx = await session.BeginTransactionAsync(); - try - { - var ex = await Record.ExceptionAsync(() => session.BeginTransactionAsync()); + var ex = await Record.ExceptionAsync(() => session.BeginTransactionAsync()); - ex.Should() - .BeOfType() - .Which - .Message.Should() - .StartWith("Attempting to nest transactions"); - } - finally - { - await tx.RollbackAsync(); - } + ex.Should() + .BeOfType() + .Which + .Message.Should() + .StartWith("Attempting to nest transactions"); } finally { - await session.CloseAsync(); + await tx.RollbackAsync(); } } [RequireServerFact] public async Task ErrorToRunInvalidCypher() { - var session = Driver.AsyncSession(); - try - { - var result = await session.RunAsync("Invalid Cypher"); - var ex = await Record.ExceptionAsync(() => result.ConsumeAsync()); + await using var session = Driver.AsyncSession(); + var result = await session.RunAsync("Invalid Cypher"); + var ex = await Record.ExceptionAsync(() => result.ConsumeAsync()); - ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); - } - finally - { - await session.CloseAsync(); - } + ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); } [RequireServerFact] public async Task ShouldFailToConnectIncorrectPort() { - var uri = Neo4jDefaultInstallation.BoltUri.Replace(Neo4jDefaultInstallation.BoltPort, "1234"); + var uri = DefaultInstallation.BoltUri.Replace(DefaultInstallation.BoltPort, "1234"); - using (var driver = GraphDatabase.Driver(uri)) - { - var session = driver.AsyncSession(); - try - { - var ex = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + await using var driver = GraphDatabase.Driver(uri); + await using var session = driver.AsyncSession(); + var ex = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - ex.Should().BeOfType(); - } - finally - { - await session.CloseAsync(); - } - } + ex.Should().BeOfType(); } [RequireServerFact] diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/NestedQueriesIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/NestedQueriesIT.cs index b6f9c3462..c4b9c9207 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/NestedQueriesIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/NestedQueriesIT.cs @@ -17,12 +17,13 @@ using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class NestedQueriesIT : DirectDriverTestBase +public sealed class NestedQueriesIT : DirectDriverTestBase { public NestedQueriesIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { @@ -31,299 +32,230 @@ public NestedQueriesIT(ITestOutputHelper output, StandAloneIntegrationTestFixtur [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithSessionRuns() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var cursor1 = await session.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + var error = await Record.ExceptionAsync( + async () => { - var cursor1 = await session.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - var error = await Record.ExceptionAsync( - async () => - { - while (await cursor1.FetchAsync()) - { - var record = cursor1.Current; - await session.RunAsync( - "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", - new { x = record["x"].As() }); - } - }); + while (await cursor1.FetchAsync()) + { + var record = cursor1.Current; + await session.RunAsync( + "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", + new { x = record["x"].As() }); + } + }); - error.Should().BeOfType(); - error.Message.Should().Contain("result has already been consumed"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("result has already been consumed"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithSessionAndTxRuns() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var cursor1 = await session.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + var error = await Record.ExceptionAsync( + async () => { - var cursor1 = await session.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - var error = await Record.ExceptionAsync( - async () => - { - while (await cursor1.FetchAsync()) - { - await session.BeginTransactionAsync(); - } - }); + while (await cursor1.FetchAsync()) + { + await session.BeginTransactionAsync(); + } + }); - error.Should().BeOfType(); - error.Message.Should() - .Contain("result has already been consumed"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("result has already been consumed"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithSessionRunAndTxFunc() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try - { - var cursor1 = await session.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - var error = await Record.ExceptionAsync( - async () => - { - while (await cursor1.FetchAsync()) - { - var record = cursor1.Current; - await session.WriteTransactionAsync( - async tx => await tx.RunAsync( - "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", - new { x = record["x"].As() })); - } - }); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); - error.Should().BeOfType(); - error.Message.Should() - .Contain("result has already been consumed"); - } - finally + var cursor1 = await session.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + + var error = await Record.ExceptionAsync( + async () => { - await session.CloseAsync(); - } - } + while (await cursor1.FetchAsync()) + { + var record = cursor1.Current; + await session.ExecuteWriteAsync( + async tx => await tx.RunAsync( + "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", + new { x = record["x"].As() })); + } + }); + + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("result has already been consumed"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithTxAndSessionRuns() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var tx = await session.BeginTransactionAsync(); + var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + var error = await Record.ExceptionAsync( + async () => { - var tx = await session.BeginTransactionAsync(); - var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - var error = await Record.ExceptionAsync( - async () => - { - while (await cursor1.FetchAsync()) - { - var record = cursor1.Current; - await session.RunAsync( - "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", - new { x = record["x"].As() }); - } - }); + while (await cursor1.FetchAsync()) + { + var record = cursor1.Current; + await session.RunAsync( + "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", + new { x = record["x"].As() }); + } + }); - error.Should().BeOfType(); - error.Message.Should() - .Contain("Attempting to nest transactions"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Attempting to nest transactions"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithTxRuns() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var tx = await session.BeginTransactionAsync(); + var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + var error = await Record.ExceptionAsync( + async () => { - var tx = await session.BeginTransactionAsync(); - var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - var error = await Record.ExceptionAsync( - async () => - { - while (await cursor1.FetchAsync()) - { - await session.BeginTransactionAsync(); - } - }); + while (await cursor1.FetchAsync()) + { + await session.BeginTransactionAsync(); + } + }); - error.Should().BeOfType(); - error.Message.Should() - .Contain("Attempting to nest transactions"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Attempting to nest transactions"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithTxRunAndTxFunc() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var tx = await session.BeginTransactionAsync(); + var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + var error = await Record.ExceptionAsync( + async () => { - var tx = await session.BeginTransactionAsync(); - var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - var error = await Record.ExceptionAsync( - async () => + while (await cursor1.FetchAsync()) + { + var record = cursor1.Current; + await session.ExecuteWriteAsync( + async tx2 => await tx2.RunAsync( + "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", + new { x = record["x"].As() })); + } + }); + + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Attempting to nest transactions"); + } + + [RequireServerFact] + public async Task ShouldErrorToRunNestedQueriesWithTxFuncs() + { + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var error = await Record.ExceptionAsync( + async () => + await session.ExecuteReadAsync( + async tx => { + var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); while (await cursor1.FetchAsync()) { var record = cursor1.Current; - await session.WriteTransactionAsync( + await session.ExecuteWriteAsync( async tx2 => await tx2.RunAsync( "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", new { x = record["x"].As() })); } - }); - - error.Should().BeOfType(); - error.Message.Should() - .Contain("Attempting to nest transactions"); - } - finally - { - await session.CloseAsync(); - } - } - } - - [RequireServerFact] - public async Task ShouldErrorToRunNestedQueriesWithTxFuncs() - { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try - { - var error = await Record.ExceptionAsync( - async () => - await session.ReadTransactionAsync( - async tx => - { - var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - while (await cursor1.FetchAsync()) - { - var record = cursor1.Current; - await session.WriteTransactionAsync( - async tx2 => await tx2.RunAsync( - "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", - new { x = record["x"].As() })); - } - })); + })); - error.Should().BeOfType(); - error.Message.Should() - .Contain("Attempting to nest transactions"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Attempting to nest transactions"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithTxFuncAndSessionRun() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try - { - var error = await Record.ExceptionAsync( - async () => - await session.ReadTransactionAsync( - async tx => - { - var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - while (await cursor1.FetchAsync()) - { - var record = cursor1.Current; - await session.RunAsync( - "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", - new { x = record["x"].As() }); - } - })); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var error = await Record.ExceptionAsync( + async () => + await session.ExecuteReadAsync( + async tx => + { + var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + while (await cursor1.FetchAsync()) + { + var record = cursor1.Current; + await session.RunAsync( + "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", + new { x = record["x"].As() }); + } + })); - error.Should().BeOfType(); - error.Message.Should() - .Contain("Attempting to nest transactions"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Attempting to nest transactions"); } [RequireServerFact] public async Task ShouldErrorToRunNestedQueriesWithTxFuncAndTxRun() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try - { - var error = await Record.ExceptionAsync( - async () => - await session.ReadTransactionAsync( - async tx => - { - var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - while (await cursor1.FetchAsync()) - { - await session.BeginTransactionAsync(); - } - })); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var error = await Record.ExceptionAsync( + async () => + await session.ExecuteReadAsync( + async tx => + { + var cursor1 = await tx.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + while (await cursor1.FetchAsync()) + { + await session.BeginTransactionAsync(); + } + })); - error.Should().BeOfType(); - error.Message.Should() - .Contain("Attempting to nest transactions"); - } - finally - { - await session.CloseAsync(); - } - } + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Attempting to nest transactions"); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ResultIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ResultIT.cs index e3dfd0e3c..6988fcc5e 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ResultIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/ResultIT.cs @@ -22,12 +22,12 @@ using Neo4j.Driver.Tests; using Xunit; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.SessionConfigBuilder; namespace Neo4j.Driver.IntegrationTests.Direct; -public class ResultIT : DirectDriverTestBase +public sealed class ResultIT : DirectDriverTestBase { public ResultIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { @@ -59,7 +59,7 @@ public async Task GetSummary() var serverInfo = summary.Server; - var boltAddress = Neo4jDefaultInstallation.BoltUri.Replace("bolt://", string.Empty); + var boltAddress = DefaultInstallation.BoltUri.Replace("bolt://", string.Empty); serverInfo.Address.Should().Be(boltAddress); summary.ResultAvailableAfter.Should().BeGreaterOrEqualTo(TimeSpan.Zero); summary.ResultConsumedAfter.Should().BeGreaterOrEqualTo(TimeSpan.Zero); @@ -177,8 +177,8 @@ public async Task AccessSummaryAfterFailure() var summary = await cursor.ConsumeAsync(); - var boltAddress = Neo4jDefaultInstallation.BoltUri.Replace( - Neo4jDefaultInstallation.BoltHeader, + var boltAddress = DefaultInstallation.BoltUri.Replace( + DefaultInstallation.BoltHeader, string.Empty); summary.Should().NotBeNull(); @@ -200,8 +200,8 @@ public async Task ErrorAccessRecordsAfterConsume() var cursor = await session.RunAsync("unwind range(1,3) as n return n"); var summary = await cursor.ConsumeAsync(); - var boltAddress = Neo4jDefaultInstallation.BoltUri.Replace( - Neo4jDefaultInstallation.BoltHeader, + var boltAddress = DefaultInstallation.BoltUri.Replace( + DefaultInstallation.BoltHeader, string.Empty); summary.Should().NotBeNull(); @@ -323,11 +323,11 @@ private static async Task CanAccessSummary(IResultCursor cursor) private static async Task AssertCannotAccessRecords(IResultCursor cursor) { - await ConsumedException.ThrowsResultConsumedException(async () => await cursor.FetchAsync()); - await ConsumedException.ThrowsResultConsumedException(async () => await cursor.PeekAsync()); + await ConsumedException.ThrowsResultConsumedException(() => cursor.FetchAsync()); + await ConsumedException.ThrowsResultConsumedException(() => cursor.PeekAsync()); ConsumedException.ThrowsResultConsumedException(() => cursor.Current); - await ConsumedException.ThrowsResultConsumedException(async () => await cursor.SingleAsync()); - await ConsumedException.ThrowsResultConsumedException(async () => await cursor.ToListAsync()); - await ConsumedException.ThrowsResultConsumedException(async () => await cursor.ForEachAsync(r => {})); + await ConsumedException.ThrowsResultConsumedException(() => cursor.SingleAsync()); + await ConsumedException.ThrowsResultConsumedException(() => cursor.ToListAsync()); + await ConsumedException.ThrowsResultConsumedException(() => cursor.ForEachAsync(_ => {})); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/SessionIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/SessionIT.cs index 819794427..820f527dc 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/SessionIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/SessionIT.cs @@ -20,13 +20,14 @@ using System.Net.Sockets; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class SessionIT : DirectDriverTestBase +public sealed class SessionIT : DirectDriverTestBase { public SessionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { @@ -37,19 +38,16 @@ public SessionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixt [RequireServerFact] public async Task ServiceUnavailableErrorWhenFailedToConn() { - var uri = Neo4jDefaultInstallation.BoltUri.Replace(Neo4jDefaultInstallation.BoltPort, "123"); + var uri = DefaultInstallation.BoltUri.Replace(DefaultInstallation.BoltPort, "123"); using var driver = GraphDatabase.Driver(uri); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + await using var session = driver.AsyncSession(); + var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - exc.Should().BeOfType(); - exc.Message.Should().Contain("Connection with the server breaks"); - exc.GetBaseException().Should().BeAssignableTo(); - } + exc.Should().BeOfType(); + exc!.Message.Should().Contain("Connection with the server breaks"); + exc.GetBaseException().Should().BeAssignableTo(); } [RequireServerFact] @@ -58,11 +56,8 @@ public async Task DisallowNewSessionAfterDriverDispose() var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); using (driver) { - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - await VerifyRunsQuery(session); - } + await using var session = driver.AsyncSession(); + await VerifyRunsQuery(session); } // Then @@ -97,56 +92,48 @@ public async Task DisallowRunInSessionAfterDriverDispose() [RequireServerFact] public async Task ShouldConnectAndRun() { - var session = Driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var result = await session.RunAsync("RETURN 2 as Number"); - await result.ConsumeAsync(); + await using var session = Driver.AsyncSession(); + var result = await session.RunAsync("RETURN 2 as Number"); + await result.ConsumeAsync(); - var keys = await result.KeysAsync(); - keys.Should().BeEquivalentTo("Number"); - } + var keys = await result.KeysAsync(); + keys.Should().BeEquivalentTo("Number"); } [RequireServerFact] public async Task ShouldBeAbleToRunMultiQuerysInOneTransaction() { - var session = Driver.AsyncSession(); - await using (session.ConfigureAwait(false)) + await using var session = Driver.AsyncSession(); + var tx = await session.BeginTransactionAsync(); + try { - var tx = await session.BeginTransactionAsync(); - try - { - // clean db - await tx.RunAndConsumeAsync("MATCH (n) DETACH DELETE n RETURN count(*)"); - - var record = await tx.RunAndSingleAsync("CREATE (n {name:'Steve Brook'}) RETURN n.name", null); - - record["n.name"].Should().Be("Steve Brook"); - - await tx.CommitAsync(); - } - catch - { - await tx.RollbackAsync(); - throw; - } + // clean db + await tx.RunAndConsumeAsync("MATCH (n) DETACH DELETE n RETURN count(*)"); + + var record = await tx.RunAndSingleAsync("CREATE (n {name:'Steve Brook'}) RETURN n.name", null); + + record["n.name"].Should().Be("Steve Brook"); + + await tx.CommitAsync(); + } + catch + { + await tx.RollbackAsync(); + throw; } } [RequireServerFact] public async Task TheSessionErrorShouldBeClearedForEachSession() { - var session = Driver.AsyncSession(); - await using (session.ConfigureAwait(false)) + await using (var session = Driver.AsyncSession()) { var ex = await Record.ExceptionAsync(() => session.RunAndConsumeAsync("Invalid Cypher")); ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); } - session = Driver.AsyncSession(); - await using (session.ConfigureAwait(false)) + await using (var session = Driver.AsyncSession()) { await VerifyRunsQuery(session); } @@ -170,239 +157,208 @@ public async Task AfterErrorTheFirstSyncShouldAckFailureSoThatNewQueryCouldRun() public async Task RollBackTxIfErrorWithConsume() { // Given - var session = Driver.AsyncSession(); - await using (session.ConfigureAwait(false)) + await using var session = Driver.AsyncSession(); + // When failed to run a tx with consume + var tx = await session.BeginTransactionAsync(); + try { - // When failed to run a tx with consume - var tx = await session.BeginTransactionAsync(); - try - { - var ex = await Record.ExceptionAsync(() => tx.RunAndConsumeAsync("Invalid Cypher")); - ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); - } - finally - { - await tx.RollbackAsync(); - } - - // Then can run more afterwards - var result = await session.RunAndSingleAsync("RETURN 1", null); - result[0].Should().BeEquivalentTo(1); + var ex = await Record.ExceptionAsync(() => tx.RunAndConsumeAsync("Invalid Cypher")); + ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); + } + finally + { + await tx.RollbackAsync(); } + + // Then can run more afterwards + var result = await session.RunAndSingleAsync("RETURN 1", null); + result[0].Should().BeEquivalentTo(1); } [RequireServerFact] public async Task RollBackTxIfErrorWithoutConsume() { // Given - var session = Driver.AsyncSession(); - await using (session.ConfigureAwait(false)) + await using var session = Driver.AsyncSession(); + // When failed to run a tx without consume + var tx = await session.BeginTransactionAsync(); + await tx.RunAsync("CREATE (a { name: 'lizhen' })"); + await tx.RunAsync("Invalid Cypher"); + + var ex = await Record.ExceptionAsync(() => tx.CommitAsync()); + ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); + + // Then can still run more afterwards + var anotherTx = await session.BeginTransactionAsync(); + try { - // When failed to run a tx without consume - var tx = await session.BeginTransactionAsync(); - await tx.RunAsync("CREATE (a { name: 'lizhen' })"); - await tx.RunAsync("Invalid Cypher"); + var result = + await anotherTx.RunAndSingleAsync("MATCH (a {name : 'a person'}) RETURN count(a)", null); - var ex = await Record.ExceptionAsync(() => tx.CommitAsync()); - ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); + result[0].Should().BeEquivalentTo(0); - // Then can still run more afterwards - var anotherTx = await session.BeginTransactionAsync(); - try - { - var result = - await anotherTx.RunAndSingleAsync("MATCH (a {name : 'a person'}) RETURN count(a)", null); - - result[0].Should().BeEquivalentTo(0); - - await anotherTx.CommitAsync(); - } - catch - { - await anotherTx.RollbackAsync(); - throw; - } + await anotherTx.CommitAsync(); + } + catch + { + await anotherTx.RollbackAsync(); + throw; } } [RequireServerFact] public async Task ShouldNotThrowExceptionWhenSessionClosedAfterDriver() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) + await using var session = driver.AsyncSession(); + var tx = await session.BeginTransactionAsync(); + try { - var tx = await session.BeginTransactionAsync(); - try - { - var ex = await Record.ExceptionAsync(() => tx.RunAndConsumeAsync("Invalid Cypher")); - ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); - } - finally - { - await tx.RollbackAsync(); - } - - var result = await session.RunAndSingleAsync("RETURN 1", null); - result[0].Should().BeEquivalentTo(1); + var ex = await Record.ExceptionAsync(() => tx.RunAndConsumeAsync("Invalid Cypher")); + ex.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); } + finally + { + await tx.RollbackAsync(); + } + + var result = await session.RunAndSingleAsync("RETURN 1", null); + result[0].Should().BeEquivalentTo(1); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterRun() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor = await session.RunAsync("RETURN 1 As X"); - var keys = await cursor.KeysAsync(); + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1 As X"); + var keys = await cursor.KeysAsync(); - keys.Should().BeEquivalentTo("X"); - } + keys.Should().BeEquivalentTo("X"); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterRunAndResultConsumption() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor = await session.RunAsync("RETURN 1 As X"); - var keys1 = await cursor.KeysAsync(); + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1 As X"); + var keys1 = await cursor.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); + keys1.Should().BeEquivalentTo("X"); - await cursor.ConsumeAsync(); + await cursor.ConsumeAsync(); - var keys2 = await cursor.KeysAsync(); - keys2.Should().BeEquivalentTo("X"); - } + var keys2 = await cursor.KeysAsync(); + keys2.Should().BeEquivalentTo("X"); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRun() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor1 = await session.RunAsync("RETURN 1 As X"); - var cursor2 = await session.RunAsync("RETURN 1 As Y"); + await using var session = driver.AsyncSession(); + var cursor1 = await session.RunAsync("RETURN 1 As X"); + var cursor2 = await session.RunAsync("RETURN 1 As Y"); - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - } + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRunAndResultConsumption() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor1 = await session.RunAsync("RETURN 1 As X"); - var cursor2 = await session.RunAsync("RETURN 1 As Y"); + await using var session = driver.AsyncSession(); + var cursor1 = await session.RunAsync("RETURN 1 As X"); + var cursor2 = await session.RunAsync("RETURN 1 As Y"); - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); - await cursor1.ConsumeAsync(); - await cursor2.ConsumeAsync(); + await cursor1.ConsumeAsync(); + await cursor2.ConsumeAsync(); - keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - } + keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRunNoOrder() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor1 = await session.RunAsync("RETURN 1 As X"); - var cursor2 = await session.RunAsync("RETURN 1 As Y"); + await using var session = driver.AsyncSession(); + var cursor1 = await session.RunAsync("RETURN 1 As X"); + var cursor2 = await session.RunAsync("RETURN 1 As Y"); - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - } + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRunAndResultConsumptionNoOrder() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor1 = await session.RunAsync("RETURN 1 As X"); - var cursor2 = await session.RunAsync("RETURN 1 As Y"); + await using var session = driver.AsyncSession(); + var cursor1 = await session.RunAsync("RETURN 1 As X"); + var cursor2 = await session.RunAsync("RETURN 1 As Y"); - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); - await cursor2.ConsumeAsync(); - await cursor1.ConsumeAsync(); + await cursor2.ConsumeAsync(); + await cursor1.ConsumeAsync(); - keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - } + keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); } [RequireServerFact] public async Task ShouldNotBeAbleToAccessRecordsAfterSessionClose() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); IResultCursor cursor; - await using (session.ConfigureAwait(false)) + await using (var session = driver.AsyncSession()) { cursor = await session.RunAsync("RETURN 1 As X"); } - var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); + var error = await Record.ExceptionAsync(() => cursor.ToListAsync()); error.Should().BeOfType(); } [RequireServerFact] public async Task ShouldNotBeAbleToAccessRecordsAfterSummary() { - using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); - var session = driver.AsyncSession(); - await using (session.ConfigureAwait(false)) - { - var cursor = await session.RunAsync("RETURN 1 As X"); - await cursor.ConsumeAsync(); + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("RETURN 1 As X"); + await cursor.ConsumeAsync(); - var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); - error.Should().BeOfType(); - } + var error = await Record.ExceptionAsync(() => cursor.ToListAsync()); + error.Should().BeOfType(); } private static async Task VerifyRunsQuery(IAsyncSession session) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/TransactionIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/TransactionIT.cs index e77547a5b..6ba295b94 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/TransactionIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Direct/TransactionIT.cs @@ -19,12 +19,14 @@ using System.Diagnostics; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Direct; -public class TransactionIT : DirectDriverTestBase +public sealed class TransactionIT : DirectDriverTestBase { public TransactionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) { @@ -35,387 +37,281 @@ public TransactionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture [RequireServerFact] public async Task ShouldRetry() { - var session = Driver.AsyncSession(); - try - { - var timer = Stopwatch.StartNew(); - - var exc = await Record.ExceptionAsync( - () => - session.WriteTransactionAsync( - tx => - throw new SessionExpiredException($"Failed at {timer.Elapsed}"))); - - timer.Stop(); - - exc.Should() - .BeOfType() - .Which.InnerException.Should() - .BeOfType() - .Which.InnerExceptions.Should() - .NotBeEmpty() - .And.AllBeOfType(); - - timer.Elapsed.Should().BeGreaterThan(TimeSpan.FromSeconds(30)); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var timer = Stopwatch.StartNew(); + + var exc = await Record.ExceptionAsync( + () => + session.ExecuteWriteAsync( + _ => + throw new SessionExpiredException($"Failed at {timer.Elapsed}"))); + + timer.Stop(); + + exc.Should() + .BeOfType() + .Which.InnerException.Should() + .BeOfType() + .Which.InnerExceptions.Should() + .NotBeEmpty() + .And.AllBeOfType(); + + timer.Elapsed.Should().BeGreaterThan(TimeSpan.FromSeconds(30)); } [RequireServerFact] public async Task ShouldCommitTransactionByDefault() { - var session = Driver.AsyncSession(); - try - { - var createResult = - await session.WriteTransactionAsync( - tx => - tx.RunAndSingleAsync("CREATE (n) RETURN count(n)", null)); - - // the read operation should see the commited write tx - var matchResult = - await session.ReadTransactionAsync( - tx => - tx.RunAndSingleAsync("MATCH (n) RETURN count(n)", null)); - - createResult.Should().BeEquivalentTo(matchResult); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var createResult = + await session.ExecuteWriteAsync( + tx => + tx.RunAndSingleAsync("CREATE (n) RETURN count(n)", null)); + + // the read operation should see the commited write tx + var matchResult = + await session.ExecuteReadAsync( + tx => + tx.RunAndSingleAsync("MATCH (n) RETURN count(n)", null)); + + createResult.Should().BeEquivalentTo(matchResult); } [RequireServerFact] public async Task ShouldNotCommitTransaction() { - var session = Driver.AsyncSession(); + var createResult = -1; + await using var session = Driver.AsyncSession(); try { - var createResult = await session.WriteTransactionAsync( + await session.ExecuteWriteAsync( async tx => { - var result = await tx.RunAndSingleAsync("CREATE (n) RETURN count(n)", null, r => r[0].As()); - await tx.RollbackAsync(); - return result; - }); + createResult = await tx.RunAndSingleAsync( + "CREATE (n) RETURN count(n)", + null, + r => r[0].As()); - // the read operation should not see the rolled back write tx - var matchResult = - await session.ReadTransactionAsync( - tx => - tx.RunAndSingleAsync("MATCH (n) RETURN count(n)", null, r => r[0].As())); - - createResult.Should().Be(matchResult + 1); + throw new InvalidOperationException("Throw in a transaction"); + }); } - finally + catch (InvalidOperationException) { - await session.CloseAsync(); + // ignore this exception! + // it was thrown to cancel the transaction. } + + // the read operation should not see the rolled back write tx + var matchResult = + await session.ExecuteReadAsync( + tx => + tx.RunAndSingleAsync("MATCH (n) RETURN count(n)", null, r => r[0].As())); + + createResult.Should().Be(matchResult + 1); } [RequireServerFact] public async Task ShouldNotCommitIfError() { - var session = Driver.AsyncSession(); - try - { - var exc = await Record.ExceptionAsync( - () => session.WriteTransactionAsync( - async tx => - { - await tx.RunAsync("CREATE (n) RETURN count(n)"); - throw new ProtocolException("Broken"); - })); - - exc.Should().NotBeNull(); - - // the read operation should not see the rolled back write tx - var matchResult = - await session.ReadTransactionAsync( - tx => - tx.RunAndSingleAsync("MATCH (n) RETURN count(n)", null, r => r[0].As())); - - matchResult.Should().Be(0); - } - finally - { - await session.CloseAsync(); - } + await using var session = Driver.AsyncSession(); + var exc = await Record.ExceptionAsync( + () => session.ExecuteWriteAsync( + async tx => + { + await tx.RunAsync("CREATE (n) RETURN count(n)"); + throw new ProtocolException("Broken"); + })); + + exc.Should().NotBeNull(); + + // the read operation should not see the rolled back write tx + var matchResult = + await session.ExecuteReadAsync( + tx => + tx.RunAndSingleAsync("MATCH (n) RETURN count(n)", null, r => r[0].As())); + + matchResult.Should().Be(0); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterRun() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - - var cursor = await txc.RunAsync("RETURN 1 As X"); - var keys = await cursor.KeysAsync(); - - keys.Should().HaveCount(1); - keys.Should().Contain("X"); - - await txc.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + + var cursor = await txc.RunAsync("RETURN 1 As X"); + var keys = await cursor.KeysAsync(); + + keys.Should().HaveCount(1); + keys.Should().Contain("X"); + + await txc.CommitAsync(); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterRunAndResultConsumption() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - var cursor = await txc.RunAsync("RETURN 1 As X"); - - var keys = await cursor.KeysAsync(); - keys.Should().BeEquivalentTo("X"); - - await cursor.ConsumeAsync(); - - keys = await cursor.KeysAsync(); - keys.Should().BeEquivalentTo("X"); - - await txc.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + var cursor = await txc.RunAsync("RETURN 1 As X"); + + var keys = await cursor.KeysAsync(); + keys.Should().BeEquivalentTo("X"); + + await cursor.ConsumeAsync(); + + keys = await cursor.KeysAsync(); + keys.Should().BeEquivalentTo("X"); + + await txc.CommitAsync(); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRun() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - - var cursor1 = await txc.RunAsync("RETURN 1 As X"); - var cursor2 = await txc.RunAsync("RETURN 1 As Y"); - - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - - await txc.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + + var cursor1 = await txc.RunAsync("RETURN 1 As X"); + var cursor2 = await txc.RunAsync("RETURN 1 As Y"); + + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + + await txc.CommitAsync(); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRunAndResultConsumption() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - - var cursor1 = await txc.RunAsync("RETURN 1 As X"); - var cursor2 = await txc.RunAsync("RETURN 1 As Y"); - - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - - await cursor1.ConsumeAsync(); - await cursor2.ConsumeAsync(); - - keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - - await txc.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + + var cursor1 = await txc.RunAsync("RETURN 1 As X"); + var cursor2 = await txc.RunAsync("RETURN 1 As Y"); + + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + + await cursor1.ConsumeAsync(); + await cursor2.ConsumeAsync(); + + keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + + await txc.CommitAsync(); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRunNoOrder() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - - var cursor1 = await txc.RunAsync("RETURN 1 As X"); - var cursor2 = await txc.RunAsync("RETURN 1 As Y"); - - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - - await txc.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + + var cursor1 = await txc.RunAsync("RETURN 1 As X"); + var cursor2 = await txc.RunAsync("RETURN 1 As Y"); + + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + + await txc.CommitAsync(); } [RequireServerFact] public async Task KeysShouldBeAvailableAfterConsecutiveRunAndResultConsumptionNoOrder() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - - var cursor1 = await txc.RunAsync("RETURN 1 As X"); - var cursor2 = await txc.RunAsync("RETURN 1 As Y"); - - var keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - var keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - - await cursor2.ConsumeAsync(); - await cursor1.ConsumeAsync(); - - keys2 = await cursor2.KeysAsync(); - keys2.Should().BeEquivalentTo("Y"); - keys1 = await cursor1.KeysAsync(); - keys1.Should().BeEquivalentTo("X"); - - await txc.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + + var cursor1 = await txc.RunAsync("RETURN 1 As X"); + var cursor2 = await txc.RunAsync("RETURN 1 As Y"); + + var keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + var keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + + await cursor2.ConsumeAsync(); + await cursor1.ConsumeAsync(); + + keys2 = await cursor2.KeysAsync(); + keys2.Should().BeEquivalentTo("Y"); + keys1 = await cursor1.KeysAsync(); + keys1.Should().BeEquivalentTo("X"); + + await txc.CommitAsync(); } [RequireServerFact] public async Task ShouldNotBeAbleToAccessRecordsAfterRollback() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - var cursor = await txc.RunAsync("RETURN 1 As X"); - await txc.RollbackAsync(); - var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); - error.Should().BeOfType(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + var cursor = await txc.RunAsync("RETURN 1 As X"); + await txc.RollbackAsync(); + var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); + error.Should().BeOfType(); } [RequireServerFact] public async Task ShouldNotBeAbleToAccessRecordsAfterCommit() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - var cursor = await txc.RunAsync("RETURN 1 As X"); - await txc.CommitAsync(); - var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); - error.Should().BeOfType(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + var cursor = await txc.RunAsync("RETURN 1 As X"); + await txc.CommitAsync(); + var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); + error.Should().BeOfType(); } [RequireServerFact] public async Task ShouldNotBeAbleToAccessRecordsAfterSummary() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - var cursor = await txc.RunAsync("RETURN 1 As X"); - await cursor.ConsumeAsync(); - - var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); - error.Should().BeOfType(); - await txc.RollbackAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + var cursor = await txc.RunAsync("RETURN 1 As X"); + await cursor.ConsumeAsync(); + + var error = await Record.ExceptionAsync(async () => await cursor.ToListAsync()); + error.Should().BeOfType(); + await txc.RollbackAsync(); } [RequireServerFact] public async Task ShouldBeAbleToRunNestedQueries() { - using (var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2))) - { - const int size = 1024; - var session = driver.AsyncSession(o => o.WithFetchSize(5)); - try - { - var txc1 = await session.BeginTransactionAsync(); - var cursor1 = await txc1.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); - - await cursor1.ForEachAsync( - async r => - await txc1.RunAsync( - "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", - new { x = r["x"].As() })); - - var count = await (await txc1.RunAsync("MATCH (n:Node) RETURN count(n)")).SingleAsync(); - count[0].As().Should().Be(size); - await txc1.RollbackAsync(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(ServerEndPoint, AuthToken, o => o.WithFetchSize(2)); + const int size = 1024; + await using var session = driver.AsyncSession(o => o.WithFetchSize(5)); + var txc1 = await session.BeginTransactionAsync(); + var cursor1 = await txc1.RunAsync("UNWIND range(1, $size) AS x RETURN x", new { size }); + + await cursor1.ForEachAsync( + r => + txc1.RunAsync( + "UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", + new { x = r["x"].As() })); + + var count = await (await txc1.RunAsync("MATCH (n:Node) RETURN count(n)")).SingleAsync(); + count[0].As().Should().Be(size); + await txc1.RollbackAsync(); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Examples.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Examples.cs index 1692f1477..3fdca7504 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Examples.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Examples.cs @@ -22,14 +22,12 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using FluentAssertions; -using Neo4j.Driver.IntegrationTests; using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.DatabaseExtensions; +using static Neo4j.Driver.IntegrationTests.Extensions.DatabaseExtensions; -// ReSharper disable once CheckNamespace -namespace Neo4j.Driver.Examples; +namespace Neo4j.Driver.IntegrationTests; /// The driver examples since 1.2 driver public class Examples @@ -45,10 +43,8 @@ public AutocommitTransactionExample(ITestOutputHelper output, StandAloneIntegrat // tag::autocommit-transaction[] public void AddPerson(string name) { - using (var session = Driver.Session()) - { - session.Run("CREATE (a:Person {name: $name})", new { name }); - } + using var session = Driver.Session(); + session.Run("CREATE (a:Person {name: $name})", new { name }); } // end::autocommit-transaction[] @@ -80,12 +76,10 @@ public IDriver CreateDriverWithBasicAuth(string uri, string user, string passwor public void TestBasicAuthExample() { // Given - using (var driver = CreateDriverWithBasicAuth(Uri, User, Password)) - using (var session = driver.Session()) - { - // When & Then - session.Run("RETURN 1").Single()[0].As().Should().Be(1); - } + using var driver = CreateDriverWithBasicAuth(Uri, User, Password); + using var session = driver.Session(); + // When & Then + session.Run("RETURN 1").Single()[0].As().Should().Be(1); } } @@ -142,12 +136,10 @@ public IDriver CreateDriverWithCustomizedConnectionTimeout(string uri, string us public void TestConfigConnectionTimeoutExample() { // Given - using (var driver = CreateDriverWithCustomizedConnectionTimeout(Uri, User, Password)) - using (var session = driver.Session()) - { - // When & Then - session.Run("RETURN 1").Single()[0].As().Should().Be(1); - } + using var driver = CreateDriverWithCustomizedConnectionTimeout(Uri, User, Password); + using var session = driver.Session(); + // When & Then + session.Run("RETURN 1").Single()[0].As().Should().Be(1); } } @@ -172,12 +164,10 @@ public IDriver CreateDriverWithCustomizedMaxRetryTime(string uri, string user, s public void TestConfigMaxRetryTimeExample() { // Given - using (var driver = CreateDriverWithCustomizedMaxRetryTime(Uri, User, Password)) - using (var session = driver.Session()) - { - // When & Then - session.Run("RETURN 1").Single()[0].As().Should().Be(1); - } + using var driver = CreateDriverWithCustomizedMaxRetryTime(Uri, User, Password); + using var session = driver.Session(); + // When & Then + session.Run("RETURN 1").Single()[0].As().Should().Be(1); } } @@ -202,12 +192,10 @@ public IDriver CreateDriverWithCustomizedTrustStrategy(string uri, string user, public void TestConfigTrustExample() { // Given - using (var driver = CreateDriverWithCustomizedTrustStrategy(Uri, User, Password)) - using (var session = driver.Session()) - { - // When & Then - session.Run("RETURN 1").Single()[0].As().Should().Be(1); - } + using var driver = CreateDriverWithCustomizedTrustStrategy(Uri, User, Password); + using var session = driver.Session(); + // When & Then + session.Run("RETURN 1").Single()[0].As().Should().Be(1); } } @@ -232,12 +220,10 @@ public IDriver CreateDriverWithCustomizedSecurityStrategy(string uri, string use public void TestConfigUnencryptedExample() { // Given - using (var driver = CreateDriverWithCustomizedSecurityStrategy(Uri, User, Password)) - using (var session = driver.Session()) - { - // When & Then - session.Run("RETURN 1").Single()[0].As().Should().Be(1); - } + using var driver = CreateDriverWithCustomizedSecurityStrategy(Uri, User, Password); + using var session = driver.Session(); + // When & Then + session.Run("RETURN 1").Single()[0].As().Should().Be(1); } } @@ -261,26 +247,23 @@ private IDriver CreateDriverWithCustomResolver( public void AddPerson(string name) { - using (var driver = CreateDriverWithCustomResolver( - "neo4j://x.example.com", - AuthTokens.Basic(Username, Password), - ServerAddress.From("a.example.com", 7687), - ServerAddress.From("b.example.com", 7877), - ServerAddress.From("c.example.com", 9092))) - { - using (var session = driver.Session()) - { - session.Run("CREATE (a:Person {name: $name})", new { name }); - } - } + using var driver = CreateDriverWithCustomResolver( + "neo4j://x.example.com", + AuthTokens.Basic(Username, Password), + ServerAddress.From("a.example.com", 7687), + ServerAddress.From("b.example.com", 7877), + ServerAddress.From("c.example.com", 9092)); + + using var session = driver.Session(); + session.Run("CREATE (a:Person {name: $name})", new { name }); } // end::config-custom-resolver[] [RequireBoltStubServerFact] public void TestCustomResolverExample() { - using var server1 = BoltStubServer.Start("V4/get_routing_table_only", 9001); - using var server2 = BoltStubServer.Start("V4/return_1", 9002); + using var _ = BoltStubServer.Start("V4/get_routing_table_only", 9001); + using var __ = BoltStubServer.Start("V4/return_1", 9002); using var driver = CreateDriverWithCustomResolver( "neo4j://x.example.com", AuthTokens.None, @@ -362,11 +345,9 @@ public IDriver CreateDriverWithKerberosAuth(string uri, string ticket) public void TestKerberosAuthExample() { // Given - using (var driver = CreateDriverWithKerberosAuth(Uri, "kerberos ticket")) - { - // When & Then - driver.Should().BeOfType(); - } + using var driver = CreateDriverWithKerberosAuth(Uri, "kerberos ticket"); + // When & Then + driver.Should().BeOfType(); } } @@ -446,19 +427,15 @@ public DriverLifecycleExampleTest(ITestOutputHelper output, StandAloneIntegratio public void TestDriverLifecycleExample() { // Given - var driver = new DriverLifecycleExample(Uri, User, Password).Driver; - using (var session = driver.Session()) - { - // When & Then - session.Run("RETURN 1").Single()[0].As().Should().Be(1); - } + using var driver = new DriverLifecycleExample(Uri, User, Password).Driver; + using var session = driver.Session(); + // When & Then + session.Run("RETURN 1").Single()[0].As().Should().Be(1); } // tag::driver-lifecycle[] public class DriverLifecycleExample : IDisposable { - private bool _disposed; - public DriverLifecycleExample(string uri, string user, string password) { Driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password)); @@ -468,28 +445,7 @@ public DriverLifecycleExample(string uri, string user, string password) public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~DriverLifecycleExample() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - Driver?.Dispose(); - } - - _disposed = true; + Driver?.Dispose(); } } } @@ -514,24 +470,12 @@ public void TestHelloWorldExample() public class HelloWorldExample : IDisposable { private readonly IDriver _driver; - private bool _disposed; public HelloWorldExample(string uri, string user, string password) { _driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password)); } - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~HelloWorldExample() - { - Dispose(false); - } - public void PrintGreeting(string message) { using var session = _driver.Session(); @@ -550,19 +494,9 @@ public void PrintGreeting(string message) Console.WriteLine(greeting); } - protected virtual void Dispose(bool disposing) + public void Dispose() { - if (_disposed) - { - return; - } - - if (disposing) - { - _driver?.Dispose(); - } - - _disposed = true; + _driver?.Dispose(); } public static void Main() @@ -1101,13 +1035,13 @@ public void TestPassBookmarksExample() } } -[Collection(SAIntegrationCollection.CollectionName)] +[Collection(SaIntegrationCollection.CollectionName)] public abstract class BaseExample : IDisposable { private bool _disposed; - protected string Password = Neo4jDefaultInstallation.Password; - protected string Uri = Neo4jDefaultInstallation.BoltUri; - protected string User = Neo4jDefaultInstallation.User; + protected string Password = DefaultInstallation.Password; + protected string Uri = DefaultInstallation.BoltUri; + protected string User = DefaultInstallation.User; protected BaseExample(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesAsync.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesAsync.cs index 6384ddc5e..13c60f6ad 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesAsync.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesAsync.cs @@ -21,13 +21,11 @@ using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Neo4j.Driver.IntegrationTests; using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; -// ReSharper disable once CheckNamespace -namespace Neo4j.Driver.ExamplesAsync; +namespace Neo4j.Driver.IntegrationTests; public class ExamplesAsync { @@ -719,7 +717,9 @@ protected virtual void Dispose(bool disposing) _disposed = true; } +#pragma warning disable CS8892 public static async Task Main(string[] args) +#pragma warning restore CS8892 { // Aura queries use an encrypted connection using the "neo4j+s" protocol var boltUrl = "%%BOLT_URL_PLACEHOLDER%%"; @@ -1007,13 +1007,13 @@ public async void TestTransactionFunctionExample() } } -[Collection(SAIntegrationCollection.CollectionName)] +[Collection(SaIntegrationCollection.CollectionName)] public abstract class BaseAsyncExample : IDisposable { private bool _disposed; - protected string Password = Neo4jDefaultInstallation.Password; - protected string Uri = Neo4jDefaultInstallation.BoltUri; - protected string User = Neo4jDefaultInstallation.User; + protected string Password = DefaultInstallation.Password; + protected string Uri = DefaultInstallation.BoltUri; + protected string User = DefaultInstallation.User; protected BaseAsyncExample(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesRx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesRx.cs index 12fe8a4c3..bf8a71f8d 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesRx.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/ExamplesRx.cs @@ -19,15 +19,14 @@ using System.Reactive.Linq; using System.Threading.Tasks; using Microsoft.Reactive.Testing; -using Neo4j.Driver.IntegrationTests; using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Reactive; using Xunit; using Xunit.Abstractions; using static Microsoft.Reactive.Testing.ReactiveTest; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; -namespace Neo4j.Driver.ExamplesAsync; +namespace Neo4j.Driver.IntegrationTests; public class ExamplesRx { @@ -177,12 +176,12 @@ public async Task TestResultConsumeExample() } } -[Collection(SAIntegrationCollection.CollectionName)] +[Collection(SaIntegrationCollection.CollectionName)] public abstract class BaseRxExample : AbstractRxTest, IDisposable { private bool _disposed; - protected string Uri = Neo4jDefaultInstallation.BoltUri; - protected string User = Neo4jDefaultInstallation.User; + protected string Uri = DefaultInstallation.BoltUri; + protected string User = DefaultInstallation.User; protected BaseRxExample(StandAloneIntegrationTestFixture fixture) { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/CollectionExtensions.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/CollectionExtensions.cs index 00bd41dcb..edb99c8b0 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/CollectionExtensions.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/CollectionExtensions.cs @@ -19,15 +19,16 @@ using System.Collections.Generic; using System.Linq; -namespace Neo4j.Driver.IntegrationTests; +namespace Neo4j.Driver.IntegrationTests.Extensions; public static class CollectionExtensions { public static T RandomElement(this IEnumerable list) { var random = new Random(Guid.NewGuid().GetHashCode()); - var index = random.Next(0, list.Count()); - return list.ElementAt(index); + var eagerList = list.ToList(); + var index = random.Next(0, eagerList.Count()); + return eagerList.ElementAt(index); } public static IEnumerable> Batch(this IEnumerable collection, int batchSize) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/DatabaseExtensions.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/DatabaseExtensions.cs index b8f760bfe..fb9eef76c 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/DatabaseExtensions.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/DatabaseExtensions.cs @@ -18,38 +18,24 @@ using System.Threading.Tasks; using static Neo4j.Driver.SessionConfigBuilder; -namespace Neo4j.Driver.IntegrationTests; +namespace Neo4j.Driver.IntegrationTests.Extensions; -public class DatabaseExtensions +public static class DatabaseExtensions { public static async Task CreateDatabase(IDriver driver, string name, bool async = false) { - var session = driver.AsyncSession(ForDatabase("system")); + await using var session = driver.AsyncSession(ForDatabase("system")); - try - { - var wait = async ? " WAIT" : string.Empty; - var cursor = await session.RunAsync($"CREATE DATABASE {name}{wait}"); - await cursor.ConsumeAsync(); - } - finally - { - await session.CloseAsync(); - } + var wait = async ? " WAIT" : string.Empty; + var cursor = await session.RunAsync($"CREATE DATABASE {name}{wait}"); + await cursor.ConsumeAsync(); } public static async Task DropDatabase(IDriver driver, string name, bool async = false) { - var session = driver.AsyncSession(ForDatabase("system")); - try - { - var wait = async ? " WAIT" : string.Empty; - var cursor = await session.RunAsync($"DROP DATABASE {name}{wait}"); - await cursor.ConsumeAsync(); - } - finally - { - await session.CloseAsync(); - } + await using var session = driver.AsyncSession(ForDatabase("system")); + var wait = async ? " WAIT" : string.Empty; + var cursor = await session.RunAsync($"DROP DATABASE {name}{wait}"); + await cursor.ConsumeAsync(); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/SessionExtensions.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/SessionExtensions.cs index d8c4ef064..adea7467b 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/SessionExtensions.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Extensions/SessionExtensions.cs @@ -18,7 +18,7 @@ using System; using System.Threading.Tasks; -namespace Neo4j.Driver.IntegrationTests; +namespace Neo4j.Driver.IntegrationTests.Extensions; public static class SessionExtensions { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltStubServer.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltStubServer.cs index 63c041a01..3f6c50cfa 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltStubServer.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltStubServer.cs @@ -35,7 +35,7 @@ internal class BoltStubServer : IDisposable static BoltStubServer() { var assemblyUri = new Uri(typeof(BoltStubServer).GetTypeInfo().Assembly.Location); - var assemblyDirectory = new FileInfo(assemblyUri.AbsolutePath).Directory.FullName; + var assemblyDirectory = new FileInfo(assemblyUri.AbsolutePath).Directory!.FullName; ScriptSourcePath = Path.Combine(assemblyDirectory, "Resources"); } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltkitHelper.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltkitHelper.cs index 90a5721bc..fd5427b9b 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltkitHelper.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/BoltkitHelper.cs @@ -34,7 +34,7 @@ public static class BoltkitHelper private static string _boltkitArgs; private static BoltkitStatus _boltkitAvailable = BoltkitStatus.Unknown; private static Tuple _isClusterSupported; - private static readonly object _syncLock = new(); + private static readonly object SyncLock = new(); public static string BoltkitArgs { @@ -74,7 +74,7 @@ private static bool IsBoltkitAvailable() { if (_boltkitAvailable == BoltkitStatus.Unknown) { - lock (_syncLock) + lock (SyncLock) { // only update it once if (_boltkitAvailable == BoltkitStatus.Unknown) @@ -122,19 +122,14 @@ public static Tuple IsClusterSupported() return _isClusterSupported; } - public static bool IPV6Available() + public static bool Ipv6Available() { return NetworkInterface.GetAllNetworkInterfaces().Any(nic => nic.Supports(NetworkInterfaceComponent.IPv6)); } - public static bool IPV6Enabled() + public static bool Ipv6Enabled() { - if (bool.TryParse(GetEnvironmentVariable("NEOCTRL_DISABLE_IPV6"), out var disableIPv6) && disableIPv6) - { - return false; - } - - return true; + return !bool.TryParse(GetEnvironmentVariable("NEOCTRL_DISABLE_IPV6"), out var disableIPv6) || !disableIPv6; } public static string ServerVersion() @@ -172,7 +167,7 @@ private static string DiscoverTargetDirectory() var localFile = new FileInfo(localPath); var sourcePath = new DirectoryInfo( Path.Combine( - localFile.DirectoryName, + localFile.DirectoryName!, string.Format("..{0}..{0}..{0}..{0}..{0}Target", Path.DirectorySeparatorChar))); return sourcePath.FullName; diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CausalClusterIntegrationTestFixture.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CausalClusterIntegrationTestFixture.cs new file mode 100644 index 000000000..6deb40e3d --- /dev/null +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CausalClusterIntegrationTestFixture.cs @@ -0,0 +1,66 @@ +// Copyright (c) "Neo4j" +// Neo4j Sweden AB [http://neo4j.com] +// +// This file is part of Neo4j. +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Neo4j.Driver.IntegrationTests.Internals; + +public sealed class CausalClusterIntegrationTestFixture : IDisposable +{ + private bool _disposed; + + public CausalClusterIntegrationTestFixture() + { + if (ExistingCluster.IsClusterProvided()) + { + Cluster = new ExistingCluster(); + } + else + { + var isClusterSupported = BoltkitHelper.IsClusterSupported(); + if (!isClusterSupported.Item1) + { + return; + } + + try + { + Cluster = new CausalCluster(); + } + catch (Exception) + { + Dispose(); + throw; + } + } + } + + public ICausalCluster Cluster { get; } + + public void Dispose() + { + switch (_disposed) + { + case true: return; + case false: + Cluster?.Dispose(); + break; + } + + _disposed = true; + } +} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CcIntegrationCollection.cs similarity index 52% rename from Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommand.cs rename to Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CcIntegrationCollection.cs index 78b0c1cdd..9596876ac 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommand.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CcIntegrationCollection.cs @@ -1,4 +1,4 @@ -// Copyright (c) "Neo4j" +// Copyright (c) "Neo4j" // Neo4j Sweden AB [http://neo4j.com] // // This file is part of Neo4j. @@ -15,24 +15,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -using FluentAssertions; using Xunit; -namespace Neo4j.Driver.IntegrationTests.Stress; +namespace Neo4j.Driver.IntegrationTests.Internals; -public class BlockingWrongCommand : BlockingCommand +[CollectionDefinition(CollectionName)] +public class CcIntegrationCollection : ICollectionFixture { - public BlockingWrongCommand(IDriver driver) - : base(driver, false) - { - } - - public override void Execute(StressTestContext context) - { - using (var session = NewSession(AccessMode.Read, context)) - { - var exc = Record.Exception(() => session.Run("RETURN").Consume()); - exc.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); - } - } + public const string CollectionName = "CausalClusterIntegration"; + // This class has no code, and is never created. Its purpose is simply + // to be the place to apply [CollectionDefinition] and all the + // ICollectionFixture<> interfaces. } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CertificateUtils.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CertificateUtils.cs index c3efb5b74..f6c2ff1f0 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CertificateUtils.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/CertificateUtils.cs @@ -51,10 +51,10 @@ public static Pkcs12Store CreateCert( var keyPair = keyPairGen.GenerateKeyPair(); var certGenerator = new X509V3CertificateGenerator(); - certGenerator.SetSubjectDN(new X509Name("CN=" + commonName)); + certGenerator.SetSubjectDN(new X509Name($"CN={commonName}")); if (signBy == null) { - certGenerator.SetIssuerDN(new X509Name("CN=" + commonName)); + certGenerator.SetIssuerDN(new X509Name($"CN={commonName}")); } else { @@ -66,16 +66,17 @@ public static Pkcs12Store CreateCert( certGenerator.SetNotAfter(notAfter); certGenerator.SetPublicKey(keyPair.Public); - if ((dnsAltNames?.Any() ?? false) || (ipAddressAltNames?.Any() ?? false)) + var altNames = dnsAltNames?.ToArray() ?? Array.Empty(); + var addressAltNames = ipAddressAltNames?.ToArray() ?? Array.Empty(); + if (altNames.Any() || addressAltNames.Any()) { var alternativeNames = new List(); + alternativeNames.AddRange( - dnsAltNames?.Select(name => new GeneralName(GeneralName.DnsName, name)) ?? - Enumerable.Empty()); + altNames.Select(name => new GeneralName(GeneralName.DnsName, name))); alternativeNames.AddRange( - ipAddressAltNames?.Select(ip => new GeneralName(GeneralName.IPAddress, ip)) ?? - Enumerable.Empty()); + addressAltNames.Select(ip => new GeneralName(GeneralName.IPAddress, ip))); certGenerator.AddExtension( X509Extensions.SubjectAlternativeName, @@ -93,7 +94,7 @@ public static Pkcs12Store CreateCert( return ToPkcs12(certificate, keyPair.Private); } - public static Pkcs12Store ToPkcs12(X509Certificate certificate, AsymmetricKeyParameter privateKey) + private static Pkcs12Store ToPkcs12(X509Certificate certificate, AsymmetricKeyParameter privateKey) { var pkcs12Store = new Pkcs12Store(); var certificateEntry = new X509CertificateEntry(certificate); diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/CausalCluster.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/CausalCluster.cs index d2cf175ac..882d8792e 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/CausalCluster.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/CausalCluster.cs @@ -23,7 +23,7 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -public class CausalCluster : ICausalCluster +public sealed class CausalCluster : ICausalCluster { private static readonly TimeSpan ClusterOnlineTimeout = TimeSpan.FromMinutes(2); @@ -102,17 +102,15 @@ private void Kill() private void WaitForMembersOnline() { - void VerifyCanExecute(AccessMode mode, List exceptions) + void VerifyCanExecute(AccessMode mode) { - using (var driver = GraphDatabase.Driver(AnyCore().BoltRoutingUri, AuthToken)) - using (var session = driver.Session(o => o.WithDefaultAccessMode(mode))) - { - session.Run("RETURN 1").Consume(); - } + using var driver = GraphDatabase.Driver(AnyCore().BoltRoutingUri, AuthToken); + using var session = driver.Session(o => o.WithDefaultAccessMode(mode)); + session.Run("RETURN 1").Consume(); } var expectedOnlineMembers = Members.Select(x => x.BoltUri.Authority).ToHashSet(); - var onlineMembers = Enumerable.Empty(); + var onlineMembers = Array.Empty(); var errors = new List(); var timer = Stopwatch.StartNew(); @@ -124,25 +122,24 @@ void VerifyCanExecute(AccessMode mode, List exceptions) { try { - using (var driver = GraphDatabase.Driver(AnyCore().BoltRoutingUri, AuthToken)) - using (var session = driver.Session(o => o.WithDefaultAccessMode(AccessMode.Read))) + using var driver = GraphDatabase.Driver(AnyCore().BoltRoutingUri, AuthToken); + using var session = driver.Session(o => o.WithDefaultAccessMode(AccessMode.Read)); + + var records = session.Run("CALL dbms.cluster.overview()").ToList(); + + var cluster = session.Run("CALL dbms.cluster.overview()").ToList(); + if (!DbAvailable(cluster)) { - var addresses = new List(); - var records = session.Run("CALL dbms.cluster.overview()").ToList(); - foreach (var record in records) - { - addresses.Add( - record["addresses"].As>().First().As().Replace("bolt://", "")); - } - - var cluster = session.Run("CALL dbms.cluster.overview()").ToList(); - if (!Neo4jDbAvailable(cluster)) - { - continue; - } - - onlineMembers = addresses; + continue; } + + onlineMembers = records.Select( + record => record["addresses"] + .As>() + .First() + .As() + .Replace("bolt://", "")) + .ToArray(); } catch (Exception exc) { @@ -159,10 +156,10 @@ void VerifyCanExecute(AccessMode mode, List exceptions) try { // Verify that we can connect to a FOLLOWER - VerifyCanExecute(AccessMode.Read, errors); + VerifyCanExecute(AccessMode.Read); // Verify that we can connect to a LEADER - VerifyCanExecute(AccessMode.Write, errors); + VerifyCanExecute(AccessMode.Write); return; } @@ -175,7 +172,7 @@ void VerifyCanExecute(AccessMode mode, List exceptions) throw new TimeoutException($"Timed out waiting for the cluster to become available. Seen errors: {errors}"); } - private static bool Neo4jDbAvailable(List cluster) + private static bool DbAvailable(List cluster) { return cluster.Any( x => x.Values.TryGetValue("databases", out var y) && @@ -183,7 +180,7 @@ private static bool Neo4jDbAvailable(List cluster) .TryGetValue("neo4j", out _)); } - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (_disposed) { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExistingCluster.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExistingCluster.cs index b21947021..dc172d4e0 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExistingCluster.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExistingCluster.cs @@ -33,7 +33,7 @@ public void Dispose() public Uri BoltRoutingUri => new(GetEnvOrThrow(ClusterUri)); public IAuthToken AuthToken => AuthTokens.Basic( - GetEnvOrDefault(ClusterUser, Neo4jDefaultInstallation.User), + GetEnvOrDefault(ClusterUser, DefaultInstallation.User), GetEnvOrThrow(ClusterPassword)); public void Configure(ConfigBuilder builder) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExternalBoltkitClusterInstaller.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExternalBoltkitClusterInstaller.cs index 32f251855..c97597db9 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExternalBoltkitClusterInstaller.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/ExternalBoltkitClusterInstaller.cs @@ -21,14 +21,14 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -public class ExternalBoltkitClusterInstaller : IInstaller +public sealed class ExternalBoltkitClusterInstaller : IInstaller { private const int Cores = 3; - //TODO Add readreplicas into the cluster too + //TODO: Add read replicas into the cluster too //private const int ReadReplicas = 2; private const string Password = "cluster"; - public static readonly string ClusterDir = Path.Combine(BoltkitHelper.TargetDir, "cluster"); + private static readonly string ClusterDir = Path.Combine(BoltkitHelper.TargetDir, "cluster"); private readonly IShellCommandRunner _commandRunner; public ExternalBoltkitClusterInstaller() @@ -41,7 +41,7 @@ public void Install() if (Directory.Exists(ClusterDir)) { _commandRunner.Debug($"Found and using cluster installed at `{ClusterDir}`."); - // no need to redownload and change the password if already downloaded locally + // no need to re-download and change the password if already downloaded locally return; } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/SingleInstance.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/SingleInstance.cs index b88d7ce3a..2cc02272b 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/SingleInstance.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/Cluster/SingleInstance.cs @@ -29,15 +29,10 @@ public SingleInstance(string httpUri, string boltUri, string homePath, string pa { HttpUri = new Uri(httpUri); BoltUri = new Uri(boltUri); - BoltRoutingUri = new Uri(BoltRoutingScheme + $"{BoltUri.Host}:{BoltUri.Port}"); - if (homePath == null) - { - HomePath = "UNKNOWN"; - } - else - { - HomePath = new DirectoryInfo(homePath).FullName; - } + BoltRoutingUri = new Uri($"{BoltRoutingScheme}{BoltUri.Host}:{BoltUri.Port}"); + HomePath = homePath == null + ? "UNKNOWN" + : new DirectoryInfo(homePath).FullName; AuthToken = AuthTokens.Basic(Username, password); } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IInstaller.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IInstaller.cs index 1773e701a..3f6224c5b 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IInstaller.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IInstaller.cs @@ -15,14 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System.Collections.Generic; - namespace Neo4j.Driver.IntegrationTests.Internals; public interface IInstaller { - void Install(); - ISet Start(); - void Stop(); - void Kill(); } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IShellCommandRunner.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IShellCommandRunner.cs index e71dff02a..bad4e77e2 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IShellCommandRunner.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IShellCommandRunner.cs @@ -25,27 +25,22 @@ public interface IShellCommandRunner string[] RunCommand(string command, params string[] arguments); void BeginRunCommand(string command, params string[] arguments); - string[] EndRunCommand(); + void EndRunCommand(); } public abstract class ShellCommandRunner : IShellCommandRunner { public abstract string[] RunCommand(string command, params string[] arguments); public abstract void BeginRunCommand(string command, params string[] arguments); - public abstract string[] EndRunCommand(); + public abstract void EndRunCommand(); public virtual void Debug(string message) { System.Diagnostics.Debug.WriteLine(message); } - - protected static string ShellCommandArgument(string command, string[] arguments) - { - return $"{command} {string.Join(" ", arguments)}"; - } } -public class ShellCommandRunnerFactory +public sealed class ShellCommandRunnerFactory { public static IShellCommandRunner Create() { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestAttribute.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestAttribute.cs index d03e856b6..36f56beef 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestAttribute.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestAttribute.cs @@ -17,13 +17,12 @@ using System; using System.Text; -using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal.Util; using Xunit; -namespace Neo4j.Driver.IntegrationTests; +namespace Neo4j.Driver.IntegrationTests.Internals; -public class RequireBoltStubServerFactAttribute : FactAttribute +public sealed class RequireBoltStubServerFactAttribute : FactAttribute { //Default server version required to run stub tests is anything less than 4.3. After this version testkit takes over the stub tests. public RequireBoltStubServerFactAttribute( @@ -51,7 +50,7 @@ private void CheckStubServer(StringBuilder skipText) } } -public class RequireBoltStubServerTheoryAttribute : TheoryAttribute +public sealed class RequireBoltStubServerTheoryAttribute : TheoryAttribute { //Default server version required to run stub tests is anything less than 4.3. After this version testkit takes over the stub tests. public RequireBoltStubServerTheoryAttribute( @@ -201,6 +200,8 @@ public static bool RequiredServerAvailableBetween( /// Use `RequireServerFact` tag for the tests that require a single instance public class RequireServerFactAttribute : FactAttribute { + private readonly VersionComparison _versionComparison; + public RequireServerFactAttribute( string versionText = null, VersionComparison versionCompare = VersionComparison.EqualTo) @@ -220,15 +221,15 @@ public RequireServerFactAttribute( } } - /// between inclusive, exclusive respectively - /// - /// public RequireServerFactAttribute( string minVersionText, string maxVersionText, VersionComparison versionComparison) { - Assert.Equal(versionComparison, VersionComparison.Between); + if (versionComparison != VersionComparison.Between) + throw new ArgumentException(nameof(versionComparison)); + + _versionComparison = versionComparison; var skipText = new StringBuilder(); if (!BoltkitHelper.ServerAvailable()) @@ -245,7 +246,7 @@ public RequireServerFactAttribute( } } -public class RequireEnterpriseEdition : RequireServerFactAttribute +public sealed class RequireEnterpriseEdition : RequireServerFactAttribute { public RequireEnterpriseEdition( string versionText = null, @@ -276,7 +277,7 @@ public RequireEnterpriseEdition( } } -public class RequireServerWithIPv6FactAttribute : RequireServerFactAttribute +public sealed class RequireServerWithIPv6FactAttribute : RequireServerFactAttribute { public RequireServerWithIPv6FactAttribute( string versionText = null, @@ -285,11 +286,11 @@ public RequireServerWithIPv6FactAttribute( { if (string.IsNullOrEmpty(Skip)) { - if (!BoltkitHelper.IPV6Available()) + if (!BoltkitHelper.Ipv6Available()) { Skip = "IPv6 is not available"; } - else if (!BoltkitHelper.IPV6Enabled()) + else if (!BoltkitHelper.Ipv6Enabled()) { Skip = "IPv6 is disabled"; } @@ -298,7 +299,7 @@ public RequireServerWithIPv6FactAttribute( } /// Use `RequireServerTheory` tag for the tests that require a single instance -public class RequireServerTheoryAttribute : TheoryAttribute +public sealed class RequireServerTheoryAttribute : TheoryAttribute { public RequireServerTheoryAttribute( string versionText = null, @@ -321,7 +322,7 @@ public RequireServerTheoryAttribute( } /// Use `RequireClusterFact` tag for the tests that require a cluster -public class RequireClusterFactAttribute : FactAttribute +public sealed class RequireClusterFactAttribute : FactAttribute { public RequireClusterFactAttribute( string versionText = null, @@ -343,20 +344,7 @@ public RequireClusterFactAttribute( } } -/// Use `RequireClusterTheory` tag for the tests that require a cluster -public class RequireClusterTheoryAttribute : TheoryAttribute -{ - public RequireClusterTheoryAttribute() - { - var isClusterSupported = BoltkitHelper.IsClusterSupported(); - if (!isClusterSupported.Item1) - { - Skip = isClusterSupported.Item2; - } - } -} - -public class ShouldNotRunInTestKitFact : FactAttribute +public sealed class ShouldNotRunInTestKitFact : FactAttribute { public ShouldNotRunInTestKitFact() { @@ -368,9 +356,9 @@ public ShouldNotRunInTestKitFact() } } -public class ShouldNotRunInTestKit_RequireServerFactAttribute : RequireServerFactAttribute +public sealed class ShouldNotRunInTestKitRequireServerFactAttribute : RequireServerFactAttribute { - public ShouldNotRunInTestKit_RequireServerFactAttribute() + public ShouldNotRunInTestKitRequireServerFactAttribute() { var envVariable = Environment.GetEnvironmentVariable("TEST_NEO4J_USING_TESTKIT"); if (!string.IsNullOrEmpty(envVariable) && envVariable.Equals("true", StringComparison.OrdinalIgnoreCase)) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestFixture.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestFixture.cs index 570eaab0e..6bf4ec19f 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestFixture.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/IntegrationTestFixture.cs @@ -16,15 +16,11 @@ // limitations under the License. using System; -using Neo4j.Driver.IntegrationTests.Internals; -using Xunit; -namespace Neo4j.Driver.IntegrationTests; +namespace Neo4j.Driver.IntegrationTests.Internals; -public class StandAloneIntegrationTestFixture : IDisposable +public sealed class StandAloneIntegrationTestFixture : IDisposable { - private bool _disposed; - public StandAloneIntegrationTestFixture() { StandAloneSharedInstance = CreateInstance(); @@ -34,28 +30,7 @@ public StandAloneIntegrationTestFixture() public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~StandAloneIntegrationTestFixture() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - StandAloneSharedInstance?.Dispose(); - } - - _disposed = true; + StandAloneSharedInstance?.Dispose(); } private IStandAlone CreateInstance() @@ -81,81 +56,3 @@ private IStandAlone CreateInstance() } } } - -public class CausalClusterIntegrationTestFixture : IDisposable -{ - private bool _disposed; - - public CausalClusterIntegrationTestFixture() - { - if (ExistingCluster.IsClusterProvided()) - { - Cluster = new ExistingCluster(); - } - else - { - var isClusterSupported = BoltkitHelper.IsClusterSupported(); - if (!isClusterSupported.Item1) - { - return; - } - - try - { - Cluster = new CausalCluster(); - } - catch (Exception) - { - Dispose(); - throw; - } - } - } - - public ICausalCluster Cluster { get; } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~CausalClusterIntegrationTestFixture() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - //Dispose managed state (managed objects). - Cluster?.Dispose(); - } - - _disposed = true; - } -} - -[CollectionDefinition(CollectionName)] -public class SAIntegrationCollection : ICollectionFixture -{ - public const string CollectionName = "StandAloneIntegration"; - // This class has no code, and is never created. Its purpose is simply - // to be the place to apply [CollectionDefinition] and all the - // ICollectionFixture<> interfaces. -} - -[CollectionDefinition(CollectionName)] -public class CCIntegrationCollection : ICollectionFixture -{ - public const string CollectionName = "CausalClusterIntegration"; - // This class has no code, and is never created. Its purpose is simply - // to be the place to apply [CollectionDefinition] and all the - // ICollectionFixture<> interfaces. -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ProcessBasedCommandRunner.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ProcessBasedCommandRunner.cs index 09b305e8a..6db88b25e 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ProcessBasedCommandRunner.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ProcessBasedCommandRunner.cs @@ -23,39 +23,17 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -public class ProcessBasedCommandRunner : ShellCommandRunner, IDisposable +public sealed class ProcessBasedCommandRunner : ShellCommandRunner, IDisposable { private const int DefaultTimeOut = 4 * 60 * 1000; // 4 minutes - private bool _disposed; private Process _process; private StringBuilder _stdErr; private List _stdOut; public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~ProcessBasedCommandRunner() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - _process?.Dispose(); - } - - _disposed = true; + { + _process?.Dispose(); } private static Process CreateProcess( @@ -77,7 +55,7 @@ private static Process CreateProcess( } }; - result.OutputDataReceived += (s, e) => + result.OutputDataReceived += (_, e) => { if (e.Data != null) { @@ -85,7 +63,7 @@ private static Process CreateProcess( } }; - result.ErrorDataReceived += (s, e) => + result.ErrorDataReceived += (_, e) => { if (e.Data != null) { @@ -156,7 +134,7 @@ public override void BeginRunCommand(string command, params string[] arguments) } } - public override string[] EndRunCommand() + public override void EndRunCommand() { try { @@ -188,8 +166,6 @@ public override string[] EndRunCommand() $"{Environment.NewLine}stderr:{Environment.NewLine}{_stdErr}" + $"{Environment.NewLine}output:{Environment.NewLine}{_stdOut.ToContentString($"{Environment.NewLine}")}"); } - - return _stdOut.ToArray(); } finally { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/SaIntegrationCollection.cs similarity index 50% rename from Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommand.cs rename to Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/SaIntegrationCollection.cs index bd7ef47d2..373353f65 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommand.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/SaIntegrationCollection.cs @@ -1,4 +1,4 @@ -// Copyright (c) "Neo4j" +// Copyright (c) "Neo4j" // Neo4j Sweden AB [http://neo4j.com] // // This file is part of Neo4j. @@ -15,26 +15,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -using FluentAssertions; using Xunit; -namespace Neo4j.Driver.IntegrationTests.Stress; +namespace Neo4j.Driver.IntegrationTests.Internals; -public class BlockingFailingCommand : BlockingCommand +[CollectionDefinition(CollectionName)] +public class SaIntegrationCollection : ICollectionFixture { - public BlockingFailingCommand(IDriver driver) - : base(driver, false) - { - } - - public override void Execute(StressTestContext context) - { - using (var session = NewSession(AccessMode.Read, context)) - { - var result = session.Run("UNWIND [10, 5, 0] AS x RETURN 10 / x"); - var exc = Record.Exception(() => result.Consume()); - - exc.Should().BeOfType().Which.Message.Should().Contain("/ by zero"); - } - } + public const string CollectionName = "StandAloneIntegration"; + // This class has no code, and is never created. Its purpose is simply + // to be the place to apply [CollectionDefinition] and all the + // ICollectionFixture<> interfaces. } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ShellCommandRunnerTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ShellCommandRunnerTests.cs index 6fb0db2fa..44ab2e943 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ShellCommandRunnerTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/ShellCommandRunnerTests.cs @@ -17,7 +17,7 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -public class ShellCommandRunnerTests +public abstract class ShellCommandRunnerTests { public class RunCommandMethod { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/Neo4jDefaultInstallation.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/DefaultInstallation.cs similarity index 72% rename from Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/Neo4jDefaultInstallation.cs rename to Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/DefaultInstallation.cs index 59073dc14..1fab4fecf 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/Neo4jDefaultInstallation.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/DefaultInstallation.cs @@ -21,17 +21,17 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -public class Neo4jDefaultInstallation +public static class DefaultInstallation { - public static string User = "neo4j"; - public static string Password = "neo4j"; - public static string HttpUri = "http://127.0.0.1:7474"; + public static readonly string User = "neo4j"; + public static readonly string Password = "neo4j"; + public static readonly string HttpUri = "http://127.0.0.1:7474"; - public static string BoltHeader = "bolt://"; - public static string BoltHost = "127.0.0.1"; - public static string BoltPort = "7687"; + public static readonly string BoltHeader = "bolt://"; + private static readonly string BoltHost = "127.0.0.1"; + public static readonly string BoltPort = "7687"; - static Neo4jDefaultInstallation() + static DefaultInstallation() { if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TEST_NEO4J_USER"))) { @@ -58,16 +58,10 @@ static Neo4jDefaultInstallation() public static IDriver NewBoltDriver(Uri boltUri, IAuthToken authToken) { - ILogger logger; var configuredLevelStr = Environment.GetEnvironmentVariable("NEOLOGLEVEL"); - if (Enum.TryParse(configuredLevelStr ?? "", true, out var configuredLevel)) - { - logger = new TestLogger(s => Console.WriteLine(s), configuredLevel); - } - else - { - logger = new TestLogger(s => Debug.WriteLine(s), ExtendedLogLevel.Debug); - } + var logger = Enum.TryParse(configuredLevelStr ?? "", true, out var configuredLevel) + ? new TestLogger(Console.WriteLine, configuredLevel) + : new TestLogger(s => Debug.WriteLine(s), ExtendedLogLevel.Debug); return GraphDatabase.Driver(boltUri, authToken, o => { o.WithLogger(logger); }); } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/ExternalBoltkitInstaller.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/ExternalBoltkitInstaller.cs index f5c10393c..2d035a73d 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/ExternalBoltkitInstaller.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/ExternalBoltkitInstaller.cs @@ -20,8 +20,8 @@ using System.Linq; using Neo4j.Driver.Internal; using Org.BouncyCastle.Pkcs; -using static Neo4j.Driver.IntegrationTests.Internals.Neo4jDefaultInstallation; -using static Neo4j.Driver.IntegrationTests.Internals.Neo4jSettingsHelper; +using static Neo4j.Driver.IntegrationTests.Internals.DefaultInstallation; +using static Neo4j.Driver.IntegrationTests.Internals.SettingsHelper; namespace Neo4j.Driver.IntegrationTests.Internals; @@ -70,7 +70,7 @@ public void Install() _commandRunner.RunCommand("neoctrl-create-user", $"\"{HomeDir}\"", "neo4j", Password); - if (BoltkitHelper.IPV6Available() && BoltkitHelper.IPV6Enabled()) + if (BoltkitHelper.Ipv6Available() && BoltkitHelper.Ipv6Enabled()) { DefaultConfig[ListenAddr] = Ipv6EnabledAddr; } @@ -110,7 +110,7 @@ public void EnsureRunningWithSettings(IDictionary keyValuePair) private void UpdateSettings(IDictionary keyValuePair) { _commandRunner.Debug($"Updating server config to {keyValuePair.ToContentString()}"); - Neo4jSettingsHelper.UpdateSettings(HomeDir, keyValuePair); + SettingsHelper.UpdateSettings(HomeDir, keyValuePair); } public void EnsureProcedures(string sourceProcedureJarPath) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/LocalStandAloneInstance.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/LocalStandAloneInstance.cs index d01635f38..453030641 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/LocalStandAloneInstance.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/LocalStandAloneInstance.cs @@ -19,49 +19,27 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -public class LocalStandAloneInstance : SingleInstance, IStandAlone +public sealed class LocalStandAloneInstance : SingleInstance, IStandAlone { private const string UsingLocalServer = "DOTNET_DRIVER_USING_LOCAL_SERVER"; - private bool _disposed; public LocalStandAloneInstance() : base( - Neo4jDefaultInstallation.HttpUri, - Neo4jDefaultInstallation.BoltUri, + DefaultInstallation.HttpUri, + DefaultInstallation.BoltUri, null, - Neo4jDefaultInstallation.Password) + DefaultInstallation.Password) { - Driver = Neo4jDefaultInstallation.NewBoltDriver(BoltUri, AuthToken); + Driver = DefaultInstallation.NewBoltDriver(BoltUri, AuthToken); } public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); + Driver.Dispose(); } public IDriver Driver { get; } - ~LocalStandAloneInstance() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - Driver.Dispose(); - } - - _disposed = true; - } - public static bool IsServerProvided() { // If a system flag is set, then we use the local single server instead diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/Neo4jSettingsHelper.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/SettingsHelper.cs similarity index 57% rename from Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/Neo4jSettingsHelper.cs rename to Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/SettingsHelper.cs index 76d4e4bee..436114b49 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/Neo4jSettingsHelper.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/SettingsHelper.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Internals; -internal static class Neo4jSettingsHelper +internal static class SettingsHelper { public const string ListenAddr = "dbms.connectors.default_listen_address"; public const string Ipv6EnabledAddr = "::"; @@ -37,41 +37,39 @@ public static void UpdateSettings(string location, IDictionary k var tempFileName = Path.Combine(location, "conf/neo4j.conf.tmp"); File.Move(configFileName, tempFileName); - using (var reader = new StreamReader(new FileStream(tempFileName, FileMode.Open, FileAccess.Read))) - using (var writer = - new StreamWriter(new FileStream(configFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))) + using var reader = new StreamReader(new FileStream(tempFileName, FileMode.Open, FileAccess.Read)); + using var writer = + new StreamWriter(new FileStream(configFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)); + + while (reader.ReadLine() is { } line) { - string line; - while ((line = reader.ReadLine()) != null) + if (line.Trim() == string.Empty || line.Trim().StartsWith("#")) + { + // empty or comments, print as original + writer.WriteLine(line); + } + else { - if (line.Trim() == string.Empty || line.Trim().StartsWith("#")) + var tokens = line.Split('='); + if (tokens.Length == 2 && keyValuePairCopy.ContainsKey(tokens[0].Trim())) { - // empty or comments, print as original - writer.WriteLine(line); + var key = tokens[0].Trim(); + // found property and update it to the new value + writer.WriteLine($"{key}={keyValuePairCopy[key]}"); + keyValuePairCopy.Remove(key); } else { - var tokens = line.Split('='); - if (tokens.Length == 2 && keyValuePairCopy.ContainsKey(tokens[0].Trim())) - { - var key = tokens[0].Trim(); - // found property and update it to the new value - writer.WriteLine($"{key}={keyValuePairCopy[key]}"); - keyValuePairCopy.Remove(key); - } - else - { - // not the property that we are looking for, print it as original - writer.WriteLine(line); - } + // not the property that we are looking for, print it as original + writer.WriteLine(line); } } + } - // write the extra properties at the end of the file - foreach (var pair in keyValuePairCopy) - { - writer.WriteLine($"{pair.Key}={pair.Value}"); - } + // write the extra properties at the end of the file + foreach (var pair in keyValuePairCopy) + { + writer.WriteLine($"{pair.Key}={pair.Value}"); } // delete the temp file diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/StandAlone.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/StandAlone.cs index 31d28d453..957acf245 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/StandAlone.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Internals/StandAlone/StandAlone.cs @@ -26,12 +26,11 @@ public interface IStandAlone : ISingleInstance, IDisposable IDriver Driver { get; } } -public class StandAlone : IStandAlone +public sealed class StandAlone : IStandAlone { private readonly ExternalBoltkitInstaller _installer = new(); private ISingleInstance _delegator; - private bool _disposed; public StandAlone() { @@ -92,13 +91,23 @@ public StandAlone(Pkcs12Store store) public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } + DisposeBoltDriver(); - ~StandAlone() - { - Dispose(false); + try + { + _installer.Stop(); + } + catch + { + try + { + _installer.Kill(); + } + catch + { + // ignored + } + } } private void RetryIfFailToStart() @@ -116,38 +125,7 @@ private void RetryIfFailToStart() private void NewBoltDriver() { - Driver = Neo4jDefaultInstallation.NewBoltDriver(BoltUri, AuthToken); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - DisposeBoltDriver(); - - try - { - _installer.Stop(); - } - catch - { - try - { - _installer.Kill(); - } - catch - { - // ignored - } - } - } - - _disposed = true; + Driver = DefaultInstallation.NewBoltDriver(BoltUri, AuthToken); } private void DisposeBoltDriver() @@ -160,9 +138,6 @@ public override string ToString() return _delegator?.ToString() ?? "No server found"; } - /// This method will always restart the server with the updated certificates - /// - /// public void RestartServerWithCertificate(Pkcs12Store store) { DisposeBoltDriver(); diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Neo4j.Driver.Tests.Integration.csproj b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Neo4j.Driver.Tests.Integration.csproj index a59907ed7..ed0b8d8cb 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Neo4j.Driver.Tests.Integration.csproj +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Neo4j.Driver.Tests.Integration.csproj @@ -1,5 +1,5 @@  - + net6.0 false @@ -18,38 +18,38 @@ Neo4j.Driver.IntegrationTests - - - - - - - - - - - + + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - - - - - - - + + + + + + + - + @@ -151,7 +151,7 @@ Always - + Always @@ -172,9 +172,9 @@ - + - + diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/AbstractRxIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/AbstractRxIT.cs index 5bbc365df..3ed3ce0e9 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/AbstractRxIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/AbstractRxIT.cs @@ -25,33 +25,34 @@ namespace Neo4j.Driver.IntegrationTests.Reactive; -[Collection(SAIntegrationCollection.CollectionName)] +[Collection(SaIntegrationCollection.CollectionName)] public abstract class AbstractRxIT : AbstractRxTest, IDisposable { private readonly List _sessions = new(); - private bool _disposed; + protected bool IsDispose { get; private set; } protected AbstractRxIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output) { Server = fixture.StandAloneSharedInstance; - ServerEndPoint = Server.BoltUri; - AuthToken = Server.AuthToken; } protected IStandAlone Server { get; } - protected Uri ServerEndPoint { get; } - protected IAuthToken AuthToken { get; } - public void Dispose() + public virtual void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } + switch (IsDispose) + { + case true: return; + case false: + _sessions.ForEach(x => x.Close().WaitForCompletion()); + _sessions.Clear(); + break; + } - ~AbstractRxIT() - { - Dispose(false); + //Mark as disposed + IsDispose = true; + GC.SuppressFinalize(this); } protected IRxSession NewSession() @@ -60,21 +61,4 @@ protected IRxSession NewSession() _sessions.Add(session); return session; } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - _sessions.ForEach(x => x.Close().WaitForCompletion()); - _sessions.Clear(); - } - - //Mark as disposed - _disposed = true; - } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NavigationIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NavigationIT.cs index 93850fee5..0bc937ee0 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NavigationIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NavigationIT.cs @@ -18,9 +18,10 @@ using System.Linq; using System.Reactive.Linq; using Microsoft.Reactive.Testing; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Reactive; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.Reactive.Utils; namespace Neo4j.Driver.IntegrationTests.Reactive; @@ -235,7 +236,7 @@ public void ShouldReturnKeysForEachObserver() { var result = NewRunnable().Run("UNWIND RANGE(1,5) AS n RETURN n as number, 't'+n as text"); - var keys1 = result.Keys().WaitForCompletion(); + var keys1 = result.Keys().WaitForCompletion().ToArray(); result.Consume().WaitForCompletion(); var keys2 = result.Keys().WaitForCompletion(); @@ -254,7 +255,7 @@ public void ShouldReturnSummaryForEachObserver() { var result = NewRunnable().Run("UNWIND RANGE(1,5) AS n RETURN n as number, 't'+n as text"); - var summary1 = result.Consume().WaitForCompletion(); + var summary1 = result.Consume().WaitForCompletion().ToArray(); var summary2 = result.Consume().WaitForCompletion(); var summary3 = result.Consume().WaitForCompletion(); @@ -383,86 +384,56 @@ public void ShouldStreamRecordsOnDemand() public class Session : Specs { - private readonly IRxSession rxSession; - private bool _disposed; + private readonly IRxSession _rxSession; public Session(ITestOutputHelper output, StandAloneIntegrationTestFixture standAlone) : base(output, standAlone) { - rxSession = NewSession(); - } - - ~Session() - { - Dispose(false); + _rxSession = NewSession(); } protected override IRxRunnable NewRunnable() { - return rxSession; + return _rxSession; } - protected override void Dispose(bool disposing) + public override void Dispose() { - if (_disposed) - { - return; - } - - if (disposing) + if (!IsDispose) { - // clean database after each test run - rxSession.Close().WaitForCompletion(); + _rxSession.Close().WaitForCompletion(); } - //Mark as disposed - _disposed = true; - - base.Dispose(disposing); + base.Dispose(); } } public class Transaction : Specs { - private readonly IRxSession rxSession; - private readonly IRxTransaction rxTransaction; - private bool _disposed; + private readonly IRxSession _rxSession; + private readonly IRxTransaction _rxTransaction; public Transaction(ITestOutputHelper output, StandAloneIntegrationTestFixture standAlone) : base(output, standAlone) { - rxSession = NewSession(); - rxTransaction = rxSession.BeginTransaction().SingleAsync().Wait(); - } - - ~Transaction() - { - Dispose(false); + _rxSession = NewSession(); + _rxTransaction = _rxSession.BeginTransaction().SingleAsync().Wait(); } protected override IRxRunnable NewRunnable() { - return rxTransaction; + return _rxTransaction; } - protected override void Dispose(bool disposing) + public override void Dispose() { - if (_disposed) - { - return; - } - - if (disposing) + if (!IsDispose) { // clean database after each test run - rxTransaction.Commit().WaitForCompletion(); - rxSession.Close().WaitForCompletion(); + _rxTransaction.Commit().WaitForCompletion(); + _rxSession.Close().WaitForCompletion(); } - - //Mark as disposed - _disposed = true; - - base.Dispose(disposing); + base.Dispose(); } } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NestedQueriesIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NestedQueriesIT.cs index aaa05b29f..eb87c2dfa 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NestedQueriesIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/NestedQueriesIT.cs @@ -17,10 +17,11 @@ using System.Reactive.Linq; using Microsoft.Reactive.Testing; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Reactive; using Xunit; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.Reactive.Utils; namespace Neo4j.Driver.IntegrationTests.Reactive; @@ -91,7 +92,7 @@ public void ShouldErrorToRunNestedQueriesWithTransactionFunctions() const int size = 1024; var session = Server.Driver.RxSession(o => o.WithFetchSize(5)); - session.ReadTransaction( + session.ExecuteRead( txc => txc.Run("UNWIND range(1, $size) AS x RETURN x", new { size }) .Records() @@ -99,7 +100,7 @@ public void ShouldErrorToRunNestedQueriesWithTransactionFunctions() .Buffer(10) .SelectMany( x => - session.WriteTransaction( + session.ExecuteWrite( txc2 => txc2.Run("UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", new { x }) .Records())) @@ -119,7 +120,7 @@ public void ShouldCloseSessionWhenRunNestedQueriesWithTransactionFunctions() const int size = 1024; var session = Server.Driver.RxSession(o => o.WithFetchSize(5)); - session.ReadTransaction( + session.ExecuteRead( txc => txc.Run("UNWIND range(1, $size) AS x RETURN x", new { size }) .Records() @@ -127,7 +128,7 @@ public void ShouldCloseSessionWhenRunNestedQueriesWithTransactionFunctions() .Buffer(10) .SelectMany( x => - session.WriteTransaction( + session.ExecuteWrite( txc2 => txc2.Run("UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", new { x }) .Records())) @@ -149,7 +150,7 @@ public void ShouldErrorToRunNestedQueriesWithSessionRunAndTransactionFunction() .Buffer(10) .SelectMany( x => - session.WriteTransaction( + session.ExecuteWrite( txc2 => txc2.Run("UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", new { x }).Records())) .Select(r => r[0].As()) @@ -174,7 +175,7 @@ public void ShouldCloseSessionWhenRunNestedQueriesWithSessionRunAndTransactionFu .Buffer(10) .SelectMany( x => - session.WriteTransaction( + session.ExecuteWrite( txc2 => txc2.Run("UNWIND $x AS id CREATE (n:Node {id: id}) RETURN n.id", new { x }).Records())) .Select(r => r[0].As()) @@ -189,7 +190,7 @@ public void ShouldErrorToRunNestedQueriesWithTransactionFunctionAndSessionRun() const int size = 1024; var session = Server.Driver.RxSession(o => o.WithFetchSize(5)); - session.ReadTransaction( + session.ExecuteRead( txc => txc.Run("UNWIND range(1, $size) AS x RETURN x", new { size }) .Records() .Select(r => r[0].As()) @@ -213,7 +214,7 @@ public void ShouldCloseSessionWhenRunNestedQueriesWithTransactionFunctionAndSess const int size = 1024; var session = Server.Driver.RxSession(o => o.WithFetchSize(5)); - session.ReadTransaction( + session.ExecuteRead( txc => txc.Run("UNWIND range(1, $size) AS x RETURN x", new { size }) .Records() .Select(r => r[0].As()) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SessionIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SessionIT.cs index 79bf7052e..a87d62843 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SessionIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SessionIT.cs @@ -22,9 +22,10 @@ using System.Threading; using FluentAssertions; using Microsoft.Reactive.Testing; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Reactive; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.Reactive.Utils; namespace Neo4j.Driver.IntegrationTests.Reactive; @@ -92,7 +93,7 @@ public void ShouldBeAbleToCloseSessionAfterUserFailure() session.Run("RETURN 1") .Records() .SelectMany( - r => + _ => { throw new Exception("Got you!"); #pragma warning disable CS0162 @@ -109,7 +110,7 @@ public void ShouldRunTransactionWithoutRetries() var work = new ConfigurableTransactionWork("CREATE (:WithoutRetry) RETURN 5"); NewSession() - .WriteTransaction(work.Work) + .ExecuteWrite(work.Work) .WaitForCompletion() .AssertEqual( OnNext(0, 5), @@ -133,7 +134,7 @@ public void ShouldRunTransactionWithRetriesOnReactiveFailures() }; NewSession() - .WriteTransaction(work.Work) + .ExecuteWrite(work.Work) .WaitForCompletion() .AssertEqual( OnNext(0, 7), @@ -157,7 +158,7 @@ public void ShouldRunTransactionWithRetriesOnSynchronousFailures() }; NewSession() - .WriteTransaction(work.Work) + .ExecuteWrite(work.Work) .WaitForCompletion() .AssertEqual( OnNext(0, 7), @@ -173,7 +174,7 @@ public void ShouldFailOnTransactionThatCannotBeRetried() var work = new ConfigurableTransactionWork("UNWIND [10, 5, 0] AS x CREATE (:Hi) RETURN 10/x"); NewSession() - .WriteTransaction(work.Work) + .ExecuteWrite(work.Work) .WaitForCompletion() .AssertEqual( OnNext(0, 1), @@ -194,7 +195,7 @@ public void ShouldFailEvenAfterATransientError() }; NewSession() - .WriteTransaction(work.Work) + .ExecuteWrite(work.Work) .WaitForCompletion() .AssertEqual( OnError( @@ -242,18 +243,18 @@ public IEnumerable ReactiveFailures set => _reactiveFailures = (value ?? Enumerable.Empty()).GetEnumerator(); } - public IObservable Work(IRxTransaction txc) + public IObservable Work(IRxRunnable txc) { Interlocked.Increment(ref _invocations); if (_syncFailures.MoveNext()) { - throw _syncFailures.Current; + throw _syncFailures.Current!; } if (_reactiveFailures.MoveNext()) { - return Observable.Throw(_reactiveFailures.Current); + return Observable.Throw(_reactiveFailures.Current!); } return txc.Run(_query).Records().Select(r => r[0].As()); diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SummaryIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SummaryIT.cs index ddc3651ef..4fd888a5a 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SummaryIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/SummaryIT.cs @@ -20,32 +20,26 @@ using System.Reactive.Linq; using FluentAssertions; using Microsoft.Reactive.Testing; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal; using Neo4j.Driver.Internal.Result; using Neo4j.Driver.Reactive; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.Reactive.Utils; using static Neo4j.Driver.Tests.Assertions; namespace Neo4j.Driver.IntegrationTests.Reactive; -public class SummaryIT +public abstract class SummaryIT { public abstract class Specs : AbstractRxIT { - private bool _disposed; - protected Specs(ITestOutputHelper output, StandAloneIntegrationTestFixture standAlone) : base(output, standAlone) { } - ~Specs() - { - Dispose(false); - } - protected abstract IRxRunnable NewRunnable(); [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] @@ -113,7 +107,7 @@ public void ShouldReturnUpdateStatisticsWithDeletes() VerifySummary( "CREATE (n:Label3 {id: $id1})-[:KNOWS]->(m:Label4 {id: $id2}) RETURN n, m", new { id1 = 10, id2 = 20 }, - s => true); + _ => true); VerifySummary( "MATCH (n:Label3)-[r:KNOWS]->(m:Label4) DELETE n, r", @@ -302,143 +296,111 @@ private void VerifySummary(string query, object parameters, Func(0)); } - protected override void Dispose(bool disposing) + public override void Dispose() { - if (_disposed) + if (!IsDispose) { - return; + CleanUpOnDispose(); } - if (disposing) + base.Dispose(); + } + + private void CleanUpOnDispose() + { + using var session = Server.Driver.Session(); + + if (RequireServer.RequiredServerAvailable("5.0.0", GreaterThanOrEqualTo)) { - using (var session = Server.Driver.Session()) + foreach (var drop in session.Run("SHOW CONSTRAINTS").ToList()) { - if (RequireServer.RequiredServerAvailable("5.0.0", GreaterThanOrEqualTo)) + if (drop.Values.TryGetValue("name", out var name)) { - foreach (var drop in session.Run("SHOW CONSTRAINTS").ToList()) - { - if (drop.Values.TryGetValue("name", out var name)) - { - session.Run($"DROP CONSTRAINT {name}").Consume(); - } - } + session.Run($"DROP CONSTRAINT {name}").Consume(); + } + } - foreach (var drop in session.Run("SHOW INDEXES").ToList()) - { - if (drop.Values.TryGetValue("name", out var name)) - { - session.Run($"DROP INDEX {name}").Consume(); - } - } + foreach (var drop in session.Run("SHOW INDEXES").ToList()) + { + if (drop.Values.TryGetValue("name", out var name)) + { + session.Run($"DROP INDEX {name}").Consume(); } - else + } + } + else + { + foreach (var drop in session.Run("CALL db.constraints()").ToList()) + { + if (drop.Values.TryGetValue("name", out var name)) { - foreach (var drop in session.Run("CALL db.constraints()").ToList()) - { - if (drop.Values.TryGetValue("name", out var name)) - { - session.Run($"DROP CONSTRAINT {name}").Consume(); - } - } + session.Run($"DROP CONSTRAINT {name}").Consume(); + } + } - foreach (var drop in session.Run("CALL db.indexes()").ToList()) - { - if (drop.Values.TryGetValue("name", out var name)) - { - session.Run($"DROP INDEX {name}").Consume(); - } - } + foreach (var drop in session.Run("CALL db.indexes()").ToList()) + { + if (drop.Values.TryGetValue("name", out var name)) + { + session.Run($"DROP INDEX {name}").Consume(); } } } - - //Mark as disposed - _disposed = true; - - base.Dispose(disposing); } } public class Session : Specs { - private readonly IRxSession rxSession; - private bool _disposed; + private readonly IRxSession _rxSession; public Session(ITestOutputHelper output, StandAloneIntegrationTestFixture standAlone) : base(output, standAlone) { - rxSession = NewSession(); - } - - ~Session() - { - Dispose(false); + _rxSession = NewSession(); } protected override IRxRunnable NewRunnable() { - return rxSession; + return _rxSession; } - protected override void Dispose(bool disposing) + public override void Dispose() { - if (_disposed) + if (!IsDispose) { - return; + _rxSession.Close().WaitForCompletion(); } - if (disposing) - { - rxSession.Close().WaitForCompletion(); - } - - //Mark as disposed - _disposed = true; - - base.Dispose(disposing); + base.Dispose(); } } public class Transaction : Specs { - private readonly IRxSession rxSession; - private readonly IRxTransaction rxTransaction; - private bool _disposed; + private readonly IRxSession _rxSession; + private readonly IRxTransaction _rxTransaction; public Transaction(ITestOutputHelper output, StandAloneIntegrationTestFixture standAlone) : base(output, standAlone) { - rxSession = NewSession(); - rxTransaction = rxSession.BeginTransaction().SingleAsync().Wait(); - } - - ~Transaction() - { - Dispose(false); + _rxSession = NewSession(); + _rxTransaction = _rxSession.BeginTransaction().SingleAsync().Wait(); } protected override IRxRunnable NewRunnable() { - return rxTransaction; + return _rxTransaction; } - protected override void Dispose(bool disposing) + public override void Dispose() { - if (_disposed) + if (!IsDispose) { - return; + _rxTransaction.Commit().WaitForCompletion(); + _rxSession.Close().WaitForCompletion(); } - if (disposing) - { - rxTransaction.Commit().WaitForCompletion(); - rxSession.Close().WaitForCompletion(); - } - - //Mark as disposed - _disposed = true; - - base.Dispose(disposing); + base.Dispose(); } } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/TransactionIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/TransactionIT.cs index 92c1ed397..63dd72c86 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/TransactionIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Reactive/TransactionIT.cs @@ -23,19 +23,18 @@ using System.Threading.Tasks; using FluentAssertions; using Microsoft.Reactive.Testing; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Reactive; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.Reactive.Utils; using static Neo4j.Driver.Tests.Assertions; namespace Neo4j.Driver.IntegrationTests.Reactive; -public class TransactionIT : AbstractRxIT +public sealed class TransactionIT : AbstractRxIT { - private const string BehaviourDifferenceWJavaDriver = "TODO: Behaviour Difference w/Java Driver"; - - private readonly IRxSession session; + private readonly IRxSession _session; public TransactionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture fixture) : base(output, fixture) @@ -46,20 +45,20 @@ public TransactionIT(ITestOutputHelper output, StandAloneIntegrationTestFixture tmpSession.Run("MATCH (n) DETACH DELETE n").Consume(); } - session = NewSession(); + _session = NewSession(); } [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public void ShouldCommitEmptyTx() { - var bookmarkBefore = session.LastBookmarks; + var bookmarkBefore = _session.LastBookmarks; - session.BeginTransaction() + _session.BeginTransaction() .SelectMany(tx => tx.Commit()) .WaitForCompletion() .AssertEqual(OnCompleted(0)); - var bookmarkAfter = session.LastBookmarks; + var bookmarkAfter = _session.LastBookmarks; bookmarkBefore.Should().BeNull(); bookmarkAfter.Should().NotBe(bookmarkBefore); @@ -68,14 +67,14 @@ public void ShouldCommitEmptyTx() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public void ShouldRollbackEmptyTx() { - var bookmarkBefore = session.LastBookmarks; + var bookmarkBefore = _session.LastBookmarks; - session.BeginTransaction() + _session.BeginTransaction() .SelectMany(tx => tx.Rollback()) .WaitForCompletion() .AssertEqual(OnCompleted(0)); - var bookmarkAfter = session.LastBookmarks; + var bookmarkAfter = _session.LastBookmarks; bookmarkBefore.Should().BeNull(); bookmarkAfter.Should().Be(bookmarkBefore); @@ -84,7 +83,7 @@ public void ShouldRollbackEmptyTx() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public void ShouldRunQueryAndCommit() { - session.BeginTransaction() + _session.BeginTransaction() .SelectMany( txc => txc.Run("CREATE (n:Node {id: 42}) RETURN n") @@ -103,7 +102,7 @@ public void ShouldRunQueryAndCommit() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldRunQueryAndRollback() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 4242); VerifyCanRollback(txc); @@ -125,7 +124,7 @@ public Task ShouldRunMultipleQuerysAndRollback() private async Task VerifyRunMultipleQuerys(bool commit) { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); var result1 = txc.Run("CREATE (n:Node {id : 1})"); await result1.Records().SingleOrDefaultAsync(); @@ -155,7 +154,7 @@ public Task ShouldRunMultipleQuerysWithoutWaitingAndRollback() private async Task VerifyRunMultipleQuerysWithoutWaiting(bool commit) { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); var result1 = txc.Run("CREATE (n:Node {id : 1})"); var result2 = txc.Run("CREATE (n:Node {id : 2})"); @@ -182,7 +181,7 @@ public Task ShouldRunMultipleQuerysWithoutStreamingAndRollback() private async Task VerifyRunMultipleQuerysWithoutStreaming(bool commit) { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); var result1 = txc.Run("CREATE (n:Node {id : 1})"); var result2 = txc.Run("CREATE (n:Node {id : 2})"); @@ -198,7 +197,7 @@ private async Task VerifyRunMultipleQuerysWithoutStreaming(bool commit) [RequireServerFact] public async Task ShouldFailToCommitAfterAFailedQuery() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyFailsWithWrongQuery(txc); @@ -210,7 +209,7 @@ public async Task ShouldFailToCommitAfterAFailedQuery() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldSucceedToRollbackAfterAFailedQuery() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyFailsWithWrongQuery(txc); @@ -222,7 +221,7 @@ public async Task ShouldSucceedToRollbackAfterAFailedQuery() [RequireServerFact] public async Task ShouldFailToCommitAfterSuccessfulAndFailedQuerys() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 5); VerifyCanReturnOne(txc); @@ -236,7 +235,7 @@ public async Task ShouldFailToCommitAfterSuccessfulAndFailedQuerys() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldSucceedToRollbackAfterSuccessfulAndFailedQuerys() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 5); VerifyCanReturnOne(txc); @@ -250,7 +249,7 @@ public async Task ShouldSucceedToRollbackAfterSuccessfulAndFailedQuerys() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldFailToRunAnotherQueryAfterAFailedOne() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyFailsWithWrongQuery(txc); @@ -283,7 +282,7 @@ public void ShouldFailToBeginTxcWithInvalidBookmark() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldNotAllowCommitAfterCommit() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 6); VerifyCanCommit(txc); @@ -302,7 +301,7 @@ public async Task ShouldNotAllowCommitAfterCommit() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldNotAllowRollbackAfterRollback() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 6); VerifyCanRollback(txc); @@ -321,7 +320,7 @@ public async Task ShouldNotAllowRollbackAfterRollback() [RequireServerFact] public async Task ShouldFailToCommitAfterRollback() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 6); VerifyCanRollback(txc); @@ -340,7 +339,7 @@ public async Task ShouldFailToCommitAfterRollback() [RequireServerFact] public async Task ShouldFailToRollbackAfterCommit() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 6); VerifyCanCommit(txc); @@ -370,7 +369,7 @@ public Task ShouldFailToRunQueryAfterCompletedTxcAndRollback() private async Task VerifyFailToRunQueryAfterCompletedTxc(bool commit) { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc, 15); VerifyCanCommitOrRollback(txc, commit); @@ -389,19 +388,19 @@ private async Task VerifyFailToRunQueryAfterCompletedTxc(bool commit) [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldUpdateBookmark() { - var bookmark1 = session.LastBookmarks; + var bookmark1 = _session.LastBookmarks; - var txc1 = await session.BeginTransaction().SingleAsync(); + var txc1 = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc1, 20); VerifyCanCommit(txc1); - var bookmark2 = session.LastBookmarks; + var bookmark2 = _session.LastBookmarks; - var txc2 = await session.BeginTransaction().SingleAsync(); + var txc2 = await _session.BeginTransaction().SingleAsync(); VerifyCanCreateNode(txc2, 20); VerifyCanCommit(txc2); - var bookmark3 = session.LastBookmarks; + var bookmark3 = _session.LastBookmarks; bookmark1.Should().BeNull(); bookmark2.Should().NotBe(bookmark1); @@ -411,7 +410,7 @@ public async Task ShouldUpdateBookmark() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldPropagateFailuresFromQuerys() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); var result1 = txc.Run("CREATE (:TestNode) RETURN 1 as n"); var result2 = txc.Run("CREATE (:TestNode) RETURN 2 as n"); @@ -435,7 +434,7 @@ public async Task ShouldPropagateFailuresFromQuerys() [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldNotRunUntilSubscribed() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); var result1 = txc.Run("RETURN 1"); var result2 = txc.Run("RETURN 2"); @@ -471,7 +470,7 @@ public Task ShouldNotPropagateFailureIfNotExecutedAndRollBacked() private async Task VerifyNotPropagateFailureIfNotExecuted(bool commit) { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); txc.Run("RETURN ILLEGAL"); @@ -481,7 +480,7 @@ private async Task VerifyNotPropagateFailureIfNotExecuted(bool commit) [RequireServerFact("4.0.0", GreaterThanOrEqualTo)] public async Task ShouldNotPropagateRunFailureFromSummary() { - var txc = await session.BeginTransaction().SingleAsync(); + var txc = await _session.BeginTransaction().SingleAsync(); var result = txc.Run("RETURN Wrong"); result.Records() @@ -502,7 +501,7 @@ public void ShouldHandleNestedQueries() { const int size = 1024; - var messages = session.BeginTransaction() + var messages = _session.BeginTransaction() .SelectMany( txc => txc.Run("UNWIND range(1, $size) AS x RETURN x", new { size }) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/BoltV4IT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/BoltV4IT.cs index e468bad09..67d7d3ab1 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/BoltV4IT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/BoltV4IT.cs @@ -17,14 +17,17 @@ using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.TestUtil; +using Xunit; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; using static Neo4j.Driver.SessionConfigBuilder; namespace Neo4j.Driver.IntegrationTests.Routing; -public class BoltV4IT : RoutingDriverTestBase +public sealed class BoltV4IT : RoutingDriverTestBase { private readonly IDriver _driver; @@ -70,20 +73,15 @@ public async Task ShouldReturnDatabaseInfoForDatabaseInTxFunc() public async Task ShouldReturnDatabaseInfoForDatabaseInAutoCommit() { var dbname = "foo"; - var session = _driver.AsyncSession(ForDatabase("system")); Bookmarks bookmarks; - try - { - await session.RunAsync(new Query($"CREATE DATABASE {dbname}")); - bookmarks = session.LastBookmarks; - } - finally + await using (var initial = _driver.AsyncSession(ForDatabase("system"))) { - await session.CloseAsync(); + await initial.RunAsync(new Query($"CREATE DATABASE {dbname}")); + bookmarks = initial.LastBookmarks; } - session = _driver.AsyncSession( + await using var session = _driver.AsyncSession( o => { if (!string.IsNullOrEmpty(dbname)) @@ -94,40 +92,32 @@ public async Task ShouldReturnDatabaseInfoForDatabaseInAutoCommit() o.WithBookmarks(bookmarks ?? Bookmarks.Empty); }); - try - { - var result = await session.RunAsync(new Query("RETURN 1")); - var summary = await result.ConsumeAsync(); - summary.Database.Should().NotBeNull(); - summary.Database.Name.Should().Be(dbname); - } - finally - { - await session.CloseAsync(); - } + var result = await session.RunAsync(new Query("RETURN 1")); + var summary = await result.ConsumeAsync(); + summary.Database.Should().NotBeNull(); + summary.Database.Name.Should().Be(dbname); } [RequireClusterFact("4.0.0", GreaterThanOrEqualTo)] - public void ShouldThrowForNonExistentDatabaseInTxFunc() + public async Task ShouldThrowForNonExistentDatabaseInTxFunc() { - this.Awaiting(_ => VerifyDatabaseNameOnSummaryTxFunc("bar", "bar")) - .Should() - .Throw() - .WithMessage("*database does not exist*"); + var exception = await Record.ExceptionAsync(() => VerifyDatabaseNameOnSummaryTxFunc("bar", "bar")); + exception.Should().BeOfType().Which.Message.Should().Be("*database does not exist*"); } [RequireClusterFact("4.0.0", VersionComparison.LessThan)] - public void ShouldThrowWhenDatabaseIsSpecifiedInTxFunc() + public async Task ShouldThrowWhenDatabaseIsSpecifiedInTxFunc() { - this.Awaiting(_ => VerifyDatabaseNameOnSummaryTxFunc("bar", "bar")) - .Should() - .Throw() - .WithMessage("*to a server that does not support multiple databases.*"); + var exception = await Record.ExceptionAsync(() => VerifyDatabaseNameOnSummaryTxFunc("bar", "bar")); + exception.Should() + .BeOfType() + .Which.Message.Should() + .Be("*to a server that does not support multiple databases.*"); } private async Task VerifyDatabaseNameOnSummaryTxFunc(string name, string expected, Bookmarks bookmarks = null) { - var session = _driver.AsyncSession( + await using var session = _driver.AsyncSession( o => { if (!string.IsNullOrEmpty(name)) @@ -138,44 +128,23 @@ private async Task VerifyDatabaseNameOnSummaryTxFunc(string name, string expecte o.WithBookmarks(bookmarks ?? Bookmarks.Empty); }); - try - { - var summary = - await session.ReadTransactionAsync(async txc => { return await txc.RunAndConsumeAsync("RETURN 1"); }); + var summary = + await session.ExecuteReadAsync(txc => txc.RunAndConsumeAsync("RETURN 1")); - summary.Database.Should().NotBeNull(); - summary.Database.Name.Should().Be(expected); - } - finally - { - await session.CloseAsync(); - } + summary.Database.Should().NotBeNull(); + summary.Database.Name.Should().Be(expected); } private static async Task CreateDatabase(IDriver driver, string name) { - var session = driver.AsyncSession(ForDatabase("system")); - try - { - await session.WriteTransactionAsync(async txc => await txc.RunAndConsumeAsync($"CREATE DATABASE {name}")); - return session.LastBookmarks; - } - finally - { - await session.CloseAsync(); - } + await using var session = driver.AsyncSession(ForDatabase("system")); + await session.ExecuteWriteAsync(async txc => await txc.RunAndConsumeAsync($"CREATE DATABASE {name}")); + return session.LastBookmarks; } private static async Task DropDatabase(IDriver driver, string name, Bookmarks bookmarks) { - var session = driver.AsyncSession(o => o.WithDatabase("system").WithBookmarks(bookmarks)); - try - { - await session.WriteTransactionAsync(async txc => await txc.RunAndConsumeAsync($"DROP DATABASE {name}")); - } - finally - { - await session.CloseAsync(); - } + await using var session = driver.AsyncSession(o => o.WithDatabase("system").WithBookmarks(bookmarks)); + await session.ExecuteWriteAsync(async txc => await txc.RunAndConsumeAsync($"DROP DATABASE {name}")); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverAsyncIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverAsyncIT.cs index 258ee42c0..1a13f3246 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverAsyncIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverAsyncIT.cs @@ -18,12 +18,13 @@ using System; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Routing; -public class RoutingDriverAsyncIT : RoutingDriverTestBase +public sealed class RoutingDriverAsyncIT : RoutingDriverTestBase { public RoutingDriverAsyncIT(ITestOutputHelper output, CausalClusterIntegrationTestFixture fixture) : base( output, @@ -34,65 +35,39 @@ public RoutingDriverAsyncIT(ITestOutputHelper output, CausalClusterIntegrationTe [RequireClusterFact] public async Task ShouldFailWithAuthenticationError() { - Exception exception = null; - using (var driver = GraphDatabase.Driver(RoutingServer, AuthTokens.Basic("fake", "fake"))) - { - var session = driver.AsyncSession(); - try - { - exception = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(RoutingServer, AuthTokens.Basic("fake", "fake")); + await using var session = driver.AsyncSession(); + var exception = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - exception.Should().BeOfType(); - exception.Message.Should().Be("The client is unauthorized due to authentication failure."); + exception.Should() + .BeOfType() + .Which.Message.Should() + .Be("The client is unauthorized due to authentication failure."); } [RequireClusterFact] public async Task ShouldConnectClusterWithRoutingScheme() { - using (var driver = GraphDatabase.Driver(RoutingServer, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var result = await session.RunAsync("UNWIND range(1,10000) AS x RETURN sum(x)"); - var read = await result.FetchAsync(); - read.Should().BeTrue(); - result.Current[0].As().Should().Be(10001 * 10000 / 2); - read = await result.FetchAsync(); - read.Should().BeFalse(); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(RoutingServer, AuthToken); + await using var session = driver.AsyncSession(); + var result = await session.RunAsync("UNWIND range(1,10000) AS x RETURN sum(x)"); + var read = await result.FetchAsync(); + read.Should().BeTrue(); + result.Current[0].As().Should().Be(10001 * 10000 / 2); + read = await result.FetchAsync(); + read.Should().BeFalse(); } [RequireClusterFact] public async Task ShouldThrowServiceUnavailableExceptionIfNoServer() { - Exception error = null; - using (var driver = GraphDatabase.Driver(WrongServer, AuthTokens.Basic("fake", "fake"))) - { - var session = driver.AsyncSession(); - try - { - error = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(WrongServer, AuthTokens.Basic("fake", "fake")); + await using var session = driver.AsyncSession(); + var error = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - error.Should().BeOfType(); - error.Message.Should() + error.Should() + .BeOfType() + .Which.Message.Should() .Be( "Failed to connect to any routing server. Please make sure that the cluster is up and can be accessed by the driver and retry."); } @@ -108,8 +83,9 @@ public async Task ShouldDisallowMoreQueryAfterDriverDispose() driver.Dispose(); var error = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - error.Should().BeOfType(); - error.Message.Should() + error.Should() + .BeOfType() + .Which.Message.Should() .StartWith("Failed to acquire a new connection as the driver has already been disposed."); } @@ -126,7 +102,9 @@ public async Task ShouldDisallowMoreConnectionsAfterDriverDispose() await session.CloseAsync(); var error = Record.Exception(() => driver.AsyncSession()); - error.Should().BeOfType(); - error.Message.Should().Contain("Cannot open a new session on a driver that is already disposed."); + error.Should() + .BeOfType() + .Which.Message.Should() + .Contain("Cannot open a new session on a driver that is already disposed."); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverIT.cs index b6acdef0f..4eb733864 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverIT.cs @@ -18,13 +18,15 @@ using System; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Routing; -[Collection(CCIntegrationCollection.CollectionName)] -public class RoutingDriverIT : RoutingDriverTestBase +[Collection(CcIntegrationCollection.CollectionName)] +public sealed class RoutingDriverIT : RoutingDriverTestBase { public RoutingDriverIT(ITestOutputHelper output, CausalClusterIntegrationTestFixture fixture) : base( output, @@ -35,106 +37,68 @@ public RoutingDriverIT(ITestOutputHelper output, CausalClusterIntegrationTestFix [RequireClusterFact] public async Task ShouldFailWithAuthenticationError() { - using (var driver = GraphDatabase.Driver(RoutingServer, AuthTokens.Basic("fake", "fake"))) - { - var session = driver.AsyncSession(); - try - { - var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + await using var driver = GraphDatabase.Driver(RoutingServer, AuthTokens.Basic("fake", "fake")); + await using var session = driver.AsyncSession(); + var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - exc.Should() - .BeOfType() - .Which - .Message.Should() - .Be("The client is unauthorized due to authentication failure."); - } - finally - { - await session.CloseAsync(); - } - } + exc.Should() + .BeOfType() + .Which + .Message.Should() + .Be("The client is unauthorized due to authentication failure."); } [RequireClusterFact] public async Task ShouldConnectClusterWithRoutingScheme() { - using (var driver = GraphDatabase.Driver(RoutingServer, AuthToken)) - { - var session = driver.AsyncSession(); - try - { - var result = await session.RunAndSingleAsync( - "UNWIND range(1,10000) AS x RETURN sum(x)", - null, - r => r[0].As()); - - result.Should().Be(10001 * 10000 / 2); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(RoutingServer, AuthToken); + await using var session = driver.AsyncSession(); + var result = await session.RunAndSingleAsync( + "UNWIND range(1,10000) AS x RETURN sum(x)", + null, + r => r[0].As()); + + result.Should().Be(10001 * 10000 / 2); } [RequireClusterFact] public async Task ShouldLoadBalanceBetweenServers() { - using (var driver = GraphDatabase.Driver(RoutingServer, AuthToken)) + await using var driver = GraphDatabase.Driver(RoutingServer, AuthToken); + + for (var i = 0; i < 10; i++) { - for (var i = 0; i < 10; i++) + string addr1, addr2; + + await using (var session1 = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read))) + { + var summary = await session1.RunAndConsumeAsync("RETURN 1"); + addr1 = summary.Server.Address; + } + + await using (var session2 = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read))) { - string addr1, addr2; - - var session1 = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); - try - { - var summary = await session1.RunAndConsumeAsync("RETURN 1"); - addr1 = summary.Server.Address; - } - finally - { - await session1.CloseAsync(); - } - - var session2 = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); - try - { - var summary = await session2.RunAndConsumeAsync("RETURN 2"); - addr2 = summary.Server.Address; - } - finally - { - await session2.CloseAsync(); - } - - addr1.Should().NotBe(addr2); + var summary = await session2.RunAndConsumeAsync("RETURN 2"); + addr2 = summary.Server.Address; } + + addr1.Should().NotBe(addr2); } } [RequireClusterFact] public async Task ShouldThrowServiceUnavailableExceptionIfNoServer() { - using (var driver = GraphDatabase.Driver(WrongServer, AuthTokens.Basic("fake", "fake"))) - { - var session = driver.AsyncSession(); - try - { - var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); - - exc.Should() - .BeOfType() - .Which - .Message.Should() - .Be( - "Failed to connect to any routing server. Please make sure that the cluster is up and can be accessed by the driver and retry."); - } - finally - { - await session.CloseAsync(); - } - } + await using var driver = GraphDatabase.Driver(WrongServer, AuthTokens.Basic("fake", "fake")); + await using var session = driver.AsyncSession(); + var exc = await Record.ExceptionAsync(() => session.RunAsync("RETURN 1")); + + exc.Should() + .BeOfType() + .Which + .Message.Should() + .Be( + "Failed to connect to any routing server. Please make sure that the cluster is up and can be accessed by the driver and retry."); } [RequireClusterFact] diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverTestBase.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverTestBase.cs index 58f0266d4..eda3d47b6 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverTestBase.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Routing/RoutingDriverTestBase.cs @@ -23,14 +23,11 @@ namespace Neo4j.Driver.IntegrationTests.Routing; -[Collection(CCIntegrationCollection.CollectionName)] +[Collection(CcIntegrationCollection.CollectionName)] public abstract class RoutingDriverTestBase : IDisposable { - private bool _disposed; - - public RoutingDriverTestBase(ITestOutputHelper output, CausalClusterIntegrationTestFixture fixture) + protected RoutingDriverTestBase(ITestOutputHelper output, CausalClusterIntegrationTestFixture fixture) { - Output = output; Cluster = fixture.Cluster; AuthToken = Cluster.AuthToken; @@ -44,38 +41,16 @@ public RoutingDriverTestBase(ITestOutputHelper output, CausalClusterIntegrationT }); } - protected ITestOutputHelper Output { get; } protected ICausalCluster Cluster { get; } protected IAuthToken AuthToken { get; } protected string RoutingServer => Cluster.BoltRoutingUri.ToString(); - protected string WrongServer => "neo4j://localhost:1234"; - protected IDriver Driver { get; } + protected static string WrongServer => "neo4j://localhost:1234"; + private IDriver Driver { get; } public void Dispose() { - Dispose(true); + Driver.Dispose(); GC.SuppressFinalize(this); } - - ~RoutingDriverTestBase() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - Driver.Dispose(); - } - - //Mark as disposed - _disposed = true; - } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommand.cs deleted file mode 100644 index a858f3ec7..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommand.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncFailingCommand : AsyncCommand -{ - public AsyncFailingCommand(IDriver driver) - : base(driver, false) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - - try - { - var cursor = await session.RunAsync("UNWIND [10, 5, 0] AS x RETURN 10 / x"); - var exc = await Record.ExceptionAsync(() => cursor.ConsumeAsync()); - - exc.Should().BeOfType().Which.Message.Should().Contain("/ by zero"); - } - finally - { - await session.CloseAsync(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandInTx.cs deleted file mode 100644 index a276559ed..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandInTx.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncFailingCommandInTx : AsyncCommand -{ - public AsyncFailingCommandInTx(IDriver driver) - : base(driver, false) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - - try - { - var txc = await BeginTransaction(session, context); - - try - { - var cursor = await txc.RunAsync("UNWIND [10, 5, 0] AS x RETURN 10 / x"); - var exc = await Record.ExceptionAsync(() => cursor.ConsumeAsync()); - - exc.Should().BeOfType().Which.Message.Should().Contain("/ by zero"); - } - finally - { - await txc.RollbackAsync(); - } - } - finally - { - await session.CloseAsync(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandTxFunc.cs index b47376ca7..a74f5bfa6 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncFailingCommandTxFunc.cs @@ -21,7 +21,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class AsyncFailingCommandTxFunc : AsyncCommand +public sealed class AsyncFailingCommandTxFunc : AsyncCommand { public AsyncFailingCommandTxFunc(IDriver driver) : base(driver, false) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommand.cs deleted file mode 100644 index ab8c0237e..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommand.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncReadCommand : AsyncCommand -{ - public AsyncReadCommand(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - try - { - var cursor = await session.RunAsync("MATCH (n) RETURN n LIMIT 1"); - var records = await cursor.ToListAsync(); - if (records.Count > 0) - { - records[0][0].Should().BeAssignableTo(); - context.NodeRead(await cursor.ConsumeAsync()); - } - } - finally - { - await session.CloseAsync(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandInTx.cs deleted file mode 100644 index 69694cc85..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandInTx.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncReadCommandInTx : AsyncCommand -{ - public AsyncReadCommandInTx(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - try - { - var txc = await BeginTransaction(session, context); - - try - { - var cursor = await txc.RunAsync("MATCH (n) RETURN n LIMIT 1"); - var records = await cursor.ToListAsync(); - if (records.Count > 0) - { - records[0][0].Should().BeAssignableTo(); - - context.NodeRead(await cursor.ConsumeAsync()); - } - - await txc.CommitAsync(); - } - catch - { - await txc.RollbackAsync(); - throw; - } - } - finally - { - await session.CloseAsync(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandTxFunc.cs index 390c268b5..0bb5c3700 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncReadCommandTxFunc.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class AsyncReadCommandTxFunc : AsyncCommand +public sealed class AsyncReadCommandTxFunc : AsyncCommand { public AsyncReadCommandTxFunc(IDriver driver, bool useBookmark) : base(driver, useBookmark) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommand.cs deleted file mode 100644 index 507ce364d..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommand.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Threading.Tasks; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncWriteCommand : AsyncCommand -{ - private readonly StressTest _test; - - public AsyncWriteCommand(StressTest test, IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - _test = test ?? throw new ArgumentNullException(nameof(test)); - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var summary = default(IResultSummary); - var error = default(Exception); - - var session = NewSession(AccessMode.Write, context); - try - { - var cursor = await session.RunAsync("CREATE ()"); - summary = await cursor.ConsumeAsync(); - - if (session.LastBookmarks != null) - { - context.Bookmarks = session.LastBookmarks; - } - } - catch (Exception exc) - { - error = exc; - if (!_test.HandleWriteFailure(error, context)) - { - throw; - } - } - finally - { - await session.CloseAsync(); - } - - if (error == null && summary != null) - { - summary.Counters.NodesCreated.Should().Be(1); - context.NodeCreated(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandInTx.cs deleted file mode 100644 index bea4e2226..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandInTx.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Threading.Tasks; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncWriteCommandInTx : AsyncCommand -{ - private readonly StressTest _test; - - public AsyncWriteCommandInTx(StressTest test, IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - _test = test ?? throw new ArgumentNullException(nameof(test)); - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var summary = default(IResultSummary); - var error = default(Exception); - - var session = NewSession(AccessMode.Write, context); - try - { - var txc = await BeginTransaction(session, context); - try - { - var cursor = await txc.RunAsync("CREATE ()"); - summary = await cursor.ConsumeAsync(); - - await txc.CommitAsync(); - } - catch - { - await txc.RollbackAsync(); - throw; - } - - context.Bookmarks = session.LastBookmarks; - } - catch (Exception exc) - { - error = exc; - if (!_test.HandleWriteFailure(error, context)) - { - throw; - } - } - finally - { - await session.CloseAsync(); - } - - if (error == null && summary != null) - { - summary.Counters.NodesCreated.Should().Be(1); - context.NodeCreated(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandTxFunc.cs index 2830ec31c..7abc80976 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandTxFunc.cs @@ -21,7 +21,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class AsyncWriteCommandTxFunc : AsyncCommand +public sealed class AsyncWriteCommandTxFunc : AsyncCommand { private readonly StressTest _test; diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSession.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSession.cs deleted file mode 100644 index 9c4a605af..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSession.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncWriteCommandUsingReadSession: AsyncCommand -{ - public AsyncWriteCommandUsingReadSession(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var cursor = default(IResultCursor); - - var session = NewSession(AccessMode.Read, context); - try - { - var exc = await Record.ExceptionAsync( - async () => - { - cursor = await session.RunAsync("CREATE ()"); - await cursor.ConsumeAsync(); - }); - - exc.Should().BeOfType(); - } - finally - { - await session.CloseAsync(); - } - - cursor.Should().NotBeNull(); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(0); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionInTx.cs deleted file mode 100644 index 1d69c0f6d..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionInTx.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncWriteCommandUsingReadSessionInTx: AsyncCommand -{ - public AsyncWriteCommandUsingReadSessionInTx(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var cursor = default(IResultCursor); - - var session = NewSession(AccessMode.Read, context); - try - { - var txc = await BeginTransaction(session, context); - try - { - var exc = await Record.ExceptionAsync( - async () => - { - cursor = await txc.RunAsync("CREATE ()"); - await cursor.ConsumeAsync(); - }); - - exc.Should().BeOfType(); - } - finally - { - await txc.RollbackAsync(); - } - } - finally - { - await session.CloseAsync(); - } - - cursor.Should().NotBeNull(); - var summary = await cursor.ConsumeAsync(); - summary.Counters.NodesCreated.Should().Be(0); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionTxFunc.cs index ab46e498d..d39737b28 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWriteCommandUsingReadSessionTxFunc.cs @@ -21,7 +21,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class AsyncWriteCommandUsingReadSessionTxFunc : AsyncCommand +public sealed class AsyncWriteCommandUsingReadSessionTxFunc : AsyncCommand { public AsyncWriteCommandUsingReadSessionTxFunc(IDriver driver, bool useBookmark) : base(driver, useBookmark) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommand.cs deleted file mode 100644 index 05b55f23e..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncWrongCommand: AsyncCommand -{ - public AsyncWrongCommand(IDriver driver) - : base(driver, false) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - try - { - var exc = await Record.ExceptionAsync( - async () => - { - var cursor = await session.RunAsync("RETURN"); - await cursor.ConsumeAsync(); - }); - - exc.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); - } - finally - { - await session.CloseAsync(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandInTx.cs deleted file mode 100644 index cf23cfc6c..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandInTx.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class AsyncWrongCommandInTx : AsyncCommand -{ - public AsyncWrongCommandInTx(IDriver driver) - : base(driver, false) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - try - { - var txc = await BeginTransaction(session, context); - try - { - var exc = await Record.ExceptionAsync( - async () => - { - var cursor = await txc.RunAsync("RETURN"); - await cursor.ConsumeAsync(); - }); - - exc.Should() - .BeOfType() - .Which.Code.Should() - .Be("Neo.ClientError.Statement.SyntaxError"); - } - finally - { - await txc.RollbackAsync(); - } - } - finally - { - await session.CloseAsync(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandTxFunc.cs index f6750f294..da679e5d3 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Async/AsyncWrongCommandTxFunc.cs @@ -21,7 +21,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class AsyncWrongCommandTxFunc : AsyncCommand +public sealed class AsyncWrongCommandTxFunc : AsyncCommand { public AsyncWrongCommandTxFunc(IDriver driver) : base(driver, false) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/AsyncCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/AsyncCommand.cs index 5e0e29aa8..7e5cc73c4 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/AsyncCommand.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/AsyncCommand.cs @@ -33,31 +33,11 @@ protected AsyncCommand(IDriver driver, bool useBookmark) public abstract Task ExecuteAsync(StressTestContext context); - public IAsyncSession NewSession(AccessMode mode, StressTestContext context) + protected IAsyncSession NewSession(AccessMode mode, StressTestContext context) { return _driver.AsyncSession( o => o.WithDefaultAccessMode(mode) .WithBookmarks(_useBookmark ? new[] { context.Bookmarks } : Array.Empty())); } - - public Task BeginTransaction(IAsyncSession session, StressTestContext context) - { - if (_useBookmark) - { - while (true) - { - try - { - return session.BeginTransactionAsync(); - } - catch (TransientException) - { - context.BookmarkFailed(); - } - } - } - - return session.BeginTransactionAsync(); - } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandInTx.cs deleted file mode 100644 index 625f69832..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandInTx.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingFailingCommandInTx: BlockingCommand -{ - public BlockingFailingCommandInTx(IDriver driver) - : base(driver, false) - { - } - - public override void Execute(StressTestContext context) - { - using (var session = NewSession(AccessMode.Read, context)) - using (var txc = BeginTransaction(session, context)) - { - var result = txc.Run("UNWIND [10, 5, 0] AS x RETURN 10 / x"); - var exc = Record.Exception(() => result.Consume()); - - exc.Should().BeOfType().Which.Message.Should().Contain("/ by zero"); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandTxFunc.cs index 62b800808..c008980e2 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingFailingCommandTxFunc.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class BlockingFailingCommandTxFunc : BlockingCommand +public sealed class BlockingFailingCommandTxFunc : BlockingCommand { public BlockingFailingCommandTxFunc(IDriver driver) : base(driver, false) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommand.cs deleted file mode 100644 index 1d9093742..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommand.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Linq; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingReadCommand : BlockingCommand -{ - public BlockingReadCommand(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override void Execute(StressTestContext context) - { - using (var session = NewSession(AccessMode.Read, context)) - { - var result = session.Run("MATCH (n) RETURN n LIMIT 1"); - var record = result.SingleOrDefault(); - record?[0].Should().BeAssignableTo(); - context.NodeRead(result.Consume()); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandInTx.cs deleted file mode 100644 index c8e1d4b37..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandInTx.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Linq; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingReadCommandInTx: BlockingCommand -{ - public BlockingReadCommandInTx(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override void Execute(StressTestContext context) - { - using (var session = NewSession(AccessMode.Read, context)) - using (var txc = BeginTransaction(session, context)) - { - var result = txc.Run("MATCH (n) RETURN n LIMIT 1"); - var record = result.SingleOrDefault(); - record?[0].Should().BeAssignableTo(); - - context.NodeRead(result.Consume()); - - txc.Commit(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandTxFunc.cs index 1c7353b9f..2fe1c7851 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingReadCommandTxFunc.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class BlockingReadCommandTxFunc: BlockingCommand +public sealed class BlockingReadCommandTxFunc: BlockingCommand { public BlockingReadCommandTxFunc(IDriver driver, bool useBookmark) : base(driver, useBookmark) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommand.cs deleted file mode 100644 index d5549e154..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommand.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingWriteCommand: BlockingCommand -{ - private readonly StressTest _test; - - public BlockingWriteCommand(StressTest test, IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - _test = test ?? throw new ArgumentNullException(nameof(test)); - } - - public override void Execute(StressTestContext context) - { - var summary = default(IResultSummary); - var error = default(Exception); - - try - { - using (var session = NewSession(AccessMode.Write, context)) - { - summary = session.Run("CREATE ()").Consume(); - - if (session.LastBookmarks != null) - { - context.Bookmarks = session.LastBookmarks; - } - } - } - catch (Exception exc) - { - error = exc; - if (!_test.HandleWriteFailure(error, context)) - { - throw; - } - } - - if (error == null && summary != null) - { - summary.Counters.NodesCreated.Should().Be(1); - context.NodeCreated(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandInTx.cs deleted file mode 100644 index 7dba8fed8..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandInTx.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using FluentAssertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingWriteCommandInTx : BlockingCommand -{ - private readonly StressTest _test; - - public BlockingWriteCommandInTx(StressTest test, IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - _test = test ?? throw new ArgumentNullException(nameof(test)); - } - - public override void Execute(StressTestContext context) - { - var summary = default(IResultSummary); - var error = default(Exception); - - try - { - using (var session = NewSession(AccessMode.Write, context)) - { - using (var txc = BeginTransaction(session, context)) - { - summary = txc.Run("CREATE ()").Consume(); - - txc.Commit(); - } - - context.Bookmarks = session.LastBookmarks; - } - } - catch (Exception exc) - { - error = exc; - if (!_test.HandleWriteFailure(error, context)) - { - throw; - } - } - - if (error == null && summary != null) - { - summary.Counters.NodesCreated.Should().Be(1); - context.NodeCreated(); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandTxFunc.cs index edbb9a117..5eceda62b 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandTxFunc.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class BlockingWriteCommandTxFunc : BlockingCommand +public sealed class BlockingWriteCommandTxFunc : BlockingCommand { private readonly StressTest _test; diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSession.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSession.cs deleted file mode 100644 index 8a17477d5..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSession.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingWriteCommandUsingReadSession : BlockingCommand -{ - public BlockingWriteCommandUsingReadSession(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override void Execute(StressTestContext context) - { - var result = default(IResult); - - using (var session = NewSession(AccessMode.Read, context)) - { - var exc = Record.Exception( - () => - { - result = session.Run("CREATE ()"); - result.Consume(); - return result; - }); - - exc.Should().BeOfType(); - } - - result.Should().NotBeNull(); - result.Consume().Counters.NodesCreated.Should().Be(0); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionInTx.cs deleted file mode 100644 index 0ee526930..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionInTx.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingWriteCommandUsingReadSessionInTx : BlockingCommand -{ - public BlockingWriteCommandUsingReadSessionInTx(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override void Execute(StressTestContext context) - { - var result = default(IResult); - - using (var session = NewSession(AccessMode.Read, context)) - using (var txc = BeginTransaction(session, context)) - { - var exc = Record.Exception( - () => - { - result = txc.Run("CREATE ()"); - result.Consume(); - return result; - }); - - exc.Should().BeOfType(); - } - - result.Should().NotBeNull(); - result.Consume().Counters.NodesCreated.Should().Be(0); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionTxFunc.cs index 4c7f2a445..84f0669e8 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWriteCommandUsingReadSessionTxFunc.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class BlockingWriteCommandUsingReadSessionTxFunc : BlockingCommand +public sealed class BlockingWriteCommandUsingReadSessionTxFunc : BlockingCommand { public BlockingWriteCommandUsingReadSessionTxFunc(IDriver driver, bool useBookmark) : base(driver, useBookmark) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandInTx.cs deleted file mode 100644 index 50df327b6..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandInTx.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using FluentAssertions; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class BlockingWrongCommandInTx: BlockingCommand -{ - public BlockingWrongCommandInTx(IDriver driver) - : base(driver, false) - { - } - - public override void Execute(StressTestContext context) - { - using (var session = NewSession(AccessMode.Read, context)) - using (var txc = BeginTransaction(session, context)) - { - var exc = Record.Exception(() => txc.Run("RETURN").Consume()); - exc.Should().BeOfType().Which.Code.Should().Be("Neo.ClientError.Statement.SyntaxError"); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandTxFunc.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandTxFunc.cs index 8cf1fc5b7..01957c829 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandTxFunc.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Blocking/BlockingWrongCommandTxFunc.cs @@ -20,7 +20,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class BlockingWrongCommandTxFunc : BlockingCommand +public sealed class BlockingWrongCommandTxFunc : BlockingCommand { public BlockingWrongCommandTxFunc(IDriver driver) : base(driver, false) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/BlockingCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/BlockingCommand.cs index 356305697..f5be708b1 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/BlockingCommand.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/BlockingCommand.cs @@ -21,8 +21,8 @@ namespace Neo4j.Driver.IntegrationTests.Stress; public abstract class BlockingCommand : IBlockingCommand { - protected readonly IDriver _driver; - protected readonly bool _useBookmark; + private readonly IDriver _driver; + private readonly bool _useBookmark; protected BlockingCommand(IDriver driver, bool useBookmark) { @@ -32,31 +32,11 @@ protected BlockingCommand(IDriver driver, bool useBookmark) public abstract void Execute(StressTestContext context); - public ISession NewSession(AccessMode mode, StressTestContext context) + protected ISession NewSession(AccessMode mode, StressTestContext context) { return _driver.Session( o => o.WithDefaultAccessMode(mode) .WithBookmarks(_useBookmark ? new[] { context.Bookmarks } : Array.Empty())); } - - public ITransaction BeginTransaction(ISession session, StressTestContext context) - { - if (_useBookmark) - { - while (true) - { - try - { - return session.BeginTransaction(); - } - catch (TransientException) - { - context.BookmarkFailed(); - } - } - } - - return session.BeginTransaction(); - } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/CausalClusterStressTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/CausalClusterStressTests.cs index 3fc4fc746..854e7c4ca 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/CausalClusterStressTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/CausalClusterStressTests.cs @@ -22,14 +22,16 @@ using System.Text; using System.Threading; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Stress; -[Collection(CCIntegrationCollection.CollectionName)] -public class CausalClusterStressTests : StressTest +[Collection(CcIntegrationCollection.CollectionName)] +// ReSharper disable once UnusedMember.Global +public sealed class CausalClusterStressTests : StressTest { private readonly CausalClusterIntegrationTestFixture _cluster; diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommand.cs deleted file mode 100644 index 04c9827de..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommand.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Reactive.Linq; -using System.Threading.Tasks; -using Microsoft.Reactive.Testing; -using Neo4j.Driver.Internal; -using Neo4j.Driver.Reactive; -using static Neo4j.Driver.Reactive.Utils; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class RxFailingCommand : RxCommand -{ - public RxFailingCommand(IDriver driver) - : base(driver, false) - { - } - - public override Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - - session - .Run("UNWIND [10, 5, 0] AS x RETURN 10 / x") - .Records() - .Select(r => r[0].As()) - .CatchAndThrow(_ => session.Close()) - .Concat(session.Close()) - .WaitForCompletion() - .AssertEqual( - OnNext(0, 1), - OnNext(0, 2), - OnError(0, MatchesException(exc => exc.Message.Contains("/ by zero")))); - - return Task.CompletedTask; - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommandInTx.cs index 8be7450ed..427afbdda 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommandInTx.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxFailingCommandInTx.cs @@ -24,7 +24,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class RxFailingCommandInTx: RxCommand +public sealed class RxFailingCommandInTx: RxCommand { public RxFailingCommandInTx(IDriver driver) : base(driver, false) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommand.cs deleted file mode 100644 index fd9b4981b..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommand.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Reactive.Linq; -using System.Threading.Tasks; -using FluentAssertions; -using Neo4j.Driver.Internal; -using static Neo4j.Driver.Tests.Assertions; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class RxReadCommand : RxCommand -{ - public RxReadCommand(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - var result = session.Run("MATCH (n) RETURN n LIMIT 1"); - - var summary = await result - .Records() - .SingleOrDefaultAsync() - .All(r => Matches(() => r?[0].Should().BeAssignableTo())) - .SelectMany(_ => result.Consume()) - .CatchAndThrow(_ => session.Close()) - .Concat(session.Close()); - - if (summary != null) - { - context.NodeRead(summary); - } - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommandInTx.cs index fd3322869..695876ab6 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommandInTx.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxReadCommandInTx.cs @@ -23,7 +23,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class RxReadCommandInTx : RxCommand +public sealed class RxReadCommandInTx : RxCommand { public RxReadCommandInTx(IDriver driver, bool useBookmark) : base(driver, useBookmark) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommand.cs deleted file mode 100644 index 5a046f6f5..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommand.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using FluentAssertions; -using Neo4j.Driver.Internal; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class RxWriteCommand : RxCommand -{ - private readonly StressTest _test; - - public RxWriteCommand(StressTest test, IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - _test = test ?? throw new ArgumentNullException(nameof(test)); - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Write, context); - - await session - .Run("CREATE ()") - .Consume() - .Select( - summary => - { - summary.Counters.NodesCreated.Should().Be(1); - context.NodeCreated(); - return summary; - }) - .Catch( - (Exception error) => - !_test.HandleWriteFailure(error, context) - ? Observable.Throw(error) - : Observable.Empty()) - .Finally( - () => - { - if (session.LastBookmarks != null) - { - context.Bookmarks = session.LastBookmarks; - } - }) - .SingleOrDefaultAsync() - .CatchAndThrow(_ => session.Close()) - .Concat(session.Close()); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandInTx.cs index 3fe9ae8e9..64554242d 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandInTx.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandInTx.cs @@ -23,7 +23,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class RxWriteCommandInTx : RxCommand +public sealed class RxWriteCommandInTx : RxCommand { private readonly StressTest _test; diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSession.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSession.cs deleted file mode 100644 index d456ec3ad..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSession.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Reactive.Linq; -using System.Threading.Tasks; -using FluentAssertions; -using Neo4j.Driver.Internal; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class RxWriteCommandUsingReadSession : RxCommand -{ - public RxWriteCommandUsingReadSession(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - var result = session.Run("CREATE ()"); - - var exc = await Record.ExceptionAsync( - async () => await result - .Records() - .CatchAndThrow(_ => session.Close()) - .Concat(session.Close())); - - exc.Should().BeOfType(); - - result.Should().NotBeNull(); - var summary = await result.Consume(); - summary.Counters.NodesCreated.Should().Be(0); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSessionInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSessionInTx.cs deleted file mode 100644 index ebd1c825c..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWriteCommandUsingReadSessionInTx.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Reactive.Linq; -using System.Threading.Tasks; -using FluentAssertions; -using Neo4j.Driver.Internal; -using Xunit; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class RxWriteCommandUsingReadSessionInTx : RxCommand -{ - public RxWriteCommandUsingReadSessionInTx(IDriver driver, bool useBookmark) - : base(driver, useBookmark) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - var result = default(IRxResult); - - var exc = await Record.ExceptionAsync( - async () => await BeginTransaction(session, context) - .SelectMany( - txc => - { - result = txc.Run("CREATE ()"); - - return result - .Records() - .CatchAndThrow(_ => txc.Rollback()) - .Concat(txc.Commit()); - }) - .CatchAndThrow(_ => session.Close()) - .Concat(session.Close())); - - exc.Should().BeOfType(); - - result.Should().NotBeNull(); - var summary = await result.Consume(); - summary.Counters.NodesCreated.Should().Be(0); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommand.cs deleted file mode 100644 index c3f95a7c1..000000000 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommand.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) "Neo4j" -// Neo4j Sweden AB [http://neo4j.com] -// -// This file is part of Neo4j. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Reactive; -using System.Reactive.Linq; -using System.Threading.Tasks; -using Microsoft.Reactive.Testing; -using Neo4j.Driver.Internal; -using static Neo4j.Driver.Reactive.Utils; - -namespace Neo4j.Driver.IntegrationTests.Stress; - -public class RxWrongCommand : RxCommand -{ - public RxWrongCommand(IDriver driver) - : base(driver, false) - { - } - - public override async Task ExecuteAsync(StressTestContext context) - { - var session = NewSession(AccessMode.Read, context); - - var result = await session - .Run("RETURN") - .Records() - .CatchAndThrow(_ => session.Close()) - .Concat(session.Close()) - .Materialize() - .Select(r => new Recorded>(0, r)) - .ToList(); - - result.AssertEqual( - OnError( - 0, - MatchesException(exc => exc.Code.Equals("Neo.ClientError.Statement.SyntaxError")))); - } -} diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommandInTx.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommandInTx.cs index b90f518db..c7474d403 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommandInTx.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/Reactive/RxWrongCommandInTx.cs @@ -24,7 +24,7 @@ namespace Neo4j.Driver.IntegrationTests.Stress; -public class RxWrongCommandInTx : RxCommand +public sealed class RxWrongCommandInTx : RxCommand { public RxWrongCommandInTx(IDriver driver) : base(driver, false) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/RxCommand.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/RxCommand.cs index 944255964..ccc32e5a0 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/RxCommand.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/RxCommand.cs @@ -24,8 +24,8 @@ namespace Neo4j.Driver.IntegrationTests.Stress; public abstract class RxCommand : ReactiveTest, IRxCommand { - protected readonly IDriver _driver; - protected readonly bool _useBookmark; + private readonly IDriver _driver; + private readonly bool _useBookmark; protected RxCommand(IDriver driver, bool useBookmark) { @@ -35,7 +35,7 @@ protected RxCommand(IDriver driver, bool useBookmark) public abstract Task ExecuteAsync(StressTestContext context); - public IRxSession NewSession(AccessMode mode, StressTestContext context) + protected IRxSession NewSession(AccessMode mode, StressTestContext context) { return _driver.RxSession( o => @@ -43,7 +43,7 @@ public IRxSession NewSession(AccessMode mode, StressTestContext context) .WithBookmarks(_useBookmark ? new[] { context.Bookmarks } : Array.Empty())); } - public IObservable BeginTransaction(IRxSession session, StressTestContext context) + protected IObservable BeginTransaction(IRxSession session, StressTestContext context) { if (_useBookmark) { diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/SingleInstanceStressTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/SingleInstanceStressTests.cs index 56b1760db..5ec97f6b5 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/SingleInstanceStressTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/SingleInstanceStressTests.cs @@ -21,12 +21,14 @@ using System.Text; using System.Threading; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit; using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Stress; -[Collection(SAIntegrationCollection.CollectionName)] +[Collection(SaIntegrationCollection.CollectionName)] +// ReSharper disable once UnusedMember.Global public class SingleInstanceStressTests : StressTest { private readonly StandAloneIntegrationTestFixture _standalone; diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/StressTest.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/StressTest.cs index cd44795c3..dc0df0603 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/StressTest.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stress/StressTest.cs @@ -24,15 +24,17 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; namespace Neo4j.Driver.IntegrationTests.Stress; public abstract class StressTest: IDisposable { - public enum StressTestMinLogLevel + private enum StressTestMinLogLevel { Trace, Debug, diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/AccessModeTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/AccessModeTests.cs index 27e6959f7..a09cee6ba 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/AccessModeTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/AccessModeTests.cs @@ -17,12 +17,13 @@ using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; using Neo4j.Driver.IntegrationTests.Internals; using Xunit; namespace Neo4j.Driver.IntegrationTests.Stub; -public class AccessModeTests +public sealed class AccessModeTests { private static void NoEncryption(ConfigBuilder builder) { @@ -32,56 +33,32 @@ private static void NoEncryption(ConfigBuilder builder) [RequireBoltStubServerFact] public async Task RunOnReadModeSessionShouldGoToReader() { - using (BoltStubServer.Start("V4/accessmode_router", 9001)) - { - using (BoltStubServer.Start("V4/accessmode_reader_implicit", 9003)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); - try - { - var result = await session.RunAndSingleAsync("RETURN $x", new { x = 1 }, r => r[0].As()); - - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_router", 9001); + using var __ = BoltStubServer.Start("V4/accessmode_reader_implicit", 9003); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); + var result = await session.RunAndSingleAsync("RETURN $x", new { x = 1 }, r => r[0].As()); + + result.Should().Be(1); } [RequireBoltStubServerFact] public async Task RunOnReadModeTransactionShouldGoToReader() { - using (BoltStubServer.Start("V4/accessmode_router", 9001)) - { - using (BoltStubServer.Start("V4/accessmode_reader_explicit", 9003)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); - try - { - var tx = await session.BeginTransactionAsync(); - var result = await tx.RunAndSingleAsync("RETURN $x", new { x = 1 }, r => r[0].As()); - - result.Should().Be(1); - - await tx.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_router", 9001); + using var __ = BoltStubServer.Start("V4/accessmode_reader_explicit", 9003); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); + var tx = await session.BeginTransactionAsync(); + var result = await tx.RunAndSingleAsync("RETURN $x", new { x = 1 }, r => r[0].As()); + + result.Should().Be(1); + + await tx.CommitAsync(); } [RequireBoltStubServerTheory] @@ -89,91 +66,55 @@ public async Task RunOnReadModeTransactionShouldGoToReader() [InlineData(AccessMode.Write)] public async Task ReadTransactionOnSessionShouldGoToReader(AccessMode mode) { - using (BoltStubServer.Start("V4/accessmode_router", 9001)) - { - using (BoltStubServer.Start("V4/accessmode_reader_func", 9003)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(mode)); - try - { - var result = await session.ReadTransactionAsync( - tx => - tx.RunAndSingleAsync("RETURN $x", new { x = 1 }, r => r[0].As())); - - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_router", 9001); + using var __ = BoltStubServer.Start("V4/accessmode_reader_func", 9003); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(mode)); + var result = await session.ExecuteReadAsync( + tx => + tx.RunAndSingleAsync("RETURN $x", new { x = 1 }, r => r[0].As())); + + result.Should().Be(1); } [RequireBoltStubServerFact] public async Task RunOnWriteModeSessionShouldGoToWriter() { - using (BoltStubServer.Start("V4/accessmode_router", 9001)) - { - using (BoltStubServer.Start("V4/accessmode_writer_implicit", 9002)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); - try - { - var result = await session.RunAndSingleAsync( - "CREATE (n: { id: $x }) RETURN $x", - new { x = 1 }, - r => r[0].As()); - - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_router", 9001); + using var __ = BoltStubServer.Start("V4/accessmode_writer_implicit", 9002); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); + var result = await session.RunAndSingleAsync( + "CREATE (n: { id: $x }) RETURN $x", + new { x = 1 }, + r => r[0].As()); + + result.Should().Be(1); } [RequireBoltStubServerFact] public async Task RunOnWriteModeTransactionShouldGoToWriter() { - using (BoltStubServer.Start("V4/accessmode_router", 9001)) - { - using (BoltStubServer.Start("V4/accessmode_writer_explicit", 9002)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); - try - { - var tx = await session.BeginTransactionAsync(); - - var result = await tx.RunAndSingleAsync( - "CREATE (n: { id: $x }) RETURN $x", - new { x = 1 }, - r => r[0].As()); - - result.Should().Be(1); - - await tx.CommitAsync(); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_router", 9001); + using var __ = BoltStubServer.Start("V4/accessmode_writer_explicit", 9002); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); + var tx = await session.BeginTransactionAsync(); + + var result = await tx.RunAndSingleAsync( + "CREATE (n: { id: $x }) RETURN $x", + new { x = 1 }, + r => r[0].As()); + + result.Should().Be(1); + + await tx.CommitAsync(); } [RequireBoltStubServerTheory] @@ -181,31 +122,19 @@ public async Task RunOnWriteModeTransactionShouldGoToWriter() [InlineData(AccessMode.Write)] public async Task WriteTransactionOnSessionShouldGoToWriter(AccessMode mode) { - using (BoltStubServer.Start("V4/accessmode_router", 9001)) - { - using (BoltStubServer.Start("V4/accessmode_writer_func", 9002)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(mode)); - try - { - var result = await session.WriteTransactionAsync( - tx => - tx.RunAndSingleAsync( - "CREATE (n: { id: $x }) RETURN $x", - new { x = 1 }, - r => r[0].As())); - - result.Should().Be(1); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_router", 9001); + using var __ = BoltStubServer.Start("V4/accessmode_writer_func", 9002); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, NoEncryption); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(mode)); + var result = await session.ExecuteWriteAsync( + tx => + tx.RunAndSingleAsync( + "CREATE (n: { id: $x }) RETURN $x", + new { x = 1 }, + r => r[0].As())); + + result.Should().Be(1); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/DirectDriverTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/DirectDriverTests.cs index fcaad2962..c5a1314e6 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/DirectDriverTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/DirectDriverTests.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Neo4j.Driver.IntegrationTests.Internals; @@ -26,7 +27,7 @@ namespace Neo4j.Driver.IntegrationTests.Stub; -public class DirectDriverTests +public sealed class DirectDriverTests { public DirectDriverTests(ITestOutputHelper output) { @@ -35,7 +36,7 @@ public DirectDriverTests(ITestOutputHelper output) .WithLogger(TestLogger.Create(output)); } - public Action SetupConfig { get; } + private Action SetupConfig { get; } [RequireBoltStubServerFact] public async Task ShouldLogServerAddress() @@ -48,31 +49,16 @@ void SetupConfig(ConfigBuilder o) o.WithLogger(new TestLogger(logs.Add, ExtendedLogLevel.Debug)); } - using (BoltStubServer.Start("V4/accessmode_reader_implicit", 9001)) - { - using (var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); - try - { - var cursor = await session.RunAsync("RETURN $x", new { x = 1 }); - var list = await cursor.ToListAsync(r => Convert.ToInt32(r[0])); - - list.Should().HaveCount(1).And.Contain(1); - } - finally - { - await session.CloseAsync(); - } - } - } + using var _ = BoltStubServer.Start("V4/accessmode_reader_implicit", 9001); + await using var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig); + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); + var cursor = await session.RunAsync("RETURN $x", new { x = 1 }); + var list = await cursor.ToListAsync(r => Convert.ToInt32(r[0])); - foreach (var log in logs) + list.Should().HaveCount(1).And.Contain(1); + foreach (var log in logs.Where(log => log.StartsWith("[Debug]:[conn-"))) { - if (log.StartsWith("[Debug]:[conn-")) - { - log.Should().Contain("127.0.0.1:9001"); - } + log.Should().Contain("127.0.0.1:9001"); } } @@ -86,38 +72,31 @@ public async Task CanSendMultipleBookmarks() "neo4j:bookmark:v1:tx16", "neo4j:bookmark:v1:tx68" }; - using (BoltStubServer.Start("V4/multiple_bookmarks", 9001)) + using var _ = BoltStubServer.Start("V4/multiple_bookmarks", 9001); + var uri = new Uri("bolt://127.0.0.1:9001"); + await using var driver = GraphDatabase.Driver(uri, SetupConfig); + + await using var session = driver.AsyncSession(o => o.WithBookmarks(Bookmarks.From(bookmarks))); + try { - var uri = new Uri("bolt://127.0.0.1:9001"); - using (var driver = GraphDatabase.Driver(uri, SetupConfig)) + var txc = await session.BeginTransactionAsync(); + try { - var session = driver.AsyncSession(o => o.WithBookmarks(Bookmarks.From(bookmarks))); - try - { - var txc = await session.BeginTransactionAsync(); - try - { - await txc.RunAsync("CREATE (n {name:'Bob'})"); - await txc.CommitAsync(); - } - catch - { - await txc.RollbackAsync(); - throw; - } - } - catch (Exception ex) - { - var var = ex.Message; - } - finally - { - await session.CloseAsync(); - } - - session.LastBookmark.Should().Be(Bookmarks.From("neo4j:bookmark:v1:tx95")); + await txc.RunAsync("CREATE (n {name:'Bob'})"); + await txc.CommitAsync(); } + catch + { + await txc.RollbackAsync(); + throw; + } + } + catch (Exception) + { + // no op } + + session.LastBookmarks.Should().Be(Bookmarks.From("neo4j:bookmark:v1:tx95")); } [RequireBoltStubServerTheory] @@ -125,32 +104,21 @@ public async Task CanSendMultipleBookmarks() [InlineData("V4")] public async Task ShouldOnlyResetAfterError(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/rollback_error", 9001)) + using var _ = BoltStubServer.Start($"{boltVersion}/rollback_error", 9001); + var uri = new Uri("bolt://127.0.0.1:9001"); + await using var driver = GraphDatabase.Driver(uri, SetupConfig); + await using var session = driver.AsyncSession(); + var txc = await session.BeginTransactionAsync(); + try { - var uri = new Uri("bolt://127.0.0.1:9001"); - using (var driver = GraphDatabase.Driver(uri, SetupConfig)) - { - var session = driver.AsyncSession(); - try - { - var txc = await session.BeginTransactionAsync(); - try - { - var result = await txc.RunAsync("CREATE (n {name:'Alice'}) RETURN n.name AS name"); - var exception = await Record.ExceptionAsync(() => result.ConsumeAsync()); - - exception.Should().BeOfType(); - } - finally - { - await txc.RollbackAsync(); - } - } - finally - { - await session.CloseAsync(); - } - } + var result = await txc.RunAsync("CREATE (n {name:'Alice'}) RETURN n.name AS name"); + var exception = await Record.ExceptionAsync(() => result.ConsumeAsync()); + + exception.Should().BeOfType(); + } + finally + { + await txc.RollbackAsync(); } } @@ -159,13 +127,9 @@ public async Task ShouldOnlyResetAfterError(string boltVersion) [InlineData("V4")] public async Task ShouldVerifyConnectivity(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/supports_multidb", 9001)) - { - using (var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig)) - { - await driver.VerifyConnectivityAsync(); - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/supports_multidb", 9001); + await using var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig); + await driver.VerifyConnectivityAsync(); } [RequireBoltStubServerTheory] @@ -173,36 +137,20 @@ public async Task ShouldVerifyConnectivity(string boltVersion) [InlineData("V4")] public async Task ShouldThrowSecurityErrorWhenFailedToHello(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/fail_to_auth", 9001)) - { - using (var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig)) - { - var error = await Record.ExceptionAsync(() => driver.VerifyConnectivityAsync()); - error.Should().BeOfType(); - error.Message.Should().StartWith("blabla"); - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/fail_to_auth", 9001); + await using var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig); + var error = await Record.ExceptionAsync(() => driver.VerifyConnectivityAsync()); + error.Should().BeOfType().Which.Message.Should().StartWith("blabla"); } [RequireBoltStubServerTheory] [InlineData("V4_1")] //Use same script on all versions after 4.1 public async Task ShouldNotThrowOnNoopMessages(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/noop", 9001)) - { - using (var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig)) - { - //await driver.VerifyConnectivityAsync(); - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("MATCH (N) RETURN n.name"); - } - finally - { - await session.CloseAsync(); - } - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/noop", 9001); + await using var driver = GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, SetupConfig); + //await driver.VerifyConnectivityAsync(); + await using var session = driver.AsyncSession(); + await session.RunAsync("MATCH (N) RETURN n.name"); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/MultiDatabasesTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/MultiDatabasesTests.cs index 12148663a..3a4cd5662 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/MultiDatabasesTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/MultiDatabasesTests.cs @@ -18,6 +18,7 @@ using System; using System.Threading.Tasks; using FluentAssertions; +using Neo4j.Driver.IntegrationTests.Extensions; using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.TestUtil; using Xunit; @@ -25,215 +26,142 @@ namespace Neo4j.Driver.IntegrationTests.Stub; -public class MultiDatabasesTests +public sealed class MultiDatabasesTests { - private readonly ITestOutputHelper _output; private readonly Action _setupConfig; public MultiDatabasesTests(ITestOutputHelper output) { - _output = output; - _setupConfig = o => o.WithLogger(TestLogger.Create(output)); } [Fact] public async Task ShouldDiscoverEndpointsForADatabaseAndRead() { - using (BoltStubServer.Start("V4/acquire_endpoints_aDatabase", 9001)) - { - using (BoltStubServer.Start("V4/read_from_aDatabase", 9005)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var session = driver.AsyncSession( - o => - o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Read)); - - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/acquire_endpoints_aDatabase", 9001); + using var __ = BoltStubServer.Start("V4/read_from_aDatabase", 9005); + await using var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession( + o => + o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Read)); + + var cursor = + await session.RunAsync("MATCH (n) RETURN n.name"); + + var result = await cursor.ToListAsync(r => r[0].As()); + + result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); } [Fact] public async Task ShouldDiscoverEndpointsForADatabaseAndWrite() { - using (BoltStubServer.Start("V4/acquire_endpoints_aDatabase", 9001)) - { - using (BoltStubServer.Start("V4/write_to_aDatabase", 9007)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var session = driver.AsyncSession( - o => - o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Write)); - - try - { - await session.RunAndConsumeAsync("CREATE (n {name:'Bob'})"); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/acquire_endpoints_aDatabase", 9001); + using var __ = BoltStubServer.Start("V4/write_to_aDatabase", 9007); + await using var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession( + o => + o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Write)); + + await session.RunAndConsumeAsync("CREATE (n {name:'Bob'})"); } [Fact] public async Task ShouldDiscoverEndpointsForDefaultDatabase() { - using (BoltStubServer.Start("V4/acquire_endpoints_default_database", 9001)) - { - using (BoltStubServer.Start("V4/read", 9005)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/acquire_endpoints_default_database", 9001); + using var __ = BoltStubServer.Start("V4/read", 9005); + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Read)); + var cursor = + await session.RunAsync("MATCH (n) RETURN n.name"); + + var result = await cursor.ToListAsync(r => r[0].As()); + + result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); } [Fact] - public void ShouldThrowOnInvalidRoutingTable() + public async Task ShouldThrowOnInvalidRoutingTable() { - using (BoltStubServer.Start("V4/acquire_endpoints_aDatabase_no_servers", 9001)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig)) + using var _ = BoltStubServer.Start("V4/acquire_endpoints_aDatabase_no_servers", 9001); + + var exception = await Record.ExceptionAsync( + async () => { - Func p = async _ => - { - var session = driver.AsyncSession( - o => - o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Read)); - - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - }; - - this.Awaiting(p) - .Should() - .Throw() - .WithMessage("Failed to connect to any routing server.*"); - } - } + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession( + o => + o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Read)); + + await session.RunAsync("MATCH (n) RETURN n.name"); + }); + + exception + .Should() + .BeOfType() + .Which.Message.Should() + .Be("Failed to connect to any routing server.*"); } [Fact] - public void ShouldThrowOnProcedureNotFound() + public async Task ShouldThrowOnDatabaseNotFound() { - using (BoltStubServer.Start("V4/acquire_endpoints_db_not_found", 9001)) - { - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig)) + using var _ = BoltStubServer.Start("V4/acquire_endpoints_db_not_found", 9001); + + var exception = await Record.ExceptionAsync( + async () => { - Func p = async _ => - { - var session = driver.AsyncSession( - o => - o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Read)); - - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - }; - - this.Awaiting(p) - .Should() - .Throw() - .WithMessage("database not found"); - } - } + await using var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession( + o => + o.WithDatabase("aDatabase").WithDefaultAccessMode(AccessMode.Read)); + + var cursor = + await session.RunAsync("MATCH (n) RETURN n.name"); + + var result = await cursor.ToListAsync(r => r[0].As()); + + result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); + }); + + exception + .Should() + .BeOfType() + .Which.Message.Should() + .Be("database not found"); } [Fact] public async Task ShouldDiscoverEndpointsForADatabaseWithBookmarks() { - using (BoltStubServer.Start("V4/acquire_endpoints_aDatabase_with_bookmark", 9001)) - { - using (BoltStubServer.Start("V4/read_from_aDatabase_with_bookmark", 9005)) - { - var bookmark1 = Bookmarks.From("system:1111"); - var bookmark2 = Bookmarks.From("aDatabase:5555"); - - using (var driver = - GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var session = driver.AsyncSession( - o => - o.WithDatabase("aDatabase") - .WithDefaultAccessMode(AccessMode.Read) - .WithBookmarks(bookmark1, bookmark2)); - - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - } - } - } + using var _ = BoltStubServer.Start("V4/acquire_endpoints_aDatabase_with_bookmark", 9001); + using var __ = BoltStubServer.Start("V4/read_from_aDatabase_with_bookmark", 9005); + var bookmark1 = Bookmarks.From("system:1111"); + var bookmark2 = Bookmarks.From("aDatabase:5555"); + + await using var driver = + GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession( + o => + o.WithDatabase("aDatabase") + .WithDefaultAccessMode(AccessMode.Read) + .WithBookmarks(bookmark1, bookmark2)); + + var cursor = + await session.RunAsync("MATCH (n) RETURN n.name"); + + var result = await cursor.ToListAsync(r => r[0].As()); + + result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); } [RequireBoltStubServerTheory] @@ -243,20 +171,16 @@ public async Task ShouldDiscoverEndpointsForADatabaseWithBookmarks() [InlineData("V4", "bolt")] public async Task ShouldDetectMultiDatabasesFeature(string boltVersion, string scheme) { - using (BoltStubServer.Start($"{boltVersion}/supports_multidb", 9001)) + using var _ = BoltStubServer.Start($"{boltVersion}/supports_multidb", 9001); + await using var driver = GraphDatabase.Driver($"{scheme}://127.0.0.1:9001", AuthTokens.None, _setupConfig); + var support = await driver.SupportsMultiDbAsync(); + if (boltVersion.Equals("V3")) { - using (var driver = GraphDatabase.Driver($"{scheme}://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var support = await driver.SupportsMultiDbAsync(); - if (boltVersion.Equals("V3")) - { - support.Should().BeFalse(); - } - else - { - support.Should().BeTrue(); - } - } + support.Should().BeFalse(); + } + else + { + support.Should().BeTrue(); } } @@ -265,11 +189,9 @@ public async Task ShouldDetectMultiDatabasesFeature(string boltVersion, string s [InlineData("bolt")] public async Task ShouldFailToDetectMultiDatabasesFeature(string scheme) { - using (var driver = GraphDatabase.Driver($"{scheme}://127.0.0.1:9099", AuthTokens.None, _setupConfig)) - { - var error = await Record.ExceptionAsync(() => driver.SupportsMultiDbAsync()); - error.Should().BeOfType(); - } + await using var driver = GraphDatabase.Driver($"{scheme}://127.0.0.1:9099", AuthTokens.None, _setupConfig); + var error = await Record.ExceptionAsync(() => driver.SupportsMultiDbAsync()); + error.Should().BeOfType(); } [RequireBoltStubServerTheory] @@ -279,14 +201,9 @@ public async Task ShouldFailToDetectMultiDatabasesFeature(string scheme) [InlineData("V4", "bolt")] public async Task ShouldThrowSecurityErrorWhenFailToHello(string boltVersion, string scheme) { - using (BoltStubServer.Start($"{boltVersion}/fail_to_auth", 9001)) - { - using (var driver = GraphDatabase.Driver($"{scheme}://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var error = await Record.ExceptionAsync(() => driver.SupportsMultiDbAsync()); - error.Should().BeOfType(); - error.Message.Should().StartWith("blabla"); - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/fail_to_auth", 9001); + await using var driver = GraphDatabase.Driver($"{scheme}://127.0.0.1:9001", AuthTokens.None, _setupConfig); + var error = await Record.ExceptionAsync(() => driver.SupportsMultiDbAsync()); + error.Should().BeOfType().Which.Message.Should().StartWith("blabla"); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/ResultStreamingTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/ResultStreamingTests.cs index ce619ee33..2dde0c8dc 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/ResultStreamingTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/ResultStreamingTests.cs @@ -28,7 +28,7 @@ namespace Neo4j.Driver.IntegrationTests.Stub; -public class ResultStreamingTests +public sealed class ResultStreamingTests { private readonly ITestOutputHelper _output; private readonly Action _setupConfig; @@ -36,108 +36,81 @@ public class ResultStreamingTests public ResultStreamingTests(ITestOutputHelper output) { _output = output; - _setupConfig = o => o.WithLogger(TestLogger.Create(output)); } [Fact] public async Task ShouldStreamingWithAsyncSession() { - using (BoltStubServer.Start("V4/streaming_records_all", 9001)) - { - using (var driver = - GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, _setupConfig)) - { - var session = driver.AsyncSession(); - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - } - } + using var _ = BoltStubServer.Start("V4/streaming_records_all", 9001); + await using var driver = + GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, _setupConfig); + + await using var session = driver.AsyncSession(); + var cursor = + await session.RunAsync("MATCH (n) RETURN n.name"); + + var result = await cursor.ToListAsync(r => r[0].As()); + + result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); } [Fact] public async Task ShouldAllowChangeFetchSize() { - using (BoltStubServer.Start("V4/streaming_records", 9001)) - { - using (var driver = GraphDatabase.Driver( - "bolt://127.0.0.1:9001", - AuthTokens.None, - o => o.WithLogger(TestLogger.Create(_output)).WithFetchSize(2))) - { - var session = driver.AsyncSession(); - try - { - var cursor = - await session.RunAsync("MATCH (n) RETURN n.name"); - - var result = await cursor.ToListAsync(r => r[0].As()); - - result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); - } - finally - { - await session.CloseAsync(); - } - } - } + using var _ = BoltStubServer.Start("V4/streaming_records", 9001); + await using var driver = GraphDatabase.Driver( + "bolt://127.0.0.1:9001", + AuthTokens.None, + o => o.WithLogger(TestLogger.Create(_output)).WithFetchSize(2)); + + await using var session = driver.AsyncSession(); + var cursor = + await session.RunAsync("MATCH (n) RETURN n.name"); + + var result = await cursor.ToListAsync(r => r[0].As()); + + result.Should().BeEquivalentTo("Bob", "Alice", "Tina"); } [Fact] public void ShouldDiscardIfNotFinished() { - using (BoltStubServer.Start("V4/discard_streaming_records", 9001)) - { - using (var driver = GraphDatabase.Driver( - "bolt://127.0.0.1:9001", - AuthTokens.None, - o => o.WithLogger(TestLogger.Create(_output)).WithFetchSize(2))) - { - var session = driver.RxSession(); - - session.Run("UNWIND [1,2,3,4] AS n RETURN n") - .Keys() - .WaitForCompletion() - .AssertEqual( - OnNext(0, Utils.MatchesKeys("n")), - OnCompleted(0)); - - session.Close().WaitForCompletion().AssertEqual(OnCompleted(0)); - } - } + using var _ = BoltStubServer.Start("V4/discard_streaming_records", 9001); + using var driver = GraphDatabase.Driver( + "bolt://127.0.0.1:9001", + AuthTokens.None, + o => o.WithLogger(TestLogger.Create(_output)).WithFetchSize(2)); + + var session = driver.RxSession(); + + session.Run("UNWIND [1,2,3,4] AS n RETURN n") + .Keys() + .WaitForCompletion() + .AssertEqual( + OnNext(0, Utils.MatchesKeys("n")), + OnCompleted(0)); + + session.Close().WaitForCompletion().AssertEqual(OnCompleted(0)); } [Fact] public void ShouldDiscardTxIfNotFinished() { - using (BoltStubServer.Start("V4/discard_streaming_records_tx", 9001)) - { - using (var driver = GraphDatabase.Driver( - "bolt://127.0.0.1:9001", - AuthTokens.None, - o => o.WithLogger(TestLogger.Create(_output)).WithFetchSize(2))) - { - var session = driver.RxSession(); - - session.ReadTransaction(tx => tx.Run("UNWIND [1,2,3,4] AS n RETURN n").Keys()) - .WaitForCompletion() - .AssertEqual( - OnNext(0, Utils.MatchesKeys("n")), - OnCompleted(0)); - - session.Close().WaitForCompletion().AssertEqual(OnCompleted(0)); - } - } + using var _ = BoltStubServer.Start("V4/discard_streaming_records_tx", 9001); + using var driver = GraphDatabase.Driver( + "bolt://127.0.0.1:9001", + AuthTokens.None, + o => o.WithLogger(TestLogger.Create(_output)).WithFetchSize(2)); + + var session = driver.RxSession(); + + session.ExecuteRead(tx => tx.Run("UNWIND [1,2,3,4] AS n RETURN n").Keys()) + .WaitForCompletion() + .AssertEqual( + OnNext(0, Utils.MatchesKeys("n")), + OnCompleted(0)); + + session.Close().WaitForCompletion().AssertEqual(OnCompleted(0)); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/RoutingDriverTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/RoutingDriverTests.cs index 4e3199095..f4f5eafcd 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/RoutingDriverTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/RoutingDriverTests.cs @@ -20,46 +20,34 @@ using FluentAssertions; using Neo4j.Driver.IntegrationTests.Internals; using Xunit; -using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Stub; -public class RoutingDriverTests +public sealed class RoutingDriverTests { - public RoutingDriverTests(ITestOutputHelper output) + public RoutingDriverTests() { SetupConfig = o => o .WithEncryptionLevel(EncryptionLevel.None); } - public Action SetupConfig { get; } + private Action SetupConfig { get; } [RequireBoltStubServerTheory] [InlineData("V3")] [InlineData("V4")] public async Task SendRoutingContextToServer(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/get_routing_table_with_context", 9001)) - { - var uri = new Uri("neo4j://127.0.0.1:9001/?policy=my_policy®ion=china"); - using (var driver = GraphDatabase.Driver(uri, SetupConfig)) - { - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("MATCH (n) RETURN n.name AS name"); - var records = await cursor.ToListAsync(); + using var _ = BoltStubServer.Start($"{boltVersion}/get_routing_table_with_context", 9001); + var uri = new Uri("neo4j://127.0.0.1:9001/?policy=my_policy®ion=china"); + await using var driver = GraphDatabase.Driver(uri, SetupConfig); + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("MATCH (n) RETURN n.name AS name"); + var records = await cursor.ToListAsync(); - records.Count.Should().Be(2); - records[0]["name"].As().Should().Be("Alice"); - records[1]["name"].As().Should().Be("Bob"); - } - finally - { - await session.CloseAsync(); - } - } - } + records.Count.Should().Be(2); + records[0]["name"].As().Should().Be("Alice"); + records[1]["name"].As().Should().Be("Bob"); } [RequireBoltStubServerTheory] @@ -67,28 +55,17 @@ public async Task SendRoutingContextToServer(string boltVersion) [InlineData("V4")] public async Task InvokeProcedureGetRoutingTableWhenServerVersionPermits(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/get_routing_table", 9001)) - { - var uri = new Uri("neo4j://127.0.0.1:9001"); - using (var driver = GraphDatabase.Driver(uri, SetupConfig)) - { - var session = driver.AsyncSession(); - try - { - var cursor = await session.RunAsync("MATCH (n) RETURN n.name AS name"); - var records = await cursor.ToListAsync(); + using var _ = BoltStubServer.Start($"{boltVersion}/get_routing_table", 9001); + var uri = new Uri("neo4j://127.0.0.1:9001"); + await using var driver = GraphDatabase.Driver(uri, SetupConfig); + await using var session = driver.AsyncSession(); + var cursor = await session.RunAsync("MATCH (n) RETURN n.name AS name"); + var records = await cursor.ToListAsync(); - records.Count.Should().Be(3); - records[0]["name"].As().Should().Be("Alice"); - records[1]["name"].As().Should().Be("Bob"); - records[2]["name"].As().Should().Be("Eve"); - } - finally - { - await session.CloseAsync(); - } - } - } + records.Count.Should().Be(3); + records[0]["name"].As().Should().Be("Alice"); + records[1]["name"].As().Should().Be("Bob"); + records[2]["name"].As().Should().Be("Eve"); } [RequireBoltStubServerTheory] @@ -96,13 +73,9 @@ public async Task InvokeProcedureGetRoutingTableWhenServerVersionPermits(string [InlineData("V4")] public async Task ShouldVerifyConnectivity(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/verify_connectivity", 9001)) - { - using (var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, SetupConfig)) - { - await driver.VerifyConnectivityAsync(); - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/verify_connectivity", 9001); + await using var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, SetupConfig); + await driver.VerifyConnectivityAsync(); } [RequireBoltStubServerTheory] @@ -110,14 +83,9 @@ public async Task ShouldVerifyConnectivity(string boltVersion) [InlineData("V4")] public async Task ShouldThrowSecurityErrorWhenFailedToHello(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/fail_to_auth", 9001)) - { - using (var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, SetupConfig)) - { - var error = await Record.ExceptionAsync(() => driver.VerifyConnectivityAsync()); - error.Should().BeOfType(); - error.Message.Should().StartWith("blabla"); - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/fail_to_auth", 9001); + await using var driver = GraphDatabase.Driver("neo4j://127.0.0.1:9001", AuthTokens.None, SetupConfig); + var error = await Record.ExceptionAsync(() => driver.VerifyConnectivityAsync()); + error.Should().BeOfType().Which.Message.Should().StartWith("blabla"); } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/TransactionTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/TransactionTests.cs index a9ee08630..adf83aa50 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/TransactionTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Stub/TransactionTests.cs @@ -22,7 +22,6 @@ using FluentAssertions; using Neo4j.Driver.IntegrationTests.Internals; using Xunit; -using Xunit.Abstractions; namespace Neo4j.Driver.IntegrationTests.Stub; @@ -34,12 +33,12 @@ public static bool HasCause(this Exception exception) { T => true, AggregateException aggregate => aggregate.InnerExceptions.Any(x => x.HasCause()), - _ => exception.InnerException?.HasCause() ?? false + var _ => exception.InnerException?.HasCause() ?? false }; } } -public class TransactionTests +public abstract class TransactionTests { private static void NoEncryptionAndShortRetry(ConfigBuilder builder) { @@ -54,27 +53,22 @@ public class ExplicitTransaction [InlineData("V4")] public void ShouldFailIfCommitFailsDueToBrokenConnection(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001)) - { - using (var driver = - GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry)) - { - using (var session = driver.Session(o => o.WithDefaultAccessMode(AccessMode.Write))) - { - var txc = session.BeginTransaction(); - var result = txc.Run("CREATE (n {name: 'Bob'})"); - - var exc = Record.Exception(() => txc.Commit()); - - exc.Should() - .BeOfType() - .Which - .HasCause() - .Should() - .BeTrue(); - } - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001); + using var driver = + GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry); + + using var session = driver.Session(o => o.WithDefaultAccessMode(AccessMode.Write)); + var txc = session.BeginTransaction(); + txc.Run("CREATE (n {name: 'Bob'})"); + + var exc = Record.Exception(() => txc.Commit()); + + exc.Should() + .BeOfType() + .Which + .HasCause() + .Should() + .BeTrue(); } [Theory] @@ -82,74 +76,53 @@ public void ShouldFailIfCommitFailsDueToBrokenConnection(string boltVersion) [InlineData("V4")] public async Task ShouldFailIfCommitFailsDueToBrokenConnectionAsync(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001)) - { - using (var driver = - GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry)) - { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); - try - { - var txc = await session.BeginTransactionAsync(); - var result = await txc.RunAsync("CREATE (n {name: 'Bob'})"); - - var exc = await Record.ExceptionAsync(() => txc.CommitAsync()); - - exc.Should() - .BeOfType() - .Which - .HasCause() - .Should() - .BeTrue(); - } - finally - { - await session.CloseAsync(); - } - } - } + using var _ = BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001); + await using var driver = + GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); + var txc = await session.BeginTransactionAsync(); + await txc.RunAsync("CREATE (n {name: 'Bob'})"); + + var exc = await Record.ExceptionAsync(() => txc.CommitAsync()); + + exc.Should() + .BeOfType() + .Which + .HasCause() + .Should() + .BeTrue(); } } public class TransactionFunction { - private readonly ITestOutputHelper _testOutputHelper; - - public TransactionFunction(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - [Theory] [InlineData("V3")] [InlineData("V4")] public void ShouldFailIfCommitFailsDueToBrokenConnection(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001)) - { - using (var driver = - GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry)) + using var _ = BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001); + + var exc = Record.Exception( + () => { - var session = driver.Session(o => o.WithDefaultAccessMode(AccessMode.Write)); - try - { - var exc = Record.Exception( - () => - session.WriteTransaction(txc => txc.Run("CREATE (n {name: 'Bob'})"))); - - exc.Should() - .BeOfType() - .Which - .HasCause() - .Should() - .BeTrue(); - } - finally - { - session.Dispose(); - } - } - } + using var driver = GraphDatabase.Driver( + "bolt://127.0.0.1:9001", + AuthTokens.None, + NoEncryptionAndShortRetry); + + using var session = driver.Session(o => o.WithDefaultAccessMode(AccessMode.Write)); + + session.ExecuteWrite(txc => txc.Run("CREATE (n {name: 'Bob'})")); + }); + + exc.Should() + .BeOfType() + .Which + .HasCause() + .Should() + .BeTrue(); } [Theory] @@ -157,34 +130,25 @@ public void ShouldFailIfCommitFailsDueToBrokenConnection(string boltVersion) [InlineData("V4")] public async Task ShouldFailIfCommitFailsDueToBrokenConnectionAsync(string boltVersion) { - using (BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001)) - { - using (var driver = - GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry)) + using var _ = BoltStubServer.Start($"{boltVersion}/connection_error_on_commit", 9001); + + var exc = await Record.ExceptionAsync( + async () => { - var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); - - try - { - var exc = await Record.ExceptionAsync( - () => - { - return session.WriteTransactionAsync(txc => txc.RunAsync("CREATE (n {name: 'Bob'})")); - }); - - exc.Should() - .BeOfType() - .Which - .HasCause() - .Should() - .BeTrue(); - } - finally - { - await session.CloseAsync(); - } - } - } + await using var driver = + GraphDatabase.Driver("bolt://127.0.0.1:9001", AuthTokens.None, NoEncryptionAndShortRetry); + + await using var session = driver.AsyncSession(o => o.WithDefaultAccessMode(AccessMode.Write)); + + await session.ExecuteWriteAsync(txc => txc.RunAsync("CREATE (n {name: 'Bob'})")); + }); + + exc.Should() + .BeOfType() + .Which + .HasCause() + .Should() + .BeTrue(); } } } diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/PointsIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/PointsIT.cs index d2bc15a69..952bd7550 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/PointsIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/PointsIT.cs @@ -21,12 +21,13 @@ using System.Threading.Tasks; using FluentAssertions; using Neo4j.Driver.IntegrationTests.Direct; +using Neo4j.Driver.IntegrationTests.Internals; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; namespace Neo4j.Driver.IntegrationTests.Types; -public class PointsIT : DirectDriverTestBase +public sealed class PointsIT : DirectDriverTestBase { private const int Wgs84SrId = 4326; private const int Wgs843DSrId = 4979; @@ -159,36 +160,19 @@ private async Task TestSendAndReceiveList(IList points) private IList GenerateRandomPointList(int sequence, int count) { - return Enumerable.Range(0, count).Select(i => GenerateRandomPoint(sequence)).ToList(); + return Enumerable.Range(0, count).Select(_ => GenerateRandomPoint(sequence)).ToList(); } private Point GenerateRandomPoint(int sequence) { - switch (sequence % 4) + return (sequence % 4) switch { - case 0: - return new Point(Wgs84SrId, GenerateRandomX(), GenerateRandomY()); - - case 1: - return new Point( - Wgs843DSrId, - GenerateRandomX(), - GenerateRandomY(), - GenerateRandomZ()); - - case 2: - return new Point(CartesianSrId, GenerateRandomX(), GenerateRandomY()); - - case 3: - return new Point( - Cartesian3DSrId, - GenerateRandomX(), - GenerateRandomY(), - GenerateRandomZ()); - - default: - throw new ArgumentOutOfRangeException(); - } + 0 => new Point(Wgs84SrId, GenerateRandomX(), GenerateRandomY()), + 1 => new Point(Wgs843DSrId, GenerateRandomX(), GenerateRandomY(), GenerateRandomZ()), + 2 => new Point(CartesianSrId, GenerateRandomX(), GenerateRandomY()), + 3 => new Point(Cartesian3DSrId, GenerateRandomX(), GenerateRandomY(), GenerateRandomZ()), + var _ => throw new ArgumentOutOfRangeException() + }; } private double GenerateRandomX() diff --git a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/TemporalTypesIT.cs b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/TemporalTypesIT.cs index ce20ab2ce..7a9963a11 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/TemporalTypesIT.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests.Integration/Types/TemporalTypesIT.cs @@ -21,13 +21,14 @@ using System.Threading.Tasks; using FluentAssertions; using Neo4j.Driver.IntegrationTests.Direct; +using Neo4j.Driver.IntegrationTests.Internals; using Neo4j.Driver.Internal; using Xunit.Abstractions; -using static Neo4j.Driver.IntegrationTests.VersionComparison; +using static Neo4j.Driver.IntegrationTests.Internals.VersionComparison; namespace Neo4j.Driver.IntegrationTests.Types; -public class TemporalTypesIT : DirectDriverTestBase +public sealed class TemporalTypesIT : DirectDriverTestBase { private const int NumberOfRandomSequences = 100; private const int MinArrayLength = 5; @@ -282,7 +283,7 @@ public async Task ShouldSendAndReceiveRandomDuration() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomDuration()) + .Select(_ => RandomDuration()) .Select(TestSendAndReceive)); } @@ -291,7 +292,7 @@ public async Task ShouldSendAndReceiveRandomLocalDate() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomLocalDate()) + .Select(_ => RandomLocalDate()) .Select(TestSendAndReceive)); } @@ -300,7 +301,7 @@ public async Task ShouldSendAndReceiveRandomLocalDateTime() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomLocalDateTime()) + .Select(_ => RandomLocalDateTime()) .Select(TestSendAndReceive)); } @@ -309,7 +310,7 @@ public async Task ShouldSendAndReceiveRandomLocalTime() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomLocalTime()) + .Select(_ => RandomLocalTime()) .Select(TestSendAndReceive)); } @@ -318,7 +319,7 @@ public async Task ShouldSendAndReceiveRandomOffsetTime() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomOffsetTime()) + .Select(_ => RandomOffsetTime()) .Select(TestSendAndReceive)); } @@ -327,7 +328,7 @@ public async Task ShouldSendAndReceiveRandomOffsetDateTime() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomOffsetDateTime()) + .Select(_ => RandomOffsetDateTime()) .Select(TestSendAndReceive)); } @@ -336,7 +337,7 @@ public async Task ShouldSendAndReceiveRandomZonedDateTime() { await Task.WhenAll( Enumerable.Range(0, NumberOfRandomSequences) - .Select(i => RandomZonedDateTime()) + .Select(_ => RandomZonedDateTime()) .Select(TestSendAndReceive)); } @@ -349,7 +350,7 @@ public async Task ShouldSendAndReceiveArrayOfDuration() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomDuration())); + .Select(_ => RandomDuration())); } [RequireServerFact("3.4.0", GreaterThanOrEqualTo)] @@ -357,7 +358,7 @@ public async Task ShouldSendAndReceiveArrayOfLocalDate() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomLocalDate())); + .Select(_ => RandomLocalDate())); } [RequireServerFact("3.4.0", GreaterThanOrEqualTo)] @@ -365,7 +366,7 @@ public async Task ShouldSendAndReceiveArrayOfLocalDateTime() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomLocalDateTime())); + .Select(_ => RandomLocalDateTime())); } [RequireServerFact("3.4.0", GreaterThanOrEqualTo)] @@ -373,7 +374,7 @@ public async Task ShouldSendAndReceiveArrayOfLocalTime() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomLocalTime())); + .Select(_ => RandomLocalTime())); } [RequireServerFact("3.4.0", GreaterThanOrEqualTo)] @@ -381,7 +382,7 @@ public async Task ShouldSendAndReceiveArrayOfOffsetTime() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomOffsetTime())); + .Select(_ => RandomOffsetTime())); } [RequireServerFact("3.4.0", "4.3.0", Between)] @@ -389,7 +390,7 @@ public async Task ShouldSendAndReceiveArrayOfOffsetDateTime() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomOffsetDateTime())); + .Select(_ => RandomOffsetDateTime())); } [RequireServerFact("3.4.0", "4.3.0", Between)] @@ -397,7 +398,7 @@ public async Task ShouldSendAndReceiveArrayOfZonedDateTime() { await TestSendAndReceiveArray( Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomZonedDateTime())); + .Select(_ => RandomZonedDateTime())); } #endregion @@ -540,7 +541,7 @@ public async Task ShouldSendAndReceiveSystemTimeSpanNanoseconds() public async Task ShouldSendAndReceiveArrayOfSystemDateTime() { var array = Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomSystemDateTime()) + .Select(_ => RandomSystemDateTime()) .ToList(); var actual = array.Select(v => new LocalDateTime(v)).ToList(); @@ -552,7 +553,7 @@ public async Task ShouldSendAndReceiveArrayOfSystemDateTime() public async Task ShouldSendAndReceiveArrayOfSystemDateTimeOffset() { var array = Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomSystemDateTimeOffset()) + .Select(_ => RandomSystemDateTimeOffset()) .ToList(); var actual = array.Select(v => new ZonedDateTime(v)).ToList(); @@ -564,7 +565,7 @@ public async Task ShouldSendAndReceiveArrayOfSystemDateTimeOffset() public async Task ShouldSendAndReceiveArrayOfSystemTimeSpan() { var array = Enumerable.Range(0, _random.Next(MinArrayLength, MaxArrayLength)) - .Select(i => RandomSystemTime()) + .Select(_ => RandomSystemTime()) .ToList(); var actual = array.Select(v => new LocalTime(v)).ToList(); diff --git a/Neo4j.Driver/Neo4j.Driver/AuthTokens.cs b/Neo4j.Driver/Neo4j.Driver/AuthTokens.cs index b8e31b613..b06c0a29d 100644 --- a/Neo4j.Driver/Neo4j.Driver/AuthTokens.cs +++ b/Neo4j.Driver/Neo4j.Driver/AuthTokens.cs @@ -177,7 +177,7 @@ public static IAuthToken Custom( /// /// /// + /// cref="GraphDatabase.Driver(string, IAuthToken, System.Action{Neo4j.Driver.ConfigBuilder})"/> /// /// Base64 encoded token /// An authentication token that can be used to connect to Neo4j. diff --git a/Neo4j.Driver/Neo4j.Driver/Experimental/FluentQueries/ExecutableQuery.cs b/Neo4j.Driver/Neo4j.Driver/Experimental/FluentQueries/ExecutableQuery.cs index ee3fdee40..aeddbe638 100644 --- a/Neo4j.Driver/Neo4j.Driver/Experimental/FluentQueries/ExecutableQuery.cs +++ b/Neo4j.Driver/Neo4j.Driver/Experimental/FluentQueries/ExecutableQuery.cs @@ -87,9 +87,9 @@ public static ExecutableQuery> GetDefault(IInternalDriver return new ExecutableQuery>(new Query(cypher), driver, null, ToListAsync); } - private static async ValueTask> ToListAsync(IAsyncEnumerable enumerable) + private static async ValueTask> ToListAsync(IAsyncEnumerable enumerable) { - var result = new List(); + var result = new List(); await foreach (var item in enumerable) { result.Add(item); diff --git a/Neo4j.Driver/Neo4j.Driver/IResultCursor.cs b/Neo4j.Driver/Neo4j.Driver/IResultCursor.cs index fe2e0b6ff..20ccd1207 100644 --- a/Neo4j.Driver/Neo4j.Driver/IResultCursor.cs +++ b/Neo4j.Driver/Neo4j.Driver/IResultCursor.cs @@ -25,7 +25,7 @@ namespace Neo4j.Driver; /// Provides access to the result as an asynchronous stream of s. The records in the result /// is lazily retrieved and could only be visited once in a sequential order. /// -/// Calling will enumerate the entire stream. +/// Calling will enumerate the entire stream. public interface IResultCursor : IAsyncEnumerable { /// Returns the current record that has already been read via . @@ -52,7 +52,7 @@ public interface IResultCursor : IAsyncEnumerable /// Asynchronously gets the after streaming the whole records to the client. If the /// records in the result are not fully consumed, then calling this method will discard all remaining records to yield the /// summary. If you want to obtain the summary without discarding the records, consider buffering the unconsumed result - /// using . If all records in the records stream are already consumed, then + /// using . If all records in the records stream are already consumed, then /// this method will return the summary directly. /// /// A task returning the result summary of the running query. diff --git a/Neo4j.Driver/Neo4j.Driver/Internal/AsyncSessionResourceManager.cs b/Neo4j.Driver/Neo4j.Driver/Internal/AsyncSessionResourceManager.cs index fed3b91a1..d0eed1341 100644 --- a/Neo4j.Driver/Neo4j.Driver/Internal/AsyncSessionResourceManager.cs +++ b/Neo4j.Driver/Neo4j.Driver/Internal/AsyncSessionResourceManager.cs @@ -28,6 +28,7 @@ internal partial class AsyncSession : IResultResourceHandler, ITransactionResour { /// Only set the bookmark to a new value if the new value is not null /// The new bookmarks. + /// public void UpdateBookmarks(Bookmarks bookmarks, IDatabaseInfo dbInfo = null) { _initialBookmarks = null; diff --git a/Neo4j.Driver/Neo4j.Driver/Neo4jException.cs b/Neo4j.Driver/Neo4j.Driver/Neo4jException.cs index 2496e7609..d5e3fb37e 100644 --- a/Neo4j.Driver/Neo4j.Driver/Neo4jException.cs +++ b/Neo4j.Driver/Neo4j.Driver/Neo4jException.cs @@ -141,6 +141,7 @@ public TransientException(string code, string message, Exception innerException) { } + /// public override bool IsRetriable => true; } @@ -196,6 +197,7 @@ public ServiceUnavailableException(string message, Exception innerException) : b { } + /// public override bool IsRetriable => true; } @@ -220,6 +222,7 @@ public SessionExpiredException(string message, Exception innerException) : base( { } + /// public override bool IsRetriable => true; } @@ -243,6 +246,7 @@ public ConnectionReadTimeoutException(string message, Exception innerException) { } + /// public override bool IsRetriable => true; } @@ -342,6 +346,7 @@ public AuthorizationException(string message) : base(ErrorCode, message) { } + /// public override bool IsRetriable => true; internal static bool IsAuthorizationError(string code) diff --git a/Neo4j.Driver/Neo4j.Driver/SessionConfig.cs b/Neo4j.Driver/Neo4j.Driver/SessionConfig.cs index d626c8c71..51c042b33 100644 --- a/Neo4j.Driver/Neo4j.Driver/SessionConfig.cs +++ b/Neo4j.Driver/Neo4j.Driver/SessionConfig.cs @@ -85,10 +85,10 @@ internal SessionConfig() /// /// The default access mode set is overriden when transaction functions (i.e. /// + /// cref="IAsyncSession.ExecuteReadAsync{T}(System.Func{Neo4j.Driver.IAsyncQueryRunner,System.Threading.Tasks.Task{T}}, System.Action{TransactionConfigBuilder})"/> /// and /// + /// cref="IAsyncSession.ExecuteWriteAsync{T}(System.Func{Neo4j.Driver.IAsyncQueryRunner,System.Threading.Tasks.Task{T}}, System.Action{TransactionConfigBuilder})"/> /// is used (with corresponding access modes derived from invoked method name). /// /// @@ -214,7 +214,7 @@ public SessionConfigBuilder WithDefaultAccessMode(AccessMode defaultAccessMode) } /// Sets the initial bookmarks to be used by the constructed session. - /// the initial bookmarks + /// the initial bookmarks /// this instance /// [Obsolete("Replaced by WithBookmarks. Will be removed in 6.0.")]