| author | |
| committer | |
| log | 10525b869d1a50eef65d8ec2717dda61c937e154 |
| tree | dccd6804ff8dd824094d7177238c3c909c3b3679 |
| parent | 37b9a2e6a4aa59494406d38495768778502fbcda |
5 files changed, 662 insertions(+), 612 deletions(-)
build.zig+13-17| ... | @@ -10,27 +10,23 @@ pub fn build(b: &Builder) { | ... | @@ -10,27 +10,23 @@ pub fn build(b: &Builder) { |
| 10 | const run_tests_cmd = b.addCommand(b.out_dir, b.env_map, "./run_tests", [][]const u8{}); | 10 | const run_tests_cmd = b.addCommand(b.out_dir, b.env_map, "./run_tests", [][]const u8{}); |
| 11 | run_tests_cmd.step.dependOn(&run_tests_exe.step); | 11 | run_tests_cmd.step.dependOn(&run_tests_exe.step); |
| 12 | 12 | ||
| 13 | const self_hosted_tests_debug_nolibc = b.addTest("test/self_hosted.zig"); | ||
| 14 | |||
| 15 | const self_hosted_tests_release_nolibc = b.addTest("test/self_hosted.zig"); | ||
| 16 | self_hosted_tests_release_nolibc.setRelease(true); | ||
| 17 | |||
| 18 | const self_hosted_tests_debug_libc = b.addTest("test/self_hosted.zig"); | ||
| 19 | self_hosted_tests_debug_libc.linkLibrary("c"); | ||
| 20 | |||
| 21 | const self_hosted_tests_release_libc = b.addTest("test/self_hosted.zig"); | ||
| 22 | self_hosted_tests_release_libc.setRelease(true); | ||
| 23 | self_hosted_tests_release_libc.linkLibrary("c"); | ||
| 24 | |||
| 25 | const self_hosted_tests = b.step("test-self-hosted", "Run the self-hosted tests"); | 13 | const self_hosted_tests = b.step("test-self-hosted", "Run the self-hosted tests"); |
| 26 | self_hosted_tests.dependOn(&self_hosted_tests_debug_nolibc.step); | 14 | for ([]bool{false, true}) |release| { |
| 27 | self_hosted_tests.dependOn(&self_hosted_tests_release_nolibc.step); | 15 | for ([]bool{false, true}) |link_libc| { |
| 28 | self_hosted_tests.dependOn(&self_hosted_tests_debug_libc.step); | 16 | const these_tests = b.addTest("test/self_hosted.zig"); |
| 29 | self_hosted_tests.dependOn(&self_hosted_tests_release_libc.step); | 17 | // TODO add prefix to test names |
| 18 | // TODO pass test_filter to these_tests | ||
| 19 | these_tests.setRelease(release); | ||
| 20 | if (link_libc) { | ||
| 21 | these_tests.linkLibrary("c"); | ||
| 22 | } | ||
| 23 | self_hosted_tests.dependOn(&these_tests.step); | ||
| 24 | } | ||
| 25 | } | ||
| 30 | 26 | ||
| 31 | test_step.dependOn(self_hosted_tests); | 27 | test_step.dependOn(self_hosted_tests); |
| 32 | //test_step.dependOn(&run_tests_cmd.step); | 28 | //test_step.dependOn(&run_tests_cmd.step); |
| 33 | 29 | ||
| 34 | test_step.dependOn(tests.addCompareOutputTests(b, test_filter)); | 30 | test_step.dependOn(tests.addCompareOutputTests(b, test_filter)); |
| 35 | //test_step.dependOn(tests.addBuildExampleTests(b, test_filter)); | 31 | test_step.dependOn(tests.addBuildExampleTests(b, test_filter)); |
| 36 | } | 32 | } |
test/build_examples.zig created+60| ... | @@ -0,0 +1,60 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const build = std.build; | ||
| 3 | const mem = std.mem; | ||
| 4 | const fmt = std.fmt; | ||
| 5 | |||
| 6 | pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | ||
| 7 | const cases = %%b.allocator.create(BuildExamplesContext); | ||
| 8 | *cases = BuildExamplesContext { | ||
| 9 | .b = b, | ||
| 10 | .step = b.step("test-build-examples", "Build the examples"), | ||
| 11 | .test_index = 0, | ||
| 12 | .test_filter = test_filter, | ||
| 13 | }; | ||
| 14 | |||
| 15 | cases.add("example/hello_world/hello.zig"); | ||
| 16 | cases.addC("example/hello_world/hello_libc.zig"); | ||
| 17 | cases.add("example/cat/main.zig"); | ||
| 18 | cases.add("example/guess_number/main.zig"); | ||
| 19 | |||
| 20 | return cases.step; | ||
| 21 | } | ||
| 22 | |||
| 23 | const BuildExamplesContext = struct { | ||
| 24 | b: &build.Builder, | ||
| 25 | step: &build.Step, | ||
| 26 | test_index: usize, | ||
| 27 | test_filter: ?[]const u8, | ||
| 28 | |||
| 29 | pub fn addC(self: &BuildExamplesContext, root_src: []const u8) { | ||
| 30 | self.addAllArgs(root_src, true); | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn add(self: &BuildExamplesContext, root_src: []const u8) { | ||
| 34 | self.addAllArgs(root_src, false); | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) { | ||
| 38 | const b = self.b; | ||
| 39 | |||
| 40 | for ([]bool{false, true}) |release| { | ||
| 41 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})", | ||
| 42 | root_src, if (release) "release" else "debug"); | ||
| 43 | if (const filter ?= self.test_filter) { | ||
| 44 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | ||
| 45 | continue; | ||
| 46 | } | ||
| 47 | |||
| 48 | const exe = b.addExecutable("test", root_src); | ||
| 49 | exe.setRelease(release); | ||
| 50 | if (link_libc) { | ||
| 51 | exe.linkLibrary("c"); | ||
| 52 | } | ||
| 53 | |||
| 54 | const log_step = b.addLog("PASS {}\n", annotated_case_name); | ||
| 55 | log_step.step.dependOn(&exe.step); | ||
| 56 | |||
| 57 | self.step.dependOn(&log_step.step); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | }; | ||
test/compare_output.zig created+587| ... | @@ -0,0 +1,587 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const debug = std.debug; | ||
| 3 | const build = std.build; | ||
| 4 | const os = std.os; | ||
| 5 | const StdIo = os.ChildProcess.StdIo; | ||
| 6 | const Term = os.ChildProcess.Term; | ||
| 7 | const Buffer0 = std.cstr.Buffer0; | ||
| 8 | const io = std.io; | ||
| 9 | const mem = std.mem; | ||
| 10 | const fmt = std.fmt; | ||
| 11 | const List = std.list.List; | ||
| 12 | |||
| 13 | error TestFailed; | ||
| 14 | |||
| 15 | pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | ||
| 16 | const cases = %%b.allocator.create(CompareOutputContext); | ||
| 17 | *cases = CompareOutputContext { | ||
| 18 | .b = b, | ||
| 19 | .compare_output_tests = b.step("test-compare-output", "Run the compare output tests"), | ||
| 20 | .test_index = 0, | ||
| 21 | .test_filter = test_filter, | ||
| 22 | }; | ||
| 23 | |||
| 24 | cases.addC("hello world with libc", | ||
| 25 | \\const c = @cImport(@cInclude("stdio.h")); | ||
| 26 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | ||
| 27 | \\ _ = c.puts(c"Hello, world!"); | ||
| 28 | \\ return 0; | ||
| 29 | \\} | ||
| 30 | , "Hello, world!" ++ os.line_sep); | ||
| 31 | |||
| 32 | cases.addCase({ | ||
| 33 | var tc = cases.create("multiple files with private function", | ||
| 34 | \\use @import("std").io; | ||
| 35 | \\use @import("foo.zig"); | ||
| 36 | \\ | ||
| 37 | \\pub fn main() -> %void { | ||
| 38 | \\ privateFunction(); | ||
| 39 | \\ %%stdout.printf("OK 2\n"); | ||
| 40 | \\} | ||
| 41 | \\ | ||
| 42 | \\fn privateFunction() { | ||
| 43 | \\ printText(); | ||
| 44 | \\} | ||
| 45 | , "OK 1\nOK 2\n"); | ||
| 46 | |||
| 47 | tc.addSourceFile("foo.zig", | ||
| 48 | \\use @import("std").io; | ||
| 49 | \\ | ||
| 50 | \\// purposefully conflicting function with main.zig | ||
| 51 | \\// but it's private so it should be OK | ||
| 52 | \\fn privateFunction() { | ||
| 53 | \\ %%stdout.printf("OK 1\n"); | ||
| 54 | \\} | ||
| 55 | \\ | ||
| 56 | \\pub fn printText() { | ||
| 57 | \\ privateFunction(); | ||
| 58 | \\} | ||
| 59 | ); | ||
| 60 | |||
| 61 | tc | ||
| 62 | }); | ||
| 63 | |||
| 64 | cases.addCase({ | ||
| 65 | var tc = cases.create("import segregation", | ||
| 66 | \\use @import("foo.zig"); | ||
| 67 | \\use @import("bar.zig"); | ||
| 68 | \\ | ||
| 69 | \\pub fn main() -> %void { | ||
| 70 | \\ foo_function(); | ||
| 71 | \\ bar_function(); | ||
| 72 | \\} | ||
| 73 | , "OK\nOK\n"); | ||
| 74 | |||
| 75 | tc.addSourceFile("foo.zig", | ||
| 76 | \\use @import("std").io; | ||
| 77 | \\pub fn foo_function() { | ||
| 78 | \\ %%stdout.printf("OK\n"); | ||
| 79 | \\} | ||
| 80 | ); | ||
| 81 | |||
| 82 | tc.addSourceFile("bar.zig", | ||
| 83 | \\use @import("other.zig"); | ||
| 84 | \\use @import("std").io; | ||
| 85 | \\ | ||
| 86 | \\pub fn bar_function() { | ||
| 87 | \\ if (foo_function()) { | ||
| 88 | \\ %%stdout.printf("OK\n"); | ||
| 89 | \\ } | ||
| 90 | \\} | ||
| 91 | ); | ||
| 92 | |||
| 93 | tc.addSourceFile("other.zig", | ||
| 94 | \\pub fn foo_function() -> bool { | ||
| 95 | \\ // this one conflicts with the one from foo | ||
| 96 | \\ return true; | ||
| 97 | \\} | ||
| 98 | ); | ||
| 99 | |||
| 100 | tc | ||
| 101 | }); | ||
| 102 | |||
| 103 | cases.addCase({ | ||
| 104 | var tc = cases.create("two files use import each other", | ||
| 105 | \\use @import("a.zig"); | ||
| 106 | \\ | ||
| 107 | \\pub fn main() -> %void { | ||
| 108 | \\ ok(); | ||
| 109 | \\} | ||
| 110 | , "OK\n"); | ||
| 111 | |||
| 112 | tc.addSourceFile("a.zig", | ||
| 113 | \\use @import("b.zig"); | ||
| 114 | \\const io = @import("std").io; | ||
| 115 | \\ | ||
| 116 | \\pub const a_text = "OK\n"; | ||
| 117 | \\ | ||
| 118 | \\pub fn ok() { | ||
| 119 | \\ %%io.stdout.printf(b_text); | ||
| 120 | \\} | ||
| 121 | ); | ||
| 122 | |||
| 123 | tc.addSourceFile("b.zig", | ||
| 124 | \\use @import("a.zig"); | ||
| 125 | \\ | ||
| 126 | \\pub const b_text = a_text; | ||
| 127 | ); | ||
| 128 | |||
| 129 | tc | ||
| 130 | }); | ||
| 131 | |||
| 132 | cases.add("hello world without libc", | ||
| 133 | \\const io = @import("std").io; | ||
| 134 | \\ | ||
| 135 | \\pub fn main() -> %void { | ||
| 136 | \\ %%io.stdout.printf("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a')); | ||
| 137 | \\} | ||
| 138 | , "Hello, world!\n0012 012 a\n"); | ||
| 139 | |||
| 140 | cases.addC("number literals", | ||
| 141 | \\const c = @cImport(@cInclude("stdio.h")); | ||
| 142 | \\ | ||
| 143 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | ||
| 144 | \\ _ = c.printf(c"0: %llu\n", | ||
| 145 | \\ u64(0)); | ||
| 146 | \\ _ = c.printf(c"320402575052271: %llu\n", | ||
| 147 | \\ u64(320402575052271)); | ||
| 148 | \\ _ = c.printf(c"0x01236789abcdef: %llu\n", | ||
| 149 | \\ u64(0x01236789abcdef)); | ||
| 150 | \\ _ = c.printf(c"0xffffffffffffffff: %llu\n", | ||
| 151 | \\ u64(0xffffffffffffffff)); | ||
| 152 | \\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n", | ||
| 153 | \\ u64(0x000000ffffffffffffffff)); | ||
| 154 | \\ _ = c.printf(c"0o1777777777777777777777: %llu\n", | ||
| 155 | \\ u64(0o1777777777777777777777)); | ||
| 156 | \\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n", | ||
| 157 | \\ u64(0o0000001777777777777777777777)); | ||
| 158 | \\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", | ||
| 159 | \\ u64(0b1111111111111111111111111111111111111111111111111111111111111111)); | ||
| 160 | \\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", | ||
| 161 | \\ u64(0b0000001111111111111111111111111111111111111111111111111111111111111111)); | ||
| 162 | \\ | ||
| 163 | \\ _ = c.printf(c"\n"); | ||
| 164 | \\ | ||
| 165 | \\ _ = c.printf(c"0.0: %a\n", | ||
| 166 | \\ f64(0.0)); | ||
| 167 | \\ _ = c.printf(c"0e0: %a\n", | ||
| 168 | \\ f64(0e0)); | ||
| 169 | \\ _ = c.printf(c"0.0e0: %a\n", | ||
| 170 | \\ f64(0.0e0)); | ||
| 171 | \\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n", | ||
| 172 | \\ f64(000000000000000000000000000000000000000000000000000000000.0e0)); | ||
| 173 | \\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n", | ||
| 174 | \\ f64(0.000000000000000000000000000000000000000000000000000000000e0)); | ||
| 175 | \\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n", | ||
| 176 | \\ f64(0.0e000000000000000000000000000000000000000000000000000000000)); | ||
| 177 | \\ _ = c.printf(c"1.0: %a\n", | ||
| 178 | \\ f64(1.0)); | ||
| 179 | \\ _ = c.printf(c"10.0: %a\n", | ||
| 180 | \\ f64(10.0)); | ||
| 181 | \\ _ = c.printf(c"10.5: %a\n", | ||
| 182 | \\ f64(10.5)); | ||
| 183 | \\ _ = c.printf(c"10.5e5: %a\n", | ||
| 184 | \\ f64(10.5e5)); | ||
| 185 | \\ _ = c.printf(c"10.5e+5: %a\n", | ||
| 186 | \\ f64(10.5e+5)); | ||
| 187 | \\ _ = c.printf(c"50.0e-2: %a\n", | ||
| 188 | \\ f64(50.0e-2)); | ||
| 189 | \\ _ = c.printf(c"50e-2: %a\n", | ||
| 190 | \\ f64(50e-2)); | ||
| 191 | \\ | ||
| 192 | \\ _ = c.printf(c"\n"); | ||
| 193 | \\ | ||
| 194 | \\ _ = c.printf(c"0x1.0: %a\n", | ||
| 195 | \\ f64(0x1.0)); | ||
| 196 | \\ _ = c.printf(c"0x10.0: %a\n", | ||
| 197 | \\ f64(0x10.0)); | ||
| 198 | \\ _ = c.printf(c"0x100.0: %a\n", | ||
| 199 | \\ f64(0x100.0)); | ||
| 200 | \\ _ = c.printf(c"0x103.0: %a\n", | ||
| 201 | \\ f64(0x103.0)); | ||
| 202 | \\ _ = c.printf(c"0x103.7: %a\n", | ||
| 203 | \\ f64(0x103.7)); | ||
| 204 | \\ _ = c.printf(c"0x103.70: %a\n", | ||
| 205 | \\ f64(0x103.70)); | ||
| 206 | \\ _ = c.printf(c"0x103.70p4: %a\n", | ||
| 207 | \\ f64(0x103.70p4)); | ||
| 208 | \\ _ = c.printf(c"0x103.70p5: %a\n", | ||
| 209 | \\ f64(0x103.70p5)); | ||
| 210 | \\ _ = c.printf(c"0x103.70p+5: %a\n", | ||
| 211 | \\ f64(0x103.70p+5)); | ||
| 212 | \\ _ = c.printf(c"0x103.70p-5: %a\n", | ||
| 213 | \\ f64(0x103.70p-5)); | ||
| 214 | \\ | ||
| 215 | \\ _ = c.printf(c"\n"); | ||
| 216 | \\ | ||
| 217 | \\ _ = c.printf(c"0b10100.00010e0: %a\n", | ||
| 218 | \\ f64(0b10100.00010e0)); | ||
| 219 | \\ _ = c.printf(c"0o10700.00010e0: %a\n", | ||
| 220 | \\ f64(0o10700.00010e0)); | ||
| 221 | \\ | ||
| 222 | \\ return 0; | ||
| 223 | \\} | ||
| 224 | , | ||
| 225 | \\0: 0 | ||
| 226 | \\320402575052271: 320402575052271 | ||
| 227 | \\0x01236789abcdef: 320402575052271 | ||
| 228 | \\0xffffffffffffffff: 18446744073709551615 | ||
| 229 | \\0x000000ffffffffffffffff: 18446744073709551615 | ||
| 230 | \\0o1777777777777777777777: 18446744073709551615 | ||
| 231 | \\0o0000001777777777777777777777: 18446744073709551615 | ||
| 232 | \\0b1111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 | ||
| 233 | \\0b0000001111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 | ||
| 234 | \\ | ||
| 235 | \\0.0: 0x0p+0 | ||
| 236 | \\0e0: 0x0p+0 | ||
| 237 | \\0.0e0: 0x0p+0 | ||
| 238 | \\000000000000000000000000000000000000000000000000000000000.0e0: 0x0p+0 | ||
| 239 | \\0.000000000000000000000000000000000000000000000000000000000e0: 0x0p+0 | ||
| 240 | \\0.0e000000000000000000000000000000000000000000000000000000000: 0x0p+0 | ||
| 241 | \\1.0: 0x1p+0 | ||
| 242 | \\10.0: 0x1.4p+3 | ||
| 243 | \\10.5: 0x1.5p+3 | ||
| 244 | \\10.5e5: 0x1.0059p+20 | ||
| 245 | \\10.5e+5: 0x1.0059p+20 | ||
| 246 | \\50.0e-2: 0x1p-1 | ||
| 247 | \\50e-2: 0x1p-1 | ||
| 248 | \\ | ||
| 249 | \\0x1.0: 0x1p+0 | ||
| 250 | \\0x10.0: 0x1p+4 | ||
| 251 | \\0x100.0: 0x1p+8 | ||
| 252 | \\0x103.0: 0x1.03p+8 | ||
| 253 | \\0x103.7: 0x1.037p+8 | ||
| 254 | \\0x103.70: 0x1.037p+8 | ||
| 255 | \\0x103.70p4: 0x1.037p+12 | ||
| 256 | \\0x103.70p5: 0x1.037p+13 | ||
| 257 | \\0x103.70p+5: 0x1.037p+13 | ||
| 258 | \\0x103.70p-5: 0x1.037p+3 | ||
| 259 | \\ | ||
| 260 | \\0b10100.00010e0: 0x1.41p+4 | ||
| 261 | \\0o10700.00010e0: 0x1.1c0001p+12 | ||
| 262 | \\ | ||
| 263 | ); | ||
| 264 | |||
| 265 | cases.add("order-independent declarations", | ||
| 266 | \\const io = @import("std").io; | ||
| 267 | \\const z = io.stdin_fileno; | ||
| 268 | \\const x : @typeOf(y) = 1234; | ||
| 269 | \\const y : u16 = 5678; | ||
| 270 | \\pub fn main() -> %void { | ||
| 271 | \\ var x_local : i32 = print_ok(x); | ||
| 272 | \\} | ||
| 273 | \\fn print_ok(val: @typeOf(x)) -> @typeOf(foo) { | ||
| 274 | \\ %%io.stdout.printf("OK\n"); | ||
| 275 | \\ return 0; | ||
| 276 | \\} | ||
| 277 | \\const foo : i32 = 0; | ||
| 278 | , "OK\n"); | ||
| 279 | |||
| 280 | cases.addC("expose function pointer to C land", | ||
| 281 | \\const c = @cImport(@cInclude("stdlib.h")); | ||
| 282 | \\ | ||
| 283 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { | ||
| 284 | \\ const a_int = @ptrcast(&i32, a ?? unreachable); | ||
| 285 | \\ const b_int = @ptrcast(&i32, b ?? unreachable); | ||
| 286 | \\ if (*a_int < *b_int) { | ||
| 287 | \\ -1 | ||
| 288 | \\ } else if (*a_int > *b_int) { | ||
| 289 | \\ 1 | ||
| 290 | \\ } else { | ||
| 291 | \\ c_int(0) | ||
| 292 | \\ } | ||
| 293 | \\} | ||
| 294 | \\ | ||
| 295 | \\export fn main() -> c_int { | ||
| 296 | \\ var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; | ||
| 297 | \\ | ||
| 298 | \\ c.qsort(@ptrcast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); | ||
| 299 | \\ | ||
| 300 | \\ for (array) |item, i| { | ||
| 301 | \\ if (item != i) { | ||
| 302 | \\ c.abort(); | ||
| 303 | \\ } | ||
| 304 | \\ } | ||
| 305 | \\ | ||
| 306 | \\ return 0; | ||
| 307 | \\} | ||
| 308 | , ""); | ||
| 309 | |||
| 310 | cases.addC("casting between float and integer types", | ||
| 311 | \\const c = @cImport(@cInclude("stdio.h")); | ||
| 312 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | ||
| 313 | \\ const small: f32 = 3.25; | ||
| 314 | \\ const x: f64 = small; | ||
| 315 | \\ const y = i32(x); | ||
| 316 | \\ const z = f64(y); | ||
| 317 | \\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); | ||
| 318 | \\ return 0; | ||
| 319 | \\} | ||
| 320 | , "3.25\n3\n3.00\n-0.40\n"); | ||
| 321 | |||
| 322 | cases.add("same named methods in incomplete struct", | ||
| 323 | \\const io = @import("std").io; | ||
| 324 | \\ | ||
| 325 | \\const Foo = struct { | ||
| 326 | \\ field1: Bar, | ||
| 327 | \\ | ||
| 328 | \\ fn method(a: &const Foo) -> bool { true } | ||
| 329 | \\}; | ||
| 330 | \\ | ||
| 331 | \\const Bar = struct { | ||
| 332 | \\ field2: i32, | ||
| 333 | \\ | ||
| 334 | \\ fn method(b: &const Bar) -> bool { true } | ||
| 335 | \\}; | ||
| 336 | \\ | ||
| 337 | \\pub fn main() -> %void { | ||
| 338 | \\ const bar = Bar {.field2 = 13,}; | ||
| 339 | \\ const foo = Foo {.field1 = bar,}; | ||
| 340 | \\ if (!foo.method()) { | ||
| 341 | \\ %%io.stdout.printf("BAD\n"); | ||
| 342 | \\ } | ||
| 343 | \\ if (!bar.method()) { | ||
| 344 | \\ %%io.stdout.printf("BAD\n"); | ||
| 345 | \\ } | ||
| 346 | \\ %%io.stdout.printf("OK\n"); | ||
| 347 | \\} | ||
| 348 | , "OK\n"); | ||
| 349 | |||
| 350 | cases.add("defer with only fallthrough", | ||
| 351 | \\const io = @import("std").io; | ||
| 352 | \\pub fn main() -> %void { | ||
| 353 | \\ %%io.stdout.printf("before\n"); | ||
| 354 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 355 | \\ defer %%io.stdout.printf("defer2\n"); | ||
| 356 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 357 | \\ %%io.stdout.printf("after\n"); | ||
| 358 | \\} | ||
| 359 | , "before\nafter\ndefer3\ndefer2\ndefer1\n"); | ||
| 360 | |||
| 361 | cases.add("defer with return", | ||
| 362 | \\const io = @import("std").io; | ||
| 363 | \\const os = @import("std").os; | ||
| 364 | \\pub fn main() -> %void { | ||
| 365 | \\ %%io.stdout.printf("before\n"); | ||
| 366 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 367 | \\ defer %%io.stdout.printf("defer2\n"); | ||
| 368 | \\ if (os.args.count() == 1) return; | ||
| 369 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 370 | \\ %%io.stdout.printf("after\n"); | ||
| 371 | \\} | ||
| 372 | , "before\ndefer2\ndefer1\n"); | ||
| 373 | |||
| 374 | cases.add("%defer and it fails", | ||
| 375 | \\const io = @import("std").io; | ||
| 376 | \\pub fn main() -> %void { | ||
| 377 | \\ do_test() %% return; | ||
| 378 | \\} | ||
| 379 | \\fn do_test() -> %void { | ||
| 380 | \\ %%io.stdout.printf("before\n"); | ||
| 381 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 382 | \\ %defer %%io.stdout.printf("deferErr\n"); | ||
| 383 | \\ %return its_gonna_fail(); | ||
| 384 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 385 | \\ %%io.stdout.printf("after\n"); | ||
| 386 | \\} | ||
| 387 | \\error IToldYouItWouldFail; | ||
| 388 | \\fn its_gonna_fail() -> %void { | ||
| 389 | \\ return error.IToldYouItWouldFail; | ||
| 390 | \\} | ||
| 391 | , "before\ndeferErr\ndefer1\n"); | ||
| 392 | |||
| 393 | cases.add("%defer and it passes", | ||
| 394 | \\const io = @import("std").io; | ||
| 395 | \\pub fn main() -> %void { | ||
| 396 | \\ do_test() %% return; | ||
| 397 | \\} | ||
| 398 | \\fn do_test() -> %void { | ||
| 399 | \\ %%io.stdout.printf("before\n"); | ||
| 400 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 401 | \\ %defer %%io.stdout.printf("deferErr\n"); | ||
| 402 | \\ %return its_gonna_pass(); | ||
| 403 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 404 | \\ %%io.stdout.printf("after\n"); | ||
| 405 | \\} | ||
| 406 | \\fn its_gonna_pass() -> %void { } | ||
| 407 | , "before\nafter\ndefer3\ndefer1\n"); | ||
| 408 | |||
| 409 | cases.addCase({ | ||
| 410 | var tc = cases.create("@embedFile", | ||
| 411 | \\const foo_txt = @embedFile("foo.txt"); | ||
| 412 | \\const io = @import("std").io; | ||
| 413 | \\ | ||
| 414 | \\pub fn main() -> %void { | ||
| 415 | \\ %%io.stdout.printf(foo_txt); | ||
| 416 | \\} | ||
| 417 | , "1234\nabcd\n"); | ||
| 418 | |||
| 419 | tc.addSourceFile("foo.txt", "1234\nabcd\n"); | ||
| 420 | |||
| 421 | tc | ||
| 422 | }); | ||
| 423 | |||
| 424 | return cases.compare_output_tests; | ||
| 425 | } | ||
| 426 | |||
| 427 | const CompareOutputContext = struct { | ||
| 428 | b: &build.Builder, | ||
| 429 | compare_output_tests: &build.Step, | ||
| 430 | test_index: usize, | ||
| 431 | test_filter: ?[]const u8, | ||
| 432 | |||
| 433 | const TestCase = struct { | ||
| 434 | name: []const u8, | ||
| 435 | sources: List(SourceFile), | ||
| 436 | expected_output: []const u8, | ||
| 437 | link_libc: bool, | ||
| 438 | |||
| 439 | const SourceFile = struct { | ||
| 440 | filename: []const u8, | ||
| 441 | source: []const u8, | ||
| 442 | }; | ||
| 443 | |||
| 444 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) { | ||
| 445 | %%self.sources.append(SourceFile { | ||
| 446 | .filename = filename, | ||
| 447 | .source = source, | ||
| 448 | }); | ||
| 449 | } | ||
| 450 | }; | ||
| 451 | |||
| 452 | pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, | ||
| 453 | expected_output: []const u8) -> TestCase | ||
| 454 | { | ||
| 455 | var tc = TestCase { | ||
| 456 | .name = name, | ||
| 457 | .sources = List(TestCase.SourceFile).init(self.b.allocator), | ||
| 458 | .expected_output = expected_output, | ||
| 459 | .link_libc = false, | ||
| 460 | }; | ||
| 461 | tc.addSourceFile("source.zig", source); | ||
| 462 | return tc; | ||
| 463 | } | ||
| 464 | |||
| 465 | pub fn addC(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | ||
| 466 | var tc = self.create(name, source, expected_output); | ||
| 467 | tc.link_libc = true; | ||
| 468 | self.addCase(tc); | ||
| 469 | } | ||
| 470 | |||
| 471 | pub fn add(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | ||
| 472 | const tc = self.create(name, source, expected_output); | ||
| 473 | self.addCase(tc); | ||
| 474 | } | ||
| 475 | |||
| 476 | pub fn addCase(self: &CompareOutputContext, case: &const TestCase) { | ||
| 477 | const b = self.b; | ||
| 478 | |||
| 479 | const root_src = %%os.path.join(b.allocator, "test_artifacts", case.sources.items[0].filename); | ||
| 480 | const exe_path = %%os.path.join(b.allocator, "test_artifacts", "test"); | ||
| 481 | |||
| 482 | for ([]bool{false, true}) |release| { | ||
| 483 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} ({})", | ||
| 484 | case.name, if (release) "release" else "debug"); | ||
| 485 | if (const filter ?= self.test_filter) { | ||
| 486 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | ||
| 487 | continue; | ||
| 488 | } | ||
| 489 | |||
| 490 | const exe = b.addExecutable("test", root_src); | ||
| 491 | exe.setOutputPath(exe_path); | ||
| 492 | exe.setRelease(release); | ||
| 493 | if (case.link_libc) { | ||
| 494 | exe.linkLibrary("c"); | ||
| 495 | } | ||
| 496 | |||
| 497 | for (case.sources.toSliceConst()) |src_file| { | ||
| 498 | const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename); | ||
| 499 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | ||
| 500 | exe.step.dependOn(&write_src.step); | ||
| 501 | } | ||
| 502 | |||
| 503 | const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name, | ||
| 504 | case.expected_output); | ||
| 505 | run_and_cmp_output.step.dependOn(&exe.step); | ||
| 506 | |||
| 507 | self.compare_output_tests.dependOn(&run_and_cmp_output.step); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | }; | ||
| 511 | |||
| 512 | const RunCompareOutputStep = struct { | ||
| 513 | step: build.Step, | ||
| 514 | context: &CompareOutputContext, | ||
| 515 | exe_path: []const u8, | ||
| 516 | name: []const u8, | ||
| 517 | expected_output: []const u8, | ||
| 518 | test_index: usize, | ||
| 519 | |||
| 520 | pub fn create(context: &CompareOutputContext, exe_path: []const u8, | ||
| 521 | name: []const u8, expected_output: []const u8) -> &RunCompareOutputStep | ||
| 522 | { | ||
| 523 | const allocator = context.b.allocator; | ||
| 524 | const ptr = %%allocator.create(RunCompareOutputStep); | ||
| 525 | *ptr = RunCompareOutputStep { | ||
| 526 | .context = context, | ||
| 527 | .exe_path = exe_path, | ||
| 528 | .name = name, | ||
| 529 | .expected_output = expected_output, | ||
| 530 | .test_index = context.test_index, | ||
| 531 | .step = build.Step.init("RunCompareOutput", allocator, make), | ||
| 532 | }; | ||
| 533 | context.test_index += 1; | ||
| 534 | return ptr; | ||
| 535 | } | ||
| 536 | |||
| 537 | fn make(step: &build.Step) -> %void { | ||
| 538 | const self = @fieldParentPtr(RunCompareOutputStep, "step", step); | ||
| 539 | const b = self.context.b; | ||
| 540 | |||
| 541 | const full_exe_path = b.pathFromRoot(self.exe_path); | ||
| 542 | |||
| 543 | %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); | ||
| 544 | |||
| 545 | var child = os.ChildProcess.spawn(full_exe_path, [][]u8{}, &b.env_map, | ||
| 546 | StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err| | ||
| 547 | { | ||
| 548 | debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err)); | ||
| 549 | }; | ||
| 550 | |||
| 551 | const term = child.wait() %% |err| { | ||
| 552 | debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err)); | ||
| 553 | }; | ||
| 554 | switch (term) { | ||
| 555 | Term.Clean => |code| { | ||
| 556 | if (code != 0) { | ||
| 557 | %%io.stderr.printf("Process {} exited with error code {}\n", full_exe_path, code); | ||
| 558 | return error.TestFailed; | ||
| 559 | } | ||
| 560 | }, | ||
| 561 | else => { | ||
| 562 | %%io.stderr.printf("Process {} terminated unexpectedly\n", full_exe_path); | ||
| 563 | return error.TestFailed; | ||
| 564 | }, | ||
| 565 | }; | ||
| 566 | |||
| 567 | var stdout = %%Buffer0.initEmpty(b.allocator); | ||
| 568 | var stderr = %%Buffer0.initEmpty(b.allocator); | ||
| 569 | |||
| 570 | %%(??child.stdout).readAll(&stdout); | ||
| 571 | %%(??child.stderr).readAll(&stderr); | ||
| 572 | |||
| 573 | if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) { | ||
| 574 | %%io.stderr.printf( | ||
| 575 | \\ | ||
| 576 | \\========= Expected this output: ========= | ||
| 577 | \\{} | ||
| 578 | \\================================================ | ||
| 579 | \\{} | ||
| 580 | \\ | ||
| 581 | , self.expected_output, stdout.toSliceConst()); | ||
| 582 | return error.TestFailed; | ||
| 583 | } | ||
| 584 | %%io.stderr.printf("OK\n"); | ||
| 585 | } | ||
| 586 | }; | ||
| 587 | |||
test/run_tests.cpp-8| ... | @@ -272,13 +272,6 @@ static TestCase *add_example_compile_libc(const char *root_source_file) { | ... | @@ -272,13 +272,6 @@ static TestCase *add_example_compile_libc(const char *root_source_file) { |
| 272 | 272 | ||
| 273 | //////////////////////////////////////////////////////////////////////////////////// | 273 | //////////////////////////////////////////////////////////////////////////////////// |
| 274 | 274 | ||
| 275 | static void add_build_examples(void) { | ||
| 276 | add_example_compile("example/hello_world/hello.zig"); | ||
| 277 | add_example_compile_libc("example/hello_world/hello_libc.zig"); | ||
| 278 | add_example_compile("example/cat/main.zig"); | ||
| 279 | add_example_compile("example/guess_number/main.zig"); | ||
| 280 | } | ||
| 281 | |||
| 282 | 275 | ||
| 283 | //////////////////////////////////////////////////////////////////////////////////// | 276 | //////////////////////////////////////////////////////////////////////////////////// |
| 284 | 277 | ||
| ... | @@ -2615,7 +2608,6 @@ int main(int argc, char **argv) { | ... | @@ -2615,7 +2608,6 @@ int main(int argc, char **argv) { |
| 2615 | } | 2608 | } |
| 2616 | } | 2609 | } |
| 2617 | } | 2610 | } |
| 2618 | add_build_examples(); | ||
| 2619 | add_debug_safety_test_cases(); | 2611 | add_debug_safety_test_cases(); |
| 2620 | add_compile_failure_test_cases(); | 2612 | add_compile_failure_test_cases(); |
| 2621 | add_parse_error_tests(); | 2613 | add_parse_error_tests(); |
test/tests.zig+2-587| ... | @@ -1,587 +1,2 @@ | ... | @@ -1,587 +1,2 @@ |
| 1 | const std = @import("std"); | 1 | pub const addCompareOutputTests = @import("compare_output.zig").addCompareOutputTests; |
| 2 | const debug = std.debug; | 2 | pub const addBuildExampleTests = @import("build_examples.zig").addBuildExampleTests; |
| 3 | const build = std.build; | ||
| 4 | const os = std.os; | ||
| 5 | const StdIo = os.ChildProcess.StdIo; | ||
| 6 | const Term = os.ChildProcess.Term; | ||
| 7 | const Buffer0 = std.cstr.Buffer0; | ||
| 8 | const io = std.io; | ||
| 9 | const mem = std.mem; | ||
| 10 | const fmt = std.fmt; | ||
| 11 | const List = std.list.List; | ||
| 12 | |||
| 13 | error TestFailed; | ||
| 14 | |||
| 15 | pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | ||
| 16 | const cases = %%b.allocator.create(CompareOutputContext); | ||
| 17 | *cases = CompareOutputContext { | ||
| 18 | .b = b, | ||
| 19 | .compare_output_tests = b.step("test-compare-output", "Run the compare output tests"), | ||
| 20 | .test_index = 0, | ||
| 21 | .test_filter = test_filter, | ||
| 22 | }; | ||
| 23 | |||
| 24 | cases.addC("hello world with libc", | ||
| 25 | \\const c = @cImport(@cInclude("stdio.h")); | ||
| 26 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | ||
| 27 | \\ _ = c.puts(c"Hello, world!"); | ||
| 28 | \\ return 0; | ||
| 29 | \\} | ||
| 30 | , "Hello, world!" ++ os.line_sep); | ||
| 31 | |||
| 32 | cases.addCase({ | ||
| 33 | var tc = cases.create("multiple files with private function", | ||
| 34 | \\use @import("std").io; | ||
| 35 | \\use @import("foo.zig"); | ||
| 36 | \\ | ||
| 37 | \\pub fn main() -> %void { | ||
| 38 | \\ privateFunction(); | ||
| 39 | \\ %%stdout.printf("OK 2\n"); | ||
| 40 | \\} | ||
| 41 | \\ | ||
| 42 | \\fn privateFunction() { | ||
| 43 | \\ printText(); | ||
| 44 | \\} | ||
| 45 | , "OK 1\nOK 2\n"); | ||
| 46 | |||
| 47 | tc.addSourceFile("foo.zig", | ||
| 48 | \\use @import("std").io; | ||
| 49 | \\ | ||
| 50 | \\// purposefully conflicting function with main.zig | ||
| 51 | \\// but it's private so it should be OK | ||
| 52 | \\fn privateFunction() { | ||
| 53 | \\ %%stdout.printf("OK 1\n"); | ||
| 54 | \\} | ||
| 55 | \\ | ||
| 56 | \\pub fn printText() { | ||
| 57 | \\ privateFunction(); | ||
| 58 | \\} | ||
| 59 | ); | ||
| 60 | |||
| 61 | tc | ||
| 62 | }); | ||
| 63 | |||
| 64 | cases.addCase({ | ||
| 65 | var tc = cases.create("import segregation", | ||
| 66 | \\use @import("foo.zig"); | ||
| 67 | \\use @import("bar.zig"); | ||
| 68 | \\ | ||
| 69 | \\pub fn main() -> %void { | ||
| 70 | \\ foo_function(); | ||
| 71 | \\ bar_function(); | ||
| 72 | \\} | ||
| 73 | , "OK\nOK\n"); | ||
| 74 | |||
| 75 | tc.addSourceFile("foo.zig", | ||
| 76 | \\use @import("std").io; | ||
| 77 | \\pub fn foo_function() { | ||
| 78 | \\ %%stdout.printf("OK\n"); | ||
| 79 | \\} | ||
| 80 | ); | ||
| 81 | |||
| 82 | tc.addSourceFile("bar.zig", | ||
| 83 | \\use @import("other.zig"); | ||
| 84 | \\use @import("std").io; | ||
| 85 | \\ | ||
| 86 | \\pub fn bar_function() { | ||
| 87 | \\ if (foo_function()) { | ||
| 88 | \\ %%stdout.printf("OK\n"); | ||
| 89 | \\ } | ||
| 90 | \\} | ||
| 91 | ); | ||
| 92 | |||
| 93 | tc.addSourceFile("other.zig", | ||
| 94 | \\pub fn foo_function() -> bool { | ||
| 95 | \\ // this one conflicts with the one from foo | ||
| 96 | \\ return true; | ||
| 97 | \\} | ||
| 98 | ); | ||
| 99 | |||
| 100 | tc | ||
| 101 | }); | ||
| 102 | |||
| 103 | cases.addCase({ | ||
| 104 | var tc = cases.create("two files use import each other", | ||
| 105 | \\use @import("a.zig"); | ||
| 106 | \\ | ||
| 107 | \\pub fn main() -> %void { | ||
| 108 | \\ ok(); | ||
| 109 | \\} | ||
| 110 | , "OK\n"); | ||
| 111 | |||
| 112 | tc.addSourceFile("a.zig", | ||
| 113 | \\use @import("b.zig"); | ||
| 114 | \\const io = @import("std").io; | ||
| 115 | \\ | ||
| 116 | \\pub const a_text = "OK\n"; | ||
| 117 | \\ | ||
| 118 | \\pub fn ok() { | ||
| 119 | \\ %%io.stdout.printf(b_text); | ||
| 120 | \\} | ||
| 121 | ); | ||
| 122 | |||
| 123 | tc.addSourceFile("b.zig", | ||
| 124 | \\use @import("a.zig"); | ||
| 125 | \\ | ||
| 126 | \\pub const b_text = a_text; | ||
| 127 | ); | ||
| 128 | |||
| 129 | tc | ||
| 130 | }); | ||
| 131 | |||
| 132 | cases.add("hello world without libc", | ||
| 133 | \\const io = @import("std").io; | ||
| 134 | \\ | ||
| 135 | \\pub fn main() -> %void { | ||
| 136 | \\ %%io.stdout.printf("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a')); | ||
| 137 | \\} | ||
| 138 | , "Hello, world!\n0012 012 a\n"); | ||
| 139 | |||
| 140 | cases.addC("number literals", | ||
| 141 | \\const c = @cImport(@cInclude("stdio.h")); | ||
| 142 | \\ | ||
| 143 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | ||
| 144 | \\ _ = c.printf(c"0: %llu\n", | ||
| 145 | \\ u64(0)); | ||
| 146 | \\ _ = c.printf(c"320402575052271: %llu\n", | ||
| 147 | \\ u64(320402575052271)); | ||
| 148 | \\ _ = c.printf(c"0x01236789abcdef: %llu\n", | ||
| 149 | \\ u64(0x01236789abcdef)); | ||
| 150 | \\ _ = c.printf(c"0xffffffffffffffff: %llu\n", | ||
| 151 | \\ u64(0xffffffffffffffff)); | ||
| 152 | \\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n", | ||
| 153 | \\ u64(0x000000ffffffffffffffff)); | ||
| 154 | \\ _ = c.printf(c"0o1777777777777777777777: %llu\n", | ||
| 155 | \\ u64(0o1777777777777777777777)); | ||
| 156 | \\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n", | ||
| 157 | \\ u64(0o0000001777777777777777777777)); | ||
| 158 | \\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", | ||
| 159 | \\ u64(0b1111111111111111111111111111111111111111111111111111111111111111)); | ||
| 160 | \\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", | ||
| 161 | \\ u64(0b0000001111111111111111111111111111111111111111111111111111111111111111)); | ||
| 162 | \\ | ||
| 163 | \\ _ = c.printf(c"\n"); | ||
| 164 | \\ | ||
| 165 | \\ _ = c.printf(c"0.0: %a\n", | ||
| 166 | \\ f64(0.0)); | ||
| 167 | \\ _ = c.printf(c"0e0: %a\n", | ||
| 168 | \\ f64(0e0)); | ||
| 169 | \\ _ = c.printf(c"0.0e0: %a\n", | ||
| 170 | \\ f64(0.0e0)); | ||
| 171 | \\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n", | ||
| 172 | \\ f64(000000000000000000000000000000000000000000000000000000000.0e0)); | ||
| 173 | \\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n", | ||
| 174 | \\ f64(0.000000000000000000000000000000000000000000000000000000000e0)); | ||
| 175 | \\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n", | ||
| 176 | \\ f64(0.0e000000000000000000000000000000000000000000000000000000000)); | ||
| 177 | \\ _ = c.printf(c"1.0: %a\n", | ||
| 178 | \\ f64(1.0)); | ||
| 179 | \\ _ = c.printf(c"10.0: %a\n", | ||
| 180 | \\ f64(10.0)); | ||
| 181 | \\ _ = c.printf(c"10.5: %a\n", | ||
| 182 | \\ f64(10.5)); | ||
| 183 | \\ _ = c.printf(c"10.5e5: %a\n", | ||
| 184 | \\ f64(10.5e5)); | ||
| 185 | \\ _ = c.printf(c"10.5e+5: %a\n", | ||
| 186 | \\ f64(10.5e+5)); | ||
| 187 | \\ _ = c.printf(c"50.0e-2: %a\n", | ||
| 188 | \\ f64(50.0e-2)); | ||
| 189 | \\ _ = c.printf(c"50e-2: %a\n", | ||
| 190 | \\ f64(50e-2)); | ||
| 191 | \\ | ||
| 192 | \\ _ = c.printf(c"\n"); | ||
| 193 | \\ | ||
| 194 | \\ _ = c.printf(c"0x1.0: %a\n", | ||
| 195 | \\ f64(0x1.0)); | ||
| 196 | \\ _ = c.printf(c"0x10.0: %a\n", | ||
| 197 | \\ f64(0x10.0)); | ||
| 198 | \\ _ = c.printf(c"0x100.0: %a\n", | ||
| 199 | \\ f64(0x100.0)); | ||
| 200 | \\ _ = c.printf(c"0x103.0: %a\n", | ||
| 201 | \\ f64(0x103.0)); | ||
| 202 | \\ _ = c.printf(c"0x103.7: %a\n", | ||
| 203 | \\ f64(0x103.7)); | ||
| 204 | \\ _ = c.printf(c"0x103.70: %a\n", | ||
| 205 | \\ f64(0x103.70)); | ||
| 206 | \\ _ = c.printf(c"0x103.70p4: %a\n", | ||
| 207 | \\ f64(0x103.70p4)); | ||
| 208 | \\ _ = c.printf(c"0x103.70p5: %a\n", | ||
| 209 | \\ f64(0x103.70p5)); | ||
| 210 | \\ _ = c.printf(c"0x103.70p+5: %a\n", | ||
| 211 | \\ f64(0x103.70p+5)); | ||
| 212 | \\ _ = c.printf(c"0x103.70p-5: %a\n", | ||
| 213 | \\ f64(0x103.70p-5)); | ||
| 214 | \\ | ||
| 215 | \\ _ = c.printf(c"\n"); | ||
| 216 | \\ | ||
| 217 | \\ _ = c.printf(c"0b10100.00010e0: %a\n", | ||
| 218 | \\ f64(0b10100.00010e0)); | ||
| 219 | \\ _ = c.printf(c"0o10700.00010e0: %a\n", | ||
| 220 | \\ f64(0o10700.00010e0)); | ||
| 221 | \\ | ||
| 222 | \\ return 0; | ||
| 223 | \\} | ||
| 224 | , | ||
| 225 | \\0: 0 | ||
| 226 | \\320402575052271: 320402575052271 | ||
| 227 | \\0x01236789abcdef: 320402575052271 | ||
| 228 | \\0xffffffffffffffff: 18446744073709551615 | ||
| 229 | \\0x000000ffffffffffffffff: 18446744073709551615 | ||
| 230 | \\0o1777777777777777777777: 18446744073709551615 | ||
| 231 | \\0o0000001777777777777777777777: 18446744073709551615 | ||
| 232 | \\0b1111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 | ||
| 233 | \\0b0000001111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 | ||
| 234 | \\ | ||
| 235 | \\0.0: 0x0p+0 | ||
| 236 | \\0e0: 0x0p+0 | ||
| 237 | \\0.0e0: 0x0p+0 | ||
| 238 | \\000000000000000000000000000000000000000000000000000000000.0e0: 0x0p+0 | ||
| 239 | \\0.000000000000000000000000000000000000000000000000000000000e0: 0x0p+0 | ||
| 240 | \\0.0e000000000000000000000000000000000000000000000000000000000: 0x0p+0 | ||
| 241 | \\1.0: 0x1p+0 | ||
| 242 | \\10.0: 0x1.4p+3 | ||
| 243 | \\10.5: 0x1.5p+3 | ||
| 244 | \\10.5e5: 0x1.0059p+20 | ||
| 245 | \\10.5e+5: 0x1.0059p+20 | ||
| 246 | \\50.0e-2: 0x1p-1 | ||
| 247 | \\50e-2: 0x1p-1 | ||
| 248 | \\ | ||
| 249 | \\0x1.0: 0x1p+0 | ||
| 250 | \\0x10.0: 0x1p+4 | ||
| 251 | \\0x100.0: 0x1p+8 | ||
| 252 | \\0x103.0: 0x1.03p+8 | ||
| 253 | \\0x103.7: 0x1.037p+8 | ||
| 254 | \\0x103.70: 0x1.037p+8 | ||
| 255 | \\0x103.70p4: 0x1.037p+12 | ||
| 256 | \\0x103.70p5: 0x1.037p+13 | ||
| 257 | \\0x103.70p+5: 0x1.037p+13 | ||
| 258 | \\0x103.70p-5: 0x1.037p+3 | ||
| 259 | \\ | ||
| 260 | \\0b10100.00010e0: 0x1.41p+4 | ||
| 261 | \\0o10700.00010e0: 0x1.1c0001p+12 | ||
| 262 | \\ | ||
| 263 | ); | ||
| 264 | |||
| 265 | cases.add("order-independent declarations", | ||
| 266 | \\const io = @import("std").io; | ||
| 267 | \\const z = io.stdin_fileno; | ||
| 268 | \\const x : @typeOf(y) = 1234; | ||
| 269 | \\const y : u16 = 5678; | ||
| 270 | \\pub fn main() -> %void { | ||
| 271 | \\ var x_local : i32 = print_ok(x); | ||
| 272 | \\} | ||
| 273 | \\fn print_ok(val: @typeOf(x)) -> @typeOf(foo) { | ||
| 274 | \\ %%io.stdout.printf("OK\n"); | ||
| 275 | \\ return 0; | ||
| 276 | \\} | ||
| 277 | \\const foo : i32 = 0; | ||
| 278 | , "OK\n"); | ||
| 279 | |||
| 280 | cases.addC("expose function pointer to C land", | ||
| 281 | \\const c = @cImport(@cInclude("stdlib.h")); | ||
| 282 | \\ | ||
| 283 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { | ||
| 284 | \\ const a_int = @ptrcast(&i32, a ?? unreachable); | ||
| 285 | \\ const b_int = @ptrcast(&i32, b ?? unreachable); | ||
| 286 | \\ if (*a_int < *b_int) { | ||
| 287 | \\ -1 | ||
| 288 | \\ } else if (*a_int > *b_int) { | ||
| 289 | \\ 1 | ||
| 290 | \\ } else { | ||
| 291 | \\ c_int(0) | ||
| 292 | \\ } | ||
| 293 | \\} | ||
| 294 | \\ | ||
| 295 | \\export fn main() -> c_int { | ||
| 296 | \\ var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; | ||
| 297 | \\ | ||
| 298 | \\ c.qsort(@ptrcast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); | ||
| 299 | \\ | ||
| 300 | \\ for (array) |item, i| { | ||
| 301 | \\ if (item != i) { | ||
| 302 | \\ c.abort(); | ||
| 303 | \\ } | ||
| 304 | \\ } | ||
| 305 | \\ | ||
| 306 | \\ return 0; | ||
| 307 | \\} | ||
| 308 | , ""); | ||
| 309 | |||
| 310 | cases.addC("casting between float and integer types", | ||
| 311 | \\const c = @cImport(@cInclude("stdio.h")); | ||
| 312 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | ||
| 313 | \\ const small: f32 = 3.25; | ||
| 314 | \\ const x: f64 = small; | ||
| 315 | \\ const y = i32(x); | ||
| 316 | \\ const z = f64(y); | ||
| 317 | \\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); | ||
| 318 | \\ return 0; | ||
| 319 | \\} | ||
| 320 | , "3.25\n3\n3.00\n-0.40\n"); | ||
| 321 | |||
| 322 | cases.add("same named methods in incomplete struct", | ||
| 323 | \\const io = @import("std").io; | ||
| 324 | \\ | ||
| 325 | \\const Foo = struct { | ||
| 326 | \\ field1: Bar, | ||
| 327 | \\ | ||
| 328 | \\ fn method(a: &const Foo) -> bool { true } | ||
| 329 | \\}; | ||
| 330 | \\ | ||
| 331 | \\const Bar = struct { | ||
| 332 | \\ field2: i32, | ||
| 333 | \\ | ||
| 334 | \\ fn method(b: &const Bar) -> bool { true } | ||
| 335 | \\}; | ||
| 336 | \\ | ||
| 337 | \\pub fn main() -> %void { | ||
| 338 | \\ const bar = Bar {.field2 = 13,}; | ||
| 339 | \\ const foo = Foo {.field1 = bar,}; | ||
| 340 | \\ if (!foo.method()) { | ||
| 341 | \\ %%io.stdout.printf("BAD\n"); | ||
| 342 | \\ } | ||
| 343 | \\ if (!bar.method()) { | ||
| 344 | \\ %%io.stdout.printf("BAD\n"); | ||
| 345 | \\ } | ||
| 346 | \\ %%io.stdout.printf("OK\n"); | ||
| 347 | \\} | ||
| 348 | , "OK\n"); | ||
| 349 | |||
| 350 | cases.add("defer with only fallthrough", | ||
| 351 | \\const io = @import("std").io; | ||
| 352 | \\pub fn main() -> %void { | ||
| 353 | \\ %%io.stdout.printf("before\n"); | ||
| 354 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 355 | \\ defer %%io.stdout.printf("defer2\n"); | ||
| 356 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 357 | \\ %%io.stdout.printf("after\n"); | ||
| 358 | \\} | ||
| 359 | , "before\nafter\ndefer3\ndefer2\ndefer1\n"); | ||
| 360 | |||
| 361 | cases.add("defer with return", | ||
| 362 | \\const io = @import("std").io; | ||
| 363 | \\const os = @import("std").os; | ||
| 364 | \\pub fn main() -> %void { | ||
| 365 | \\ %%io.stdout.printf("before\n"); | ||
| 366 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 367 | \\ defer %%io.stdout.printf("defer2\n"); | ||
| 368 | \\ if (os.args.count() == 1) return; | ||
| 369 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 370 | \\ %%io.stdout.printf("after\n"); | ||
| 371 | \\} | ||
| 372 | , "before\ndefer2\ndefer1\n"); | ||
| 373 | |||
| 374 | cases.add("%defer and it fails", | ||
| 375 | \\const io = @import("std").io; | ||
| 376 | \\pub fn main() -> %void { | ||
| 377 | \\ do_test() %% return; | ||
| 378 | \\} | ||
| 379 | \\fn do_test() -> %void { | ||
| 380 | \\ %%io.stdout.printf("before\n"); | ||
| 381 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 382 | \\ %defer %%io.stdout.printf("deferErr\n"); | ||
| 383 | \\ %return its_gonna_fail(); | ||
| 384 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 385 | \\ %%io.stdout.printf("after\n"); | ||
| 386 | \\} | ||
| 387 | \\error IToldYouItWouldFail; | ||
| 388 | \\fn its_gonna_fail() -> %void { | ||
| 389 | \\ return error.IToldYouItWouldFail; | ||
| 390 | \\} | ||
| 391 | , "before\ndeferErr\ndefer1\n"); | ||
| 392 | |||
| 393 | cases.add("%defer and it passes", | ||
| 394 | \\const io = @import("std").io; | ||
| 395 | \\pub fn main() -> %void { | ||
| 396 | \\ do_test() %% return; | ||
| 397 | \\} | ||
| 398 | \\fn do_test() -> %void { | ||
| 399 | \\ %%io.stdout.printf("before\n"); | ||
| 400 | \\ defer %%io.stdout.printf("defer1\n"); | ||
| 401 | \\ %defer %%io.stdout.printf("deferErr\n"); | ||
| 402 | \\ %return its_gonna_pass(); | ||
| 403 | \\ defer %%io.stdout.printf("defer3\n"); | ||
| 404 | \\ %%io.stdout.printf("after\n"); | ||
| 405 | \\} | ||
| 406 | \\fn its_gonna_pass() -> %void { } | ||
| 407 | , "before\nafter\ndefer3\ndefer1\n"); | ||
| 408 | |||
| 409 | cases.addCase({ | ||
| 410 | var tc = cases.create("@embedFile", | ||
| 411 | \\const foo_txt = @embedFile("foo.txt"); | ||
| 412 | \\const io = @import("std").io; | ||
| 413 | \\ | ||
| 414 | \\pub fn main() -> %void { | ||
| 415 | \\ %%io.stdout.printf(foo_txt); | ||
| 416 | \\} | ||
| 417 | , "1234\nabcd\n"); | ||
| 418 | |||
| 419 | tc.addSourceFile("foo.txt", "1234\nabcd\n"); | ||
| 420 | |||
| 421 | tc | ||
| 422 | }); | ||
| 423 | |||
| 424 | return cases.compare_output_tests; | ||
| 425 | } | ||
| 426 | |||
| 427 | const CompareOutputContext = struct { | ||
| 428 | b: &build.Builder, | ||
| 429 | compare_output_tests: &build.Step, | ||
| 430 | test_index: usize, | ||
| 431 | test_filter: ?[]const u8, | ||
| 432 | |||
| 433 | const TestCase = struct { | ||
| 434 | name: []const u8, | ||
| 435 | sources: List(SourceFile), | ||
| 436 | expected_output: []const u8, | ||
| 437 | link_libc: bool, | ||
| 438 | |||
| 439 | const SourceFile = struct { | ||
| 440 | filename: []const u8, | ||
| 441 | source: []const u8, | ||
| 442 | }; | ||
| 443 | |||
| 444 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) { | ||
| 445 | %%self.sources.append(SourceFile { | ||
| 446 | .filename = filename, | ||
| 447 | .source = source, | ||
| 448 | }); | ||
| 449 | } | ||
| 450 | }; | ||
| 451 | |||
| 452 | pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, | ||
| 453 | expected_output: []const u8) -> TestCase | ||
| 454 | { | ||
| 455 | var tc = TestCase { | ||
| 456 | .name = name, | ||
| 457 | .sources = List(TestCase.SourceFile).init(self.b.allocator), | ||
| 458 | .expected_output = expected_output, | ||
| 459 | .link_libc = false, | ||
| 460 | }; | ||
| 461 | tc.addSourceFile("source.zig", source); | ||
| 462 | return tc; | ||
| 463 | } | ||
| 464 | |||
| 465 | pub fn addC(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | ||
| 466 | var tc = self.create(name, source, expected_output); | ||
| 467 | tc.link_libc = true; | ||
| 468 | self.addCase(tc); | ||
| 469 | } | ||
| 470 | |||
| 471 | pub fn add(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | ||
| 472 | const tc = self.create(name, source, expected_output); | ||
| 473 | self.addCase(tc); | ||
| 474 | } | ||
| 475 | |||
| 476 | pub fn addCase(self: &CompareOutputContext, case: &const TestCase) { | ||
| 477 | const b = self.b; | ||
| 478 | |||
| 479 | const root_src = %%os.path.join(b.allocator, "test_artifacts", case.sources.items[0].filename); | ||
| 480 | const exe_path = %%os.path.join(b.allocator, "test_artifacts", "test"); | ||
| 481 | |||
| 482 | for ([]bool{false, true}) |release| { | ||
| 483 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} ({})", | ||
| 484 | case.name, if (release) "release" else "debug"); | ||
| 485 | if (const filter ?= self.test_filter) { | ||
| 486 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | ||
| 487 | continue; | ||
| 488 | } | ||
| 489 | |||
| 490 | const exe = b.addExecutable("test", root_src); | ||
| 491 | exe.setOutputPath(exe_path); | ||
| 492 | exe.setRelease(release); | ||
| 493 | if (case.link_libc) { | ||
| 494 | exe.linkLibrary("c"); | ||
| 495 | } | ||
| 496 | |||
| 497 | for (case.sources.toSliceConst()) |src_file| { | ||
| 498 | const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename); | ||
| 499 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | ||
| 500 | exe.step.dependOn(&write_src.step); | ||
| 501 | } | ||
| 502 | |||
| 503 | const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name, | ||
| 504 | case.expected_output); | ||
| 505 | run_and_cmp_output.step.dependOn(&exe.step); | ||
| 506 | |||
| 507 | self.compare_output_tests.dependOn(&run_and_cmp_output.step); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | }; | ||
| 511 | |||
| 512 | const RunCompareOutputStep = struct { | ||
| 513 | step: build.Step, | ||
| 514 | context: &CompareOutputContext, | ||
| 515 | exe_path: []const u8, | ||
| 516 | name: []const u8, | ||
| 517 | expected_output: []const u8, | ||
| 518 | test_index: usize, | ||
| 519 | |||
| 520 | pub fn create(context: &CompareOutputContext, exe_path: []const u8, | ||
| 521 | name: []const u8, expected_output: []const u8) -> &RunCompareOutputStep | ||
| 522 | { | ||
| 523 | const allocator = context.b.allocator; | ||
| 524 | const ptr = %%allocator.create(RunCompareOutputStep); | ||
| 525 | *ptr = RunCompareOutputStep { | ||
| 526 | .context = context, | ||
| 527 | .exe_path = exe_path, | ||
| 528 | .name = name, | ||
| 529 | .expected_output = expected_output, | ||
| 530 | .test_index = context.test_index, | ||
| 531 | .step = build.Step.init("RunCompareOutput", allocator, make), | ||
| 532 | }; | ||
| 533 | context.test_index += 1; | ||
| 534 | return ptr; | ||
| 535 | } | ||
| 536 | |||
| 537 | fn make(step: &build.Step) -> %void { | ||
| 538 | const self = @fieldParentPtr(RunCompareOutputStep, "step", step); | ||
| 539 | const b = self.context.b; | ||
| 540 | |||
| 541 | const full_exe_path = b.pathFromRoot(self.exe_path); | ||
| 542 | |||
| 543 | %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); | ||
| 544 | |||
| 545 | var child = os.ChildProcess.spawn(full_exe_path, [][]u8{}, &b.env_map, | ||
| 546 | StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err| | ||
| 547 | { | ||
| 548 | debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err)); | ||
| 549 | }; | ||
| 550 | |||
| 551 | const term = child.wait() %% |err| { | ||
| 552 | debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err)); | ||
| 553 | }; | ||
| 554 | switch (term) { | ||
| 555 | Term.Clean => |code| { | ||
| 556 | if (code != 0) { | ||
| 557 | %%io.stderr.printf("Process {} exited with error code {}\n", full_exe_path, code); | ||
| 558 | return error.TestFailed; | ||
| 559 | } | ||
| 560 | }, | ||
| 561 | else => { | ||
| 562 | %%io.stderr.printf("Process {} terminated unexpectedly\n", full_exe_path); | ||
| 563 | return error.TestFailed; | ||
| 564 | }, | ||
| 565 | }; | ||
| 566 | |||
| 567 | var stdout = %%Buffer0.initEmpty(b.allocator); | ||
| 568 | var stderr = %%Buffer0.initEmpty(b.allocator); | ||
| 569 | |||
| 570 | %%(??child.stdout).readAll(&stdout); | ||
| 571 | %%(??child.stderr).readAll(&stderr); | ||
| 572 | |||
| 573 | if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) { | ||
| 574 | %%io.stderr.printf( | ||
| 575 | \\ | ||
| 576 | \\========= Expected this output: ========= | ||
| 577 | \\{} | ||
| 578 | \\================================================ | ||
| 579 | \\{} | ||
| 580 | \\ | ||
| 581 | , self.expected_output, stdout.toSliceConst()); | ||
| 582 | return error.TestFailed; | ||
| 583 | } | ||
| 584 | %%io.stderr.printf("OK\n"); | ||
| 585 | } | ||
| 586 | }; | ||
| 587 |