@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.
1,262 lines (1,065 loc) • 42 kB
text/typescript
/**
* Comprehensive Test Suite for Distributed Memory Manager
* Tests namespace-based memory operations, synchronization, and topology management
*/
import {
DistributedMemoryManager,
MemoryTopology,
AgentNode,
MemoryDelta,
MemoryOperation,
MemoryMetrics,
SynchronizationStats,
} from "../distributed-memory-manager.js";
import { VectorClock } from "../vector-clocks.js";
// Mock dependencies
jest.mock("../../../utils/logger.js");
jest.mock("../../../core/cache-manager.js");
jest.mock("../vector-clocks.js");
jest.mock("../crdt-sync.js");
jest.mock("../gossip-protocol.js");
jest.mock("../memory-compressor.js");
jest.mock("../conflict-resolver.js");
jest.mock("../memory-sharding.js");
const mockVectorClock = VectorClock as jest.MockedClass<typeof VectorClock>;
describe("DistributedMemoryManager", () => {
let memoryManager: DistributedMemoryManager;
let mockVectorClockInstance: jest.Mocked<VectorClock>;
beforeEach(() => {
jest.clearAllMocks();
// Setup mock vector clock
mockVectorClockInstance = {
increment: jest.fn().mockReturnThis(),
merge: jest.fn(),
copy: jest.fn().mockReturnThis(),
compare: jest.fn().mockReturnValue("concurrent"),
toString: jest.fn().mockReturnValue("1:1"),
isNewer: jest.fn().mockReturnValue(true),
} as any;
mockVectorClock.mockImplementation(() => mockVectorClockInstance);
mockVectorClock.fromString = jest
.fn()
.mockReturnValue(mockVectorClockInstance);
memoryManager = new DistributedMemoryManager("test-agent", {
type: "mesh",
replicationFactor: 3,
consistencyLevel: "eventual",
});
});
afterEach(() => {
memoryManager?.emergencyCleanup("test cleanup");
});
describe("Initialization", () => {
it("should initialize with default configuration", () => {
const topology = memoryManager.getTopology();
expect(topology.type).toBe("mesh");
expect(topology.nodes).toHaveLength(1);
expect(topology.nodes[0].agentId).toBe("test-agent");
expect(topology.replicationFactor).toBe(3);
expect(topology.consistencyLevel).toBe("eventual");
});
it("should initialize with custom configuration", () => {
const customManager = new DistributedMemoryManager(
"custom-agent",
{
type: "hierarchical",
replicationFactor: 5,
consistencyLevel: "strong",
},
{
enableCompression: true,
enableSharding: true,
maxMemorySize: 200 * 1024 * 1024,
},
);
const topology = customManager.getTopology();
expect(topology.type).toBe("hierarchical");
expect(topology.replicationFactor).toBe(5);
expect(topology.consistencyLevel).toBe("strong");
customManager.emergencyCleanup("test cleanup");
});
it("should setup local agent with correct capabilities", () => {
const topology = memoryManager.getTopology();
const localAgent = topology.nodes[0];
expect(localAgent.agentId).toBe("test-agent");
expect(localAgent.role).toBe("replica");
expect(localAgent.capabilities).toContain("sync");
expect(localAgent.capabilities).toContain("compress");
expect(localAgent.trustLevel).toBe(1.0);
});
});
describe("Namespace-Based Memory Operations", () => {
describe("Memory Storage and Retrieval", () => {
it("should store and retrieve data by namespace", async () => {
const operation: MemoryOperation = {
type: "set",
key: "user:123",
value: { name: "John Doe", email: "john@example.com" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "test-agent",
},
};
// Simulate applying the operation
await (memoryManager as any).applyOperation(operation);
// Check if the operation was applied
const memoryStore = (memoryManager as any).memoryStore;
expect(memoryStore.has("user:123")).toBe(true);
const stored = memoryStore.get("user:123");
expect(stored.value).toEqual(operation.value);
expect(stored.metadata.namespace).toBe("user");
});
it("should handle multiple namespaces independently", async () => {
const userOperation: MemoryOperation = {
type: "set",
key: "user:123",
value: { name: "John Doe" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "test-agent",
},
};
const sessionOperation: MemoryOperation = {
type: "set",
key: "session:abc",
value: { token: "xyz", expiry: Date.now() + 3600000 },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 3,
namespace: "session",
sourceAgent: "test-agent",
},
};
await (memoryManager as any).applyOperation(userOperation);
await (memoryManager as any).applyOperation(sessionOperation);
const memoryStore = (memoryManager as any).memoryStore;
expect(memoryStore.has("user:123")).toBe(true);
expect(memoryStore.has("session:abc")).toBe(true);
const userData = memoryStore.get("user:123");
const sessionData = memoryStore.get("session:abc");
expect(userData.metadata.namespace).toBe("user");
expect(sessionData.metadata.namespace).toBe("session");
});
it("should extract namespace from key correctly", () => {
const extractNamespace = (memoryManager as any).extractNamespace;
expect(extractNamespace("user:123")).toBe("user");
expect(extractNamespace("session:abc:def")).toBe("session");
expect(extractNamespace("simple-key")).toBe("default");
expect(extractNamespace("")).toBe("default");
});
it("should handle namespace-based TTL operations", async () => {
const operation: MemoryOperation = {
type: "set",
key: "cache:temp-data",
value: { data: "temporary" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 1,
namespace: "cache",
sourceAgent: "test-agent",
ttl: 1000, // 1 second
},
};
await (memoryManager as any).applyOperation(operation);
const memoryStore = (memoryManager as any).memoryStore;
const stored = memoryStore.get("cache:temp-data");
expect(stored.metadata.ttl).toBe(1000);
expect(stored.metadata.namespace).toBe("cache");
});
});
describe("Namespace-Based Conflict Resolution", () => {
it("should resolve conflicts within same namespace", async () => {
// Setup conflicting operations in same namespace
const operation1: MemoryOperation = {
type: "set",
key: "user:123",
value: { name: "John Doe", version: 1 },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "agent-1",
},
};
const operation2: MemoryOperation = {
type: "set",
key: "user:123",
value: { name: "John Smith", version: 2 },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "agent-2",
},
};
// Mock conflict detection
mockVectorClockInstance.compare.mockReturnValue("concurrent");
await (memoryManager as any).applyOperation(operation1);
// Second operation should detect conflict
const conflict = await (memoryManager as any).applyOperation(
operation2,
);
expect(conflict).toBe(operation2); // Should return the conflicting operation
});
it("should handle namespace-specific conflict resolution strategies", async () => {
const conflicts: MemoryOperation[] = [
{
type: "set",
key: "user:123",
value: { name: "Conflicted User" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "test-agent",
conflictResolution: "latest-wins",
},
},
];
// Mock conflict resolver
const mockConflictResolver = (memoryManager as any).conflictResolver;
mockConflictResolver.resolve = jest
.fn()
.mockResolvedValue(conflicts[0]);
await (memoryManager as any).resolveConflicts(conflicts);
expect(mockConflictResolver.resolve).toHaveBeenCalledWith(
conflicts[0],
undefined, // existing value
);
});
it("should isolate conflicts between different namespaces", async () => {
// Operations with same key but different namespaces shouldn't conflict
const userOperation: MemoryOperation = {
type: "set",
key: "user:data",
value: { type: "user" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "test-agent",
},
};
const cacheOperation: MemoryOperation = {
type: "set",
key: "cache:data", // Different namespace, but conceptually similar
value: { type: "cache" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "cache",
sourceAgent: "test-agent",
},
};
// Both should apply without conflict
const conflict1 = await (memoryManager as any).applyOperation(
userOperation,
);
const conflict2 = await (memoryManager as any).applyOperation(
cacheOperation,
);
expect(conflict1).toBeNull();
expect(conflict2).toBeNull();
});
});
describe("Namespace-Based Synchronization", () => {
it("should create namespace-aware delta synchronization", async () => {
// Add some namespaced data
const operations = [
{
type: "set" as const,
key: "user:123",
value: { name: "John" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "test-agent",
},
},
{
type: "set" as const,
key: "session:abc",
value: { token: "xyz" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 3,
namespace: "session",
sourceAgent: "test-agent",
},
},
];
// Apply operations to memory store
const memoryStore = (memoryManager as any).memoryStore;
operations.forEach((op) => {
memoryStore.set(op.key, {
value: op.value,
vectorClock: op.vectorClock,
metadata: op.metadata,
});
});
// Mock delta operations calculation
jest
.spyOn(memoryManager as any, "calculateDeltaOperations")
.mockResolvedValue(operations);
const delta = await memoryManager.createDeltaSync("target-agent");
expect(delta).toBeDefined();
expect(delta!.operations).toHaveLength(2);
expect(delta!.operations.map((op) => op.metadata.namespace)).toEqual([
"user",
"session",
]);
});
it("should apply namespace-aware delta operations", async () => {
const delta: MemoryDelta = {
deltaId: "test-delta",
sourceAgent: "source-agent",
targetAgents: ["test-agent"],
version: "1:1",
operations: [
{
type: "set",
key: "user:456",
value: { name: "Jane Doe" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "source-agent",
},
},
],
merkleRoot: "mock-root",
compressedData: Buffer.from("compressed"),
checksum: "mock-checksum",
timestamp: new Date(),
dependencies: [],
};
// Mock verification and decompression
jest
.spyOn(memoryManager as any, "verifyDeltaIntegrity")
.mockReturnValue(true);
const mockCompressor = (memoryManager as any).compressor;
mockCompressor.decompress = jest
.fn()
.mockResolvedValue(delta.operations);
const result = await memoryManager.applyDelta(delta);
expect(result).toBe(true);
const memoryStore = (memoryManager as any).memoryStore;
expect(memoryStore.has("user:456")).toBe(true);
const stored = memoryStore.get("user:456");
expect(stored.metadata.namespace).toBe("user");
});
it("should filter synchronization by namespace relevance", async () => {
const contextUpdate = {
id: "context-123",
requiredCapabilities: ["user-management"],
namespaces: ["user", "session"],
ttl: 3600000,
};
// Mock nodes with different capabilities
const nodes: AgentNode[] = [
{
agentId: "agent-1",
address: "agent://agent-1:8080",
role: "replica",
capacity: { memory: 100, cpu: 80, network: 100 },
capabilities: ["user-management", "session-management"],
trustLevel: 0.9,
lastSeen: new Date(),
vectorClock: mockVectorClockInstance,
shards: [],
},
{
agentId: "agent-2",
address: "agent://agent-2:8081",
role: "replica",
capacity: { memory: 100, cpu: 80, network: 100 },
capabilities: ["cache-management"],
trustLevel: 0.7,
lastSeen: new Date(),
vectorClock: mockVectorClockInstance,
shards: [],
},
];
// Mock relevance calculation
jest
.spyOn(memoryManager as any, "calculateRelevanceScores")
.mockResolvedValue(
new Map([
["agent-1", 0.8], // High relevance
["agent-2", 0.3], // Low relevance
]),
);
await memoryManager.propagateContext(contextUpdate, {
relevanceThreshold: 0.5,
namespace: "user",
});
// Should only propagate to agent-1 due to relevance threshold
// This would be verified through event emissions or mock calls
expect(true).toBe(true); // Placeholder assertion
});
});
describe("Memory Operations by Type", () => {
it("should handle SET operations correctly", async () => {
const operation: MemoryOperation = {
type: "set",
key: "config:setting",
value: { theme: "dark", lang: "en" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "config",
sourceAgent: "test-agent",
},
};
const result = await (memoryManager as any).applyOperation(operation);
expect(result).toBeNull(); // No conflict
const memoryStore = (memoryManager as any).memoryStore;
const stored = memoryStore.get("config:setting");
expect(stored.value).toEqual(operation.value);
});
it("should handle DELETE operations correctly", async () => {
// First set a value
const memoryStore = (memoryManager as any).memoryStore;
memoryStore.set("temp:data", {
value: { temp: true },
vectorClock: mockVectorClockInstance,
metadata: {
namespace: "temp",
sourceAgent: "test-agent",
priority: 1,
},
});
const deleteOperation: MemoryOperation = {
type: "delete",
key: "temp:data",
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "temp",
sourceAgent: "test-agent",
},
};
await (memoryManager as any).applyOperation(deleteOperation);
expect(memoryStore.has("temp:data")).toBe(false);
});
it("should handle MERGE operations correctly", async () => {
// Setup existing data
const memoryStore = (memoryManager as any).memoryStore;
memoryStore.set("user:profile", {
value: { name: "John", age: 30 },
vectorClock: mockVectorClockInstance,
metadata: {
namespace: "user",
sourceAgent: "test-agent",
priority: 5,
},
});
const mergeOperation: MemoryOperation = {
type: "merge",
key: "user:profile",
value: { email: "john@example.com", age: 31 },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "user",
sourceAgent: "test-agent",
},
};
// Mock CRDT merge
const mockCrdtSync = (memoryManager as any).crdtSync;
mockCrdtSync.merge = jest.fn().mockResolvedValue({
name: "John",
age: 31,
email: "john@example.com",
});
await (memoryManager as any).applyOperation(mergeOperation);
expect(mockCrdtSync.merge).toHaveBeenCalled();
});
});
});
describe("Topology Management", () => {
describe("Topology Optimization", () => {
it("should analyze swarm characteristics for optimization", () => {
const characteristics = (
memoryManager as any
).analyzeSwarmCharacteristics();
expect(characteristics).toHaveProperty("agentCount");
expect(characteristics).toHaveProperty("averageLatency");
expect(characteristics).toHaveProperty("memoryPressure");
expect(characteristics).toHaveProperty("consistencyRequirements");
expect(characteristics.agentCount).toBe(1); // Only local agent initially
});
it("should select optimal topology based on characteristics", async () => {
const selectOptimalTopology = (memoryManager as any)
.selectOptimalTopology;
// Test small swarm
let result = await selectOptimalTopology({
agentCount: 5,
memoryPressure: 0.3,
consistencyRequirements: { level: "eventual" },
});
expect(result).toBe("mesh");
// Test large swarm with strong consistency
result = await selectOptimalTopology({
agentCount: 20,
memoryPressure: 0.5,
consistencyRequirements: { level: "strong" },
});
expect(result).toBe("hierarchical");
// Test high memory pressure
result = await selectOptimalTopology({
agentCount: 15,
memoryPressure: 0.9,
consistencyRequirements: { level: "eventual" },
});
expect(result).toBe("hybrid");
});
it("should reconfigure topology when needed", async () => {
const initialTopology = memoryManager.getTopology();
expect(initialTopology.type).toBe("mesh");
// Mock topology analysis to suggest change
jest
.spyOn(memoryManager as any, "selectOptimalTopology")
.mockResolvedValue("hierarchical");
await memoryManager.optimizeTopology();
const newTopology = memoryManager.getTopology();
expect(newTopology.type).toBe("hierarchical");
});
});
describe("Agent Management", () => {
it("should add new agent to topology", async () => {
const newAgent: Partial<AgentNode> = {
agentId: "new-agent",
role: "replica",
capabilities: ["sync", "compress"],
};
await memoryManager.addAgent(newAgent);
const topology = memoryManager.getTopology();
expect(topology.nodes).toHaveLength(2);
const addedAgent = topology.nodes.find(
(n) => n.agentId === "new-agent",
);
expect(addedAgent).toBeDefined();
expect(addedAgent!.role).toBe("replica");
expect(addedAgent!.capabilities).toContain("sync");
});
it("should remove agent from topology", async () => {
// First add an agent
await memoryManager.addAgent({ agentId: "temp-agent" });
let topology = memoryManager.getTopology();
expect(topology.nodes).toHaveLength(2);
await memoryManager.removeAgent("temp-agent");
topology = memoryManager.getTopology();
expect(topology.nodes).toHaveLength(1);
expect(
topology.nodes.find((n) => n.agentId === "temp-agent"),
).toBeUndefined();
});
it("should handle agent removal with shard redistribution", async () => {
// Add agent with shards
const agentWithShards: Partial<AgentNode> = {
agentId: "shard-agent",
shards: ["shard-1", "shard-2"],
};
await memoryManager.addAgent(agentWithShards);
// Mock sharding manager
const mockSharding = (memoryManager as any).memorySharding;
mockSharding.redistributeShards = jest
.fn()
.mockResolvedValue(undefined);
await memoryManager.removeAgent("shard-agent");
expect(mockSharding.redistributeShards).toHaveBeenCalledWith(
["shard-1", "shard-2"],
expect.any(Array),
);
});
it("should rebalance shards when adding agents", async () => {
const mockSharding = (memoryManager as any).memorySharding;
mockSharding.rebalanceShards = jest.fn().mockResolvedValue(undefined);
await memoryManager.addAgent({ agentId: "balance-agent" });
expect(mockSharding.rebalanceShards).toHaveBeenCalled();
});
});
describe("Connection Management", () => {
it("should optimize connections in topology", async () => {
// Add multiple agents
await memoryManager.addAgent({ agentId: "agent-1" });
await memoryManager.addAgent({ agentId: "agent-2" });
const optimizeConnections = jest
.spyOn(memoryManager as any, "optimizeConnections")
.mockResolvedValue(undefined);
await memoryManager.optimizeTopology();
expect(optimizeConnections).toHaveBeenCalled();
});
it("should calculate topology efficiency correctly", () => {
const calculateTopologyEfficiency = (memoryManager as any)
.calculateTopologyEfficiency;
// With 1 node and no connections
let efficiency = calculateTopologyEfficiency();
expect(efficiency).toBe(0); // No connections possible with 1 node
// Mock 3 nodes with 2 connections out of possible 3
const topology = memoryManager.getTopology();
topology.nodes = [
{ agentId: "agent-1" } as AgentNode,
{ agentId: "agent-2" } as AgentNode,
{ agentId: "agent-3" } as AgentNode,
];
topology.connections = [
{ fromAgent: "agent-1", toAgent: "agent-2" } as any,
{ fromAgent: "agent-2", toAgent: "agent-3" } as any,
];
efficiency = calculateTopologyEfficiency();
expect(efficiency).toBeCloseTo(2 / 3); // 2 connections out of 3 possible
});
});
});
describe("Memory Compression and Optimization", () => {
describe("Data Compression", () => {
it("should compress memory data with optimal algorithm", async () => {
const testData = {
users: Array.from({ length: 100 }, (_, i) => ({
id: i,
name: `User ${i}`,
email: `user${i}@example.com`,
})),
};
// Mock compression analysis
jest
.spyOn(memoryManager as any, "analyzeDataCharacteristics")
.mockReturnValue({ type: "object", size: 5000, repetitionRate: 0.3 });
jest
.spyOn(memoryManager as any, "selectCompressionAlgorithm")
.mockReturnValue("brotli");
const mockCompressor = (memoryManager as any).compressor;
mockCompressor.compressWithAlgorithm = jest
.fn()
.mockResolvedValue(Buffer.from("compressed-data"));
const result = await memoryManager.compressMemoryData(testData, {
enableDeduplication: true,
});
expect(result).toBeInstanceOf(Buffer);
expect(mockCompressor.compressWithAlgorithm).toHaveBeenCalledWith(
testData,
"brotli",
undefined,
);
});
it("should select appropriate compression algorithm", () => {
const selectCompressionAlgorithm = (memoryManager as any)
.selectCompressionAlgorithm;
expect(selectCompressionAlgorithm({ type: "text" })).toBe("brotli");
expect(selectCompressionAlgorithm({ repetitionRate: 0.9 })).toBe("lz4");
expect(
selectCompressionAlgorithm({ type: "mixed", repetitionRate: 0.3 }),
).toBe("neural");
});
it("should handle data deduplication", async () => {
const duplicatedData = [1, 2, 2, 3, 3, 3, 4];
const deduplicateData = (memoryManager as any).deduplicateData;
const result = await deduplicateData(duplicatedData);
expect(result).toEqual([1, 2, 3, 4]);
});
});
describe("Memory Metrics and Monitoring", () => {
it("should calculate comprehensive memory metrics", () => {
// Setup some memory data
const memoryStore = (memoryManager as any).memoryStore;
memoryStore.set("user:1", {
value: { name: "User 1" },
metadata: { namespace: "user" },
});
memoryStore.set("session:1", {
value: { token: "abc" },
metadata: { namespace: "session" },
});
const metrics = memoryManager.getMemoryMetrics();
expect(metrics).toHaveProperty("totalMemoryUsage");
expect(metrics).toHaveProperty("replicatedMemoryUsage");
expect(metrics).toHaveProperty("compressionSavings");
expect(metrics).toHaveProperty("syncLatency");
expect(metrics).toHaveProperty("topologyEfficiency");
expect(metrics).toHaveProperty("conflictRate");
expect(metrics.totalMemoryUsage).toBeGreaterThan(0);
});
it("should track synchronization statistics", () => {
const stats = memoryManager.getSynchronizationStats();
expect(stats).toHaveProperty("totalSyncs");
expect(stats).toHaveProperty("successfulSyncs");
expect(stats).toHaveProperty("failedSyncs");
expect(stats).toHaveProperty("averageSyncTime");
expect(stats).toHaveProperty("compressionRatio");
expect(stats).toHaveProperty("conflictsResolved");
});
it("should calculate partition balance correctly", () => {
const calculatePartitionBalance = (memoryManager as any)
.calculatePartitionBalance;
// Mock topology with balanced shards
const topology = memoryManager.getTopology();
topology.nodes = [
{ agentId: "agent-1", shards: ["shard-1", "shard-2"] } as AgentNode,
{ agentId: "agent-2", shards: ["shard-3", "shard-4"] } as AgentNode,
{ agentId: "agent-3", shards: ["shard-5", "shard-6"] } as AgentNode,
];
const balance = calculatePartitionBalance();
expect(balance).toBeCloseTo(1.0); // Perfect balance
});
it("should calculate conflict rate correctly", () => {
const calculateConflictRate = (memoryManager as any)
.calculateConflictRate;
// Set up some stats
const stats = (memoryManager as any).stats;
stats.totalSyncs = 100;
stats.conflictsResolved = 5;
const rate = calculateConflictRate();
expect(rate).toBeCloseTo(0.005); // 5 conflicts out of 1000 operations (100 * 10)
});
});
});
describe("Context Propagation and Intelligence", () => {
describe("Relevance-Based Propagation", () => {
it("should calculate relevance scores for agents", async () => {
const contextUpdate = {
id: "context-1",
requiredCapabilities: ["user-management", "analytics"],
};
const nodes: AgentNode[] = [
{
agentId: "agent-1",
capabilities: ["user-management", "analytics"],
trustLevel: 0.9,
address: "agent://agent-1:8080",
role: "replica",
capacity: { memory: 100, cpu: 80, network: 100 },
lastSeen: new Date(),
vectorClock: mockVectorClockInstance,
shards: [],
},
{
agentId: "agent-2",
capabilities: ["cache-management"],
trustLevel: 0.7,
address: "agent://agent-2:8081",
role: "replica",
capacity: { memory: 100, cpu: 80, network: 100 },
lastSeen: new Date(),
vectorClock: mockVectorClockInstance,
shards: [],
},
];
const calculateRelevanceScores = (memoryManager as any)
.calculateRelevanceScores;
const scores = await calculateRelevanceScores(contextUpdate, nodes);
expect(scores.size).toBe(2);
expect(scores.get("agent-1")).toBeGreaterThan(scores.get("agent-2"));
});
it("should filter agents by relevance threshold", async () => {
const scores = new Map([
["agent-1", 0.8],
["agent-2", 0.3],
["agent-3", 0.6],
]);
// Mock topology nodes
const topology = memoryManager.getTopology();
topology.nodes = [
{ agentId: "agent-1" } as AgentNode,
{ agentId: "agent-2" } as AgentNode,
{ agentId: "agent-3" } as AgentNode,
];
const filterByRelevance = (memoryManager as any).filterByRelevance;
const relevant = filterByRelevance(scores, 0.5);
expect(relevant).toHaveLength(2);
expect(relevant.map((a) => a.agentId)).toEqual(["agent-1", "agent-3"]);
});
it("should personalize context for different agents", async () => {
const contextUpdate = {
id: "context-1",
capabilities: ["user-management", "analytics", "reporting"],
data: { sensitive: true },
};
const agent: AgentNode = {
agentId: "agent-1",
capabilities: ["user-management"],
trustLevel: 0.7,
address: "agent://agent-1:8080",
role: "replica",
capacity: { memory: 100, cpu: 80, network: 100 },
lastSeen: new Date(),
vectorClock: mockVectorClockInstance,
shards: [],
};
const personalizeContext = (memoryManager as any).personalizeContext;
const personalized = await personalizeContext(
contextUpdate,
agent,
0.6,
);
expect(personalized.capabilities).toEqual(["user-management"]);
expect(personalized.detail).toBe("summary"); // Low relevance
});
});
describe("Context Distribution", () => {
it("should distribute operations to relevant agents", async () => {
const operations: MemoryOperation[] = [
{
type: "set",
key: "context:update",
value: { data: "contextual" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "context",
sourceAgent: "test-agent",
},
},
];
const targetAgents = ["agent-1", "agent-2"];
// Mock delta creation
jest.spyOn(memoryManager, "createDeltaSync").mockResolvedValue({
deltaId: "test-delta",
operations,
sourceAgent: "test-agent",
} as MemoryDelta);
const sendDeltaToAgent = jest
.spyOn(memoryManager as any, "sendDeltaToAgent")
.mockResolvedValue(undefined);
const distributeOperations = (memoryManager as any)
.distributeOperations;
await distributeOperations(operations, targetAgents);
expect(sendDeltaToAgent).toHaveBeenCalledTimes(2);
});
it("should handle context propagation with options", async () => {
const contextUpdate = {
id: "context-123",
data: "important data",
};
// Mock the entire propagation chain
jest
.spyOn(memoryManager as any, "calculateRelevanceScores")
.mockResolvedValue(new Map([["agent-1", 0.8]]));
jest
.spyOn(memoryManager as any, "filterByRelevance")
.mockReturnValue([{ agentId: "agent-1" } as AgentNode]);
jest
.spyOn(memoryManager as any, "personalizeContext")
.mockResolvedValue({ ...contextUpdate, personalized: true });
jest
.spyOn(memoryManager as any, "distributeOperations")
.mockResolvedValue(undefined);
await memoryManager.propagateContext(contextUpdate, {
priority: 8,
maxTargets: 5,
namespace: "urgent",
});
// Verify the propagation chain was called
expect(true).toBe(true); // Placeholder - in real tests would verify mock calls
});
});
});
describe("Emergency and Error Handling", () => {
describe("Emergency Cleanup", () => {
it("should perform emergency cleanup correctly", async () => {
// Setup some memory data
const memoryStore = (memoryManager as any).memoryStore;
memoryStore.set("data:1", { value: "test" });
memoryStore.set("data:2", { value: "test" });
const clearNonCriticalMemory = jest
.spyOn(memoryManager as any, "clearNonCriticalMemory")
.mockResolvedValue(undefined);
const compressAllMemory = jest
.spyOn(memoryManager as any, "compressAllMemory")
.mockResolvedValue(undefined);
await memoryManager.emergencyCleanup(
"Memory pressure exceeded threshold",
);
expect(clearNonCriticalMemory).toHaveBeenCalled();
expect(compressAllMemory).toHaveBeenCalled();
});
it("should reset metrics during emergency cleanup", async () => {
const initialMetrics = memoryManager.getMemoryMetrics();
await memoryManager.emergencyCleanup("Test cleanup");
const clearedMetrics = memoryManager.getMemoryMetrics();
// Most numeric metrics should be reset to 0
expect(clearedMetrics.totalMemoryUsage).toBe(0);
expect(clearedMetrics.replicatedMemoryUsage).toBe(0);
});
it("should handle emergency cleanup failures gracefully", async () => {
// Mock a failure in cleanup
jest
.spyOn(memoryManager as any, "clearNonCriticalMemory")
.mockRejectedValue(new Error("Cleanup failed"));
await expect(
memoryManager.emergencyCleanup("Test failure"),
).rejects.toThrow("Cleanup failed");
});
});
describe("Error Recovery", () => {
it("should handle delta application failures", async () => {
const invalidDelta: MemoryDelta = {
deltaId: "invalid-delta",
sourceAgent: "source-agent",
targetAgents: ["test-agent"],
version: "1:1",
operations: [],
merkleRoot: "invalid-root",
compressedData: Buffer.from("invalid"),
checksum: "wrong-checksum",
timestamp: new Date(),
dependencies: [],
};
// Mock failed verification
jest
.spyOn(memoryManager as any, "verifyDeltaIntegrity")
.mockReturnValue(false);
const result = await memoryManager.applyDelta(invalidDelta);
expect(result).toBe(false);
const stats = memoryManager.getSynchronizationStats();
expect(stats.failedSyncs).toBeGreaterThan(0);
});
it("should handle network partition scenarios", async () => {
// Add multiple agents
await memoryManager.addAgent({ agentId: "agent-1" });
await memoryManager.addAgent({ agentId: "agent-2" });
let topology = memoryManager.getTopology();
expect(topology.nodes).toHaveLength(3);
// Simulate removing agents (like in a partition)
await memoryManager.removeAgent("agent-1");
await memoryManager.removeAgent("agent-2");
topology = memoryManager.getTopology();
expect(topology.nodes).toHaveLength(1); // Only local agent remains
});
});
});
describe("Performance and Scalability", () => {
describe("Large Scale Operations", () => {
it("should handle large number of memory operations efficiently", async () => {
const startTime = Date.now();
// Create many operations
const operations = Array.from({ length: 1000 }, (_, i) => ({
type: "set" as const,
key: `bulk:item-${i}`,
value: { id: i, data: `Item ${i}` },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 1,
namespace: "bulk",
sourceAgent: "test-agent",
},
}));
// Apply all operations
for (const operation of operations) {
await (memoryManager as any).applyOperation(operation);
}
const endTime = Date.now();
const duration = endTime - startTime;
// Should complete within reasonable time (adjust threshold as needed)
expect(duration).toBeLessThan(5000); // 5 seconds
const memoryStore = (memoryManager as any).memoryStore;
expect(memoryStore.size).toBe(1000);
});
it("should handle concurrent delta applications", async () => {
const createTestDelta = (id: string): MemoryDelta => ({
deltaId: `delta-${id}`,
sourceAgent: `source-${id}`,
targetAgents: ["test-agent"],
version: "1:1",
operations: [
{
type: "set",
key: `concurrent:${id}`,
value: { data: id },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "concurrent",
sourceAgent: `source-${id}`,
},
},
],
merkleRoot: `root-${id}`,
compressedData: Buffer.from(`compressed-${id}`),
checksum: `checksum-${id}`,
timestamp: new Date(),
dependencies: [],
});
// Mock successful verification and decompression
jest
.spyOn(memoryManager as any, "verifyDeltaIntegrity")
.mockReturnValue(true);
const mockCompressor = (memoryManager as any).compressor;
mockCompressor.decompress = jest.fn().mockImplementation((data) =>
Promise.resolve([
{
type: "set",
key: "test:key",
value: { data: "test" },
vectorClock: mockVectorClockInstance,
metadata: {
priority: 5,
namespace: "test",
sourceAgent: "test-agent",
},
},
]),
);
// Apply multiple deltas concurrently
const deltas = Array.from({ length: 10 }, (_, i) =>
createTestDelta(i.toString()),
);
const promises = deltas.map((delta) => memoryManager.applyDelta(delta));
const results = await Promise.all(promises);
// All should succeed
results.forEach((result) => {
expect(result).toBe(true);
});
});
});
describe("Memory Efficiency", () => {
it("should maintain reasonable memory usage under load", async () => {
const initialMetrics = memoryManager.getMemoryMetrics();
// Add substantial amount of data
const memoryStore = (memoryManager as any).memoryStore;
for (let i = 0; i < 1000; i++) {
memoryStore.set(`load:${i}`, {
value: { data: `Large data string ${i}`.repeat(10) },
metadata: {
namespace: "load",
sourceAgent: "test-agent",
priority: 1,
},
});
}
const loadedMetrics = memoryManager.getMemoryMetrics();
expect(loadedMetrics.totalMemoryUsage).toBeGreaterThan(
initialMetrics.totalMemoryUsage,
);
// Verify memory is being tracked correctly
expect(loadedMetrics.totalMemoryUsage).toBeGreaterThan(0);
});
it("should compress data efficiently", async () => {
const largeData = {
items: Array.from({ length: 100 }, (_, i) => ({
id: i,
name: `Item ${i}`,
description:
`This is item number ${i} with some repeated content`.repeat(5),
})),
};
const mockCompressor = (memoryManager as any).compressor;
mockCompressor.compressWithAlgorithm = jest
.fn()
.mockResolvedValue(Buffer.from("compressed"));
const originalSize = JSON.stringify(largeData).length;
const compressed = await memoryManager.compressMemoryData(largeData);
expect(compressed.length).toBeLessThan(originalSize);
const stats = memoryManager.getSynchronizationStats();
expect(stats.compressionRatio).toBeGreaterThan(0);
});
});
});
});