# Tester for nimsuggest. # Every test file can have a #[!]# comment that is deleted from the input # before 'nimsuggest' is invoked to ensure this token doesn't make a # crucial difference for Nim's parser. import os, osproc, strutils, streams, re type Test = object cmd, dest: string script: seq[(string, string)] const curDir = when defined(windows): "" else: "" DummyEof = "!EOF!" proc parseTest(filename: string): Test = const cursorMarker = "#[!]#" let nimsug = curDir & addFileExt("nimsuggest", ExeExt) result.dest = getTempDir() / extractFilename(filename) result.cmd = nimsug & " --tester " & result.dest result.script = @[] 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 & "\";\"" & result.dest & "\":" & $i & ":" & $marker tmp.writeLine x.replace(cursorMarker, "") else: tmp.writeLine x if x.contains("""""""""): inc specSection elif specSection == 1: if x.startsWith("$nimsuggest"): result.cmd = x % ["nimsuggest", nimsug, "file", filename] elif x.startsWith("!edit"): 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: # expected output line: let x = x % ["file", filename] result.script[^1][1].add x.replace(";;", "\t") & '\L' inc i tmp.close() # now that we know the markers, substitute them: for a in mitems(result.script): a[0] = a[0] % markers proc edit(tmpfile, cmd: string) = let x = cmd.splitWhitespace() let f = if x.len >= 4: 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 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 let cl = parseCmdLine(s.cmd) var p = startProcess(command=cl[0], args=cl[1 .. ^1], options={poStdErrToStdOut, poUsePath, poInteractive, poDemon}) let outp = p.outputStream let inp = p.inputStream var report = "" var a = newStringOfCap(120) try: # read and ignore anything nimsuggest says at startup: while outp.readLine(a): if a == DummyEof: break for req, resp in items(s.script): if req.startsWith("!edit"): edit(s.dest, req) else: 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() close(p) if report.len > 0: echo report result = report.len proc main() = var failures = 0 for x in walkFiles(getAppDir() / "tests/t*.nim"): echo "Test ", x failures += runTest(expandFilename(x)) if failures > 0: quit 1 main()