summary refs log tree commit diff stats
path: root/tests/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/stdlib')
-rw-r--r--tests/stdlib/t10231.nim15
-rw-r--r--tests/stdlib/tgetaddrinfo.nim36
-rw-r--r--tests/stdlib/tjsonmacro.nim4
-rw-r--r--tests/stdlib/tmath.nim91
-rw-r--r--tests/stdlib/tmget.nim8
-rw-r--r--tests/stdlib/tos.nim110
-rw-r--r--tests/stdlib/tosproc.nim112
-rw-r--r--tests/stdlib/trepr.nim11
-rw-r--r--tests/stdlib/ttimes.nim11
-rw-r--r--tests/stdlib/tunittest.nim1
10 files changed, 307 insertions, 92 deletions
diff --git a/tests/stdlib/t10231.nim b/tests/stdlib/t10231.nim
new file mode 100644
index 000000000..2bb64b475
--- /dev/null
+++ b/tests/stdlib/t10231.nim
@@ -0,0 +1,15 @@
+discard """
+  target: cpp
+  action: run
+  exitcode: 0
+"""
+
+import os
+
+# consider moving this inside tosproc (taking care that it's for cpp mode)
+
+if paramCount() == 0:
+  # main process
+  doAssert execShellCmd(getAppFilename().quoteShell & " test") == 1
+else:
+  quit 1
diff --git a/tests/stdlib/tgetaddrinfo.nim b/tests/stdlib/tgetaddrinfo.nim
new file mode 100644
index 000000000..39102e131
--- /dev/null
+++ b/tests/stdlib/tgetaddrinfo.nim
@@ -0,0 +1,36 @@
+discard """
+  exitcode: 0
+  output: ""
+"""
+
+# bug: https://github.com/nim-lang/Nim/issues/10198
+
+import nativesockets
+
+block DGRAM_UDP:
+  let aiList = getAddrInfo("127.0.0.1", 999.Port, AF_INET, SOCK_DGRAM, IPPROTO_UDP)
+  doAssert aiList != nil
+  doAssert aiList.ai_addr != nil
+  doAssert aiList.ai_addrlen == 16
+  doAssert aiList.ai_next == nil
+  freeAddrInfo aiList
+
+when defined(posix):
+
+  block RAW_ICMP:
+    # the port will be ignored
+    let aiList = getAddrInfo("127.0.0.1", 999.Port, AF_INET, SOCK_RAW, IPPROTO_ICMP)
+    doAssert aiList != nil
+    doAssert aiList.ai_addr != nil
+    doAssert aiList.ai_addrlen == 16
+    doAssert aiList.ai_next == nil
+    freeAddrInfo aiList
+
+  block RAW_ICMPV6:
+    # the port will be ignored
+    let aiList = getAddrInfo("::1", 999.Port, AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
+    doAssert aiList != nil
+    doAssert aiList.ai_addr != nil
+    doAssert aiList.ai_addrlen == 28
+    doAssert aiList.ai_next == nil
+    freeAddrInfo aiList
diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim
index 33332447b..2e95b4833 100644
--- a/tests/stdlib/tjsonmacro.nim
+++ b/tests/stdlib/tjsonmacro.nim
@@ -516,3 +516,7 @@ when true:
       var w = u.to(MyDistRef)
       doAssert v.name == "smith"
       doAssert MyRef(w).name == "smith"
+
+    block test_tuple:
+      doAssert $(%* (a1: 10, a2: "foo")) == """{"a1":10,"a2":"foo"}"""
+      doAssert $(%* (10, "foo")) == """[10,"foo"]"""
diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim
index 581308a7e..bdb5aa332 100644
--- a/tests/stdlib/tmath.nim
+++ b/tests/stdlib/tmath.nim
@@ -4,6 +4,10 @@ discard """
 
 [Suite] random float
 
+[Suite] cumsum
+
+[Suite] random sample
+
 [Suite] ^
 
 '''
@@ -11,34 +15,34 @@ discard """
 
 import math, random, os
 import unittest
-import sets
+import sets, tables
 
 suite "random int":
   test "there might be some randomness":
     var set = initSet[int](128)
-    randomize()
+
     for i in 1..1000:
       incl(set, random(high(int)))
     check len(set) == 1000
   test "single number bounds work":
-    randomize()
+
     var rand: int
     for i in 1..1000:
       rand = random(1000)
       check rand < 1000
       check rand > -1
   test "slice bounds work":
-    randomize()
+
     var rand: int
     for i in 1..1000:
       rand = random(100..1000)
       check rand < 1000
       check rand >= 100
-  test "randomize() again gives new numbers":
-    randomize()
+  test " again gives new numbers":
+
     var rand1 = random(1000000)
     os.sleep(200)
-    randomize()
+
     var rand2 = random(1000000)
     check rand1 != rand2
 
@@ -46,32 +50,93 @@ suite "random int":
 suite "random float":
   test "there might be some randomness":
     var set = initSet[float](128)
-    randomize()
+
     for i in 1..100:
       incl(set, random(1.0))
     check len(set) == 100
   test "single number bounds work":
-    randomize()
+
     var rand: float
     for i in 1..1000:
       rand = random(1000.0)
       check rand < 1000.0
       check rand > -1.0
   test "slice bounds work":
-    randomize()
+
     var rand: float
     for i in 1..1000:
       rand = random(100.0..1000.0)
       check rand < 1000.0
       check rand >= 100.0
-  test "randomize() again gives new numbers":
-    randomize()
+  test " again gives new numbers":
+
     var rand1:float = random(1000000.0)
     os.sleep(200)
-    randomize()
+
     var rand2:float = random(1000000.0)
     check rand1 != rand2
 
+suite "cumsum":
+  test "cumsum int seq return":
+    let counts = [ 1, 2, 3, 4 ]
+    check counts.cumsummed == [ 1, 3, 6, 10 ]
+
+  test "cumsum float seq return":
+    let counts = [ 1.0, 2.0, 3.0, 4.0 ]
+    check counts.cumsummed == [ 1.0, 3.0, 6.0, 10.0 ]
+
+  test "cumsum int in-place":
+    var counts = [ 1, 2, 3, 4 ]
+    counts.cumsum
+    check counts == [ 1, 3, 6, 10 ]
+
+  test "cumsum float in-place":
+    var counts = [ 1.0, 2.0, 3.0, 4.0 ]
+    counts.cumsum
+    check counts == [ 1.0, 3.0, 6.0, 10.0 ]
+
+suite "random sample":
+  test "non-uniform array sample unnormalized int CDF":
+    let values = [ 10, 20, 30, 40, 50 ] # values
+    let counts = [ 4, 3, 2, 1, 0 ]      # weights aka unnormalized probabilities
+    var histo = initCountTable[int]()
+    let cdf = counts.cumsummed          # unnormalized CDF
+    for i in 0 ..< 5000:
+      histo.inc(sample(values, cdf))
+    check histo.len == 4                # number of non-zero in `counts`
+    # Any one bin is a binomial random var for n samples, each with prob p of
+    # adding a count to k; E[k]=p*n, Var k=p*(1-p)*n, approximately Normal for
+    # big n.  So, P(abs(k - p*n)/sqrt(p*(1-p)*n))>3.0) =~ 0.0027, while
+    # P(wholeTestFails) =~ 1 - P(binPasses)^4 =~ 1 - (1-0.0027)^4 =~ 0.01.
+    for i, c in counts:
+      if c == 0:
+        check values[i] notin histo
+        continue
+      let p = float(c) / float(cdf[^1])
+      let n = 5000.0
+      let expected = p * n
+      let stdDev = sqrt(n * p * (1.0 - p))
+      check abs(float(histo[values[i]]) - expected) <= 3.0 * stdDev
+
+  test "non-uniform array sample normalized float CDF":
+    let values = [ 10, 20, 30, 40, 50 ]     # values
+    let counts = [ 0.4, 0.3, 0.2, 0.1, 0 ]  # probabilities
+    var histo = initCountTable[int]()
+    let cdf = counts.cumsummed              # normalized CDF
+    for i in 0 ..< 5000:
+      histo.inc(sample(values, cdf))
+    check histo.len == 4                    # number of non-zero in ``counts``
+    for i, c in counts:
+      if c == 0:
+        check values[i] notin histo
+        continue
+      let p = float(c) / float(cdf[^1])
+      let n = 5000.0
+      let expected = p * n
+      let stdDev = sqrt(n * p * (1.0 - p))
+      # NOTE: like unnormalized int CDF test, P(wholeTestFails) =~ 0.01.
+      check abs(float(histo[values[i]]) - expected) <= 3.0 * stdDev
+
 suite "^":
   test "compiles for valid types":
     check: compiles(5 ^ 2)
diff --git a/tests/stdlib/tmget.nim b/tests/stdlib/tmget.nim
index 5792b6282..5e2e327f4 100644
--- a/tests/stdlib/tmget.nim
+++ b/tests/stdlib/tmget.nim
@@ -11,10 +11,10 @@ Can't access 6
 Can't access 6
 10
 11
-Can't access 6
+0
 10
 11
-Can't access 6
+0
 10
 11
 Can't access 6
@@ -85,7 +85,7 @@ block:
   except KeyError:
     echo "Can't access 6"
   echo x[5]
-  x[5] += 1
+  x.inc 5, 1
   var c = x[5]
   echo c
 
@@ -97,7 +97,7 @@ block:
   except KeyError:
     echo "Can't access 6"
   echo x[5]
-  x[5] += 1
+  x.inc 5, 1
   var c = x[5]
   echo c
 
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index 467f64fff..e4e14d5a1 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -189,62 +189,44 @@ block walkDirRec:
 
   removeDir("walkdir_test")
 
-block normalizedPath:
-  when defined(posix):
-    block relative:
-      doAssert normalizedPath(".") == "."
-      doAssert normalizedPath("..") == ".."
-      doAssert normalizedPath("../") == ".."
-      doAssert normalizedPath("../..") == "../.."
-      doAssert normalizedPath("../a/..") == ".."
-      doAssert normalizedPath("../a/../") == ".."
-      doAssert normalizedPath("./") == "."
-
-    block absolute:
-      doAssert normalizedPath("/") == "/"
-      doAssert normalizedPath("/.") == "/"
-      doAssert normalizedPath("/..") == "/"
-      doAssert normalizedPath("/../") == "/"
-      doAssert normalizedPath("/../..") == "/"
-      doAssert normalizedPath("/../../") == "/"
-      doAssert normalizedPath("/../../../") == "/"
-      doAssert normalizedPath("/a/b/../../foo") == "/foo"
-      doAssert normalizedPath("/a/b/../../../foo") == "/foo"
-      doAssert normalizedPath("/./") == "/"
-      doAssert normalizedPath("//") == "/"
-      doAssert normalizedPath("///") == "/"
-      doAssert normalizedPath("/a//b") == "/a/b"
-      doAssert normalizedPath("/a///b") == "/a/b"
-      doAssert normalizedPath("/a/b/c/..") == "/a/b"
-      doAssert normalizedPath("/a/b/c/../") == "/a/b"
+when not defined(windows):
+  block walkDirRelative:
+    createDir("walkdir_test")
+    createSymlink(".", "walkdir_test/c")
+    for k, p in walkDir("walkdir_test", true):
+      doAssert k == pcLinkToDir
+    removeDir("walkdir_test")
 
-  else:
-    block relative:
-      doAssert normalizedPath(".") == "."
-      doAssert normalizedPath("..") == ".."
-      doAssert normalizedPath("..\\") == ".."
-      doAssert normalizedPath("..\\..") == "..\\.."
-      doAssert normalizedPath("..\\a\\..") == ".."
-      doAssert normalizedPath("..\\a\\..\\") == ".."
-      doAssert normalizedPath(".\\") == "."
-
-    block absolute:
-      doAssert normalizedPath("\\") == "\\"
-      doAssert normalizedPath("\\.") == "\\"
-      doAssert normalizedPath("\\..") == "\\"
-      doAssert normalizedPath("\\..\\") == "\\"
-      doAssert normalizedPath("\\..\\..") == "\\"
-      doAssert normalizedPath("\\..\\..\\") == "\\"
-      doAssert normalizedPath("\\..\\..\\..\\") == "\\"
-      doAssert normalizedPath("\\a\\b\\..\\..\\foo") == "\\foo"
-      doAssert normalizedPath("\\a\\b\\..\\..\\..\\foo") == "\\foo"
-      doAssert normalizedPath("\\.\\") == "\\"
-      doAssert normalizedPath("\\\\") == "\\"
-      doAssert normalizedPath("\\\\\\") == "\\"
-      doAssert normalizedPath("\\a\\\\b") == "\\a\\b"
-      doAssert normalizedPath("\\a\\\\\\b") == "\\a\\b"
-      doAssert normalizedPath("\\a\\b\\c\\..") == "\\a\\b"
-      doAssert normalizedPath("\\a\\b\\c\\..\\") == "\\a\\b"
+block normalizedPath:
+  doAssert normalizedPath("") == ""
+  block relative:
+    doAssert normalizedPath(".") == "."
+    doAssert normalizedPath("foo/..") == "."
+    doAssert normalizedPath("foo//../bar/.") == "bar"
+    doAssert normalizedPath("..") == ".."
+    doAssert normalizedPath("../") == ".."
+    doAssert normalizedPath("../..") == unixToNativePath"../.."
+    doAssert normalizedPath("../a/..") == ".."
+    doAssert normalizedPath("../a/../") == ".."
+    doAssert normalizedPath("./") == "."
+
+  block absolute:
+    doAssert normalizedPath("/") == unixToNativePath"/"
+    doAssert normalizedPath("/.") == unixToNativePath"/"
+    doAssert normalizedPath("/..") == unixToNativePath"/.."
+    doAssert normalizedPath("/../") == unixToNativePath"/.."
+    doAssert normalizedPath("/../..") == unixToNativePath"/../.."
+    doAssert normalizedPath("/../../") == unixToNativePath"/../.."
+    doAssert normalizedPath("/../../../") == unixToNativePath"/../../.."
+    doAssert normalizedPath("/a/b/../../foo") == unixToNativePath"/foo"
+    doAssert normalizedPath("/a/b/../../../foo") == unixToNativePath"/../foo"
+    doAssert normalizedPath("/./") == unixToNativePath"/"
+    doAssert normalizedPath("//") == unixToNativePath"/"
+    doAssert normalizedPath("///") == unixToNativePath"/"
+    doAssert normalizedPath("/a//b") == unixToNativePath"/a/b"
+    doAssert normalizedPath("/a///b") == unixToNativePath"/a/b"
+    doAssert normalizedPath("/a/b/c/..") == unixToNativePath"/a/b"
+    doAssert normalizedPath("/a/b/c/../") == unixToNativePath"/a/b"
 
 block isHidden:
   when defined(posix):
@@ -265,3 +247,21 @@ block absolutePath:
     doAssert absolutePath("a", "/b/c") == "/b/c" / "a"
     doAssert absolutePath("/a", "b/") == "/a"
 
+block splitFile:
+  doAssert splitFile("") == ("", "", "")
+  doAssert splitFile("abc/") == ("abc", "", "")
+  doAssert splitFile("/") == ("/", "", "")
+  doAssert splitFile("./abc") == (".", "abc", "")
+  doAssert splitFile(".txt") == ("", ".txt", "")
+  doAssert splitFile("abc/.txt") == ("abc", ".txt", "")
+  doAssert splitFile("abc") == ("", "abc", "")
+  doAssert splitFile("abc.txt") == ("", "abc", ".txt")
+  doAssert splitFile("/abc.txt") == ("/", "abc", ".txt")
+  doAssert splitFile("/foo/abc.txt") == ("/foo", "abc", ".txt")
+  doAssert splitFile("/foo/abc.txt.gz") == ("/foo", "abc.txt", ".gz")
+  doAssert splitFile(".") == ("", ".", "")
+  doAssert splitFile("abc/.") == ("abc", ".", "")
+  doAssert splitFile("..") == ("", "..", "")
+  doAssert splitFile("a/..") == ("a", "..", "")
+
+# execShellCmd is tested in tosproc
diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim
index 9d57d4574..b8d3be9bb 100644
--- a/tests/stdlib/tosproc.nim
+++ b/tests/stdlib/tosproc.nim
@@ -1,23 +1,99 @@
-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)
+    try:
+      removeFile(exePath)
+    except OSError:
+      discard
diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim
index 33cb581ef..c1941bd38 100644
--- a/tests/stdlib/trepr.nim
+++ b/tests/stdlib/trepr.nim
@@ -1,5 +1,6 @@
 discard """
-  output: "{a, b}{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}"
+  output: '''{a, b}{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
+[1, 2, 3, 4, 5, 6]'''
 """
 
 type
