summary refs log tree commit diff stats
path: root/tests/osproc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/osproc')
-rw-r--r--tests/osproc/passenv.nim32
-rw-r--r--tests/osproc/tclose.nim24
-rw-r--r--tests/osproc/texecps.nim30
-rw-r--r--tests/osproc/texitsignal.nim39
-rw-r--r--tests/osproc/tnoexe.nim27
-rw-r--r--tests/osproc/treadlines.nim23
-rw-r--r--tests/osproc/twaitforexit.nim38
-rw-r--r--tests/osproc/tworkingdir.nim21
8 files changed, 234 insertions, 0 deletions
diff --git a/tests/osproc/passenv.nim b/tests/osproc/passenv.nim
new file mode 100644
index 000000000..40b1c3f7c
--- /dev/null
+++ b/tests/osproc/passenv.nim
@@ -0,0 +1,32 @@
+discard """
+  file: "passenv.nim"
+  output: "123"
+  targets: "c cpp objc"
+"""
+
+import osproc, os, strtabs
+
+# Checks that the environment is passed correctly in startProcess
+# To do that launches a copy of itself with a new environment.
+
+if paramCount() == 0:
+  # Parent process
+
+  let env = newStringTable()
+  env["A"] = "1"
+  env["B"] = "2"
+  env["C"] = "3"
+
+  let p = startProcess(
+    getAppFilename(),
+    args = @["child"],
+    env = env,
+    options = {poStdErrToStdOut, poUsePath, poParentStreams}
+  )
+
+  discard p.waitForExit
+
+else:
+  # Child process
+  # should output "123"
+  echo getEnv("A") & getEnv("B") & getEnv("C")
diff --git a/tests/osproc/tclose.nim b/tests/osproc/tclose.nim
new file mode 100644
index 000000000..1c99237c7
--- /dev/null
+++ b/tests/osproc/tclose.nim
@@ -0,0 +1,24 @@
+discard """
+  exitcode: 0
+"""
+
+when defined(linux):
+  import osproc, os
+
+  proc countFds(): int =
+    result = 0
+    for i in walkDir("/proc/self/fd"):
+      result += 1
+
+  let initCount = countFds()
+
+  let p = osproc.startProcess("echo", options={poUsePath})
+  doAssert countFds() == initCount + 3
+  p.close
+  doAssert countFds() == initCount
+
+  let p1 = osproc.startProcess("echo", options={poUsePath})
+  discard p1.inputStream
+  doAssert countFds() == initCount + 3
+  p.close
+  doAssert countFds() == initCount
diff --git a/tests/osproc/texecps.nim b/tests/osproc/texecps.nim
new file mode 100644
index 000000000..b818fe8eb
--- /dev/null
+++ b/tests/osproc/texecps.nim
@@ -0,0 +1,30 @@
+discard """
+joinable: false
+"""
+
+import osproc, streams, strutils, os
+
+const NumberOfProcesses = 13
+
+var gResults {.threadvar.}: seq[string]
+
+proc execCb(idx: int, p: Process) =
+  let exitCode = p.peekExitCode
+  if exitCode < len(gResults):
+    gResults[exitCode] = p.outputStream.readAll.strip
+
+when true:
+  if paramCount() == 0:
+    gResults = newSeq[string](NumberOfProcesses)
+    var checks = newSeq[string](NumberOfProcesses)
+    var commands = newSeq[string](NumberOfProcesses)
+    for i in 0..len(commands) - 1:
+      commands[i] = getAppFileName() & " " & $i
+      checks[i] = $i
+    let cres = execProcesses(commands, options = {poStdErrToStdOut},
+                             afterRunEvent = execCb)
+    doAssert(cres == len(commands) - 1)
+    doAssert(gResults == checks)
+  else:
+    echo paramStr(1)
+    programResult = parseInt(paramStr(1))
diff --git a/tests/osproc/texitsignal.nim b/tests/osproc/texitsignal.nim
new file mode 100644
index 000000000..fbf5068ea
--- /dev/null
+++ b/tests/osproc/texitsignal.nim
@@ -0,0 +1,39 @@
+discard """
+  output: '''true
+true'''
+  targets: "c"
+"""
+
+import os, osproc
+when not defined(windows):
+  import posix
+
+# Checks that the environment is passed correctly in startProcess
+# To do that launches a copy of itself with a new environment.
+
+if paramCount() == 0:
+  # Parent process
+
+  let p = startProcess(
+    getAppFilename(),
+    args = @["child"],
+    options = {poStdErrToStdOut, poUsePath, poParentStreams}
+  )
+
+  echo p.running()
+
+  p.kill()
+
+  when defined(windows):
+    # windows kill happens using TerminateProcess(h, 0), so we should get a
+    # 0 here
+    echo p.waitForExit() == 0
+  elif defined(haiku):
+    # on Haiku, the program main thread receive SIGKILLTHR
+    echo p.waitForExit() == 128 + SIGKILLTHR
+  else:
+    # on posix (non-windows), kill sends SIGKILL
+    echo p.waitForExit() == 128 + SIGKILL
+
+else:
+  sleep(5000)  # should get killed before this
diff --git a/tests/osproc/tnoexe.nim b/tests/osproc/tnoexe.nim
new file mode 100644
index 000000000..19a3cca67
--- /dev/null
+++ b/tests/osproc/tnoexe.nim
@@ -0,0 +1,27 @@
+discard """
+  output: '''true
+true'''
+"""
+
+import std/osproc
+
+const command = "lsaaa -lah"
+
+try:
+  let process = startProcess(command, options = {poUsePath})
+  discard process.waitForExit()
+except OSError as e:
+  echo e.errorCode != 0
+
+# `poEvalCommand`, invokes the system shell to run the specified command
+try:
+  let process = startProcess(command, options = {poUsePath, poEvalCommand})
+  # linux
+  let exitCode = process.waitForExit()
+  echo exitCode != 0
+except OSError as e:
+  # Because the implementation of `poEvalCommand` on different platforms is inconsistent, 
+  # Linux will not throw an exception, but Windows will throw an exception
+
+  # windows
+  echo e.errorCode != 0
diff --git a/tests/osproc/treadlines.nim b/tests/osproc/treadlines.nim
new file mode 100644
index 000000000..bb6a7f129
--- /dev/null
+++ b/tests/osproc/treadlines.nim
@@ -0,0 +1,23 @@
+discard """
+  output: '''
+Error: cannot open 'a.nim'
+Error: cannot open 'b.nim'
+'''
+  targets: "c"
+"""
+
+import osproc
+from std/os import getCurrentCompilerExe
+
+var ps: seq[Process] # compile & run 2 progs in parallel
+const nim = getCurrentCompilerExe()
+for prog in ["a", "b"]:
+  ps.add startProcess(nim, "",
+                      ["r", "--hint:Conf:off", "--hint:Processing:off", prog],
+                      options = {poUsePath, poDaemon, poStdErrToStdOut})
+
+for p in ps:
+  let (lines, exCode) = p.readLines
+  if exCode != 0:
+    for line in lines: echo line
+  p.close
diff --git a/tests/osproc/twaitforexit.nim b/tests/osproc/twaitforexit.nim
new file mode 100644
index 000000000..535faca63
--- /dev/null
+++ b/tests/osproc/twaitforexit.nim
@@ -0,0 +1,38 @@
+import std/[osproc, os, times]
+
+block: # bug #5091
+    when defined(linux):
+        const filename = "false"
+        var p = startProcess(filename, options = {poStdErrToStdOut, poUsePath})
+        os.sleep(1000) # make sure process has exited already
+
+        let atStart = getTime()
+        const msWait = 2000
+
+        try:
+            discard waitForExit(p, msWait)
+        except OSError:
+            discard
+
+        # check that we don't have to wait msWait milliseconds
+        doAssert(getTime() <  atStart + milliseconds(msWait))
+
+block: # bug #23825
+
+    # the sleep command might not be available in all Windows installations
+
+    when defined(linux):
+
+        var thr: array[0..99, Thread[int]]
+
+        proc threadFunc(i: int) {.thread.} =
+            let sleepTime = float(i) / float(thr.len + 1)
+            doAssert sleepTime < 1.0
+            let p = startProcess("sleep", workingDir = "", args = @[$sleepTime], options = {poUsePath, poParentStreams})
+            # timeout = 1_000_000 seconds ~= 278 hours ~= 11.5 days
+            doAssert p.waitForExit(timeout=1_000_000_000) == 0
+
+        for i in low(thr)..high(thr):
+            createThread(thr[i], threadFunc, i)
+
+        joinThreads(thr) 
diff --git a/tests/osproc/tworkingdir.nim b/tests/osproc/tworkingdir.nim
new file mode 100644
index 000000000..3a3c1b6ab
--- /dev/null
+++ b/tests/osproc/tworkingdir.nim
@@ -0,0 +1,21 @@
+discard """
+  output: ""
+"""
+
+import osproc, os
+when defined(windows):
+  # Windows don't have this issue, so we won't test it.
+  discard
+else:
+  let dir1 = getCurrentDir()
+  var process: Process
+  when defined(android):
+    process = startProcess("/system/bin/env", "/system/bin", ["true"])
+  elif defined(haiku):
+    process = startProcess("/bin/env", "/bin", ["true"])
+  else:
+    process = startProcess("/usr/bin/env", "/usr/bin", ["true"])
+  let dir2 = getCurrentDir()
+  discard process.waitForExit()
+  process.close()
+  doAssert(dir1 == dir2, $dir1 & " != " & $dir2)