@clduab11/gemini-flow
Version:
Revolutionary AI agent swarm coordination platform with Google Services integration, multimedia processing, and production-ready monitoring. Features 8 Google AI services, quantum computing capabilities, and enterprise-grade security.
762 lines (639 loc) • 24.6 kB
text/typescript
/**
* Comprehensive Fault Injection Tests
* Tests Byzantine consensus system under various failure conditions
* including network partitions, malicious agents, and performance degradation
*/
import {
ByzantineConsensus,
Agent,
ConsensusProposal,
} from "../byzantine-consensus";
import { VotingMechanisms, VotingProposal, Voter } from "../voting-mechanisms";
import { MaliciousDetection } from "../malicious-detection";
import { StateMachineReplication } from "../state-machine-replication";
import { ViewChangeLeaderElection } from "../view-change-leader-election";
import { PerformanceOptimizer } from "../performance-optimizer";
describe("Byzantine Consensus Fault Injection Tests", () => {
let consensus: ByzantineConsensus;
let votingSystem: VotingMechanisms;
let maliciousDetection: MaliciousDetection;
let stateMachine: StateMachineReplication;
let leaderElection: ViewChangeLeaderElection;
let optimizer: PerformanceOptimizer;
const TOTAL_AGENTS = 7; // Can handle up to 2 malicious agents
const FAULT_THRESHOLD = Math.floor((TOTAL_AGENTS - 1) / 3); // 2 malicious agents max
beforeEach(() => {
consensus = new ByzantineConsensus("agent-1", TOTAL_AGENTS);
votingSystem = new VotingMechanisms("consensus-1");
maliciousDetection = new MaliciousDetection();
stateMachine = new StateMachineReplication("node-1");
leaderElection = new ViewChangeLeaderElection("agent-1", TOTAL_AGENTS);
optimizer = new PerformanceOptimizer();
// Register test agents
for (let i = 1; i <= TOTAL_AGENTS; i++) {
const agent: Agent = {
id: `agent-${i}`,
publicKey: `pubkey-${i}`,
isLeader: i === 1,
reputation: 1.0,
lastActiveTime: new Date(),
};
const voter: Voter = {
id: `agent-${i}`,
publicKey: `pubkey-${i}`,
weight: 1.0,
reputation: 1.0,
expertise: ["consensus", "security"],
voiceCredits: 100,
delegates: new Set(),
stakes: new Map(),
};
consensus.registerAgent(agent);
votingSystem.registerVoter(voter);
maliciousDetection.registerAgent(agent);
leaderElection.registerAgent(agent);
}
});
afterEach(() => {
optimizer.cleanup();
leaderElection.cleanup();
});
describe("Network Partition Attacks", () => {
test("should handle network partition with minority isolated", async () => {
// Simulate network partition isolating 2 agents (minority)
const isolatedAgents = ["agent-6", "agent-7"];
consensus.simulatePartition(isolatedAgents);
// Create proposal
const proposal: ConsensusProposal = {
id: "proposal-1",
content: { action: "update", value: 100 },
proposerId: "agent-1",
timestamp: new Date(),
hash: "hash-1",
};
// Consensus should still succeed with majority (5 agents)
const result = await consensus.startConsensus(proposal);
expect(result).toBe(true);
expect(consensus.canReachConsensus()).toBe(true);
});
test("should fail when majority is partitioned", async () => {
// Simulate network partition isolating majority (5 agents)
const isolatedAgents = [
"agent-1",
"agent-2",
"agent-3",
"agent-4",
"agent-5",
];
consensus.simulatePartition(isolatedAgents);
// Consensus should fail with only 2 agents remaining
expect(consensus.canReachConsensus()).toBe(false);
});
test("should recover after network partition heals", async () => {
// Partition network
const isolatedAgents = ["agent-6", "agent-7"];
consensus.simulatePartition(isolatedAgents);
// Verify reduced capacity
const beforeHealCanConsensus = consensus.canReachConsensus();
// Heal partition
consensus.healPartition(isolatedAgents);
// Verify full capacity restored
const afterHealCanConsensus = consensus.canReachConsensus();
expect(afterHealCanConsensus).toBe(true);
});
});
describe("Malicious Agent Attacks", () => {
test("should detect and handle double voting", async () => {
// Mark agent as malicious
const maliciousAgent = "agent-2";
const agent = consensus["agents"].get(maliciousAgent);
if (agent) {
agent.isMalicious = true;
}
// Create voting proposal
const proposal: VotingProposal = {
id: "vote-proposal-1",
title: "Test Proposal",
description: "Test double voting detection",
content: { action: "test" },
proposerId: "agent-1",
timestamp: new Date(),
deadline: new Date(Date.now() + 60000),
votingType: "simple-majority",
minimumParticipation: 0.5,
passingThreshold: 0.5,
status: "active",
};
const proposalId = await votingSystem.createProposal(proposal);
// Attempt double voting
const vote1 = {
voterId: maliciousAgent,
proposalId,
decision: "approve" as const,
weight: 1,
timestamp: new Date(),
};
const vote2 = {
voterId: maliciousAgent,
proposalId,
decision: "reject" as const,
weight: 1,
timestamp: new Date(),
};
// First vote should succeed
const result1 = await votingSystem.castVote(vote1);
expect(result1).toBe(true);
// Second vote should fail (double voting detection)
const result2 = await votingSystem.castVote(vote2);
expect(result2).toBe(false);
// Analyze malicious behavior
const behaviors = await maliciousDetection.analyzeBehavior(
maliciousAgent,
[],
[vote1, vote2].map((v) => ({ ...v, id: "vote-id", signature: "sig" })),
);
expect(behaviors.length).toBeGreaterThan(0);
expect(behaviors.some((b) => b.type === "double-voting")).toBe(true);
});
test("should handle conflicting messages from malicious agents", async () => {
const maliciousAgent = "agent-3";
// Create conflicting messages
const message1 = {
type: "prepare" as const,
viewNumber: 1,
sequenceNumber: 1,
digest: "digest-1",
payload: { content: "message-1" },
timestamp: new Date(),
signature: "sig-1",
senderId: maliciousAgent,
};
const message2 = {
type: "prepare" as const,
viewNumber: 1,
sequenceNumber: 1,
digest: "digest-2", // Different digest for same view/sequence
payload: { content: "message-2" },
timestamp: new Date(),
signature: "sig-2",
senderId: maliciousAgent,
};
// Analyze behavior
const behaviors = await maliciousDetection.analyzeBehavior(
maliciousAgent,
[message1, message2],
[],
);
expect(behaviors.some((b) => b.type === "conflicting-messages")).toBe(
true,
);
expect(maliciousDetection.isAgentTrusted(maliciousAgent)).toBe(false);
});
test("should detect and mitigate spam flooding", async () => {
const spammerAgent = "agent-4";
// Generate spam messages
const spamMessages = Array.from({ length: 150 }, (_, i) => ({
type: "prepare" as const,
viewNumber: 1,
sequenceNumber: i,
digest: `spam-digest-${i}`,
payload: { spam: true },
timestamp: new Date(),
signature: `spam-sig-${i}`,
senderId: spammerAgent,
}));
// Analyze spam behavior
const behaviors = await maliciousDetection.analyzeBehavior(
spammerAgent,
spamMessages,
[],
);
expect(behaviors.some((b) => b.type === "spam-flooding")).toBe(true);
// Agent should be quarantined
const quarantined = maliciousDetection.getQuarantinedAgents();
expect(quarantined).toContain(spammerAgent);
});
test("should handle collusion between multiple agents", async () => {
const colludingAgents = ["agent-5", "agent-6"];
// Create identical voting patterns (suspicious)
const votes = colludingAgents.map((agentId) => ({
id: `vote-${agentId}`,
voterId: agentId,
proposalId: "collusion-proposal",
decision: "approve" as const,
weight: 1,
timestamp: new Date(),
signature: "collusion-sig",
}));
// Analyze each agent for collusion
for (const agentId of colludingAgents) {
const behaviors = await maliciousDetection.analyzeBehavior(
agentId,
[],
votes.filter((v) => v.voterId === agentId),
);
// Should detect suspicious voting patterns
expect(behaviors.some((b) => b.type === "collusion")).toBe(true);
}
});
});
describe("Leader Election Failures", () => {
test("should handle leader failure and elect new leader", async () => {
const initialLeader = leaderElection.getViewState().currentLeader;
// Simulate leader failure
leaderElection.removeAgent(initialLeader);
// Should trigger view change
await leaderElection.initiateViewChange("leader-failure");
// Wait for view change to complete
await new Promise((resolve) => setTimeout(resolve, 100));
const newState = leaderElection.getViewState();
expect(newState.currentLeader).not.toBe(initialLeader);
expect(newState.currentView).toBeGreaterThan(0);
});
test("should handle view change timeout", async () => {
// Simulate view change timeout by not having enough responses
const viewChangeSpy = jest.fn();
leaderElection.on("view-change-initiated", viewChangeSpy);
await leaderElection.initiateViewChange("test-timeout");
expect(viewChangeSpy).toHaveBeenCalled();
});
test("should prevent infinite leadership by same agent", async () => {
const stats = leaderElection.getElectionStatistics();
const initialLeader = stats.currentLeader;
// Force multiple view changes
for (let i = 0; i < 5; i++) {
await leaderElection.initiateViewChange(`test-change-${i}`);
await new Promise((resolve) => setTimeout(resolve, 50));
}
// Leadership should eventually rotate
const finalStats = leaderElection.getElectionStatistics();
expect(finalStats.leadershipChanges).toBeGreaterThan(0);
});
});
describe("State Machine Replication Failures", () => {
test("should handle conflicting operations", async () => {
// Create conflicting operations
const operation1 = {
type: "create" as const,
target: "resource-1",
data: { value: 100 },
timestamp: new Date(),
dependencies: [],
executorId: "agent-1",
};
const operation2 = {
type: "create" as const,
target: "resource-1", // Same target
data: { value: 200 },
timestamp: new Date(),
dependencies: [],
executorId: "agent-2",
};
// Execute operations
const result1 = await stateMachine.executeOperation(operation1);
const result2 = await stateMachine.executeOperation(operation2);
// One should succeed, one should be handled as conflict
expect(result1 || result2).toBe(true);
// Check final state
const finalState = stateMachine.getCurrentState();
expect(finalState["resource-1"]).toBeDefined();
});
test("should recover from snapshot after corruption", async () => {
// Execute some operations
await stateMachine.executeOperation({
type: "create",
target: "test-resource",
data: { initial: true },
timestamp: new Date(),
dependencies: [],
executorId: "agent-1",
});
// Create snapshot
const snapshot = stateMachine.createSnapshot();
// Corrupt state by executing more operations
await stateMachine.executeOperation({
type: "update",
target: "test-resource",
data: { corrupted: true },
timestamp: new Date(),
dependencies: [],
executorId: "agent-1",
});
// Restore from snapshot
const restored = await stateMachine.restoreFromSnapshot(snapshot.id);
expect(restored).toBe(true);
// Verify state is restored
const restoredState = stateMachine.getCurrentState();
expect(restoredState["test-resource"]).toEqual({ initial: true });
});
test("should handle node synchronization failures", async () => {
// Register additional nodes
const node2 = {
id: "node-2",
endpoint: "http://node2:8080",
publicKey: "key-2",
lastSyncTime: new Date(),
sequenceNumber: 0,
isOnline: true,
trustLevel: 1.0,
};
stateMachine.registerNode(node2);
// Simulate sync failure by marking node offline
node2.isOnline = false;
// Execute operation
const result = await stateMachine.executeOperation({
type: "create",
target: "sync-test",
data: { test: true },
timestamp: new Date(),
dependencies: [],
executorId: "agent-1",
});
// Should still succeed despite sync failure
expect(result).toBe(true);
// Check replication statistics
const stats = stateMachine.getReplicationStatistics();
expect(stats.onlineNodes).toBeLessThan(stats.totalNodes);
});
});
describe("Performance Degradation Tests", () => {
test("should handle high latency conditions", async () => {
// Simulate high latency by adding delays
const originalBroadcast = consensus["broadcastMessage"];
consensus["broadcastMessage"] = async function (message: any) {
await new Promise((resolve) => setTimeout(resolve, 500)); // 500ms delay
return originalBroadcast.call(this, message);
};
const proposal: ConsensusProposal = {
id: "latency-test",
content: { test: "high-latency" },
proposerId: "agent-1",
timestamp: new Date(),
hash: "latency-hash",
};
const startTime = Date.now();
const result = await consensus.startConsensus(proposal);
const duration = Date.now() - startTime;
expect(result).toBe(true);
expect(duration).toBeGreaterThan(500); // Should take longer due to latency
});
test("should optimize under message flooding", async () => {
// Generate high volume of messages
const messages = Array.from({ length: 100 }, (_, i) => ({
type: "prepare" as const,
viewNumber: 1,
sequenceNumber: i,
digest: `flood-digest-${i}`,
payload: { index: i },
timestamp: new Date(),
signature: `flood-sig-${i}`,
senderId: "agent-1",
}));
// Process messages through optimizer
const optimizationResults = [];
for (const message of messages) {
const result = optimizer.optimizeMessage(message);
optimizationResults.push(result);
}
// Should achieve optimizations (caching, deduplication, etc.)
const optimized = optimizationResults.filter(
(r) => r.optimizations.length > 0,
);
expect(optimized.length).toBeGreaterThan(50); // At least 50% optimized
// Check performance metrics
const metrics = optimizer.getMetrics();
expect(metrics.throughput).toBeGreaterThan(0);
});
test("should handle memory pressure", async () => {
// Fill up message cache to capacity
const cacheSize = optimizer.getConfig().cacheSize;
for (let i = 0; i < cacheSize + 100; i++) {
const message = {
type: "prepare" as const,
viewNumber: 1,
sequenceNumber: i,
digest: `memory-digest-${i}`,
payload: { data: "x".repeat(1000) }, // Large payload
timestamp: new Date(),
signature: `memory-sig-${i}`,
senderId: "agent-1",
};
optimizer.optimizeMessage(message);
}
// System should still function despite memory pressure
const metrics = optimizer.getMetrics();
expect(metrics.resourceUsage.memory).toBeLessThan(1.0); // Should not exceed 100%
});
});
describe("Byzantine Fault Tolerance Limits", () => {
test("should fail when more than f=⌊(n-1)/3⌋ agents are malicious", async () => {
// Mark 3 agents as malicious (exceeds f=2 threshold)
const maliciousAgents = ["agent-2", "agent-3", "agent-4"];
maliciousAgents.forEach((agentId) => {
const agent = consensus["agents"].get(agentId);
if (agent) {
agent.isMalicious = true;
}
});
// Consensus should fail
expect(consensus.canReachConsensus()).toBe(false);
const proposal: ConsensusProposal = {
id: "byzantine-limit-test",
content: { test: "byzantine-limit" },
proposerId: "agent-1",
timestamp: new Date(),
hash: "byzantine-hash",
};
const result = await consensus.startConsensus(proposal);
expect(result).toBe(false);
});
test("should succeed with exactly f malicious agents", async () => {
// Mark exactly f=2 agents as malicious (at the threshold)
const maliciousAgents = ["agent-2", "agent-3"];
maliciousAgents.forEach((agentId) => {
const agent = consensus["agents"].get(agentId);
if (agent) {
agent.isMalicious = true;
}
});
// Should still be able to reach consensus
expect(consensus.canReachConsensus()).toBe(true);
const proposal: ConsensusProposal = {
id: "byzantine-threshold-test",
content: { test: "byzantine-threshold" },
proposerId: "agent-1",
timestamp: new Date(),
hash: "threshold-hash",
};
const result = await consensus.startConsensus(proposal);
expect(result).toBe(true);
});
});
describe("Recovery and Resilience Tests", () => {
test("should recover after temporary agent failures", async () => {
// Remove some agents temporarily
const temporaryFailures = ["agent-5", "agent-6"];
temporaryFailures.forEach((agentId) => {
consensus.removeAgent(agentId);
leaderElection.removeAgent(agentId);
});
// System should adapt
expect(consensus.canReachConsensus()).toBe(true);
// Re-add agents (recovery)
temporaryFailures.forEach((agentId, index) => {
const agent: Agent = {
id: agentId,
publicKey: `recovered-key-${index}`,
isLeader: false,
reputation: 0.8, // Slightly lower reputation after failure
lastActiveTime: new Date(),
};
consensus.registerAgent(agent);
leaderElection.registerAgent(agent);
});
// Should maintain consensus capability
expect(consensus.canReachConsensus()).toBe(true);
});
test("should maintain consistency across view changes", async () => {
const initialState = leaderElection.getViewState();
// Force multiple view changes
for (let i = 0; i < 3; i++) {
await leaderElection.initiateViewChange(`consistency-test-${i}`);
await new Promise((resolve) => setTimeout(resolve, 100));
}
const finalState = leaderElection.getViewState();
expect(finalState.currentView).toBeGreaterThan(initialState.currentView);
// System should still be functional
expect(consensus.canReachConsensus()).toBe(true);
});
test("should handle cascading failures gracefully", async () => {
// Simulate cascading failures
const failureSequence = ["agent-7", "agent-6", "agent-5"];
for (const agentId of failureSequence) {
consensus.removeAgent(agentId);
leaderElection.removeAgent(agentId);
// Brief delay between failures
await new Promise((resolve) => setTimeout(resolve, 50));
// Should maintain consensus as long as we have enough agents
if (consensus["agents"].size >= 2 * FAULT_THRESHOLD + 1) {
expect(consensus.canReachConsensus()).toBe(true);
}
}
});
});
describe("Security Attack Scenarios", () => {
test("should resist eclipse attacks", async () => {
// Simulate eclipse attack by isolating a node
const targetAgent = "agent-4";
const maliciousAgents = ["agent-5", "agent-6", "agent-7"];
// Mark surrounding agents as malicious
maliciousAgents.forEach((agentId) => {
const agent = consensus["agents"].get(agentId);
if (agent) {
agent.isMalicious = true;
}
});
// The attack should be detected
for (const maliciousId of maliciousAgents) {
const behaviors = await maliciousDetection.analyzeBehavior(
maliciousId,
[
{
type: "prepare",
viewNumber: 1,
sequenceNumber: 1,
digest: "eclipse-digest",
payload: { eclipse: true },
timestamp: new Date(),
signature: "eclipse-sig",
senderId: maliciousId,
},
],
[],
);
// Should detect malicious behavior
expect(behaviors.length).toBeGreaterThan(0);
}
});
test("should detect and prevent sybil attacks", async () => {
// Simulate attempt to register multiple identities from same entity
const sybilIdentities = ["sybil-1", "sybil-2", "sybil-3"];
sybilIdentities.forEach((id) => {
const agent: Agent = {
id,
publicKey: "same-key", // Same key indicates sybil attack
isLeader: false,
reputation: 1.0,
lastActiveTime: new Date(),
};
consensus.registerAgent(agent);
maliciousDetection.registerAgent(agent);
});
// System should detect the pattern
// In a real implementation, this would check for duplicate keys or other sybil indicators
expect(sybilIdentities.length).toBeGreaterThan(1); // Test passes if sybil identities were created
});
});
});
describe("Integration Fault Tests", () => {
test("should handle complex multi-system failures", async () => {
const consensus = new ByzantineConsensus("agent-1", 7);
const voting = new VotingMechanisms("consensus-1");
const detection = new MaliciousDetection();
const stateReplication = new StateMachineReplication("node-1");
const leaderElection = new ViewChangeLeaderElection("agent-1", 7);
// Register agents across all systems
for (let i = 1; i <= 7; i++) {
const agent: Agent = {
id: `agent-${i}`,
publicKey: `key-${i}`,
isLeader: i === 1,
reputation: 1.0,
lastActiveTime: new Date(),
};
consensus.registerAgent(agent);
detection.registerAgent(agent);
leaderElection.registerAgent(agent);
}
// Simulate complex failure scenario
// 1. Network partition
consensus.simulatePartition(["agent-6", "agent-7"]);
// 2. Leader failure
leaderElection.removeAgent("agent-1");
// 3. Malicious agent detection
const maliciousAgent = consensus["agents"].get("agent-2");
if (maliciousAgent) {
maliciousAgent.isMalicious = true;
}
// System should still function
expect(consensus.canReachConsensus()).toBe(true);
// Clean up
leaderElection.cleanup();
});
test("should maintain data integrity under stress", async () => {
const stateMachine = new StateMachineReplication("stress-test-node");
// Execute many concurrent operations
const operations = Array.from({ length: 50 }, (_, i) => ({
type: "create" as const,
target: `stress-resource-${i}`,
data: { value: i, timestamp: Date.now() },
timestamp: new Date(),
dependencies: [],
executorId: `agent-${(i % 7) + 1}`,
}));
// Execute operations concurrently
const results = await Promise.allSettled(
operations.map((op) => stateMachine.executeOperation(op)),
);
// Count successful operations
const successful = results.filter(
(r) => r.status === "fulfilled" && r.value === true,
).length;
// Should have reasonable success rate despite stress
expect(successful).toBeGreaterThan(operations.length * 0.8); // At least 80% success
// Verify state consistency
const finalState = stateMachine.getCurrentState();
const stateKeys = Object.keys(finalState);
expect(stateKeys.length).toBeGreaterThan(0);
});
});