commit 030742f1f73d0c9a237d7512d894e88b05ad53af (tree) parent 15c4fae1c93d970d02a9eede96371fb7c053837f Author: Andrew Kelley <andrew@ziglang.org> Date: Wed, 8 Mar 2023 00:16:16 -0700 re-enable standalone tests based on build.zig Diffstat:
43 files changed, 746 insertions(+), 627 deletions(-)
diff --git a/build.zig b/build.zig @@ -445,9 +445,7 @@ pub fn build(b: *std.Build) !void { test_step.dependOn(tests.addCompareOutputTests(b, test_filter, optimization_modes)); test_step.dependOn(tests.addStandaloneTests( b, - test_filter, optimization_modes, - skip_non_native, enable_macos_sdk, skip_stage2_tests, enable_symlinks_windows, @@ -455,7 +453,7 @@ pub fn build(b: *std.Build) !void { test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release)); test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, skip_stage2_tests, enable_symlinks_windows)); test_step.dependOn(tests.addStackTraceTests(b, test_filter, optimization_modes)); - test_step.dependOn(tests.addCliTests(b, test_filter, optimization_modes)); + test_step.dependOn(tests.addCliTests(b)); test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, optimization_modes)); test_step.dependOn(tests.addTranslateCTests(b, test_filter)); if (!skip_run_translated_c) { diff --git a/test/standalone.zig b/test/standalone.zig @@ -3,6 +3,8 @@ pub const SimpleCase = struct { link_libc: bool = false, all_modes: bool = false, target: std.zig.CrossTarget = .{}, + is_test: bool = false, + is_exe: bool = true, }; pub const BuildCase = struct { @@ -27,6 +29,17 @@ pub const simple_cases = [_]SimpleCase{ //.{ // .src_path = "test/standalone/issue_9693/main.zig", //}, + .{ + .src_path = "test/standalone/brace_expansion.zig", + .is_test = true, + }, + .{ + .src_path = "test/standalone/issue_7030.zig", + .target = .{ + .cpu_arch = .wasm32, + .os_tag = .freestanding, + }, + }, .{ .src_path = "test/standalone/issue_12471/main.zig" }, .{ .src_path = "test/standalone/guess_number/main.zig" }, @@ -57,88 +70,143 @@ pub const simple_cases = [_]SimpleCase{ .{ .src_path = "tools/update_spirv_features.zig" }, }; -pub const build_cases = [_]BuildCase{}; - -//pub fn addCases(cases: *tests.StandaloneContext) void { -// cases.addBuildFile("test/standalone/options/build.zig", .{ -// .extra_argv = &.{ -// "-Dbool_true", -// "-Dbool_false=false", -// "-Dint=1234", -// "-De=two", -// "-Dstring=hello", -// }, -// }); -// -// cases.addBuildFile("test/standalone/test_runner_path/build.zig", .{ .requires_stage2 = true }); -// cases.addBuildFile("test/standalone/issue_13970/build.zig", .{}); -// cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{}); -// cases.addBuildFile("test/standalone/shared_library/build.zig", .{}); -// cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{}); -// cases.addBuildFile("test/standalone/mix_c_files/build.zig", .{ -// .build_modes = true, -// .cross_targets = true, -// }); -// cases.addBuildFile("test/standalone/global_linkage/build.zig", .{}); -// cases.addBuildFile("test/standalone/static_c_lib/build.zig", .{}); -// cases.addBuildFile("test/standalone/issue_339/build.zig", .{}); -// cases.addBuildFile("test/standalone/issue_8550/build.zig", .{}); -// cases.addBuildFile("test/standalone/issue_794/build.zig", .{}); -// cases.addBuildFile("test/standalone/issue_5825/build.zig", .{}); -// cases.addBuildFile("test/standalone/pkg_import/build.zig", .{}); -// cases.addBuildFile("test/standalone/use_alias/build.zig", .{}); -// cases.addBuildFile("test/standalone/brace_expansion/build.zig", .{}); -// if (builtin.os.tag != .windows or builtin.cpu.arch != .aarch64) { -// // https://github.com/ziglang/zig/issues/13685 -// cases.addBuildFile("test/standalone/empty_env/build.zig", .{}); -// } -// cases.addBuildFile("test/standalone/issue_7030/build.zig", .{}); -// cases.addBuildFile("test/standalone/install_raw_hex/build.zig", .{}); -// if (builtin.zig_backend == .stage1) { // https://github.com/ziglang/zig/issues/12194 -// cases.addBuildFile("test/standalone/issue_9812/build.zig", .{}); -// } -// if (builtin.os.tag != .windows) { -// // https://github.com/ziglang/zig/issues/12419 -// cases.addBuildFile("test/standalone/issue_11595/build.zig", .{}); -// } -// -// if (builtin.os.tag != .wasi and -// // https://github.com/ziglang/zig/issues/13550 -// (builtin.os.tag != .macos or builtin.cpu.arch != .aarch64) and -// // https://github.com/ziglang/zig/issues/13686 -// (builtin.os.tag != .windows or builtin.cpu.arch != .aarch64)) -// { -// cases.addBuildFile("test/standalone/load_dynamic_library/build.zig", .{}); -// } -// -// if (builtin.os.tag == .windows) { -// cases.addBuildFile("test/standalone/windows_spawn/build.zig", .{}); -// } -// -// cases.addBuildFile("test/standalone/c_compiler/build.zig", .{ -// .build_modes = true, -// .cross_targets = true, -// }); -// -// // Try to build and run a PIE executable. -// if (builtin.os.tag == .linux) { -// cases.addBuildFile("test/standalone/pie/build.zig", .{}); -// } -// cases.addBuildFile("test/standalone/issue_12706/build.zig", .{}); -// if (std.os.have_sigpipe_support) { -// cases.addBuildFile("test/standalone/sigpipe/build.zig", .{}); -// } -// -// cases.addBuildFile("test/standalone/issue_13030/build.zig", .{ .build_modes = true }); -// cases.addBuildFile("test/standalone/emit_asm_and_bin/build.zig", .{}); -// cases.addBuildFile("test/standalone/issue_12588/build.zig", .{}); -// cases.addBuildFile("test/standalone/embed_generated_file/build.zig", .{}); -// -// cases.addBuildFile("test/standalone/dep_diamond/build.zig", .{}); -// cases.addBuildFile("test/standalone/dep_triangle/build.zig", .{}); -// cases.addBuildFile("test/standalone/dep_recursive/build.zig", .{}); -// cases.addBuildFile("test/standalone/dep_mutually_recursive/build.zig", .{}); -// cases.addBuildFile("test/standalone/dep_shared_builtin/build.zig", .{}); -//} +pub const build_cases = [_]BuildCase{ + .{ + .build_root = "test/standalone/test_runner_path", + .import = @import("standalone/test_runner_path/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_13970", + .import = @import("standalone/issue_13970/build.zig"), + }, + .{ + .build_root = "test/standalone/main_pkg_path", + .import = @import("standalone/main_pkg_path/build.zig"), + }, + .{ + .build_root = "test/standalone/shared_library", + .import = @import("standalone/shared_library/build.zig"), + }, + .{ + .build_root = "test/standalone/mix_o_files", + .import = @import("standalone/mix_o_files/build.zig"), + }, + .{ + .build_root = "test/standalone/mix_c_files", + .import = @import("standalone/mix_c_files/build.zig"), + }, + .{ + .build_root = "test/standalone/global_linkage", + .import = @import("standalone/global_linkage/build.zig"), + }, + .{ + .build_root = "test/standalone/static_c_lib", + .import = @import("standalone/static_c_lib/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_339", + .import = @import("standalone/issue_339/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_8550", + .import = @import("standalone/issue_8550/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_794", + .import = @import("standalone/issue_794/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_5825", + .import = @import("standalone/issue_5825/build.zig"), + }, + .{ + .build_root = "test/standalone/pkg_import", + .import = @import("standalone/pkg_import/build.zig"), + }, + .{ + .build_root = "test/standalone/use_alias", + .import = @import("standalone/use_alias/build.zig"), + }, + .{ + .build_root = "test/standalone/install_raw_hex", + .import = @import("standalone/install_raw_hex/build.zig"), + }, + // TODO take away EmitOption.emit_to option and make it give a FileSource + //.{ + // .build_root = "test/standalone/emit_asm_and_bin", + // .import = @import("standalone/emit_asm_and_bin/build.zig"), + //}, + // TODO take away EmitOption.emit_to option and make it give a FileSource + //.{ + // .build_root = "test/standalone/issue_12588", + // .import = @import("standalone/issue_12588/build.zig"), + //}, + .{ + .build_root = "test/standalone/embed_generated_file", + .import = @import("standalone/embed_generated_file/build.zig"), + }, + .{ + .build_root = "test/standalone/dep_diamond", + .import = @import("standalone/dep_diamond/build.zig"), + }, + .{ + .build_root = "test/standalone/dep_triangle", + .import = @import("standalone/dep_triangle/build.zig"), + }, + .{ + .build_root = "test/standalone/dep_recursive", + .import = @import("standalone/dep_recursive/build.zig"), + }, + .{ + .build_root = "test/standalone/dep_mutually_recursive", + .import = @import("standalone/dep_mutually_recursive/build.zig"), + }, + .{ + .build_root = "test/standalone/dep_shared_builtin", + .import = @import("standalone/dep_shared_builtin/build.zig"), + }, + .{ + .build_root = "test/standalone/empty_env", + .import = @import("standalone/empty_env/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_9812", + .import = @import("standalone/issue_9812/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_11595", + .import = @import("standalone/issue_11595/build.zig"), + }, + .{ + .build_root = "test/standalone/load_dynamic_library", + .import = @import("standalone/load_dynamic_library/build.zig"), + }, + .{ + .build_root = "test/standalone/windows_spawn", + .import = @import("standalone/windows_spawn/build.zig"), + }, + .{ + .build_root = "test/standalone/c_compiler", + .import = @import("standalone/c_compiler/build.zig"), + }, + .{ + .build_root = "test/standalone/pie", + .import = @import("standalone/pie/build.zig"), + }, + .{ + .build_root = "test/standalone/issue_12706", + .import = @import("standalone/issue_12706/build.zig"), + }, + // TODO This test is disabled for doing naughty things in the build script. + // The logic needs to get moved to a child process instead of build.zig. + //.{ + // .build_root = "test/standalone/sigpipe", + // .import = @import("standalone/sigpipe/build.zig"), + //}, + .{ + .build_root = "test/standalone/issue_13030", + .import = @import("standalone/issue_13030/build.zig"), + }, +}; const std = @import("std"); diff --git a/test/standalone/brace_expansion.zig b/test/standalone/brace_expansion.zig @@ -0,0 +1,292 @@ +const std = @import("std"); +const io = std.io; +const mem = std.mem; +const debug = std.debug; +const assert = debug.assert; +const testing = std.testing; +const ArrayList = std.ArrayList; +const maxInt = std.math.maxInt; + +const Token = union(enum) { + Word: []const u8, + OpenBrace, + CloseBrace, + Comma, + Eof, +}; + +var gpa = std.heap.GeneralPurposeAllocator(.{}){}; +var global_allocator = gpa.allocator(); + +fn tokenize(input: []const u8) !ArrayList(Token) { + const State = enum { + Start, + Word, + }; + + var token_list = ArrayList(Token).init(global_allocator); + errdefer token_list.deinit(); + var tok_begin: usize = undefined; + var state = State.Start; + + for (input, 0..) |b, i| { + switch (state) { + .Start => switch (b) { + 'a'...'z', 'A'...'Z' => { + state = State.Word; + tok_begin = i; + }, + '{' => try token_list.append(Token.OpenBrace), + '}' => try token_list.append(Token.CloseBrace), + ',' => try token_list.append(Token.Comma), + else => return error.InvalidInput, + }, + .Word => switch (b) { + 'a'...'z', 'A'...'Z' => {}, + '{', '}', ',' => { + try token_list.append(Token{ .Word = input[tok_begin..i] }); + switch (b) { + '{' => try token_list.append(Token.OpenBrace), + '}' => try token_list.append(Token.CloseBrace), + ',' => try token_list.append(Token.Comma), + else => unreachable, + } + state = State.Start; + }, + else => return error.InvalidInput, + }, + } + } + switch (state) { + State.Start => {}, + State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }), + } + try token_list.append(Token.Eof); + return token_list; +} + +const Node = union(enum) { + Scalar: []const u8, + List: ArrayList(Node), + Combine: []Node, + + fn deinit(self: Node) void { + switch (self) { + .Scalar => {}, + .Combine => |pair| { + pair[0].deinit(); + pair[1].deinit(); + global_allocator.free(pair); + }, + .List => |list| { + for (list.items) |item| { + item.deinit(); + } + list.deinit(); + }, + } + } +}; + +const ParseError = error{ + InvalidInput, + OutOfMemory, +}; + +fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node { + const first_token = tokens.items[token_index.*]; + token_index.* += 1; + + const result_node = switch (first_token) { + .Word => |word| Node{ .Scalar = word }, + .OpenBrace => blk: { + var list = ArrayList(Node).init(global_allocator); + errdefer { + for (list.items) |node| node.deinit(); + list.deinit(); + } + while (true) { + try list.append(try parse(tokens, token_index)); + + const token = tokens.items[token_index.*]; + token_index.* += 1; + + switch (token) { + .CloseBrace => break, + .Comma => continue, + else => return error.InvalidInput, + } + } + break :blk Node{ .List = list }; + }, + else => return error.InvalidInput, + }; + + switch (tokens.items[token_index.*]) { + .Word, .OpenBrace => { + const pair = try global_allocator.alloc(Node, 2); + errdefer global_allocator.free(pair); + pair[0] = result_node; + pair[1] = try parse(tokens, token_index); + return Node{ .Combine = pair }; + }, + else => return result_node, + } +} + +fn expandString(input: []const u8, output: *ArrayList(u8)) !void { + const tokens = try tokenize(input); + defer tokens.deinit(); + if (tokens.items.len == 1) { + return output.resize(0); + } + + var token_index: usize = 0; + const root = try parse(&tokens, &token_index); + defer root.deinit(); + const last_token = tokens.items[token_index]; + switch (last_token) { + Token.Eof => {}, + else => return error.InvalidInput, + } + + var result_list = ArrayList(ArrayList(u8)).init(global_allocator); + defer { + for (result_list.items) |*buf| buf.deinit(); + result_list.deinit(); + } + + try expandNode(root, &result_list); + + try output.resize(0); + for (result_list.items, 0..) |buf, i| { + if (i != 0) { + try output.append(' '); + } + try output.appendSlice(buf.items); + } +} + +const ExpandNodeError = error{OutOfMemory}; + +fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void { + assert(output.items.len == 0); + switch (node) { + .Scalar => |scalar| { + var list = ArrayList(u8).init(global_allocator); + errdefer list.deinit(); + try list.appendSlice(scalar); + try output.append(list); + }, + .Combine => |pair| { + const a_node = pair[0]; + const b_node = pair[1]; + + var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator); + defer { + for (child_list_a.items) |*buf| buf.deinit(); + child_list_a.deinit(); + } + try expandNode(a_node, &child_list_a); + + var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator); + defer { + for (child_list_b.items) |*buf| buf.deinit(); + child_list_b.deinit(); + } + try expandNode(b_node, &child_list_b); + + for (child_list_a.items) |buf_a| { + for (child_list_b.items) |buf_b| { + var combined_buf = ArrayList(u8).init(global_allocator); + errdefer combined_buf.deinit(); + + try combined_buf.appendSlice(buf_a.items); + try combined_buf.appendSlice(buf_b.items); + try output.append(combined_buf); + } + } + }, + .List => |list| { + for (list.items) |child_node| { + var child_list = ArrayList(ArrayList(u8)).init(global_allocator); + errdefer for (child_list.items) |*buf| buf.deinit(); + defer child_list.deinit(); + + try expandNode(child_node, &child_list); + + for (child_list.items) |buf| { + try output.append(buf); + } + } + }, + } +} + +pub fn main() !void { + defer _ = gpa.deinit(); + const stdin_file = io.getStdIn(); + const stdout_file = io.getStdOut(); + + const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize)); + defer global_allocator.free(stdin); + + var result_buf = ArrayList(u8).init(global_allocator); + defer result_buf.deinit(); + + try expandString(stdin, &result_buf); + try stdout_file.writeAll(result_buf.items); +} + +test "invalid inputs" { + global_allocator = std.testing.allocator; + + try expectError("}ABC", error.InvalidInput); + try expectError("{ABC", error.InvalidInput); + try expectError("}{", error.InvalidInput); + try expectError("{}", error.InvalidInput); + try expectError("A,B,C", error.InvalidInput); + try expectError("{A{B,C}", error.InvalidInput); + try expectError("{A,}", error.InvalidInput); + + try expectError("\n", error.InvalidInput); +} + +fn expectError(test_input: []const u8, expected_err: anyerror) !void { + var output_buf = ArrayList(u8).init(global_allocator); + defer output_buf.deinit(); + + try testing.expectError(expected_err, expandString(test_input, &output_buf)); +} + +test "valid inputs" { + global_allocator = std.testing.allocator; + + try expectExpansion("{x,y,z}", "x y z"); + try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By"); + try expectExpansion("{A,B{x,y}}", "A Bx By"); + + try expectExpansion("{ABC}", "ABC"); + try expectExpansion("{A,B,C}", "A B C"); + try expectExpansion("ABC", "ABC"); + + try expectExpansion("", ""); + try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh"); + try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh"); + try expectExpansion("{A,B}a", "Aa Ba"); + try expectExpansion("{C,{x,y}}", "C x y"); + try expectExpansion("z{C,{x,y}}", "zC zx zy"); + try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg"); + try expectExpansion("a{x,y}b", "axb ayb"); + try expectExpansion("z{{a,b}}", "za zb"); + try expectExpansion("a{b}", "ab"); +} + +fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void { + var result = ArrayList(u8).init(global_allocator); + defer result.deinit(); + + expandString(test_input, &result) catch unreachable; + + try testing.expectEqualSlices(u8, expected_result, result.items); +} diff --git a/test/standalone/brace_expansion/build.zig b/test/standalone/brace_expansion/build.zig @@ -1,11 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.Build) void { - const main = b.addTest(.{ - .root_source_file = .{ .path = "main.zig" }, - .optimize = b.standardOptimizeOption(.{}), - }); - - const test_step = b.step("test", "Test it"); - test_step.dependOn(&main.step); -} diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig @@ -1,292 +0,0 @@ -const std = @import("std"); -const io = std.io; -const mem = std.mem; -const debug = std.debug; -const assert = debug.assert; -const testing = std.testing; -const ArrayList = std.ArrayList; -const maxInt = std.math.maxInt; - -const Token = union(enum) { - Word: []const u8, - OpenBrace, - CloseBrace, - Comma, - Eof, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -var global_allocator = gpa.allocator(); - -fn tokenize(input: []const u8) !ArrayList(Token) { - const State = enum { - Start, - Word, - }; - - var token_list = ArrayList(Token).init(global_allocator); - errdefer token_list.deinit(); - var tok_begin: usize = undefined; - var state = State.Start; - - for (input, 0..) |b, i| { - switch (state) { - .Start => switch (b) { - 'a'...'z', 'A'...'Z' => { - state = State.Word; - tok_begin = i; - }, - '{' => try token_list.append(Token.OpenBrace), - '}' => try token_list.append(Token.CloseBrace), - ',' => try token_list.append(Token.Comma), - else => return error.InvalidInput, - }, - .Word => switch (b) { - 'a'...'z', 'A'...'Z' => {}, - '{', '}', ',' => { - try token_list.append(Token{ .Word = input[tok_begin..i] }); - switch (b) { - '{' => try token_list.append(Token.OpenBrace), - '}' => try token_list.append(Token.CloseBrace), - ',' => try token_list.append(Token.Comma), - else => unreachable, - } - state = State.Start; - }, - else => return error.InvalidInput, - }, - } - } - switch (state) { - State.Start => {}, - State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }), - } - try token_list.append(Token.Eof); - return token_list; -} - -const Node = union(enum) { - Scalar: []const u8, - List: ArrayList(Node), - Combine: []Node, - - fn deinit(self: Node) void { - switch (self) { - .Scalar => {}, - .Combine => |pair| { - pair[0].deinit(); - pair[1].deinit(); - global_allocator.free(pair); - }, - .List => |list| { - for (list.items) |item| { - item.deinit(); - } - list.deinit(); - }, - } - } -}; - -const ParseError = error{ - InvalidInput, - OutOfMemory, -}; - -fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node { - const first_token = tokens.items[token_index.*]; - token_index.* += 1; - - const result_node = switch (first_token) { - .Word => |word| Node{ .Scalar = word }, - .OpenBrace => blk: { - var list = ArrayList(Node).init(global_allocator); - errdefer { - for (list.items) |node| node.deinit(); - list.deinit(); - } - while (true) { - try list.append(try parse(tokens, token_index)); - - const token = tokens.items[token_index.*]; - token_index.* += 1; - - switch (token) { - .CloseBrace => break, - .Comma => continue, - else => return error.InvalidInput, - } - } - break :blk Node{ .List = list }; - }, - else => return error.InvalidInput, - }; - - switch (tokens.items[token_index.*]) { - .Word, .OpenBrace => { - const pair = try global_allocator.alloc(Node, 2); - errdefer global_allocator.free(pair); - pair[0] = result_node; - pair[1] = try parse(tokens, token_index); - return Node{ .Combine = pair }; - }, - else => return result_node, - } -} - -fn expandString(input: []const u8, output: *ArrayList(u8)) !void { - const tokens = try tokenize(input); - defer tokens.deinit(); - if (tokens.items.len == 1) { - return output.resize(0); - } - - var token_index: usize = 0; - const root = try parse(&tokens, &token_index); - defer root.deinit(); - const last_token = tokens.items[token_index]; - switch (last_token) { - Token.Eof => {}, - else => return error.InvalidInput, - } - - var result_list = ArrayList(ArrayList(u8)).init(global_allocator); - defer { - for (result_list.items) |*buf| buf.deinit(); - result_list.deinit(); - } - - try expandNode(root, &result_list); - - try output.resize(0); - for (result_list.items, 0..) |buf, i| { - if (i != 0) { - try output.append(' '); - } - try output.appendSlice(buf.items); - } -} - -const ExpandNodeError = error{OutOfMemory}; - -fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void { - assert(output.items.len == 0); - switch (node) { - .Scalar => |scalar| { - var list = ArrayList(u8).init(global_allocator); - errdefer list.deinit(); - try list.appendSlice(scalar); - try output.append(list); - }, - .Combine => |pair| { - const a_node = pair[0]; - const b_node = pair[1]; - - var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator); - defer { - for (child_list_a.items) |*buf| buf.deinit(); - child_list_a.deinit(); - } - try expandNode(a_node, &child_list_a); - - var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator); - defer { - for (child_list_b.items) |*buf| buf.deinit(); - child_list_b.deinit(); - } - try expandNode(b_node, &child_list_b); - - for (child_list_a.items) |buf_a| { - for (child_list_b.items) |buf_b| { - var combined_buf = ArrayList(u8).init(global_allocator); - errdefer combined_buf.deinit(); - - try combined_buf.appendSlice(buf_a.items); - try combined_buf.appendSlice(buf_b.items); - try output.append(combined_buf); - } - } - }, - .List => |list| { - for (list.items) |child_node| { - var child_list = ArrayList(ArrayList(u8)).init(global_allocator); - errdefer for (child_list.items) |*buf| buf.deinit(); - defer child_list.deinit(); - - try expandNode(child_node, &child_list); - - for (child_list.items) |buf| { - try output.append(buf); - } - } - }, - } -} - -pub fn main() !void { - defer _ = gpa.deinit(); - const stdin_file = io.getStdIn(); - const stdout_file = io.getStdOut(); - - const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize)); - defer global_allocator.free(stdin); - - var result_buf = ArrayList(u8).init(global_allocator); - defer result_buf.deinit(); - - try expandString(stdin.items, &result_buf); - try stdout_file.write(result_buf.items); -} - -test "invalid inputs" { - global_allocator = std.testing.allocator; - - try expectError("}ABC", error.InvalidInput); - try expectError("{ABC", error.InvalidInput); - try expectError("}{", error.InvalidInput); - try expectError("{}", error.InvalidInput); - try expectError("A,B,C", error.InvalidInput); - try expectError("{A{B,C}", error.InvalidInput); - try expectError("{A,}", error.InvalidInput); - - try expectError("\n", error.InvalidInput); -} - -fn expectError(test_input: []const u8, expected_err: anyerror) !void { - var output_buf = ArrayList(u8).init(global_allocator); - defer output_buf.deinit(); - - try testing.expectError(expected_err, expandString(test_input, &output_buf)); -} - -test "valid inputs" { - global_allocator = std.testing.allocator; - - try expectExpansion("{x,y,z}", "x y z"); - try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By"); - try expectExpansion("{A,B{x,y}}", "A Bx By"); - - try expectExpansion("{ABC}", "ABC"); - try expectExpansion("{A,B,C}", "A B C"); - try expectExpansion("ABC", "ABC"); - - try expectExpansion("", ""); - try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh"); - try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh"); - try expectExpansion("{A,B}a", "Aa Ba"); - try expectExpansion("{C,{x,y}}", "C x y"); - try expectExpansion("z{C,{x,y}}", "zC zx zy"); - try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg"); - try expectExpansion("a{x,y}b", "axb ayb"); - try expectExpansion("z{{a,b}}", "za zb"); - try expectExpansion("a{b}", "ab"); -} - -fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void { - var result = ArrayList(u8).init(global_allocator); - defer result.deinit(); - - expandString(test_input, &result) catch unreachable; - - try testing.expectEqualSlices(u8, expected_result, result.items); -} diff --git a/test/standalone/c_compiler/build.zig b/test/standalone/c_compiler/build.zig @@ -1,27 +1,24 @@ const std = @import("std"); const builtin = @import("builtin"); -const CrossTarget = std.zig.CrossTarget; -// TODO integrate this with the std.Build executor API -fn isRunnableTarget(t: CrossTarget) bool { - if (t.isNative()) return true; +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; - return (t.getOsTag() == builtin.os.tag and - t.getCpuArch() == builtin.cpu.arch); + add(b, test_step, .Debug); + add(b, test_step, .ReleaseFast); + add(b, test_step, .ReleaseSmall); + add(b, test_step, .ReleaseSafe); } -pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); - - const test_step = b.step("test", "Test the program"); +fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { + const target: std.zig.CrossTarget = .{}; const exe_c = b.addExecutable(.{ .name = "test_c", .optimize = optimize, .target = target, }); - b.default_step.dependOn(&exe_c.step); exe_c.addCSourceFile("test.c", &[0][]const u8{}); exe_c.linkLibC(); @@ -47,13 +44,13 @@ pub fn build(b: *std.Build) void { else => {}, } - if (isRunnableTarget(target)) { - const run_c_cmd = exe_c.run(); - test_step.dependOn(&run_c_cmd.step); - const run_cpp_cmd = exe_cpp.run(); - test_step.dependOn(&run_cpp_cmd.step); - } else { - test_step.dependOn(&exe_c.step); - test_step.dependOn(&exe_cpp.step); - } + const run_c_cmd = b.addRunArtifact(exe_c); + run_c_cmd.expectExitCode(0); + run_c_cmd.skip_foreign_checks = true; + test_step.dependOn(&run_c_cmd.step); + + const run_cpp_cmd = b.addRunArtifact(exe_cpp); + run_cpp_cmd.expectExitCode(0); + run_cpp_cmd.skip_foreign_checks = true; + test_step.dependOn(&run_cpp_cmd.step); } diff --git a/test/standalone/dep_diamond/build.zig b/test/standalone/dep_diamond/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const shared = b.createModule(.{ .source_file = .{ .path = "shared.zig" }, @@ -23,6 +26,5 @@ pub fn build(b: *std.Build) void { const run = exe.run(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/dep_mutually_recursive/build.zig b/test/standalone/dep_mutually_recursive/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const foo = b.createModule(.{ .source_file = .{ .path = "foo.zig" }, @@ -21,6 +24,5 @@ pub fn build(b: *std.Build) void { const run = exe.run(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/dep_recursive/build.zig b/test/standalone/dep_recursive/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const foo = b.createModule(.{ .source_file = .{ .path = "foo.zig" }, @@ -17,6 +20,5 @@ pub fn build(b: *std.Build) void { const run = exe.run(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/dep_shared_builtin/build.zig b/test/standalone/dep_shared_builtin/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const exe = b.addExecutable(.{ .name = "test", @@ -14,6 +17,5 @@ pub fn build(b: *std.Build) void { const run = exe.run(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/dep_triangle/build.zig b/test/standalone/dep_triangle/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const shared = b.createModule(.{ .source_file = .{ .path = "shared.zig" }, @@ -20,6 +23,5 @@ pub fn build(b: *std.Build) void { const run = exe.run(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/embed_generated_file/build.zig b/test/standalone/embed_generated_file/build.zig @@ -1,8 +1,8 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; const bootloader = b.addExecutable(.{ .name = "bootloader", @@ -16,13 +16,11 @@ pub fn build(b: *std.Build) void { const exe = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, - .target = target, - .optimize = optimize, + .optimize = .Debug, }); exe.addAnonymousModule("bootloader.elf", .{ .source_file = bootloader.getOutputSource(), }); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&exe.step); } diff --git a/test/standalone/emit_asm_and_bin/build.zig b/test/standalone/emit_asm_and_bin/build.zig @@ -1,6 +1,9 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = b.standardOptimizeOption(.{}), @@ -8,6 +11,5 @@ pub fn build(b: *std.Build) void { main.emit_asm = .{ .emit_to = b.pathFromRoot("main.s") }; main.emit_bin = .{ .emit_to = b.pathFromRoot("main") }; - const test_step = b.step("test", "Run test"); test_step.dependOn(&main.step); } diff --git a/test/standalone/empty_env/build.zig b/test/standalone/empty_env/build.zig @@ -1,15 +1,25 @@ const std = @import("std"); +const builtin = @import("builtin"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + + if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64) { + // https://github.com/ziglang/zig/issues/13685 + return; + } + const main = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, - .optimize = b.standardOptimizeOption(.{}), + .optimize = optimize, }); - const run = main.run(); + const run = b.addRunArtifact(main); run.clearEnvironment(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/global_linkage/build.zig b/test/standalone/global_linkage/build.zig @@ -1,20 +1,24 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test the program"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; const obj1 = b.addStaticLibrary(.{ .name = "obj1", .root_source_file = .{ .path = "obj1.zig" }, .optimize = optimize, - .target = .{}, + .target = target, }); const obj2 = b.addStaticLibrary(.{ .name = "obj2", .root_source_file = .{ .path = "obj2.zig" }, .optimize = optimize, - .target = .{}, + .target = target, }); const main = b.addTest(.{ @@ -24,6 +28,5 @@ pub fn build(b: *std.Build) void { main.linkLibrary(obj1); main.linkLibrary(obj2); - const test_step = b.step("test", "Test it"); test_step.dependOn(&main.step); } diff --git a/test/standalone/install_raw_hex/build.zig b/test/standalone/install_raw_hex/build.zig @@ -3,8 +3,8 @@ const std = @import("std"); const CheckFileStep = std.Build.CheckFileStep; pub fn build(b: *std.Build) void { - const test_step = b.step("test", "Test the program"); - b.default_step.dependOn(test_step); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; const target = .{ .cpu_arch = .thumb, @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { .abi = .gnueabihf, }; - const optimize = b.standardOptimizeOption(.{}); + const optimize: std.builtin.OptimizeMode = .Debug; const elf = b.addExecutable(.{ .name = "zig-nrf52-blink.elf", diff --git a/test/standalone/issue_11595/build.zig b/test/standalone/issue_11595/build.zig @@ -1,18 +1,17 @@ const std = @import("std"); const builtin = @import("builtin"); -const CrossTarget = std.zig.CrossTarget; -// TODO integrate this with the std.Build executor API -fn isRunnableTarget(t: CrossTarget) bool { - if (t.isNative()) return true; +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; - return (t.getOsTag() == builtin.os.tag and - t.getCpuArch() == builtin.cpu.arch); -} + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; -pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); + if (builtin.os.tag == .windows) { + // https://github.com/ziglang/zig/issues/12419 + return; + } const exe = b.addExecutable(.{ .name = "zigtest", @@ -44,11 +43,9 @@ pub fn build(b: *std.Build) void { b.default_step.dependOn(&exe.step); - const test_step = b.step("test", "Test the program"); - if (isRunnableTarget(target)) { - const run_cmd = exe.run(); - test_step.dependOn(&run_cmd.step); - } else { - test_step.dependOn(&exe.step); - } + const run_cmd = b.addRunArtifact(exe); + run_cmd.skip_foreign_checks = true; + run_cmd.expectExitCode(0); + + test_step.dependOn(&run_cmd.step); } diff --git a/test/standalone/issue_12588/build.zig b/test/standalone/issue_12588/build.zig @@ -1,8 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; const obj = b.addObject(.{ .name = "main", @@ -15,6 +18,5 @@ pub fn build(b: *std.Build) void { obj.emit_bin = .no_emit; b.default_step.dependOn(&obj.step); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&obj.step); } diff --git a/test/standalone/issue_12706/build.zig b/test/standalone/issue_12706/build.zig @@ -2,17 +2,12 @@ const std = @import("std"); const builtin = @import("builtin"); const CrossTarget = std.zig.CrossTarget; -// TODO integrate this with the std.Build executor API -fn isRunnableTarget(t: CrossTarget) bool { - if (t.isNative()) return true; - - return (t.getOsTag() == builtin.os.tag and - t.getCpuArch() == builtin.cpu.arch); -} - pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; const exe = b.addExecutable(.{ .name = "main", @@ -20,22 +15,15 @@ pub fn build(b: *std.Build) void { .optimize = optimize, .target = target, }); - exe.install(); const c_sources = [_][]const u8{ "test.c", }; - exe.addCSourceFiles(&c_sources, &.{}); exe.linkLibC(); - b.default_step.dependOn(&exe.step); - - const test_step = b.step("test", "Test the program"); - if (isRunnableTarget(target)) { - const run_cmd = exe.run(); - test_step.dependOn(&run_cmd.step); - } else { - test_step.dependOn(&exe.step); - } + const run_cmd = b.addRunArtifact(exe); + run_cmd.expectExitCode(0); + run_cmd.skip_foreign_checks = true; + test_step.dependOn(&run_cmd.step); } diff --git a/test/standalone/issue_13030/build.zig b/test/standalone/issue_13030/build.zig @@ -3,17 +3,22 @@ const builtin = @import("builtin"); const CrossTarget = std.zig.CrossTarget; pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + add(b, test_step, .Debug); + add(b, test_step, .ReleaseFast); + add(b, test_step, .ReleaseSmall); + add(b, test_step, .ReleaseSafe); +} + +fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { const obj = b.addObject(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = target, + .target = .{}, }); - b.default_step.dependOn(&obj.step); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&obj.step); } diff --git a/test/standalone/issue_13970/build.zig b/test/standalone/issue_13970/build.zig @@ -1,6 +1,9 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + const test1 = b.addTest(.{ .root_source_file = .{ .path = "test_root/empty.zig" }, }); @@ -14,7 +17,6 @@ pub fn build(b: *std.Build) void { test2.setTestRunner("src/main.zig"); test3.setTestRunner("src/main.zig"); - const test_step = b.step("test", "Test package path resolution of custom test runner"); test_step.dependOn(&test1.step); test_step.dependOn(&test2.step); test_step.dependOn(&test3.step); diff --git a/test/standalone/issue_339/build.zig b/test/standalone/issue_339/build.zig @@ -1,13 +1,18 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; + const obj = b.addObject(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, - .target = b.standardTargetOptions(.{}), - .optimize = b.standardOptimizeOption(.{}), + .target = target, + .optimize = optimize, }); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&obj.step); } diff --git a/test/standalone/issue_5825/build.zig b/test/standalone/issue_5825/build.zig @@ -1,12 +1,15 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + const target = .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .msvc, }; - const optimize = b.standardOptimizeOption(.{}); + const optimize: std.builtin.OptimizeMode = .Debug; const obj = b.addObject(.{ .name = "issue_5825", .root_source_file = .{ .path = "main.zig" }, @@ -24,6 +27,5 @@ pub fn build(b: *std.Build) void { exe.linkSystemLibrary("ntdll"); exe.addObject(obj); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&exe.step); } diff --git a/test/standalone/issue_7030/main.zig b/test/standalone/issue_7030.zig diff --git a/test/standalone/issue_7030/build.zig b/test/standalone/issue_7030/build.zig @@ -1,17 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.Build) void { - const exe = b.addExecutable(.{ - .name = "issue_7030", - .root_source_file = .{ .path = "main.zig" }, - .target = .{ - .cpu_arch = .wasm32, - .os_tag = .freestanding, - }, - }); - exe.install(); - b.default_step.dependOn(&exe.step); - - const test_step = b.step("test", "Test the program"); - test_step.dependOn(&exe.step); -} diff --git a/test/standalone/issue_794/build.zig b/test/standalone/issue_794/build.zig @@ -1,13 +1,13 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + const test_artifact = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, }); test_artifact.addIncludePath("a_directory"); - b.default_step.dependOn(&test_artifact.step); - - const test_step = b.step("test", "Test the program"); test_step.dependOn(&test_artifact.step); } diff --git a/test/standalone/issue_8550/build.zig b/test/standalone/issue_8550/build.zig @@ -1,6 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) !void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const target = std.zig.CrossTarget{ .os_tag = .freestanding, .cpu_arch = .arm, @@ -8,7 +12,7 @@ pub fn build(b: *std.Build) !void { .explicit = &std.Target.arm.cpu.arm1176jz_s, }, }; - const optimize = b.standardOptimizeOption(.{}); + const kernel = b.addExecutable(.{ .name = "kernel", .root_source_file = .{ .path = "./main.zig" }, @@ -19,6 +23,5 @@ pub fn build(b: *std.Build) !void { kernel.setLinkerScriptPath(.{ .path = "./linker.ld" }); kernel.install(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&kernel.step); } diff --git a/test/standalone/issue_9812/build.zig b/test/standalone/issue_9812/build.zig @@ -1,7 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build) !void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const zip_add = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, @@ -13,6 +17,5 @@ pub fn build(b: *std.Build) !void { zip_add.addIncludePath("vendor/kuba-zip"); zip_add.linkLibC(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&zip_add.step); } diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig @@ -1,8 +1,19 @@ const std = @import("std"); +const builtin = @import("builtin"); pub fn build(b: *std.Build) void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; + + const ok = (builtin.os.tag != .wasi and + // https://github.com/ziglang/zig/issues/13550 + (builtin.os.tag != .macos or builtin.cpu.arch != .aarch64) and + // https://github.com/ziglang/zig/issues/13686 + (builtin.os.tag != .windows or builtin.cpu.arch != .aarch64)); + if (!ok) return; const lib = b.addSharedLibrary(.{ .name = "add", @@ -19,9 +30,10 @@ pub fn build(b: *std.Build) void { .target = target, }); - const run = main.run(); + const run = b.addRunArtifact(main); run.addArtifactArg(lib); + run.skip_foreign_checks = true; + run.expectExitCode(0); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&run.step); } diff --git a/test/standalone/load_dynamic_library/main.zig b/test/standalone/load_dynamic_library/main.zig @@ -11,11 +11,7 @@ pub fn main() !void { var lib = try std.DynLib.open(dynlib_name); defer lib.close(); - const Add = switch (@import("builtin").zig_backend) { - .stage1 => fn (i32, i32) callconv(.C) i32, - else => *const fn (i32, i32) callconv(.C) i32, - }; - + const Add = *const fn (i32, i32) callconv(.C) i32; const addFn = lib.lookup(Add, "add") orelse return error.SymbolNotFound; const result = addFn(12, 34); diff --git a/test/standalone/main_pkg_path/build.zig b/test/standalone/main_pkg_path/build.zig @@ -1,11 +1,13 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + const test_exe = b.addTest(.{ .root_source_file = .{ .path = "a/test.zig" }, }); test_exe.setMainPkgPath("."); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&test_exe.step); } diff --git a/test/standalone/mix_c_files/build.zig b/test/standalone/mix_c_files/build.zig @@ -1,34 +1,28 @@ const std = @import("std"); -const builtin = @import("builtin"); -const CrossTarget = std.zig.CrossTarget; -// TODO integrate this with the std.Build executor API -fn isRunnableTarget(t: CrossTarget) bool { - if (t.isNative()) return true; +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; - return (t.getOsTag() == builtin.os.tag and - t.getCpuArch() == builtin.cpu.arch); + add(b, test_step, .Debug); + add(b, test_step, .ReleaseFast); + add(b, test_step, .ReleaseSmall); + add(b, test_step, .ReleaseSafe); } -pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); - +fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = target, }); exe.addCSourceFile("test.c", &[_][]const u8{"-std=c11"}); exe.linkLibC(); b.default_step.dependOn(&exe.step); - const test_step = b.step("test", "Test the program"); - if (isRunnableTarget(target)) { - const run_cmd = exe.run(); - test_step.dependOn(&run_cmd.step); - } else { - test_step.dependOn(&exe.step); - } + const run_cmd = b.addRunArtifact(exe); + run_cmd.skip_foreign_checks = true; + run_cmd.expectExitCode(0); + + test_step.dependOn(&run_cmd.step); } diff --git a/test/standalone/mix_o_files/build.zig b/test/standalone/mix_o_files/build.zig @@ -1,18 +1,23 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; const obj = b.addObject(.{ .name = "base64", .root_source_file = .{ .path = "base64.zig" }, .optimize = optimize, - .target = .{}, + .target = target, }); const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, + .target = target, }); exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"}); exe.addObject(obj); @@ -22,6 +27,5 @@ pub fn build(b: *std.Build) void { const run_cmd = exe.run(); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&run_cmd.step); } diff --git a/test/standalone/pie/build.zig b/test/standalone/pie/build.zig @@ -1,14 +1,21 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{ + .os_tag = .linux, + .cpu_arch = .x86_64, + }; + const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, - .optimize = b.standardOptimizeOption(.{}), + .optimize = optimize, + .target = target, }); main.pie = true; - const test_step = b.step("test", "Test the program"); test_step.dependOn(&main.step); - - b.default_step.dependOn(test_step); } diff --git a/test/standalone/pkg_import/build.zig b/test/standalone/pkg_import/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const exe = b.addExecutable(.{ .name = "test", @@ -12,6 +15,5 @@ pub fn build(b: *std.Build) void { const run = exe.run(); - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/standalone/shared_library/build.zig b/test/standalone/shared_library/build.zig @@ -1,8 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - const target = b.standardTargetOptions(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{}; const lib = b.addSharedLibrary(.{ .name = "mathtest", .root_source_file = .{ .path = "mathtest.zig" }, @@ -20,10 +23,7 @@ pub fn build(b: *std.Build) void { exe.linkLibrary(lib); exe.linkSystemLibrary("c"); - b.default_step.dependOn(&exe.step); - const run_cmd = exe.run(); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&run_cmd.step); } diff --git a/test/standalone/sigpipe/build.zig b/test/standalone/sigpipe/build.zig @@ -2,7 +2,16 @@ const std = @import("std"); const os = std.os; pub fn build(b: *std.build.Builder) !void { - const test_step = b.step("test", "Run the tests"); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + // TODO signal handling code has no business being in a build script. + // this logic needs to move to a file called parent.zig which is + // added as an executable. + + //if (!std.os.have_sigpipe_support) { + // return; + //} // This test runs "breakpipe" as a child process and that process // depends on inheriting a SIGPIPE disposition of "default". diff --git a/test/standalone/static_c_lib/build.zig b/test/standalone/static_c_lib/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; const foo = b.addStaticLibrary(.{ .name = "foo", @@ -18,6 +21,5 @@ pub fn build(b: *std.Build) void { test_exe.linkLibrary(foo); test_exe.addIncludePath("."); - const test_step = b.step("test", "Test it"); test_step.dependOn(&test_exe.step); } diff --git a/test/standalone/test_runner_path/build.zig b/test/standalone/test_runner_path/build.zig @@ -1,6 +1,11 @@ const std = @import("std"); +pub const requires_stage2 = true; + pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test the program"); + b.default_step = test_step; + const test_exe = b.addTest(.{ .root_source_file = .{ .path = "test.zig" }, .kind = .test_exe, @@ -9,6 +14,5 @@ pub fn build(b: *std.Build) void { const test_run = test_exe.run(); - const test_step = b.step("test", "Test the program"); test_step.dependOn(&test_run.step); } diff --git a/test/standalone/test_runner_path/test_runner.zig b/test/standalone/test_runner_path/test_runner.zig @@ -1,51 +1,19 @@ const std = @import("std"); -const io = std.io; const builtin = @import("builtin"); -pub const io_mode: io.Mode = builtin.test_io_mode; - pub fn main() void { - const test_fn_list = builtin.test_functions; var ok_count: usize = 0; var skip_count: usize = 0; var fail_count: usize = 0; - var async_frame_buffer: []align(std.Target.stack_align) u8 = undefined; - // TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly - // ignores the alignment of the slice. - async_frame_buffer = &[_]u8{}; - - for (test_fn_list) |test_fn| { - const result = if (test_fn.async_frame_size) |size| switch (io_mode) { - .evented => blk: { - if (async_frame_buffer.len < size) { - std.heap.page_allocator.free(async_frame_buffer); - async_frame_buffer = std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size) catch @panic("out of memory"); - } - const casted_fn = @ptrCast(fn () callconv(.Async) anyerror!void, test_fn.func); - break :blk await @asyncCall(async_frame_buffer, {}, casted_fn, .{}); - }, - .blocking => { - skip_count += 1; - continue; - }, - } else test_fn.func(); - if (result) |_| { + for (builtin.test_functions) |test_fn| { + if (test_fn.func()) |_| { ok_count += 1; } else |err| switch (err) { - error.SkipZigTest => { - skip_count += 1; - }, - else => { - fail_count += 1; - }, + error.SkipZigTest => skip_count += 1, + else => fail_count += 1, } } - if (ok_count == test_fn_list.len) { - std.debug.print("All {d} tests passed.\n", .{ok_count}); - } else { - std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); - } if (ok_count != 1 or skip_count != 1 or fail_count != 1) { std.process.exit(1); } diff --git a/test/standalone/use_alias/build.zig b/test/standalone/use_alias/build.zig @@ -1,12 +1,16 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, - .optimize = b.standardOptimizeOption(.{}), + .optimize = optimize, }); main.addIncludePath("."); - const test_step = b.step("test", "Test it"); test_step.dependOn(&main.step); } diff --git a/test/standalone/windows_spawn/build.zig b/test/standalone/windows_spawn/build.zig @@ -1,23 +1,34 @@ const std = @import("std"); +const builtin = @import("builtin"); pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const optimize: std.builtin.OptimizeMode = .Debug; + const target: std.zig.CrossTarget = .{ + .os_tag = .windows, + .cpu_arch = .x86_64, + }; const hello = b.addExecutable(.{ .name = "hello", .root_source_file = .{ .path = "hello.zig" }, .optimize = optimize, + .target = target, }); const main = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, + .target = target, }); - const run = main.run(); + const run = b.addRunArtifact(main); run.addArtifactArg(hello); + run.expectExitCode(0); + run.skip_foreign_checks = true; - const test_step = b.step("test", "Test it"); test_step.dependOn(&run.step); } diff --git a/test/tests.zig b/test/tests.zig @@ -560,34 +560,62 @@ pub fn addStackTraceTests( pub fn addStandaloneTests( b: *std.Build, - test_filter: ?[]const u8, optimize_modes: []const OptimizeMode, - skip_non_native: bool, enable_macos_sdk: bool, omit_stage2: bool, enable_symlinks_windows: bool, ) *Step { const step = b.step("test-standalone", "Run the standalone tests"); - - _ = test_filter; - _ = skip_non_native; - _ = enable_macos_sdk; - _ = omit_stage2; - _ = enable_symlinks_windows; + const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows; for (standalone.simple_cases) |case| { for (optimize_modes) |optimize| { if (!case.all_modes and optimize != .Debug) continue; - const exe = b.addExecutable(.{ - .name = std.fs.path.stem(case.src_path), - .root_source_file = .{ .path = case.src_path }, - .optimize = optimize, - .target = case.target, - }); - if (case.link_libc) exe.linkLibC(); + if (case.is_exe) { + const exe = b.addExecutable(.{ + .name = std.fs.path.stem(case.src_path), + .root_source_file = .{ .path = case.src_path }, + .optimize = optimize, + .target = case.target, + }); + if (case.link_libc) exe.linkLibC(); + + step.dependOn(&exe.step); + } - step.dependOn(&exe.step); + if (case.is_test) { + const exe = b.addTest(.{ + .name = std.fs.path.stem(case.src_path), + .root_source_file = .{ .path = case.src_path }, + .optimize = optimize, + .target = case.target, + }); + if (case.link_libc) exe.linkLibC(); + + step.dependOn(&exe.step); + } + } + } + + inline for (standalone.build_cases) |case| { + const requires_stage2 = @hasDecl(case.import, "requires_stage2") and + case.import.requires_stage2; + const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and + case.import.requires_symlinks; + const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and + case.import.requires_macos_sdk; + const bad = + (requires_stage2 and omit_stage2) or + (requires_symlinks and omit_symlinks) or + (requires_macos_sdk and !enable_macos_sdk); + if (!bad) { + const dep = b.anonymousDependency(case.build_root, case.import, .{}); + const dep_step = dep.builder.default_step; + assert(mem.startsWith(u8, dep.builder.dep_prefix, "test.")); + const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..]; + dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name }); + step.dependOn(dep_step); } } @@ -603,19 +631,19 @@ pub fn addLinkTests( const step = b.step("test-link", "Run the linker tests"); const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows; - inline for (link.cases) |link_test| { - const requires_stage2 = @hasDecl(link_test.import, "requires_stage2") and - link_test.import.requires_stage2; - const requires_symlinks = @hasDecl(link_test.import, "requires_symlinks") and - link_test.import.requires_symlinks; - const requires_macos_sdk = @hasDecl(link_test.import, "requires_macos_sdk") and - link_test.import.requires_macos_sdk; + inline for (link.cases) |case| { + const requires_stage2 = @hasDecl(case.import, "requires_stage2") and + case.import.requires_stage2; + const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and + case.import.requires_symlinks; + const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and + case.import.requires_macos_sdk; const bad = (requires_stage2 and omit_stage2) or (requires_symlinks and omit_symlinks) or (requires_macos_sdk and !enable_macos_sdk); if (!bad) { - const dep = b.anonymousDependency(link_test.build_root, link_test.import, .{}); + const dep = b.anonymousDependency(case.build_root, case.import, .{}); const dep_step = dep.builder.default_step; assert(mem.startsWith(u8, dep.builder.dep_prefix, "test.")); const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..]; @@ -627,9 +655,7 @@ pub fn addLinkTests( return step; } -pub fn addCliTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step { - _ = test_filter; - _ = optimize_modes; +pub fn addCliTests(b: *std.Build) *Step { const step = b.step("test-cli", "Test the command line interface"); { @@ -815,6 +841,19 @@ pub fn addCliTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []co step.dependOn(&cleanup.step); } + { + // TODO this should move to become a CLI test rather than standalone + // cases.addBuildFile("test/standalone/options/build.zig", .{ + // .extra_argv = &.{ + // "-Dbool_true", + // "-Dbool_false=false", + // "-Dint=1234", + // "-De=two", + // "-Dstring=hello", + // }, + // }); + } + return step; }