summary refs log tree commit diff stats
path: root/tests/stdlib/tosproc.nim
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2019-01-13 00:00:39 -0800
committerAndreas Rumpf <rumpf_a@web.de>2019-01-13 09:00:39 +0100
commit9af85fb69f26dcae5fba7881a597d78f6bc7ffc8 (patch)
treed267ba0b76363369bd8907d5e4924eac1e85e7eb /tests/stdlib/tosproc.nim
parentf5cc2e2de567b36d33778ddf263b7a440f1d3b11 (diff)
downloadNim-9af85fb69f26dcae5fba7881a597d78f6bc7ffc8.tar.gz
fixes #10273 execShellCmd now returns nonzero when child killed with signal + other fixes (#10274)
* s/exitStatus(...)/exitStatusLikeShell(...)/
* fix #10273 execShellCmd now returns nonzero when child exits with signal
* test case for #10249 and explanation for the bug
* fix test failure
* add tests/nim.cfg
Diffstat (limited to 'tests/stdlib/tosproc.nim')
-rw-r--r--tests/stdlib/tosproc.nim109
1 files changed, 91 insertions, 18 deletions
diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim
index 9d57d4574..7a7c1836f 100644
--- a/tests/stdlib/tosproc.nim
+++ b/tests/stdlib/tosproc.nim
@@ -1,23 +1,96 @@
-discard """
-  output: ""
-"""
 # test the osproc module
 
-import os, osproc
+import stdtest/specialpaths
+import "../.." / compiler/unittest_light
 
-block execProcessTest:
-  let dir = parentDir(currentSourcePath())
-  let (outp, err) = execCmdEx("nim c " & quoteShell(dir / "osproctest.nim"))
-  doAssert err == 0
-  let exePath = dir / addFileExt("osproctest", ExeExt)
-  let outStr1 = execProcess(exePath, workingDir=dir, args=["foo", "b A r"], options={})
-  doAssert outStr1 == dir & "\nfoo\nb A r\n"
+when defined(case_testfile): # compiled test file for child process
+  from posix import exitnow
+  proc c_exit2(code: c_int): void {.importc: "_exit", header: "<unistd.h>".}
+  import os
+  var a = 0
+  proc fun(b = 0) =
+    a.inc
+    if a mod 10000000 == 0: # prevents optimizing it away
+      echo a
+    fun(b+1)
 
-  const testDir = "t e st"
-  createDir(testDir)
-  doAssert dirExists(testDir)
-  let outStr2 = execProcess(exePath, workingDir=testDir, args=["x yz"], options={})
-  doAssert outStr2 == absolutePath(testDir) & "\nx yz\n"
+  proc main() =
+    let args = commandLineParams()
+    echo (msg: "child binary", pid: getCurrentProcessId())
+    let arg = args[0]
+    echo (arg: arg)
+    case arg
+    of "exit_0":
+      if true: quit(0)
+    of "exitnow_139":
+      if true: exitnow(139)
+    of "c_exit2_139":
+      if true: c_exit2(139)
+    of "quit_139":
+      # `exitStatusLikeShell` doesn't distinguish between a process that
+      # exit(139) and a process that gets killed with `SIGSEGV` because
+      # 139 = 11 + 128 = SIGSEGV + 128.
+      # However, as #10249 shows, this leads to bad debugging experience
+      # when a child process dies with SIGSEGV, leaving no trace of why it
+      # failed. The shell (and lldb debugger) solves that by inserting a
+      # helpful msg: `segmentation fault` when it detects a signal killed
+      # the child.
+      # todo: expose an API that will show more diagnostic, returing
+      # (exitCode, signal) instead of just `shellExitCode`.
+      if true: quit(139)
+    of "exit_recursion": # stack overflow by infinite recursion
+      fun()
+      echo a
+    of "exit_array": # bad array access
+      echo args[1]
+  main()
 
-  removeDir(testDir)
-  removeFile(exePath)
+else:
+
+  import os, osproc, strutils, posix
+
+  block execShellCmdTest:
+    ## first, compile child program
+    const nim = getCurrentCompilerExe()
+    const sourcePath = currentSourcePath()
+    let output = buildDir / "D20190111T024543".addFileExt(ExeExt)
+    let cmd = "$# c -o:$# -d:release -d:case_testfile $#" % [nim, output,
+        sourcePath]
+    # we're testing `execShellCmd` so don't rely on it to compile test file
+    # note: this should be exported in posix.nim
+    proc c_system(cmd: cstring): cint {.importc: "system",
+      header: "<stdlib.h>".}
+    assertEquals c_system(cmd), 0
+
+    ## use it
+    template runTest(arg: string, expected: int) =
+      echo (arg2: arg, expected2: expected)
+      assertEquals execShellCmd(output & " " & arg), expected
+
+    runTest("exit_0", 0)
+    runTest("exitnow_139", 139)
+    runTest("c_exit2_139", 139)
+    runTest("quit_139", 139)
+    runTest("exit_array", 1)
+    when defined(posix): # on windows, -1073741571
+      runTest("exit_recursion", SIGSEGV.int + 128) # bug #10273: was returning 0
+      assertEquals exitStatusLikeShell(SIGSEGV), SIGSEGV + 128.cint
+
+  block execProcessTest:
+    let dir = parentDir(currentSourcePath())
+    let (outp, err) = execCmdEx("nim c " & quoteShell(dir / "osproctest.nim"))
+    doAssert err == 0
+    let exePath = dir / addFileExt("osproctest", ExeExt)
+    let outStr1 = execProcess(exePath, workingDir = dir, args = ["foo",
+        "b A r"], options = {})
+    doAssert outStr1 == dir & "\nfoo\nb A r\n"
+
+    const testDir = "t e st"
+    createDir(testDir)
+    doAssert dirExists(testDir)
+    let outStr2 = execProcess(exePath, workingDir = testDir, args = ["x yz"],
+        options = {})
+    doAssert outStr2 == absolutePath(testDir) & "\nx yz\n"
+
+    removeDir(testDir)
+    removeFile(exePath)