summary refs log tree commit diff stats
path: root/tests/misc/trunner.nim
blob: d67547d62cd79fe04319217ebf9817c185cea558 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
discard """
  targets: "c cpp"
  joinable: false
"""

## tests that don't quite fit the mold and are easier to handle via `execCmdEx`
## A few others could be added to here to simplify code.
## Note: this test is a bit slow but tests a lot of things; please don't disable.

import std/[strformat,os,osproc,unittest]
from std/sequtils import toSeq,mapIt
from std/algorithm import sorted
import stdtest/[specialpaths, unittest_light]
from std/private/globs import nativeToUnixPath

import "$lib/../compiler/nimpaths"

const
  nim = getCurrentCompilerExe()
  mode =
    when defined(c): "c"
    elif defined(cpp): "cpp"
    else: static: doAssert false
  nimcache = buildDir / "nimcacheTrunner"
    # instead of `querySetting(nimcacheDir)`, avoids stomping on other parallel tests

proc runCmd(file, options = ""): auto =
  let fileabs = testsDir / file.unixToNativePath
  doAssert fileabs.fileExists, fileabs
  let cmd = fmt"{nim} {mode} {options} --hints:off {fileabs}"
  result = execCmdEx(cmd)
  when false:  echo result[0] & "\n" & result[1] # for debugging

when defined(nimTrunnerFfi):
  block: # mevalffi
    when defined(openbsd):
      #[
      openbsd defines `#define stderr (&__sF[2])` which makes it cumbersome
      for dlopen'ing inside `importcSymbol`. Instead of adding special rules
      inside `importcSymbol` to handle this, we disable just the part that's
      not working and will provide a more general, clean fix in future PR.
      ]#
      var opt = "-d:nimEvalffiStderrWorkaround"
      let prefix = ""
    else:
      var opt = ""
      let prefix = """
hello world stderr
hi stderr
"""
    let (output, exitCode) = runCmd("vm/mevalffi.nim", fmt"{opt} --experimental:compiletimeFFI")
    let expected = fmt"""
{prefix}foo
foo:100
foo:101
foo:102:103
foo:102:103:104
foo:0.03:asdf:103:105
ret=[s1:foobar s2:foobar age:25 pi:3.14]
"""
    doAssert output == expected, output
    doAssert exitCode == 0

