hicon-consensus
Version:
Node.js bindings for HiCon hybrid consensus algorithm
164 lines (149 loc) • 4.69 kB
text/typescript
import { createNode, createCluster, NodeState } from '../';
// Mock para evitar problemas con los bindings nativos durante pruebas
jest.mock('../', () => ({
createNode: jest.fn(() => ({
start: jest.fn().mockResolvedValue(undefined),
propose: jest.fn().mockResolvedValue({
success: true,
term: 1,
index: 1,
errorMessage: null
}),
getState: jest.fn().mockReturnValue('leader'),
getLogEntries: jest.fn().mockReturnValue([
{ term: 1, index: 1, data: '{"key":"test","value":"data"}' }
]),
getMetrics: jest.fn().mockReturnValue({
messagesReceived: 10,
messagesSent: 8,
consensusTimeMs: 15,
currentTerm: 1,
lastLogIndex: 1,
currentState: 'leader',
uptime: 60000
}),
stop: jest.fn().mockResolvedValue(undefined),
on: jest.fn()
})),
createCluster: jest.fn().mockResolvedValue({
getNodes: jest.fn().mockReturnValue([]),
getLeader: jest.fn().mockReturnValue(null),
propose: jest.fn().mockResolvedValue({
success: true,
term: 1,
index: 1,
errorMessage: null
}),
simulateNodeFailure: jest.fn().mockResolvedValue(undefined),
restoreNode: jest.fn().mockResolvedValue(undefined),
stop: jest.fn().mockResolvedValue(undefined)
}),
NodeState: {
Follower: 'follower',
Candidate: 'candidate',
Leader: 'leader'
}
}));
describe('HiCon Node', () => {
it('should create a node with options', () => {
const node = createNode({
id: 'test-node',
logPath: '/tmp/test',
redundancyFactor: 3,
enableEncryption: true
});
expect(node).toBeDefined();
expect(createNode).toHaveBeenCalledWith({
id: 'test-node',
logPath: '/tmp/test',
redundancyFactor: 3,
enableEncryption: true
});
});
it('should start a node with peers', async () => {
const node = createNode({ id: 'test-node' });
await node.start(['peer1', 'peer2']);
expect(node.start).toHaveBeenCalledWith(['peer1', 'peer2']);
});
it('should propose values to consensus', async () => {
const node = createNode({ id: 'test-node' });
const result = await node.propose(JSON.stringify({ key: 'test', value: 'data' }));
expect(result).toEqual({
success: true,
term: 1,
index: 1,
errorMessage: null
});
});
it('should get current state', () => {
const node = createNode({ id: 'test-node' });
const state = node.getState();
expect(state).toBe('leader');
});
it('should get log entries', () => {
const node = createNode({ id: 'test-node' });
const logs = node.getLogEntries();
expect(logs).toHaveLength(1);
expect(logs[0]).toEqual({
term: 1,
index: 1,
data: '{"key":"test","value":"data"}'
});
});
it('should get metrics', () => {
const node = createNode({ id: 'test-node' });
const metrics = node.getMetrics();
expect(metrics).toEqual({
messagesReceived: 10,
messagesSent: 8,
consensusTimeMs: 15,
currentTerm: 1,
lastLogIndex: 1,
currentState: 'leader',
uptime: 60000
});
});
it('should stop gracefully', async () => {
const node = createNode({ id: 'test-node' });
await node.stop();
expect(node.stop).toHaveBeenCalled();
});
it('should register event listeners', () => {
const node = createNode({ id: 'test-node' });
const listener = jest.fn();
node.on('stateChange', listener);
expect(node.on).toHaveBeenCalledWith('stateChange', listener);
});
});
describe('HiCon Cluster', () => {
it('should create a cluster', async () => {
const cluster = await createCluster(5, 3);
expect(cluster).toBeDefined();
expect(createCluster).toHaveBeenCalledWith(5, 3);
});
it('should propose values to the cluster', async () => {
const cluster = await createCluster(3);
const result = await cluster.propose(JSON.stringify({ key: 'cluster-test', value: 'cluster-data' }));
expect(result).toEqual({
success: true,
term: 1,
index: 1,
errorMessage: null
});
});
it('should simulate node failures', async () => {
const cluster = await createCluster(3);
await cluster.simulateNodeFailure(1);
expect(cluster.simulateNodeFailure).toHaveBeenCalledWith(1);
});
it('should restore failed nodes', async () => {
const cluster = await createCluster(3);
await cluster.restoreNode(1);
expect(cluster.restoreNode).toHaveBeenCalledWith(1);
});
it('should stop all nodes in the cluster', async () => {
const cluster = await createCluster(3);
await cluster.stop();
expect(cluster.stop).toHaveBeenCalled();
});
});