Sync DNS2 production changes - removed obsolete test suite and refactored structure
This commit is contained in:
@@ -1,209 +0,0 @@
|
||||
const crypto = require('crypto');
|
||||
const backupManager = require('../backup-manager');
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset singleton state
|
||||
backupManager.history = [];
|
||||
backupManager.config = { backups: {}, defaultRetention: { keep: 7 } };
|
||||
backupManager.running = false;
|
||||
for (const [, job] of backupManager.scheduledJobs.entries()) {
|
||||
clearInterval(job);
|
||||
}
|
||||
backupManager.scheduledJobs.clear();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
backupManager.stop();
|
||||
});
|
||||
|
||||
describe('calculateChecksum', () => {
|
||||
test('returns SHA-256 hex string', () => {
|
||||
const data = Buffer.from('test data');
|
||||
const checksum = backupManager.calculateChecksum(data);
|
||||
expect(checksum).toMatch(/^[0-9a-f]{64}$/);
|
||||
});
|
||||
|
||||
test('same data produces same checksum', () => {
|
||||
const data = Buffer.from('consistent');
|
||||
expect(backupManager.calculateChecksum(data)).toBe(backupManager.calculateChecksum(data));
|
||||
});
|
||||
|
||||
test('different data produces different checksum', () => {
|
||||
const a = backupManager.calculateChecksum(Buffer.from('aaa'));
|
||||
const b = backupManager.calculateChecksum(Buffer.from('bbb'));
|
||||
expect(a).not.toBe(b);
|
||||
});
|
||||
});
|
||||
|
||||
describe('compressBackup / decompressBackup', () => {
|
||||
test('round-trip preserves data', async () => {
|
||||
const original = { services: [{ id: 'test', name: 'Test' }], config: { theme: 'dark' } };
|
||||
const compressed = await backupManager.compressBackup(original);
|
||||
const decompressed = await backupManager.decompressBackup(compressed);
|
||||
expect(decompressed).toEqual(original);
|
||||
});
|
||||
|
||||
test('compressed output is a Buffer', async () => {
|
||||
const compressed = await backupManager.compressBackup({ test: true });
|
||||
expect(Buffer.isBuffer(compressed)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encryptBackup / decryptBackup', () => {
|
||||
const testKey = crypto.randomBytes(32).toString('hex');
|
||||
|
||||
test('round-trip preserves data with valid key', async () => {
|
||||
const original = Buffer.from('backup data here');
|
||||
const encrypted = await backupManager.encryptBackup(original, testKey);
|
||||
const decrypted = await backupManager.decryptBackup(encrypted, testKey);
|
||||
expect(decrypted.toString()).toBe(original.toString());
|
||||
});
|
||||
|
||||
test('produces a non-empty buffer', async () => {
|
||||
const original = Buffer.from('backup data here');
|
||||
const encrypted = await backupManager.encryptBackup(original, testKey);
|
||||
expect(Buffer.isBuffer(encrypted)).toBe(true);
|
||||
expect(encrypted.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('output differs from input', async () => {
|
||||
const original = Buffer.from('backup data here');
|
||||
const encrypted = await backupManager.encryptBackup(original, testKey);
|
||||
expect(encrypted.toString()).not.toBe(original.toString());
|
||||
});
|
||||
|
||||
test('throws on invalid encrypted format', async () => {
|
||||
await expect(backupManager.decryptBackup(Buffer.from('bad'), testKey)).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('throws on wrong key', async () => {
|
||||
const original = Buffer.from('secret data');
|
||||
const encrypted = await backupManager.encryptBackup(original, testKey);
|
||||
const wrongKey = crypto.randomBytes(32).toString('hex');
|
||||
await expect(backupManager.decryptBackup(encrypted, wrongKey)).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('scheduleBackup', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('parses hourly schedule', () => {
|
||||
backupManager.scheduleBackup('test', { schedule: 'hourly' });
|
||||
expect(backupManager.scheduledJobs.has('test')).toBe(true);
|
||||
});
|
||||
|
||||
test('parses daily schedule', () => {
|
||||
backupManager.scheduleBackup('test', { schedule: 'daily' });
|
||||
expect(backupManager.scheduledJobs.has('test')).toBe(true);
|
||||
});
|
||||
|
||||
test('parses weekly schedule', () => {
|
||||
backupManager.scheduleBackup('test', { schedule: 'weekly' });
|
||||
expect(backupManager.scheduledJobs.has('test')).toBe(true);
|
||||
});
|
||||
|
||||
test('parses monthly schedule', () => {
|
||||
backupManager.scheduleBackup('test', { schedule: 'monthly' });
|
||||
expect(backupManager.scheduledJobs.has('test')).toBe(true);
|
||||
});
|
||||
|
||||
test('parses custom numeric minute schedule', () => {
|
||||
backupManager.scheduleBackup('test', { schedule: '30' });
|
||||
expect(backupManager.scheduledJobs.has('test')).toBe(true);
|
||||
});
|
||||
|
||||
test('logs error for invalid schedule', () => {
|
||||
backupManager.scheduleBackup('test', { schedule: 'invalid' });
|
||||
expect(backupManager.scheduledJobs.has('test')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addToHistory', () => {
|
||||
test('appends entry to history', () => {
|
||||
backupManager.addToHistory({ id: 'b1', status: 'success' });
|
||||
expect(backupManager.history).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('trims history to 100 entries', () => {
|
||||
for (let i = 0; i < 105; i++) {
|
||||
backupManager.addToHistory({ id: `b${i}`, status: 'success' });
|
||||
}
|
||||
expect(backupManager.history.length).toBeLessThanOrEqual(100);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHistory', () => {
|
||||
test('returns entries in reverse order', () => {
|
||||
backupManager.addToHistory({ id: 'first' });
|
||||
backupManager.addToHistory({ id: 'second' });
|
||||
const history = backupManager.getHistory();
|
||||
expect(history[0].id).toBe('second');
|
||||
expect(history[1].id).toBe('first');
|
||||
});
|
||||
|
||||
test('respects limit parameter', () => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
backupManager.addToHistory({ id: `b${i}` });
|
||||
}
|
||||
expect(backupManager.getHistory(3)).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getConfig / updateConfig', () => {
|
||||
test('getConfig returns current config', () => {
|
||||
const config = backupManager.getConfig();
|
||||
expect(config).toHaveProperty('backups');
|
||||
});
|
||||
|
||||
test('updateConfig merges new config', () => {
|
||||
backupManager.updateConfig({ backups: { daily: { enabled: true, schedule: 'daily' } } });
|
||||
expect(backupManager.config.backups.daily).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('start / stop', () => {
|
||||
test('start sets running flag', () => {
|
||||
backupManager.start();
|
||||
expect(backupManager.running).toBe(true);
|
||||
backupManager.stop();
|
||||
});
|
||||
|
||||
test('start is idempotent', () => {
|
||||
backupManager.start();
|
||||
backupManager.start();
|
||||
expect(backupManager.running).toBe(true);
|
||||
backupManager.stop();
|
||||
});
|
||||
|
||||
test('stop clears running flag and jobs', () => {
|
||||
backupManager.start();
|
||||
backupManager.stop();
|
||||
expect(backupManager.running).toBe(false);
|
||||
expect(backupManager.scheduledJobs.size).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('cleanupOldBackups', () => {
|
||||
test('keeps configured number of backups', async () => {
|
||||
// Add 5 successful backups for 'daily'
|
||||
for (let i = 0; i < 5; i++) {
|
||||
backupManager.history.push({
|
||||
id: `daily-${i}`,
|
||||
name: 'daily',
|
||||
status: 'success',
|
||||
timestamp: new Date(Date.now() - i * 86400000).toISOString(),
|
||||
locations: [{ type: 'local', path: `/tmp/fake-${i}.backup` }],
|
||||
});
|
||||
}
|
||||
|
||||
await backupManager.cleanupOldBackups('daily', { keep: 3 });
|
||||
const remaining = backupManager.history.filter(b => b.name === 'daily' && b.status === 'success');
|
||||
expect(remaining.length).toBe(3);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user