nip/tests/test_nippels_merkle_integra...

279 lines
8.6 KiB
Nim

## Test suite for Nippels Merkle Tree Integration (Task 8.4)
##
## Tests the integration of Merkle Tree with NippelManager
import std/[unittest, os, times, strutils, tables, json]
import ../src/nimpak/nippels
import ../src/nimpak/merkle_tree
import ../src/nimpak/nippel_types
import ../src/nimpak/utils/resultutils
suite "Nippels Merkle Tree Integration (Task 8.4)":
var manager: NippelManager
let testRoot = getTempDir() / "nippels_merkle_test_" & $epochTime().int
setup:
# Create test directory
createDir(testRoot)
manager = newNippelManager(testRoot)
teardown:
# Deactivate all active Nippels
for name in manager.getActiveNippels():
discard manager.deactivateNippel(name)
# Clean up test directory
if dirExists(testRoot):
removeDir(testRoot)
test "Create Nippel builds initial merkle tree":
let result = manager.createNippel("test-merkle", Homestation)
check result.isOk
if result.isOk:
let nippel = result.value
# Verify merkle root is set
check nippel.merkleRoot.len > 0
check nippel.merkleRoot.startsWith("xxh3-")
# Verify merkle tree is stored in manager
check manager.merkleTrees.hasKey("test-merkle")
let tree = manager.merkleTrees["test-merkle"]
check tree.hashAlgorithm == "xxh3"
check tree.leafCount >= 0 # Empty tree initially
echo " ✅ Initial merkle tree created with root: ", nippel.merkleRoot
test "Merkle root is stored in cell configuration":
let result = manager.createNippel("test-config", Homestation)
check result.isOk
if result.isOk:
let nippel = result.value
let configPath = nippel.cellRoot / "cell.json"
check fileExists(configPath)
# Read and verify configuration contains merkle root
let config = parseJson(readFile(configPath))
check config.hasKey("storage")
check config["storage"].hasKey("merkle_root")
check config["storage"]["merkle_root"].getStr() == nippel.merkleRoot
echo " ✅ Merkle root stored in configuration"
test "Multiple Nippels have independent merkle trees":
let result1 = manager.createNippel("test-multi-1", Homestation)
let result2 = manager.createNippel("test-multi-2", Workstation)
let result3 = manager.createNippel("test-multi-3", Server)
check result1.isOk
check result2.isOk
check result3.isOk
if result1.isOk and result2.isOk and result3.isOk:
# Verify each has its own merkle tree
check manager.merkleTrees.hasKey("test-multi-1")
check manager.merkleTrees.hasKey("test-multi-2")
check manager.merkleTrees.hasKey("test-multi-3")
# Verify merkle roots (should all be the same for empty trees)
let nippel1 = result1.value
let nippel2 = result2.value
let nippel3 = result3.value
check nippel1.merkleRoot.len > 0
check nippel2.merkleRoot.len > 0
check nippel3.merkleRoot.len > 0
echo " ✅ Multiple independent merkle trees created"
test "Merkle tree uses xxh3 algorithm":
let result = manager.createNippel("test-algorithm", Homestation)
check result.isOk
if result.isOk:
let tree = manager.merkleTrees["test-algorithm"]
check tree.hashAlgorithm == "xxh3"
check tree.root.hash.startsWith("xxh3-")
echo " ✅ Merkle tree uses xxh3 algorithm"
test "Empty merkle tree has valid root hash":
let result = manager.createNippel("test-empty", Homestation)
check result.isOk
if result.isOk:
let nippel = result.value
let tree = manager.merkleTrees["test-empty"]
# Verify tree structure
check tree.root != nil
check tree.root.hash.len > 0
check tree.leafCount >= 0
# Verify root hash matches
check getRootHash(tree) == nippel.merkleRoot
echo " ✅ Empty merkle tree has valid root hash"
test "Merkle tree can be verified":
let result = manager.createNippel("test-verify", Homestation)
check result.isOk
if result.isOk:
let tree = manager.merkleTrees["test-verify"]
# Verify the tree
let verifyResult = verifyTree(tree)
check verifyResult.isOk
if verifyResult.isOk:
check verifyResult.get() == true
echo " ✅ Merkle tree verification passed"
test "Merkle tree can be updated with new files":
let result = manager.createNippel("test-update", Homestation)
check result.isOk
if result.isOk:
var tree = manager.merkleTrees["test-update"]
let oldRoot = getRootHash(tree)
# Add a file to the tree
let addResult = addFile(tree, "test.txt", "xxh3-abc123", 100)
check addResult.isOk
if addResult.isOk:
let newRoot = addResult.get()
check newRoot != oldRoot
check newRoot.len > 0
# Update the tree in manager
manager.merkleTrees["test-update"] = tree
echo " ✅ Merkle tree updated with new file"
echo " Old root: ", oldRoot
echo " New root: ", newRoot
test "Merkle tree tracks file additions":
let result = manager.createNippel("test-additions", Homestation)
check result.isOk
if result.isOk:
var tree = manager.merkleTrees["test-additions"]
# Add multiple files
discard addFile(tree, "file1.txt", "xxh3-hash1", 100)
discard addFile(tree, "file2.txt", "xxh3-hash2", 200)
discard addFile(tree, "file3.txt", "xxh3-hash3", 300)
# Verify tree has the files
let leaves = getAllLeaves(tree)
check leaves.len == 3
# Verify we can find each file
check findLeafInTree(tree, "file1.txt").isSome
check findLeafInTree(tree, "file2.txt").isSome
check findLeafInTree(tree, "file3.txt").isSome
echo " ✅ Merkle tree tracks file additions"
test "Merkle tree can diff between states":
let result = manager.createNippel("test-diff", Homestation)
check result.isOk
if result.isOk:
var tree1 = manager.merkleTrees["test-diff"]
# Add files to tree1
discard addFile(tree1, "file1.txt", "xxh3-hash1", 100)
discard addFile(tree1, "file2.txt", "xxh3-hash2", 200)
# Create tree2 with different files
var tree2 = tree1
discard addFile(tree2, "file3.txt", "xxh3-hash3", 300)
discard removeFile(tree2, "file1.txt")
# Diff the trees
let diffResult = diffTrees(tree1, tree2)
check diffResult.isOk
if diffResult.isOk:
let diffs = diffResult.get()
check diffs.len > 0
echo " ✅ Merkle tree diffing works"
echo " Found ", diffs.len, " differences"
test "Merkle tree root changes when content changes":
let result = manager.createNippel("test-changes", Homestation)
check result.isOk
if result.isOk:
var tree = manager.merkleTrees["test-changes"]
let root1 = getRootHash(tree)
# Add a file
discard addFile(tree, "file.txt", "xxh3-hash1", 100)
let root2 = getRootHash(tree)
# Modify the file
discard updateFile(tree, "file.txt", "xxh3-hash2", 150)
let root3 = getRootHash(tree)
# Remove the file
discard removeFile(tree, "file.txt")
let root4 = getRootHash(tree)
# All roots should be different
check root1 != root2
check root2 != root3
check root3 != root4
check root1 == root4 # Back to empty tree
echo " ✅ Merkle root changes with content"
test "Merkle tree verification detects tampering":
let result = manager.createNippel("test-tamper", Homestation)
check result.isOk
if result.isOk:
var tree = manager.merkleTrees["test-tamper"]
# Add files
discard addFile(tree, "file1.txt", "xxh3-hash1", 100)
discard addFile(tree, "file2.txt", "xxh3-hash2", 200)
# Verify tree is valid
let verifyResult1 = verifyTree(tree)
check verifyResult1.isOk
check verifyResult1.get() == true
# Tamper with a node (if we had access to internal nodes)
# For now, just verify that verification works
echo " ✅ Merkle tree verification works"
test "Merkle tree performance is acceptable":
let result = manager.createNippel("test-perf", Homestation)
check result.isOk
if result.isOk:
var tree = manager.merkleTrees["test-perf"]
# Add many files and measure time
let startTime = cpuTime()
for i in 1..100:
discard addFile(tree, "file" & $i & ".txt", "xxh3-hash" & $i, int64(i * 100))
let endTime = cpuTime()
let duration = (endTime - startTime) * 1000.0 # Convert to ms
echo " ✅ Added 100 files in ", duration.formatFloat(ffDecimal, 2), " ms"
# Verify performance is reasonable (< 100ms for 100 files)
check duration < 100.0
echo "✅ All Task 8.4 tests completed"