Skip to content

Commit 7f1bf1c

Browse files
cjihrigtargos
authored andcommittedAug 14, 2024
sqlite: split up large test file
The original test/parallel/test-sqlite.js test appears to time out in the CI occasionally. This commit splits the test into several smaller test files. Fixes: #54006 PR-URL: #54014 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent 94e2ea6 commit 7f1bf1c

6 files changed

+765
-662
lines changed
 
+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Flags: --experimental-sqlite
2+
'use strict';
3+
require('../common');
4+
const tmpdir = require('../common/tmpdir');
5+
const { join } = require('node:path');
6+
const { DatabaseSync } = require('node:sqlite');
7+
const { suite, test } = require('node:test');
8+
let cnt = 0;
9+
10+
tmpdir.refresh();
11+
12+
function nextDb() {
13+
return join(tmpdir.path, `database-${cnt++}.db`);
14+
}
15+
16+
suite('data binding and mapping', () => {
17+
test('supported data types', (t) => {
18+
const u8a = new TextEncoder().encode('a☃b☃c');
19+
const db = new DatabaseSync(nextDb());
20+
t.after(() => { db.close(); });
21+
const setup = db.exec(`
22+
CREATE TABLE types(
23+
key INTEGER PRIMARY KEY,
24+
int INTEGER,
25+
double REAL,
26+
text TEXT,
27+
buf BLOB
28+
) STRICT;
29+
`);
30+
t.assert.strictEqual(setup, undefined);
31+
const stmt = db.prepare('INSERT INTO types (key, int, double, text, buf) ' +
32+
'VALUES (?, ?, ?, ?, ?)');
33+
t.assert.deepStrictEqual(
34+
stmt.run(1, 42, 3.14159, 'foo', u8a),
35+
{ changes: 1, lastInsertRowid: 1 },
36+
);
37+
t.assert.deepStrictEqual(
38+
stmt.run(2, null, null, null, null),
39+
{ changes: 1, lastInsertRowid: 2 }
40+
);
41+
t.assert.deepStrictEqual(
42+
stmt.run(3, Number(8), Number(2.718), String('bar'), Buffer.from('x☃y☃')),
43+
{ changes: 1, lastInsertRowid: 3 },
44+
);
45+
t.assert.deepStrictEqual(
46+
stmt.run(4, 99n, 0xf, '', new Uint8Array()),
47+
{ changes: 1, lastInsertRowid: 4 },
48+
);
49+
50+
const query = db.prepare('SELECT * FROM types WHERE key = ?');
51+
t.assert.deepStrictEqual(query.get(1), {
52+
key: 1,
53+
int: 42,
54+
double: 3.14159,
55+
text: 'foo',
56+
buf: u8a,
57+
});
58+
t.assert.deepStrictEqual(query.get(2), {
59+
key: 2,
60+
int: null,
61+
double: null,
62+
text: null,
63+
buf: null,
64+
});
65+
t.assert.deepStrictEqual(query.get(3), {
66+
key: 3,
67+
int: 8,
68+
double: 2.718,
69+
text: 'bar',
70+
buf: new TextEncoder().encode('x☃y☃'),
71+
});
72+
t.assert.deepStrictEqual(query.get(4), {
73+
key: 4,
74+
int: 99,
75+
double: 0xf,
76+
text: '',
77+
buf: new Uint8Array(),
78+
});
79+
});
80+
81+
test('unsupported data types', (t) => {
82+
const db = new DatabaseSync(nextDb());
83+
t.after(() => { db.close(); });
84+
const setup = db.exec(
85+
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
86+
);
87+
t.assert.strictEqual(setup, undefined);
88+
89+
[
90+
undefined,
91+
() => {},
92+
Symbol(),
93+
/foo/,
94+
Promise.resolve(),
95+
new Map(),
96+
new Set(),
97+
].forEach((val) => {
98+
t.assert.throws(() => {
99+
db.prepare('INSERT INTO types (key, val) VALUES (?, ?)').run(1, val);
100+
}, {
101+
code: 'ERR_INVALID_ARG_TYPE',
102+
message: /Provided value cannot be bound to SQLite parameter 2/,
103+
});
104+
});
105+
106+
t.assert.throws(() => {
107+
const stmt = db.prepare('INSERT INTO types (key, val) VALUES ($k, $v)');
108+
stmt.run({ $k: 1, $v: () => {} });
109+
}, {
110+
code: 'ERR_INVALID_ARG_TYPE',
111+
message: /Provided value cannot be bound to SQLite parameter 2/,
112+
});
113+
});
114+
115+
test('throws when binding a BigInt that is too large', (t) => {
116+
const max = 9223372036854775807n; // Largest 64-bit signed integer value.
117+
const db = new DatabaseSync(nextDb());
118+
t.after(() => { db.close(); });
119+
const setup = db.exec(
120+
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
121+
);
122+
t.assert.strictEqual(setup, undefined);
123+
const stmt = db.prepare('INSERT INTO types (key, val) VALUES (?, ?)');
124+
t.assert.deepStrictEqual(
125+
stmt.run(1, max),
126+
{ changes: 1, lastInsertRowid: 1 },
127+
);
128+
t.assert.throws(() => {
129+
stmt.run(1, max + 1n);
130+
}, {
131+
code: 'ERR_INVALID_ARG_VALUE',
132+
message: /BigInt value is too large to bind/,
133+
});
134+
});
135+
136+
test('statements are unbound on each call', (t) => {
137+
const db = new DatabaseSync(nextDb());
138+
t.after(() => { db.close(); });
139+
const setup = db.exec(
140+
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
141+
);
142+
t.assert.strictEqual(setup, undefined);
143+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)');
144+
t.assert.deepStrictEqual(
145+
stmt.run(1, 5),
146+
{ changes: 1, lastInsertRowid: 1 },
147+
);
148+
t.assert.deepStrictEqual(
149+
stmt.run(),
150+
{ changes: 1, lastInsertRowid: 2 },
151+
);
152+
t.assert.deepStrictEqual(
153+
db.prepare('SELECT * FROM data ORDER BY key').all(),
154+
[{ key: 1, val: 5 }, { key: 2, val: null }],
155+
);
156+
});
157+
});
+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Flags: --experimental-sqlite
2+
'use strict';
3+
require('../common');
4+
const tmpdir = require('../common/tmpdir');
5+
const { existsSync } = require('node:fs');
6+
const { join } = require('node:path');
7+
const { DatabaseSync, StatementSync } = require('node:sqlite');
8+
const { suite, test } = require('node:test');
9+
let cnt = 0;
10+
11+
tmpdir.refresh();
12+
13+
function nextDb() {
14+
return join(tmpdir.path, `database-${cnt++}.db`);
15+
}
16+
17+
suite('DatabaseSync() constructor', () => {
18+
test('throws if called without new', (t) => {
19+
t.assert.throws(() => {
20+
DatabaseSync();
21+
}, {
22+
code: 'ERR_CONSTRUCT_CALL_REQUIRED',
23+
message: /Cannot call constructor without `new`/,
24+
});
25+
});
26+
27+
test('throws if database path is not a string', (t) => {
28+
t.assert.throws(() => {
29+
new DatabaseSync();
30+
}, {
31+
code: 'ERR_INVALID_ARG_TYPE',
32+
message: /The "path" argument must be a string/,
33+
});
34+
});
35+
36+
test('throws if options is provided but is not an object', (t) => {
37+
t.assert.throws(() => {
38+
new DatabaseSync('foo', null);
39+
}, {
40+
code: 'ERR_INVALID_ARG_TYPE',
41+
message: /The "options" argument must be an object/,
42+
});
43+
});
44+
45+
test('throws if options.open is provided but is not a boolean', (t) => {
46+
t.assert.throws(() => {
47+
new DatabaseSync('foo', { open: 5 });
48+
}, {
49+
code: 'ERR_INVALID_ARG_TYPE',
50+
message: /The "options\.open" argument must be a boolean/,
51+
});
52+
});
53+
});
54+
55+
suite('DatabaseSync.prototype.open()', () => {
56+
test('opens a database connection', (t) => {
57+
const dbPath = nextDb();
58+
const db = new DatabaseSync(dbPath, { open: false });
59+
t.after(() => { db.close(); });
60+
61+
t.assert.strictEqual(existsSync(dbPath), false);
62+
t.assert.strictEqual(db.open(), undefined);
63+
t.assert.strictEqual(existsSync(dbPath), true);
64+
});
65+
66+
test('throws if database is already open', (t) => {
67+
const db = new DatabaseSync(nextDb(), { open: false });
68+
t.after(() => { db.close(); });
69+
70+
db.open();
71+
t.assert.throws(() => {
72+
db.open();
73+
}, {
74+
code: 'ERR_INVALID_STATE',
75+
message: /database is already open/,
76+
});
77+
});
78+
});
79+
80+
suite('DatabaseSync.prototype.close()', () => {
81+
test('closes an open database connection', (t) => {
82+
const db = new DatabaseSync(nextDb());
83+
84+
t.assert.strictEqual(db.close(), undefined);
85+
});
86+
87+
test('throws if database is not open', (t) => {
88+
const db = new DatabaseSync(nextDb(), { open: false });
89+
90+
t.assert.throws(() => {
91+
db.close();
92+
}, {
93+
code: 'ERR_INVALID_STATE',
94+
message: /database is not open/,
95+
});
96+
});
97+
});
98+
99+
suite('DatabaseSync.prototype.prepare()', () => {
100+
test('returns a prepared statement', (t) => {
101+
const db = new DatabaseSync(nextDb());
102+
t.after(() => { db.close(); });
103+
const stmt = db.prepare('CREATE TABLE webstorage(key TEXT)');
104+
t.assert.ok(stmt instanceof StatementSync);
105+
});
106+
107+
test('throws if database is not open', (t) => {
108+
const db = new DatabaseSync(nextDb(), { open: false });
109+
110+
t.assert.throws(() => {
111+
db.prepare();
112+
}, {
113+
code: 'ERR_INVALID_STATE',
114+
message: /database is not open/,
115+
});
116+
});
117+
118+
test('throws if sql is not a string', (t) => {
119+
const db = new DatabaseSync(nextDb());
120+
t.after(() => { db.close(); });
121+
122+
t.assert.throws(() => {
123+
db.prepare();
124+
}, {
125+
code: 'ERR_INVALID_ARG_TYPE',
126+
message: /The "sql" argument must be a string/,
127+
});
128+
});
129+
});
130+
131+
suite('DatabaseSync.prototype.exec()', () => {
132+
test('executes SQL', (t) => {
133+
const db = new DatabaseSync(nextDb());
134+
t.after(() => { db.close(); });
135+
const result = db.exec(`
136+
CREATE TABLE data(
137+
key INTEGER PRIMARY KEY,
138+
val INTEGER
139+
) STRICT;
140+
INSERT INTO data (key, val) VALUES (1, 2);
141+
INSERT INTO data (key, val) VALUES (8, 9);
142+
`);
143+
t.assert.strictEqual(result, undefined);
144+
const stmt = db.prepare('SELECT * FROM data ORDER BY key');
145+
t.assert.deepStrictEqual(stmt.all(), [
146+
{ key: 1, val: 2 },
147+
{ key: 8, val: 9 },
148+
]);
149+
});
150+
151+
test('reports errors from SQLite', (t) => {
152+
const db = new DatabaseSync(nextDb());
153+
t.after(() => { db.close(); });
154+
155+
t.assert.throws(() => {
156+
db.exec('CREATE TABLEEEE');
157+
}, {
158+
code: 'ERR_SQLITE_ERROR',
159+
message: /syntax error/,
160+
});
161+
});
162+
163+
test('throws if database is not open', (t) => {
164+
const db = new DatabaseSync(nextDb(), { open: false });
165+
166+
t.assert.throws(() => {
167+
db.exec();
168+
}, {
169+
code: 'ERR_INVALID_STATE',
170+
message: /database is not open/,
171+
});
172+
});
173+
174+
test('throws if sql is not a string', (t) => {
175+
const db = new DatabaseSync(nextDb());
176+
t.after(() => { db.close(); });
177+
178+
t.assert.throws(() => {
179+
db.exec();
180+
}, {
181+
code: 'ERR_INVALID_ARG_TYPE',
182+
message: /The "sql" argument must be a string/,
183+
});
184+
});
185+
});

0 commit comments

Comments
 (0)