143 lines
4.7 KiB
Nim
143 lines
4.7 KiB
Nim
## Test suite for comprehensive error handling
|
|
## Task 37: Implement comprehensive error handling
|
|
|
|
import unittest, strutils, sequtils
|
|
import ../src/nimpak/errors
|
|
import ../src/nip/types
|
|
|
|
suite "Comprehensive Error Handling Tests":
|
|
|
|
test "Error formatting":
|
|
let err = packageNotFoundError("nginx")
|
|
let formatted = formatError(err)
|
|
|
|
check formatted.contains("PackageNotFound")
|
|
check formatted.contains("nginx")
|
|
check formatted.contains("Suggestions")
|
|
check formatted.contains("typos")
|
|
|
|
test "Checksum mismatch error":
|
|
let err = checksumMismatchError(
|
|
"/var/cache/nip/pkg.tar",
|
|
"abc123def456",
|
|
"xyz789ghi012"
|
|
)
|
|
|
|
check err.code == ChecksumMismatch
|
|
check err.msg.contains("Checksum verification failed")
|
|
check err.context.contains("abc123")
|
|
check err.suggestions.len > 0
|
|
|
|
test "Permission denied error":
|
|
let err = permissionDeniedError("/usr/lib/nip", "write")
|
|
|
|
check err.code == PermissionDenied
|
|
check err.msg.contains("write")
|
|
check err.suggestions.len >= 2
|
|
|
|
test "Network error handling":
|
|
let err = networkError("https://repo.nexusos.io/index", "Connection refused")
|
|
|
|
check err.code == NetworkError
|
|
check err.context.contains("Connection refused")
|
|
|
|
test "Download failed with HTTP code":
|
|
let err = downloadFailedError("https://repo.nexusos.io/pkg.tar", 404)
|
|
|
|
check err.code == DownloadFailed
|
|
check err.context.contains("404")
|
|
|
|
test "Elevation required error":
|
|
let err = elevationRequiredError("system package installation")
|
|
|
|
check err.code == ElevationRequired
|
|
check err.msg.contains("Elevated privileges")
|
|
check err.suggestions.anyIt(it.contains("sudo"))
|
|
|
|
test "Signature invalid error":
|
|
let err = signatureInvalidError("compromised-pkg", "0xDEADBEEF")
|
|
|
|
check err.code == SignatureInvalid
|
|
check err.context.contains("0xDEADBEEF")
|
|
|
|
test "GC failed error":
|
|
let err = gcFailedError("Objects in use")
|
|
|
|
check err.code == GarbageCollectionFailed
|
|
check err.suggestions.anyIt(it.contains("gc"))
|
|
|
|
test "Reference integrity error":
|
|
let err = referenceIntegrityError("xxh3-abc123def456", 5, 3)
|
|
|
|
check err.code == ReferenceIntegrityError
|
|
check err.context.contains("Expected: 5")
|
|
check err.context.contains("Actual: 3")
|
|
|
|
test "Transaction failed error":
|
|
let err = transactionFailedError("tx-12345", "file_copy")
|
|
|
|
check err.code == TransactionFailed
|
|
check err.msg.contains("tx-12345")
|
|
|
|
test "Error recoverability check":
|
|
let networkErr = networkError("http://example.com", "timeout")
|
|
let sigErr = signatureInvalidError("bad-pkg")
|
|
|
|
check isRecoverable(networkErr)
|
|
check not isRecoverable(sigErr)
|
|
|
|
test "Recovery strategy suggestion":
|
|
let networkErr = networkError("http://example.com", "timeout")
|
|
let permErr = permissionDeniedError("/root", "read")
|
|
let sigErr = signatureInvalidError("bad-pkg")
|
|
|
|
check suggestRecovery(networkErr) == Retry
|
|
check suggestRecovery(permErr) == Manual
|
|
check suggestRecovery(sigErr) == Abort
|
|
|
|
test "Error wrapping":
|
|
let originalErr = networkError("http://repo.io", "DNS failure")
|
|
let wrappedErr = wrapError(originalErr, DownloadFailed, "Package download failed")
|
|
|
|
check wrappedErr.code == DownloadFailed
|
|
# wrapError puts "Caused by: <original msg>" in context
|
|
check wrappedErr.context.contains("Caused by")
|
|
check wrappedErr.context.contains("http://repo.io")
|
|
|
|
test "Error chaining":
|
|
let err1 = networkError("http://repo.io", "timeout")
|
|
let err2 = downloadFailedError("http://repo.io/pkg.tar")
|
|
let err3 = packageNotFoundError("nginx")
|
|
|
|
let chainedMsg = chain(err1, err2, err3)
|
|
|
|
check chainedMsg.contains("Error chain")
|
|
check chainedMsg.contains("NetworkError")
|
|
check chainedMsg.contains("DownloadFailed")
|
|
check chainedMsg.contains("PackageNotFound")
|
|
|
|
test "All error codes have factory functions coverage":
|
|
# Verify key error codes have dedicated factory functions
|
|
let errors = @[
|
|
packageNotFoundError("test"),
|
|
checksumMismatchError("file", "a", "b"),
|
|
permissionDeniedError("/path", "op"),
|
|
elevationRequiredError("op"),
|
|
networkError("url", "detail"),
|
|
downloadFailedError("url"),
|
|
repositoryUnavailableError("repo"),
|
|
timeoutError("op", 30),
|
|
buildFailedError("pkg", "stage"),
|
|
missingDependencyError("pkg", "dep"),
|
|
signatureInvalidError("pkg"),
|
|
objectNotFoundError("hash"),
|
|
gcFailedError("reason"),
|
|
transactionFailedError("tx", "op"),
|
|
rollbackFailedError("tx", "reason")
|
|
]
|
|
|
|
check errors.len >= 15
|
|
for err in errors:
|
|
check err.msg.len > 0
|
|
check err.suggestions.len > 0
|