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. ## Note: if needed, we could use `matrix: "-d:case1; -d:case2"` to split this ## into several independent tests while retaining the common test helpers. import std/[strformat,os,osproc,unittest,compilesettings] from std/sequtils import toSeq,mapIt from std/algorithm import sorted import stdtest/[specialpaths, unittest_light] from std/private/globs import nativeToUnixPath from strutils import startsWith, strip, removePrefix from std/sugar import dup import "$lib/../compiler/nimpaths" proc isDots(a: string): bool = ## test for `hintProcessing` dots a.startsWith(".") and a.strip(chars = {'.'}) == "" const defaultHintsOff = "--hint:successx:off --hint:buildmode:off --hint:exec:off --hint:link:off --hint:cc:off --hint:conf:off --hint:processing:off --hint:QuitCalled:off" # useful when you want to turn only some hints on, and some common ones off. # pending https://github.com/timotheecour/Nim/issues/453, simplify to: `--hints:off` nim = getCurrentCompilerExe() mode = querySetting(backend) nimcache = buildDir / "nimcacheTrunner" # instead of `querySetting(nimcacheDir)`, avoids stomping on other parallel tests proc runNimCmd(file, options = "", rtarg = ""): auto = let fileabs = testsDir / file.unixToNativePath # doAssert fileabs.fileExists, fileabs # disabled because this allows passing `nim r --eval:code fakefile` let cmd = fmt"{nim} {mode} {options} --hints:off {fileabs} {rtarg}" result = execCmdEx(cmd) when false: # for debugging echo cmd echo result[0] & "\n" & $result[1] proc runNimCmdChk(file, options = "", rtarg = ""): string = let (ret, status) = runNimCmd(file, options, rtarg = rtarg) doAssert status == 0, $(file, options) & "\n" & ret ret proc genShellCmd(filename: string): string = let filename = filename.quoteShell when defined(windows): "cmd /c " & filename # or "cmd /c " ? else: "sh " & filename 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 = runNimCmdChk("vm/mevalffi.nim", fmt"{opt} --experimental:compiletimeFFI") doAssert output == 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] """, output elif not defined(nimTestsTrunnerDebugging): # don't run twice the same test with `nimTrunnerFfi` # use `-d:nimTestsTrunnerDebugging` for debugging convenience when you want to just run 1 test import std/strutils import std/json 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..>> ")) == "3" # prompt depends on `nimUseLinenoise` check3 lines[2].isDots check3 lines[3] == "ab" check3 lines[4] == "" else: check3 "3" in outp check3 "ab" in outp doAssert exitCode == 0 block: let (outp, exitCode) = run "echo 1+2; quit(2)" check3 "3" in outp doAssert exitCode == 2 block: # nimBetterRun let file = "misc/mbetterrun.nim" const nimcache2 = buildDir / "D20210423T185116" removeDir nimcache2 # related to `-d:nimBetterRun` let opt = fmt"-r --usenimcache --nimcache:{nimcache2}" var ret = "" for a in @["v1", "v2", "v1", "v3"]: ret.add runNimCmdChk(file, fmt"{opt} -d:mbetterrunVal:{a}") ret.add runNimCmdChk(file, fmt"{opt} -d:mbetterrunVal:v2", rtarg = "arg1 arg2") # rt arguments should not cause a recompilation doAssert ret == """ compiling: v1 running: v1 compiling: v2 running: v2 running: v1 compiling: v3 running: v3 running: v2 """, ret block: # nim dump let cmd = fmt"{nim} dump --dump.format:json -d:D20210428T161003 --hints:off ." let (ret, status) = execCmdEx(cmd) doAssert status == 0 let j = ret.parseJson # sanity checks doAssert "D20210428T161003" in j["defined_symbols"].to(seq[string]) doAssert j["version"].to(string) == NimVersion doAssert j["nimExe"].to(string) == getCurrentCompilerExe() block: # genscript const nimcache2 = buildDir / "D20210524T212851" removeDir(nimcache2) let input = "tgenscript_fakefile" # no need for a real file, --eval is good enough let output = runNimCmdChk(input, fmt"""--genscript --nimcache:{nimcache2.quoteShell} --eval:"echo(12345)" """) doAssert output.len == 0, output let ext = when defined(windows): ".bat" else: ".sh" let filename = fmt"compile_{input}{ext}" # synchronize with `generateScript` doAssert fileExists(nimcache2/filename), nimcache2/filename let (outp, status) = execCmdEx(genShellCmd(filename), options = {poStdErrToStdOut}, workingDir = nimcache2) doAssert status == 0, outp let (outp2, status2) = execCmdEx(nimcache2 / input, options = {poStdErrToStdOut}) doAssert outp2 == "12345\n", outp2 doAssert status2 == 0 else: discard # only during debugging, tests added here will run with `-d:nimTestsTrunnerDebugging` enabled