381 lines
12 KiB
Nim
381 lines
12 KiB
Nim
## Tests for platform detection and isolation strategy selection
|
|
##
|
|
## Property-Based Tests:
|
|
## - Property 14: Platform Detection Accuracy
|
|
## - Property 15: Strategy Selection Correctness
|
|
## - Property 16: Mode Selection Logic
|
|
|
|
import std/[unittest, options]
|
|
import ../src/nip/platform
|
|
|
|
suite "Platform Detection":
|
|
|
|
test "detectOSType returns valid OS type":
|
|
## Test that OS type detection returns a valid value
|
|
let osType = detectOSType()
|
|
check osType in [Linux, FreeBSD, OpenBSD, NetBSD, macOS, Embedded]
|
|
|
|
test "getOSTypeString returns non-empty string":
|
|
## Test that OS type string conversion works
|
|
let osType = detectOSType()
|
|
let osStr = getOSTypeString(osType)
|
|
check osStr.len > 0
|
|
|
|
test "getKernelVersion returns non-empty string":
|
|
## Test that kernel version detection works
|
|
let version = getKernelVersion()
|
|
check version.len > 0
|
|
check version != "unknown" or true # May be unknown on some systems
|
|
|
|
test "parseKernelVersion handles valid version strings":
|
|
## Test kernel version parsing
|
|
let (major, minor, patch) = parseKernelVersion("5.10.0")
|
|
check major == 5
|
|
check minor == 10
|
|
check patch == 0
|
|
|
|
test "parseKernelVersion handles version with suffix":
|
|
## Test kernel version parsing with suffix
|
|
let (major, minor, patch) = parseKernelVersion("5.10.0-generic")
|
|
check major == 5
|
|
check minor == 10
|
|
check patch == 0
|
|
|
|
test "parseKernelVersion handles incomplete versions":
|
|
## Test kernel version parsing with incomplete version
|
|
let (major, minor, patch) = parseKernelVersion("5.10")
|
|
check major == 5
|
|
check minor == 10
|
|
check patch == 0
|
|
|
|
test "getMemoryTotal returns positive value":
|
|
## Test that memory detection returns a positive value
|
|
let memory = getMemoryTotal()
|
|
check memory >= 0 # May be 0 on some systems
|
|
|
|
test "getCPUCount returns positive value":
|
|
## Test that CPU count detection returns a positive value
|
|
let cpuCount = getCPUCount()
|
|
check cpuCount > 0
|
|
|
|
test "detectEmbeddedDevice returns boolean":
|
|
## Test that embedded device detection returns a boolean
|
|
let isEmbedded = detectEmbeddedDevice()
|
|
check isEmbedded in [true, false]
|
|
|
|
suite "Platform Capabilities":
|
|
|
|
test "detectPlatform returns valid capabilities":
|
|
## Property 14: Platform Detection Accuracy
|
|
## For any platform, detectPlatform() SHALL return accurate capabilities
|
|
let caps = detectPlatform()
|
|
|
|
# Verify OS type is valid
|
|
check caps.osType in [Linux, FreeBSD, OpenBSD, NetBSD, macOS, Embedded]
|
|
|
|
# Verify kernel version is non-empty
|
|
check caps.kernelVersion.len >= 0
|
|
|
|
# Verify memory and CPU are non-negative
|
|
check caps.memoryTotal >= 0
|
|
check caps.cpuCount > 0
|
|
|
|
test "detectPlatform consistency":
|
|
## Test that multiple calls return consistent results
|
|
let caps1 = detectPlatform()
|
|
let caps2 = detectPlatform()
|
|
|
|
check caps1.osType == caps2.osType
|
|
check caps1.isRoot == caps2.isRoot
|
|
check caps1.isEmbedded == caps2.isEmbedded
|
|
|
|
test "detectPlatform Linux capabilities":
|
|
## Test Linux-specific capability detection
|
|
when defined(linux):
|
|
let caps = detectPlatform()
|
|
check caps.osType == Linux
|
|
check caps.hasJails == false
|
|
check caps.hasUnveil == false
|
|
|
|
test "detectPlatform FreeBSD capabilities":
|
|
## Test FreeBSD-specific capability detection
|
|
when defined(freebsd):
|
|
let caps = detectPlatform()
|
|
check caps.osType == FreeBSD
|
|
check caps.hasUserNamespaces == false
|
|
check caps.hasUnveil == false
|
|
|
|
test "detectPlatform OpenBSD capabilities":
|
|
## Test OpenBSD-specific capability detection
|
|
when defined(openbsd):
|
|
let caps = detectPlatform()
|
|
check caps.osType == OpenBSD
|
|
check caps.hasUserNamespaces == false
|
|
check caps.hasJails == false
|
|
|
|
suite "Isolation Strategy Selection":
|
|
|
|
test "selectStrategy returns valid strategy":
|
|
## Property 15: Strategy Selection Correctness
|
|
## For any platform capabilities, selectStrategy() SHALL return a valid strategy
|
|
let caps = detectPlatform()
|
|
let strategy = selectStrategy(caps)
|
|
|
|
check strategy in [LinuxNamespace, FreeBSDJail, OpenBSDUnveil, POSIXFallback]
|
|
|
|
test "selectStrategy Linux with namespaces":
|
|
## Test strategy selection for Linux with namespace support
|
|
var caps = PlatformCapabilities(
|
|
osType: Linux,
|
|
hasUserNamespaces: true,
|
|
hasJails: false,
|
|
hasUnveil: false,
|
|
isRoot: false,
|
|
kernelVersion: "5.10.0",
|
|
isEmbedded: false,
|
|
memoryTotal: 8 * 1024 * 1024 * 1024,
|
|
cpuCount: 4
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == LinuxNamespace
|
|
|
|
test "selectStrategy Linux without namespaces":
|
|
## Test strategy selection for Linux without namespace support
|
|
var caps = PlatformCapabilities(
|
|
osType: Linux,
|
|
hasUserNamespaces: false,
|
|
hasJails: false,
|
|
hasUnveil: false,
|
|
isRoot: false,
|
|
kernelVersion: "4.4.0",
|
|
isEmbedded: false,
|
|
memoryTotal: 8 * 1024 * 1024 * 1024,
|
|
cpuCount: 4
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == POSIXFallback
|
|
|
|
test "selectStrategy FreeBSD with jails":
|
|
## Test strategy selection for FreeBSD with jail support
|
|
var caps = PlatformCapabilities(
|
|
osType: FreeBSD,
|
|
hasUserNamespaces: false,
|
|
hasJails: true,
|
|
hasUnveil: false,
|
|
isRoot: true,
|
|
kernelVersion: "11.0",
|
|
isEmbedded: false,
|
|
memoryTotal: 8 * 1024 * 1024 * 1024,
|
|
cpuCount: 4
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == FreeBSDJail
|
|
|
|
test "selectStrategy FreeBSD without jails":
|
|
## Test strategy selection for FreeBSD without jail support
|
|
var caps = PlatformCapabilities(
|
|
osType: FreeBSD,
|
|
hasUserNamespaces: false,
|
|
hasJails: false,
|
|
hasUnveil: false,
|
|
isRoot: false,
|
|
kernelVersion: "10.0",
|
|
isEmbedded: false,
|
|
memoryTotal: 8 * 1024 * 1024 * 1024,
|
|
cpuCount: 4
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == POSIXFallback
|
|
|
|
test "selectStrategy OpenBSD with unveil":
|
|
## Test strategy selection for OpenBSD with unveil support
|
|
var caps = PlatformCapabilities(
|
|
osType: OpenBSD,
|
|
hasUserNamespaces: false,
|
|
hasJails: false,
|
|
hasUnveil: true,
|
|
isRoot: true,
|
|
kernelVersion: "6.4",
|
|
isEmbedded: false,
|
|
memoryTotal: 8 * 1024 * 1024 * 1024,
|
|
cpuCount: 4
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == OpenBSDUnveil
|
|
|
|
test "selectStrategy OpenBSD without unveil":
|
|
## Test strategy selection for OpenBSD without unveil support
|
|
var caps = PlatformCapabilities(
|
|
osType: OpenBSD,
|
|
hasUserNamespaces: false,
|
|
hasJails: false,
|
|
hasUnveil: false,
|
|
isRoot: false,
|
|
kernelVersion: "6.3",
|
|
isEmbedded: false,
|
|
memoryTotal: 8 * 1024 * 1024 * 1024,
|
|
cpuCount: 4
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == POSIXFallback
|
|
|
|
test "selectStrategy embedded device":
|
|
## Test strategy selection for embedded device
|
|
var caps = PlatformCapabilities(
|
|
osType: Linux,
|
|
hasUserNamespaces: false,
|
|
hasJails: false,
|
|
hasUnveil: false,
|
|
isRoot: false,
|
|
kernelVersion: "4.14.0",
|
|
isEmbedded: true,
|
|
memoryTotal: 256 * 1024 * 1024,
|
|
cpuCount: 1
|
|
)
|
|
let strategy = selectStrategy(caps)
|
|
check strategy == POSIXFallback
|
|
|
|
suite "Installation Mode Selection":
|
|
|
|
test "selectMode returns valid mode":
|
|
## Property 16: Mode Selection Logic
|
|
## For any strategy, selectMode() SHALL return a valid mode
|
|
let caps = detectPlatform()
|
|
let strategy = selectStrategy(caps)
|
|
let mode = selectMode(strategy, none(InstallMode))
|
|
|
|
check mode in [UserMode, SystemMode]
|
|
|
|
test "selectMode Linux namespace prefers user mode":
|
|
## Test that Linux namespace strategy prefers user mode
|
|
let strategy = LinuxNamespace
|
|
let mode = selectMode(strategy, none(InstallMode))
|
|
check mode == UserMode
|
|
|
|
test "selectMode FreeBSD jail requires system mode":
|
|
## Test that FreeBSD jail strategy requires system mode
|
|
let strategy = FreeBSDJail
|
|
let mode = selectMode(strategy, none(InstallMode))
|
|
check mode == SystemMode
|
|
|
|
test "selectMode OpenBSD unveil requires system mode":
|
|
## Test that OpenBSD unveil strategy requires system mode
|
|
let strategy = OpenBSDUnveil
|
|
let mode = selectMode(strategy, none(InstallMode))
|
|
check mode == SystemMode
|
|
|
|
test "selectMode POSIX fallback as root":
|
|
## Test POSIX fallback mode selection as root
|
|
let strategy = POSIXFallback
|
|
let mode = selectMode(strategy, none(InstallMode))
|
|
# Mode depends on whether running as root
|
|
check mode in [UserMode, SystemMode]
|
|
|
|
test "selectMode respects user request for valid strategy":
|
|
## Test that user request is respected when valid
|
|
let strategy = LinuxNamespace
|
|
let mode = selectMode(strategy, some(UserMode))
|
|
check mode == UserMode
|
|
|
|
test "selectMode falls back on invalid user request":
|
|
## Test that invalid user request falls back gracefully
|
|
let strategy = FreeBSDJail
|
|
let mode = selectMode(strategy, some(UserMode))
|
|
# Should fall back to SystemMode since FreeBSD jail doesn't support user mode
|
|
check mode == SystemMode
|
|
|
|
suite "Strategy Information":
|
|
|
|
test "getStrategyDescription returns non-empty string":
|
|
## Test that strategy descriptions are available
|
|
for strategy in [LinuxNamespace, FreeBSDJail, OpenBSDUnveil, POSIXFallback]:
|
|
let desc = getStrategyDescription(strategy)
|
|
check desc.len > 0
|
|
|
|
test "getSecurityLevel returns valid level":
|
|
## Test that security levels are valid (1-5)
|
|
for strategy in [LinuxNamespace, FreeBSDJail, OpenBSDUnveil, POSIXFallback]:
|
|
let level = getSecurityLevel(strategy)
|
|
check level >= 1 and level <= 5
|
|
|
|
test "getStrategyInfo returns non-empty string":
|
|
## Test that strategy info is available
|
|
for strategy in [LinuxNamespace, FreeBSDJail, OpenBSDUnveil, POSIXFallback]:
|
|
let info = getStrategyInfo(strategy)
|
|
check info.len > 0
|
|
|
|
test "security levels are reasonable":
|
|
## Test that security levels make sense
|
|
check getSecurityLevel(LinuxNamespace) == 5
|
|
check getSecurityLevel(FreeBSDJail) == 5
|
|
check getSecurityLevel(OpenBSDUnveil) == 4
|
|
check getSecurityLevel(POSIXFallback) == 1
|
|
|
|
suite "Embedded Device Constraints":
|
|
|
|
test "getEmbeddedConstraints returns valid constraints":
|
|
## Test that embedded constraints are valid
|
|
let constraints = getEmbeddedConstraints()
|
|
|
|
check constraints.maxConcurrentDownloads > 0
|
|
check constraints.maxConcurrentBuilds > 0
|
|
check constraints.maxCacheSize > 0
|
|
|
|
test "embedded constraints are reasonable":
|
|
## Test that embedded constraints are reasonable
|
|
let constraints = getEmbeddedConstraints()
|
|
|
|
# Downloads should be limited
|
|
check constraints.maxConcurrentDownloads <= 4
|
|
|
|
# Builds should be single-threaded
|
|
check constraints.maxConcurrentBuilds == 1
|
|
|
|
# Cache should be limited
|
|
check constraints.maxCacheSize <= 1024 * 1024 * 1024 # Max 1GB
|
|
|
|
test "embedded constraints enable compression":
|
|
## Test that compression is enabled for embedded
|
|
let constraints = getEmbeddedConstraints()
|
|
check constraints.enableCompression == true
|
|
|
|
test "embedded constraints enable deduplication":
|
|
## Test that deduplication is enabled for embedded
|
|
let constraints = getEmbeddedConstraints()
|
|
check constraints.enableDeduplication == true
|
|
|
|
suite "Byte Formatting":
|
|
|
|
test "formatBytes handles bytes":
|
|
## Test byte formatting for small sizes
|
|
check formatBytes(512) == "512B"
|
|
|
|
test "formatBytes handles kilobytes":
|
|
## Test byte formatting for kilobytes
|
|
check formatBytes(1024) == "1KB"
|
|
check formatBytes(2048) == "2KB"
|
|
|
|
test "formatBytes handles megabytes":
|
|
## Test byte formatting for megabytes
|
|
check formatBytes(1024 * 1024) == "1MB"
|
|
check formatBytes(512 * 1024 * 1024) == "512MB"
|
|
|
|
test "formatBytes handles gigabytes":
|
|
## Test byte formatting for gigabytes
|
|
check formatBytes(1024 * 1024 * 1024) == "1GB"
|
|
check formatBytes(8 * 1024 * 1024 * 1024) == "8GB"
|
|
|
|
suite "Platform Summary":
|
|
|
|
test "printPlatformInfo does not crash":
|
|
## Test that platform info printing works
|
|
let caps = detectPlatform()
|
|
# This should not crash or raise an exception
|
|
printPlatformInfo(caps)
|
|
|
|
test "printEmbeddedConstraints does not crash":
|
|
## Test that embedded constraints printing works
|
|
let constraints = getEmbeddedConstraints()
|
|
# This should not crash or raise an exception
|
|
printEmbeddedConstraints(constraints)
|