feat: bux test command + Std::Test module

- Add 'bux test' CLI command: discovers .bux files in tests/, compiles
  each into a temp package, runs them, reports pass/fail
- Add Std::Test module with Assert, AssertEqInt, AssertTrue,
  AssertFalse, Fail
- Add bux_exit and bux_assert C runtime primitives
- Update README.md and docs/BuildAndTest.md
This commit is contained in:
2026-06-05 22:58:02 +03:00
parent 2a19734c72
commit f02b354e9a
5 changed files with 104 additions and 1 deletions
+1 -1
View File
@@ -198,7 +198,7 @@ func Main() -> int {
| **CTFE** | `const func` — compile-time function execution |
| **Trait Bounds** | `func Max<T: Comparable>(a: T, b: T) -> T` |
| **Package Manager** | `bux add`, `bux install`, `bux.lock`, path + git deps |
| **Tooling** | `bux new`, `bux build`, `bux run`, `bux check` |
| **Tooling** | `bux new`, `bux build`, `bux run`, `bux test`, `bux check` |
---
+42
View File
@@ -24,6 +24,7 @@ Commands:
install Resolve and install dependencies
build Build the current package
run Build and run the current package
test Run tests in tests/ directory
check Type-check the current package
clean Remove build artifacts
help Show this help message
@@ -574,6 +575,46 @@ proc cmdClean*(args: seq[string], opts: GlobalOptions): int =
printInfo("clean: build directory removed", useColor)
return 0
proc cmdTest*(args: seq[string], opts: GlobalOptions): int =
let useColor = shouldUseColor(opts)
let root = getCurrentDir()
let testsDir = root / "tests"
var testFiles: seq[string] = @[]
if dirExists(testsDir):
for kind, path in walkDir(testsDir):
if kind == pcFile and path.endsWith(".bux"):
testFiles.add(path)
if testFiles.len == 0:
printError("no tests found in tests/ directory", useColor)
return 1
var passed = 0
var failed = 0
for testFile in testFiles:
let testName = splitFile(testFile).name
let tmpDir = getTempDir() / "bux_test_" & testName
removeDir(tmpDir)
createDir(tmpDir / "src")
copyFile(testFile, tmpDir / "src" / "Main.bux")
writeFile(tmpDir / "bux.toml", "[package]\nname = \"" & testName & "\"\nversion = \"0.1.0\"\n")
let buildRes = cmdBuild(@[tmpDir], opts)
if buildRes != 0:
printError(&" FAIL {testName} (build)", useColor)
failed += 1
continue
var execFile = tmpDir / "build" / testName
if not fileExists(execFile):
execFile = tmpDir / "build" / "bux_out"
let exitCode = execCmd(execFile)
if exitCode == 0:
printInfo(&" PASS {testName}", useColor)
passed += 1
else:
printError(&" FAIL {testName} (exit {exitCode})", useColor)
failed += 1
removeDir(tmpDir)
echo &"\nResults: {passed} passed, {failed} failed"
return if failed > 0: 1 else: 0
proc cmdVersion*(args: seq[string], opts: GlobalOptions): int =
echo "bux 0.1.0 (bootstrap)"
return 0
@@ -597,6 +638,7 @@ proc runCli*(args: seq[string]): int =
of "build": return cmdBuild(cmdArgs, opts)
of "run": return cmdRun(cmdArgs, opts)
of "check": return cmdCheck(cmdArgs, opts)
of "test": return cmdTest(cmdArgs, opts)
of "clean": return cmdClean(cmdArgs, opts)
of "version", "--version", "-v": return cmdVersion(cmdArgs, opts)
of "help", "--help", "-h":
+3
View File
@@ -89,6 +89,9 @@ Output = "Bin"
./buxc run
./buxc run ./myproject
# Run tests
./buxc test
# Clean build artifacts
./buxc clean
```
+14
View File
@@ -1324,6 +1324,20 @@ const char* bux_socket_error(void) {
return strerror(errno);
}
/* ============================================================================
* Test / Assert primitives
* ============================================================================ */
void bux_exit(int code) {
exit(code);
}
void bux_assert(int cond, const char* file, int line, const char* expr) {
if (!cond) {
fprintf(stderr, "ASSERT FAILED: %s at %s:%d\n", expr, file, line);
exit(1);
}
}
/* ============================================================================
* Cryptography primitives (OpenSSL)
+44
View File
@@ -0,0 +1,44 @@
module Std::Test {
extern func bux_exit(code: int);
extern func bux_assert(cond: int, file: String, line: int, expr: String);
func Test_Exit(code: int) {
bux_exit(code);
}
func Test_Assert(cond: bool) {
bux_assert(cond as int, "", 0, "");
}
func Test_AssertEqInt(a: int, b: int) {
if a != b {
PrintLine("ASSERT_EQ FAILED:");
PrintInt(a);
PrintLine(" != ");
PrintInt(b);
bux_exit(1);
}
}
func Test_AssertTrue(cond: bool) {
if !cond {
PrintLine("ASSERT_TRUE FAILED");
bux_exit(1);
}
}
func Test_AssertFalse(cond: bool) {
if cond {
PrintLine("ASSERT_FALSE FAILED");
bux_exit(1);
}
}
func Test_Fail(msg: String) {
PrintLine("FAIL:");
PrintLine(msg);
bux_exit(1);
}
}