release: v0.6.0 — 完全移除 IndexedDB,自研 KVStore 事务存储引擎(多key原子写/快照日志恢复/CRC自愈)+ KVStoreEngine + 旧库迁移工具 + 10万级压力验证 + 崩溃注入e2e
This commit is contained in:
@@ -14,7 +14,10 @@ import { AriaEngine } from '../../src/engine/aria/index';
|
||||
import { EncryptedBackend } from '../../src/engine/aria/store/encrypted_backend';
|
||||
import { MemoryBackend } from '../../src/engine/aria/store/backend';
|
||||
import { createSchema } from '../../src/table/schema';
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
import { installOPFSMock } from '../helpers/opfs-mock';
|
||||
|
||||
beforeEach(() => { installOPFSMock(new Map()); });
|
||||
|
||||
let idbCounter = 0;
|
||||
function uniqueDB(): string {
|
||||
@@ -182,7 +185,7 @@ describe('AriaEngine — EncryptedBackend 单元', () => {
|
||||
describe('AriaEngine — 全库加密(集成)', () => {
|
||||
it('加密库:写入 → close → 同密码重开数据完整', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'master-pass' } });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'master-pass' } });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(SCHEMA());
|
||||
await engine.insert('users', [
|
||||
@@ -193,7 +196,7 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
await engine.close();
|
||||
|
||||
// 重开(同密码)
|
||||
const engine2 = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'master-pass' } });
|
||||
const engine2 = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'master-pass' } });
|
||||
await engine2.open(dbName, 1);
|
||||
const rows = await engine2.find('users', { table: 'users' });
|
||||
expect(rows).toHaveLength(2);
|
||||
@@ -206,42 +209,42 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
|
||||
it('加密库:错误密码重开 → ARIA_DECRYPT_ERROR', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'right-pass' } });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'right-pass' } });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(SCHEMA());
|
||||
await engine.insert('users', [{ id: '1', name: 'A', secret: 'x' }]);
|
||||
await engine.close();
|
||||
|
||||
const engine2 = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'wrong-pass' } });
|
||||
const engine2 = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'wrong-pass' } });
|
||||
await expect(engine2.open(dbName, 1)).rejects.toMatchObject({ code: 'ARIA_DECRYPT_ERROR' });
|
||||
});
|
||||
|
||||
it('加密库:无密码打开 → ARIA_ENCRYPT_REQUIRED', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'pw' } });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'pw' } });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(SCHEMA());
|
||||
await engine.close();
|
||||
|
||||
const engine2 = new AriaEngine({ storageBackend: 'indexeddb' });
|
||||
const engine2 = new AriaEngine({ storageBackend: 'opfs' });
|
||||
await expect(engine2.open(dbName, 1)).rejects.toMatchObject({ code: 'ARIA_ENCRYPT_REQUIRED' });
|
||||
});
|
||||
|
||||
it('明文库:加密配置打开 → ARIA_ENCRYPT_CONFIG_ERROR', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb' });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs' });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(SCHEMA());
|
||||
await engine.insert('users', [{ id: '1', name: 'A', secret: 'plain' }]);
|
||||
await engine.close();
|
||||
|
||||
const engine2 = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'pw' } });
|
||||
const engine2 = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'pw' } });
|
||||
await expect(engine2.open(dbName, 1)).rejects.toMatchObject({ code: 'ARIA_ENCRYPT_CONFIG_ERROR' });
|
||||
});
|
||||
|
||||
it('加密库:底层存储全部为密文(SSTable/Schema/WAL 均不可见明文)', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'pw' } });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'pw' } });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(SCHEMA());
|
||||
await engine.insert('users', [{ id: '1', name: 'Alice', secret: 'needle-in-cipher' }]);
|
||||
@@ -267,7 +270,7 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
it('加密 + 压缩组合:往返完整(压缩层先压,加密层后加密)', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({
|
||||
storageBackend: 'indexeddb',
|
||||
storageBackend: 'opfs',
|
||||
compression: true,
|
||||
encryption: { password: 'pw-compress' },
|
||||
memtableSizeThreshold: 64 * 1024 * 1024,
|
||||
@@ -283,7 +286,7 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
await engine.close();
|
||||
|
||||
const engine2 = new AriaEngine({
|
||||
storageBackend: 'indexeddb',
|
||||
storageBackend: 'opfs',
|
||||
compression: true,
|
||||
encryption: { password: 'pw-compress' },
|
||||
});
|
||||
@@ -296,7 +299,7 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
|
||||
it('加密库:clearAll 保留密钥(库身份),同密码重开重建,新密码被拒', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'old-pw' } });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'old-pw' } });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(SCHEMA());
|
||||
await engine.insert('users', [{ id: '1', name: 'A', secret: 'x' }]);
|
||||
@@ -304,11 +307,11 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
await engine.close();
|
||||
|
||||
// clearAll 保留 keymeta → 换新密码会被拒绝
|
||||
const engineWrong = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'new-pw' } });
|
||||
const engineWrong = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'new-pw' } });
|
||||
await expect(engineWrong.open(dbName, 1)).rejects.toMatchObject({ code: 'ARIA_DECRYPT_ERROR' });
|
||||
|
||||
// 同密码重开可重建
|
||||
const engine2 = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'old-pw' } });
|
||||
const engine2 = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'old-pw' } });
|
||||
await engine2.open(dbName, 1);
|
||||
await engine2.createTable(SCHEMA());
|
||||
await engine2.insert('users', [{ id: '1', name: 'A', secret: 'new' }]);
|
||||
@@ -319,7 +322,7 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
it('加密库:WAL 崩溃恢复路径可用(含加密 WAL)', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({
|
||||
storageBackend: 'indexeddb',
|
||||
storageBackend: 'opfs',
|
||||
encryption: { password: 'pw' },
|
||||
walSyncMode: 'full',
|
||||
checkpointInterval: 100000,
|
||||
@@ -336,7 +339,7 @@ describe('AriaEngine — 全库加密(集成)', () => {
|
||||
|
||||
// 重开:WAL 重放(加密 WAL 解密后解析)
|
||||
const engine2 = new AriaEngine({
|
||||
storageBackend: 'indexeddb',
|
||||
storageBackend: 'opfs',
|
||||
encryption: { password: 'pw' },
|
||||
walSyncMode: 'full',
|
||||
checkpointInterval: 100000,
|
||||
|
||||
Reference in New Issue
Block a user