@@ -25,3 +26,11 @@ when false:
 #  "a", "b", "c", "d", "e"
 #]
 #echo(repr(testseq))
+
+# bug #7878
+proc test(variable: var openarray[int]) =
+  echo repr(variable)
+
+var arr = [1, 2, 3, 4, 5, 6]
+
+test(arr)
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index ed87b15ac..3999c968f 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -245,6 +245,17 @@ suite "ttimes":
     parseTestExcp("12345", "uuuu")
     parseTestExcp("-1 BC", "UUUU g")
 
+  test "incorrect inputs: invalid sign":
+    parseTestExcp("+1", "YYYY")
+    parseTestExcp("+1", "dd")
+    parseTestExcp("+1", "MM")
+    parseTestExcp("+1", "hh")
+    parseTestExcp("+1", "mm")
+    parseTestExcp("+1", "ss")
+
+  test "_ as a separator":
+    discard parse("2000_01_01", "YYYY'_'MM'_'dd")
+
   test "dynamic timezone":
     let tz = staticTz(seconds = -9000)
     let dt = initDateTime(1, mJan, 2000, 12, 00, 00, tz)
diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim
index c8656bbff..65baefef0 100644
--- a/tests/stdlib/tunittest.nim
+++ b/tests/stdlib/tunittest.nim
@@ -50,7 +50,6 @@ test "unittest multiple requires":
 import math, random
 from strutils import parseInt
 proc defectiveRobot() =
-  randomize()
   case random(1..4)
   of 1: raise newException(OSError, "CANNOT COMPUTE!")
   of 2: discard parseInt("Hello World!")