From dcfdc053cb5f9fb4d5eac0a2233c75126b7a8188 Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Wed, 14 Jan 2026 23:59:54 +0000 Subject: Added some of the tests. --- tests/features/test_asm.zc | 54 ++++++++++++ tests/features/test_build_directives.zc | 19 ++++ tests/features/test_comptime_suite.zc | 29 +++++++ tests/features/test_concurrency_suite.zc | 98 +++++++++++++++++++++ tests/features/test_destructuring.zc | 38 ++++++++ tests/features/test_embed.zc | 57 ++++++++++++ tests/features/test_intel.zc | 22 +++++ tests/features/test_operators_suite.zc | 144 +++++++++++++++++++++++++++++++ tests/features/test_traits_suite.zc | 104 ++++++++++++++++++++++ 9 files changed, 565 insertions(+) create mode 100644 tests/features/test_asm.zc create mode 100644 tests/features/test_build_directives.zc create mode 100644 tests/features/test_comptime_suite.zc create mode 100644 tests/features/test_concurrency_suite.zc create mode 100644 tests/features/test_destructuring.zc create mode 100644 tests/features/test_embed.zc create mode 100644 tests/features/test_intel.zc create mode 100644 tests/features/test_operators_suite.zc create mode 100644 tests/features/test_traits_suite.zc (limited to 'tests/features') diff --git a/tests/features/test_asm.zc b/tests/features/test_asm.zc new file mode 100644 index 0000000..01f35d5 --- /dev/null +++ b/tests/features/test_asm.zc @@ -0,0 +1,54 @@ +fn test_nop() { + asm { nop } +} + +fn test_pause() { + asm { pause } +} + +fn test_multiline() { + asm { + mov $1, %rax + mov $2, %rbx + add %rbx, %rax + } +} + +fn test_volatile() { + asm volatile { + mfence + } +} + +test "test_asm" { + println "Testing inline assembly..."; + + test_nop(); + test_pause(); + test_multiline(); + test_volatile(); + + println "-> Assembly blocks compiled successfully!"; +} + +fn add_five(x: int) -> int { + var result: int; + asm { + "mov {x}, {result}" + "add $5, {result}" + : out(result) + : in(x) + } + return result; +} + +test "test_asm_params" { + println "Testing assembly parameters..."; + var val = add_five(10); + if (val == 15) { + println "-> Success! add_five(10) = 15"; + } else { + println "-> Failed: expected 15, got {val}"; + exit(1); + } +} diff --git a/tests/features/test_build_directives.zc b/tests/features/test_build_directives.zc new file mode 100644 index 0000000..d6e35b3 --- /dev/null +++ b/tests/features/test_build_directives.zc @@ -0,0 +1,19 @@ +//> link: -lm +//> cflags: -O2 + +// Declare C math function (since we don't have a math stdlib module yet) +extern fn sin(x: double) -> double; + +test "test_build_directives" { + println "Running Build Directives Test..."; + var x = 3.14159 / 2.0; // PI/2 + var 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)"; + } +} diff --git a/tests/features/test_comptime_suite.zc b/tests/features/test_comptime_suite.zc new file mode 100644 index 0000000..b8127ec --- /dev/null +++ b/tests/features/test_comptime_suite.zc @@ -0,0 +1,29 @@ + +comptime { + printf("fn generated_func() {\n"); + printf(" println \" I was generated at compile time!\";\n"); + printf("}\n"); +} + +@comptime +fn double_ct(x: int) -> int { + return x * 2; +} + +test "test_comptime_block" { + println "Running Comptime Test..."; + generated_func(); + println "Comptime Test Complete."; +} + +test "test_comptime_attr" { + var x = double_ct(21); + assert(x == 42, "Comptime function failed"); + println "Comptime function called successfully"; +} + +test "test_comptime_fn" { + comptime { + println "println \"Hello from comptime fn!\";"; + } +} diff --git a/tests/features/test_concurrency_suite.zc b/tests/features/test_concurrency_suite.zc new file mode 100644 index 0000000..836594d --- /dev/null +++ b/tests/features/test_concurrency_suite.zc @@ -0,0 +1,98 @@ +//> link: -lpthread +import "std/thread.zc" + +async fn double_slowly(x: int) -> int { + usleep(1000); + return x * 2; +} + +async fn add_async(a: int, b: int) -> int { + return a + b; +} + +async fn say_hello() { + puts("Hello from async!"); +} + +struct Point { + x: int; + y: int; +} + +async fn make_point(x: int, y: int) -> Point { + return Point{x: x, y: y}; +} + +struct Counter { + val: int; + lock: Mutex; +} + +test "test_async_basics" { + var future1 = double_slowly(21); + var future2 = add_async(10, 20); + + var result1 = await future1; + var result2 = await future2; + + assert(result1 == 42, "Async double failed"); + assert(result2 == 30, "Async add failed"); +} + +test "test_async_struct_return" { + var f = make_point(5, 7); + var p = await f; + + assert(p.x == 5, "Async struct x failed"); + assert(p.y == 7, "Async struct y failed"); +} + +test "test_async_void" { + var f = say_hello(); + await f; +} + +test "test_thread" { + println "Testing Concurrency..."; + + var c = (Counter*)malloc(sizeof(Counter)); + c.val = 0; + c.lock = Mutex::new(); + + const N = 10000; + + var t1_res = Thread::spawn(fn() { + for (var i=0; i (int, int) { + return (10, 20); +} + +test "test_destructuring" { + var p = Point{x: 1, y: 2}; + + // Explicit Struct Destructuring (Shorthand) + var Point{x, y} = p; + assert(x == 1, "x is 1"); + assert(y == 2, "y is 2"); + + // Explicit Struct Destructuring (Renamed) + var Point{x: a, y: b} = p; + assert(a == 1, "a is 1"); + assert(b == 2, "b is 2"); + + // Anonymous Struct Destructuring (Inferred) + // Note: Anonymous block only supports shorthand {x, y} currently. + // var {x: x2} = p; // Not supported yet in anonymous block parser + + // Tuple Destructuring + var (t1, t2) = tuple_ret(); + assert(t1 == 10, "t1 is 10"); + assert(t2 == 20, "t2 is 20"); + + println "Destructuring OK"; +} diff --git a/tests/features/test_embed.zc b/tests/features/test_embed.zc new file mode 100644 index 0000000..f6d9468 --- /dev/null +++ b/tests/features/test_embed.zc @@ -0,0 +1,57 @@ + +test "test_embed" { + "=> Static File Analyzer"; + + var data = embed "std.zc"; + + "Target File: 'std.zc'"; + "File Size: {data.len} bytes"; + ""; + + var lines: I32 = 1; + var words: I32 = 0; + var sum: U64 = 0; + var in_word: bool = 0; + + "Analyzing content..."; + + var i: int = 0; + while (i < data.len) { + var c: char = data.data[i]; + + match c { + '\n' => { + lines++; + in_word = 0; + } + + ' ', '\t', '\r' => { + in_word = 0; + } + + _ => { + if (!in_word) { + words++; + in_word = 1; + } + } + } + + var b: U8 = c; + sum = sum + b; + + i++; + } + + ""; + "*** Report ***"; + "Total Lines: {lines}"; + "Total Words: {words}"; + + "Checksum: 0x{sum:X} (Simple Sum)"; + "Average Byte: {sum / data.len}"; + + ""; + "Analysis successfully completed."; + +} diff --git a/tests/features/test_intel.zc b/tests/features/test_intel.zc new file mode 100644 index 0000000..8547501 --- /dev/null +++ b/tests/features/test_intel.zc @@ -0,0 +1,22 @@ +//> cflags: -masm=intel + +fn add_five_intel(x: int) -> int { + var result: int; + asm { + "mov {result}, {x}" + "add {result}, 5" + : out(result) + : in(x) + } + return result; +} + +test "test_intel" { + var val = add_five_intel(10); + "Sum Intel: 10 + 5 = {val}"; + + match val { + 15 => printf("-> Success!\n") + _ => printf("-> Failed: expected 15, got {val}\n") + } +} diff --git a/tests/features/test_operators_suite.zc b/tests/features/test_operators_suite.zc new file mode 100644 index 0000000..68b73fe --- /dev/null +++ b/tests/features/test_operators_suite.zc @@ -0,0 +1,144 @@ + +struct Flags { + bits: int; +} + +impl Flags { + fn new(b: int) -> Flags { return Flags{bits: b}; } + + fn bitor(self, other: Flags) -> Flags { + " [DEBUG] Custom bitor called! combining {self.bits} | {other.bits}"; + return Flags { bits: self.bits | other.bits }; + } +} + +struct Container { + val: int; +} + +impl Container { + fn new(v: int) -> Container { return Container { val: v }; } + + fn get(self, idx: int) -> int { + return self.val + idx; + } + + fn set(self, idx: int, v: int) { + self.val = v + idx; + } + + fn neg(self) -> Container { + return Container { val: -self.val }; + } + + fn not(self) -> bool { + return self.val == 0; + } + + fn bitnot(self) -> Container { + return Container { val: ~self.val }; + } +} + +enum Result { + Ok(int), + Err(int) +} + +fn make_ok(v: int) -> Result { + return Result_Ok(v); +} + +fn make_err(e: int) -> Result { + return Result_Err(e); +} + +fn process_result(fail: int) -> Result { + var val = make_ok(10)?; + + if (fail) { + var v2 = make_err(500)?; + return Result_Ok(v2 + 1000); + } + + return Result_Ok(val + 20); +} + +fn add(a: int, b: int) -> int { + return a + b; +} + +fn twice(x: int) -> int { + return x * 2; +} + +test "test_operator_overloading" { + "=> Bitwise Primitives"; + var a = 0b1100; + var b = 0b1010; + + "{a} | {b} = {a | b} (Expected 14)"; + "{a} & {b} = {a & b} (Expected 8)"; + "{a} ^ {b} = {a ^ b} (Expected 6)"; + "{a} << 1 = {a << 1} (Expected 24)"; + + "=> Compound Assignment Desugaring"; + var x = 10; + x += 5; // 15 + x <<= 1; // 30 + + "=> Struct Overloading + Compound (|=)"; + var f1 = Flags::new(1); + var f2 = Flags::new(4); + f1 |= f2; + "Result bits: {f1.bits} (Expected 5)"; + + const MAX_LIMIT = 100; +} + +test "test_extended_overloading" { + var c = Container::new(10); + + // Index Get + assert(c[5] == 15, "Get Failed"); + + // Index Set + c[2] = 20; + assert(c.val == 22, "Set Failed"); + + // Compound Assignment + c[0] += 5; + assert(c.val == 27, "Compound Set Failed"); + + // Unary Neg + var n = -c; + assert(n.val == -27, "Neg Failed"); + + // Unary Not + assert(!c == false, "Not Operator Failed"); + + // Unary Bitnot + var b = ~c; + assert(b.val == ~27, "Bitnot Failed"); +} + +test "test_pipe_operator" { + var res = 5 |> twice; + assert(res == 10, "Pipe twice failed"); + + var res2 = 10 |> add(20); + assert(res2 == 30, "Pipe add failed"); + + var res3 = 5 |> twice |> add(10); // 20 + assert(res3 == 20, "Multi-pipe failed"); +} + +test "test_try_operator" { + var res_ok = process_result(0); + assert(res_ok.tag == Result_Ok_Tag, "Expected Ok"); + assert(res_ok.data.Ok == 30, "Expected 30"); + + var res_err = process_result(1); + assert(res_err.tag == Result_Err_Tag, "Expected Err"); + assert(res_err.data.Err == 500, "Expected Err(500)"); +} diff --git a/tests/features/test_traits_suite.zc b/tests/features/test_traits_suite.zc new file mode 100644 index 0000000..7fe7d1c --- /dev/null +++ b/tests/features/test_traits_suite.zc @@ -0,0 +1,104 @@ + +trait Greeter { + fn greet(self, msg: string); + fn shout(self); +} + +struct Robot { + id: int; +} + +impl Greeter for Robot { + fn greet(self, msg: string) { + println "Robot {self.id} says: {msg}"; + } + fn shout(self) { + println "ROBOT {self.id} ACTIVATED"; + } +} + +trait Shape { + fn area(self) -> float; + fn name(self) -> string; +} + +struct Circle { + radius: float; +} + +impl Shape for Circle { + fn area(self) -> float { + return 3.14159 * self.radius * self.radius; + } + fn name(self) -> string { + return "Circle"; + } +} + +struct Rectangle { + width: float; + height: float; +} + +impl Shape for Rectangle { + fn area(self) -> float { + return self.width * self.height; + } + fn name(self) -> string { + return "Rectangle"; + } +} + +@derive(Debug, Clone, Eq) +struct Point { + x: int; + y: int; +} + + +fn print_shape_info(s: Shape) { + println "Shape: {s.name()}, Area: {s.area()}"; +} + +test "basic_traits" { + var r: Robot = Robot { id: 42 }; + var g: Greeter = &r; + + g.greet("Hello World"); + g.shout(); +} + +test "advanced_traits" { + var c = Circle { radius: 5.0 }; + var r = Rectangle { width: 4.0, height: 6.0 }; + + var s_c: Shape = &c; + var s_r: Shape = &r; + + print_shape_info(s_c); + print_shape_info(s_r); + + if (s_c.area() > s_r.area()) { + println "Circle is larger"; + } else { + println "Rectangle is larger"; + } +} + +test "test_derive" { + var p1 = Point{x: 10, y: 20}; + + // Debug + var s = p1.to_string(); + assert(strcmp(s, "Point { ... }") == 0, "Debug string matches"); + + // Clone + var p2 = p1.clone(); + assert(p2.x == 10, "Clone x matches"); + + // Eq + assert(p1.eq(p2) == true, "Eq works (true)"); + + var p3 = Point{x: 10, y: 21}; + assert(p1.eq(p3) == false, "Eq works (false)"); +} -- cgit v1.2.3