aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/while.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-29 15:54:04 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-29 15:54:04 -0700
commit4307436b9945f814ff5731981df1d19febf3ba0a (patch)
treeefaaec94a41d632d45f255d464d9787eb02c4c9b /test/behavior/while.zig
parent5a02c938dafdf2bb11b2350b6ad3161ef93744f0 (diff)
downloadzig-4307436b9945f814ff5731981df1d19febf3ba0a.tar.gz
zig-4307436b9945f814ff5731981df1d19febf3ba0a.zip
move behavior tests from test/stage1/ to test/
And fix test cases to make them pass. This is in preparation for starting to pass behavior tests with self-hosted.
Diffstat (limited to 'test/behavior/while.zig')
-rw-r--r--test/behavior/while.zig289
1 files changed, 289 insertions, 0 deletions
diff --git a/test/behavior/while.zig b/test/behavior/while.zig
new file mode 100644
index 0000000000..c9207396f7
--- /dev/null
+++ b/test/behavior/while.zig
@@ -0,0 +1,289 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "while loop" {
+ var i: i32 = 0;
+ while (i < 4) {
+ i += 1;
+ }
+ expect(i == 4);
+ expect(whileLoop1() == 1);
+}
+fn whileLoop1() i32 {
+ return whileLoop2();
+}
+fn whileLoop2() i32 {
+ while (true) {
+ return 1;
+ }
+}
+
+test "static eval while" {
+ expect(static_eval_while_number == 1);
+}
+const static_eval_while_number = staticWhileLoop1();
+fn staticWhileLoop1() i32 {
+ return whileLoop2();
+}
+fn staticWhileLoop2() i32 {
+ while (true) {
+ return 1;
+ }
+}
+
+test "continue and break" {
+ runContinueAndBreakTest();
+ expect(continue_and_break_counter == 8);
+}
+var continue_and_break_counter: i32 = 0;
+fn runContinueAndBreakTest() void {
+ var i: i32 = 0;
+ while (true) {
+ continue_and_break_counter += 2;
+ i += 1;
+ if (i < 4) {
+ continue;
+ }
+ break;
+ }
+ expect(i == 4);
+}
+
+test "return with implicit cast from while loop" {
+ returnWithImplicitCastFromWhileLoopTest() catch unreachable;
+}
+fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
+ while (true) {
+ return;
+ }
+}
+
+test "while with continue expression" {
+ var sum: i32 = 0;
+ {
+ var i: i32 = 0;
+ while (i < 10) : (i += 1) {
+ if (i == 5) continue;
+ sum += i;
+ }
+ }
+ expect(sum == 40);
+}
+
+test "while with else" {
+ var sum: i32 = 0;
+ var i: i32 = 0;
+ var got_else: i32 = 0;
+ while (i < 10) : (i += 1) {
+ sum += 1;
+ } else {
+ got_else += 1;
+ }
+ expect(sum == 10);
+ expect(got_else == 1);
+}
+
+test "while with optional as condition" {
+ numbers_left = 10;
+ var sum: i32 = 0;
+ while (getNumberOrNull()) |value| {
+ sum += value;
+ }
+ expect(sum == 45);
+}
+
+test "while with optional as condition with else" {
+ numbers_left = 10;
+ var sum: i32 = 0;
+ var got_else: i32 = 0;
+ while (getNumberOrNull()) |value| {
+ sum += value;
+ expect(got_else == 0);
+ } else {
+ got_else += 1;
+ }
+ expect(sum == 45);
+ expect(got_else == 1);
+}
+
+test "while with error union condition" {
+ numbers_left = 10;
+ var sum: i32 = 0;
+ var got_else: i32 = 0;
+ while (getNumberOrErr()) |value| {
+ sum += value;
+ } else |err| {
+ expect(err == error.OutOfNumbers);
+ got_else += 1;
+ }
+ expect(sum == 45);
+ expect(got_else == 1);
+}
+
+var numbers_left: i32 = undefined;
+fn getNumberOrErr() anyerror!i32 {
+ return if (numbers_left == 0) error.OutOfNumbers else x: {
+ numbers_left -= 1;
+ break :x numbers_left;
+ };
+}
+fn getNumberOrNull() ?i32 {
+ return if (numbers_left == 0) null else x: {
+ numbers_left -= 1;
+ break :x numbers_left;
+ };
+}
+
+test "while on optional with else result follow else prong" {
+ const result = while (returnNull()) |value| {
+ break value;
+ } else
+ @as(i32, 2);
+ expect(result == 2);
+}
+
+test "while on optional with else result follow break prong" {
+ const result = while (returnOptional(10)) |value| {
+ break value;
+ } else
+ @as(i32, 2);
+ expect(result == 10);
+}
+
+test "while on error union with else result follow else prong" {
+ const result = while (returnError()) |value| {
+ break value;
+ } else |err|
+ @as(i32, 2);
+ expect(result == 2);
+}
+
+test "while on error union with else result follow break prong" {
+ const result = while (returnSuccess(10)) |value| {
+ break value;
+ } else |err|
+ @as(i32, 2);
+ expect(result == 10);
+}
+
+test "while on bool with else result follow else prong" {
+ const result = while (returnFalse()) {
+ break @as(i32, 10);
+ } else
+ @as(i32, 2);
+ expect(result == 2);
+}
+
+test "while on bool with else result follow break prong" {
+ const result = while (returnTrue()) {
+ break @as(i32, 10);
+ } else
+ @as(i32, 2);
+ expect(result == 10);
+}
+
+test "break from outer while loop" {
+ testBreakOuter();
+ comptime testBreakOuter();
+}
+
+fn testBreakOuter() void {
+ outer: while (true) {
+ while (true) {
+ break :outer;
+ }
+ }
+}
+
+test "continue outer while loop" {
+ testContinueOuter();
+ comptime testContinueOuter();
+}
+
+fn testContinueOuter() void {
+ var i: usize = 0;
+ outer: while (i < 10) : (i += 1) {
+ while (true) {
+ continue :outer;
+ }
+ }
+}
+
+fn returnNull() ?i32 {
+ return null;
+}
+fn returnOptional(x: i32) ?i32 {
+ return x;
+}
+fn returnError() anyerror!i32 {
+ return error.YouWantedAnError;
+}
+fn returnSuccess(x: i32) anyerror!i32 {
+ return x;
+}
+fn returnFalse() bool {
+ return false;
+}
+fn returnTrue() bool {
+ return true;
+}
+
+test "while bool 2 break statements and an else" {
+ const S = struct {
+ fn entry(t: bool, f: bool) void {
+ var ok = false;
+ ok = while (t) {
+ if (f) break false;
+ if (t) break true;
+ } else false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
+
+test "while optional 2 break statements and an else" {
+ const S = struct {
+ fn entry(opt_t: ?bool, f: bool) void {
+ var ok = false;
+ ok = while (opt_t) |t| {
+ if (f) break false;
+ if (t) break true;
+ } else false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
+
+test "while error 2 break statements and an else" {
+ const S = struct {
+ fn entry(opt_t: anyerror!bool, f: bool) void {
+ var ok = false;
+ ok = while (opt_t) |t| {
+ if (f) break false;
+ if (t) break true;
+ } else |_| false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
+
+test "while copies its payload" {
+ const S = struct {
+ fn doTheTest() void {
+ var tmp: ?i32 = 10;
+ while (tmp) |value| {
+ // Modify the original variable
+ tmp = null;
+ expect(value == 10);
+ }
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}