aboutsummaryrefslogtreecommitdiff
path: root/spec/util/quick.lua
diff options
context:
space:
mode:
Diffstat (limited to 'spec/util/quick.lua')
-rw-r--r--spec/util/quick.lua106
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)
37end 37end
38 38
39local function parse(filename) 39local 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