summary refs log tree commit diff stats
path: root/nimsuggest/tester.nim
diff options
context:
space:
mode:
Diffstat (limited to 'nimsuggest/tester.nim')
-rw-r--r--nimsuggest/tester.nim74
1 files changed, 53 insertions, 21 deletions
diff --git a/nimsuggest/tester.nim b/nimsuggest/tester.nim
index 019181810..9b9488348 100644
--- a/nimsuggest/tester.nim
+++ b/nimsuggest/tester.nim
@@ -2,8 +2,11 @@
 # 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.
+# When debugging, to run a single test, use for e.g.:
+# `nim r nimsuggest/tester.nim nimsuggest/tests/tsug_accquote.nim`
 
 import os, osproc, strutils, streams, re, sexp, net
+from sequtils import toSeq
 
 type
   Test = object
@@ -13,15 +16,17 @@ type
     disabled: bool
 
 const
-  curDir = when defined(windows): "" else: ""
   DummyEof = "!EOF!"
+  tpath = "nimsuggest/tests"
+  # we could also use `stdtest/specialpaths`
 
-template tpath(): untyped = getAppDir() / "tests"
+import std/compilesettings
 
 proc parseTest(filename: string; epcMode=false): Test =
   const cursorMarker = "#[!]#"
-  let nimsug = curDir & addFileExt("nimsuggest", ExeExt)
-  let libpath = findExe("nim").splitFile().dir /../ "lib"
+  let nimsug = "bin" / addFileExt("nimsuggest_testing", ExeExt)
+  doAssert nimsug.fileExists, nimsug
+  const libpath = querySetting(libPath)
   result.filename = filename
   result.dest = getTempDir() / extractFilename(filename)
   result.cmd = nimsug & " --tester " & result.dest
@@ -61,7 +66,7 @@ proc parseTest(filename: string; epcMode=false): Test =
       elif x.startsWith(">"):
         # since 'markers' here are not complete yet, we do the $substitutions
         # afterwards
-        result.script.add((x.substr(1).replaceWord("$path", tpath()), ""))
+        result.script.add((x.substr(1).replaceWord("$path", tpath).replaceWord("$file", filename), ""))
       elif x.len > 0:
         # expected output line:
         let x = x % ["file", filename, "lib", libpath]
@@ -102,7 +107,7 @@ proc parseCmd(c: string): seq[string] =
 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
+  let f = if x.len >= 4: tpath / x[3] else: tmpfile
   try:
     let content = readFile(f)
     let newcontent = content.replace(x[1], x[2])
@@ -119,12 +124,12 @@ proc exec(x: seq[string]) =
 
 proc copy(x: seq[string]) =
   if x.len != 3: quit "!copy takes two arguments"
-  let rel = tpath()
+  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])
+  removeFile(tpath / x[1])
 
 proc runCmd(cmd, dest: string): bool =
   result = cmd[0] == '!'
@@ -213,7 +218,12 @@ proc sexpToAnswer(s: SexpNode): string =
       result.add doc
       result.add '\t'
       result.addInt a[8].getNum
-      if a.len >= 10:
+      if a.len >= 11:
+        result.add '\t'
+        result.addInt a[9].getNum
+        result.add '\t'
+        result.addInt a[10].getNum
+      elif a.len >= 10:
         result.add '\t'
         result.add a[9].getStr
     result.add '\L'
@@ -224,8 +234,8 @@ proc doReport(filename, answer, resp: string; report: var string) =
     var hasDiff = false
     for i in 0..min(resp.len-1, answer.len-1):
       if resp[i] != answer[i]:
-        report.add "\n  Expected:  " & resp.substr(i, i+200)
-        report.add "\n  But got:   " & answer.substr(i, i+200)
+        report.add "\n  Expected:\n" & resp
+        report.add "\n  But got:\n" & answer
         hasDiff = true
         break
     if not hasDiff:
@@ -247,13 +257,15 @@ proc runEpcTest(filename: string): int =
   for cmd in s.startup:
     if not runCmd(cmd, s.dest):
       quit "invalid command: " & cmd
-  let epccmd = s.cmd.replace("--tester", "--epc --v2 --log")
+  let epccmd = if s.cmd.contains("--v3"):
+    s.cmd.replace("--tester", "--epc --log")
+  else:
+    s.cmd.replace("--tester", "--epc --v2 --log")
   let cl = parseCmdLine(epccmd)
   var p = startProcess(command=cl[0], args=cl[1 .. ^1],
                        options={poStdErrToStdOut, poUsePath,
                        poInteractive, poDaemon})
   let outp = p.outputStream
-  let inp = p.inputStream
   var report = ""
   var socket = newSocket()
   try:
@@ -267,17 +279,28 @@ proc runEpcTest(filename: string): int =
         os.sleep(50)
         inc i
       let a = outp.readAll().strip()
-    let port = parseInt(a)
+    var port: int
+    try:
+      port = parseInt(a)
+    except ValueError:
+      echo "Error parsing port number: " & a
+      echo outp.readAll()
+      quit 1
     socket.connect("localhost", Port(port))
+
     for req, resp in items(s.script):
       if not runCmd(req, s.dest):
         socket.sendEpcStr(req)
         let sx = parseSexp(socket.recvEpc())
         if not req.startsWith("mod "):
-          let answer = sexpToAnswer(sx)
+          let answer = if sx[2].kind == SNil: "" else: sexpToAnswer(sx)
           doReport(filename, answer, resp, report)
-  finally:
+
     socket.sendEpcStr "return arg"
+      # bugfix: this was in `finally` block, causing the original error to be
+      # potentially masked by another one in case `socket.sendEpcStr` raises
+      # (e.g. if socket couldn't connect in the 1st place)
+  finally:
     close(p)
   if report.len > 0:
     echo "==== EPC ========================================"
@@ -313,8 +336,12 @@ proc runTest(filename: string): int =
           answer.add '\L'
         doReport(filename, answer, resp, report)
   finally:
-    inp.writeLine("quit")
-    inp.flush()
+    try:
+      inp.writeLine("quit")
+      inp.flush()
+    except IOError, OSError:
+      # assume it's SIGPIPE, ie, the child already died
+      discard
     close(p)
   if report.len > 0:
     echo "==== STDIN ======================================"
@@ -326,11 +353,16 @@ proc main() =
   if os.paramCount() > 0:
     let x = os.paramStr(1)
     let xx = expandFilename x
+    # run only stdio when running single test
     failures += runTest(xx)
-    failures += runEpcTest(xx)
   else:
-    for x in walkFiles(getAppDir() / "tests/t*.nim"):
-      echo "Test ", x
+    let files = toSeq(walkFiles(tpath / "t*.nim"))
+    for i, x in files:
+      echo "$#/$# test: $#" % [$i, $files.len, x]
+      when defined(i386):
+        if x == "nimsuggest/tests/tmacro_highlight.nim":
+          echo "skipping" # workaround bug #17945
+          continue
       let xx = expandFilename x
       when not defined(windows):
         # XXX Windows IO redirection seems bonkers: