summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/features/_opaque_alias_lib.zc13
-rw-r--r--tests/features/_opaque_lib.zc15
-rw-r--r--tests/features/test_build_directives.zc21
-rw-r--r--tests/features/test_implicit_fstring.zc19
-rw-r--r--tests/features/test_opaque.zc18
-rw-r--r--tests/features/test_opaque_alias.zc13
-rw-r--r--tests/features/test_traits_suite.zc2
-rw-r--r--tests/memory/test_memory_safety.zc9
-rw-r--r--tests/memory/test_unsafe.zc15
-rwxr-xr-xtests/run_example_transpile.sh39
-rw-r--r--tests/std/test_direct_array_iteration.zc37
-rw-r--r--tests/std/test_env.zc2
-rw-r--r--tests/std/test_json_serialization.zc149
-rw-r--r--tests/std/test_process.zc26
-rw-r--r--tests/std/test_slice_iteration.zc29
15 files changed, 386 insertions, 21 deletions
diff --git a/tests/features/_opaque_alias_lib.zc b/tests/features/_opaque_alias_lib.zc
new file mode 100644
index 0000000..7ca4abc
--- /dev/null
+++ b/tests/features/_opaque_alias_lib.zc
@@ -0,0 +1,13 @@
+opaque alias Handle = int;
+
+fn new_handle(v: int) -> Handle {
+ return v; // Implicit cast int -> Handle (OK in module)
+}
+
+fn get_val(h: Handle) -> int {
+ return h; // Implicit cast Handle -> int (OK in module)
+}
+
+fn compare_handles(a: Handle, b: Handle) -> bool {
+ return a == b; // Strict equality (OK)
+}
diff --git a/tests/features/_opaque_lib.zc b/tests/features/_opaque_lib.zc
new file mode 100644
index 0000000..de4d4c4
--- /dev/null
+++ b/tests/features/_opaque_lib.zc
@@ -0,0 +1,15 @@
+opaque struct SecretBox {
+ value: int;
+}
+
+fn new_box(v: int) -> SecretBox {
+ return SecretBox { value: v };
+}
+
+fn get_value(b: SecretBox*) -> int {
+ return b.value;
+}
+
+fn set_value(b: SecretBox*, v: int) {
+ b.value = v;
+}
diff --git a/tests/features/test_build_directives.zc b/tests/features/test_build_directives.zc
index 7edd317..d3f1cba 100644
--- a/tests/features/test_build_directives.zc
+++ b/tests/features/test_build_directives.zc
@@ -1,19 +1,8 @@
-//> link: -lm
-//> cflags: -O2
-// Declare C math function (since we don't have a math stdlib module yet)
-extern fn sin(x: double) -> double;
+//> shell: echo "Env Worked" > ${PWD}/build_dir_env.txt
+//> linux: shell: echo "Linux Worked" > ${PWD}/build_dir_linux.txt
+//> windows: shell: echo "Windows Worked" > ${PWD}/build_dir_windows.txt
-test "test_build_directives" {
- println "Running Build Directives Test...";
- let x = 3.14159 / 2.0; // PI/2
- let s = sin(x);
- // sin(PI/2) should be 1.0
- println "sin(PI/2) = {s}";
-
- if (s > 0.99 && s < 1.01) {
- println "Math Link Success!";
- } else {
- println "Math Link Failure (Value wrong)";
- }
+fn main() {
+ return 0;
}
diff --git a/tests/features/test_implicit_fstring.zc b/tests/features/test_implicit_fstring.zc
new file mode 100644
index 0000000..85a6c86
--- /dev/null
+++ b/tests/features/test_implicit_fstring.zc
@@ -0,0 +1,19 @@
+
+test "implicit_fstring_interpolation" {
+ let result = 123;
+ let s = "{result}";
+ // Should be "123"
+ assert(strcmp(s, "123") == 0, "Implicit f-string failed");
+}
+
+test "implicit_fstring_complex" {
+ let a = 10;
+ let b = 20;
+ let s = "Sum: {a + b}";
+ assert(strcmp(s, "Sum: 30") == 0, "Complex implicit f-string failed");
+}
+
+test "no_interpolation" {
+ let s = "Hello World";
+ assert(strcmp(s, "Hello World") == 0, "Plain string failed");
+}
diff --git a/tests/features/test_opaque.zc b/tests/features/test_opaque.zc
new file mode 100644
index 0000000..5c84b2a
--- /dev/null
+++ b/tests/features/test_opaque.zc
@@ -0,0 +1,18 @@
+import "_opaque_lib.zc";
+
+fn main() {
+ let b = new_box(42);
+
+ // Stack allocation should work (size known)
+ let b2: SecretBox;
+ b2 = b;
+
+ // Public methods should work
+ let v = get_value(&b2);
+ assert(v == 42, "Value should be 42");
+
+ set_value(&b2, 100);
+ assert(get_value(&b2) == 100, "Value should be 100");
+
+ println "Opaque struct test passed";
+}
diff --git a/tests/features/test_opaque_alias.zc b/tests/features/test_opaque_alias.zc
new file mode 100644
index 0000000..062fa1f
--- /dev/null
+++ b/tests/features/test_opaque_alias.zc
@@ -0,0 +1,13 @@
+import "_opaque_alias_lib.zc";
+
+fn main() {
+ let h = new_handle(42);
+ let v = get_val(h);
+
+ assert(v == 42, "Opaque Alias FAIL");
+
+ let h2 = new_handle(42);
+ assert(compare_handles(h, h2), "Equality FAIL");
+
+ println "Opaque Alias OK";
+}
diff --git a/tests/features/test_traits_suite.zc b/tests/features/test_traits_suite.zc
index 205bdf6..2ff8378 100644
--- a/tests/features/test_traits_suite.zc
+++ b/tests/features/test_traits_suite.zc
@@ -90,7 +90,7 @@ test "test_derive" {
// Debug
let s = p1.to_string();
- assert(strcmp(s, "Point { ... }") == 0, "Debug string matches");
+ assert(strcmp(s, "Point {{ ... }}") == 0, "Debug string matches");
// Clone
let p2 = p1.clone();
diff --git a/tests/memory/test_memory_safety.zc b/tests/memory/test_memory_safety.zc
index a5cc960..b672cc9 100644
--- a/tests/memory/test_memory_safety.zc
+++ b/tests/memory/test_memory_safety.zc
@@ -1,5 +1,6 @@
import "std/mem.zc"
+import "std/slice.zc"
// ** Globals **
let DROP_COUNT = 0;
@@ -127,11 +128,13 @@ test "test_slice" {
let data: int[5] = [1, 2, 3, 4, 5];
let s = Slice<int>::new(&data[0], 5);
f" Slice len: {(int)s.len}";
- let v2 = s.get(2);
+ let opt_v2 = s.get(2);
+ let v2 = opt_v2.unwrap();
f" Slice[2]: {v2}";
assert(v2 == 3, "Slice get failed");
- s.set(0, 99);
- let v0 = s.get(0);
+ s.data[0] = 99;
+ let opt_v0 = s.get(0);
+ let v0 = opt_v0.unwrap();
f" After set: Slice[0] = {v0}";
assert(v0 == 99, "Slice set failed");
" ✓ Slice works!";
diff --git a/tests/memory/test_unsafe.zc b/tests/memory/test_unsafe.zc
index fe1150f..6114d6c 100644
--- a/tests/memory/test_unsafe.zc
+++ b/tests/memory/test_unsafe.zc
@@ -54,3 +54,18 @@ test "test_static_local" {
assert b == 2;
assert c == 3;
}
+
+struct CastFoo {
+ val: int;
+}
+
+fn test_cast_precedence_helper(ptr: void*) -> int {
+ return ((CastFoo*)ptr)->val;
+}
+
+test "test_cast_precedence" {
+ let f = CastFoo{val: 42};
+ let ptr = (void*)&f;
+ let val = test_cast_precedence_helper(ptr);
+ assert(val == 42, "Cast precedence failed");
+}
diff --git a/tests/run_example_transpile.sh b/tests/run_example_transpile.sh
new file mode 100755
index 0000000..c08a3ea
--- /dev/null
+++ b/tests/run_example_transpile.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+ZC="./zc"
+EXAMPLES_DIR="examples"
+FAIL_COUNT=0
+PASS_COUNT=0
+
+echo "Running Example Transpilation Tests..."
+
+while IFS= read -r file; do
+ echo -n "Transpiling $file... "
+
+ OUTPUT=$($ZC transpile "$file" 2>&1)
+ EXIT_CODE=$?
+
+ if [ $EXIT_CODE -eq 0 ]; then
+ echo "PASS"
+ PASS_COUNT=$((PASS_COUNT + 1))
+ [ -f "out.c" ] && rm "out.c"
+ [ -f "a.out" ] && rm "a.out"
+ else
+ echo "FAIL"
+ echo "$OUTPUT"
+ FAIL_COUNT=$((FAIL_COUNT + 1))
+ fi
+
+done < <(find "$EXAMPLES_DIR" -name "*.zc")
+
+echo "----------------------------------------"
+echo "Summary:"
+echo "-> Passed: $PASS_COUNT"
+echo "-> Failed: $FAIL_COUNT"
+echo "----------------------------------------"
+
+if [ $FAIL_COUNT -ne 0 ]; then
+ exit 1
+fi
+
+exit 0
diff --git a/tests/std/test_direct_array_iteration.zc b/tests/std/test_direct_array_iteration.zc
new file mode 100644
index 0000000..359951f
--- /dev/null
+++ b/tests/std/test_direct_array_iteration.zc
@@ -0,0 +1,37 @@
+import "std/slice.zc"
+
+test "direct array iteration" {
+ let arr: int[5] = [1, 2, 3, 4, 5];
+
+ let sum = 0;
+ for val in arr {
+ sum = sum + val;
+ }
+
+ assert(sum == 15, "Sum should be 1+2+3+4+5 = 15");
+}
+
+test "direct array iteration with different types" {
+ let floats: float[3] = [1.5, 2.5, 3.0];
+ let count = 0;
+
+ for f in floats {
+ count = count + 1;
+ }
+
+ assert(count == 3, "Should iterate over all 3 elements");
+}
+
+// TODO: Nested array iteration needs special handling
+// test "nested array iteration" {
+// let matrix: int[2][3] = [[1, 2, 3], [4, 5, 6]];
+// let total = 0;
+//
+// for row in matrix {
+// for val in row {
+// total = total + val;
+// }
+// }
+//
+// assert(total == 21, "Sum should be 1+2+3+4+5+6 = 21");
+// }
diff --git a/tests/std/test_env.zc b/tests/std/test_env.zc
index 25d5bc1..4b68712 100644
--- a/tests/std/test_env.zc
+++ b/tests/std/test_env.zc
@@ -30,7 +30,7 @@ test "test_std_env_get_dup" {
assert(env_var.is_some(), "env_var should have a value");
let value = env_var.unwrap();
- assert(value.c_str() == "ok3", "value should be ok3");
+ assert(strcmp(value.c_str(), "ok3") == 0, "value should be ok3");
value.free();
diff --git a/tests/std/test_json_serialization.zc b/tests/std/test_json_serialization.zc
new file mode 100644
index 0000000..9fd5b32
--- /dev/null
+++ b/tests/std/test_json_serialization.zc
@@ -0,0 +1,149 @@
+import "std/json.zc"
+import "std/io.zc"
+
+test "primitives" {
+ // Null
+ let v = JsonValue::null();
+ let s = v.to_string();
+ let expected = String::from("null");
+ if (!s.eq(&expected)) {
+ panic("Null serialization failed");
+ }
+ expected.free();
+ s.free();
+
+ // Bool True
+ v = JsonValue::bool(true);
+ s = v.to_string();
+ expected = String::from("true");
+ if (!s.eq(&expected)) {
+ panic("Bool true serialization failed");
+ }
+ expected.free();
+ s.free();
+
+ // Bool False
+ v = JsonValue::bool(false);
+ s = v.to_string();
+ expected = String::from("false");
+ if (!s.eq(&expected)) {
+ panic("Bool false serialization failed");
+ }
+ expected.free();
+ s.free();
+
+ // Number Int
+ v = JsonValue::number(123.0);
+ s = v.to_string();
+ expected = String::from("123");
+ if (!s.eq(&expected)) {
+ println "{s.c_str()}";
+ panic("Number 123 serialization failed");
+ }
+ expected.free();
+ s.free();
+
+ // Number Float
+ v = JsonValue::number(12.5);
+ s = v.to_string();
+ expected = String::from("12.5");
+ if (!s.eq(&expected)) {
+ panic("Number 12.5 serialization failed");
+ }
+ expected.free();
+ s.free();
+
+ // String Simple
+ v = JsonValue::string("hello");
+ s = v.to_string();
+ expected = String::from("\"hello\"");
+ if (!s.eq(&expected)) {
+ println "{s.c_str()}";
+ panic("String hello serialization failed");
+ }
+ expected.free();
+ s.free();
+
+ // String Escaped
+ v = JsonValue::string("hello \"world\"");
+ s = v.to_string();
+ expected = String::from("\"hello \\\"world\\\"\"");
+ if (!s.eq(&expected)) {
+ println "Got: {s.c_str()}";
+ panic("String escaped serialization failed");
+ }
+ expected.free();
+ s.free();
+}
+
+test "array" {
+ let v = JsonValue::array();
+ v.push(JsonValue::number(1.0));
+ v.push(JsonValue::bool(true));
+ v.push(JsonValue::string("a"));
+
+ let s = v.to_string();
+ let expected = String::from("[1,true,\"a\"]");
+ if (!s.eq(&expected)) {
+ println "Got: {s.c_str()}";
+ panic("Array serialization failed");
+ }
+ expected.free();
+ s.free();
+}
+
+test "object" {
+ let v = JsonValue::object();
+ v.set("key", JsonValue::string("value"));
+
+ let s = v.to_string();
+ // Round trip verification to avoid parser bug with literals
+ let parsed_res = JsonValue::parse(s.c_str());
+ if (parsed_res.is_err()) {
+ panic("Object round trip parse failed");
+ }
+ let parsed = parsed_res.unwrap();
+ if (!parsed.is_object()) panic("Round trip not object");
+
+ let val_opt = (*parsed).get_string("key");
+ if (val_opt.is_none()) panic("Round trip missing 'key'");
+
+ let val_str = val_opt.unwrap();
+ if (strcmp(val_str, "value") != 0) panic("Round trip wrong value");
+
+ // Cleanup
+ (*parsed).free();
+ free(parsed);
+ s.free();
+}
+
+test "nested" {
+ // {"arr":[1,2]}
+ let v = JsonValue::object();
+ let arr = JsonValue::array();
+ arr.push(JsonValue::number(1.0));
+ arr.push(JsonValue::number(2.0));
+ v.set("arr", arr);
+
+ let s = v.to_string();
+
+ // Round trip
+ let parsed_res = JsonValue::parse(s.c_str());
+ if (parsed_res.is_err()) {
+ panic("Round trip parse failed");
+ }
+ let parsed = parsed_res.unwrap();
+ if (!parsed.is_object()) panic("Round trip type mismatch");
+
+ let arr_opt = (*parsed).get_array("arr");
+ if (arr_opt.is_none()) panic("Round trip missing arr");
+
+ let arr_ptr = arr_opt.unwrap();
+ if (!(*arr_ptr).is_array()) panic("Inner not array");
+ if ((*arr_ptr).len() != 2) panic("Wrong array length");
+
+ // Cleanup
+ (*parsed).free();
+ free(parsed);
+ s.free();
+} \ No newline at end of file
diff --git a/tests/std/test_process.zc b/tests/std/test_process.zc
new file mode 100644
index 0000000..a3ba6ce
--- /dev/null
+++ b/tests/std/test_process.zc
@@ -0,0 +1,26 @@
+
+import "std/process.zc";
+import "std/string.zc";
+
+test "process output" {
+ let cmd = Command::new("echo");
+ cmd.arg("hello");
+
+ let out = cmd.output();
+
+ assert(out.exit_code == 0);
+ // echo usually outputs newline
+ assert(out.stdout.contains('h'));
+ assert(out.stdout.contains('e'));
+ assert(out.stdout.contains('l'));
+ assert(out.stdout.contains('o'));
+
+ // out is dropped automatically
+ // cmd is dropped automatically
+}
+
+test "process status" {
+ let cmd = Command::new("true"); // true command returns 0
+ let status = cmd.status();
+ assert(status == 0);
+}
diff --git a/tests/std/test_slice_iteration.zc b/tests/std/test_slice_iteration.zc
new file mode 100644
index 0000000..b7eddf4
--- /dev/null
+++ b/tests/std/test_slice_iteration.zc
@@ -0,0 +1,29 @@
+import "std/slice.zc"
+import "std/io.zc"
+
+test "slice from array iteration" {
+ let ints: int[5] = [1, 2, 3, 4, 5];
+ let slice = Slice<int>::from_array((int*)(&ints), 5);
+
+ // Test iteration
+ let sum = 0;
+ for val in slice {
+ sum = sum + val;
+ }
+
+ if (sum != 15) {
+ panic("Slice iteration failed: expected sum 15");
+ }
+}
+
+test "slice methods" {
+ let arr: int[3] = [10, 20, 30];
+ let slice = Slice<int>::from_array((int*)(&arr), 3);
+
+ if (slice.length() != 3) panic("Slice length wrong");
+ if (slice.is_empty()) panic("Slice should not be empty");
+
+ let opt = slice.get(1);
+ if (opt.is_none()) panic("Slice get failed");
+ if (opt.unwrap() != 20) panic("Slice get returned wrong value");
+}