blob bcdc642a (21072B) - Raw
1 const std = @import("std"); 2 const os = std.os; 3 const tests = @import("tests.zig"); 4 5 pub fn addCases(cases: *tests.CompareOutputContext) void { 6 cases.addC("hello world with libc", 7 \\const c = @cImport({ 8 \\ // See https://github.com/ziglang/zig/issues/515 9 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1"); 10 \\ @cInclude("stdio.h"); 11 \\}); 12 \\pub export fn main(argc: c_int, argv: [*][*]u8) c_int { 13 \\ _ = argc; 14 \\ _ = argv; 15 \\ _ = c.puts("Hello, world!"); 16 \\ return 0; 17 \\} 18 , "Hello, world!" ++ if (@import("builtin").os.tag == .windows) "\r\n" else "\n"); 19 20 cases.add("hello world without libc", 21 \\const io = @import("std").io; 22 \\ 23 \\pub fn main() void { 24 \\ const stdout = io.getStdOut().writer(); 25 \\ stdout.print("Hello, world!\n{d:4} {x:3} {c}\n", .{@as(u32, 12), @as(u16, 0x12), @as(u8, 'a')}) catch unreachable; 26 \\} 27 , "Hello, world!\n 12 12 a\n"); 28 29 cases.addC("number literals", 30 \\const std = @import("std"); 31 \\const builtin = @import("builtin"); 32 \\const is_windows = builtin.os.tag == .windows; 33 \\const c = @cImport({ 34 \\ if (is_windows) { 35 \\ // See https://github.com/ziglang/zig/issues/515 36 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1"); 37 \\ @cInclude("io.h"); 38 \\ @cInclude("fcntl.h"); 39 \\ } 40 \\ @cInclude("stdio.h"); 41 \\}); 42 \\ 43 \\pub export fn main(argc: c_int, argv: [*][*]u8) c_int { 44 \\ _ = argc; 45 \\ _ = argv; 46 \\ if (is_windows) { 47 \\ // we want actual \n, not \r\n 48 \\ _ = c._setmode(1, c._O_BINARY); 49 \\ } 50 \\ _ = c.printf("0: %llu\n", 51 \\ @as(u64, 0)); 52 \\ _ = c.printf("320402575052271: %llu\n", 53 \\ @as(u64, 320402575052271)); 54 \\ _ = c.printf("0x01236789abcdef: %llu\n", 55 \\ @as(u64, 0x01236789abcdef)); 56 \\ _ = c.printf("0xffffffffffffffff: %llu\n", 57 \\ @as(u64, 0xffffffffffffffff)); 58 \\ _ = c.printf("0x000000ffffffffffffffff: %llu\n", 59 \\ @as(u64, 0x000000ffffffffffffffff)); 60 \\ _ = c.printf("0o1777777777777777777777: %llu\n", 61 \\ @as(u64, 0o1777777777777777777777)); 62 \\ _ = c.printf("0o0000001777777777777777777777: %llu\n", 63 \\ @as(u64, 0o0000001777777777777777777777)); 64 \\ _ = c.printf("0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", 65 \\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111)); 66 \\ _ = c.printf("0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", 67 \\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111)); 68 \\ 69 \\ _ = c.printf("\n"); 70 \\ 71 \\ _ = c.printf("0.0: %.013a\n", 72 \\ @as(f64, 0.0)); 73 \\ _ = c.printf("0e0: %.013a\n", 74 \\ @as(f64, 0e0)); 75 \\ _ = c.printf("0.0e0: %.013a\n", 76 \\ @as(f64, 0.0e0)); 77 \\ _ = c.printf("000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n", 78 \\ @as(f64, 0.0e0)); 79 \\ _ = c.printf("0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n", 80 \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0)); 81 \\ _ = c.printf("0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n", 82 \\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000)); 83 \\ _ = c.printf("1.0: %.013a\n", 84 \\ @as(f64, 1.0)); 85 \\ _ = c.printf("10.0: %.013a\n", 86 \\ @as(f64, 10.0)); 87 \\ _ = c.printf("10.5: %.013a\n", 88 \\ @as(f64, 10.5)); 89 \\ _ = c.printf("10.5e5: %.013a\n", 90 \\ @as(f64, 10.5e5)); 91 \\ _ = c.printf("10.5e+5: %.013a\n", 92 \\ @as(f64, 10.5e+5)); 93 \\ _ = c.printf("50.0e-2: %.013a\n", 94 \\ @as(f64, 50.0e-2)); 95 \\ _ = c.printf("50e-2: %.013a\n", 96 \\ @as(f64, 50e-2)); 97 \\ 98 \\ _ = c.printf("\n"); 99 \\ 100 \\ _ = c.printf("0x1.0: %.013a\n", 101 \\ @as(f64, 0x1.0)); 102 \\ _ = c.printf("0x10.0: %.013a\n", 103 \\ @as(f64, 0x10.0)); 104 \\ _ = c.printf("0x100.0: %.013a\n", 105 \\ @as(f64, 0x100.0)); 106 \\ _ = c.printf("0x103.0: %.013a\n", 107 \\ @as(f64, 0x103.0)); 108 \\ _ = c.printf("0x103.7: %.013a\n", 109 \\ @as(f64, 0x103.7)); 110 \\ _ = c.printf("0x103.70: %.013a\n", 111 \\ @as(f64, 0x103.70)); 112 \\ _ = c.printf("0x103.70p4: %.013a\n", 113 \\ @as(f64, 0x103.70p4)); 114 \\ _ = c.printf("0x103.70p5: %.013a\n", 115 \\ @as(f64, 0x103.70p5)); 116 \\ _ = c.printf("0x103.70p+5: %.013a\n", 117 \\ @as(f64, 0x103.70p+5)); 118 \\ _ = c.printf("0x103.70p-5: %.013a\n", 119 \\ @as(f64, 0x103.70p-5)); 120 \\ 121 \\ return 0; 122 \\} 123 , 124 \\0: 0 125 \\320402575052271: 320402575052271 126 \\0x01236789abcdef: 320402575052271 127 \\0xffffffffffffffff: 18446744073709551615 128 \\0x000000ffffffffffffffff: 18446744073709551615 129 \\0o1777777777777777777777: 18446744073709551615 130 \\0o0000001777777777777777777777: 18446744073709551615 131 \\0b1111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 132 \\0b0000001111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 133 \\ 134 \\0.0: 0x0.0000000000000p+0 135 \\0e0: 0x0.0000000000000p+0 136 \\0.0e0: 0x0.0000000000000p+0 137 \\000000000000000000000000000000000000000000000000000000000.0e0: 0x0.0000000000000p+0 138 \\0.000000000000000000000000000000000000000000000000000000000e0: 0x0.0000000000000p+0 139 \\0.0e000000000000000000000000000000000000000000000000000000000: 0x0.0000000000000p+0 140 \\1.0: 0x1.0000000000000p+0 141 \\10.0: 0x1.4000000000000p+3 142 \\10.5: 0x1.5000000000000p+3 143 \\10.5e5: 0x1.0059000000000p+20 144 \\10.5e+5: 0x1.0059000000000p+20 145 \\50.0e-2: 0x1.0000000000000p-1 146 \\50e-2: 0x1.0000000000000p-1 147 \\ 148 \\0x1.0: 0x1.0000000000000p+0 149 \\0x10.0: 0x1.0000000000000p+4 150 \\0x100.0: 0x1.0000000000000p+8 151 \\0x103.0: 0x1.0300000000000p+8 152 \\0x103.7: 0x1.0370000000000p+8 153 \\0x103.70: 0x1.0370000000000p+8 154 \\0x103.70p4: 0x1.0370000000000p+12 155 \\0x103.70p5: 0x1.0370000000000p+13 156 \\0x103.70p+5: 0x1.0370000000000p+13 157 \\0x103.70p-5: 0x1.0370000000000p+3 158 \\ 159 ); 160 161 cases.add("order-independent declarations", 162 \\const io = @import("std").io; 163 \\const z = io.stdin_fileno; 164 \\const x : @TypeOf(y) = 1234; 165 \\const y : u16 = 5678; 166 \\pub fn main() void { 167 \\ var x_local : i32 = print_ok(x); 168 \\ _ = x_local; 169 \\} 170 \\fn print_ok(val: @TypeOf(x)) @TypeOf(foo) { 171 \\ _ = val; 172 \\ const stdout = io.getStdOut().writer(); 173 \\ stdout.print("OK\n", .{}) catch unreachable; 174 \\ return 0; 175 \\} 176 \\const foo : i32 = 0; 177 , "OK\n"); 178 179 cases.addC("expose function pointer to C land", 180 \\const c = @cImport(@cInclude("stdlib.h")); 181 \\ 182 \\export fn compare_fn(a: ?*const anyopaque, b: ?*const anyopaque) c_int { 183 \\ const a_int: *const i32 = @ptrCast(@alignCast(a)); 184 \\ const b_int: *const i32 = @ptrCast(@alignCast(b)); 185 \\ if (a_int.* < b_int.*) { 186 \\ return -1; 187 \\ } else if (a_int.* > b_int.*) { 188 \\ return 1; 189 \\ } else { 190 \\ return 0; 191 \\ } 192 \\} 193 \\ 194 \\pub export fn main() c_int { 195 \\ var array = [_]u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; 196 \\ 197 \\ c.qsort(@ptrCast(&array), @intCast(array.len), @sizeOf(i32), compare_fn); 198 \\ 199 \\ for (array, 0..) |item, i| { 200 \\ if (item != i) { 201 \\ c.abort(); 202 \\ } 203 \\ } 204 \\ 205 \\ return 0; 206 \\} 207 , ""); 208 209 cases.addC("casting between float and integer types", 210 \\const std = @import("std"); 211 \\const builtin = @import("builtin"); 212 \\const is_windows = builtin.os.tag == .windows; 213 \\const c = @cImport({ 214 \\ if (is_windows) { 215 \\ // See https://github.com/ziglang/zig/issues/515 216 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1"); 217 \\ @cInclude("io.h"); 218 \\ @cInclude("fcntl.h"); 219 \\ } 220 \\ @cInclude("stdio.h"); 221 \\}); 222 \\ 223 \\pub export fn main(argc: c_int, argv: [*][*]u8) c_int { 224 \\ _ = argc; 225 \\ _ = argv; 226 \\ if (is_windows) { 227 \\ // we want actual \n, not \r\n 228 \\ _ = c._setmode(1, c._O_BINARY); 229 \\ } 230 \\ const small: f32 = 3.25; 231 \\ const x: f64 = small; 232 \\ const y: i32 = @intFromFloat(x); 233 \\ const z: f64 = @floatFromInt(y); 234 \\ _ = c.printf("%.2f\n%d\n%.2f\n%.2f\n", x, y, z, @as(f64, -0.4)); 235 \\ return 0; 236 \\} 237 , "3.25\n3\n3.00\n-0.40\n"); 238 239 cases.add("same named methods in incomplete struct", 240 \\const io = @import("std").io; 241 \\ 242 \\const Foo = struct { 243 \\ field1: Bar, 244 \\ 245 \\ fn method(a: *const Foo) bool { 246 \\ _ = a; 247 \\ return true; 248 \\ } 249 \\}; 250 \\ 251 \\const Bar = struct { 252 \\ field2: i32, 253 \\ 254 \\ fn method(b: *const Bar) bool { 255 \\ _ = b; 256 \\ return true; 257 \\ } 258 \\}; 259 \\ 260 \\pub fn main() void { 261 \\ const bar = Bar {.field2 = 13,}; 262 \\ const foo = Foo {.field1 = bar,}; 263 \\ const stdout = io.getStdOut().writer(); 264 \\ if (!foo.method()) { 265 \\ stdout.print("BAD\n", .{}) catch unreachable; 266 \\ } 267 \\ if (!bar.method()) { 268 \\ stdout.print("BAD\n", .{}) catch unreachable; 269 \\ } 270 \\ stdout.print("OK\n", .{}) catch unreachable; 271 \\} 272 , "OK\n"); 273 274 cases.add("defer with only fallthrough", 275 \\const io = @import("std").io; 276 \\pub fn main() void { 277 \\ const stdout = io.getStdOut().writer(); 278 \\ stdout.print("before\n", .{}) catch unreachable; 279 \\ defer stdout.print("defer1\n", .{}) catch unreachable; 280 \\ defer stdout.print("defer2\n", .{}) catch unreachable; 281 \\ defer stdout.print("defer3\n", .{}) catch unreachable; 282 \\ stdout.print("after\n", .{}) catch unreachable; 283 \\} 284 , "before\nafter\ndefer3\ndefer2\ndefer1\n"); 285 286 cases.add("defer with return", 287 \\const io = @import("std").io; 288 \\const os = @import("std").os; 289 \\pub fn main() void { 290 \\ const stdout = io.getStdOut().writer(); 291 \\ stdout.print("before\n", .{}) catch unreachable; 292 \\ defer stdout.print("defer1\n", .{}) catch unreachable; 293 \\ defer stdout.print("defer2\n", .{}) catch unreachable; 294 \\ var gpa = @import("std").heap.GeneralPurposeAllocator(.{}){}; 295 \\ defer _ = gpa.deinit(); 296 \\ var arena = @import("std").heap.ArenaAllocator.init(gpa.allocator()); 297 \\ defer arena.deinit(); 298 \\ var args_it = @import("std").process.argsWithAllocator(arena.allocator()) catch unreachable; 299 \\ if (args_it.skip() and !args_it.skip()) return; 300 \\ defer stdout.print("defer3\n", .{}) catch unreachable; 301 \\ stdout.print("after\n", .{}) catch unreachable; 302 \\} 303 , "before\ndefer2\ndefer1\n"); 304 305 cases.add("errdefer and it fails", 306 \\const io = @import("std").io; 307 \\pub fn main() void { 308 \\ do_test() catch return; 309 \\} 310 \\fn do_test() !void { 311 \\ const stdout = io.getStdOut().writer(); 312 \\ stdout.print("before\n", .{}) catch unreachable; 313 \\ defer stdout.print("defer1\n", .{}) catch unreachable; 314 \\ errdefer stdout.print("deferErr\n", .{}) catch unreachable; 315 \\ try its_gonna_fail(); 316 \\ defer stdout.print("defer3\n", .{}) catch unreachable; 317 \\ stdout.print("after\n", .{}) catch unreachable; 318 \\} 319 \\fn its_gonna_fail() !void { 320 \\ return error.IToldYouItWouldFail; 321 \\} 322 , "before\ndeferErr\ndefer1\n"); 323 324 cases.add("errdefer and it passes", 325 \\const io = @import("std").io; 326 \\pub fn main() void { 327 \\ do_test() catch return; 328 \\} 329 \\fn do_test() !void { 330 \\ const stdout = io.getStdOut().writer(); 331 \\ stdout.print("before\n", .{}) catch unreachable; 332 \\ defer stdout.print("defer1\n", .{}) catch unreachable; 333 \\ errdefer stdout.print("deferErr\n", .{}) catch unreachable; 334 \\ try its_gonna_pass(); 335 \\ defer stdout.print("defer3\n", .{}) catch unreachable; 336 \\ stdout.print("after\n", .{}) catch unreachable; 337 \\} 338 \\fn its_gonna_pass() anyerror!void { } 339 , "before\nafter\ndefer3\ndefer1\n"); 340 341 cases.addCase(x: { 342 var tc = cases.create("@embedFile", 343 \\const foo_txt = @embedFile("foo.txt"); 344 \\const io = @import("std").io; 345 \\ 346 \\pub fn main() void { 347 \\ const stdout = io.getStdOut().writer(); 348 \\ stdout.print(foo_txt, .{}) catch unreachable; 349 \\} 350 , "1234\nabcd\n"); 351 352 tc.addSourceFile("foo.txt", "1234\nabcd\n"); 353 354 break :x tc; 355 }); 356 357 cases.addCase(x: { 358 var tc = cases.create("parsing args", 359 \\const std = @import("std"); 360 \\const io = std.io; 361 \\const os = std.os; 362 \\ 363 \\pub fn main() !void { 364 \\ var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 365 \\ defer _ = gpa.deinit(); 366 \\ var arena = std.heap.ArenaAllocator.init(gpa.allocator()); 367 \\ defer arena.deinit(); 368 \\ var args_it = try std.process.argsWithAllocator(arena.allocator()); 369 \\ const stdout = io.getStdOut().writer(); 370 \\ var index: usize = 0; 371 \\ _ = args_it.skip(); 372 \\ while (args_it.next()) |arg| : (index += 1) { 373 \\ try stdout.print("{}: {s}\n", .{index, arg}); 374 \\ } 375 \\} 376 , 377 \\0: first arg 378 \\1: 'a' 'b' \ 379 \\2: bare 380 \\3: ba""re 381 \\4: " 382 \\5: last arg 383 \\ 384 ); 385 386 tc.setCommandLineArgs(&[_][]const u8{ 387 "first arg", 388 "'a' 'b' \\", 389 "bare", 390 "ba\"\"re", 391 "\"", 392 "last arg", 393 }); 394 395 break :x tc; 396 }); 397 398 cases.addCase(x: { 399 var tc = cases.create("parsing args new API", 400 \\const std = @import("std"); 401 \\const io = std.io; 402 \\const os = std.os; 403 \\ 404 \\pub fn main() !void { 405 \\ var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 406 \\ defer _ = gpa.deinit(); 407 \\ var arena = std.heap.ArenaAllocator.init(gpa.allocator()); 408 \\ defer arena.deinit(); 409 \\ var args_it = try std.process.argsWithAllocator(arena.allocator()); 410 \\ const stdout = io.getStdOut().writer(); 411 \\ var index: usize = 0; 412 \\ _ = args_it.skip(); 413 \\ while (args_it.next()) |arg| : (index += 1) { 414 \\ try stdout.print("{}: {s}\n", .{index, arg}); 415 \\ } 416 \\} 417 , 418 \\0: first arg 419 \\1: 'a' 'b' \ 420 \\2: bare 421 \\3: ba""re 422 \\4: " 423 \\5: last arg 424 \\ 425 ); 426 427 tc.setCommandLineArgs(&[_][]const u8{ 428 "first arg", 429 "'a' 'b' \\", 430 "bare", 431 "ba\"\"re", 432 "\"", 433 "last arg", 434 }); 435 436 break :x tc; 437 }); 438 439 // It is required to override the log function in order to print to stdout instead of stderr 440 cases.add("std.log per scope log level override", 441 \\const std = @import("std"); 442 \\ 443 \\pub const std_options = struct { 444 \\ pub const log_level: std.log.Level = .debug; 445 \\ 446 \\ pub const log_scope_levels = &[_]std.log.ScopeLevel{ 447 \\ .{ .scope = .a, .level = .warn }, 448 \\ .{ .scope = .c, .level = .err }, 449 \\ }; 450 \\ pub const logFn = log; 451 \\}; 452 \\ 453 \\const loga = std.log.scoped(.a); 454 \\const logb = std.log.scoped(.b); 455 \\const logc = std.log.scoped(.c); 456 \\ 457 \\pub fn main() !void { 458 \\ loga.debug("", .{}); 459 \\ logb.debug("", .{}); 460 \\ logc.debug("", .{}); 461 \\ 462 \\ loga.info("", .{}); 463 \\ logb.info("", .{}); 464 \\ logc.info("", .{}); 465 \\ 466 \\ loga.warn("", .{}); 467 \\ logb.warn("", .{}); 468 \\ logc.warn("", .{}); 469 \\ 470 \\ loga.err("", .{}); 471 \\ logb.err("", .{}); 472 \\ logc.err("", .{}); 473 \\} 474 \\pub fn log( 475 \\ comptime level: std.log.Level, 476 \\ comptime scope: @TypeOf(.EnumLiteral), 477 \\ comptime format: []const u8, 478 \\ args: anytype, 479 \\) void { 480 \\ const level_txt = comptime level.asText(); 481 \\ const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "):"; 482 \\ const stdout = std.io.getStdOut().writer(); 483 \\ nosuspend stdout.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; 484 \\} 485 , 486 \\debug(b): 487 \\info(b): 488 \\warning(a): 489 \\warning(b): 490 \\error(a): 491 \\error(b): 492 \\error(c): 493 \\ 494 ); 495 496 // It is required to override the log function in order to print to stdout instead of stderr 497 cases.add("std.heap.LoggingAllocator logs to std.log", 498 \\const std = @import("std"); 499 \\ 500 \\pub const std_options = struct { 501 \\ pub const log_level: std.log.Level = .debug; 502 \\ pub const logFn = log; 503 \\}; 504 \\ 505 \\pub fn main() !void { 506 \\ var allocator_buf: [10]u8 = undefined; 507 \\ var fba = std.heap.FixedBufferAllocator.init(&allocator_buf); 508 \\ var fba_wrapped = std.mem.validationWrap(fba); 509 \\ var logging_allocator = std.heap.loggingAllocator(fba_wrapped.allocator()); 510 \\ const allocator = logging_allocator.allocator(); 511 \\ 512 \\ var a = try allocator.alloc(u8, 10); 513 \\ try std.testing.expect(allocator.resize(a, 5)); 514 \\ a = a[0..5]; 515 \\ try std.testing.expect(a.len == 5); 516 \\ try std.testing.expect(!allocator.resize(a, 20)); 517 \\ allocator.free(a); 518 \\} 519 \\ 520 \\pub fn log( 521 \\ comptime level: std.log.Level, 522 \\ comptime scope: @TypeOf(.EnumLiteral), 523 \\ comptime format: []const u8, 524 \\ args: anytype, 525 \\) void { 526 \\ const level_txt = comptime level.asText(); 527 \\ const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; 528 \\ const stdout = std.io.getStdOut().writer(); 529 \\ nosuspend stdout.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; 530 \\} 531 , 532 \\debug: alloc - success - len: 10, ptr_align: 0 533 \\debug: shrink - success - 10 to 5, buf_align: 0 534 \\error: expand - failure - 5 to 20, buf_align: 0 535 \\debug: free - len: 5 536 \\ 537 ); 538 539 cases.add("valid carriage return example", "const io = @import(\"std\").io;\r\n" ++ // Testing CRLF line endings are valid 540 "\r\n" ++ 541 "pub \r fn main() void {\r\n" ++ // Testing isolated carriage return as whitespace is valid 542 " const stdout = io.getStdOut().writer();\r\n" ++ 543 " stdout.print(\\\\A Multiline\r\n" ++ // testing CRLF at end of multiline string line is valid and normalises to \n in the output 544 " \\\\String\r\n" ++ 545 " , .{}) catch unreachable;\r\n" ++ 546 "}\r\n", "A Multiline\nString"); 547 }