diff --git a/test/Core.Tests/Debugging/DefaultDebugGremlinQuerySerializationTest.cs b/test/Core.Tests/Debugging/DefaultDebugGremlinQuerySerializationTest.cs index 65eab20c9b..556adcc77b 100644 --- a/test/Core.Tests/Debugging/DefaultDebugGremlinQuerySerializationTest.cs +++ b/test/Core.Tests/Debugging/DefaultDebugGremlinQuerySerializationTest.cs @@ -4,10 +4,10 @@ namespace ExRam.Gremlinq.Core.Tests { - public sealed class DefaultDebugGremlinQuerySerializationTest : QueryExecutionTest + public sealed class DefaultDebugGremlinQuerySerializationTest : QueryExecutionTest, IClassFixture { - public DefaultDebugGremlinQuerySerializationTest(ITestOutputHelper testOutputHelper) : base( - GremlinqFixture.Empty, + public DefaultDebugGremlinQuerySerializationTest(GremlinqFixture fixture, ITestOutputHelper testOutputHelper) : base( + fixture, new DebugGremlinQueryVerifier(), testOutputHelper) { diff --git a/test/Core.Tests/Serialization/BytecodeQuerySerializationTest.cs b/test/Core.Tests/Serialization/BytecodeQuerySerializationTest.cs index f1bf8573f0..0b7c6f209d 100644 --- a/test/Core.Tests/Serialization/BytecodeQuerySerializationTest.cs +++ b/test/Core.Tests/Serialization/BytecodeQuerySerializationTest.cs @@ -5,9 +5,9 @@ namespace ExRam.Gremlinq.Core.Tests { - public sealed class BytecodeQuerySerializationTest : QueryExecutionTest + public sealed class BytecodeQuerySerializationTest : QueryExecutionTest, IClassFixture { - public BytecodeQuerySerializationTest(ITestOutputHelper testOutputHelper) : base(GremlinqFixture.Empty, new SerializingVerifier(), testOutputHelper) + public BytecodeQuerySerializationTest(GremlinqFixture fixture, ITestOutputHelper testOutputHelper) : base(fixture, new SerializingVerifier(), testOutputHelper) { } } diff --git a/test/Core.Tests/Serialization/Graphson2GremlinQuerySerializationTest.cs b/test/Core.Tests/Serialization/Graphson2GremlinQuerySerializationTest.cs index 2e5a9b22f4..ce56c7b406 100644 --- a/test/Core.Tests/Serialization/Graphson2GremlinQuerySerializationTest.cs +++ b/test/Core.Tests/Serialization/Graphson2GremlinQuerySerializationTest.cs @@ -4,12 +4,12 @@ namespace ExRam.Gremlinq.Core.Tests { - public sealed class Graphson2GremlinQuerySerializationTest : QueryExecutionTest + public sealed class Graphson2GremlinQuerySerializationTest : QueryExecutionTest, IClassFixture { private static readonly GraphSON2Writer GraphSon2Writer = new (); - public Graphson2GremlinQuerySerializationTest(ITestOutputHelper testOutputHelper) : base( - GremlinqFixture.Empty, + public Graphson2GremlinQuerySerializationTest(GremlinqFixture fixture, ITestOutputHelper testOutputHelper) : base( + fixture, new GraphSonStringSerializingVerifier(GraphSon2Writer), testOutputHelper) { diff --git a/test/Core.Tests/Serialization/Graphson3GremlinQuerySerializationTest.cs b/test/Core.Tests/Serialization/Graphson3GremlinQuerySerializationTest.cs index a9b0d8ac62..beb16fc765 100644 --- a/test/Core.Tests/Serialization/Graphson3GremlinQuerySerializationTest.cs +++ b/test/Core.Tests/Serialization/Graphson3GremlinQuerySerializationTest.cs @@ -4,12 +4,12 @@ namespace ExRam.Gremlinq.Core.Tests { - public sealed class Graphson3GremlinQuerySerializationTest : QueryExecutionTest + public sealed class Graphson3GremlinQuerySerializationTest : QueryExecutionTest, IClassFixture { private static readonly GraphSON3Writer GraphSon3Writer = new (); - public Graphson3GremlinQuerySerializationTest(ITestOutputHelper testOutputHelper) : base( - GremlinqFixture.Empty, + public Graphson3GremlinQuerySerializationTest(GremlinqFixture fixture, ITestOutputHelper testOutputHelper) : base( + fixture, new GraphSonStringSerializingVerifier(GraphSon3Writer), testOutputHelper) { diff --git a/test/Core.Tests/Serialization/Graphson3WithGroovyGremlinQuerySerializationTest.cs b/test/Core.Tests/Serialization/Graphson3WithGroovyGremlinQuerySerializationTest.cs index 4eda8448a0..1de9d720ee 100644 --- a/test/Core.Tests/Serialization/Graphson3WithGroovyGremlinQuerySerializationTest.cs +++ b/test/Core.Tests/Serialization/Graphson3WithGroovyGremlinQuerySerializationTest.cs @@ -4,12 +4,12 @@ namespace ExRam.Gremlinq.Core.Tests { - public sealed class Graphson3WithGroovyGremlinQuerySerializationTest : QueryExecutionTest + public sealed class Graphson3WithGroovyGremlinQuerySerializationTest : QueryExecutionTest, IClassFixture { private static readonly GraphSON3Writer GraphSon3Writer = new(); - public Graphson3WithGroovyGremlinQuerySerializationTest(ITestOutputHelper testOutputHelper) : base( - new GroovyGremlinQuerySerializationFixture(), + public Graphson3WithGroovyGremlinQuerySerializationTest(GroovyGremlinQuerySerializationFixture fixture, ITestOutputHelper testOutputHelper) : base( + fixture, new GraphSonStringSerializingVerifier(GraphSon3Writer), testOutputHelper) { diff --git a/test/Core.Tests/Serialization/OuterProjectionTest.cs b/test/Core.Tests/Serialization/OuterProjectionTest.cs index 11d212e0bc..0c6947effc 100644 --- a/test/Core.Tests/Serialization/OuterProjectionTest.cs +++ b/test/Core.Tests/Serialization/OuterProjectionTest.cs @@ -5,7 +5,7 @@ namespace ExRam.Gremlinq.Core.Tests { - public sealed class OuterProjectionTest : QueryExecutionTest + public sealed class OuterProjectionTest : QueryExecutionTest, IClassFixture { private sealed class ProjectionVerifier : GremlinQueryVerifier { @@ -16,7 +16,7 @@ public ProjectionVerifier(Func? settingsTaskModifier public override SettingsTask Verify(IGremlinQueryBase query) => InnerVerify(query.ToTraversal().Projection.ToTraversal(query.AsAdmin().Environment).Steps.ToArray()); } - public OuterProjectionTest(ITestOutputHelper testOutputHelper) : base(GremlinqFixture.Empty, new ProjectionVerifier(), testOutputHelper) + public OuterProjectionTest(GremlinqFixture fixture, ITestOutputHelper testOutputHelper) : base(fixture, new ProjectionVerifier(), testOutputHelper) { } } diff --git a/test/Providers.CosmosDb.Tests/NoPasswordIntegrationTests.cs b/test/Providers.CosmosDb.Tests/NoPasswordIntegrationTests.cs index de9c67f6b1..d91b31e66c 100644 --- a/test/Providers.CosmosDb.Tests/NoPasswordIntegrationTests.cs +++ b/test/Providers.CosmosDb.Tests/NoPasswordIntegrationTests.cs @@ -32,7 +32,7 @@ protected override async Task TransformQuerySource(IGremlin public NoPasswordIntegrationTests(NoPasswordFixture fixture) : base(new JTokenExecutingVerifier()) { - _g = fixture.GremlinQuerySource.Result; + _g = fixture.G; } [Fact(Skip = "CosmosDb often seems to close the connection right after an Authenticate status.")] diff --git a/test/Providers.GremlinServer.Tests/WrongPasswordIntegrationTests.cs b/test/Providers.GremlinServer.Tests/WrongPasswordIntegrationTests.cs index 95318847c6..7879cd5325 100644 --- a/test/Providers.GremlinServer.Tests/WrongPasswordIntegrationTests.cs +++ b/test/Providers.GremlinServer.Tests/WrongPasswordIntegrationTests.cs @@ -36,7 +36,7 @@ protected override async Task TransformQuerySource(IContain public WrongPasswordIntegrationTests(WrongPasswordGremlinServerContainerFixture fixture) : base(new JTokenExecutingVerifier()) { - _g = fixture.GremlinQuerySource.Result; + _g = fixture.G; } [Fact] diff --git a/test/Tests.Fixtures/GremlinqFixture.cs b/test/Tests.Fixtures/GremlinqFixture.cs index 1cbc5a801d..6476890889 100644 --- a/test/Tests.Fixtures/GremlinqFixture.cs +++ b/test/Tests.Fixtures/GremlinqFixture.cs @@ -6,74 +6,33 @@ namespace ExRam.Gremlinq.Tests.Fixtures { - public abstract class GremlinqFixture : IAsyncLifetime + public class GremlinqFixture : IAsyncLifetime { - private sealed class EmptyGremlinqTestFixture : GremlinqFixture - { - protected override async Task TransformQuerySource(IGremlinQuerySource g) => g; - } + private IGremlinQuerySource? _g; - public static readonly GremlinqFixture Empty = new EmptyGremlinqTestFixture(); + protected virtual async Task TransformQuerySource(IGremlinQuerySource g) => g; - private static readonly TaskCompletionSource Disposed = new (); - private TaskCompletionSource? _lazyQuerySource; - - static GremlinqFixture() + public virtual async Task InitializeAsync() { - Disposed.TrySetException(new ObjectDisposedException(nameof(GremlinqFixture))); + _g = await TransformQuerySource(g + .ConfigureEnvironment(env => env + .ConfigureOptions(options => options + .SetValue(GremlinqOption.StringComparisonTranslationStrictness, + StringComparisonTranslationStrictness.Lenient)))); + + _g = _g + .ConfigureEnvironment(env => env + .ConfigureModel(model => model == GraphModel.Invalid + ? GraphModel.FromBaseTypes() + : model)); } - protected abstract Task TransformQuerySource(IGremlinQuerySource g); - - public Task GremlinQuerySource => GetGremlinQuerySource(); - - private async Task GetGremlinQuerySource() + public virtual async Task DisposeAsync() { - if (Volatile.Read(ref _lazyQuerySource) is { } tcs) - return await tcs.Task; - - var newTcs = new TaskCompletionSource(); - - if (Interlocked.CompareExchange(ref _lazyQuerySource, newTcs, null) == null) - { - try - { - var g1 = await TransformQuerySource(g - .ConfigureEnvironment(env => env - .ConfigureOptions(options => options - .SetValue(GremlinqOption.StringComparisonTranslationStrictness, StringComparisonTranslationStrictness.Lenient)))); - - newTcs.TrySetResult(g1 - .ConfigureEnvironment(env => env - .ConfigureModel(model => model == GraphModel.Invalid - ? GraphModel.FromBaseTypes() - : model))); - } - catch (Exception ex) - { - newTcs.TrySetException(ex); - - Interlocked.CompareExchange(ref _lazyQuerySource, null, newTcs); - } - - return await newTcs.Task; - } - else - return await GetGremlinQuerySource(); + if (_g is IAsyncDisposable disposable) + await disposable.DisposeAsync(); } - public async Task InitializeAsync() - { - - } - - public async Task DisposeAsync() - { - if (Interlocked.Exchange(ref _lazyQuerySource, Disposed) is { } tcs && tcs != Disposed) - { - if (await tcs.Task is IAsyncDisposable disposable) - await disposable.DisposeAsync(); - } - } + public IGremlinQuerySource G => _g ?? throw new InvalidOperationException(); } } diff --git a/test/Tests.Fixtures/QueryExecutionTest.cs b/test/Tests.Fixtures/QueryExecutionTest.cs index 29af2ace52..c1f0d695ad 100644 --- a/test/Tests.Fixtures/QueryExecutionTest.cs +++ b/test/Tests.Fixtures/QueryExecutionTest.cs @@ -18,17 +18,13 @@ public abstract class QueryExecutionTest : GremlinqTestBase { private static readonly string Id = "id"; - private readonly Lazy _lazyGremlinQuerySource; + protected readonly IGremlinQuerySource _g; protected QueryExecutionTest(GremlinqFixture fixture, GremlinQueryVerifier verifier, ITestOutputHelper testOutputHelper) : base(verifier) { - _lazyGremlinQuerySource = new Lazy( - () => fixture.GremlinQuerySource.Result, - LazyThreadSafetyMode.PublicationOnly); + _g = fixture.G; } - protected IGremlinQuerySource _g => _lazyGremlinQuerySource.Value; - [Fact] public virtual Task AddE_from_StepLabel() => _g .AddV(new Country { CountryCallingCode = "+49" }) diff --git a/test/Tests.Fixtures/TestContainerFixture.cs b/test/Tests.Fixtures/TestContainerFixture.cs index 2411f5d93a..b18d7e4df7 100644 --- a/test/Tests.Fixtures/TestContainerFixture.cs +++ b/test/Tests.Fixtures/TestContainerFixture.cs @@ -105,12 +105,22 @@ async ValueTask IAsyncDisposable.DisposeAsync() private readonly int _port; + private IContainer? _container; + protected TestContainerFixtureBase(int port = 8182) { _port = port; } - protected override sealed async Task TransformQuerySource(IGremlinQuerySource g) + protected sealed override async Task TransformQuerySource(IGremlinQuerySource g) + { + if (_container is { } container) + return await TransformQuerySource(_container, new ContainerAttachedGremlinQuerySource(container, g)); + + throw new InvalidOperationException(); + } + + public override async Task InitializeAsync() { var containerBuilder = new ContainerBuilder() .WithImage(await GetImage()) @@ -119,13 +129,21 @@ protected override sealed async Task TransformQuerySource(I .ForUnixContainer() .UntilPortIsAvailable(_port)); - var container = CustomizeContainer(containerBuilder) + _container = CustomizeContainer(containerBuilder) .Build(); - await container + await _container .StartAsync(); - return await TransformQuerySource(container, new ContainerAttachedGremlinQuerySource(container, g)); + await base.InitializeAsync(); + } + + public override async Task DisposeAsync() + { + if (_container is { } container) + await container.StopAsync(); + + await base.DisposeAsync(); } protected abstract Task GetImage();