Exemplo n.º 1
0
        public async Task CancelAsyncHard()
        {
            if (IsMultiplexing)
            {
                return; // Multiplexing, cancellation
            }
            await using var postmasterMock = PgPostmasterMock.Start(ConnectionString);
            using var _          = CreateTempPool(postmasterMock.ConnectionString, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            await postmasterMock.WaitForServerConnection();

            var processId = conn.ProcessID;

            var cancellationSource = new CancellationTokenSource();

            using var cmd = new NpgsqlCommand("SELECT 1", conn);
            var t = cmd.ExecuteScalarAsync(cancellationSource.Token);

            cancellationSource.Cancel();

            var exception = Assert.ThrowsAsync <OperationCanceledException>(async() => await t);

            Assert.That(exception.InnerException, Is.TypeOf <TimeoutException>());
            Assert.That(exception.CancellationToken, Is.EqualTo(cancellationSource.Token));

            Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Broken));
            Assert.That((await postmasterMock.WaitForCancellationRequest()).ProcessId,
                        Is.EqualTo(processId));
        }
Exemplo n.º 2
0
        public async Task SavepointPrepends()
        {
            await using var postmasterMock = PgPostmasterMock.Start(ConnectionString);
            using var _          = CreateTempPool(postmasterMock.ConnectionString, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            var pgMock = await postmasterMock.WaitForServerConnection();

            using var tx = conn.BeginTransaction();
            var saveTask = tx.SaveAsync("foo");

            Assert.That(saveTask.Status, Is.EqualTo(TaskStatus.RanToCompletion));

            // If we're here, SaveAsync above didn't wait for any response, which is the right behavior

            await pgMock
            .WriteCommandComplete()
            .WriteReadyForQuery()     // BEGIN response
            .WriteCommandComplete()
            .WriteReadyForQuery()     // SAVEPOINT response
            .WriteScalarResponseAndFlush(1);

            await conn.ExecuteScalarAsync("SELECT 1");

            await pgMock.ExpectSimpleQuery("BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED");

            await pgMock.ExpectSimpleQuery("SAVEPOINT foo");

            await pgMock.ExpectExtendedQuery();
        }
Exemplo n.º 3
0
        public async Task TimeoutAsyncHard()
        {
            if (IsMultiplexing)
            {
                return; // Multiplexing, Timeout
            }
            var builder = new NpgsqlConnectionStringBuilder(ConnectionString)
            {
                CommandTimeout = 1
            };

            await using var postmasterMock = PgPostmasterMock.Start(builder.ConnectionString);
            using var _          = CreateTempPool(postmasterMock.ConnectionString, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            await postmasterMock.WaitForServerConnection();

            var processId = conn.ProcessID;

            Assert.That(async() => await conn.ExecuteScalarAsync("SELECT 1"),
                        Throws.Exception
                        .TypeOf <NpgsqlException>()
                        .With.InnerException.TypeOf <TimeoutException>());

            Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Broken));
            Assert.That((await postmasterMock.WaitForCancellationRequest()).ProcessId,
                        Is.EqualTo(processId));
        }
Exemplo n.º 4
0
        public async Task CancelAsyncHard()
        {
            if (IsMultiplexing)
            {
                return; // Multiplexing, cancellation
            }
            await using var postmasterMock = new PgPostmasterMock(ConnectionString);
            using var _          = CreateTempPool(postmasterMock.ConnectionString, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            var processId = conn.ProcessID;

            var cancellationSource = new CancellationTokenSource();

            using var cmd = new NpgsqlCommand("SELECT 1", conn);
            var t = cmd.ExecuteScalarAsync(cancellationSource.Token);

            cancellationSource.Cancel();
            Assert.That(async() => await t, Throws.Exception
                        .TypeOf <OperationCanceledException>()
                        .With.InnerException.Null);

            Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Broken));
            Assert.That(postmasterMock.GetPendingCancellationRequest().ProcessId,
                        Is.EqualTo(processId));
        }
Exemplo n.º 5
0
        public async Task Bug3466([Values(false, true)] bool isBroken)
        {
            if (IsMultiplexing)
            {
                return; // Multiplexing, cancellation
            }
            var csb = new NpgsqlConnectionStringBuilder(ConnectionString)
            {
                Pooling = false,
            };

            await using var postmasterMock = PgPostmasterMock.Start(csb.ToString(), completeCancellationImmediately: false);
            using var _          = CreateTempPool(postmasterMock.ConnectionString, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            var serverMock = await postmasterMock.WaitForServerConnection();

            var processId = conn.ProcessID;

            using var cancellationSource = new CancellationTokenSource();
            using var cmd = new NpgsqlCommand("SELECT 1", conn)
                  {
                      CommandTimeout = 3
                  };
            var t = Task.Run(() => cmd.ExecuteScalar());

            // We have to be sure the command's state is InProgress, otherwise the cancellation request will never be sent
            cmd.WaitUntilCommandIsInProgress();
            // Perform cancellation, which will block on the server side
            var cancelTask = Task.Run(() => cmd.Cancel());
            // Note what we have to wait for the cancellation request, otherwise the connection might be closed concurrently
            // and the cancellation request is never send
            var cancellationRequest = await postmasterMock.WaitForCancellationRequest();

            if (isBroken)
            {
                Assert.ThrowsAsync <OperationCanceledException>(async() => await t);
                Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Broken));
            }
            else
            {
                await serverMock
                .WriteParseComplete()
                .WriteBindComplete()
                .WriteRowDescription(new FieldDescription(PostgresTypeOIDs.Int4))
                .WriteDataRow(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(1)))
                .WriteCommandComplete()
                .WriteReadyForQuery()
                .FlushAsync();

                Assert.DoesNotThrowAsync(async() => await t);
                Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Open));
                await conn.CloseAsync();
            }

            // Release the cancellation at the server side, and make sure it completes without an exception
            cancellationRequest.Complete();
            Assert.DoesNotThrowAsync(async() => await cancelTask);
        }
Exemplo n.º 6
0
        public async Task Connect_to_correct_host_with_available_idle(
            string targetSessionAttributes, MockState[] servers, int expectedServer)
        {
            var postmasters = servers.Select(s => PgPostmasterMock.Start(state: s)).ToArray();

            await using var __ = new DisposableWrapper(postmasters);

            // First, open and close a connection with the TargetSessionAttributes matching the first server.
            // This ensures wew have an idle connection in the pool.
            var connectionStringBuilder = new NpgsqlConnectionStringBuilder
            {
                Host = MultipleHosts(postmasters),
                TargetSessionAttributes = servers[0] switch
                {
                    Primary => "read-write",
                    PrimaryReadOnly => "read-only",
                    Standby => "standby",
                    _ => throw new ArgumentOutOfRangeException()
                },
Exemplo n.º 7
0
        public async Task Bug3509()
        {
            if (IsMultiplexing)
            {
                return;
            }

            var csb = new NpgsqlConnectionStringBuilder(ConnectionString)
            {
                KeepAlive = 1,
            };

            await using var postmasterMock = PgPostmasterMock.Start(csb.ToString());
            using var _          = CreateTempPool(postmasterMock.ConnectionString, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            var serverMock = await postmasterMock.WaitForServerConnection();

            // Wait for a keepalive to arrive at the server, reply with an error
            await serverMock.WaitForData();

            var queryTask = Task.Run(async() => await conn.ExecuteNonQueryAsync("SELECT 1"));
            // TODO: kind of flaky - think of the way to rewrite
            // giving a queryTask some time to get stuck on a lock
            await Task.Delay(100);

            await serverMock
            .WriteErrorResponse("42")
            .WriteReadyForQuery()
            .FlushAsync();

            await serverMock
            .WriteScalarResponseAndFlush(1);

            var ex = Assert.ThrowsAsync <NpgsqlException>(async() => await queryTask) !;

            Assert.That(ex.InnerException, Is.TypeOf <NpgsqlException>()
                        .With.InnerException.TypeOf <PostgresException>());
        }
Exemplo n.º 8
0
        public async Task Connect_to_correct_host(string targetSessionAttributes, MockState[] servers, int expectedServer)
        {
            var postmasters = servers.Select(s => PgPostmasterMock.Start(state: s)).ToArray();

            await using var __ = new DisposableWrapper(postmasters);

            var connectionStringBuilder = new NpgsqlConnectionStringBuilder
            {
                Host = MultipleHosts(postmasters),
                TargetSessionAttributes = targetSessionAttributes,
                ServerCompatibilityMode = ServerCompatibilityMode.NoTypeLoading,
            };

            using var pool       = CreateTempPool(connectionStringBuilder, out var connectionString);
            await using var conn = await OpenConnectionAsync(connectionString);

            Assert.That(conn.Port, Is.EqualTo(postmasters[expectedServer].Port));

            for (var i = 0; i <= expectedServer; i++)
            {
                _ = await postmasters[i].WaitForServerConnection();
            }
        }