else: # don't run twice the same test
  import std/[strutils]
  template check2(msg) = doAssert msg in output, output

  block: # tests with various options `nim doc --project --index --docroot`
    # regression tests for issues and PRS: #14376 #13223 #6583 ##13647
    let file = testsDir / "nimdoc/sub/mmain.nim"
    let mainFname = "mmain.html"
    let htmldocsDirCustom = nimcache / "htmldocsCustom"
    let docroot = testsDir / "nimdoc"
    let options = [
      0: "--project",
      1: "--project --docroot",
      2: "",
      3: fmt"--outDir:{htmldocsDirCustom}",
      4: fmt"--docroot:{docroot}",
      5: "--project --useNimcache",
      6: "--index:off",
    ]

    for i in 0..<options.len:
      let htmldocsDir = case i
      of 3: htmldocsDirCustom
      of 5: nimcache / htmldocsDirname
      else: file.parentDir / htmldocsDirname

      var cmd = fmt"{nim} doc --index:on --listFullPaths --hint:successX:on --nimcache:{nimcache} {options[i]} {file}"
      removeDir(htmldocsDir)
      let (outp, exitCode) = execCmdEx(cmd)
      check exitCode == 0
      let ret = toSeq(walkDirRec(htmldocsDir, relative=true)).mapIt(it.nativeToUnixPath).sorted.join("\n")
      let context = $(i, ret, cmd)
      var expected = ""
      case i
      of 0,5:
        let htmlFile = htmldocsDir/"mmain.html"
        check htmlFile in outp # sanity check for `hintSuccessX`
        assertEquals ret, fmt"""
{dotdotMangle}/imp.html
{dotdotMangle}/imp.idx
{docHackJsFname}
imp.html
imp.idx
imp2.html
imp2.idx
mmain.html
mmain.idx
{nimdocOutCss}
{theindexFname}""", context
      of 1: assertEquals ret, fmt"""
{docHackJsFname}
{nimdocOutCss}
tests/nimdoc/imp.html
tests/nimdoc/imp.idx
tests/nimdoc/sub/imp.html
tests/nimdoc/sub/imp.idx
tests/nimdoc/sub/imp2.html
tests/nimdoc/sub/imp2.idx
tests/nimdoc/sub/mmain.html
tests/nimdoc/sub/mmain.idx
{theindexFname}"""
      of 2, 3: assertEquals ret, fmt"""
{docHackJsFname}
mmain.html
mmain.idx
{nimdocOutCss}""", context
      of 4: assertEquals ret, fmt"""
{docHackJsFname}
{nimdocOutCss}
sub/mmain.html
sub/mmain.idx""", context
      of 6: assertEquals ret, fmt"""
mmain.html
{nimdocOutCss}""", context
      else: doAssert false

  block: # mstatic_assert
    let (output, exitCode) = runCmd("ccgbugs/mstatic_assert.nim", "-d:caseBad")
    check2 "sizeof(bool) == 2"
    check exitCode != 0

  block: # ABI checks
    let file = "misc/msizeof5.nim"
    block:
      let (output, exitCode) = runCmd(file, "-d:checkAbi")
      doAssert exitCode == 0, output
    block:
      let (output, exitCode) = runCmd(file, "-d:checkAbi -d:caseBad")
      # on platforms that support _StaticAssert natively, errors will show full context, eg:
      # error: static_assert failed due to requirement 'sizeof(unsigned char) == 8'
      # "backend & Nim disagree on size for: BadImportcType{int64} [declared in mabi_check.nim(1, 6)]"
      check2 "sizeof(unsigned char) == 8"
      check2 "sizeof(struct Foo2) == 1"
      check2 "sizeof(Foo5) == 16"
      check2 "sizeof(Foo5) == 3"
      check2 "sizeof(struct Foo6) == "
      check exitCode != 0

  import streams
  block: # stdin input
    let nimcmd = fmt"""{nim} r --hints:off - -firstparam "-second param" """
    let expected = """@["-firstparam", "-second param"]"""
    block:
      let p = startProcess(nimcmd, options = {poEvalCommand})
      p.inputStream.write("import os; echo commandLineParams()")
      p.inputStream.close
      var output = p.outputStream.readAll
      let error = p.errorStream.readAll
      doAssert p.waitForExit == 0
      doAssert error.len == 0, $error
      output.stripLineEnd
      check output == expected
      p.errorStream.close
      p.outputStream.close

    block:
      when defined posix:
        # xxx on windows, `poEvalCommand` should imply `/cmd`, (which should
        # make this work), but currently doesn't
        let cmd = fmt"""echo "import os; echo commandLineParams()" | {nimcmd}"""
        var (output, exitCode) = execCmdEx(cmd)
        output.stripLineEnd
        check output == expected
        doAssert exitCode == 0

  block: # nim doc --backend:$backend --doccmd:$cmd
    # test for https://github.com/nim-lang/Nim/issues/13129
    # test for https://github.com/nim-lang/Nim/issues/13891
    let file = testsDir / "nimdoc/m13129.nim"
    for backend in fmt"{mode} js".split:
      # pending #14343 this fails on windows: --doccmd:"-d:m13129Foo2 --hints:off"
      let cmd = fmt"""{nim} doc -b:{backend} --nimcache:{nimcache} -d:m13129Foo1 "--doccmd:-d:m13129Foo2 --hints:off" --usenimcache --hints:off {file}"""
      check execCmdEx(cmd) == (&"ok1:{backend}\nok2: backend: {backend}\n", 0)
    # checks that --usenimcache works with `nim doc`
    check fileExists(nimcache / "htmldocs/m13129.html")

    block: # mak sure --backend works with `nim r`
      let cmd = fmt"{nim} r --backend:{mode} --hints:off --nimcache:{nimcache} {file}"
      check execCmdEx(cmd) == ("ok3\n", 0)

  block: # further issues with `--backend`
    let file = testsDir / "misc/mbackend.nim"
    var cmd = fmt"{nim} doc -b:cpp --hints:off --nimcache:{nimcache} {file}"
    check execCmdEx(cmd) == ("", 0)
    cmd = fmt"{nim} check -b:c -b:cpp --hints:off --nimcache:{nimcache} {file}"
    check execCmdEx(cmd) == ("", 0)
    # issue https://github.com/timotheecour/Nim/issues/175
    cmd = fmt"{nim} c -b:js -b:cpp --hints:off --nimcache:{nimcache} {file}"
    check execCmdEx(cmd) == ("", 0)

  block: # some importc tests
    # issue #14314
    let file = testsDir / "misc/mimportc.nim"
    let cmd = fmt"{nim} r -b:cpp --hints:off --nimcache:{nimcache} --warningAsError:ProveInit {file}"
    check execCmdEx(cmd) == ("witness\n", 0)