| ... | ... | @@ -11,8 +11,9 @@ const enable_wine: bool = build_options.enable_wine; |
| 11 | 11 | const enable_wasmtime: bool = build_options.enable_wasmtime; |
| 12 | 12 | const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; |
| 13 | 13 | const ThreadPool = @import("ThreadPool.zig"); |
| 14 | const CrossTarget = std.zig.CrossTarget; |
| 14 | 15 | |
| 15 | | const cheader = @embedFile("link/cbe.h"); |
| 16 | const c_header = @embedFile("link/cbe.h"); |
| 16 | 17 | |
| 17 | 18 | test "self-hosted" { |
| 18 | 19 | var ctx = TestContext.init(); |
| ... | ... | @@ -88,6 +89,9 @@ pub const TestContext = struct { |
| 88 | 89 | /// A transformation update transforms the input and tests against |
| 89 | 90 | /// the expected output ZIR. |
| 90 | 91 | Transformation: [:0]const u8, |
| 92 | /// Check the main binary output file against an expected set of bytes. |
| 93 | /// This is most useful with, for example, `-ofmt=c`. |
| 94 | CompareObjectFile: []const u8, |
| 91 | 95 | /// An error update attempts to compile bad code, and ensures that it |
| 92 | 96 | /// fails to compile, and for the expected reasons. |
| 93 | 97 | /// A slice containing the expected errors *in sequential order*. |
| ... | ... | @@ -109,12 +113,12 @@ pub const TestContext = struct { |
| 109 | 113 | path: []const u8, |
| 110 | 114 | }; |
| 111 | 115 | |
| 112 | | pub const TestType = enum { |
| 116 | pub const Extension = enum { |
| 113 | 117 | Zig, |
| 114 | 118 | ZIR, |
| 115 | 119 | }; |
| 116 | 120 | |
| 117 | | /// A Case consists of a set of *updates*. The same Compilation is used for each |
| 121 | /// A `Case` consists of a list of `Update`. The same `Compilation` is used for each |
| 118 | 122 | /// update, so each update's source is treated as a single file being |
| 119 | 123 | /// updated by the test harness and incrementally compiled. |
| 120 | 124 | pub const Case = struct { |
| ... | ... | @@ -123,13 +127,14 @@ pub const TestContext = struct { |
| 123 | 127 | name: []const u8, |
| 124 | 128 | /// The platform the test targets. For non-native platforms, an emulator |
| 125 | 129 | /// such as QEMU is required for tests to complete. |
| 126 | | target: std.zig.CrossTarget, |
| 130 | target: CrossTarget, |
| 127 | 131 | /// In order to be able to run e.g. Execution updates, this must be set |
| 128 | 132 | /// to Executable. |
| 129 | 133 | output_mode: std.builtin.OutputMode, |
| 130 | 134 | updates: std.ArrayList(Update), |
| 131 | | extension: TestType, |
| 132 | | cbe: bool = false, |
| 135 | extension: Extension, |
| 136 | object_format: ?std.builtin.ObjectFormat = null, |
| 137 | emit_h: bool = false, |
| 133 | 138 | |
| 134 | 139 | files: std.ArrayList(File), |
| 135 | 140 | |
| ... | ... | @@ -145,6 +150,7 @@ pub const TestContext = struct { |
| 145 | 150 | /// Adds a subcase in which the module is updated with `src`, and a C |
| 146 | 151 | /// header is generated. |
| 147 | 152 | pub fn addHeader(self: *Case, src: [:0]const u8, result: [:0]const u8) void { |
| 153 | self.emit_h = true; |
| 148 | 154 | self.updates.append(.{ |
| 149 | 155 | .src = src, |
| 150 | 156 | .case = .{ .Header = result }, |
| ... | ... | @@ -160,6 +166,15 @@ pub const TestContext = struct { |
| 160 | 166 | }) catch unreachable; |
| 161 | 167 | } |
| 162 | 168 | |
| 169 | /// Adds a subcase in which the module is updated with `src`, compiled, |
| 170 | /// and the object file data is compared against `result`. |
| 171 | pub fn addCompareObjectFile(self: *Case, src: [:0]const u8, result: []const u8) void { |
| 172 | self.updates.append(.{ |
| 173 | .src = src, |
| 174 | .case = .{ .CompareObjectFile = result }, |
| 175 | }) catch unreachable; |
| 176 | } |
| 177 | |
| 163 | 178 | /// Adds a subcase in which the module is updated with `src`, which |
| 164 | 179 | /// should contain invalid input, and ensures that compilation fails |
| 165 | 180 | /// for the expected reasons, given in sequential order in `errors` in |
| ... | ... | @@ -214,86 +229,100 @@ pub const TestContext = struct { |
| 214 | 229 | pub fn addExe( |
| 215 | 230 | ctx: *TestContext, |
| 216 | 231 | name: []const u8, |
| 217 | | target: std.zig.CrossTarget, |
| 218 | | T: TestType, |
| 232 | target: CrossTarget, |
| 233 | extension: Extension, |
| 219 | 234 | ) *Case { |
| 220 | 235 | ctx.cases.append(Case{ |
| 221 | 236 | .name = name, |
| 222 | 237 | .target = target, |
| 223 | 238 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 224 | 239 | .output_mode = .Exe, |
| 225 | | .extension = T, |
| 240 | .extension = extension, |
| 226 | 241 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 227 | 242 | }) catch unreachable; |
| 228 | 243 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 229 | 244 | } |
| 230 | 245 | |
| 231 | 246 | /// Adds a test case for Zig input, producing an executable |
| 232 | | pub fn exe(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case { |
| 247 | pub fn exe(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 233 | 248 | return ctx.addExe(name, target, .Zig); |
| 234 | 249 | } |
| 235 | 250 | |
| 236 | 251 | /// Adds a test case for ZIR input, producing an executable |
| 237 | | pub fn exeZIR(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case { |
| 252 | pub fn exeZIR(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 238 | 253 | return ctx.addExe(name, target, .ZIR); |
| 239 | 254 | } |
| 240 | 255 | |
| 256 | pub fn exeFromCompiledC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 257 | ctx.cases.append(Case{ |
| 258 | .name = name, |
| 259 | .target = target, |
| 260 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 261 | .output_mode = .Exe, |
| 262 | .extension = .Zig, |
| 263 | .object_format = .c, |
| 264 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 265 | }) catch unreachable; |
| 266 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 267 | } |
| 268 | |
| 241 | 269 | pub fn addObj( |
| 242 | 270 | ctx: *TestContext, |
| 243 | 271 | name: []const u8, |
| 244 | | target: std.zig.CrossTarget, |
| 245 | | T: TestType, |
| 272 | target: CrossTarget, |
| 273 | extension: Extension, |
| 246 | 274 | ) *Case { |
| 247 | 275 | ctx.cases.append(Case{ |
| 248 | 276 | .name = name, |
| 249 | 277 | .target = target, |
| 250 | 278 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 251 | 279 | .output_mode = .Obj, |
| 252 | | .extension = T, |
| 280 | .extension = extension, |
| 253 | 281 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 254 | 282 | }) catch unreachable; |
| 255 | 283 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 256 | 284 | } |
| 257 | 285 | |
| 258 | | /// Adds a test case for Zig input, producing an object file |
| 259 | | pub fn obj(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case { |
| 286 | /// Adds a test case for Zig input, producing an object file. |
| 287 | pub fn obj(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 260 | 288 | return ctx.addObj(name, target, .Zig); |
| 261 | 289 | } |
| 262 | 290 | |
| 263 | | /// Adds a test case for ZIR input, producing an object file |
| 264 | | pub fn objZIR(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case { |
| 291 | /// Adds a test case for ZIR input, producing an object file. |
| 292 | pub fn objZIR(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 265 | 293 | return ctx.addObj(name, target, .ZIR); |
| 266 | 294 | } |
| 267 | 295 | |
| 268 | | pub fn addC(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget, T: TestType) *Case { |
| 296 | /// Adds a test case for Zig or ZIR input, producing C code. |
| 297 | pub fn addC(ctx: *TestContext, name: []const u8, target: CrossTarget, ext: Extension) *Case { |
| 269 | 298 | ctx.cases.append(Case{ |
| 270 | 299 | .name = name, |
| 271 | 300 | .target = target, |
| 272 | 301 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 273 | 302 | .output_mode = .Obj, |
| 274 | | .extension = T, |
| 275 | | .cbe = true, |
| 303 | .extension = ext, |
| 304 | .object_format = .c, |
| 276 | 305 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 277 | 306 | }) catch unreachable; |
| 278 | 307 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 279 | 308 | } |
| 280 | 309 | |
| 281 | | pub fn c(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 282 | | ctx.addC(name, target, .Zig).addTransform(src, cheader ++ out); |
| 310 | pub fn c(ctx: *TestContext, name: []const u8, target: CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 311 | ctx.addC(name, target, .Zig).addCompareObjectFile(src, c_header ++ out); |
| 283 | 312 | } |
| 284 | 313 | |
| 285 | | pub fn h(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 286 | | ctx.addC(name, target, .Zig).addHeader(src, cheader ++ out); |
| 314 | pub fn h(ctx: *TestContext, name: []const u8, target: CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 315 | ctx.addC(name, target, .Zig).addHeader(src, c_header ++ out); |
| 287 | 316 | } |
| 288 | 317 | |
| 289 | 318 | pub fn addCompareOutput( |
| 290 | 319 | ctx: *TestContext, |
| 291 | 320 | name: []const u8, |
| 292 | | T: TestType, |
| 321 | extension: Extension, |
| 293 | 322 | src: [:0]const u8, |
| 294 | 323 | expected_stdout: []const u8, |
| 295 | 324 | ) void { |
| 296 | | ctx.addExe(name, .{}, T).addCompareOutput(src, expected_stdout); |
| 325 | ctx.addExe(name, .{}, extension).addCompareOutput(src, expected_stdout); |
| 297 | 326 | } |
| 298 | 327 | |
| 299 | 328 | /// Adds a test case that compiles the Zig source given in `src`, executes |
| ... | ... | @@ -321,12 +350,12 @@ pub const TestContext = struct { |
| 321 | 350 | pub fn addTransform( |
| 322 | 351 | ctx: *TestContext, |
| 323 | 352 | name: []const u8, |
| 324 | | target: std.zig.CrossTarget, |
| 325 | | T: TestType, |
| 353 | target: CrossTarget, |
| 354 | extension: Extension, |
| 326 | 355 | src: [:0]const u8, |
| 327 | 356 | result: [:0]const u8, |
| 328 | 357 | ) void { |
| 329 | | ctx.addObj(name, target, T).addTransform(src, result); |
| 358 | ctx.addObj(name, target, extension).addTransform(src, result); |
| 330 | 359 | } |
| 331 | 360 | |
| 332 | 361 | /// Adds a test case that compiles the Zig given in `src` to ZIR and tests |
| ... | ... | @@ -334,7 +363,7 @@ pub const TestContext = struct { |
| 334 | 363 | pub fn transform( |
| 335 | 364 | ctx: *TestContext, |
| 336 | 365 | name: []const u8, |
| 337 | | target: std.zig.CrossTarget, |
| 366 | target: CrossTarget, |
| 338 | 367 | src: [:0]const u8, |
| 339 | 368 | result: [:0]const u8, |
| 340 | 369 | ) void { |
| ... | ... | @@ -346,7 +375,7 @@ pub const TestContext = struct { |
| 346 | 375 | pub fn transformZIR( |
| 347 | 376 | ctx: *TestContext, |
| 348 | 377 | name: []const u8, |
| 349 | | target: std.zig.CrossTarget, |
| 378 | target: CrossTarget, |
| 350 | 379 | src: [:0]const u8, |
| 351 | 380 | result: [:0]const u8, |
| 352 | 381 | ) void { |
| ... | ... | @@ -356,12 +385,12 @@ pub const TestContext = struct { |
| 356 | 385 | pub fn addError( |
| 357 | 386 | ctx: *TestContext, |
| 358 | 387 | name: []const u8, |
| 359 | | target: std.zig.CrossTarget, |
| 360 | | T: TestType, |
| 388 | target: CrossTarget, |
| 389 | extension: Extension, |
| 361 | 390 | src: [:0]const u8, |
| 362 | 391 | expected_errors: []const []const u8, |
| 363 | 392 | ) void { |
| 364 | | ctx.addObj(name, target, T).addError(src, expected_errors); |
| 393 | ctx.addObj(name, target, extension).addError(src, expected_errors); |
| 365 | 394 | } |
| 366 | 395 | |
| 367 | 396 | /// Adds a test case that ensures that the Zig given in `src` fails to |
| ... | ... | @@ -370,7 +399,7 @@ pub const TestContext = struct { |
| 370 | 399 | pub fn compileError( |
| 371 | 400 | ctx: *TestContext, |
| 372 | 401 | name: []const u8, |
| 373 | | target: std.zig.CrossTarget, |
| 402 | target: CrossTarget, |
| 374 | 403 | src: [:0]const u8, |
| 375 | 404 | expected_errors: []const []const u8, |
| 376 | 405 | ) void { |
| ... | ... | @@ -383,7 +412,7 @@ pub const TestContext = struct { |
| 383 | 412 | pub fn compileErrorZIR( |
| 384 | 413 | ctx: *TestContext, |
| 385 | 414 | name: []const u8, |
| 386 | | target: std.zig.CrossTarget, |
| 415 | target: CrossTarget, |
| 387 | 416 | src: [:0]const u8, |
| 388 | 417 | expected_errors: []const []const u8, |
| 389 | 418 | ) void { |
| ... | ... | @@ -393,11 +422,11 @@ pub const TestContext = struct { |
| 393 | 422 | pub fn addCompiles( |
| 394 | 423 | ctx: *TestContext, |
| 395 | 424 | name: []const u8, |
| 396 | | target: std.zig.CrossTarget, |
| 397 | | T: TestType, |
| 425 | target: CrossTarget, |
| 426 | extension: Extension, |
| 398 | 427 | src: [:0]const u8, |
| 399 | 428 | ) void { |
| 400 | | ctx.addObj(name, target, T).compiles(src); |
| 429 | ctx.addObj(name, target, extension).compiles(src); |
| 401 | 430 | } |
| 402 | 431 | |
| 403 | 432 | /// Adds a test case that asserts that the Zig given in `src` compiles |
| ... | ... | @@ -405,7 +434,7 @@ pub const TestContext = struct { |
| 405 | 434 | pub fn compiles( |
| 406 | 435 | ctx: *TestContext, |
| 407 | 436 | name: []const u8, |
| 408 | | target: std.zig.CrossTarget, |
| 437 | target: CrossTarget, |
| 409 | 438 | src: [:0]const u8, |
| 410 | 439 | ) void { |
| 411 | 440 | ctx.addCompiles(name, target, .Zig, src); |
| ... | ... | @@ -416,7 +445,7 @@ pub const TestContext = struct { |
| 416 | 445 | pub fn compilesZIR( |
| 417 | 446 | ctx: *TestContext, |
| 418 | 447 | name: []const u8, |
| 419 | | target: std.zig.CrossTarget, |
| 448 | target: CrossTarget, |
| 420 | 449 | src: [:0]const u8, |
| 421 | 450 | ) void { |
| 422 | 451 | ctx.addCompiles(name, target, .ZIR, src); |
| ... | ... | @@ -430,7 +459,7 @@ pub const TestContext = struct { |
| 430 | 459 | pub fn incrementalFailure( |
| 431 | 460 | ctx: *TestContext, |
| 432 | 461 | name: []const u8, |
| 433 | | target: std.zig.CrossTarget, |
| 462 | target: CrossTarget, |
| 434 | 463 | src: [:0]const u8, |
| 435 | 464 | expected_errors: []const []const u8, |
| 436 | 465 | fixed_src: [:0]const u8, |
| ... | ... | @@ -448,7 +477,7 @@ pub const TestContext = struct { |
| 448 | 477 | pub fn incrementalFailureZIR( |
| 449 | 478 | ctx: *TestContext, |
| 450 | 479 | name: []const u8, |
| 451 | | target: std.zig.CrossTarget, |
| 480 | target: CrossTarget, |
| 452 | 481 | src: [:0]const u8, |
| 453 | 482 | expected_errors: []const []const u8, |
| 454 | 483 | fixed_src: [:0]const u8, |
| ... | ... | @@ -548,12 +577,11 @@ pub const TestContext = struct { |
| 548 | 577 | .root_src_path = tmp_src_path, |
| 549 | 578 | }; |
| 550 | 579 | |
| 551 | | const ofmt: ?std.builtin.ObjectFormat = if (case.cbe) .c else null; |
| 552 | 580 | const bin_name = try std.zig.binNameAlloc(arena, .{ |
| 553 | 581 | .root_name = "test_case", |
| 554 | 582 | .target = target, |
| 555 | 583 | .output_mode = case.output_mode, |
| 556 | | .object_format = ofmt, |
| 584 | .object_format = case.object_format, |
| 557 | 585 | }); |
| 558 | 586 | |
| 559 | 587 | const emit_directory: Compilation.Directory = .{ |
| ... | ... | @@ -564,7 +592,7 @@ pub const TestContext = struct { |
| 564 | 592 | .directory = emit_directory, |
| 565 | 593 | .basename = bin_name, |
| 566 | 594 | }; |
| 567 | | const emit_h: ?Compilation.EmitLoc = if (case.cbe) |
| 595 | const emit_h: ?Compilation.EmitLoc = if (case.emit_h) |
| 568 | 596 | .{ |
| 569 | 597 | .directory = emit_directory, |
| 570 | 598 | .basename = "test_case.h", |
| ... | ... | @@ -588,7 +616,7 @@ pub const TestContext = struct { |
| 588 | 616 | .emit_h = emit_h, |
| 589 | 617 | .root_pkg = &root_pkg, |
| 590 | 618 | .keep_source_files_loaded = true, |
| 591 | | .object_format = ofmt, |
| 619 | .object_format = case.object_format, |
| 592 | 620 | .is_native_os = case.target.isNativeOs(), |
| 593 | 621 | .is_native_abi = case.target.isNativeAbi(), |
| 594 | 622 | }); |
| ... | ... | @@ -631,9 +659,10 @@ pub const TestContext = struct { |
| 631 | 659 | }, |
| 632 | 660 | } |
| 633 | 661 | } |
| 634 | | if (case.cbe) { |
| 635 | | const C = comp.bin_file.cast(link.File.C).?; |
| 636 | | std.debug.print("Generated C: \n===============\n{}\n\n===========\n\n", .{C.main.items}); |
| 662 | if (comp.bin_file.cast(link.File.C)) |c_file| { |
| 663 | std.debug.print("Generated C: \n===============\n{}\n\n===========\n\n", .{ |
| 664 | c_file.main.items, |
| 665 | }); |
| 637 | 666 | } |
| 638 | 667 | std.debug.print("Test failed.\n", .{}); |
| 639 | 668 | std.process.exit(1); |
| ... | ... | @@ -644,39 +673,37 @@ pub const TestContext = struct { |
| 644 | 673 | .Header => |expected_output| { |
| 645 | 674 | var file = try tmp.dir.openFile("test_case.h", .{ .read = true }); |
| 646 | 675 | defer file.close(); |
| 647 | | var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read headeroutput!"); |
| 676 | const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024); |
| 677 | |
| 678 | std.testing.expectEqualStrings(expected_output, out); |
| 679 | }, |
| 680 | .CompareObjectFile => |expected_output| { |
| 681 | var file = try tmp.dir.openFile(bin_name, .{ .read = true }); |
| 682 | defer file.close(); |
| 683 | const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024); |
| 648 | 684 | |
| 649 | 685 | std.testing.expectEqualStrings(expected_output, out); |
| 650 | 686 | }, |
| 651 | 687 | .Transformation => |expected_output| { |
| 652 | | if (case.cbe) { |
| 653 | | // The C file is always closed after an update, because we don't support |
| 654 | | // incremental updates. |
| 655 | | var file = try tmp.dir.openFile(bin_name, .{ .read = true }); |
| 656 | | defer file.close(); |
| 657 | | var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read C output!"); |
| 658 | | std.testing.expectEqualStrings(expected_output, out); |
| 659 | | } else { |
| 660 | | update_node.setEstimatedTotalItems(5); |
| 661 | | var emit_node = update_node.start("emit", 0); |
| 662 | | emit_node.activate(); |
| 663 | | var new_zir_module = try zir.emit(allocator, comp.bin_file.options.module.?); |
| 664 | | defer new_zir_module.deinit(allocator); |
| 665 | | emit_node.end(); |
| 666 | | |
| 667 | | var write_node = update_node.start("write", 0); |
| 668 | | write_node.activate(); |
| 669 | | var out_zir = std.ArrayList(u8).init(allocator); |
| 670 | | defer out_zir.deinit(); |
| 671 | | try new_zir_module.writeToStream(allocator, out_zir.outStream()); |
| 672 | | write_node.end(); |
| 673 | | |
| 674 | | var test_node = update_node.start("assert", 0); |
| 675 | | test_node.activate(); |
| 676 | | defer test_node.end(); |
| 677 | | |
| 678 | | std.testing.expectEqualStrings(expected_output, out_zir.items); |
| 679 | | } |
| 688 | update_node.setEstimatedTotalItems(5); |
| 689 | var emit_node = update_node.start("emit", 0); |
| 690 | emit_node.activate(); |
| 691 | var new_zir_module = try zir.emit(allocator, comp.bin_file.options.module.?); |
| 692 | defer new_zir_module.deinit(allocator); |
| 693 | emit_node.end(); |
| 694 | |
| 695 | var write_node = update_node.start("write", 0); |
| 696 | write_node.activate(); |
| 697 | var out_zir = std.ArrayList(u8).init(allocator); |
| 698 | defer out_zir.deinit(); |
| 699 | try new_zir_module.writeToStream(allocator, out_zir.outStream()); |
| 700 | write_node.end(); |
| 701 | |
| 702 | var test_node = update_node.start("assert", 0); |
| 703 | test_node.activate(); |
| 704 | defer test_node.end(); |
| 705 | |
| 706 | std.testing.expectEqualStrings(expected_output, out_zir.items); |
| 680 | 707 | }, |
| 681 | 708 | .Error => |e| { |
| 682 | 709 | var test_node = update_node.start("assert", 0); |
| ... | ... | @@ -734,8 +761,6 @@ pub const TestContext = struct { |
| 734 | 761 | } |
| 735 | 762 | }, |
| 736 | 763 | .Execution => |expected_stdout| { |
| 737 | | std.debug.assert(!case.cbe); |
| 738 | | |
| 739 | 764 | update_node.setEstimatedTotalItems(4); |
| 740 | 765 | var exec_result = x: { |
| 741 | 766 | var exec_node = update_node.start("execute", 0); |
| ... | ... | @@ -745,9 +770,12 @@ pub const TestContext = struct { |
| 745 | 770 | var argv = std.ArrayList([]const u8).init(allocator); |
| 746 | 771 | defer argv.deinit(); |
| 747 | 772 | |
| 748 | | const exe_path = try std.fmt.allocPrint(arena, "." ++ std.fs.path.sep_str ++ "{}", .{bin_name}); |
| 749 | | |
| 750 | | switch (case.target.getExternalExecutor()) { |
| 773 | const exe_path = try std.fmt.allocPrint(arena, "." ++ std.fs.path.sep_str ++ "{s}", .{bin_name}); |
| 774 | if (case.object_format != null and case.object_format.? == .c) { |
| 775 | try argv.appendSlice(&[_][]const u8{ |
| 776 | std.testing.zig_exe_path, "run", exe_path, "-lc", |
| 777 | }); |
| 778 | } else switch (case.target.getExternalExecutor()) { |
| 751 | 779 | .native => try argv.append(exe_path), |
| 752 | 780 | .unavailable => { |
| 753 | 781 | try self.runInterpreterIfAvailable(allocator, &exec_node, case, tmp.dir, bin_name); |
| ... | ... | @@ -809,18 +837,13 @@ pub const TestContext = struct { |
| 809 | 837 | switch (exec_result.term) { |
| 810 | 838 | .Exited => |code| { |
| 811 | 839 | if (code != 0) { |
| 812 | | std.debug.print("elf file exited with code {}\n", .{code}); |
| 840 | std.debug.print("execution exited with code {}\n", .{code}); |
| 813 | 841 | return error.BinaryBadExitCode; |
| 814 | 842 | } |
| 815 | 843 | }, |
| 816 | 844 | else => return error.BinaryCrashed, |
| 817 | 845 | } |
| 818 | | if (!std.mem.eql(u8, expected_stdout, exec_result.stdout)) { |
| 819 | | std.debug.panic( |
| 820 | | "update index {}, mismatched stdout\n====Expected (len={}):====\n{}\n====Actual (len={}):====\n{}\n========\n", |
| 821 | | .{ update_index, expected_stdout.len, expected_stdout, exec_result.stdout.len, exec_result.stdout }, |
| 822 | | ); |
| 823 | | } |
| 846 | std.testing.expectEqualStrings(expected_stdout, exec_result.stdout); |
| 824 | 847 | }, |
| 825 | 848 | } |
| 826 | 849 | } |