authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-26 06:51:35-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-26 06:51:35-04:00
log6d536168b004a56e0cd0748dca8f0e7f0822fdce
tree70dfa0557bee2ae62b062281a9cf58a588a60e9c
parent0e952a9f3a1522a6fd39d67a495d3918b8d8240d
signature Commit is signed but in an unrecognized format.

Stage2/Testing: Update documentation


1 files changed, 64 insertions(+), 23 deletions(-)

src-self-hosted/test.zig+64-23
...@@ -34,7 +34,7 @@ pub const TestContext = struct {...@@ -34,7 +34,7 @@ pub const TestContext = struct {
34 /// effects of the incremental compilation.34 /// effects of the incremental compilation.
35 src: [:0]const u8,35 src: [:0]const u8,
36 case: union(enum) {36 case: union(enum) {
37 /// A transformation update transforms the input ZIR and tests against37 /// A transformation update transforms the input and tests against
38 /// the expected output ZIR.38 /// the expected output ZIR.
39 Transformation: [:0]const u8,39 Transformation: [:0]const u8,
40 /// An error update attempts to compile bad code, and ensures that it40 /// An error update attempts to compile bad code, and ensures that it
...@@ -43,6 +43,7 @@ pub const TestContext = struct {...@@ -43,6 +43,7 @@ pub const TestContext = struct {
43 Error: []const ErrorMsg,43 Error: []const ErrorMsg,
44 /// An execution update compiles and runs the input, testing the44 /// An execution update compiles and runs the input, testing the
45 /// stdout against the expected results45 /// stdout against the expected results
46 /// This is a slice containing the expected message.
46 Execution: []const u8,47 Execution: []const u8,
47 },48 },
48 };49 };
...@@ -56,16 +57,20 @@ pub const TestContext = struct {...@@ -56,16 +57,20 @@ pub const TestContext = struct {
56 /// update, so each update's source is treated as a single file being57 /// update, so each update's source is treated as a single file being
57 /// updated by the test harness and incrementally compiled.58 /// updated by the test harness and incrementally compiled.
58 pub const Case = struct {59 pub const Case = struct {
60 /// The name of the test case. This is shown if a test fails, and
61 /// otherwise ignored.
59 name: []const u8,62 name: []const u8,
60 /// The platform the test targets. For non-native platforms, an emulator63 /// The platform the test targets. For non-native platforms, an emulator
61 /// such as QEMU is required for tests to complete.64 /// such as QEMU is required for tests to complete.
62 target: std.zig.CrossTarget,65 target: std.zig.CrossTarget,
66 /// In order to be able to run e.g. Execution updates, this must be set
67 /// to Executable.
63 output_mode: std.builtin.OutputMode,68 output_mode: std.builtin.OutputMode,
64 updates: std.ArrayList(Update),69 updates: std.ArrayList(Update),
65 @"type": TestType,70 @"type": TestType,
6671
67 /// Adds a subcase in which the module is updated with new ZIR, and the72 /// Adds a subcase in which the module is updated with `src`, and the
68 /// resulting ZIR is validated.73 /// resulting ZIR is validated against `result`.
69 pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void {74 pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void {
70 self.updates.append(.{75 self.updates.append(.{
71 .src = src,76 .src = src,
...@@ -73,6 +78,8 @@ pub const TestContext = struct {...@@ -73,6 +78,8 @@ pub const TestContext = struct {
73 }) catch unreachable;78 }) catch unreachable;
74 }79 }
7580
81 /// Adds a subcase in which the module is updated with `src`, compiled,
82 /// run, and the output is tested against `result`.
76 pub fn addCompareOutput(self: *Case, src: [:0]const u8, result: []const u8) void {83 pub fn addCompareOutput(self: *Case, src: [:0]const u8, result: []const u8) void {
77 self.updates.append(.{84 self.updates.append(.{
78 .src = src,85 .src = src,
...@@ -80,10 +87,10 @@ pub const TestContext = struct {...@@ -80,10 +87,10 @@ pub const TestContext = struct {
80 }) catch unreachable;87 }) catch unreachable;
81 }88 }
8289
83 /// Adds a subcase in which the module is updated with invalid ZIR, and90 /// Adds a subcase in which the module is updated with `src`, which
84 /// ensures that compilation fails for the expected reasons.91 /// should contain invalid input, and ensures that compilation fails
85 ///92 /// for the expected reasons, given in sequential order in `errors` in
86 /// Errors must be specified in sequential order.93 /// the form `:error: line:column: message`.
87 pub fn addError(self: *Case, src: [:0]const u8, errors: []const []const u8) void {94 pub fn addError(self: *Case, src: [:0]const u8, errors: []const []const u8) void {
88 var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch unreachable;95 var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch unreachable;
89 for (errors) |e, i| {96 for (errors) |e, i| {
...@@ -121,6 +128,8 @@ pub const TestContext = struct {...@@ -121,6 +128,8 @@ pub const TestContext = struct {
121 self.updates.append(.{ .src = src, .case = .{ .Error = array } }) catch unreachable;128 self.updates.append(.{ .src = src, .case = .{ .Error = array } }) catch unreachable;
122 }129 }
123130
131 /// Adds a subcase in which the module is updated with `src`, and
132 /// asserts that it compiles without issue
124 pub fn compiles(self: *Case, src: [:0]const u8) void {133 pub fn compiles(self: *Case, src: [:0]const u8) void {
125 self.addError(src, &[_][]const u8{});134 self.addError(src, &[_][]const u8{});
126 }135 }
...@@ -142,10 +151,12 @@ pub const TestContext = struct {...@@ -142,10 +151,12 @@ pub const TestContext = struct {
142 return &ctx.cases.items[ctx.cases.items.len - 1];151 return &ctx.cases.items[ctx.cases.items.len - 1];
143 }152 }
144153
154 /// Adds a test case for Zig input, producing an executable
145 pub fn exe(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {155 pub fn exe(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {
146 return ctx.addExe(name, target, .Zig);156 return ctx.addExe(name, target, .Zig);
147 }157 }
148158
159 /// Adds a test case for ZIR input, producing an executable
149 pub fn exeZIR(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {160 pub fn exeZIR(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {
150 return ctx.addExe(name, target, .ZIR);161 return ctx.addExe(name, target, .ZIR);
151 }162 }
...@@ -166,10 +177,12 @@ pub const TestContext = struct {...@@ -166,10 +177,12 @@ pub const TestContext = struct {
166 return &ctx.cases.items[ctx.cases.items.len - 1];177 return &ctx.cases.items[ctx.cases.items.len - 1];
167 }178 }
168179
180 /// Adds a test case for Zig input, producing an object file
169 pub fn obj(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {181 pub fn obj(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {
170 return ctx.addObj(name, target, .Zig);182 return ctx.addObj(name, target, .Zig);
171 }183 }
172184
185 /// Adds a test case for ZIR input, producing an object file
173 pub fn objZIR(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {186 pub fn objZIR(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget) *Case {
174 return ctx.addObj(name, target, .ZIR);187 return ctx.addObj(name, target, .ZIR);
175 }188 }
...@@ -184,6 +197,8 @@ pub const TestContext = struct {...@@ -184,6 +197,8 @@ pub const TestContext = struct {
184 ctx.addExe(name, .{}, T).addCompareOutput(src, expected_stdout);197 ctx.addExe(name, .{}, T).addCompareOutput(src, expected_stdout);
185 }198 }
186199
200 /// Adds a test case that compiles the Zig source given in `src`, executes
201 /// it, runs it, and tests the output against `expected_stdout`
187 pub fn compareOutput(202 pub fn compareOutput(
188 ctx: *TestContext,203 ctx: *TestContext,
189 name: []const u8,204 name: []const u8,
...@@ -193,6 +208,8 @@ pub const TestContext = struct {...@@ -193,6 +208,8 @@ pub const TestContext = struct {
193 return ctx.addCompareOutput(name, .Zig, src, expected_stdout);208 return ctx.addCompareOutput(name, .Zig, src, expected_stdout);
194 }209 }
195210
211 /// Adds a test case that compiles the ZIR source given in `src`, executes
212 /// it, runs it, and tests the output against `expected_stdout`
196 pub fn compareOutputZIR(213 pub fn compareOutputZIR(
197 ctx: *TestContext,214 ctx: *TestContext,
198 name: []const u8,215 name: []const u8,
...@@ -213,6 +230,8 @@ pub const TestContext = struct {...@@ -213,6 +230,8 @@ pub const TestContext = struct {
213 ctx.addObj(name, target, T).addTransform(src, result);230 ctx.addObj(name, target, T).addTransform(src, result);
214 }231 }
215232
233 /// Adds a test case that compiles the Zig given in `src` to ZIR and tests
234 /// the ZIR against `result`
216 pub fn transform(235 pub fn transform(
217 ctx: *TestContext,236 ctx: *TestContext,
218 name: []const u8,237 name: []const u8,
...@@ -223,6 +242,8 @@ pub const TestContext = struct {...@@ -223,6 +242,8 @@ pub const TestContext = struct {
223 ctx.addTransform(name, target, .Zig, src, result);242 ctx.addTransform(name, target, .Zig, src, result);
224 }243 }
225244
245 /// Adds a test case that cleans up the ZIR source given in `src`, and
246 /// tests the resulting ZIR against `result`
226 pub fn transformZIR(247 pub fn transformZIR(
227 ctx: *TestContext,248 ctx: *TestContext,
228 name: []const u8,249 name: []const u8,
...@@ -244,6 +265,9 @@ pub const TestContext = struct {...@@ -244,6 +265,9 @@ pub const TestContext = struct {
244 ctx.addObj(name, target, T).addError(src, expected_errors);265 ctx.addObj(name, target, T).addError(src, expected_errors);
245 }266 }
246267
268 /// Adds a test case that ensures that the Zig given in `src` fails to
269 /// compile for the expected reasons, given in sequential order in
270 /// `expected_errors` in the form `:error: line:column: message`.
247 pub fn compileError(271 pub fn compileError(
248 ctx: *TestContext,272 ctx: *TestContext,
249 name: []const u8,273 name: []const u8,
...@@ -254,6 +278,9 @@ pub const TestContext = struct {...@@ -254,6 +278,9 @@ pub const TestContext = struct {
254 ctx.addError(name, target, .Zig, src, expected_errors);278 ctx.addError(name, target, .Zig, src, expected_errors);
255 }279 }
256280
281 /// Adds a test case that ensures that the ZIR given in `src` fails to
282 /// compile for the expected reasons, given in sequential order in
283 /// `expected_errors` in the form `:error: line:column: message`.
257 pub fn compileErrorZIR(284 pub fn compileErrorZIR(
258 ctx: *TestContext,285 ctx: *TestContext,
259 name: []const u8,286 name: []const u8,
...@@ -274,48 +301,62 @@ pub const TestContext = struct {...@@ -274,48 +301,62 @@ pub const TestContext = struct {
274 ctx.addObj(name, target, T).compiles(src);301 ctx.addObj(name, target, T).compiles(src);
275 }302 }
276303
277 pub fn incrementalFailure(304 /// Adds a test case that asserts that the Zig given in `src` compiles
305 /// without any errors.
306 pub fn compiles(
278 ctx: *TestContext,307 ctx: *TestContext,
279 name: []const u8,308 name: []const u8,
280 target: std.zig.CrossTarget,309 target: std.zig.CrossTarget,
281 src: [:0]const u8,310 src: [:0]const u8,
282 expected_errors: []const []const u8,
283 fixed_src: [:0]const u8,
284 ) void {311 ) void {
285 var case = ctx.addObj(name, target, .Zig);312 ctx.addCompiles(name, target, .Zig, src);
286 case.addError(src, expected_errors);
287 case.compiles(fixed_src);
288 }313 }
289314
290 pub fn incrementalFailureZIR(315 /// Adds a test case that asserts that the ZIR given in `src` compiles
316 /// without any errors.
317 pub fn compilesZIR(
291 ctx: *TestContext,318 ctx: *TestContext,
292 name: []const u8,319 name: []const u8,
293 target: std.zig.CrossTarget,320 target: std.zig.CrossTarget,
294 src: [:0]const u8,321 src: [:0]const u8,
295 expected_errors: []const []const u8,
296 fixed_src: [:0]const u8,
297 ) void {322 ) void {
298 var case = ctx.addObj(name, target, .ZIR);323 ctx.addCompiles(name, target, .ZIR, src);
299 case.addError(src, expected_errors);
300 case.compiles(fixed_src);
301 }324 }
302325
303 pub fn compiles(326 /// Adds a test case that first ensures that the Zig given in `src` fails
327 /// to compile for the reasons given in sequential order in
328 /// `expected_errors` in the form `:error: line:column: message`, then
329 /// asserts that fixing the source (updating with `fixed_src`) isn't broken
330 /// by incremental compilation.
331 pub fn incrementalFailure(
304 ctx: *TestContext,332 ctx: *TestContext,
305 name: []const u8,333 name: []const u8,
306 target: std.zig.CrossTarget,334 target: std.zig.CrossTarget,
307 src: [:0]const u8,335 src: [:0]const u8,
336 expected_errors: []const []const u8,
337 fixed_src: [:0]const u8,
308 ) void {338 ) void {
309 ctx.addCompiles(name, target, .Zig, src);339 var case = ctx.addObj(name, target, .Zig);
340 case.addError(src, expected_errors);
341 case.compiles(fixed_src);
310 }342 }
311343
312 pub fn compilesZIR(344 /// Adds a test case that first ensures that the ZIR given in `src` fails
345 /// to compile for the reasons given in sequential order in
346 /// `expected_errors` in the form `:error: line:column: message`, then
347 /// asserts that fixing the source (updating with `fixed_src`) isn't broken
348 /// by incremental compilation.
349 pub fn incrementalFailureZIR(
313 ctx: *TestContext,350 ctx: *TestContext,
314 name: []const u8,351 name: []const u8,
315 target: std.zig.CrossTarget,352 target: std.zig.CrossTarget,
316 src: [:0]const u8,353 src: [:0]const u8,
354 expected_errors: []const []const u8,
355 fixed_src: [:0]const u8,
317 ) void {356 ) void {
318 ctx.addCompiles(name, target, .ZIR, src);357 var case = ctx.addObj(name, target, .ZIR);
358 case.addError(src, expected_errors);
359 case.compiles(fixed_src);
319 }360 }
320361
321 fn init() TestContext {362 fn init() TestContext {