summary refs log tree commit diff stats
path: root/tools/nimsuggest/tester.nim
blob: f340c23e1775b529b537f7fb99fc293316dc92d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 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: 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)
  let dest = getTempDir() / extractFilename(filename)
  result.cmd = nimsug & " --tester " & dest
  result.script = @[]
  var tmp = open(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
      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(">"):
        # 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 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):
      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()