Skip to content

Commit 63fbe1f

Browse files
committed
test: connections failing auth are not added to the connection pool
1 parent 2bba929 commit 63fbe1f

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2836,5 +2836,5 @@ Running Slonik tests requires having a local PostgreSQL instance.
28362836
The easiest way to setup a temporary instance for testing is using Docker, e.g.
28372837
28382838
```bash
2839-
docker run --name slonik-test --rm -it -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 postgres -N 1000
2839+
docker run --name slonik-test --rm -it -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres -N 1000
28402840
```

packages/slonik/src/helpers.test/createIntegrationTests.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
InputSyntaxError,
1414
InvalidInputError,
1515
NotNullIntegrityConstraintViolationError,
16+
parseDsn,
1617
sql,
1718
StatementCancelledError,
1819
StatementTimeoutError,
@@ -24,6 +25,7 @@ import {
2425
import { type TestContextType } from './createTestRunner';
2526
import { type DriverFactory } from '@slonik/driver';
2627
import { type TestFn } from 'ava';
28+
import { randomUUID } from 'node:crypto';
2729
import { setTimeout as delay } from 'node:timers/promises';
2830
import * as sinon from 'sinon';
2931
import { z } from 'zod';
@@ -2110,6 +2112,81 @@ export const createIntegrationTests = (
21102112
await pool.end();
21112113
});
21122114

2115+
test('connections failing auth are not added to the connection pool', async (t) => {
2116+
const superPool = await createPool(t.context.dsn, {
2117+
driverFactory,
2118+
maximumPoolSize: 1,
2119+
});
2120+
2121+
const connection = parseDsn(t.context.dsn);
2122+
2123+
const testUser = `auth_change_test_${randomUUID().split('-')[0]}`;
2124+
2125+
await superPool.query(
2126+
sql.unsafe`
2127+
CREATE ROLE ${sql.identifier([testUser])}
2128+
WITH LOGIN SUPERUSER
2129+
PASSWORD 'auth_change_test'
2130+
`,
2131+
);
2132+
2133+
// Connect as the new role
2134+
const pool = await createPool(
2135+
`postgres://${testUser}:auth_change_test@${connection.host}:${connection.port}/${connection.databaseName}`,
2136+
{
2137+
driverFactory,
2138+
idleTimeout: 1_000,
2139+
maximumPoolSize: 1,
2140+
},
2141+
);
2142+
2143+
await pool.oneFirst(sql.unsafe`
2144+
SELECT pg_backend_pid();
2145+
`);
2146+
2147+
// Change the password
2148+
await superPool.query(
2149+
sql.unsafe`
2150+
ALTER ROLE ${sql.identifier([testUser])}
2151+
PASSWORD 'auth_change_test_changed'
2152+
`,
2153+
);
2154+
2155+
// Wait for the idle timeout to expire
2156+
await delay(1_000);
2157+
2158+
// Ensure that there are no longer active connections.
2159+
t.like(pool.state(), {
2160+
acquiredConnections: 0,
2161+
idleConnections: 0,
2162+
pendingDestroyConnections: 0,
2163+
pendingReleaseConnections: 0,
2164+
waitingClients: 0,
2165+
});
2166+
2167+
const error = await t.throwsAsync(
2168+
pool.oneFirst(sql.unsafe`
2169+
SELECT pg_backend_pid();
2170+
`),
2171+
);
2172+
2173+
// @ts-expect-error TODO
2174+
t.is(error.cause.code, '28P01');
2175+
2176+
// Ensure that the connection was not added to the pool.
2177+
t.like(pool.state(), {
2178+
acquiredConnections: 0,
2179+
idleConnections: 0,
2180+
pendingDestroyConnections: 0,
2181+
pendingReleaseConnections: 0,
2182+
waitingClients: 0,
2183+
});
2184+
2185+
await pool.end();
2186+
2187+
await superPool.end();
2188+
});
2189+
21132190
test('retains a minimum number of connections in the pool', async (t) => {
21142191
const pool = await createPool(t.context.dsn, {
21152192
driverFactory,

0 commit comments

Comments
 (0)