| 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 | 10 | const run_tests_cmd = b.addCommand(b.out_dir, b.env_map, "./run_tests", [][]const u8{}); |
| 11 | 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 | 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); | |
| 27 | self_hosted_tests.dependOn(&self_hosted_tests_release_nolibc.step); | |
| 28 | self_hosted_tests.dependOn(&self_hosted_tests_debug_libc.step); | |
| 29 | self_hosted_tests.dependOn(&self_hosted_tests_release_libc.step); | |
| 14 | for ([]bool{false, true}) |release| { | |
| 15 | for ([]bool{false, true}) |link_libc| { | |
| 16 | const these_tests = b.addTest("test/self_hosted.zig"); | |
| 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 | 27 | test_step.dependOn(self_hosted_tests); |
| 32 | 28 | //test_step.dependOn(&run_tests_cmd.step); |
| 33 | 29 | |
| 34 | 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 | 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 | 2608 | } |
| 2616 | 2609 | } |
| 2617 | 2610 | } |
| 2618 | add_build_examples(); | |
| 2619 | 2611 | add_debug_safety_test_cases(); |
| 2620 | 2612 | add_compile_failure_test_cases(); |
| 2621 | 2613 | add_parse_error_tests(); |
test/tests.zig+2-587| ... | ... | @@ -1,587 +1,2 @@ |
| 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 | ||
| 1 | pub const addCompareOutputTests = @import("compare_output.zig").addCompareOutputTests; | |
| 2 | pub const addBuildExampleTests = @import("build_examples.zig").addBuildExampleTests; |