## 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: " 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