71 lines
2.5 KiB
Nim
71 lines
2.5 KiB
Nim
import std/[unittest, os, posix, strutils]
|
|
import nip/namespace
|
|
import nip/manifest_parser
|
|
|
|
# Import unshare for testing availability
|
|
proc unshare(flags: cint): cint {.importc: "unshare", header: "<sched.h>".}
|
|
const CLONE_NEWUSER = 0x10000000
|
|
|
|
# Note: Testing namespaces usually requires root or unprivileged user namespace support enabled.
|
|
# Most CI/Docker environments might block this.
|
|
# We will check if we can unshare first.
|
|
|
|
proc canUnshare(): bool =
|
|
# Try to unshare user namespace
|
|
if unshare(CLONE_NEWUSER) == 0:
|
|
return true
|
|
return false
|
|
|
|
suite "NIP Namespace Isolation Tests":
|
|
|
|
test "Initialize Launcher":
|
|
let manifest = PackageManifest(name: "test-app", version: parseSemanticVersion("1.0.0"), license: "MIT")
|
|
let launcher = newLauncher(manifest, "/tmp/install", "/tmp/cas")
|
|
check launcher != nil
|
|
check launcher.manifest.name == "test-app"
|
|
|
|
test "Sandbox Execution (Mock/Check)":
|
|
# This test is tricky without actually running it.
|
|
# We verify the logic compiles and basic object creation works.
|
|
# Actual execution requires a binary to run.
|
|
|
|
if not canUnshare():
|
|
echo "User namespaces not supported in this environment - SKIPPING"
|
|
else:
|
|
# If we can unshare, we can try a minimal test
|
|
# But 'run' does execv which replaces the process.
|
|
# We need to fork first in the test.
|
|
|
|
let pid = fork()
|
|
if pid == 0:
|
|
# Child
|
|
try:
|
|
let manifest = PackageManifest(name: "true", version: parseSemanticVersion("1.0.0"), license: "MIT")
|
|
# We point installDir to /bin so it finds 'true' (assuming logic looks in bin/)
|
|
# Wait, the logic looks in installDir/bin/<name>
|
|
# So we need to fake that.
|
|
|
|
createDir("/tmp/nip_test_ns/bin")
|
|
copyFile("/bin/true", "/tmp/nip_test_ns/bin/true")
|
|
|
|
let launcher = newLauncher(manifest, "/tmp/nip_test_ns", "/tmp")
|
|
|
|
# This will replace the process
|
|
launcher.run(@[])
|
|
|
|
# Should not reach here
|
|
quit(1)
|
|
except Exception as e:
|
|
if "Operation not permitted" in e.msg:
|
|
echo "SKIPPING: Unshare not permitted in child (likely CI restriction)"
|
|
quit(0)
|
|
else:
|
|
echo "Child exception: ", e.msg
|
|
quit(1)
|
|
else:
|
|
# Parent
|
|
var status: cint
|
|
discard waitpid(pid, status, 0)
|
|
check WIFEXITED(status)
|
|
check WEXITSTATUS(status) == 0
|