feat(enterprise): add auth TLS and recovery hardening
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartdb from '../ts/index.js';
|
||||
import { MongoClient, Db } from 'mongodb';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
let tmpDir: string;
|
||||
let localDb: smartdb.LocalSmartDb;
|
||||
let client: MongoClient;
|
||||
let db: Db;
|
||||
let dataPath: string;
|
||||
let corruptedSize: number;
|
||||
|
||||
function makeTmpDir(): string {
|
||||
return fs.mkdtempSync(path.join(os.tmpdir(), 'smartdb-crash-test-'));
|
||||
}
|
||||
|
||||
function cleanTmpDir(dir: string): void {
|
||||
if (fs.existsSync(dir)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
async function startAndConnect(): Promise<void> {
|
||||
localDb = new smartdb.LocalSmartDb({ folderPath: tmpDir });
|
||||
const info = await localDb.start();
|
||||
client = new MongoClient(info.connectionUri, {
|
||||
directConnection: true,
|
||||
serverSelectionTimeoutMS: 5000,
|
||||
});
|
||||
await client.connect();
|
||||
db = client.db('crashtest');
|
||||
}
|
||||
|
||||
tap.test('crash-recovery: create baseline data', async () => {
|
||||
tmpDir = makeTmpDir();
|
||||
await startAndConnect();
|
||||
|
||||
await db.collection('docs').insertMany([
|
||||
{ key: 'a', value: 1 },
|
||||
{ key: 'b', value: 2 },
|
||||
{ key: 'c', value: 3 },
|
||||
]);
|
||||
|
||||
await client.close();
|
||||
await localDb.stop();
|
||||
|
||||
dataPath = path.join(tmpDir, 'crashtest', 'docs', 'data.rdb');
|
||||
expect(fs.existsSync(dataPath)).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('crash-recovery: append a torn final record', async () => {
|
||||
const data = fs.readFileSync(dataPath);
|
||||
const partialRecord = data.subarray(64, 94);
|
||||
expect(partialRecord.length).toEqual(30);
|
||||
|
||||
fs.appendFileSync(dataPath, partialRecord);
|
||||
corruptedSize = fs.statSync(dataPath).size;
|
||||
expect(corruptedSize).toEqual(data.length + partialRecord.length);
|
||||
});
|
||||
|
||||
tap.test('crash-recovery: restart truncates invalid tail and preserves valid records', async () => {
|
||||
await startAndConnect();
|
||||
|
||||
const repairedSize = fs.statSync(dataPath).size;
|
||||
expect(repairedSize < corruptedSize).toBeTrue();
|
||||
|
||||
const docs = await db.collection('docs').find({}).sort({ key: 1 }).toArray();
|
||||
expect(docs.map(doc => doc.key)).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
||||
tap.test('crash-recovery: future writes remain durable after tail repair', async () => {
|
||||
await db.collection('docs').insertOne({ key: 'd', value: 4 });
|
||||
expect(await db.collection('docs').countDocuments()).toEqual(4);
|
||||
|
||||
await client.close();
|
||||
await localDb.stop();
|
||||
|
||||
await startAndConnect();
|
||||
const docs = await db.collection('docs').find({}).sort({ key: 1 }).toArray();
|
||||
expect(docs.map(doc => doc.key)).toEqual(['a', 'b', 'c', 'd']);
|
||||
});
|
||||
|
||||
tap.test('crash-recovery: cleanup', async () => {
|
||||
await client.close();
|
||||
await localDb.stop();
|
||||
cleanTmpDir(tmpDir);
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
Reference in New Issue
Block a user