diff options
Diffstat (limited to 'tools/nimsuggest/tester.nim')
-rw-r--r-- | tools/nimsuggest/tester.nim | 123 |
1 files changed, 103 insertions, 20 deletions
diff --git a/tools/nimsuggest/tester.nim b/tools/nimsuggest/tester.nim index 70a7da5b2..c90afe3db 100644 --- a/tools/nimsuggest/tester.nim +++ b/tools/nimsuggest/tester.nim @@ -7,27 +7,31 @@ import os, osproc, strutils, streams, re type Test = object - cmd: string + cmd, dest: string + startup: seq[string] script: seq[(string, string)] const - curDir = when defined(windows): "" else: "./" + curDir = when defined(windows): "" else: "" DummyEof = "!EOF!" +template tpath(): untyped = getAppDir() / "tests" + proc parseTest(filename: string): Test = const cursorMarker = "#[!]#" let nimsug = curDir & addFileExt("nimsuggest", ExeExt) - let dest = getTempDir() / extractFilename(filename) - result.cmd = nimsug & " --tester " & dest + result.dest = getTempDir() / extractFilename(filename) + result.cmd = nimsug & " --tester " & result.dest result.script = @[] - var tmp = open(dest, fmWrite) + result.startup = @[] + var tmp = open(result.dest, fmWrite) var specSection = 0 var markers = newSeq[string]() var i = 1 for x in lines(filename): let marker = x.find(cursorMarker)+1 if marker > 0: - markers.add filename & ";" & dest & ":" & $i & ":" & $marker + markers.add "\"" & filename & "\";\"" & result.dest & "\":" & $i & ":" & $marker tmp.writeLine x.replace(cursorMarker, "") else: tmp.writeLine x @@ -36,26 +40,104 @@ proc parseTest(filename: string): Test = elif specSection == 1: if x.startsWith("$nimsuggest"): result.cmd = x % ["nimsuggest", nimsug, "file", filename] + elif x.startsWith("!"): + if result.cmd.len == 0: + result.startup.add x + else: + result.script.add((x, "")) elif x.startsWith(">"): # since 'markers' here are not complete yet, we do the $substitutions # afterwards - result.script.add((x.substr(1), "")) - else: + result.script.add((x.substr(1).replaceWord("$path", tpath()), "")) + elif x.len > 0: # expected output line: let x = x % ["file", filename] result.script[^1][1].add x.replace(";;", "\t") & '\L' + # else: ignore empty lines for better readability of the specs inc i tmp.close() # now that we know the markers, substitute them: for a in mitems(result.script): a[0] = a[0] % markers +proc parseCmd(c: string): seq[string] = + # we don't support double quotes for now so that + # we can later support them properly with escapes and stuff. + result = @[] + var i = 0 + var a = "" + while true: + setLen(a, 0) + # eat all delimiting whitespace + while c[i] in {' ', '\t', '\l', '\r'}: inc(i) + case c[i] + of '"': raise newException(ValueError, "double quotes not yet supported: " & c) + of '\'': + var delim = c[i] + inc(i) # skip ' or " + while c[i] != '\0' and c[i] != delim: + add a, c[i] + inc(i) + if c[i] != '\0': inc(i) + of '\0': break + else: + while c[i] > ' ': + add(a, c[i]) + inc(i) + add(result, a) + +proc edit(tmpfile: string; x: seq[string]) = + if x.len != 3 and x.len != 4: + quit "!edit takes two or three arguments" + let f = if x.len >= 4: tpath() / x[3] else: tmpfile + try: + let content = readFile(f) + let newcontent = content.replace(x[1], x[2]) + if content == newcontent: + quit "wrong test case: edit had no effect" + writeFile(f, newcontent) + except IOError: + quit "cannot edit file " & tmpfile + +proc exec(x: seq[string]) = + if x.len != 2: quit "!exec takes one argument" + if execShellCmd(x[1]) != 0: + quit "External program failed " & x[1] + +proc copy(x: seq[string]) = + if x.len != 3: quit "!copy takes two arguments" + let rel = tpath() + copyFile(rel / x[1], rel / x[2]) + +proc del(x: seq[string]) = + if x.len != 2: quit "!del takes one argument" + removeFile(tpath() / x[1]) + +proc runCmd(cmd, dest: string): bool = + result = cmd[0] == '!' + if not result: return + let x = cmd.parseCmd() + case x[0] + of "!edit": + edit(dest, x) + of "!exec": + exec(x) + of "!copy": + copy(x) + of "!del": + del(x) + else: + quit "unkown command: " & cmd + proc smartCompare(pattern, x: string): bool = if pattern.contains('*'): result = match(x, re(escapeRe(pattern).replace("\\x2A","(.*)"), {})) proc runTest(filename: string): int = let s = parseTest filename + for cmd in s.startup: + if not runCmd(cmd, s.dest): + quit "invalid command: " & cmd let cl = parseCmdLine(s.cmd) var p = startProcess(command=cl[0], args=cl[1 .. ^1], options={poStdErrToStdOut, poUsePath, @@ -69,17 +151,18 @@ proc runTest(filename: string): int = while outp.readLine(a): if a == DummyEof: break for req, resp in items(s.script): - inp.writeLine(req) - inp.flush() - var answer = "" - while outp.readLine(a): - if a == DummyEof: break - answer.add a - answer.add '\L' - if resp != answer and not smartCompare(resp, answer): - report.add "\nTest failed: " & filename - report.add "\n Expected: " & resp - report.add "\n But got: " & answer + if not runCmd(req, s.dest): + inp.writeLine(req) + inp.flush() + var answer = "" + while outp.readLine(a): + if a == DummyEof: break + answer.add a + answer.add '\L' + if resp != answer and not smartCompare(resp, answer): + report.add "\nTest failed: " & filename + report.add "\n Expected: " & resp + report.add "\n But got: " & answer finally: inp.writeLine("quit") inp.flush() @@ -90,7 +173,7 @@ proc runTest(filename: string): int = proc main() = var failures = 0 - for x in walkFiles("tests/t*.nim"): + for x in walkFiles(getAppDir() / "tests/t*.nim"): echo "Test ", x failures += runTest(expandFilename(x)) if failures > 0: |