delta-sync
Version:
A lightweight framework for bi-directional database synchronization with automatic version tracking and conflict resolution.
140 lines (139 loc) • 5.54 kB
JavaScript
// tester/CoordinatorTester.ts
import { SyncView } from '../core/types';
import { MemoryAdapter } from '../core/adapters';
import { Coordinator } from '../core/Coordinator';
export class CoordinatorTester {
constructor() {
this.testResults = {};
this.memoryAdapter = new MemoryAdapter();
this.coordinator = new Coordinator(this.memoryAdapter);
}
async runTest(testName, testFn) {
try {
await testFn();
this.testResults[testName] = {
success: true,
message: '测试通过'
};
}
catch (error) {
this.testResults[testName] = {
success: false,
message: error instanceof Error ? error.message : '未知错误'
};
console.error(`Test '${testName}' failed:`, error);
}
}
async runAllTests() {
await this.runTest('初始化', () => this.testInitialization());
await this.runTest('数据操作', () => this.testDataOperations());
await this.runTest('查询操作', () => this.testQueryOperations());
await this.runTest('变更通知', () => this.testChangeNotification());
await this.runTest('并发操作', () => this.testConcurrency());
await this.runTest('大数据量', () => this.testLargeDataset());
await this.runTest('边界情况', () => this.testEdgeCases());
const success = Object.values(this.testResults).every(result => result.success);
return { success, results: this.testResults };
}
async testInitialization() {
await this.coordinator.initSync?.();
const view = await this.coordinator.getCurrentView();
if (!(view instanceof SyncView)) {
throw new Error('初始化失败:无效的SyncView');
}
}
async testDataOperations() {
const testStore = 'test_store';
const testData = [
{ id: 'test1', content: 'test content 1' },
{ id: 'test2', content: 'test content 2' }
];
// 测试写入
const savedData = await this.coordinator.putBulk(testStore, testData);
if (savedData.length !== testData.length) {
throw new Error('数据写入失败');
}
// 测试读取
const readData = await this.coordinator.readBulk(testStore, [testData[0].id]);
if (!readData[0] || readData[0].id !== testData[0].id) {
throw new Error('数据读取失败');
}
// 测试删除
await this.coordinator.deleteBulk(testStore, [testData[0].id]);
const afterDelete = await this.coordinator.readBulk(testStore, [testData[0].id]);
if (afterDelete.length !== 0) {
throw new Error('数据删除失败');
}
}
async testQueryOperations() {
const testStore = 'query_test';
// 清理测试数据
const currentView = await this.coordinator.getCurrentView();
await this.coordinator.deleteBulk(testStore, currentView.getByStore(testStore).map(item => item.id));
// 写入测试数据
const testItems = Array.from({ length: 10 }, (_, i) => ({
id: `query-test-${i}`,
content: `content ${i}`,
timestamp: Date.now() + i
}));
await this.coordinator.putBulk(testStore, testItems);
// 测试基本查询
const result = await this.coordinator.query(testStore, { limit: 5 });
if (result.items.length !== 5) {
throw new Error(`查询数量错误: 期望5条,实际${result.items.length}条`);
}
// 测试分页
const pageResult = await this.coordinator.query(testStore, {
offset: 3,
limit: 3
});
if (pageResult.items.length !== 3) {
throw new Error(`分页查询错误: 期望3条,实际${pageResult.items.length}条`);
}
}
async testChangeNotification() {
let notified = false;
this.coordinator.onDataChanged(() => {
notified = true;
});
await this.coordinator.putBulk('test_store', [{
id: 'change-test',
content: 'change test'
}]);
await new Promise(resolve => setTimeout(resolve, 100));
if (!notified) {
throw new Error('变更通知失败');
}
}
async testConcurrency() {
const operations = Array(10).fill(null).map((_, i) => this.coordinator.putBulk('concurrent_test', [{
id: `concurrent-${i}`,
content: `concurrent content ${i}`
}]));
await Promise.all(operations);
}
async testLargeDataset() {
const largeData = Array.from({ length: 1000 }, (_, i) => ({
id: `large-${i}`,
content: `large content ${i}`
}));
await this.coordinator.putBulk('large_test', largeData);
}
async testEdgeCases() {
await this.coordinator.putBulk('edge_test', []);
await this.coordinator.putBulk('edge_test', [{
id: 'special-!@#$%^&*()',
content: '!@#$%^&*()'
}]);
// 测试大对象
const largeObject = {
id: 'large-object',
content: 'x'.repeat(1000000)
};
await this.coordinator.putBulk('edge_test', [largeObject]);
}
}
export async function testCoordinatorFunctionality() {
const tester = new CoordinatorTester();
return await tester.runAllTests();
}