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