release: v0.3.2 — 质量加固 + SQL扩展 + 表达式 + 并发同步
v0.2.6 质量加固: - 修复 AriaEngine 二级索引 SSTable 互相覆盖(命名空间隔离) - 修复 LSM 多版本读取顺序错误 + MergeIterator 取最新来源 - 重写 LZ4 压缩器(往返一致性 + 缓冲区溢出) - sstableCache LRU 上限 + 预加载兜底(BufferPool 配置生效) - 修复 React/Vue 集成 import type 运行时 bug + exports 子路径 - 新增 38 个测试(LZ4往返/Crypto/集成), 删除伪测试 v0.3.0 SQL 功能扩展: - 多语句 parseAll + 事务语句 BEGIN/COMMIT/ROLLBACK - INSERT INTO ... SELECT + UNION/UNION ALL + EXISTS 关联子查询 - CREATE/DROP INDEX 五引擎实现 + 别名 WHERE 修复 - benchmark 页面 + 36 个新测试 v0.3.1 表达式与性能: - CASE WHEN 表达式(SELECT 列/WHERE/聚合) - JOIN + 关联子查询逐行绑定 - WAL 批量组提交(写放大 O(N)→O(1)) - 修复 pending frozen 可见性 + flush 缓存竞争 v0.3.2 并发: - CASE WHEN 用于 WHERE/聚合 + JOIN 哈希连接 - 多标签页同步(multiTabSync + BroadcastChannel) - IndexedDB schema 持久化(reopen 后表结构恢复) - 修复 where-matcher 顶层 $not - 修复 CJS 产物 .js 被 ESM 解析(exports 空) — .cjs 后缀 + exports 修正 - 836 测试 / 44 套件 / 81.0% 覆盖率
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* AriaEngine CryptoManager 加解密测试
|
||||
* @module tests/engine/aria-crypto
|
||||
*
|
||||
* v0.2.6 补强:此前仅验证实例化,现在验证真实的加解密往返一致性。
|
||||
*/
|
||||
import {
|
||||
CryptoManager,
|
||||
initCrypto,
|
||||
encryptPage,
|
||||
decryptPage,
|
||||
closeCrypto,
|
||||
} from '../../src/engine/aria/crypto';
|
||||
|
||||
function toBytes(data: ArrayBuffer): number[] {
|
||||
return Array.from(new Uint8Array(data));
|
||||
}
|
||||
|
||||
describe('AriaEngine — CryptoManager', () => {
|
||||
test('加解密往返一致', async () => {
|
||||
const cm = new CryptoManager();
|
||||
await cm.init('test-password');
|
||||
expect(cm.enabled).toBe(true);
|
||||
|
||||
const original = new TextEncoder().encode('sensitive row data').buffer;
|
||||
const { iv, data } = await cm.encryptPage(original);
|
||||
// 密文应为乱码(与原文不同)
|
||||
expect(toBytes(data)).not.toEqual(toBytes(original));
|
||||
|
||||
const decrypted = await cm.decryptPage(iv, data);
|
||||
expect(toBytes(decrypted)).toEqual(toBytes(original));
|
||||
cm.close();
|
||||
expect(cm.enabled).toBe(false);
|
||||
});
|
||||
|
||||
test('错误密码解密失败(密钥不同)', async () => {
|
||||
const cm1 = new CryptoManager();
|
||||
await cm1.init('correct-password');
|
||||
const original = new TextEncoder().encode('top secret').buffer;
|
||||
const { iv, data } = await cm1.encryptPage(original);
|
||||
|
||||
const cm2 = new CryptoManager();
|
||||
await cm2.init('wrong-password');
|
||||
await expect(cm2.decryptPage(iv, data)).rejects.toThrow();
|
||||
|
||||
cm1.close();
|
||||
cm2.close();
|
||||
});
|
||||
|
||||
test('不同 salt 派生不同密钥,解密互相失败', async () => {
|
||||
const cm1 = new CryptoManager();
|
||||
await cm1.init('pwd', new Uint8Array(16).fill(1));
|
||||
const cm2 = new CryptoManager();
|
||||
await cm2.init('pwd', new Uint8Array(16).fill(2));
|
||||
|
||||
const original = new TextEncoder().encode('salt matters').buffer;
|
||||
const { iv, data } = await cm1.encryptPage(original);
|
||||
await expect(cm2.decryptPage(iv, data)).rejects.toThrow();
|
||||
|
||||
cm1.close();
|
||||
cm2.close();
|
||||
});
|
||||
|
||||
test('未初始化时加密抛错', async () => {
|
||||
const cm = new CryptoManager();
|
||||
expect(cm.enabled).toBe(false);
|
||||
const data = new TextEncoder().encode('x').buffer;
|
||||
await expect(cm.encryptPage(data)).rejects.toThrow(/not initialized/);
|
||||
});
|
||||
|
||||
test('不同实例互不影响(独立密钥状态)', async () => {
|
||||
const cm1 = new CryptoManager();
|
||||
await cm1.init('pwd-a');
|
||||
const cm2 = new CryptoManager();
|
||||
await cm2.init('pwd-b');
|
||||
|
||||
const original = new TextEncoder().encode('instance isolation').buffer;
|
||||
const { iv, data } = await cm1.encryptPage(original);
|
||||
await expect(cm2.decryptPage(iv, data)).rejects.toThrow();
|
||||
|
||||
// 各自解密自己的数据
|
||||
const dec2orig = new TextEncoder().encode('two').buffer;
|
||||
const enc2 = await cm2.encryptPage(dec2orig);
|
||||
const dec2 = await cm2.decryptPage(enc2.iv, enc2.data);
|
||||
expect(toBytes(dec2)).toEqual(toBytes(dec2orig));
|
||||
|
||||
cm1.close();
|
||||
cm2.close();
|
||||
});
|
||||
|
||||
test('全局兼容层往返一致', async () => {
|
||||
await initCrypto('global-password');
|
||||
const original = new TextEncoder().encode('global compat layer').buffer;
|
||||
const { iv, data } = await encryptPage(original);
|
||||
const decrypted = await decryptPage(iv, data);
|
||||
expect(toBytes(decrypted)).toEqual(toBytes(original));
|
||||
closeCrypto();
|
||||
});
|
||||
|
||||
test('大块数据(接近页面大小)往返一致', async () => {
|
||||
const cm = new CryptoManager();
|
||||
await cm.init('page-size-test');
|
||||
// 4KB 页面数据
|
||||
const original = new Uint8Array(4096);
|
||||
for (let i = 0; i < 4096; i++) original[i] = i % 251;
|
||||
const { iv, data } = await cm.encryptPage(original.buffer);
|
||||
const decrypted = await cm.decryptPage(iv, data);
|
||||
expect(toBytes(decrypted)).toEqual(toBytes(original.buffer));
|
||||
cm.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user