diff options
Diffstat (limited to 'spec/util/quick.lua')
-rw-r--r-- | spec/util/quick.lua | 106 |
1 files changed, 73 insertions, 33 deletions
diff --git a/spec/util/quick.lua b/spec/util/quick.lua index c8bfb61a..1fcf2b36 100644 --- a/spec/util/quick.lua +++ b/spec/util/quick.lua | |||
@@ -37,7 +37,7 @@ local function is_hr(line) | |||
37 | end | 37 | end |
38 | 38 | ||
39 | local function parse(filename) | 39 | local function parse(filename) |
40 | local fd = assert(io.open(filename, "r")) | 40 | local fd = assert(io.open(filename, "rb")) |
41 | local input = assert(fd:read("*a")) | 41 | local input = assert(fd:read("*a")) |
42 | fd:close() | 42 | fd:close() |
43 | 43 | ||
@@ -67,11 +67,27 @@ local function parse(filename) | |||
67 | os.exit(1) | 67 | os.exit(1) |
68 | end | 68 | end |
69 | 69 | ||
70 | local function bool_arg(cmd, cur_block, field, arg) | 70 | local function bool_arg(cmd, cur, field, arg) |
71 | if arg ~= "true" and arg ~= "false" then | 71 | if arg ~= "true" and arg ~= "false" then |
72 | fail(cmd .. " argument must be 'true' or 'false'") | 72 | fail(cmd .. " argument must be 'true' or 'false'") |
73 | end | 73 | end |
74 | cur_block[field] = (arg == "true") | 74 | cur[field] = (arg == "true") |
75 | end | ||
76 | |||
77 | local function block_start_arg(cmd, cur, field) | ||
78 | if not cur or cur.op ~= "RUN" then | ||
79 | fail(cmd .. " must be given in the context of a RUN") | ||
80 | end | ||
81 | if cur[field] then | ||
82 | fail(cmd .. " was already declared") | ||
83 | end | ||
84 | |||
85 | cur[field] = { | ||
86 | data = {} | ||
87 | } | ||
88 | cur_block = cur[field] | ||
89 | cur_block_name = cmd | ||
90 | table.insert(stack, "block start") | ||
75 | end | 91 | end |
76 | 92 | ||
77 | local test_env = require("spec.util.test_env") | 93 | local test_env = require("spec.util.test_env") |
@@ -109,7 +125,11 @@ local function parse(filename) | |||
109 | end)) | 125 | end)) |
110 | end | 126 | end |
111 | 127 | ||
112 | for line in input:gmatch("[^\n]*") do | 128 | if input:sub(#input, #input) ~= "\n" then |
129 | input = input .. "\n" | ||
130 | end | ||
131 | |||
132 | for line in input:gmatch("([^\r\n]*)\r?\n?") do | ||
113 | cur_line = cur_line + 1 | 133 | cur_line = cur_line + 1 |
114 | 134 | ||
115 | local state = stack[#stack] | 135 | local state = stack[#stack] |
@@ -182,34 +202,20 @@ local function parse(filename) | |||
182 | 202 | ||
183 | cur_op.exit = code | 203 | cur_op.exit = code |
184 | cur_op.exit_line = cur_line | 204 | cur_op.exit_line = cur_line |
185 | elseif cmd == "STDERR" then | 205 | elseif cmd == "VERBOSE" then |
186 | if not cur_op or cur_op.op ~= "RUN" then | 206 | if not cur_op or cur_op.op ~= "RUN" then |
187 | fail("STDERR must be given in the context of a RUN") | 207 | fail("VERBOSE must be given in the context of a RUN") |
188 | end | ||
189 | if cur_op.stderr then | ||
190 | fail("STDERR was already declared") | ||
191 | end | 208 | end |
192 | 209 | ||
193 | cur_op.stderr = { | 210 | bool_arg("VERBOSE", cur_op, "verbose", arg) |
194 | data = {} | 211 | elseif cmd == "STDERR" then |
195 | } | 212 | block_start_arg("STDERR", cur_op, "stderr") |
196 | cur_block = cur_op.stderr | 213 | elseif cmd == "NOT_STDERR" then |
197 | cur_block_name = "STDERR" | 214 | block_start_arg("NOT_STDERR", cur_op, "not_stderr") |
198 | table.insert(stack, "block start") | ||
199 | elseif cmd == "STDOUT" then | 215 | elseif cmd == "STDOUT" then |
200 | if not cur_op or cur_op.op ~= "RUN" then | 216 | block_start_arg("STDOUT", cur_op, "stdout") |
201 | fail("STDOUT must be given in the context of a RUN") | 217 | elseif cmd == "NOT_STDOUT" then |
202 | end | 218 | block_start_arg("NOT_STDOUT", cur_op, "not_stdout") |
203 | if cur_op.stdout then | ||
204 | fail("STDOUT was already declared") | ||
205 | end | ||
206 | |||
207 | cur_op.stdout = { | ||
208 | data = {} | ||
209 | } | ||
210 | cur_block = cur_op.stdout | ||
211 | cur_block_name = "STDOUT" | ||
212 | table.insert(stack, "block start") | ||
213 | elseif cmd == "TEST" then | 219 | elseif cmd == "TEST" then |
214 | table.remove(stack) | 220 | table.remove(stack) |
215 | start_test(arg) | 221 | start_test(arg) |
@@ -298,7 +304,7 @@ function quick.compile(filename, env) | |||
298 | write([=[ end ]=]) | 304 | write([=[ end ]=]) |
299 | for _, op in ipairs(t.ops) do | 305 | for _, op in ipairs(t.ops) do |
300 | if op.op == "FILE" then | 306 | if op.op == "FILE" then |
301 | write([=[ test_env.write_file(handle_tmpdir("]=], op.name, [=["), handle_tmpdir([=====[ ]=]) | 307 | write(([=[ test_env.write_file(handle_tmpdir(%q), handle_tmpdir([=====[ ]=]):format(op.name)) |
302 | for _, line in ipairs(op.data) do | 308 | for _, line in ipairs(op.data) do |
303 | write(line) | 309 | write(line) |
304 | end | 310 | end |
@@ -324,7 +330,7 @@ function quick.compile(filename, env) | |||
324 | write(([=[ local ok, _, code = os.execute(%s .. " " .. %q .. %q) ]=]):format(cmd_helper, op.args, redirs)) | 330 | write(([=[ local ok, _, code = os.execute(%s .. " " .. %q .. %q) ]=]):format(cmd_helper, op.args, redirs)) |
325 | write([=[ if type(ok) == "number" then code = (ok >= 256 and ok / 256 or ok) end ]=]) | 331 | write([=[ if type(ok) == "number" then code = (ok >= 256 and ok / 256 or ok) end ]=]) |
326 | 332 | ||
327 | write([=[ local fd_stderr = assert(io.open("stderr.txt", "r")) ]=]) | 333 | write([=[ local fd_stderr = assert(io.open("stderr.txt", "rb")) ]=]) |
328 | write([=[ local stderr_data = fd_stderr:read("*a") ]=]) | 334 | write([=[ local stderr_data = fd_stderr:read("*a") ]=]) |
329 | write([=[ fd_stderr:close() ]=]) | 335 | write([=[ fd_stderr:close() ]=]) |
330 | 336 | ||
@@ -332,23 +338,46 @@ function quick.compile(filename, env) | |||
332 | write(([=[ assert(false, error_message(%d, "RUN crashed: ", stderr_data)) ]=]):format(op.line)) | 338 | write(([=[ assert(false, error_message(%d, "RUN crashed: ", stderr_data)) ]=]):format(op.line)) |
333 | write([=[ end ]=]) | 339 | write([=[ end ]=]) |
334 | 340 | ||
335 | if op.stdout then | 341 | if op.stdout or op.not_stdout or op.verbose then |
336 | write([=[ local fd_stdout = assert(io.open("stdout.txt", "r")) ]=]) | 342 | write([=[ local fd_stdout = assert(io.open("stdout.txt", "rb")) ]=]) |
337 | write([=[ local stdout_data = fd_stdout:read("*a") ]=]) | 343 | write([=[ local stdout_data = fd_stdout:read("*a") ]=]) |
338 | write([=[ fd_stdout:close() ]=]) | 344 | write([=[ fd_stdout:close() ]=]) |
345 | end | ||
346 | |||
347 | if op.verbose then | ||
348 | write([=[ print() ]=]) | ||
349 | write([=[ print("STDOUT: --" .. ("-"):rep(70)) ]=]) | ||
350 | write([=[ print(stdout_data) ]=]) | ||
351 | write([=[ print("STDERR: --" .. ("-"):rep(70)) ]=]) | ||
352 | write([=[ print(stderr_data) ]=]) | ||
353 | write([=[ print(("-"):rep(80)) ]=]) | ||
354 | write([=[ print() ]=]) | ||
355 | end | ||
339 | 356 | ||
357 | if op.stdout then | ||
340 | write([=[ do ]=]) | 358 | write([=[ do ]=]) |
341 | write([=[ local block_at = 1 ]=]) | 359 | write([=[ local block_at = 1 ]=]) |
342 | write([=[ local s, e, line ]=]) | 360 | write([=[ local s, e, line ]=]) |
343 | for i, line in ipairs(op.stdout.data) do | 361 | for i, line in ipairs(op.stdout.data) do |
344 | write(([=[ line = %q ]=]):format(line)) | 362 | write(([=[ line = %q ]=]):format(line)) |
345 | write(([=[ s, e = string.find(stdout_data, line, block_at, true) ]=])) | 363 | write(([=[ s, e = string.find(stdout_data, line, 1, true) ]=])) |
346 | write(([=[ assert(s, error_message(%d, "STDOUT did not match: " .. line, stdout_data)) ]=]):format(op.stdout.start + i)) | 364 | write(([=[ assert(s, error_message(%d, "STDOUT did not match: " .. line, stdout_data)) ]=]):format(op.stdout.start + i)) |
347 | write(([=[ block_at = e + 1 ]=]):format(i)) | 365 | write(([=[ block_at = e + 1 ]=]):format(i)) |
348 | end | 366 | end |
349 | write([=[ end ]=]) | 367 | write([=[ end ]=]) |
350 | end | 368 | end |
351 | 369 | ||
370 | if op.not_stdout then | ||
371 | write([=[ do ]=]) | ||
372 | write([=[ local line ]=]) | ||
373 | for i, line in ipairs(op.not_stdout.data) do | ||
374 | write(([=[ line = %q ]=]):format(line)) | ||
375 | write(([=[ s = string.find(stdout_data, line, 1, true) ]=])) | ||
376 | write(([=[ assert(not s, error_message(%d, "NOT_STDOUT did match unwanted output: " .. line, stdout_data)) ]=]):format(op.stdout.start + i)) | ||
377 | end | ||
378 | write([=[ end ]=]) | ||
379 | end | ||
380 | |||
352 | if op.stderr then | 381 | if op.stderr then |
353 | write([=[ do ]=]) | 382 | write([=[ do ]=]) |
354 | write([=[ local block_at = 1 ]=]) | 383 | write([=[ local block_at = 1 ]=]) |
@@ -362,6 +391,17 @@ function quick.compile(filename, env) | |||
362 | write([=[ end ]=]) | 391 | write([=[ end ]=]) |
363 | end | 392 | end |
364 | 393 | ||
394 | if op.not_stderr then | ||
395 | write([=[ do ]=]) | ||
396 | write([=[ local line ]=]) | ||
397 | for i, line in ipairs(op.not_stderr.data) do | ||
398 | write(([=[ line = %q ]=]):format(line)) | ||
399 | write(([=[ s = string.find(stderr_data, line, block_at, true) ]=])) | ||
400 | write(([=[ assert(not s, error_message(%d, "NOT_STDERR did match unwanted output: " .. line, stderr_data)) ]=]):format(op.stderr.start + i)) | ||
401 | end | ||
402 | write([=[ end ]=]) | ||
403 | end | ||
404 | |||
365 | if op.exit then | 405 | if op.exit then |
366 | write(([=[ assert.same(%d, code, error_message(%d, "EXIT did not match: " .. %d, stderr_data)) ]=]):format(op.exit, op.exit_line, op.exit)) | 406 | write(([=[ assert.same(%d, code, error_message(%d, "EXIT did not match: " .. %d, stderr_data)) ]=]):format(op.exit, op.exit_line, op.exit)) |
367 | end | 407 | end |