summaryrefslogtreecommitdiff
path: root/tests/memory
diff options
context:
space:
mode:
Diffstat (limited to 'tests/memory')
-rw-r--r--tests/memory/test_copy_trait.zc37
-rw-r--r--tests/memory/test_drop.zc26
-rw-r--r--tests/memory/test_move_double_free.zc87
-rw-r--r--tests/memory/test_move_semantics.zc55
-rw-r--r--tests/memory/test_resources.zc59
5 files changed, 264 insertions, 0 deletions
diff --git a/tests/memory/test_copy_trait.zc b/tests/memory/test_copy_trait.zc
new file mode 100644
index 0000000..994ccee
--- /dev/null
+++ b/tests/memory/test_copy_trait.zc
@@ -0,0 +1,37 @@
+
+trait Copy {}
+
+struct Point {
+ x: int;
+ y: int;
+}
+
+impl Copy for Point {}
+
+struct Mover {
+ val: int;
+}
+
+test "copy_trait" {
+ var p1 = Point { x: 10, y: 20 };
+ var p2 = p1; // Copy, not move
+
+ // Both should be valid
+ assert(p1.x == 10, "p1 invalid after copy");
+ assert(p2.x == 10, "p2 invalid after copy");
+
+ // Modify p2, p1 should be unchanged
+ p2.x = 30;
+ assert(p1.x == 10, "p1 changed after p2 modification");
+ assert(p2.x == 30, "p2 modification failed");
+
+ println "Copy Trait Works!";
+}
+
+test "move_default" {
+ var m1 = Mover { val: 1 };
+ var m2 = m1; // Moved
+
+ // Uncommenting this should cause compile error
+ // var m3 = m1;
+}
diff --git a/tests/memory/test_drop.zc b/tests/memory/test_drop.zc
new file mode 100644
index 0000000..8b34efe
--- /dev/null
+++ b/tests/memory/test_drop.zc
@@ -0,0 +1,26 @@
+import "../../std/mem.zc"
+
+var DROP_CALLED = 0;
+
+struct MyResource {
+ id: int;
+}
+
+impl Drop for MyResource {
+ fn drop(self) {
+ println "Dropping MyResource {self.id}";
+ DROP_CALLED = 1;
+ }
+}
+
+test "drop_trait" {
+ {
+ var res = MyResource { id: 1 };
+ // Scope ends here, drop should be called
+ }
+
+ if (DROP_CALLED != 1) {
+ println "Error: Drop was not called!";
+ exit(1);
+ }
+}
diff --git a/tests/memory/test_move_double_free.zc b/tests/memory/test_move_double_free.zc
new file mode 100644
index 0000000..b82bd38
--- /dev/null
+++ b/tests/memory/test_move_double_free.zc
@@ -0,0 +1,87 @@
+import "../../std/mem.zc"
+
+// Global counters to track drop calls
+var DROP_COUNT = 0;
+var DROP_NULL_COUNT = 0;
+
+struct Resource {
+ data: int*;
+ id: int;
+}
+
+impl Drop for Resource {
+ fn drop(self) {
+ if (self.data != NULL) {
+ DROP_COUNT = DROP_COUNT + 1;
+ free(self.data);
+ self.data = NULL; // Prevent double free logic if called again, though generated code should zero
+ } else {
+ DROP_NULL_COUNT = DROP_NULL_COUNT + 1;
+ }
+ }
+}
+
+struct Container {
+ res: Resource;
+}
+
+// No explicit Drop for Container, relies on compiler generating one
+
+test "move_variable" {
+ DROP_COUNT = 0;
+ DROP_NULL_COUNT = 0;
+
+ {
+ var r1 = Resource { data: malloc(10), id: 1 };
+ var r2 = r1; // Move
+
+ // r1 should be nullified
+ // r2 owns data
+ }
+
+ assert(DROP_COUNT == 1, "Should drop exactly once (r2)");
+ assert(DROP_NULL_COUNT == 1, "Should see one null drop (r1)");
+}
+
+fn pass_through(r: Resource) -> Resource {
+ return r; // Move return
+}
+
+test "move_function" {
+ DROP_COUNT = 0;
+ DROP_NULL_COUNT = 0;
+
+ {
+ var r1 = Resource { data: malloc(10), id: 2 };
+ var r2 = pass_through(r1);
+ // r1 moved to arg -> moved to return -> moved to r2
+ }
+
+ // r1: null drop
+ // arg: null drop (moved to return)
+ // return temp: null drop (moved to r2)
+ // r2: valid drop
+
+ assert(DROP_COUNT == 1, "Should drop exactly once (final r2)");
+ // We expect multiple null drops due to intermediate moves
+ assert(DROP_NULL_COUNT >= 1, "Should see at least one null drop");
+}
+
+test "partial_move_member" {
+ DROP_COUNT = 0;
+ DROP_NULL_COUNT = 0;
+
+ {
+ var c = Container { res: Resource { data: malloc(10), id: 3 } };
+ var r = c.res; // Partial move
+
+ // c.res should be nullified
+ // r owns data
+ }
+
+ // r drops valid
+ // c drops, checks res -> null drop
+
+ assert(DROP_COUNT == 1, "Should drop exactly once (r)");
+ assert(DROP_NULL_COUNT == 1, "Should see null drop (c.res)");
+}
diff --git a/tests/memory/test_move_semantics.zc b/tests/memory/test_move_semantics.zc
new file mode 100644
index 0000000..bf0d717
--- /dev/null
+++ b/tests/memory/test_move_semantics.zc
@@ -0,0 +1,55 @@
+
+struct Point {
+ x: int;
+}
+
+struct Mover {
+ val: int;
+}
+
+test "basic_move" {
+ var p1 = Mover { val: 10 };
+ var p2 = p1; // p1 moved to p2
+
+ // Valid usage of p2
+ assert(p2.val == 10, "p2 should be valid");
+
+ // Invalid usage of p1 (Uncomment to test compiler error)
+ // var p3 = p1;
+}
+
+test "primitive_copy" {
+ var i = 10;
+ var j = i; // Copy
+ var k = i; // Copy again - should be valid
+ assert(k == 10, "Primitive copy failed");
+}
+
+test "reassignment" {
+ var m1 = Mover { val: 1 };
+ var m2 = m1; // m1 moved
+
+ m1 = Mover { val: 2 }; // Resurrect m1
+ var m3 = m1; // Valid now
+ assert(m3.val == 2, "Resurrection failed");
+}
+
+fn consume(m: Mover) {
+ assert(m.val == 10, "Func arg failed");
+}
+
+test "func_arg" {
+ var m = Mover { val: 10 };
+ consume(m); // m moved
+
+ // 2. Use after move (Call - Negative Test)
+ // consume(m); // Should fail: Use of moved value 'm'
+}
+
+/*
+// 3. Use after return (Negative Test)
+fn fail_return(m: Mover) -> Mover {
+ var m2 = m;
+ return m; // Should fail: Use of moved value 'm'
+}
+*/
diff --git a/tests/memory/test_resources.zc b/tests/memory/test_resources.zc
new file mode 100644
index 0000000..dc7b9f9
--- /dev/null
+++ b/tests/memory/test_resources.zc
@@ -0,0 +1,59 @@
+
+// Copy Trait
+@derive(Copy)
+struct Point { x: int; y: int; }
+
+// Clone Pattern
+trait Clone {
+ fn clone(self) -> Self;
+}
+
+struct Box { val: int; }
+
+impl Clone for Box {
+ fn clone(self) -> Box {
+ return Box{val: self.val};
+ }
+}
+
+// Re-initialization
+struct Resource { ptr: void*; }
+
+// Function Param Helper
+fn take_point(p: Point) {
+ if p.x != 10 {
+ // Error
+ }
+}
+
+test "Resource Semantics" {
+ "Testing Resource Semantics...";
+
+ var p1 = Point{x: 10, y: 20};
+ var p2 = p1; // Copied
+
+ var b1 = Box{val: 99};
+ var b2 = b1.clone();
+ // var b3 = b1; // This would move if uncommented.
+
+ if b2.val != 99 {
+ !"Clone failed";
+ exit(1);
+ }
+
+ // Re-initialization
+ // struct Resource (Global)
+
+ var r1 = Resource{ptr: NULL};
+ var r2 = r1; // Moved
+
+ r1 = Resource{ptr: NULL}; // Re-init
+ var r3 = r1; // Valid again
+
+ // Function Param Move (Simulated)
+ take_point(p1);
+ take_point(p1); // Still valid because Copy
+
+ "Resource Semantics Passed.";
+}
+