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 path from 'path'; import * as os from 'os'; // --------------------------------------------------------------------------- // Test: Unique index enforcement via wire protocol // Covers: unique index pre-check, createIndexes persistence, index restoration // --------------------------------------------------------------------------- let tmpDir: string; let localDb: smartdb.LocalSmartDb; let client: MongoClient; let db: Db; function makeTmpDir(): string { return fs.mkdtempSync(path.join(os.tmpdir(), 'smartdb-unique-test-')); } function cleanTmpDir(dir: string): void { if (fs.existsSync(dir)) { fs.rmSync(dir, { recursive: true, force: true }); } } // ============================================================================ // Setup // ============================================================================ tap.test('setup: start local db', async () => { tmpDir = makeTmpDir(); 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('uniquetest'); }); // ============================================================================ // Unique index enforcement on insert // ============================================================================ tap.test('unique-index: createIndex with unique: true', async () => { const coll = db.collection('users'); await coll.insertOne({ email: 'alice@example.com', name: 'Alice' }); const indexName = await coll.createIndex({ email: 1 }, { unique: true }); expect(indexName).toBeTruthy(); }); tap.test('unique-index: reject duplicate on insertOne', async () => { const coll = db.collection('users'); let threw = false; try { await coll.insertOne({ email: 'alice@example.com', name: 'Alice2' }); } catch (err: any) { threw = true; expect(err.code).toEqual(11000); } expect(threw).toBeTrue(); // Verify only 1 document exists const count = await coll.countDocuments(); expect(count).toEqual(1); }); tap.test('unique-index: allow insert with different unique value', async () => { const coll = db.collection('users'); await coll.insertOne({ email: 'bob@example.com', name: 'Bob' }); const count = await coll.countDocuments(); expect(count).toEqual(2); }); // ============================================================================ // Unique index enforcement on update // ============================================================================ tap.test('unique-index: reject duplicate on updateOne that changes unique field', async () => { const coll = db.collection('users'); let threw = false; try { await coll.updateOne( { email: 'bob@example.com' }, { $set: { email: 'alice@example.com' } } ); } catch (err: any) { threw = true; expect(err.code).toEqual(11000); } expect(threw).toBeTrue(); // Bob's email should be unchanged const bob = await coll.findOne({ name: 'Bob' }); expect(bob!.email).toEqual('bob@example.com'); }); tap.test('unique-index: allow update that keeps same unique value', async () => { const coll = db.collection('users'); await coll.updateOne( { email: 'bob@example.com' }, { $set: { name: 'Robert' } } ); const bob = await coll.findOne({ email: 'bob@example.com' }); expect(bob!.name).toEqual('Robert'); }); // ============================================================================ // Unique index enforcement on upsert // ============================================================================ tap.test('unique-index: reject duplicate on upsert insert', async () => { const coll = db.collection('users'); let threw = false; try { await coll.updateOne( { email: 'new@example.com' }, { $set: { email: 'alice@example.com', name: 'Imposter' } }, { upsert: true } ); } catch (err: any) { threw = true; } expect(threw).toBeTrue(); }); // ============================================================================ // Unique index survives restart (persistence + restoration) // ============================================================================ tap.test('unique-index: stop and restart', async () => { await client.close(); await localDb.stop(); 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('uniquetest'); }); tap.test('unique-index: enforcement persists after restart', async () => { const coll = db.collection('users'); // Data should still be there const count = await coll.countDocuments(); expect(count).toEqual(2); // Unique constraint should still be enforced without calling createIndex again let threw = false; try { await coll.insertOne({ email: 'alice@example.com', name: 'Alice3' }); } catch (err: any) { threw = true; expect(err.code).toEqual(11000); } expect(threw).toBeTrue(); // Count unchanged const countAfter = await coll.countDocuments(); expect(countAfter).toEqual(2); }); // ============================================================================ // Cleanup // ============================================================================ tap.test('unique-index: cleanup', async () => { await client.close(); await localDb.stop(); cleanTmpDir(tmpDir); }); export default tap.start();