From 330b3c4453bbff572987ad7fe2f435b353529964 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Wed, 6 May 2020 08:16:54 -0700 Subject: [PATCH] fix regression: -d:nimHasLibFFI was not being tested anymore (#14234) * * fix regression: -d:nimHasLibFFI was not being tested anymore, in part because testament was silently treating some errors as easy to overlook messages * turned that message into an error * -d:nimHasLibFFI is now being tested with nim cpp * use correct signatures for importc procs * workaround for openbsd to unblock ctffi testing --- koch.nim | 9 ++++++--- testament/categories.nim | 2 +- tests/trunner.nim | 35 ++++++++++++++++++++++++++--------- tests/vm/mevalffi.nim | 30 +++++++++++++++++------------- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/koch.nim b/koch.nim index 9193cb43ed..017db86783 100644 --- a/koch.nim +++ b/koch.nim @@ -289,11 +289,13 @@ proc findStartNim: string = proc thVersion(i: int): string = result = ("compiler" / "nim" & $i).exe +template doUseCpp(): bool = getEnv("NIM_COMPILE_TO_CPP", "false") == "true" + proc boot(args: string) = var output = "compiler" / "nim".exe var finalDest = "bin" / "nim".exe # default to use the 'c' command: - let useCpp = getEnv("NIM_COMPILE_TO_CPP", "false") == "true" + let useCpp = doUseCpp() let smartNimcache = (if "release" in args or "danger" in args: "nimcache/r_" else: "nimcache/d_") & hostOS & "_" & hostCPU @@ -542,8 +544,9 @@ proc runCI(cmd: string) = execFold("nimble install -y libffi", "nimble install -y libffi") const nimFFI = "./bin/nim.ctffi" # no need to bootstrap with koch boot (would be slower) - execFold("build with -d:nimHasLibFFI", "nim c -d:release -d:nimHasLibFFI -o:$1 compiler/nim.nim" % [nimFFI]) - execFold("test with -d:nimHasLibFFI", "$1 c -r testament/testament --nim:$1 r tests/vm/tevalffi.nim" % [nimFFI]) + let backend = if doUseCpp(): "cpp" else: "c" + execFold("build with -d:nimHasLibFFI", "nim $1 -d:release -d:nimHasLibFFI -o:$2 compiler/nim.nim" % [backend, nimFFI]) + execFold("test with -d:nimHasLibFFI", "$1 $2 -r testament/testament --nim:$1 r tests/trunner.nim" % [nimFFI, backend]) execFold("Run nimdoc tests", "nim c -r nimdoc/tester") execFold("Run nimpretty tests", "nim c -r nimpretty/tester.nim") diff --git a/testament/categories.nim b/testament/categories.nim index e1519468fe..3affe0699a 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -545,7 +545,7 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) = if existsFile(test): testSpec r, makeTest(test, options, cat), {target} else: - echo "[Warning] - ", test, " test does not exist" + doAssert false, test & " test does not exist" proc isJoinableSpec(spec: TSpec): bool = result = not spec.sortoutput and diff --git a/tests/trunner.nim b/tests/trunner.nim index 265a3712d4..f71c324a23 100644 --- a/tests/trunner.nim +++ b/tests/trunner.nim @@ -1,43 +1,60 @@ 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. -import std/[strformat,os,osproc,strutils] +import std/[strformat,os,osproc] const nim = getCurrentCompilerExe() +const mode = + when defined(c): "c" + elif defined(cpp): "cpp" + else: static: doAssert false + proc runCmd(file, options = ""): auto = - let mode = if existsEnv("NIM_COMPILE_TO_CPP"): "cpp" else: "c" const testsDir = currentSourcePath().parentDir let fileabs = testsDir / file.unixToNativePath doAssert fileabs.existsFile, fileabs let cmd = fmt"{nim} {mode} {options} --hints:off {fileabs}" result = execCmdEx(cmd) - when false: # uncomment if you need to debug - echo result[0] - echo result[1] + when false: echo result[0] & "\n" & result[1] # for debugging when defined(nimHasLibFFIEnabled): block: # mevalffi - let (output, exitCode) = runCmd("vm/mevalffi.nim", "--experimental:compiletimeFFI") - let expected = """ + 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 -foo +""" + 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} +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 check(msg) = doAssert msg in output, output block: # mstatic_assert diff --git a/tests/vm/mevalffi.nim b/tests/vm/mevalffi.nim index e15ed8f74d..ad8f8b62b5 100644 --- a/tests/vm/mevalffi.nim +++ b/tests/vm/mevalffi.nim @@ -8,9 +8,9 @@ proc c_exp(a: float64): float64 {.importc: "exp", header: "".} proc c_printf(frmt: cstring): cint {.importc: "printf", header: "", varargs, discardable.} const snprintfName = when defined(windows): "_snprintf" else: "snprintf" -proc c_snprintf*(buffer: pointer, buf_size: uint, format: cstring): cint {.importc: snprintfName, header: "", varargs .} +proc c_snprintf*(str: cstring, size: csize_t, format: cstring): cint {.importc: snprintfName, header: "", varargs .} -proc c_malloc(size:uint):pointer {.importc:"malloc", header: "".} +proc c_malloc(size: csize_t): pointer {.importc:"malloc", header: "".} proc c_free(p: pointer) {.importc:"free", header: "".} proc fun() = @@ -35,12 +35,15 @@ proc fun() = block: # c_snprintf, c_malloc, c_free let n: uint = 50 - var buffer2: pointer = c_malloc(n) + var buffer2 = cstring(cast[ptr char](c_malloc(n))) + var s: cstring = "foobar" var age: cint = 25 - discard c_snprintf(buffer2, n, "s1:%s s2:%s age:%d pi:%g", s, s, age, 3.14) - c_printf("ret={%s}\n", buffer2) - c_free(buffer2) # not sure it has an effect + let num = c_snprintf(buffer2, n, "s1:%s s2:%s age:%d pi:%g", s, s, age, 3.14) + let numExp = 34 + doAssert num == numExp + c_printf("ret=[%s]\n", buffer2) + c_free(buffer2) block: # c_printf bug var a = 123 @@ -58,10 +61,11 @@ static: fun() fun() -import system/ansi_c -block: - proc fun2()= - c_fprintf(cstderr, "hello world stderr\n") - write(stderr, "hi stderr\n") - static: fun2() - fun2() +when not defined nimEvalffiStderrWorkaround: + import system/ansi_c + block: + proc fun2()= + c_fprintf(cstderr, "hello world stderr\n") + write(stderr, "hi stderr\n") + static: fun2() + fun2()