117 lines
3.7 KiB
Nim
117 lines
3.7 KiB
Nim
import unittest, os, strutils, tables, options, json
|
|
import ../src/nimpak/cas
|
|
import ../src/nip/types
|
|
|
|
suite "CAS Performance Optimizations Tests":
|
|
|
|
var
|
|
cas: CasManager
|
|
testRoot = getTempDir() / "nip_optim_test_" & $getCurrentProcessId()
|
|
testFile = testRoot / "large_file.dat"
|
|
|
|
setup:
|
|
createDir(testRoot)
|
|
cas = initCasManager(testRoot)
|
|
|
|
# Create a dummy large file (larger than 1MB to trigger chunking)
|
|
var f = open(testFile, fmWrite)
|
|
# Write 1.5MB
|
|
let chunk = newString(1024 * 64) # 64KB
|
|
for i in 0..<24:
|
|
f.write(chunk)
|
|
f.close()
|
|
|
|
teardown:
|
|
removeDir(testRoot)
|
|
|
|
test "Index Caching":
|
|
# Initial state
|
|
check cas.indexCache.isNone
|
|
|
|
# Load index (should create empty one)
|
|
discard cas.loadIndex()
|
|
check cas.indexCache.isSome
|
|
let idx = cas.indexCache.get()
|
|
check idx.totalChunks == 0
|
|
|
|
# Update index
|
|
cas.updateIndex(100, 1)
|
|
check cas.indexCache.get().totalChunks == 1
|
|
check cas.indexCache.get().totalSize == 100
|
|
|
|
# Save and reload
|
|
discard cas.saveIndex()
|
|
|
|
# Reset manager to clear cache
|
|
var newCas = initCasManager(testRoot)
|
|
discard newCas.loadIndex()
|
|
check newCas.indexCache.get().totalChunks == 1
|
|
check newCas.indexCache.get().totalSize == 100
|
|
|
|
test "Existence Caching":
|
|
let data = "test data"
|
|
let res = cas.storeObject(data.toOpenArrayByte(0, data.len-1))
|
|
let hash = res.get().hash
|
|
|
|
# Cache should be empty initially (or populated by storeObject? storeObject doesn't update existenceCache currently)
|
|
# Wait, storeObject calls objectExists.
|
|
# But objectExists updates cache ONLY if found.
|
|
# When we store a NEW object, objectExists returns false.
|
|
# Then we write file.
|
|
# So cache is NOT updated for the new object yet.
|
|
|
|
check not cas.existenceCache.hasKey(hash)
|
|
|
|
# First check - should hit disk and populate cache
|
|
check cas.objectExists(hash)
|
|
check cas.existenceCache.hasKey(hash)
|
|
check cas.existenceCache[hash].endsWith(hash.split('-')[1])
|
|
|
|
# Second check - should hit cache
|
|
# Since our cache verifies file existence, deleting the file invalidates the cache.
|
|
# So we just verify the cache is populated.
|
|
check cas.existenceCache.hasKey(hash)
|
|
check cas.existenceCache[hash].endsWith(hash.split('-')[1])
|
|
|
|
# Invalidate cache manually
|
|
cas.existenceCache.del(hash)
|
|
check not cas.existenceCache.hasKey(hash)
|
|
|
|
test "Parallel Store Correctness":
|
|
# We test storeFileParallel for correctness
|
|
let res = cas.storeFileParallel(testFile)
|
|
if not res.isOk:
|
|
echo "Store failed: ", res.getError().msg
|
|
check res.isOk
|
|
let obj = res.get()
|
|
check obj.chunks.len > 0
|
|
|
|
# Verify we can retrieve it
|
|
let outFile = testRoot / "retrieved.dat"
|
|
let retRes = cas.retrieveFile(obj.hash, outFile)
|
|
if not retRes.isOk:
|
|
echo "Retrieve failed: ", retRes.errValue.msg
|
|
check retRes.isOk
|
|
|
|
if retRes.isOk:
|
|
check getFileInfo(outFile).size == getFileInfo(testFile).size
|
|
else:
|
|
# Debug: check if it wrote a manifest file
|
|
if fileExists(outFile):
|
|
echo "Output file size: ", getFileInfo(outFile).size
|
|
echo "Output content preview: ", readFile(outFile)[0..100]
|
|
|
|
test "Manifest Caching":
|
|
# Store a file (creates manifest)
|
|
let res = cas.storeFile(testFile)
|
|
let hash = res.get().hash
|
|
|
|
check not cas.manifestCache.hasKey(hash)
|
|
|
|
# Retrieve file - should populate manifest cache
|
|
let outFile = testRoot / "retrieved_manifest.dat"
|
|
discard cas.retrieveFile(hash, outFile)
|
|
|
|
check cas.manifestCache.hasKey(hash)
|
|
check cas.manifestCache[hash].kind == JObject
|
|
check cas.manifestCache[hash].hasKey("chunks") |