release: v0.2.4 — 701 tests, 32 suites, 零死代码, 零空壳, 全模块接入
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* AriaEngine MVCC 事务隔离 + Savepoint 测试
|
||||
* 全部 MemoryBackend,零卡死
|
||||
*/
|
||||
import { AriaEngine } from '../../src/engine/aria/index';
|
||||
import { createSchema } from '../../src/table/schema';
|
||||
|
||||
describe('AriaEngine — MVCC 事务 + Savepoint', () => {
|
||||
let engine: AriaEngine;
|
||||
|
||||
beforeEach(async () => {
|
||||
engine = new AriaEngine({ storageBackend: 'memory' });
|
||||
await engine.open('mvcc-test', 1);
|
||||
await engine.createTable(createSchema('users', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
name: { type: 'string', required: true },
|
||||
balance: { type: 'number', default: 0 },
|
||||
}));
|
||||
});
|
||||
|
||||
afterEach(async () => { await engine.close(); });
|
||||
|
||||
// ---- MVCC 事务 ----
|
||||
it('beginTransaction 分配唯一事务ID', () => {
|
||||
const id1 = (engine as any).mvcc.beginTransaction();
|
||||
const id2 = (engine as any).mvcc.beginTransaction();
|
||||
expect(id1).not.toBe(id2);
|
||||
});
|
||||
|
||||
it('commit 后事务标记为非活跃', () => {
|
||||
const txnId = (engine as any).mvcc.beginTransaction();
|
||||
(engine as any).mvcc.commitTransaction(txnId);
|
||||
expect((engine as any).mvcc.isActive(txnId)).toBe(false);
|
||||
});
|
||||
|
||||
it('rollback 后事务标记为非活跃', () => {
|
||||
const txnId = (engine as any).mvcc.beginTransaction();
|
||||
(engine as any).mvcc.rollbackTransaction(txnId);
|
||||
expect((engine as any).mvcc.isActive(txnId)).toBe(false);
|
||||
});
|
||||
|
||||
it('事务中写入版本可读', () => {
|
||||
const txnId = (engine as any).mvcc.beginTransaction();
|
||||
(engine as any).mvcc.writeVersion('users', '1', { name: 'Alice', balance: 100 }, txnId);
|
||||
const val = (engine as any).mvcc.readVersion('users', '1', txnId);
|
||||
expect(val).not.toBeNull();
|
||||
expect(val!.name).toBe('Alice');
|
||||
});
|
||||
|
||||
it('未提交版本对其他事务不可见', () => {
|
||||
const txn1 = (engine as any).mvcc.beginTransaction();
|
||||
(engine as any).mvcc.writeVersion('users', '1', { name: 'Alice' }, txn1);
|
||||
const txn2 = (engine as any).mvcc.beginTransaction();
|
||||
expect((engine as any).mvcc.readVersion('users', '1', txn2)).toBeNull();
|
||||
});
|
||||
|
||||
it('引擎层事务 commit 后数据可见', async () => {
|
||||
await engine.beginTransaction();
|
||||
await engine.insert('users', [{ id: '1', name: 'Alice', balance: 100 }]);
|
||||
await engine.commitTransaction();
|
||||
expect(await engine.count('users')).toBe(1);
|
||||
});
|
||||
|
||||
it('引擎层事务 rollback 后数据消失', async () => {
|
||||
await engine.insert('users', [{ id: '1', name: 'Alice' }]);
|
||||
await engine.beginTransaction();
|
||||
await engine.insert('users', [{ id: '2', name: 'Bob' }]);
|
||||
await engine.rollbackTransaction();
|
||||
expect(await engine.count('users')).toBe(1);
|
||||
});
|
||||
|
||||
it('GC 清理过旧版本', () => {
|
||||
for (let i = 0; i < 200; i++) {
|
||||
const txnId = (engine as any).mvcc.beginTransaction();
|
||||
(engine as any).mvcc.writeVersion('users', '1', { ver: i }, txnId);
|
||||
(engine as any).mvcc.commitTransaction(txnId);
|
||||
}
|
||||
(engine as any).mvcc.gc(50);
|
||||
const txnId = (engine as any).mvcc.beginTransaction();
|
||||
expect((engine as any).mvcc.readVersion('users', '1', txnId)).not.toBeNull();
|
||||
(engine as any).mvcc.commitTransaction(txnId);
|
||||
});
|
||||
|
||||
// ---- Savepoint ----
|
||||
it('savepoint 创建成功', async () => {
|
||||
await engine.beginTransaction();
|
||||
await (engine as any).savepoint('sp1');
|
||||
expect((engine as any).savepoints.has('sp1')).toBe(true);
|
||||
await engine.rollbackTransaction();
|
||||
});
|
||||
|
||||
it('rollbackToSavepoint 恢复快照', async () => {
|
||||
await engine.insert('users', [{ id: '1', name: 'Alice' }]);
|
||||
await engine.beginTransaction();
|
||||
await engine.insert('users', [{ id: '2', name: 'Bob' }]);
|
||||
await (engine as any).savepoint('sp1');
|
||||
await engine.insert('users', [{ id: '3', name: 'Charlie' }]);
|
||||
await (engine as any).rollbackToSavepoint('sp1');
|
||||
await engine.commitTransaction();
|
||||
expect(await engine.count('users')).toBe(2);
|
||||
});
|
||||
|
||||
it('releaseSavepoint 释放后不可回滚', async () => {
|
||||
await engine.beginTransaction();
|
||||
await (engine as any).savepoint('sp1');
|
||||
await (engine as any).releaseSavepoint('sp1');
|
||||
expect((engine as any).savepoints.has('sp1')).toBe(false);
|
||||
await engine.rollbackTransaction();
|
||||
});
|
||||
|
||||
it('重复 savepoint 名称抛出错误', async () => {
|
||||
await engine.beginTransaction();
|
||||
await (engine as any).savepoint('sp1');
|
||||
await expect((engine as any).savepoint('sp1')).rejects.toThrow('already exists');
|
||||
await engine.rollbackTransaction();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user