## test_gentoo_adapter.nim ## Unit tests for GentooAdapter import std/[unittest, tables, os, strutils, options] import ../src/nimpak/build/[types, gentoo_adapter] suite "GentooAdapter Tests": test "GentooAdapter initialization": let adapter = newGentooAdapter() check adapter != nil check adapter.name == "gentoo" check adapter.portageDir == "/var/db/repos/gentoo" check adapter.pkgDbDir == "/var/db/pkg" check adapter.packageCount == 20000 test "GentooAdapter availability check": let adapter = newGentooAdapter() let available = adapter.isAvailable() # Should match actual system state check available == fileExists("/usr/bin/emerge") test "Package name validation - valid names": let adapter = newGentooAdapter() let validNames = @[ "firefox", "app-editors/vim", "sys-apps/portage", "my-package", "package_name", "Package123" ] for name in validNames: let request = BuildRequest( packageName: name, version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir(), verbose: false ) # Should not raise ValidationError during name validation let result = adapter.buildPackage(request) # May fail for other reasons, but not validation if not result.success and result.errors.len > 0: check "Invalid package name" notin result.errors[0] test "Package name validation - invalid names": let adapter = newGentooAdapter() let invalidNames = @[ "", "../etc/passwd", "//absolute/path", "package;rm -rf /", "package`whoami`", "package$(whoami)", "a" & "b".repeat(300) # Too long ] for name in invalidNames: let request = BuildRequest( packageName: name, version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir(), verbose: false ) let result = adapter.buildPackage(request) check result.success == false check result.errors.len > 0 test "package.use generation - no flags": let adapter = newGentooAdapter() let request = BuildRequest( packageName: "test-package", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) # This will generate the package.use file discard adapter.buildPackage(request) # Check that package.use file was created let useFile = getTempDir() / "nip-test-cache" / "gentoo" / "package.use.test-package" if fileExists(useFile): let content = readFile(useFile) check "# Generated by NIP" in content test "package.use generation - with USE flags": let adapter = newGentooAdapter() let request = BuildRequest( packageName: "firefox", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @["wayland", "pulseaudio", "-gtk"], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) discard adapter.buildPackage(request) let useFile = getTempDir() / "nip-test-cache" / "gentoo" / "package.use.firefox" if fileExists(useFile): let content = readFile(useFile) check "# Generated by NIP" in content check "wayland" in content check "pulseaudio" in content check "-gtk" in content test "USE flag validation - valid flags": let adapter = newGentooAdapter() let validFlags = @[ "wayland", "pulseaudio", "-gtk", "+qt5", "enable-feature", "with_option", "flag123" ] let request = BuildRequest( packageName: "test", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: validFlags, cacheDir: getTempDir() / "nip-test-cache", verbose: false ) # Should not raise ValidationError let result = adapter.buildPackage(request) # May fail at build stage, but not at validation if not result.success and result.errors.len > 0: check "Invalid USE flag" notin result.errors[0] test "USE flag validation - invalid flags": let adapter = newGentooAdapter() # Test with malicious USE flag let request = BuildRequest( packageName: "test", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @["bad;flag"], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) let result = adapter.buildPackage(request) check result.success == false test "Build result structure": let adapter = newGentooAdapter() let request = BuildRequest( packageName: "test-package", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) let result = adapter.buildPackage(request) # Check result structure check result.source == "gentoo" check result.packageName == "test-package" # success may be false if package not found, which is expected test "Cache directory creation": let cacheDir = getTempDir() / "nip-test-cache-gentoo" # Remove if exists if dirExists(cacheDir): removeDir(cacheDir) let adapter = newGentooAdapter() let request = BuildRequest( packageName: "test", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @["flag1", "flag2"], # Add flags to trigger package.use generation cacheDir: cacheDir, verbose: false ) discard adapter.buildPackage(request) # Check that cache directory was created (even if build fails) check dirExists(cacheDir / "gentoo") or not fileExists("/usr/bin/emerge") test "Variant flags in build result": let adapter = newGentooAdapter() var variantFlags = initTable[string, seq[string]]() variantFlags["graphics"] = @["wayland", "vulkan"] variantFlags["audio"] = @["pipewire"] let request = BuildRequest( packageName: "test", version: "", variantFlags: variantFlags, sourceFlags: @[], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) let result = adapter.buildPackage(request) # Variant flags should be preserved in result check result.variantDomains.hasKey("graphics") check result.variantDomains.hasKey("audio") test "Error handling - package not found": let adapter = newGentooAdapter() # Use a package name that will definitely not be found let request = BuildRequest( packageName: "this-package-definitely-does-not-exist-12345", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) let result = adapter.buildPackage(request) # Should fail gracefully check result.success == false check result.errors.len > 0 test "Verbose mode": let adapter = newGentooAdapter() let request = BuildRequest( packageName: "test", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir() / "nip-test-cache", verbose: true ) # Should not crash with verbose mode discard adapter.buildPackage(request) test "Root privilege warning": let adapter = newGentooAdapter() let request = BuildRequest( packageName: "test", version: "", variantFlags: initTable[string, seq[string]](), sourceFlags: @[], cacheDir: getTempDir() / "nip-test-cache", verbose: false ) let result = adapter.buildPackage(request) # Should include warning about root privileges if result.warnings.len > 0: var hasRootWarning = false for warning in result.warnings: if "root" in warning.toLower(): hasRootWarning = true break # Warning may or may not be present depending on package found status discard hasRootWarning # Only run search tests if Gentoo is actually available if fileExists("/usr/bin/emerge"): suite "GentooAdapter Search Tests (Gentoo Available)": test "Search for package": let adapter = newGentooAdapter() # Try to search for a common package # Note: This test is system-dependent let result = adapter.searchPackage("bash") # May or may not find it depending on Portage availability if result.isSome: let info = result.get() check info.source == "gentoo" check info.available == true test "Search for non-existent package": let adapter = newGentooAdapter() let result = adapter.searchPackage("this-package-does-not-exist-xyz123") # Should return none check result.isNone test "Search with invalid package name": let adapter = newGentooAdapter() let result = adapter.searchPackage("../etc/passwd") # Should return none due to validation check result.isNone