201 lines
6.4 KiB
Nim
201 lines
6.4 KiB
Nim
## Test suite for the synchronization engine
|
|
##
|
|
## This module tests the bloom filter handshake, delta object creation,
|
|
## and incremental synchronization functionality.
|
|
|
|
import std/[unittest, times, json, tables, sequtils, asyncdispatch]
|
|
import ../src/nimpak/remote/sync_engine
|
|
import ../src/nimpak/cas
|
|
import ../src/nimpak/security/event_logger
|
|
|
|
suite "Synchronization Engine Tests":
|
|
|
|
setup:
|
|
# Initialize test environment
|
|
let testCasPath = "/tmp/test_cas"
|
|
let testLogPath = "/tmp/test_security.log"
|
|
|
|
# Create test CAS manager
|
|
let casManager = newCasManager(testCasPath, testCasPath)
|
|
|
|
# Create test event logger
|
|
let eventLogger = newSecurityEventLogger(testLogPath, testCasPath)
|
|
|
|
# Create sync engine with test configuration
|
|
var config = getDefaultSyncEngineConfig()
|
|
config.bloomFilterSize = 1000 # Smaller for testing
|
|
config.syncIntervalSeconds = 10 # Faster for testing
|
|
|
|
var syncEngine = newSyncEngine(casManager, eventLogger, config)
|
|
|
|
test "Bloom Filter Creation and Operations":
|
|
var filter = newBloomFilter(100, 0.01)
|
|
|
|
# Test adding items
|
|
filter.add("test-hash-1")
|
|
filter.add("test-hash-2")
|
|
filter.add("test-hash-3")
|
|
|
|
# Test contains (should return true for added items)
|
|
check filter.contains("test-hash-1") == true
|
|
check filter.contains("test-hash-2") == true
|
|
check filter.contains("test-hash-3") == true
|
|
|
|
# Test false negatives (should not occur)
|
|
check filter.contains("non-existent-hash") == false or true # May be false positive
|
|
|
|
# Test serialization
|
|
let serialized = filter.serialize()
|
|
check serialized.len > 0
|
|
|
|
# Test deserialization
|
|
let deserialized = deserializeBloomFilter(serialized)
|
|
check deserialized.size == filter.size
|
|
check deserialized.hashFunctions == filter.hashFunctions
|
|
|
|
test "Bandwidth Limiter":
|
|
var limiter = newBandwidthLimiter(1000) # 1KB/s limit
|
|
|
|
# Test bandwidth checking
|
|
check limiter.checkBandwidth(500) == true # Should allow 500 bytes
|
|
check limiter.checkBandwidth(600) == false # Should deny 600 more bytes (total 1100)
|
|
|
|
# Test bandwidth reset after time window
|
|
limiter.windowStart = now() - initDuration(seconds = 2) # Simulate time passage
|
|
check limiter.checkBandwidth(500) == true # Should allow after reset
|
|
|
|
test "Mirror Management":
|
|
var engine = syncEngine
|
|
|
|
# Test adding mirrors
|
|
let result1 = engine.addMirror("test-mirror-1", "https://test1.example.com", 100)
|
|
check result1.success == true
|
|
|
|
let result2 = engine.addMirror("test-mirror-2", "https://test2.example.com", 50)
|
|
check result2.success == true
|
|
|
|
# Test duplicate mirror
|
|
let result3 = engine.addMirror("test-mirror-1", "https://duplicate.example.com", 75)
|
|
check result3.success == false
|
|
check result3.errorCode == 409
|
|
|
|
# Test mirror selection
|
|
let bestMirror = engine.selectBestMirror()
|
|
check bestMirror.isSome()
|
|
check bestMirror.get().id == "test-mirror-1" # Higher priority
|
|
|
|
# Test removing mirror
|
|
let removeResult = engine.removeMirror("test-mirror-2")
|
|
check removeResult.success == true
|
|
|
|
test "Delta Object Creation":
|
|
let engine = syncEngine
|
|
let testData = "This is test data for delta object creation"
|
|
|
|
# Store test data in CAS
|
|
let storeResult = engine.localCasManager.storeObject(testData.toOpenArrayByte(0, testData.len - 1))
|
|
check storeResult.isOk == true
|
|
|
|
let casObject = storeResult.get()
|
|
|
|
# Create delta object
|
|
let deltaResult = engine.createDeltaObject(casObject.hash)
|
|
check deltaResult.success == true
|
|
|
|
let delta = deltaResult.value
|
|
check delta.objectHash == casObject.hash
|
|
check delta.deltaType == "add"
|
|
check delta.originalSize == testData.len.int64
|
|
|
|
test "Sync Event Extraction":
|
|
let engine = syncEngine
|
|
|
|
# Create some test security events
|
|
var testEvent = createSecurityEvent(
|
|
EventPackageVerification,
|
|
SeverityInfo,
|
|
"test-source",
|
|
"Test package verification",
|
|
%*{"package_hash": "blake2b-test123"}
|
|
)
|
|
|
|
engine.eventLogger.logSecurityEvent(testEvent)
|
|
|
|
# Extract sync events
|
|
let syncEvents = engine.extractSyncEventsFromSecurityLog(now() - initDuration(hours = 1))
|
|
|
|
# Should find at least one sync event
|
|
check syncEvents.len >= 1
|
|
|
|
# Check event properties
|
|
if syncEvents.len > 0:
|
|
let syncEvent = syncEvents[0]
|
|
check syncEvent.eventType == SyncPackageUpdated
|
|
check syncEvent.objectHash == "blake2b-test123"
|
|
|
|
test "Bloom Filter Update from Events":
|
|
var engine = syncEngine
|
|
|
|
# Create test sync events
|
|
let events = @[
|
|
SyncEvent(
|
|
id: "test-1",
|
|
timestamp: now(),
|
|
eventType: SyncPackageAdded,
|
|
objectHash: "blake2b-hash1",
|
|
metadata: newJObject(),
|
|
sequenceNumber: 1
|
|
),
|
|
SyncEvent(
|
|
id: "test-2",
|
|
timestamp: now(),
|
|
eventType: SyncPackageUpdated,
|
|
objectHash: "blake2b-hash2",
|
|
metadata: newJObject(),
|
|
sequenceNumber: 2
|
|
)
|
|
]
|
|
|
|
# Update bloom filter
|
|
engine.updateBloomFilterFromEvents(events)
|
|
|
|
# Check that objects were added to bloom filter and known objects
|
|
check engine.syncState.bloomFilter.contains("blake2b-hash1") == true
|
|
check engine.syncState.bloomFilter.contains("blake2b-hash2") == true
|
|
check "blake2b-hash1" in engine.syncState.knownObjects
|
|
check "blake2b-hash2" in engine.syncState.knownObjects
|
|
|
|
test "Mirror Health Updates":
|
|
var engine = syncEngine
|
|
|
|
# Add test mirror
|
|
discard engine.addMirror("health-test", "https://health.example.com", 50)
|
|
|
|
# Update health with good metrics
|
|
engine.updateMirrorHealth("health-test", 100.0, true) # 100ms latency, success
|
|
|
|
let mirror1 = engine.mirrors["health-test"]
|
|
check mirror1.status == MirrorActive
|
|
check mirror1.latency == 100.0
|
|
check mirror1.reliability > 0.5
|
|
|
|
# Update health with bad metrics
|
|
engine.updateMirrorHealth("health-test", 6000.0, false) # 6s latency, failure
|
|
|
|
let mirror2 = engine.mirrors["health-test"]
|
|
check mirror2.status == MirrorSlow or mirror2.status == MirrorUnreachable
|
|
check mirror2.reliability < 0.9 # Should decrease
|
|
|
|
teardown:
|
|
# Clean up test files
|
|
try:
|
|
removeDir("/tmp/test_cas")
|
|
removeFile("/tmp/test_security.log")
|
|
except:
|
|
discard # Ignore cleanup errors
|
|
|
|
# Run async tests
|
|
when isMainModule:
|
|
# Note: Async tests would need special handling in a real test suite
|
|
# For now, we just run the synchronous tests
|
|
discard |