node/test/sqlite/test_sqlite_extensions/test.js

115 lines
3.4 KiB
JavaScript

'use strict';
const common = require('../../common');
const assert = require('node:assert');
const path = require('node:path');
const sqlite = require('node:sqlite');
const test = require('node:test');
const fs = require('node:fs');
const childProcess = require('node:child_process');
if (process.config.variables.node_shared_sqlite) {
common.skip('Missing libsqlite_extension binary');
}
// Lib extension binary is named differently on different platforms
function resolveBuiltBinary() {
const buildDir = `${__dirname}/build/${common.buildType}`;
const lib = 'sqlite_extension';
const targetFile = fs.readdirSync(buildDir).find((file) => file.startsWith(lib));
return path.join(buildDir, targetFile);
}
const binary = resolveBuiltBinary();
test('should load extension successfully', () => {
const db = new sqlite.DatabaseSync(':memory:', {
allowExtension: true,
});
db.loadExtension(binary);
db.exec('SELECT noop(\'Hello, world!\');');
const query = db.prepare('SELECT noop(\'Hello, World!\') AS result');
const { result } = query.get();
assert.strictEqual(result, 'Hello, World!');
});
test('should not load extension', () => {
const db = new sqlite.DatabaseSync(':memory:', {
allowExtension: false,
});
assert.throws(() => {
db.exec('SELECT noop(\'Hello, world!\');');
}, {
message: 'no such function: noop',
code: 'ERR_SQLITE_ERROR',
});
assert.throws(() => {
db.loadExtension(binary);
}, {
message: 'extension loading is not allowed',
code: 'ERR_INVALID_STATE',
});
assert.throws(() => {
const query = db.prepare('SELECT load_extension(?)');
query.run(binary);
}, {
message: 'not authorized',
code: 'ERR_SQLITE_ERROR',
});
assert.throws(() => {
db.enableLoadExtension();
}, {
message: 'The "allow" argument must be a boolean.',
code: 'ERR_INVALID_ARG_TYPE',
});
assert.throws(() => {
db.enableLoadExtension(true);
}, {
message: 'Cannot enable extension loading because it was disabled at database creation.',
});
});
test('should load extension successfully with enableLoadExtension', () => {
const db = new sqlite.DatabaseSync(':memory:', {
allowExtension: true,
});
db.loadExtension(binary);
db.enableLoadExtension(false);
db.exec('SELECT noop(\'Hello, world!\');');
const query = db.prepare('SELECT noop(\'Hello, World!\') AS result');
const { result } = query.get();
assert.strictEqual(result, 'Hello, World!');
});
test('should not load extension with enableLoadExtension', () => {
const db = new sqlite.DatabaseSync(':memory:', {
allowExtension: true,
});
db.enableLoadExtension(false);
assert.throws(() => {
db.loadExtension(binary);
}, {
message: 'extension loading is not allowed',
});
});
test('should throw error if permission is enabled', async () => {
const [cmd, opts] = common.escapePOSIXShell`"${process.execPath}" `;
const code = `const sqlite = require('node:sqlite');
const db = new sqlite.DatabaseSync(':memory:', { allowExtension: true });`;
return new Promise((resolve) => {
childProcess.exec(
`${cmd} --permission -e "${code}"`,
{
...opts,
},
common.mustCall((err, _, stderr) => {
assert.strictEqual(err.code, 1);
assert.match(stderr, /Error: Cannot load SQLite extensions when the permission model is enabled/);
assert.match(stderr, /code: 'ERR_LOAD_SQLITE_EXTENSION'/);
resolve();
}),
);
});
});