/** * MemoryEngine 测试 */ import { MemoryEngine } from '../../src/engine/memory'; import { createSchema } from '../../src/table/schema'; describe('MemoryEngine', () => { let engine: MemoryEngine; const userSchema = createSchema('users', { id: { type: 'string', primaryKey: true }, name: { type: 'string', required: true }, age: { type: 'number', default: 0 }, email: { type: 'string', unique: true }, }); beforeEach(async () => { engine = new MemoryEngine(); await engine.open('test-db', 1); }); afterEach(async () => { await engine.close(); }); // ---- 生命周期 ---- describe('open/close', () => { it('打开后 isOpen 返回 true', () => { expect(engine.isOpen()).toBe(true); }); it('关闭后 isOpen 返回 false', async () => { await engine.close(); expect(engine.isOpen()).toBe(false); }); }); // ---- 表管理 ---- describe('表管理', () => { it('创建表', async () => { await engine.createTable(userSchema); expect(await engine.hasTable('users')).toBe(true); }); it('重复创建表抛出错误', async () => { await engine.createTable(userSchema); await expect(engine.createTable(userSchema)).rejects.toThrow('already exists'); }); it('获取所有表名', async () => { await engine.createTable(userSchema); const names = await engine.getTableNames(); expect(names).toContain('users'); }); it('删除表', async () => { await engine.createTable(userSchema); await engine.dropTable('users'); expect(await engine.hasTable('users')).toBe(false); }); }); // ---- CRUD ---- describe('插入', () => { beforeEach(async () => { await engine.createTable(userSchema); }); it('插入单行', async () => { const pks = await engine.insert('users', [ { id: '1', name: 'Alice', age: 30, email: 'alice@test.com' }, ]); expect(pks).toEqual(['1']); }); it('插入多行', async () => { const pks = await engine.insert('users', [ { id: '1', name: 'Alice', age: 30, email: 'alice@test.com' }, { id: '2', name: 'Bob', age: 25, email: 'bob@test.com' }, ]); expect(pks).toEqual(['1', '2']); }); it('重复主键抛出错误', async () => { await engine.insert('users', [{ id: '1', name: 'Alice', email: 'a@t.com' }]); await expect( engine.insert('users', [{ id: '1', name: 'Duplicate', email: 'd@t.com' }]), ).rejects.toThrow('Duplicate'); }); it('唯一约束冲突', async () => { await engine.insert('users', [{ id: '1', name: 'Alice', email: 'same@test.com' }]); await expect( engine.insert('users', [{ id: '2', name: 'Bob', email: 'same@test.com' }]), ).rejects.toThrow('Unique constraint'); }); it('必填字段缺失', async () => { await expect( engine.insert('users', [{ id: '1' }]), ).rejects.toThrow('required'); }); it('默认值填充', async () => { await engine.insert('users', [{ id: '1', name: 'Alice', email: 'a@t.com' }]); const rows = await engine.find('users', { table: 'users' }); expect(rows[0].age).toBe(0); }); it('类型错误', async () => { await expect( engine.insert('users', [{ id: '1', name: 'Alice', age: 'not-a-number', email: 'a@t.com' }]), ).rejects.toThrow('expects number'); }); }); // ---- 查询 ---- describe('查询', () => { beforeEach(async () => { await engine.createTable(userSchema); await engine.insert('users', [ { id: '1', name: 'Alice', age: 30, email: 'alice@test.com' }, { id: '2', name: 'Bob', age: 25, email: 'bob@test.com' }, { id: '3', name: 'Charlie', age: 35, email: 'charlie@test.com' }, ]); }); it('查询所有行', async () => { const rows = await engine.find('users', { table: 'users' }); expect(rows).toHaveLength(3); }); it('WHERE $gt', async () => { const rows = await engine.find('users', { table: 'users', where: { age: { $gt: 28 } }, }); expect(rows).toHaveLength(2); expect(rows.map((r) => r.id).sort()).toEqual(['1', '3']); }); it('WHERE $eq', async () => { const rows = await engine.find('users', { table: 'users', where: { name: 'Alice' }, }); expect(rows).toHaveLength(1); expect(rows[0].id).toBe('1'); }); it('WHERE $in', async () => { const rows = await engine.find('users', { table: 'users', where: { age: { $in: [25, 35] } }, }); expect(rows).toHaveLength(2); }); it('WHERE $like', async () => { const rows = await engine.find('users', { table: 'users', where: { name: { $like: 'A%' } }, }); expect(rows).toHaveLength(1); expect(rows[0].name).toBe('Alice'); }); it('ORDER BY asc', async () => { const rows = await engine.find('users', { table: 'users', orderBy: [{ column: 'age', direction: 'asc' }], }); expect(rows.map((r) => r.age)).toEqual([25, 30, 35]); }); it('ORDER BY desc', async () => { const rows = await engine.find('users', { table: 'users', orderBy: [{ column: 'age', direction: 'desc' }], }); expect(rows.map((r) => r.age)).toEqual([35, 30, 25]); }); it('LIMIT', async () => { const rows = await engine.find('users', { table: 'users', limit: 2, }); expect(rows).toHaveLength(2); }); it('OFFSET', async () => { const rows = await engine.find('users', { table: 'users', orderBy: [{ column: 'id', direction: 'asc' }], offset: 1, limit: 1, }); expect(rows).toHaveLength(1); expect(rows[0].id).toBe('2'); }); it('列选择', async () => { const rows = await engine.find('users', { table: 'users', columns: ['id', 'name'], where: { id: '1' }, }); expect(Object.keys(rows[0]).sort()).toEqual(['id', 'name']); }); }); // ---- 更新 ---- describe('更新', () => { beforeEach(async () => { await engine.createTable(userSchema); await engine.insert('users', [ { id: '1', name: 'Alice', age: 30, email: 'alice@test.com' }, { id: '2', name: 'Bob', age: 25, email: 'bob@test.com' }, ]); }); it('更新单行', async () => { const count = await engine.update('users', { table: 'users', where: { id: '1' } }, { age: 31 }, ); expect(count).toBe(1); const rows = await engine.find('users', { table: 'users', where: { id: '1' } }); expect(rows[0].age).toBe(31); }); it('更新所有行', async () => { const count = await engine.update('users', { table: 'users' }, { age: 100 }, ); expect(count).toBe(2); }); }); // ---- 删除 ---- describe('删除', () => { beforeEach(async () => { await engine.createTable(userSchema); await engine.insert('users', [ { id: '1', name: 'Alice', age: 30, email: 'alice@test.com' }, { id: '2', name: 'Bob', age: 25, email: 'bob@test.com' }, ]); }); it('条件删除', async () => { const count = await engine.delete('users', { table: 'users', where: { id: '1' } }); expect(count).toBe(1); const rows = await engine.find('users', { table: 'users' }); expect(rows).toHaveLength(1); }); it('清空表', async () => { await engine.clear('users'); const count = await engine.count('users'); expect(count).toBe(0); }); }); });