authorgravatar for carl@astholm.seCarl Åstholm <carl@astholm.se> 2024-01-16 18:20:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-07 16:05:54-07:00
logd6ecfa7025e07dde07f73844258b95cace247406
treebc6b5db21943290e0c2a43f5dbb892a3c028c7e6
parent3ed221f1494be00cc802515e33e18fdd80d41afb

Move "simple" standalone test cases to a new directory


28 files changed, 531 insertions(+), 528 deletions(-)

test/standalone.zig+14-14
......@@ -11,43 +11,43 @@ pub const SimpleCase = struct {
1111
1212pub const simple_cases = [_]SimpleCase{
1313 .{
14 .src_path = "test/standalone/hello_world/hello.zig",
14 .src_path = "test/standalone/simple/hello_world/hello.zig",
1515 .all_modes = true,
1616 },
1717 .{
18 .src_path = "test/standalone/hello_world/hello_libc.zig",
18 .src_path = "test/standalone/simple/hello_world/hello_libc.zig",
1919 .link_libc = true,
2020 .all_modes = true,
2121 },
2222 .{
23 .src_path = "test/standalone/cat/main.zig",
23 .src_path = "test/standalone/simple/cat/main.zig",
2424 },
2525 // https://github.com/ziglang/zig/issues/6025
2626 //.{
27 // .src_path = "test/standalone/issue_9693/main.zig",
27 // .src_path = "test/standalone/simple/issue_9693/main.zig",
2828 //},
2929 .{
30 .src_path = "test/standalone/brace_expansion.zig",
30 .src_path = "test/standalone/simple/brace_expansion.zig",
3131 .is_test = true,
3232 },
3333 .{
34 .src_path = "test/standalone/issue_7030.zig",
34 .src_path = "test/standalone/simple/issue_7030.zig",
3535 .target = .{
3636 .cpu_arch = .wasm32,
3737 .os_tag = .freestanding,
3838 },
3939 },
4040
41 .{ .src_path = "test/standalone/issue_12471/main.zig" },
42 .{ .src_path = "test/standalone/guess_number/main.zig" },
43 .{ .src_path = "test/standalone/main_return_error/error_u8.zig" },
44 .{ .src_path = "test/standalone/main_return_error/error_u8_non_zero.zig" },
45 .{ .src_path = "test/standalone/noreturn_call/inline.zig" },
46 .{ .src_path = "test/standalone/noreturn_call/as_arg.zig" },
47 .{ .src_path = "test/standalone/std_enums_big_enums.zig" },
41 .{ .src_path = "test/standalone/simple/issue_12471/main.zig" },
42 .{ .src_path = "test/standalone/simple/guess_number/main.zig" },
43 .{ .src_path = "test/standalone/simple/main_return_error/error_u8.zig" },
44 .{ .src_path = "test/standalone/simple/main_return_error/error_u8_non_zero.zig" },
45 .{ .src_path = "test/standalone/simple/noreturn_call/inline.zig" },
46 .{ .src_path = "test/standalone/simple/noreturn_call/as_arg.zig" },
47 .{ .src_path = "test/standalone/simple/std_enums_big_enums.zig" },
4848
4949 .{
50 .src_path = "test/standalone/issue_9402/main.zig",
50 .src_path = "test/standalone/simple/issue_9402/main.zig",
5151 .os_filter = .windows,
5252 .link_libc = true,
5353 },
test/standalone/brace_expansion.zig deleted-292
......@@ -1,292 +0,0 @@
1const std = @import("std");
2const io = std.io;
3const mem = std.mem;
4const debug = std.debug;
5const assert = debug.assert;
6const testing = std.testing;
7const ArrayList = std.ArrayList;
8const maxInt = std.math.maxInt;
9
10const Token = union(enum) {
11 Word: []const u8,
12 OpenBrace,
13 CloseBrace,
14 Comma,
15 Eof,
16};
17
18var gpa = std.heap.GeneralPurposeAllocator(.{}){};
19var global_allocator = gpa.allocator();
20
21fn tokenize(input: []const u8) !ArrayList(Token) {
22 const State = enum {
23 Start,
24 Word,
25 };
26
27 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
29 var tok_begin: usize = undefined;
30 var state = State.Start;
31
32 for (input, 0..) |b, i| {
33 switch (state) {
34 .Start => switch (b) {
35 'a'...'z', 'A'...'Z' => {
36 state = State.Word;
37 tok_begin = i;
38 },
39 '{' => try token_list.append(Token.OpenBrace),
40 '}' => try token_list.append(Token.CloseBrace),
41 ',' => try token_list.append(Token.Comma),
42 else => return error.InvalidInput,
43 },
44 .Word => switch (b) {
45 'a'...'z', 'A'...'Z' => {},
46 '{', '}', ',' => {
47 try token_list.append(Token{ .Word = input[tok_begin..i] });
48 switch (b) {
49 '{' => try token_list.append(Token.OpenBrace),
50 '}' => try token_list.append(Token.CloseBrace),
51 ',' => try token_list.append(Token.Comma),
52 else => unreachable,
53 }
54 state = State.Start;
55 },
56 else => return error.InvalidInput,
57 },
58 }
59 }
60 switch (state) {
61 State.Start => {},
62 State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
63 }
64 try token_list.append(Token.Eof);
65 return token_list;
66}
67
68const Node = union(enum) {
69 Scalar: []const u8,
70 List: ArrayList(Node),
71 Combine: []Node,
72
73 fn deinit(self: Node) void {
74 switch (self) {
75 .Scalar => {},
76 .Combine => |pair| {
77 pair[0].deinit();
78 pair[1].deinit();
79 global_allocator.free(pair);
80 },
81 .List => |list| {
82 for (list.items) |item| {
83 item.deinit();
84 }
85 list.deinit();
86 },
87 }
88 }
89};
90
91const ParseError = error{
92 InvalidInput,
93 OutOfMemory,
94};
95
96fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
97 const first_token = tokens.items[token_index.*];
98 token_index.* += 1;
99
100 const result_node = switch (first_token) {
101 .Word => |word| Node{ .Scalar = word },
102 .OpenBrace => blk: {
103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
108 while (true) {
109 try list.append(try parse(tokens, token_index));
110
111 const token = tokens.items[token_index.*];
112 token_index.* += 1;
113
114 switch (token) {
115 .CloseBrace => break,
116 .Comma => continue,
117 else => return error.InvalidInput,
118 }
119 }
120 break :blk Node{ .List = list };
121 },
122 else => return error.InvalidInput,
123 };
124
125 switch (tokens.items[token_index.*]) {
126 .Word, .OpenBrace => {
127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
129 pair[0] = result_node;
130 pair[1] = try parse(tokens, token_index);
131 return Node{ .Combine = pair };
132 },
133 else => return result_node,
134 }
135}
136
137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
138 const tokens = try tokenize(input);
139 defer tokens.deinit();
140 if (tokens.items.len == 1) {
141 return output.resize(0);
142 }
143
144 var token_index: usize = 0;
145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
147 const last_token = tokens.items[token_index];
148 switch (last_token) {
149 Token.Eof => {},
150 else => return error.InvalidInput,
151 }
152
153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
158
159 try expandNode(root, &result_list);
160
161 try output.resize(0);
162 for (result_list.items, 0..) |buf, i| {
163 if (i != 0) {
164 try output.append(' ');
165 }
166 try output.appendSlice(buf.items);
167 }
168}
169
170const ExpandNodeError = error{OutOfMemory};
171
172fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void {
173 assert(output.items.len == 0);
174 switch (node) {
175 .Scalar => |scalar| {
176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
180 },
181 .Combine => |pair| {
182 const a_node = pair[0];
183 const b_node = pair[1];
184
185 var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator);
186 defer {
187 for (child_list_a.items) |*buf| buf.deinit();
188 child_list_a.deinit();
189 }
190 try expandNode(a_node, &child_list_a);
191
192 var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator);
193 defer {
194 for (child_list_b.items) |*buf| buf.deinit();
195 child_list_b.deinit();
196 }
197 try expandNode(b_node, &child_list_b);
198
199 for (child_list_a.items) |buf_a| {
200 for (child_list_b.items) |buf_b| {
201 var combined_buf = ArrayList(u8).init(global_allocator);
202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
206 try output.append(combined_buf);
207 }
208 }
209 },
210 .List => |list| {
211 for (list.items) |child_node| {
212 var child_list = ArrayList(ArrayList(u8)).init(global_allocator);
213 errdefer for (child_list.items) |*buf| buf.deinit();
214 defer child_list.deinit();
215
216 try expandNode(child_node, &child_list);
217
218 for (child_list.items) |buf| {
219 try output.append(buf);
220 }
221 }
222 },
223 }
224}
225
226pub fn main() !void {
227 defer _ = gpa.deinit();
228 const stdin_file = io.getStdIn();
229 const stdout_file = io.getStdOut();
230
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232 defer global_allocator.free(stdin);
233
234 var result_buf = ArrayList(u8).init(global_allocator);
235 defer result_buf.deinit();
236
237 try expandString(stdin, &result_buf);
238 try stdout_file.writeAll(result_buf.items);
239}
240
241test "invalid inputs" {
242 global_allocator = std.testing.allocator;
243
244 try expectError("}ABC", error.InvalidInput);
245 try expectError("{ABC", error.InvalidInput);
246 try expectError("}{", error.InvalidInput);
247 try expectError("{}", error.InvalidInput);
248 try expectError("A,B,C", error.InvalidInput);
249 try expectError("{A{B,C}", error.InvalidInput);
250 try expectError("{A,}", error.InvalidInput);
251
252 try expectError("\n", error.InvalidInput);
253}
254
255fn expectError(test_input: []const u8, expected_err: anyerror) !void {
256 var output_buf = ArrayList(u8).init(global_allocator);
257 defer output_buf.deinit();
258
259 try testing.expectError(expected_err, expandString(test_input, &output_buf));
260}
261
262test "valid inputs" {
263 global_allocator = std.testing.allocator;
264
265 try expectExpansion("{x,y,z}", "x y z");
266 try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
267 try expectExpansion("{A,B{x,y}}", "A Bx By");
268
269 try expectExpansion("{ABC}", "ABC");
270 try expectExpansion("{A,B,C}", "A B C");
271 try expectExpansion("ABC", "ABC");
272
273 try expectExpansion("", "");
274 try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
275 try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
276 try expectExpansion("{A,B}a", "Aa Ba");
277 try expectExpansion("{C,{x,y}}", "C x y");
278 try expectExpansion("z{C,{x,y}}", "zC zx zy");
279 try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
280 try expectExpansion("a{x,y}b", "axb ayb");
281 try expectExpansion("z{{a,b}}", "za zb");
282 try expectExpansion("a{b}", "ab");
283}
284
285fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void {
286 var result = ArrayList(u8).init(global_allocator);
287 defer result.deinit();
288
289 expandString(test_input, &result) catch unreachable;
290
291 try testing.expectEqualSlices(u8, expected_result, result.items);
292}
test/standalone/build.zig.zon+3
......@@ -2,6 +2,9 @@
22 .name = "standalone_test_cases",
33 .version = "0.0.0",
44 .dependencies = .{
5 // "Simple" test cases (those in the 'simple' directory) are configured by the root build
6 // script, outside of this package.
7
58 .test_runner_path = .{
69 .path = "test_runner_path",
710 },
test/standalone/cat/main.zig deleted-46
......@@ -1,46 +0,0 @@
1const std = @import("std");
2const io = std.io;
3const process = std.process;
4const fs = std.fs;
5const mem = std.mem;
6const warn = std.log.warn;
7
8pub fn main() !void {
9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena_instance.deinit();
11 const arena = arena_instance.allocator();
12
13 const args = try process.argsAlloc(arena);
14
15 const exe = args[0];
16 var catted_anything = false;
17 const stdout_file = io.getStdOut();
18
19 const cwd = fs.cwd();
20
21 for (args[1..]) |arg| {
22 if (mem.eql(u8, arg, "-")) {
23 catted_anything = true;
24 try stdout_file.writeFileAll(io.getStdIn(), .{});
25 } else if (mem.startsWith(u8, arg, "-")) {
26 return usage(exe);
27 } else {
28 const file = cwd.openFile(arg, .{}) catch |err| {
29 warn("Unable to open file: {s}\n", .{@errorName(err)});
30 return err;
31 };
32 defer file.close();
33
34 catted_anything = true;
35 try stdout_file.writeFileAll(file, .{});
36 }
37 }
38 if (!catted_anything) {
39 try stdout_file.writeFileAll(io.getStdIn(), .{});
40 }
41}
42
43fn usage(exe: []const u8) !void {
44 warn("Usage: {s} [FILE]...\n", .{exe});
45 return error.Invalid;
46}
test/standalone/guess_number/main.zig deleted-38
......@@ -1,38 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const io = std.io;
4const fmt = std.fmt;
5
6pub fn main() !void {
7 const stdout = io.getStdOut().writer();
8 const stdin = io.getStdIn();
9
10 try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});
11
12 const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1;
13
14 while (true) {
15 try stdout.print("\nGuess a number between 1 and 100: ", .{});
16 var line_buf: [20]u8 = undefined;
17
18 const amt = try stdin.read(&line_buf);
19 if (amt == line_buf.len) {
20 try stdout.print("Input too long.\n", .{});
21 continue;
22 }
23 const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n");
24
25 const guess = fmt.parseUnsigned(u8, line, 10) catch {
26 try stdout.print("Invalid number.\n", .{});
27 continue;
28 };
29 if (guess > answer) {
30 try stdout.print("Guess lower.\n", .{});
31 } else if (guess < answer) {
32 try stdout.print("Guess higher.\n", .{});
33 } else {
34 try stdout.print("You win!\n", .{});
35 return;
36 }
37 }
38}
test/standalone/hello_world/hello.zig deleted-5
......@@ -1,5 +0,0 @@
1const std = @import("std");
2
3pub fn main() !void {
4 try std.io.getStdOut().writeAll("Hello, World!\n");
5}
test/standalone/hello_world/hello_libc.zig deleted-15
......@@ -1,15 +0,0 @@
1const c = @cImport({
2 // See https://github.com/ziglang/zig/issues/515
3 @cDefine("_NO_CRT_STDIO_INLINE", "1");
4 @cInclude("stdio.h");
5 @cInclude("string.h");
6});
7
8const msg = "Hello, world!\n";
9
10pub export fn main(argc: c_int, argv: **u8) c_int {
11 _ = argv;
12 _ = argc;
13 if (c.printf(msg) != @as(c_int, @intCast(c.strlen(msg)))) return -1;
14 return 0;
15}
test/standalone/issue_12471/main.zig deleted-12
......@@ -1,12 +0,0 @@
1const c = @cImport({
2 @cDefine("FOO", "FOO");
3 @cDefine("BAR", "FOO");
4
5 @cDefine("BAZ", "QUX");
6 @cDefine("QUX", "QUX");
7});
8
9pub fn main() u8 {
10 _ = c;
11 return 0;
12}
test/standalone/issue_7030.zig deleted-21
......@@ -1,21 +0,0 @@
1const std = @import("std");
2
3pub const std_options = .{
4 .logFn = log,
5};
6
7pub fn log(
8 comptime message_level: std.log.Level,
9 comptime scope: @Type(.EnumLiteral),
10 comptime format: []const u8,
11 args: anytype,
12) void {
13 _ = message_level;
14 _ = scope;
15 _ = format;
16 _ = args;
17}
18
19pub fn main() anyerror!void {
20 std.log.info("All your codebase are belong to us.", .{});
21}
test/standalone/issue_9402/main.zig deleted-14
......@@ -1,14 +0,0 @@
1const FILE = extern struct {
2 dummy_field: u8,
3};
4
5extern fn _ftelli64([*c]FILE) i64;
6extern fn _fseeki64([*c]FILE, i64, c_int) c_int;
7
8pub export fn main(argc: c_int, argv: **u8) c_int {
9 _ = argv;
10 _ = argc;
11 _ = _ftelli64(null);
12 _ = _fseeki64(null, 123, 2);
13 return 0;
14}
test/standalone/main_return_error/error_u8.zig deleted-5
......@@ -1,5 +0,0 @@
1const Err = error{Foo};
2
3pub fn main() !u8 {
4 return Err.Foo;
5}
test/standalone/main_return_error/error_u8_non_zero.zig deleted-10
......@@ -1,10 +0,0 @@
1const Err = error{Foo};
2
3fn foo() u8 {
4 return @intCast(9);
5}
6
7pub fn main() !u8 {
8 if (foo() == 7) return Err.Foo;
9 return 123;
10}
test/standalone/noreturn_call/as_arg.zig deleted-8
......@@ -1,8 +0,0 @@
1const std = @import("std");
2fn foo() noreturn {
3 std.process.exit(0);
4}
5fn bar(_: u8, _: u8) void {}
6pub fn main() void {
7 bar(foo(), @compileError("bad"));
8}
test/standalone/noreturn_call/inline.zig deleted-10
......@@ -1,10 +0,0 @@
1pub fn main() void {
2 _ = bar();
3}
4inline fn bar() u8 {
5 noret();
6}
7const std = @import("std");
8inline fn noret() noreturn {
9 std.process.exit(0);
10}
test/standalone/simple/brace_expansion.zig created+292
......@@ -0,0 +1,292 @@
1const std = @import("std");
2const io = std.io;
3const mem = std.mem;
4const debug = std.debug;
5const assert = debug.assert;
6const testing = std.testing;
7const ArrayList = std.ArrayList;
8const maxInt = std.math.maxInt;
9
10const Token = union(enum) {
11 Word: []const u8,
12 OpenBrace,
13 CloseBrace,
14 Comma,
15 Eof,
16};
17
18var gpa = std.heap.GeneralPurposeAllocator(.{}){};
19var global_allocator = gpa.allocator();
20
21fn tokenize(input: []const u8) !ArrayList(Token) {
22 const State = enum {
23 Start,
24 Word,
25 };
26
27 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
29 var tok_begin: usize = undefined;
30 var state = State.Start;
31
32 for (input, 0..) |b, i| {
33 switch (state) {
34 .Start => switch (b) {
35 'a'...'z', 'A'...'Z' => {
36 state = State.Word;
37 tok_begin = i;
38 },
39 '{' => try token_list.append(Token.OpenBrace),
40 '}' => try token_list.append(Token.CloseBrace),
41 ',' => try token_list.append(Token.Comma),
42 else => return error.InvalidInput,
43 },
44 .Word => switch (b) {
45 'a'...'z', 'A'...'Z' => {},
46 '{', '}', ',' => {
47 try token_list.append(Token{ .Word = input[tok_begin..i] });
48 switch (b) {
49 '{' => try token_list.append(Token.OpenBrace),
50 '}' => try token_list.append(Token.CloseBrace),
51 ',' => try token_list.append(Token.Comma),
52 else => unreachable,
53 }
54 state = State.Start;
55 },
56 else => return error.InvalidInput,
57 },
58 }
59 }
60 switch (state) {
61 State.Start => {},
62 State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
63 }
64 try token_list.append(Token.Eof);
65 return token_list;
66}
67
68const Node = union(enum) {
69 Scalar: []const u8,
70 List: ArrayList(Node),
71 Combine: []Node,
72
73 fn deinit(self: Node) void {
74 switch (self) {
75 .Scalar => {},
76 .Combine => |pair| {
77 pair[0].deinit();
78 pair[1].deinit();
79 global_allocator.free(pair);
80 },
81 .List => |list| {
82 for (list.items) |item| {
83 item.deinit();
84 }
85 list.deinit();
86 },
87 }
88 }
89};
90
91const ParseError = error{
92 InvalidInput,
93 OutOfMemory,
94};
95
96fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
97 const first_token = tokens.items[token_index.*];
98 token_index.* += 1;
99
100 const result_node = switch (first_token) {
101 .Word => |word| Node{ .Scalar = word },
102 .OpenBrace => blk: {
103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
108 while (true) {
109 try list.append(try parse(tokens, token_index));
110
111 const token = tokens.items[token_index.*];
112 token_index.* += 1;
113
114 switch (token) {
115 .CloseBrace => break,
116 .Comma => continue,
117 else => return error.InvalidInput,
118 }
119 }
120 break :blk Node{ .List = list };
121 },
122 else => return error.InvalidInput,
123 };
124
125 switch (tokens.items[token_index.*]) {
126 .Word, .OpenBrace => {
127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
129 pair[0] = result_node;
130 pair[1] = try parse(tokens, token_index);
131 return Node{ .Combine = pair };
132 },
133 else => return result_node,
134 }
135}
136
137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
138 const tokens = try tokenize(input);
139 defer tokens.deinit();
140 if (tokens.items.len == 1) {
141 return output.resize(0);
142 }
143
144 var token_index: usize = 0;
145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
147 const last_token = tokens.items[token_index];
148 switch (last_token) {
149 Token.Eof => {},
150 else => return error.InvalidInput,
151 }
152
153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
158
159 try expandNode(root, &result_list);
160
161 try output.resize(0);
162 for (result_list.items, 0..) |buf, i| {
163 if (i != 0) {
164 try output.append(' ');
165 }
166 try output.appendSlice(buf.items);
167 }
168}
169
170const ExpandNodeError = error{OutOfMemory};
171
172fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void {
173 assert(output.items.len == 0);
174 switch (node) {
175 .Scalar => |scalar| {
176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
180 },
181 .Combine => |pair| {
182 const a_node = pair[0];
183 const b_node = pair[1];
184
185 var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator);
186 defer {
187 for (child_list_a.items) |*buf| buf.deinit();
188 child_list_a.deinit();
189 }
190 try expandNode(a_node, &child_list_a);
191
192 var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator);
193 defer {
194 for (child_list_b.items) |*buf| buf.deinit();
195 child_list_b.deinit();
196 }
197 try expandNode(b_node, &child_list_b);
198
199 for (child_list_a.items) |buf_a| {
200 for (child_list_b.items) |buf_b| {
201 var combined_buf = ArrayList(u8).init(global_allocator);
202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
206 try output.append(combined_buf);
207 }
208 }
209 },
210 .List => |list| {
211 for (list.items) |child_node| {
212 var child_list = ArrayList(ArrayList(u8)).init(global_allocator);
213 errdefer for (child_list.items) |*buf| buf.deinit();
214 defer child_list.deinit();
215
216 try expandNode(child_node, &child_list);
217
218 for (child_list.items) |buf| {
219 try output.append(buf);
220 }
221 }
222 },
223 }
224}
225
226pub fn main() !void {
227 defer _ = gpa.deinit();
228 const stdin_file = io.getStdIn();
229 const stdout_file = io.getStdOut();
230
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232 defer global_allocator.free(stdin);
233
234 var result_buf = ArrayList(u8).init(global_allocator);
235 defer result_buf.deinit();
236
237 try expandString(stdin, &result_buf);
238 try stdout_file.writeAll(result_buf.items);
239}
240
241test "invalid inputs" {
242 global_allocator = std.testing.allocator;
243
244 try expectError("}ABC", error.InvalidInput);
245 try expectError("{ABC", error.InvalidInput);
246 try expectError("}{", error.InvalidInput);
247 try expectError("{}", error.InvalidInput);
248 try expectError("A,B,C", error.InvalidInput);
249 try expectError("{A{B,C}", error.InvalidInput);
250 try expectError("{A,}", error.InvalidInput);
251
252 try expectError("\n", error.InvalidInput);
253}
254
255fn expectError(test_input: []const u8, expected_err: anyerror) !void {
256 var output_buf = ArrayList(u8).init(global_allocator);
257 defer output_buf.deinit();
258
259 try testing.expectError(expected_err, expandString(test_input, &output_buf));
260}
261
262test "valid inputs" {
263 global_allocator = std.testing.allocator;
264
265 try expectExpansion("{x,y,z}", "x y z");
266 try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
267 try expectExpansion("{A,B{x,y}}", "A Bx By");
268
269 try expectExpansion("{ABC}", "ABC");
270 try expectExpansion("{A,B,C}", "A B C");
271 try expectExpansion("ABC", "ABC");
272
273 try expectExpansion("", "");
274 try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
275 try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
276 try expectExpansion("{A,B}a", "Aa Ba");
277 try expectExpansion("{C,{x,y}}", "C x y");
278 try expectExpansion("z{C,{x,y}}", "zC zx zy");
279 try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
280 try expectExpansion("a{x,y}b", "axb ayb");
281 try expectExpansion("z{{a,b}}", "za zb");
282 try expectExpansion("a{b}", "ab");
283}
284
285fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void {
286 var result = ArrayList(u8).init(global_allocator);
287 defer result.deinit();
288
289 expandString(test_input, &result) catch unreachable;
290
291 try testing.expectEqualSlices(u8, expected_result, result.items);
292}
test/standalone/simple/cat/main.zig created+46
......@@ -0,0 +1,46 @@
1const std = @import("std");
2const io = std.io;
3const process = std.process;
4const fs = std.fs;
5const mem = std.mem;
6const warn = std.log.warn;
7
8pub fn main() !void {
9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena_instance.deinit();
11 const arena = arena_instance.allocator();
12
13 const args = try process.argsAlloc(arena);
14
15 const exe = args[0];
16 var catted_anything = false;
17 const stdout_file = io.getStdOut();
18
19 const cwd = fs.cwd();
20
21 for (args[1..]) |arg| {
22 if (mem.eql(u8, arg, "-")) {
23 catted_anything = true;
24 try stdout_file.writeFileAll(io.getStdIn(), .{});
25 } else if (mem.startsWith(u8, arg, "-")) {
26 return usage(exe);
27 } else {
28 const file = cwd.openFile(arg, .{}) catch |err| {
29 warn("Unable to open file: {s}\n", .{@errorName(err)});
30 return err;
31 };
32 defer file.close();
33
34 catted_anything = true;
35 try stdout_file.writeFileAll(file, .{});
36 }
37 }
38 if (!catted_anything) {
39 try stdout_file.writeFileAll(io.getStdIn(), .{});
40 }
41}
42
43fn usage(exe: []const u8) !void {
44 warn("Usage: {s} [FILE]...\n", .{exe});
45 return error.Invalid;
46}
test/standalone/simple/guess_number/main.zig created+38
......@@ -0,0 +1,38 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const io = std.io;
4const fmt = std.fmt;
5
6pub fn main() !void {
7 const stdout = io.getStdOut().writer();
8 const stdin = io.getStdIn();
9
10 try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});
11
12 const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1;
13
14 while (true) {
15 try stdout.print("\nGuess a number between 1 and 100: ", .{});
16 var line_buf: [20]u8 = undefined;
17
18 const amt = try stdin.read(&line_buf);
19 if (amt == line_buf.len) {
20 try stdout.print("Input too long.\n", .{});
21 continue;
22 }
23 const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n");
24
25 const guess = fmt.parseUnsigned(u8, line, 10) catch {
26 try stdout.print("Invalid number.\n", .{});
27 continue;
28 };
29 if (guess > answer) {
30 try stdout.print("Guess lower.\n", .{});
31 } else if (guess < answer) {
32 try stdout.print("Guess higher.\n", .{});
33 } else {
34 try stdout.print("You win!\n", .{});
35 return;
36 }
37 }
38}
test/standalone/simple/hello_world/hello.zig created+5
......@@ -0,0 +1,5 @@
1const std = @import("std");
2
3pub fn main() !void {
4 try std.io.getStdOut().writeAll("Hello, World!\n");
5}
test/standalone/simple/hello_world/hello_libc.zig created+15
......@@ -0,0 +1,15 @@
1const c = @cImport({
2 // See https://github.com/ziglang/zig/issues/515
3 @cDefine("_NO_CRT_STDIO_INLINE", "1");
4 @cInclude("stdio.h");
5 @cInclude("string.h");
6});
7
8const msg = "Hello, world!\n";
9
10pub export fn main(argc: c_int, argv: **u8) c_int {
11 _ = argv;
12 _ = argc;
13 if (c.printf(msg) != @as(c_int, @intCast(c.strlen(msg)))) return -1;
14 return 0;
15}
test/standalone/simple/issue_12471/main.zig created+12
......@@ -0,0 +1,12 @@
1const c = @cImport({
2 @cDefine("FOO", "FOO");
3 @cDefine("BAR", "FOO");
4
5 @cDefine("BAZ", "QUX");
6 @cDefine("QUX", "QUX");
7});
8
9pub fn main() u8 {
10 _ = c;
11 return 0;
12}
test/standalone/simple/issue_7030.zig created+21
......@@ -0,0 +1,21 @@
1const std = @import("std");
2
3pub const std_options = .{
4 .logFn = log,
5};
6
7pub fn log(
8 comptime message_level: std.log.Level,
9 comptime scope: @Type(.EnumLiteral),
10 comptime format: []const u8,
11 args: anytype,
12) void {
13 _ = message_level;
14 _ = scope;
15 _ = format;
16 _ = args;
17}
18
19pub fn main() anyerror!void {
20 std.log.info("All your codebase are belong to us.", .{});
21}
test/standalone/simple/issue_9402/main.zig created+14
......@@ -0,0 +1,14 @@
1const FILE = extern struct {
2 dummy_field: u8,
3};
4
5extern fn _ftelli64([*c]FILE) i64;
6extern fn _fseeki64([*c]FILE, i64, c_int) c_int;
7
8pub export fn main(argc: c_int, argv: **u8) c_int {
9 _ = argv;
10 _ = argc;
11 _ = _ftelli64(null);
12 _ = _fseeki64(null, 123, 2);
13 return 0;
14}
test/standalone/simple/main_return_error/error_u8.zig created+5
......@@ -0,0 +1,5 @@
1const Err = error{Foo};
2
3pub fn main() !u8 {
4 return Err.Foo;
5}
test/standalone/simple/main_return_error/error_u8_non_zero.zig created+10
......@@ -0,0 +1,10 @@
1const Err = error{Foo};
2
3fn foo() u8 {
4 return @intCast(9);
5}
6
7pub fn main() !u8 {
8 if (foo() == 7) return Err.Foo;
9 return 123;
10}
test/standalone/simple/noreturn_call/as_arg.zig created+8
......@@ -0,0 +1,8 @@
1const std = @import("std");
2fn foo() noreturn {
3 std.process.exit(0);
4}
5fn bar(_: u8, _: u8) void {}
6pub fn main() void {
7 bar(foo(), @compileError("bad"));
8}
test/standalone/simple/noreturn_call/inline.zig created+10
......@@ -0,0 +1,10 @@
1pub fn main() void {
2 _ = bar();
3}
4inline fn bar() u8 {
5 noret();
6}
7const std = @import("std");
8inline fn noret() noreturn {
9 std.process.exit(0);
10}
test/standalone/simple/std_enums_big_enums.zig created+38
......@@ -0,0 +1,38 @@
1const std = @import("std");
2
3// big enums should not hit the eval branch quota
4pub fn main() void {
5 const big = struct {
6 const Big = @Type(@as(std.builtin.Type, .{
7 .Enum = .{
8 .tag_type = u16,
9 .fields = make_fields: {
10 var fields: [1001]std.builtin.Type.EnumField = undefined;
11 for (&fields, 0..) |*field, i| {
12 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };
13 }
14 fields[1000] = .{ .name = "field_9999", .value = 9999 };
15 break :make_fields &fields;
16 },
17 .decls = &.{},
18 .is_exhaustive = true,
19 },
20 }));
21 };
22
23 var set = std.enums.EnumSet(big.Big).init(.{});
24 _ = &set;
25
26 var map = std.enums.EnumMap(big.Big, u8).init(undefined);
27 map = std.enums.EnumMap(big.Big, u8).initFullWith(undefined);
28 map = std.enums.EnumMap(big.Big, u8).initFullWithDefault(123, .{});
29
30 var multiset = std.enums.EnumMultiset(big.Big).init(.{});
31 _ = &multiset;
32
33 var bounded_multiset = std.enums.BoundedEnumMultiset(big.Big, u8).init(.{});
34 _ = &bounded_multiset;
35
36 var array = std.enums.EnumArray(big.Big, u8).init(undefined);
37 array = std.enums.EnumArray(big.Big, u8).initDefault(123, .{});
38}
test/standalone/std_enums_big_enums.zig deleted-38
......@@ -1,38 +0,0 @@
1const std = @import("std");
2
3// big enums should not hit the eval branch quota
4pub fn main() void {
5 const big = struct {
6 const Big = @Type(@as(std.builtin.Type, .{
7 .Enum = .{
8 .tag_type = u16,
9 .fields = make_fields: {
10 var fields: [1001]std.builtin.Type.EnumField = undefined;
11 for (&fields, 0..) |*field, i| {
12 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };
13 }
14 fields[1000] = .{ .name = "field_9999", .value = 9999 };
15 break :make_fields &fields;
16 },
17 .decls = &.{},
18 .is_exhaustive = true,
19 },
20 }));
21 };
22
23 var set = std.enums.EnumSet(big.Big).init(.{});
24 _ = &set;
25
26 var map = std.enums.EnumMap(big.Big, u8).init(undefined);
27 map = std.enums.EnumMap(big.Big, u8).initFullWith(undefined);
28 map = std.enums.EnumMap(big.Big, u8).initFullWithDefault(123, .{});
29
30 var multiset = std.enums.EnumMultiset(big.Big).init(.{});
31 _ = &multiset;
32
33 var bounded_multiset = std.enums.BoundedEnumMultiset(big.Big, u8).init(.{});
34 _ = &bounded_multiset;
35
36 var array = std.enums.EnumArray(big.Big, u8).init(undefined);
37 array = std.enums.EnumArray(big.Big, u8).initDefault(123, .{});
38}