feat: add minimal path manipulation C module for internal VM use

Introduce a new `Path` struct and associated functions in `src/cli/path.c` and `src/cli/path.h` for resolving relative imports within the VM. The module provides operations such as normalization, directory extraction, extension removal, joining, and absolute path detection. Additionally, add a lightweight unit test framework under `test/unit/` with a `test.h`/`test.c` harness and `path_test.c` covering normalization cases. Update the build system (`Makefile`, `util/wren.mk`) to separate API tests from unit tests, rename the test executables to `api_wren` and `unit_wren`, and adjust CI targets and Python test scripts accordingly.
This commit is contained in:
Bob Nystrom
2018-03-24 17:52:16 +00:00
parent 761032c0fc
commit c4532102e8
12 changed files with 642 additions and 30 deletions
+9
View File
@@ -0,0 +1,9 @@
#include "path_test.h"
#include "test.h"
int main()
{
testPath();
return showTestResults();
}
+105
View File
@@ -0,0 +1,105 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "path.h"
#include "test.h"
static void expectNormalize(const char* input, const char* expected)
{
Path* path = pathNew(input);
Path* result = pathNormalize(path);
if (strcmp(result->chars, expected) != 0)
{
printf("FAIL %-30s Want %s\n", input, expected);
printf(" Got %s\n\n", result->chars);
fail();
}
else
{
#if SHOW_PASSES
printf("PASS %-30s -> %s\n", input, result->chars);
#endif
pass();
}
pathFree(path);
pathFree(result);
}
static void testNormalize()
{
// simple cases
expectNormalize("", ".");
expectNormalize(".", ".");
expectNormalize("..", "..");
expectNormalize("a", "a");
expectNormalize("/", "/");
// collapses redundant separators
expectNormalize("a/b/c", "a/b/c");
expectNormalize("a//b///c////d", "a/b/c/d");
// eliminates "." parts
expectNormalize("./", ".");
expectNormalize("/.", "/");
expectNormalize("/./", "/");
expectNormalize("./.", ".");
expectNormalize("a/./b", "a/b");
expectNormalize("a/.b/c", "a/.b/c");
expectNormalize("a/././b/./c", "a/b/c");
expectNormalize("././a", "a");
expectNormalize("a/./.", "a");
// eliminates ".." parts
expectNormalize("..", "..");
expectNormalize("../", "..");
expectNormalize("../../..", "../../..");
expectNormalize("../../../", "../../..");
expectNormalize("/..", "/");
expectNormalize("/../../..", "/");
expectNormalize("/../../../a", "/a");
expectNormalize("a/..", ".");
expectNormalize("a/b/..", "a");
expectNormalize("a/../b", "b");
expectNormalize("a/./../b", "b");
expectNormalize("a/b/c/../../d/e/..", "a/d");
expectNormalize("a/b/../../../../c", "../../c");
// does not walk before root on absolute paths
expectNormalize("..", "..");
expectNormalize("../", "..");
expectNormalize("/..", "/");
expectNormalize("a/..", ".");
expectNormalize("../a", "../a");
expectNormalize("/../a", "/a");
expectNormalize("/../a", "/a");
expectNormalize("a/b/..", "a");
expectNormalize("../a/b/..", "../a");
expectNormalize("a/../b", "b");
expectNormalize("a/./../b", "b");
expectNormalize("a/b/c/../../d/e/..", "a/d");
expectNormalize("a/b/../../../../c", "../../c");
expectNormalize("a/b/c/../../..d/./.e/f././", "a/..d/.e/f.");
// removes trailing separators
expectNormalize("./", ".");
expectNormalize(".//", ".");
expectNormalize("a/", "a");
expectNormalize("a/b/", "a/b");
expectNormalize("a/b///", "a/b");
expectNormalize("foo/bar/baz", "foo/bar/baz");
expectNormalize("foo", "foo");
expectNormalize("foo/bar/", "foo/bar");
expectNormalize("./foo/././bar/././", "foo/bar");
}
void testPath()
{
// TODO: Test other functions.
testNormalize();
}
+1
View File
@@ -0,0 +1 @@
void testPath();
+29
View File
@@ -0,0 +1,29 @@
#include <stdio.h>
#include "test.h"
int passes = 0;
int failures = 0;
void pass()
{
passes++;
}
void fail()
{
failures++;
}
int showTestResults()
{
if (failures > 0)
{
printf("%d out of %d tests failed. :(\n", failures, passes + failures);
return 1;
}
printf("All %d tests passed!\n", passes + failures);
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
// Set this to 1 to output passing tests.
#define SHOW_PASSES 0
void pass();
void fail();
int showTestResults();