## test_remote_cache.nim ## Tests for remote binary cache import std/[unittest, os, tables, times, options] import ../src/nimpak/build/[binary_cache, remote_cache] suite "Remote Cache Configuration": test "Load default config": let config = loadConfig("/tmp/nonexistent-config.json") check: config.timeout == DefaultTimeout config.enabled == false config.url == "" config.apiKey == "" test "Save and load config": let tempConfig = getTempDir() / "test-remote-cache.json" var config = RemoteCacheConfig() config.url = "https://cache.example.com" config.apiKey = "test-key-123" config.timeout = 600 config.enabled = true saveConfig(config, tempConfig) let loaded = loadConfig(tempConfig) check: loaded.url == "https://cache.example.com" loaded.apiKey == "test-key-123" loaded.timeout == 600 loaded.enabled == true removeFile(tempConfig) test "Config with missing fields": let tempConfig = getTempDir() / "test-partial-config.json" writeFile(tempConfig, """{"url": "https://cache.example.com"}""") let config = loadConfig(tempConfig) check: config.url == "https://cache.example.com" config.timeout == DefaultTimeout config.enabled == false removeFile(tempConfig) suite "Remote Cache Client": setup: let tempCache = getTempDir() / "test-remote-cache" removeDir(tempCache) createDir(tempCache) let bcm = newBinaryCacheManager(tempCache) var config = RemoteCacheConfig() config.url = "https://cache.example.com" config.apiKey = "test-key" config.timeout = 300 config.enabled = true let client = newRemoteCacheClient(config, bcm) teardown: removeDir(tempCache) test "Create client": check: client != nil client.config.url == "https://cache.example.com" client.config.enabled == true test "Client configuration": check: client.config.timeout == 300 client.config.apiKey == "test-key" test "Disabled client": var disabledConfig = RemoteCacheConfig() disabledConfig.enabled = false let disabledClient = newRemoteCacheClient(disabledConfig, bcm) # Should return false/none for disabled client check: disabledClient.checkAvailability() == false disabledClient.lookup("test", "1.0", "fp123").isNone suite "Remote Cache Integration": setup: let tempCache = getTempDir() / "test-integration-cache" removeDir(tempCache) createDir(tempCache) let bcm = newBinaryCacheManager(tempCache) teardown: removeDir(tempCache) test "Lookup with disabled remote cache": var config = RemoteCacheConfig() config.enabled = false let client = newRemoteCacheClient(config, bcm) let result = client.lookup("vim", "9.0", "test-fp") check: result.isNone test "Upload with disabled remote cache": var config = RemoteCacheConfig() config.enabled = false let client = newRemoteCacheClient(config, bcm) # Create test artifact let testArtifact = tempCache / "test-artifact.tar.gz" writeFile(testArtifact, "test content") let result = client.upload("vim", "9.0", "test-fp", testArtifact) check: result == false removeFile(testArtifact) test "Download with local cache hit": # Store in local cache first let testArtifact = tempCache / "test-artifact.tar.gz" writeFile(testArtifact, "test content") let stored = bcm.store("vim", "9.0", "test-fp", testArtifact) check stored # Try to download - should detect local cache hit var config = RemoteCacheConfig() config.url = "https://cache.example.com" config.enabled = true let client = newRemoteCacheClient(config, bcm) let result = client.download("vim", "9.0", "test-fp") # Should return true because already in local cache check: result == true removeFile(testArtifact) suite "Cache Key Generation": test "Generate cache key": let key = getCacheKey("vim", "9.0", "abc123") check: key == "vim-9.0-abc123" test "Cache key with empty version": let key = getCacheKey("vim", "", "abc123") check: key == "vim--abc123" test "Cache key consistency": let key1 = getCacheKey("vim", "9.0", "abc123") let key2 = getCacheKey("vim", "9.0", "abc123") check: key1 == key2 suite "Variant Fingerprint": test "Calculate fingerprint with USE flags": let fp = calculateVariantFingerprint( useFlags = @["python", "ruby", "lua"] ) check: fp.len > 0 test "Calculate fingerprint with compiler flags": let fp = calculateVariantFingerprint( cflags = "-O3 -march=native", ldflags = "-Wl,-O1" ) check: fp.len > 0 test "Calculate fingerprint with make options": var makeOpts = initTable[string, string]() makeOpts["JOBS"] = "4" makeOpts["VERBOSE"] = "1" let fp = calculateVariantFingerprint( makeOpts = makeOpts ) check: fp.len > 0 test "Fingerprint consistency": let fp1 = calculateVariantFingerprint( useFlags = @["python", "ruby"], cflags = "-O2" ) let fp2 = calculateVariantFingerprint( useFlags = @["python", "ruby"], cflags = "-O2" ) check: fp1 == fp2 test "Fingerprint changes with different flags": let fp1 = calculateVariantFingerprint( useFlags = @["python"] ) let fp2 = calculateVariantFingerprint( useFlags = @["ruby"] ) check: fp1 != fp2 test "Fingerprint with sorted USE flags": # Order shouldn't matter let fp1 = calculateVariantFingerprint( useFlags = @["python", "ruby", "lua"] ) let fp2 = calculateVariantFingerprint( useFlags = @["lua", "python", "ruby"] ) check: fp1 == fp2 echo "✅ All remote cache tests completed"