@zukhruf/testing 0.3.42 → 0.3.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/databases/clickhouse.d.ts.map +1 -1
- package/dist/databases/clickhouse.js +5 -1
- package/dist/databases/clickhouse.js.map +1 -1
- package/dist/databases/collector.d.ts +34 -0
- package/dist/databases/collector.d.ts.map +1 -0
- package/dist/databases/collector.js +20 -0
- package/dist/databases/collector.js.map +1 -0
- package/dist/databases/mariadb.d.ts +1 -2
- package/dist/databases/mariadb.d.ts.map +1 -1
- package/dist/databases/mariadb.js +2 -2
- package/dist/databases/mariadb.js.map +1 -1
- package/dist/databases/mysql-family-collector.d.ts +16 -0
- package/dist/databases/mysql-family-collector.d.ts.map +1 -0
- package/dist/databases/mysql-family-collector.js +36 -0
- package/dist/databases/mysql-family-collector.js.map +1 -0
- package/dist/databases/mysql-family-server.d.ts +5 -3
- package/dist/databases/mysql-family-server.d.ts.map +1 -1
- package/dist/databases/mysql-family-server.js +22 -15
- package/dist/databases/mysql-family-server.js.map +1 -1
- package/dist/databases/mysql.d.ts +1 -1
- package/dist/databases/mysql.d.ts.map +1 -1
- package/dist/databases/mysql.js +2 -1
- package/dist/databases/mysql.js.map +1 -1
- package/dist/databases/postgres-collector.d.ts +9 -0
- package/dist/databases/postgres-collector.d.ts.map +1 -0
- package/dist/databases/postgres-collector.js +28 -0
- package/dist/databases/postgres-collector.js.map +1 -0
- package/dist/databases/postgres.d.ts.map +1 -1
- package/dist/databases/postgres.js +13 -8
- package/dist/databases/postgres.js.map +1 -1
- package/dist/databases/sqlserver-collector.d.ts +13 -0
- package/dist/databases/sqlserver-collector.d.ts.map +1 -0
- package/dist/databases/sqlserver-collector.js +42 -0
- package/dist/databases/sqlserver-collector.js.map +1 -0
- package/dist/databases/sqlserver.d.ts.map +1 -1
- package/dist/databases/sqlserver.js +15 -20
- package/dist/databases/sqlserver.js.map +1 -1
- package/dist/databases/succeeded.d.ts +3 -3
- package/dist/databases/succeeded.d.ts.map +1 -1
- package/dist/databases/succeeded.js +2 -2
- package/dist/databases/succeeded.js.map +1 -1
- package/dist/scripts/run-cleanup.d.ts.map +1 -1
- package/dist/scripts/run-cleanup.js +96 -0
- package/dist/scripts/run-cleanup.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -142,9 +142,9 @@ Then give the file to `node --test`. The value is a path relative to the working
|
|
|
142
142
|
node --test --test-force-exit --test-global-setup=src/testing/docker-global-setup.ts "src/**/*.test.ts"
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
The global setup sets `ZUKHRUF_TESTING_RUN_ID` and `ZUKHRUF_TESTING_RUN_DIR` for the test processes. A `DockerFixtures` reads them from its `environment` and labels what it creates with the run. It records SSH forwards and host directories in the run's directory. It also writes a process record for its test process, and for each SSH command that it starts, while that command runs. While it asks the engine to create a container, it writes a creating record.
|
|
145
|
+
The global setup sets `ZUKHRUF_TESTING_RUN_ID` and `ZUKHRUF_TESTING_RUN_DIR` for the test processes. A `DockerFixtures` reads them from its `environment` and labels what it creates with the run. It records SSH forwards and host directories in the run's directory. It also writes a process record for its test process, and for each SSH command that it starts, while that command runs. While it asks the engine to create a container, it writes a creating record. In a run, `database()` puts the run's id in the name of each database that it creates on a shared server: `test_<run id>_<16 hex>`.
|
|
146
146
|
|
|
147
|
-
The global teardown removes the labeled containers with their anonymous volumes, the labeled volumes and the recorded paths. It never removes shared servers. The teardown is synchronous, because Node does not wait for an asynchronous teardown under `--test-force-exit`. When every recorded process has ended, the teardown deletes the run's records. A recorded process that still runs can still create a container. The engine can also finish a create after the test process that sent it was killed. Then the teardown keeps the records, and a later run removes what is left after that process ends.
|
|
147
|
+
The global teardown removes the labeled containers with their anonymous volumes, the labeled volumes and the recorded paths. On each running shared server of `Postgres`, `Mysql`, `Mariadb` and `SqlServer`, it drops the databases whose name has the run's id ([ADR 0011](./docs/adr/0011-the-run-id-in-a-databases-name-is-its-owner-reference-and-one-collector-for-each-kind-drops-a-dead-runs-databases.md)). It skips a kind whose driver the project did not install. It never removes shared servers. The teardown is synchronous, because Node does not wait for an asynchronous teardown under `--test-force-exit`. When every recorded process has ended, the teardown deletes the run's records. A recorded process that still runs can still create a container. The engine can also finish a create after the test process that sent it was killed. Then the teardown keeps the records, and a later run removes what is left after that process ends.
|
|
148
148
|
|
|
149
149
|
If cleanup fails, for example because the engine is unreachable, the global teardown prints the error, keeps the run's records, and sets exit code 1. The next run on the same engine removes what the run left, from any project of this user. This is recovery. Recovery does not touch a run while its runner or one of its recorded processes lives. The records are in `$XDG_STATE_HOME/zukhruf-testing/docker-runs` (`~/.local/state/zukhruf-testing/docker-runs` by default). Do not delete a record to hide a cleanup failure.
|
|
150
150
|
|
|
@@ -156,7 +156,7 @@ To pass the run to another container API, spread `docker.defaults`: it holds the
|
|
|
156
156
|
|
|
157
157
|
## Databases
|
|
158
158
|
|
|
159
|
-
`Postgres`, `Mysql`, `Mariadb`, `SqlServer` and `ClickHouse` take the `environment`, such as `process.env`. The environment selects the engine and the run. Each instance makes its own `DockerFixtures` from it. Each `database()` call creates a fresh database on a shared server; disposal drops it. `start()` creates a dedicated server; disposal stops it.
|
|
159
|
+
`Postgres`, `Mysql`, `Mariadb`, `SqlServer` and `ClickHouse` take the `environment`, such as `process.env`. The environment selects the engine and the run. Each instance makes its own `DockerFixtures` from it. Each `database()` call creates a fresh database on a shared server; disposal drops it. In a run, the name of the database has the run's id. When a test process is killed before its disposal, or a drop in disposal fails, the global teardown drops the database (see [A killed run](#a-killed-run)). Outside a run, only disposal drops it. `start()` creates a dedicated server; disposal stops it.
|
|
160
160
|
|
|
161
161
|
```ts
|
|
162
162
|
import { Postgres } from '@zukhruf/testing/postgres';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/databases/clickhouse.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGvE,kFAAkF;AAClF,qBAAa,UAAU;;gBAIT,EACV,WAAW,EACX,KAAK,GACN,EAAE,qBAAqB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAK5C,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/databases/clickhouse.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGvE,kFAAkF;AAClF,qBAAa,UAAU;;gBAIT,EACV,WAAW,EACX,KAAK,GACN,EAAE,qBAAqB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAK5C,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAkBnC"}
|
|
@@ -15,7 +15,11 @@ export class ClickHouse {
|
|
|
15
15
|
internalPort: 8123,
|
|
16
16
|
memory: '2g',
|
|
17
17
|
env: { CLICKHOUSE_SKIP_USER_SETUP: '1' },
|
|
18
|
-
healthy: (service) => timebox(() => succeeded(service, [
|
|
18
|
+
healthy: (service) => timebox(() => succeeded(service.container, [
|
|
19
|
+
'clickhouse-client',
|
|
20
|
+
'--query',
|
|
21
|
+
'SELECT 1',
|
|
22
|
+
]), { maxRetryTime: 60_000 }),
|
|
19
23
|
});
|
|
20
24
|
}
|
|
21
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/databases/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,cAAc,GAEf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,kFAAkF;AAClF,MAAM,OAAO,UAAU;IACZ,OAAO,CAAiB;IACxB,MAAM,CAAS;IAExB,YAAY,EACV,WAAW,EACX,KAAK,GACqC;QAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACxB,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,IAAI;YACZ,GAAG,EAAE,EAAE,0BAA0B,EAAE,GAAG,EAAE;YACxC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CACnB,OAAO,CACL,GAAG,EAAE,CACH,SAAS,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/databases/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,cAAc,GAEf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,kFAAkF;AAClF,MAAM,OAAO,UAAU;IACZ,OAAO,CAAiB;IACxB,MAAM,CAAS;IAExB,YAAY,EACV,WAAW,EACX,KAAK,GACqC;QAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACxB,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,IAAI;YACZ,GAAG,EAAE,EAAE,0BAA0B,EAAE,GAAG,EAAE;YACxC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CACnB,OAAO,CACL,GAAG,EAAE,CACH,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE;gBAC3B,mBAAmB;gBACnB,SAAS;gBACT,UAAU;aACX,CAAC,EACJ,EAAE,YAAY,EAAE,MAAM,EAAE,CACzB;SACJ,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Container } from '@zukhruf/docker';
|
|
2
|
+
import type { DockerHost } from '../docker/host.ts';
|
|
3
|
+
import type { TestRun } from '../docker/test-run.ts';
|
|
4
|
+
/** The kind of a database fixture's shared server: it names the collector of the server. */
|
|
5
|
+
export declare const KIND_LABEL = "dev.zukhruf.testing.kind";
|
|
6
|
+
export type Kind = 'postgres' | 'mysql' | 'mariadb' | 'sqlserver';
|
|
7
|
+
/**
|
|
8
|
+
* The name of a database that `database()` creates. In a run, the name holds
|
|
9
|
+
* the run's id, its owner reference (ADR 0011).
|
|
10
|
+
*/
|
|
11
|
+
export declare const databaseName: (run: TestRun | undefined) => string;
|
|
12
|
+
/**
|
|
13
|
+
* The databases of one server kind: `list` gives the names of the server's
|
|
14
|
+
* test databases, and `drop` drops one. Disposal and the run's cleanup both
|
|
15
|
+
* drop with `drop`.
|
|
16
|
+
*/
|
|
17
|
+
export interface Collector<Server> {
|
|
18
|
+
readonly kind: Kind;
|
|
19
|
+
/**
|
|
20
|
+
* The running shared server `container`, with the credentials of
|
|
21
|
+
* `environment`, its `Config.Env`. Disposal closes what it opened.
|
|
22
|
+
*/
|
|
23
|
+
open(container: Container, environment: Record<string, string>, host: DockerHost): Promise<Server & AsyncDisposable>;
|
|
24
|
+
/** Each database whose name starts with `test`, a superset of a run's. */
|
|
25
|
+
list(server: Server): Promise<string[]>;
|
|
26
|
+
/** Drops the database `name` if it exists. */
|
|
27
|
+
drop(server: Server, name: string): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Whether `name` is a database of the run `runId`. `_` is a wildcard of
|
|
31
|
+
* SQL's LIKE, so only the exact name pattern proves a run's database.
|
|
32
|
+
*/
|
|
33
|
+
export declare const ownedBy: (runId: string) => (name: string) => boolean;
|
|
34
|
+
//# sourceMappingURL=collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/databases/collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,4FAA4F;AAC5F,eAAO,MAAM,UAAU,6BAA6B,CAAC;AAErD,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAIlE;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,OAAO,GAAG,SAAS,KAAG,MAGvB,CAAC;AAElC;;;;GAIG;AACH,MAAM,WAAW,SAAS,CAAC,MAAM;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB;;;OAGG;IACH,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC;IACrC,0EAA0E;IAC1E,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,8CAA8C;IAC9C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,GACjB,OAAO,MAAM,MACb,MAAM,MAAM,KAAG,OAKf,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { randomBytes, randomUUID } from 'node:crypto';
|
|
2
|
+
/** The kind of a database fixture's shared server: it names the collector of the server. */
|
|
3
|
+
export const KIND_LABEL = 'dev.zukhruf.testing.kind';
|
|
4
|
+
const hex = (runId) => runId.replaceAll('-', '');
|
|
5
|
+
/**
|
|
6
|
+
* The name of a database that `database()` creates. In a run, the name holds
|
|
7
|
+
* the run's id, its owner reference (ADR 0011).
|
|
8
|
+
*/
|
|
9
|
+
export const databaseName = (run) => run
|
|
10
|
+
? `test_${hex(run.id)}_${randomBytes(8).toString('hex')}`
|
|
11
|
+
: `test_${hex(randomUUID())}`;
|
|
12
|
+
/**
|
|
13
|
+
* Whether `name` is a database of the run `runId`. `_` is a wildcard of
|
|
14
|
+
* SQL's LIKE, so only the exact name pattern proves a run's database.
|
|
15
|
+
*/
|
|
16
|
+
export const ownedBy = (runId) => (name) => {
|
|
17
|
+
const prefix = `test_${hex(runId)}_`;
|
|
18
|
+
return (name.startsWith(prefix) && /^[\da-f]{16}$/.test(name.slice(prefix.length)));
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/databases/collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOtD,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAIrD,MAAM,GAAG,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAEjE;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAwB,EAAU,EAAE,CAC/D,GAAG;IACD,CAAC,CAAC,QAAQ,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;IACzD,CAAC,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AAwBlC;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAClB,CAAC,KAAa,EAAE,EAAE,CAClB,CAAC,IAAY,EAAW,EAAE;IACxB,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;IACrC,OAAO,CACL,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAC3E,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -4,8 +4,7 @@ export type { Database, DatabaseOptions } from './database.ts';
|
|
|
4
4
|
export type MariadbOptions = DatabaseOptions;
|
|
5
5
|
export type MariadbDatabase = MysqlFamilyDatabase;
|
|
6
6
|
export declare class Mariadb extends MysqlFamilyServer {
|
|
7
|
-
|
|
8
|
-
protected readonly client = "mariadb";
|
|
7
|
+
protected readonly collector: import("./mysql-family-collector.ts").MysqlFamilyCollector;
|
|
9
8
|
protected readonly scheme = "mariadb";
|
|
10
9
|
constructor({ image, ...options }: MariadbOptions);
|
|
11
10
|
protected environment(password: string, database: string): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb.d.ts","sourceRoot":"","sources":["../../src/databases/mariadb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb.d.ts","sourceRoot":"","sources":["../../src/databases/mariadb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EACL,KAAK,mBAAmB,EACxB,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAElD,qBAAa,OAAQ,SAAQ,iBAAiB;IAC5C,mBAA4B,SAAS,6DAAW;IAChD,mBAA4B,MAAM,aAAa;gBAEnC,EAAE,KAAqB,EAAE,GAAG,OAAO,EAAE,EAAE,cAAc;cAI9C,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;CAGlE"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { mariadb } from "./mysql-family-collector.js";
|
|
1
2
|
import { MysqlFamilyServer, } from "./mysql-family-server.js";
|
|
2
3
|
export class Mariadb extends MysqlFamilyServer {
|
|
3
|
-
|
|
4
|
-
client = 'mariadb';
|
|
4
|
+
collector = mariadb;
|
|
5
5
|
scheme = 'mariadb';
|
|
6
6
|
constructor({ image = 'mariadb:lts', ...options }) {
|
|
7
7
|
super({ ...options, image });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb.js","sourceRoot":"","sources":["../../src/databases/mariadb.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,OAAO,OAAQ,SAAQ,iBAAiB;
|
|
1
|
+
{"version":3,"file":"mariadb.js","sourceRoot":"","sources":["../../src/databases/mariadb.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAEL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,OAAO,OAAQ,SAAQ,iBAAiB;IAChB,SAAS,GAAG,OAAO,CAAC;IACpB,MAAM,GAAG,SAAS,CAAC;IAE/C,YAAY,EAAE,KAAK,GAAG,aAAa,EAAE,GAAG,OAAO,EAAkB;QAC/D,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/B,CAAC;IAEkB,WAAW,CAAC,QAAgB,EAAE,QAAgB;QAC/D,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;IACzE,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Container } from '@zukhruf/docker';
|
|
2
|
+
import type { Collector } from './collector.ts';
|
|
3
|
+
export interface MysqlFamilyServer {
|
|
4
|
+
container: Container;
|
|
5
|
+
password: string;
|
|
6
|
+
}
|
|
7
|
+
/** The image creates only root, from the root password in its environment. */
|
|
8
|
+
export declare const user = "root";
|
|
9
|
+
export interface MysqlFamilyCollector extends Collector<MysqlFamilyServer> {
|
|
10
|
+
/** The client in the image. */
|
|
11
|
+
readonly client: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const mysql: MysqlFamilyCollector;
|
|
14
|
+
/** MariaDB 11 and later ship only the mariadb client, not mysql. */
|
|
15
|
+
export declare const mariadb: MysqlFamilyCollector;
|
|
16
|
+
//# sourceMappingURL=mysql-family-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql-family-collector.d.ts","sourceRoot":"","sources":["../../src/databases/mysql-family-collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAQ,MAAM,gBAAgB,CAAC;AAGtD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8EAA8E;AAC9E,eAAO,MAAM,IAAI,SAAS,CAAC;AAE3B,MAAM,WAAW,oBAAqB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACxE,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAyCD,eAAO,MAAM,KAAK,sBAAuD,CAAC;AAC1E,oEAAoE;AACpE,eAAO,MAAM,OAAO,sBAInB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { succeeded } from "./succeeded.js";
|
|
2
|
+
/** The image creates only root, from the root password in its environment. */
|
|
3
|
+
export const user = 'root';
|
|
4
|
+
/** Runs the image's client in the server's container. */
|
|
5
|
+
function mysqlFamily(kind, client, passwordVariable) {
|
|
6
|
+
const execute = ({ container, password }, args) => succeeded(container, [client, `-u${user}`, `-p${password}`, ...args]);
|
|
7
|
+
return {
|
|
8
|
+
kind,
|
|
9
|
+
client,
|
|
10
|
+
async open(container, environment) {
|
|
11
|
+
const password = environment[passwordVariable];
|
|
12
|
+
if (password === undefined)
|
|
13
|
+
throw new Error(`The ${kind} server ${container.id} has no ${passwordVariable}`);
|
|
14
|
+
return { container, password, [Symbol.asyncDispose]: async () => { } };
|
|
15
|
+
},
|
|
16
|
+
async list(server) {
|
|
17
|
+
const stdout = await execute(server, [
|
|
18
|
+
'--batch',
|
|
19
|
+
'--skip-column-names',
|
|
20
|
+
'--execute',
|
|
21
|
+
"SHOW DATABASES LIKE 'test%'",
|
|
22
|
+
]);
|
|
23
|
+
return stdout.split('\n').filter(Boolean);
|
|
24
|
+
},
|
|
25
|
+
async drop(server, name) {
|
|
26
|
+
await execute(server, [
|
|
27
|
+
'--execute',
|
|
28
|
+
`DROP DATABASE IF EXISTS \`${name}\``,
|
|
29
|
+
]);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export const mysql = mysqlFamily('mysql', 'mysql', 'MYSQL_ROOT_PASSWORD');
|
|
34
|
+
/** MariaDB 11 and later ship only the mariadb client, not mysql. */
|
|
35
|
+
export const mariadb = mysqlFamily('mariadb', 'mariadb', 'MARIADB_ROOT_PASSWORD');
|
|
36
|
+
//# sourceMappingURL=mysql-family-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql-family-collector.js","sourceRoot":"","sources":["../../src/databases/mysql-family-collector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAO3C,8EAA8E;AAC9E,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC;AAO3B,yDAAyD;AACzD,SAAS,WAAW,CAClB,IAAU,EACV,MAAc,EACd,gBAAwB;IAExB,MAAM,OAAO,GAAG,CACd,EAAE,SAAS,EAAE,QAAQ,EAAqB,EAC1C,IAAc,EACd,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,EAAE,KAAK,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IAC3E,OAAO;QACL,IAAI;QACJ,MAAM;QACN,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW;YAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC,gBAAgB,CAAC,CAAC;YAC/C,IAAI,QAAQ,KAAK,SAAS;gBACxB,MAAM,IAAI,KAAK,CACb,OAAO,IAAI,WAAW,SAAS,CAAC,EAAE,WAAW,gBAAgB,EAAE,CAChE,CAAC;YACJ,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAC;QACxE,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM;YACf,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE;gBACnC,SAAS;gBACT,qBAAqB;gBACrB,WAAW;gBACX,6BAA6B;aAC9B,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI;YACrB,MAAM,OAAO,CAAC,MAAM,EAAE;gBACpB,WAAW;gBACX,6BAA6B,IAAI,IAAI;aACtC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,qBAAqB,CAAC,CAAC;AAC1E,oEAAoE;AACpE,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,CAChC,SAAS,EACT,SAAS,EACT,uBAAuB,CACxB,CAAC"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { Database, DatabaseOptions } from './database.ts';
|
|
2
|
+
import { type MysqlFamilyCollector } from './mysql-family-collector.ts';
|
|
2
3
|
export interface MysqlFamilyDatabase extends Database {
|
|
3
4
|
query: (sql: string) => Promise<Record<string, string | null>[]>;
|
|
4
5
|
}
|
|
5
6
|
/**
|
|
6
7
|
* A template method for servers that speak MySQL's protocol and client flags:
|
|
7
8
|
* acquisitions, readiness, queries and the batch parser stay the same. A
|
|
8
|
-
* subclass names the client in its image, the
|
|
9
|
-
* the environment, and passes its default
|
|
9
|
+
* subclass names its collector (its kind and the client in its image), the
|
|
10
|
+
* connection string's scheme and the environment, and passes its default
|
|
11
|
+
* image to this constructor.
|
|
10
12
|
*/
|
|
11
13
|
export declare abstract class MysqlFamilyServer {
|
|
12
14
|
#private;
|
|
13
|
-
protected abstract readonly
|
|
15
|
+
protected abstract readonly collector: MysqlFamilyCollector;
|
|
14
16
|
protected abstract readonly scheme: string;
|
|
15
17
|
protected abstract environment(password: string, database: string): Record<string, string>;
|
|
16
18
|
constructor({ environment, image, password, database, labels, }: DatabaseOptions & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-family-server.d.ts","sourceRoot":"","sources":["../../src/databases/mysql-family-server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mysql-family-server.d.ts","sourceRoot":"","sources":["../../src/databases/mysql-family-server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,KAAK,oBAAoB,EAAQ,MAAM,6BAA6B,CAAC;AAG9E,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;CAClE;AAED;;;;;;GAMG;AACH,8BAAsB,iBAAiB;;IAKrC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;IAC5D,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAC3C,SAAS,CAAC,QAAQ,CAAC,WAAW,CAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEb,EACV,WAAW,EACX,KAAK,EACL,QAAyB,EACzB,QAAgB,EAChB,MAAM,GACP,EAAE,eAAe,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAMtC,mEAAmE;IAC7D,QAAQ,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAqB9C,wEAAwE;IAClE,KAAK,IAAI,OAAO,CAAC,mBAAmB,CAAC;CA6G5C"}
|
|
@@ -1,26 +1,33 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import { timebox } from "../async/timebox.js";
|
|
3
2
|
import { DockerFixtures } from "../docker/fixtures.js";
|
|
3
|
+
import { TestRun } from "../docker/test-run.js";
|
|
4
|
+
import { KIND_LABEL, databaseName } from "./collector.js";
|
|
5
|
+
import { user } from "./mysql-family-collector.js";
|
|
4
6
|
import { succeeded } from "./succeeded.js";
|
|
5
|
-
/** The image creates only root, from the root password in its environment. */
|
|
6
|
-
const user = 'root';
|
|
7
7
|
/**
|
|
8
8
|
* A template method for servers that speak MySQL's protocol and client flags:
|
|
9
9
|
* acquisitions, readiness, queries and the batch parser stay the same. A
|
|
10
|
-
* subclass names the client in its image, the
|
|
11
|
-
* the environment, and passes its default
|
|
10
|
+
* subclass names its collector (its kind and the client in its image), the
|
|
11
|
+
* connection string's scheme and the environment, and passes its default
|
|
12
|
+
* image to this constructor.
|
|
12
13
|
*/
|
|
13
14
|
export class MysqlFamilyServer {
|
|
14
15
|
#docker;
|
|
16
|
+
#run;
|
|
15
17
|
#options;
|
|
16
18
|
constructor({ environment, image, password = 'testpassword', database = 'app', labels, }) {
|
|
17
19
|
this.#docker = new DockerFixtures({ environment });
|
|
20
|
+
this.#run = TestRun.fromEnvironment(environment);
|
|
18
21
|
this.#options = { image, password, database, labels };
|
|
19
22
|
}
|
|
20
23
|
/** Create an isolated database on the persistent shared server. */
|
|
21
24
|
async database() {
|
|
22
25
|
const container = await this.#acquire('app', 'reuse');
|
|
23
|
-
const database =
|
|
26
|
+
const database = databaseName(this.#run);
|
|
27
|
+
const server = {
|
|
28
|
+
container: container.container,
|
|
29
|
+
password: this.#options.password,
|
|
30
|
+
};
|
|
24
31
|
try {
|
|
25
32
|
await this.#sql(container, `CREATE DATABASE \`${database}\``);
|
|
26
33
|
}
|
|
@@ -29,8 +36,8 @@ export class MysqlFamilyServer {
|
|
|
29
36
|
throw error;
|
|
30
37
|
}
|
|
31
38
|
return this.#handle(container, database, async () => {
|
|
32
|
-
await this
|
|
33
|
-
/* Best-effort cleanup
|
|
39
|
+
await this.collector.drop(server, database).catch(() => {
|
|
40
|
+
/* Best-effort: the run's cleanup drops a database that disposal left. */
|
|
34
41
|
});
|
|
35
42
|
await container.disconnect();
|
|
36
43
|
});
|
|
@@ -43,8 +50,8 @@ export class MysqlFamilyServer {
|
|
|
43
50
|
}
|
|
44
51
|
#sql(container, sql) {
|
|
45
52
|
const { password } = this.#options;
|
|
46
|
-
return succeeded(container, [
|
|
47
|
-
this.client,
|
|
53
|
+
return succeeded(container.container, [
|
|
54
|
+
this.collector.client,
|
|
48
55
|
`-u${user}`,
|
|
49
56
|
`-p${password}`,
|
|
50
57
|
'--execute',
|
|
@@ -53,8 +60,8 @@ export class MysqlFamilyServer {
|
|
|
53
60
|
}
|
|
54
61
|
async #query(container, database, sql) {
|
|
55
62
|
const { password } = this.#options;
|
|
56
|
-
const stdout = await succeeded(container, [
|
|
57
|
-
this.client,
|
|
63
|
+
const stdout = await succeeded(container.container, [
|
|
64
|
+
this.collector.client,
|
|
58
65
|
`-u${user}`,
|
|
59
66
|
`-p${password}`,
|
|
60
67
|
'--database',
|
|
@@ -86,7 +93,7 @@ export class MysqlFamilyServer {
|
|
|
86
93
|
const { image, password, labels } = this.#options;
|
|
87
94
|
return this.#docker[mode]({
|
|
88
95
|
image,
|
|
89
|
-
labels,
|
|
96
|
+
labels: { ...labels, [KIND_LABEL]: this.collector.kind },
|
|
90
97
|
internalPort: 3306,
|
|
91
98
|
env: this.environment(password, database),
|
|
92
99
|
tmpfs: ['/var/lib/mysql:rw,size=512m'],
|
|
@@ -97,8 +104,8 @@ export class MysqlFamilyServer {
|
|
|
97
104
|
#ready(container) {
|
|
98
105
|
const { password } = this.#options;
|
|
99
106
|
// TCP excludes the entrypoint's temporary, socket-only initialization server.
|
|
100
|
-
return timebox(() => succeeded(container, [
|
|
101
|
-
this.client,
|
|
107
|
+
return timebox(() => succeeded(container.container, [
|
|
108
|
+
this.collector.client,
|
|
102
109
|
'-h',
|
|
103
110
|
'127.0.0.1',
|
|
104
111
|
`-u${user}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-family-server.js","sourceRoot":"","sources":["../../src/databases/mysql-family-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mysql-family-server.js","sourceRoot":"","sources":["../../src/databases/mysql-family-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAA6B,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAM3C;;;;;;GAMG;AACH,MAAM,OAAgB,iBAAiB;IAC5B,OAAO,CAAiB;IACxB,IAAI,CAAsB;IAC1B,QAAQ,CAAC;IASlB,YAAY,EACV,WAAW,EACX,KAAK,EACL,QAAQ,GAAG,cAAc,EACzB,QAAQ,GAAG,KAAK,EAChB,MAAM,GAC8B;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACxD,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,QAAQ;QACZ,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG;YACb,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ;SACjC,CAAC;QACF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,QAAQ,IAAI,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,SAAS,CAAC,UAAU,EAAE,CAAC;YAC7B,MAAM,KAAK,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACrD,yEAAyE;YAC3E,CAAC,CAAC,CAAC;YACH,MAAM,SAAS,CAAC,UAAU,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,KAAK,CAAC,KAAK;QACT,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACnC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,CAAC,SAA2B,EAAE,GAAW;QAC3C,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACnC,OAAO,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE;YACpC,IAAI,CAAC,SAAS,CAAC,MAAM;YACrB,KAAK,IAAI,EAAE;YACX,KAAK,QAAQ,EAAE;YACf,WAAW;YACX,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CACV,SAA2B,EAC3B,QAAgB,EAChB,GAAW;QAEX,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE;YAClD,IAAI,CAAC,SAAS,CAAC,MAAM;YACrB,KAAK,IAAI,EAAE;YACX,KAAK,QAAQ,EAAE;YACf,YAAY;YACZ,QAAQ;YACR,SAAS;YACT,OAAO;YACP,WAAW;YACX,GAAG;SACJ,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,WAAW,CAAC,MAAc;QACxB,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3E,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACvB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,OAAO,MAAM,CAAC,WAAW,CACvB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5B,OAAO;oBACL,MAAM;oBACN,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;iBACvD,CAAC;YACJ,CAAC,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CACN,QAAgB,EAChB,IAAuB;QAEvB,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QAClD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxB,KAAK;YACL,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;YACxD,YAAY,EAAE,IAAI;YAClB,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC;YACzC,KAAK,EAAE,CAAC,6BAA6B,CAAC;YACtC,gBAAgB,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,SAA2B;QAChC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QACnC,8EAA8E;QAC9E,OAAO,OAAO,CACZ,GAAG,EAAE,CACH,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE;YAC7B,IAAI,CAAC,SAAS,CAAC,MAAM;YACrB,IAAI;YACJ,WAAW;YACX,KAAK,IAAI,EAAE;YACX,KAAK,QAAQ,EAAE;YACf,WAAW;YACX,UAAU;SACX,CAAC,EACJ,EAAE,YAAY,EAAE,MAAM,EAAE,CACzB,CAAC;IACJ,CAAC;IAED,OAAO,CACL,SAA2B,EAC3B,QAAgB,EAChB,OAA4B;QAE5B,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1C,OAAO;YACL,gBAAgB,EAAE,GAAG,IAAI,CAAC,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,IAAI,QAAQ,EAAE;YACxG,KAAK;YACL,IAAI;YACJ,QAAQ;YACR,QAAQ;YACR,WAAW,EAAE,SAAS,CAAC,SAAS,CAAC,EAAE;YACnC,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC;YACrD,OAAO;YACP,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO;SAC/B,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -4,7 +4,7 @@ export type { Database, DatabaseOptions } from './database.ts';
|
|
|
4
4
|
export type MysqlOptions = DatabaseOptions;
|
|
5
5
|
export type MysqlDatabase = MysqlFamilyDatabase;
|
|
6
6
|
export declare class Mysql extends MysqlFamilyServer {
|
|
7
|
-
protected readonly
|
|
7
|
+
protected readonly collector: import("./mysql-family-collector.ts").MysqlFamilyCollector;
|
|
8
8
|
protected readonly scheme = "mysql";
|
|
9
9
|
constructor({ image, ...options }: MysqlOptions);
|
|
10
10
|
protected environment(password: string, database: string): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/databases/mysql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/databases/mysql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EACL,KAAK,mBAAmB,EACxB,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,eAAe,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAEhD,qBAAa,KAAM,SAAQ,iBAAiB;IAC1C,mBAA4B,SAAS,6DAAS;IAC9C,mBAA4B,MAAM,WAAW;gBAEjC,EAAE,KAAmB,EAAE,GAAG,OAAO,EAAE,EAAE,YAAY;cAI1C,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;CAGlE"}
|
package/dist/databases/mysql.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { mysql } from "./mysql-family-collector.js";
|
|
1
2
|
import { MysqlFamilyServer, } from "./mysql-family-server.js";
|
|
2
3
|
export class Mysql extends MysqlFamilyServer {
|
|
3
|
-
|
|
4
|
+
collector = mysql;
|
|
4
5
|
scheme = 'mysql';
|
|
5
6
|
constructor({ image = 'mysql:lts', ...options }) {
|
|
6
7
|
super({ ...options, image });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/databases/mysql.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,OAAO,KAAM,SAAQ,iBAAiB;IACd,
|
|
1
|
+
{"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/databases/mysql.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAEL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,OAAO,KAAM,SAAQ,iBAAiB;IACd,SAAS,GAAG,KAAK,CAAC;IAClB,MAAM,GAAG,OAAO,CAAC;IAE7C,YAAY,EAAE,KAAK,GAAG,WAAW,EAAE,GAAG,OAAO,EAAgB;QAC3D,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/B,CAAC;IAEkB,WAAW,CAAC,QAAgB,EAAE,QAAgB;QAC/D,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Container } from '@zukhruf/docker';
|
|
2
|
+
import type { Collector } from './collector.ts';
|
|
3
|
+
export interface PostgresServer {
|
|
4
|
+
container: Container;
|
|
5
|
+
user: string;
|
|
6
|
+
}
|
|
7
|
+
/** Runs `psql` in the server's container. */
|
|
8
|
+
export declare const postgres: Collector<PostgresServer>;
|
|
9
|
+
//# sourceMappingURL=postgres-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-collector.d.ts","sourceRoot":"","sources":["../../src/databases/postgres-collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,6CAA6C;AAC7C,eAAO,MAAM,QAAQ,EAAE,SAAS,CAAC,cAAc,CAuB9C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { succeeded } from "./succeeded.js";
|
|
2
|
+
const psql = ({ container, user }, args) => succeeded(container, ['psql', '-U', user, '-d', 'postgres', ...args]);
|
|
3
|
+
/** Runs `psql` in the server's container. */
|
|
4
|
+
export const postgres = {
|
|
5
|
+
kind: 'postgres',
|
|
6
|
+
async open(container, environment) {
|
|
7
|
+
return {
|
|
8
|
+
container,
|
|
9
|
+
user: environment.POSTGRES_USER ?? 'postgres',
|
|
10
|
+
[Symbol.asyncDispose]: async () => { },
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
async list(server) {
|
|
14
|
+
const stdout = await psql(server, [
|
|
15
|
+
'-At',
|
|
16
|
+
'-c',
|
|
17
|
+
"SELECT datname FROM pg_database WHERE datname LIKE 'test%'",
|
|
18
|
+
]);
|
|
19
|
+
return stdout.split('\n').filter(Boolean);
|
|
20
|
+
},
|
|
21
|
+
async drop(server, name) {
|
|
22
|
+
await psql(server, [
|
|
23
|
+
'-c',
|
|
24
|
+
`DROP DATABASE IF EXISTS "${name}" WITH (FORCE)`,
|
|
25
|
+
]);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=postgres-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-collector.js","sourceRoot":"","sources":["../../src/databases/postgres-collector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAO3C,MAAM,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAkB,EAAE,IAAc,EAAE,EAAE,CACnE,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AAExE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAA8B;IACjD,IAAI,EAAE,UAAU;IAChB,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW;QAC/B,OAAO;YACL,SAAS;YACT,IAAI,EAAE,WAAW,CAAC,aAAa,IAAI,UAAU;YAC7C,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;SACtC,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,MAAM;QACf,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;YAChC,KAAK;YACL,IAAI;YACJ,4DAA4D;SAC7D,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI;QACrB,MAAM,IAAI,CAAC,MAAM,EAAE;YACjB,IAAI;YACJ,4BAA4B,IAAI,gBAAgB;SACjD,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/databases/postgres.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/databases/postgres.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAI/D,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qFAAqF;AACrF,qBAAa,QAAQ;;gBAKP,EACV,WAAW,EACX,KAA4B,EAC5B,QAAyB,EACzB,QAAmB,EACnB,IAAiB,EACjB,MAAM,GACP,EAAE,eAAe;IAMlB,mEAAmE;IAC7D,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IAkBnC,wEAAwE;IAClE,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC;CAqFjC"}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import { timebox } from "../async/timebox.js";
|
|
3
2
|
import { DockerFixtures } from "../docker/fixtures.js";
|
|
3
|
+
import { TestRun } from "../docker/test-run.js";
|
|
4
|
+
import { KIND_LABEL, databaseName } from "./collector.js";
|
|
5
|
+
import { postgres } from "./postgres-collector.js";
|
|
4
6
|
import { succeeded } from "./succeeded.js";
|
|
5
7
|
/** PostgreSQL test configuration. Each acquisition returns an independent handle. */
|
|
6
8
|
export class Postgres {
|
|
7
9
|
#docker;
|
|
10
|
+
#run;
|
|
8
11
|
#options;
|
|
9
12
|
constructor({ environment, image = 'postgres:18-alpine', password = 'testpassword', database = 'testdb', user = 'postgres', labels, }) {
|
|
10
13
|
this.#docker = new DockerFixtures({ environment });
|
|
14
|
+
this.#run = TestRun.fromEnvironment(environment);
|
|
11
15
|
this.#options = { image, password, database, user, labels };
|
|
12
16
|
}
|
|
13
17
|
/** Create an isolated database on the persistent shared server. */
|
|
14
18
|
async database() {
|
|
15
19
|
const container = await this.#acquire('postgres', 'reuse');
|
|
16
|
-
const database =
|
|
20
|
+
const database = databaseName(this.#run);
|
|
21
|
+
const server = { container: container.container, user: this.#options.user };
|
|
17
22
|
try {
|
|
18
23
|
await this.#sql(container, `CREATE DATABASE ${database}`);
|
|
19
24
|
}
|
|
@@ -22,8 +27,8 @@ export class Postgres {
|
|
|
22
27
|
throw error;
|
|
23
28
|
}
|
|
24
29
|
return this.#handle(container, database, async () => {
|
|
25
|
-
await
|
|
26
|
-
/* Best-effort cleanup
|
|
30
|
+
await postgres.drop(server, database).catch(() => {
|
|
31
|
+
/* Best-effort: the run's cleanup drops a database that disposal left. */
|
|
27
32
|
});
|
|
28
33
|
await container.disconnect();
|
|
29
34
|
});
|
|
@@ -35,7 +40,7 @@ export class Postgres {
|
|
|
35
40
|
return this.#handle(container, database, () => container.cleanup());
|
|
36
41
|
}
|
|
37
42
|
#sql(container, sql) {
|
|
38
|
-
return succeeded(container, [
|
|
43
|
+
return succeeded(container.container, [
|
|
39
44
|
'psql',
|
|
40
45
|
'-U',
|
|
41
46
|
this.#options.user,
|
|
@@ -49,7 +54,7 @@ export class Postgres {
|
|
|
49
54
|
const { image, password, user, labels } = this.#options;
|
|
50
55
|
return this.#docker[mode]({
|
|
51
56
|
image,
|
|
52
|
-
labels,
|
|
57
|
+
labels: { ...labels, [KIND_LABEL]: postgres.kind },
|
|
53
58
|
internalPort: 5432,
|
|
54
59
|
env: {
|
|
55
60
|
POSTGRES_PASSWORD: password,
|
|
@@ -65,14 +70,14 @@ export class Postgres {
|
|
|
65
70
|
const { user } = this.#options;
|
|
66
71
|
// TCP excludes PostgreSQL's temporary, socket-only initialization server.
|
|
67
72
|
return timebox(async () => {
|
|
68
|
-
await succeeded(container, [
|
|
73
|
+
await succeeded(container.container, [
|
|
69
74
|
'pg_isready',
|
|
70
75
|
'-h',
|
|
71
76
|
'127.0.0.1',
|
|
72
77
|
'-U',
|
|
73
78
|
user,
|
|
74
79
|
]);
|
|
75
|
-
await succeeded(container, [
|
|
80
|
+
await succeeded(container.container, [
|
|
76
81
|
'psql',
|
|
77
82
|
'-h',
|
|
78
83
|
'127.0.0.1',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/databases/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/databases/postgres.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Collector } from './collector.ts';
|
|
2
|
+
export interface SqlServerServer {
|
|
3
|
+
host: string;
|
|
4
|
+
port: number;
|
|
5
|
+
password: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const connectionString: ({ host, port, password }: SqlServerServer, database: string) => string;
|
|
8
|
+
/**
|
|
9
|
+
* Speaks to the server with the `mssql` driver: the `azure-sql-edge` image
|
|
10
|
+
* has no `sqlcmd` to exec.
|
|
11
|
+
*/
|
|
12
|
+
export declare const sqlserver: Collector<SqlServerServer>;
|
|
13
|
+
//# sourceMappingURL=sqlserver-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlserver-collector.d.ts","sourceRoot":"","sources":["../../src/databases/sqlserver-collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,gBAAgB,GAC3B,0BAA0B,eAAe,EACzC,UAAU,MAAM,KACf,MACuH,CAAC;AAe3H;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,eAAe,CAgChD,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import sql from 'mssql';
|
|
2
|
+
export const connectionString = ({ host, port, password }, database) => `Server=${host},${port};Database=${database};User Id=sa;Password=${password};TrustServerCertificate=true;Encrypt=false;`;
|
|
3
|
+
async function query(server, text) {
|
|
4
|
+
const pool = new sql.ConnectionPool(connectionString(server, 'master'));
|
|
5
|
+
try {
|
|
6
|
+
await pool.connect();
|
|
7
|
+
return (await pool.request().query(text)).recordset;
|
|
8
|
+
}
|
|
9
|
+
finally {
|
|
10
|
+
await pool.close().catch(() => { });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Speaks to the server with the `mssql` driver: the `azure-sql-edge` image
|
|
15
|
+
* has no `sqlcmd` to exec.
|
|
16
|
+
*/
|
|
17
|
+
export const sqlserver = {
|
|
18
|
+
kind: 'sqlserver',
|
|
19
|
+
async open(container, environment, host) {
|
|
20
|
+
const password = environment.MSSQL_SA_PASSWORD;
|
|
21
|
+
if (password === undefined)
|
|
22
|
+
throw new Error(`The sqlserver server ${container.id} has no MSSQL_SA_PASSWORD`);
|
|
23
|
+
const published = await container.port(1433);
|
|
24
|
+
if (!published)
|
|
25
|
+
throw new Error(`Container ${container.id} publishes no port for 1433`);
|
|
26
|
+
const forward = await host.forward(published.port);
|
|
27
|
+
return {
|
|
28
|
+
host: '127.0.0.1',
|
|
29
|
+
port: forward.port,
|
|
30
|
+
password,
|
|
31
|
+
[Symbol.asyncDispose]: forward.close,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
async list(server) {
|
|
35
|
+
const rows = await query(server, "SELECT name FROM sys.databases WHERE name LIKE 'test%'");
|
|
36
|
+
return rows.map(({ name }) => String(name));
|
|
37
|
+
},
|
|
38
|
+
async drop(server, name) {
|
|
39
|
+
await query(server, `IF DB_ID('${name}') IS NOT NULL BEGIN ALTER DATABASE [${name}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [${name}]; END`);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=sqlserver-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlserver-collector.js","sourceRoot":"","sources":["../../src/databases/sqlserver-collector.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,OAAO,CAAC;AAUxB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAmB,EACzC,QAAgB,EACR,EAAE,CACV,UAAU,IAAI,IAAI,IAAI,aAAa,QAAQ,wBAAwB,QAAQ,6CAA6C,CAAC;AAE3H,KAAK,UAAU,KAAK,CAClB,MAAuB,EACvB,IAAY;IAEZ,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAA+B;IACnD,IAAI,EAAE,WAAW;IACjB,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI;QACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,iBAAiB,CAAC;QAC/C,IAAI,QAAQ,KAAK,SAAS;YACxB,MAAM,IAAI,KAAK,CACb,wBAAwB,SAAS,CAAC,EAAE,2BAA2B,CAChE,CAAC;QACJ,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS;YACZ,MAAM,IAAI,KAAK,CAAC,aAAa,SAAS,CAAC,EAAE,6BAA6B,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACnD,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ;YACR,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,KAAK;SACrC,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,MAAM;QACf,MAAM,IAAI,GAAG,MAAM,KAAK,CACtB,MAAM,EACN,wDAAwD,CACzD,CAAC;QACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI;QACrB,MAAM,KAAK,CACT,MAAM,EACN,aAAa,IAAI,wCAAwC,IAAI,6DAA6D,IAAI,QAAQ,CACvI,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlserver.d.ts","sourceRoot":"","sources":["../../src/databases/sqlserver.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlserver.d.ts","sourceRoot":"","sources":["../../src/databases/sqlserver.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAO/D,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D,eAAO,MAAM,qBAAqB,+CACY,CAAC;AAC/C,eAAO,MAAM,qBAAqB,4CAA4C,CAAC;AAE/E,4FAA4F;AAC5F,qBAAa,SAAS;;gBAYR,EACV,WAAW,EACX,KAAK,EACL,QAA+B,EAC/B,QAAmB,EACnB,MAAM,GACP,EAAE,eAAe;IAMlB,mEAAmE;IAC7D,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IAqBnC,wEAAwE;IAClE,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC;CA8FjC"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import sql from 'mssql';
|
|
3
2
|
import pMemoize from 'p-memoize';
|
|
4
3
|
import { timebox } from "../async/timebox.js";
|
|
5
4
|
import { DockerFixtures } from "../docker/fixtures.js";
|
|
5
|
+
import { TestRun } from "../docker/test-run.js";
|
|
6
|
+
import { KIND_LABEL, databaseName } from "./collector.js";
|
|
7
|
+
import { connectionString, sqlserver, } from "./sqlserver-collector.js";
|
|
6
8
|
export const SQL_SERVER_FULL_IMAGE = 'mcr.microsoft.com/mssql/server:2022-latest';
|
|
7
9
|
export const SQL_SERVER_EDGE_IMAGE = 'mcr.microsoft.com/azure-sql-edge:latest';
|
|
8
10
|
/** SQL Server test configuration. Without an image, the engine's architecture picks one. */
|
|
9
11
|
export class SqlServer {
|
|
10
12
|
#docker;
|
|
13
|
+
#run;
|
|
11
14
|
#options;
|
|
12
15
|
#image = pMemoize(async () => {
|
|
13
16
|
if (this.#options.image)
|
|
@@ -19,18 +22,22 @@ export class SqlServer {
|
|
|
19
22
|
});
|
|
20
23
|
constructor({ environment, image, password = 'StrongP@ssw0rd123!', database = 'testdb', labels, }) {
|
|
21
24
|
this.#docker = new DockerFixtures({ environment });
|
|
25
|
+
this.#run = TestRun.fromEnvironment(environment);
|
|
22
26
|
this.#options = { image, password, database, labels };
|
|
23
27
|
}
|
|
24
28
|
/** Create an isolated database on the persistent shared server. */
|
|
25
29
|
async database() {
|
|
26
30
|
const image = await this.#image();
|
|
27
31
|
const container = await this.#acquire(image, 'reuse');
|
|
28
|
-
const database =
|
|
32
|
+
const database = databaseName(this.#run);
|
|
29
33
|
try {
|
|
30
34
|
await this.#createDatabase(container, database);
|
|
31
35
|
return this.#handle(container, image, database, async () => {
|
|
32
36
|
try {
|
|
33
|
-
await this.#
|
|
37
|
+
await sqlserver.drop(this.#server(container), database);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Best-effort: the run's cleanup drops a database that disposal left.
|
|
34
41
|
}
|
|
35
42
|
finally {
|
|
36
43
|
await container.disconnect();
|
|
@@ -56,8 +63,11 @@ export class SqlServer {
|
|
|
56
63
|
throw error;
|
|
57
64
|
}
|
|
58
65
|
}
|
|
66
|
+
#server({ host, port }) {
|
|
67
|
+
return { host, port, password: this.#options.password };
|
|
68
|
+
}
|
|
59
69
|
#connectionString(container, database) {
|
|
60
|
-
return
|
|
70
|
+
return connectionString(this.#server(container), database);
|
|
61
71
|
}
|
|
62
72
|
async #ping(container) {
|
|
63
73
|
const pool = new sql.ConnectionPool(`${this.#connectionString(container, 'master')}connectionTimeout=1000;requestTimeout=1000;`);
|
|
@@ -81,26 +91,11 @@ export class SqlServer {
|
|
|
81
91
|
await pool.close();
|
|
82
92
|
}
|
|
83
93
|
}
|
|
84
|
-
async #dropDatabase(container, database) {
|
|
85
|
-
const pool = new sql.ConnectionPool(this.#connectionString(container, 'master'));
|
|
86
|
-
try {
|
|
87
|
-
await pool.connect();
|
|
88
|
-
await pool
|
|
89
|
-
.request()
|
|
90
|
-
.query(`IF DB_ID('${database}') IS NOT NULL BEGIN ALTER DATABASE [${database}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [${database}]; END`);
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
// Best-effort cleanup; a leaked database lasts until container removal.
|
|
94
|
-
}
|
|
95
|
-
finally {
|
|
96
|
-
await pool.close().catch(() => { });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
94
|
#acquire(image, mode) {
|
|
100
95
|
const { password, labels } = this.#options;
|
|
101
96
|
return this.#docker[mode]({
|
|
102
97
|
image,
|
|
103
|
-
labels,
|
|
98
|
+
labels: { ...labels, [KIND_LABEL]: sqlserver.kind },
|
|
104
99
|
env: {
|
|
105
100
|
ACCEPT_EULA: 'Y',
|
|
106
101
|
MSSQL_SA_PASSWORD: password,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlserver.js","sourceRoot":"","sources":["../../src/databases/sqlserver.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"sqlserver.js","sourceRoot":"","sources":["../../src/databases/sqlserver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Container } from '@zukhruf/docker';
|
|
2
2
|
/**
|
|
3
|
-
* Runs `command` in
|
|
3
|
+
* Runs `command` in `container` and gives its standard output.
|
|
4
4
|
* A non-zero exit code rejects with the output of the command.
|
|
5
5
|
*/
|
|
6
|
-
export declare function succeeded(
|
|
6
|
+
export declare function succeeded(container: Container, command: string[]): Promise<string>;
|
|
7
7
|
//# sourceMappingURL=succeeded.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"succeeded.d.ts","sourceRoot":"","sources":["../../src/databases/succeeded.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"succeeded.d.ts","sourceRoot":"","sources":["../../src/databases/succeeded.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,MAAM,CAAC,CAKjB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Runs `command` in
|
|
2
|
+
* Runs `command` in `container` and gives its standard output.
|
|
3
3
|
* A non-zero exit code rejects with the output of the command.
|
|
4
4
|
*/
|
|
5
|
-
export async function succeeded(
|
|
5
|
+
export async function succeeded(container, command) {
|
|
6
6
|
const { exitCode, stdout, output } = await container.exec({ Cmd: command });
|
|
7
7
|
if (exitCode !== 0)
|
|
8
8
|
throw new Error(`${command[0]} exited with ${exitCode}: ${output}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"succeeded.js","sourceRoot":"","sources":["../../src/databases/succeeded.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,
|
|
1
|
+
{"version":3,"file":"succeeded.js","sourceRoot":"","sources":["../../src/databases/succeeded.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAAoB,EACpB,OAAiB;IAEjB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5E,IAAI,QAAQ,KAAK,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,gBAAgB,QAAQ,KAAK,MAAM,EAAE,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cleanup.d.ts","sourceRoot":"","sources":["../../src/scripts/run-cleanup.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"run-cleanup.d.ts","sourceRoot":"","sources":["../../src/scripts/run-cleanup.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAiBzD,4DAA4D;AAC5D,eAAO,MAAM,mBAAmB,SAAU,CAAC;AAE3C,gDAAgD;AAChD,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAiHD;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAED,6EAA6E;AAC7E,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
|
@@ -1,14 +1,109 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
1
9
|
import { execFile } from 'node:child_process';
|
|
2
10
|
import { readFile, readdir, rm } from 'node:fs/promises';
|
|
3
11
|
import { join } from 'node:path';
|
|
4
12
|
import { promisify } from 'node:util';
|
|
5
13
|
import { Docker } from '@zukhruf/docker';
|
|
14
|
+
import { KIND_LABEL, ownedBy, } from "../databases/collector.js";
|
|
6
15
|
import { SHARED_SERVER_LABEL } from "../docker/fixtures.js";
|
|
7
16
|
import { DockerHost, SHELL_TIMEOUT, quote } from "../docker/host.js";
|
|
8
17
|
import { TEST_RUN_LABEL, TestRun, directoryPrefix, forwardPrefix, } from "../docker/test-run.js";
|
|
9
18
|
/** How long one Engine API call of the cleanup may take. */
|
|
10
19
|
export const ENGINE_CALL_TIMEOUT = 240_000;
|
|
11
20
|
const execute = promisify(execFile);
|
|
21
|
+
const codeOf = (error) => error instanceof Error && 'code' in error ? error.code : undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The collector of each kind, loaded when a server of the kind runs. A
|
|
24
|
+
* driver is an optional peer dependency: without it, the run's test
|
|
25
|
+
* processes could not create a database of the kind.
|
|
26
|
+
*/
|
|
27
|
+
const collectors = {
|
|
28
|
+
postgres: {
|
|
29
|
+
load: async () => (await import("../databases/postgres-collector.js")).postgres,
|
|
30
|
+
},
|
|
31
|
+
mysql: {
|
|
32
|
+
load: async () => (await import("../databases/mysql-family-collector.js")).mysql,
|
|
33
|
+
},
|
|
34
|
+
mariadb: {
|
|
35
|
+
load: async () => (await import("../databases/mysql-family-collector.js")).mariadb,
|
|
36
|
+
},
|
|
37
|
+
sqlserver: {
|
|
38
|
+
driver: 'mssql',
|
|
39
|
+
load: async () => (await import("../databases/sqlserver-collector.js")).sqlserver,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
const isKind = (value) => value !== undefined && Object.hasOwn(collectors, value);
|
|
43
|
+
/** The collector of `kind`, or undefined when its driver is not installed. */
|
|
44
|
+
async function collectorOf(kind) {
|
|
45
|
+
const { driver, load } = collectors[kind];
|
|
46
|
+
if (driver !== undefined)
|
|
47
|
+
try {
|
|
48
|
+
await import(__rewriteRelativeImportExtension(driver));
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (codeOf(error) === 'ERR_MODULE_NOT_FOUND')
|
|
52
|
+
return undefined;
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
return load();
|
|
56
|
+
}
|
|
57
|
+
const running = async (container) => (await container.inspect().catch(() => undefined))?.State?.Running === true;
|
|
58
|
+
/**
|
|
59
|
+
* Drops the run's databases on each running shared server of a database
|
|
60
|
+
* fixture. A server that stops takes its databases with it. A server that
|
|
61
|
+
* does not answer yet holds none: a fixture creates a database only after
|
|
62
|
+
* the server answered its readiness check.
|
|
63
|
+
*/
|
|
64
|
+
async function dropDatabases(engine, host, runId, signal) {
|
|
65
|
+
for (const summary of await engine.containers.list({
|
|
66
|
+
filters: { label: [`${SHARED_SERVER_LABEL}=1`, KIND_LABEL] },
|
|
67
|
+
signal: signal(),
|
|
68
|
+
})) {
|
|
69
|
+
const kind = summary.Labels?.[KIND_LABEL];
|
|
70
|
+
if (!isKind(kind))
|
|
71
|
+
continue;
|
|
72
|
+
const collector = await collectorOf(kind);
|
|
73
|
+
if (!collector)
|
|
74
|
+
continue;
|
|
75
|
+
const container = await engine.containers.find(summary.Id, {
|
|
76
|
+
signal: signal(),
|
|
77
|
+
});
|
|
78
|
+
if (!container)
|
|
79
|
+
continue;
|
|
80
|
+
const inspected = await container.inspect({ signal: signal() });
|
|
81
|
+
if (!inspected.State?.Running)
|
|
82
|
+
continue;
|
|
83
|
+
const environment = Object.fromEntries((inspected.Config?.Env ?? []).map((entry) => {
|
|
84
|
+
const separator = entry.indexOf('=');
|
|
85
|
+
return [entry.slice(0, separator), entry.slice(separator + 1)];
|
|
86
|
+
}));
|
|
87
|
+
await using connection = new AsyncDisposableStack();
|
|
88
|
+
let server;
|
|
89
|
+
let names;
|
|
90
|
+
try {
|
|
91
|
+
server = connection.use(await collector.open(container, environment, host));
|
|
92
|
+
names = await collector.list(server);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
for (const name of names.filter(ownedBy(runId)))
|
|
98
|
+
try {
|
|
99
|
+
await collector.drop(server, name);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (await running(container))
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
12
107
|
async function readRecordedPath(file) {
|
|
13
108
|
const { path } = JSON.parse(await readFile(file, 'utf8'));
|
|
14
109
|
return path;
|
|
@@ -62,6 +157,7 @@ export async function cleanup(engine, previous, directory) {
|
|
|
62
157
|
await rm(path, { recursive: true, force: true });
|
|
63
158
|
}
|
|
64
159
|
}
|
|
160
|
+
await dropDatabases(engine, host, previous.id, signal);
|
|
65
161
|
}
|
|
66
162
|
/** Connects to the run's engine, cleans the run, and ends the connection. */
|
|
67
163
|
export async function connectAndCleanup(previous, directory) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cleanup.js","sourceRoot":"","sources":["../../src/scripts/run-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,
|
|
1
|
+
{"version":3,"file":"run-cleanup.js","sourceRoot":"","sources":["../../src/scripts/run-cleanup.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/testing",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.43",
|
|
4
4
|
"description": "Disposable fixtures for integration tests: Docker containers and database servers, SQLite and DuckDB databases, HTTP servers and streams, temporary directories and intercepted requests. Node's global setup and global teardown remove what a killed test run left behind.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
"pg": "^8.23.1"
|
|
145
145
|
},
|
|
146
146
|
"dependencies": {
|
|
147
|
-
"@zukhruf/docker": "^0.3.
|
|
147
|
+
"@zukhruf/docker": "^0.3.43",
|
|
148
148
|
"nano-spawn": "^2.1.0",
|
|
149
149
|
"p-memoize": "^8.0.0",
|
|
150
150
|
"p-retry": "^8.0.1"
|