264 lines
7.6 KiB
Nim
264 lines
7.6 KiB
Nim
## tests/test_build_system.nim
|
|
## Unit tests for the Nimplate build system
|
|
##
|
|
## Tests type-safe build templates, build execution, caching,
|
|
## and environment isolation for all supported build systems.
|
|
|
|
import std/[unittest, os, times, strutils]
|
|
import ../src/nimpak/build_system
|
|
import ../src/nimpak/recipes
|
|
|
|
suite "Nimplate Build System Tests":
|
|
|
|
setup:
|
|
# Create temporary test directory
|
|
let testDir = getTempDir() / "nip_test_build"
|
|
createDir(testDir)
|
|
|
|
teardown:
|
|
# Clean up test directory
|
|
let testDir = getTempDir() / "nip_test_build"
|
|
if dirExists(testDir):
|
|
removeDir(testDir)
|
|
|
|
test "Build environment creation":
|
|
let sourceDir = getTempDir() / "test_source"
|
|
createDir(sourceDir)
|
|
|
|
let env = newBuildEnvironment(sourceDir, isolated = true)
|
|
|
|
check env.sourceDir == sourceDir
|
|
check env.isolated == true
|
|
check env.environment.hasKey("PREFIX")
|
|
check env.environment.hasKey("MAKEFLAGS")
|
|
check env.workDir.contains("nimpak_build_")
|
|
|
|
test "Nimplate executor creation":
|
|
let sourceDir = getTempDir() / "test_source"
|
|
createDir(sourceDir)
|
|
|
|
let buildTmpl = getBuildSystemDefaults(CMake)
|
|
let executor = newNimplateExecutor(buildTmpl, sourceDir)
|
|
|
|
check executor.buildTemplate.system == CMake
|
|
check executor.cacheEnabled == true
|
|
check executor.sandboxed == true
|
|
check executor.environment.sourceDir == sourceDir
|
|
|
|
test "CMake build template defaults":
|
|
let buildTmpl = getBuildSystemDefaults(CMake)
|
|
|
|
check buildTmpl.system == CMake
|
|
check "-DCMAKE_BUILD_TYPE=Release" in buildTmpl.configureArgs
|
|
check "--parallel" in buildTmpl.buildArgs
|
|
|
|
test "Autotools build template defaults":
|
|
let buildTmpl = getBuildSystemDefaults(Autotools)
|
|
|
|
check buildTmpl.system == Autotools
|
|
check "--prefix=/usr" in buildTmpl.configureArgs
|
|
check "-j" in buildTmpl.buildArgs[0] # Should contain -j for parallel make
|
|
|
|
test "Meson build template defaults":
|
|
let buildTmpl = getBuildSystemDefaults(Meson)
|
|
|
|
check buildTmpl.system == Meson
|
|
check "setup" in buildTmpl.configureArgs
|
|
check "--buildtype=release" in buildTmpl.configureArgs
|
|
|
|
test "Cargo build template defaults":
|
|
let buildTmpl = getBuildSystemDefaults(Cargo)
|
|
|
|
check buildTmpl.system == Cargo
|
|
check "--release" in buildTmpl.buildArgs
|
|
|
|
test "Nim build template defaults":
|
|
let buildTmpl = getBuildSystemDefaults(NimBuild)
|
|
|
|
check buildTmpl.system == NimBuild
|
|
check "-d:release" in buildTmpl.buildArgs
|
|
|
|
test "Build hash calculation":
|
|
let sourceDir = getTempDir() / "test_source"
|
|
createDir(sourceDir)
|
|
|
|
let buildTmpl = getBuildSystemDefaults(CMake)
|
|
let hash1 = calculateBuildHash(sourceDir, buildTmpl)
|
|
let hash2 = calculateBuildHash(sourceDir, buildTmpl)
|
|
|
|
check hash1 == hash2 # Same source and template should produce same hash
|
|
check hash1.startsWith("build-")
|
|
|
|
test "Build cache detection":
|
|
let cacheDir = getTempDir() / "build_cache"
|
|
createDir(cacheDir)
|
|
|
|
let buildHash = "test-build-hash"
|
|
|
|
# Initially not cached
|
|
check isBuildCached(buildHash, cacheDir) == false
|
|
|
|
# Create cache file
|
|
let cacheFile = cacheDir / buildHash & ".cache"
|
|
writeFile(cacheFile, "cached build result")
|
|
|
|
# Now should be cached
|
|
check isBuildCached(buildHash, cacheDir) == true
|
|
|
|
test "Build environment isolation setup":
|
|
let sourceDir = getTempDir() / "test_source"
|
|
var env = newBuildEnvironment(sourceDir, isolated = true)
|
|
|
|
setupSandbox(env)
|
|
|
|
check env.environment.hasKey("SANDBOX")
|
|
check env.environment["SANDBOX"] == "true"
|
|
check env.environment.hasKey("HOME")
|
|
check env.environment.hasKey("TMPDIR")
|
|
|
|
suite "Nimplate Build Execution Tests":
|
|
|
|
test "Mock CMake build execution":
|
|
# Create a mock CMake project
|
|
let sourceDir = getTempDir() / "cmake_project"
|
|
createDir(sourceDir)
|
|
|
|
# Create a minimal CMakeLists.txt
|
|
writeFile(sourceDir / "CMakeLists.txt", """
|
|
cmake_minimum_required(VERSION 3.10)
|
|
project(TestProject)
|
|
add_executable(test main.cpp)
|
|
""")
|
|
|
|
# Create a minimal main.cpp
|
|
writeFile(sourceDir / "main.cpp", """
|
|
#include <iostream>
|
|
int main() { std::cout << "Hello World!" << std::endl; return 0; }
|
|
""")
|
|
|
|
let buildTmpl = getBuildSystemDefaults(CMake)
|
|
let executor = newNimplateExecutor(buildTmpl, sourceDir)
|
|
|
|
# This will fail in CI without CMake, but we can test the setup
|
|
check executor.buildTemplate.system == CMake
|
|
check executor.environment.sourceDir == sourceDir
|
|
|
|
test "Mock Nim build execution":
|
|
# Create a mock Nim project
|
|
let sourceDir = getTempDir() / "nim_project"
|
|
createDir(sourceDir)
|
|
|
|
# Create a minimal nim file
|
|
writeFile(sourceDir / "main.nim", """
|
|
echo "Hello from Nim!"
|
|
""")
|
|
|
|
let buildTmpl = getBuildSystemDefaults(NimBuild)
|
|
let executor = newNimplateExecutor(buildTmpl, sourceDir)
|
|
|
|
check executor.buildTemplate.system == NimBuild
|
|
check executor.environment.sourceDir == sourceDir
|
|
|
|
test "Build result structure":
|
|
# Test BuildResult type
|
|
var result = BuildResult(
|
|
success: true,
|
|
buildTime: 1.5,
|
|
outputSize: 1024,
|
|
buildLog: "Build completed successfully",
|
|
artifacts: @["/path/to/binary"],
|
|
phase: PhaseInstall,
|
|
exitCode: 0
|
|
)
|
|
|
|
check result.success == true
|
|
check result.buildTime == 1.5
|
|
check result.outputSize == 1024
|
|
check result.phase == PhaseInstall
|
|
check result.artifacts.len == 1
|
|
|
|
suite "Build System Integration Tests":
|
|
|
|
test "Build template validation":
|
|
let buildTmpl = getBuildSystemDefaults(CMake)
|
|
let warnings = validateBuildInstructions(buildTmpl)
|
|
|
|
# CMake template should be valid
|
|
check warnings.len == 0
|
|
|
|
test "Custom build template creation":
|
|
let customTmpl = createBuildTemplate(
|
|
system = Custom,
|
|
configureArgs = @["./configure", "--enable-feature"],
|
|
buildArgs = @["make", "-j4"],
|
|
installArgs = @["make", "install"]
|
|
)
|
|
|
|
check customTmpl.system == Custom
|
|
check customTmpl.configureArgs.len == 2
|
|
check customTmpl.buildArgs.len == 2
|
|
check customTmpl.installArgs.len == 2
|
|
|
|
test "Build environment cleanup":
|
|
let sourceDir = getTempDir() / "test_source"
|
|
createDir(sourceDir)
|
|
|
|
let env = newBuildEnvironment(sourceDir, isolated = true)
|
|
let workDir = env.workDir
|
|
|
|
# Work directory should exist
|
|
check dirExists(workDir)
|
|
|
|
# Clean up
|
|
cleanupBuildEnvironment(env)
|
|
|
|
# Work directory should be removed (if isolated)
|
|
# Note: This might not work in all test environments
|
|
# check not dirExists(workDir)
|
|
|
|
test "Build cache save and load":
|
|
let cacheDir = getTempDir() / "build_cache_test"
|
|
let buildHash = "test-hash-123"
|
|
|
|
let result = BuildResult(
|
|
success: true,
|
|
buildTime: 2.0,
|
|
buildLog: "Test build log",
|
|
phase: PhaseInstall
|
|
)
|
|
|
|
# Save to cache
|
|
saveBuildCache(result, buildHash, cacheDir)
|
|
|
|
# Check cache exists
|
|
check isBuildCached(buildHash, cacheDir) == true
|
|
|
|
suite "Build System Error Handling":
|
|
|
|
test "Invalid source directory handling":
|
|
let invalidDir = "/nonexistent/directory"
|
|
let buildTmpl = getBuildSystemDefaults(CMake)
|
|
|
|
# Should handle gracefully
|
|
let executor = newNimplateExecutor(buildTmpl, invalidDir)
|
|
check executor.environment.sourceDir == invalidDir
|
|
|
|
test "Build failure handling":
|
|
# Test that build failures are properly captured
|
|
var result = BuildResult(
|
|
success: false,
|
|
exitCode: 1,
|
|
buildLog: "Build failed with error",
|
|
phase: PhaseBuild
|
|
)
|
|
|
|
check result.success == false
|
|
check result.exitCode == 1
|
|
check "failed" in result.buildLog
|
|
|
|
when isMainModule:
|
|
echo "🧪 Running Build System Tests..."
|
|
echo "Testing Nimplate build templates and execution..."
|
|
|
|
# This will run all the test suites
|
|
discard |