diff options
Diffstat (limited to 'tests/stdlib')
170 files changed, 2584 insertions, 698 deletions
diff --git a/tests/stdlib/concurrency/tatomics.nim b/tests/stdlib/concurrency/tatomics.nim index 9cfdce83d..08f2e7d3e 100644 --- a/tests/stdlib/concurrency/tatomics.nim +++ b/tests/stdlib/concurrency/tatomics.nim @@ -1,3 +1,9 @@ +discard """ + # test C with -d:nimUseCppAtomics as well to check nothing breaks + matrix: "--mm:refc; --mm:orc; --mm:refc -d:nimUseCppAtomics; --mm:orc -d:nimUseCppAtomics" + targets: "c cpp" +""" + # test atomic operations import std/[atomics, bitops] diff --git a/tests/stdlib/concurrency/tatomics_size.nim b/tests/stdlib/concurrency/tatomics_size.nim index 7b43787fb..f64adb308 100644 --- a/tests/stdlib/concurrency/tatomics_size.nim +++ b/tests/stdlib/concurrency/tatomics_size.nim @@ -1,4 +1,6 @@ discard """ + # test C with -d:nimUseCppAtomics as well to check nothing breaks + matrix: "--mm:refc; --mm:orc; --mm:refc -d:nimUseCppAtomics; --mm:orc -d:nimUseCppAtomics" targets: "c cpp" """ import std/atomics @@ -16,4 +18,4 @@ block testSize: # issue 12726 f: AtomicFlag static: doAssert sizeof(Node) == sizeof(pointer) - doAssert sizeof(MyChannel) == sizeof(pointer) * 2 \ No newline at end of file + doAssert sizeof(MyChannel) == sizeof(pointer) * 2 diff --git a/tests/stdlib/config.nims b/tests/stdlib/config.nims index ea5d738e2..dffae2812 100644 --- a/tests/stdlib/config.nims +++ b/tests/stdlib/config.nims @@ -1,3 +1,5 @@ switch("styleCheck", "usages") switch("styleCheck", "error") -switch("define", "nimPreviewSlimSystem") \ No newline at end of file +switch("define", "nimPreviewSlimSystem") +switch("define", "nimPreviewCstringConversion") +switch("define", "nimPreviewProcConversion") diff --git a/tests/stdlib/mimportutils.nim b/tests/stdlib/mimportutils.nim index e89d58d27..678d9ec02 100644 --- a/tests/stdlib/mimportutils.nim +++ b/tests/stdlib/mimportutils.nim @@ -26,6 +26,12 @@ type H1*[T] = ref H2[T] H*[T] = H1[T] + Pity[T] = object + a: T + PityRef*[T] = ref Pity[T] + Hope*[T] = ref object + a: T + type BAalias* = typeof(B.default) # typeof is not a transparent abstraction, creates a `tyAlias` diff --git a/tests/stdlib/t15663.nim b/tests/stdlib/t15663.nim index 1ad5677fd..8e8bfd9a8 100644 --- a/tests/stdlib/t15663.nim +++ b/tests/stdlib/t15663.nim @@ -3,5 +3,7 @@ discard """ output: "Test" """ +import std/widestrs + let ws = newWideCString("Test") -echo ws \ No newline at end of file +echo ws diff --git a/tests/stdlib/t19304.nim b/tests/stdlib/t19304.nim new file mode 100644 index 000000000..5e8795ac5 --- /dev/null +++ b/tests/stdlib/t19304.nim @@ -0,0 +1,7 @@ +import times + +type DjangoDateTime* = distinct DateTime + +# proc toTime*(x: DjangoDateTime): Time {.borrow.} # <-- works +proc format*(x: DjangoDateTime, f: TimeFormat, + loc: DateTimeLocale = DefaultLocale): string {.borrow.} diff --git a/tests/stdlib/t20023.nim b/tests/stdlib/t20023.nim new file mode 100644 index 000000000..8f12f8993 --- /dev/null +++ b/tests/stdlib/t20023.nim @@ -0,0 +1,10 @@ +import std/[tables, hashes, assertions] + + +let t = () +var a = toTable({t:t}) +del(a,t) +let b = default(typeof(a)) + +doAssert a==b , "tables are not equal" +doAssert hash(a) == hash(b), "table hashes are not equal" diff --git a/tests/stdlib/t21251.nim b/tests/stdlib/t21251.nim new file mode 100644 index 000000000..4402e9b7e --- /dev/null +++ b/tests/stdlib/t21251.nim @@ -0,0 +1,6 @@ +import std / [tables, sets, sharedtables] + +var shared: SharedTable[int, int] +shared.init + +shared[1] = 1 diff --git a/tests/stdlib/t21406.nim b/tests/stdlib/t21406.nim new file mode 100644 index 000000000..86bf7b0c7 --- /dev/null +++ b/tests/stdlib/t21406.nim @@ -0,0 +1,7 @@ +import std/[times, strformat] +import std/assertions + +let aTime = getTime() +doAssert fmt"{aTime}" == $aTime +let aNow = now() +doAssert fmt"{aNow}" == $aNow diff --git a/tests/stdlib/t21564.nim b/tests/stdlib/t21564.nim new file mode 100644 index 000000000..0a5777d12 --- /dev/null +++ b/tests/stdlib/t21564.nim @@ -0,0 +1,32 @@ +discard """ +targets: "c js" +""" + +import bitops +import std/assertions + +proc main() = + block: # bug #21564 + # tesk `bitops.bitsliced` patch + doAssert(0x17.bitsliced(4..7) == 0x01) + doAssert(0x17.bitsliced(0..3) == 0x07) + + block: + # test in-place `bitops.bitslice` + var t = 0x12F4 + t.bitslice(4..7) + + doAssert(t == 0xF) + + block: + # test `bitops.toMask` patch via bitops.masked + doAssert(0x12FFFF34.masked(8..23) == 0x00FFFF00) + + block: # bug #22687 + var a: uint8 = 0b1111_1111 + doAssert a.bitsliced(4..7).int == 15 + +main() + +static: + main() diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim index 83a84f956..e2024df0c 100644 --- a/tests/stdlib/talgorithm.nim +++ b/tests/stdlib/talgorithm.nim @@ -1,5 +1,6 @@ discard """ targets: "c js" + matrix: "--mm:refc; --mm:orc" output:'''@["3", "2", "1"] ''' """ diff --git a/tests/stdlib/tarithmetics.nim b/tests/stdlib/tarithmetics.nim index a69334e71..0a6dd1fcf 100644 --- a/tests/stdlib/tarithmetics.nim +++ b/tests/stdlib/tarithmetics.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import std/assertions diff --git a/tests/stdlib/tasynchttpserver.nim b/tests/stdlib/tasynchttpserver.nim index 8cf0d0ced..5a7e2da40 100644 --- a/tests/stdlib/tasynchttpserver.nim +++ b/tests/stdlib/tasynchttpserver.nim @@ -109,6 +109,7 @@ proc testCustomContentLength() {.async.} = doAssert(body == "") doAssert(response.headers.hasKey("Content-Length")) doAssert(response.headers["Content-Length"] == "0") + doAssert contentLength(response) == 0 # bug #22778 runTest(handler, request, test) diff --git a/tests/stdlib/tasynchttpserver_transferencoding.nim b/tests/stdlib/tasynchttpserver_transferencoding.nim index dae87be82..886ba0f33 100644 --- a/tests/stdlib/tasynchttpserver_transferencoding.nim +++ b/tests/stdlib/tasynchttpserver_transferencoding.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--gc:arc --threads:on; --gc:arc --threads:on -d:danger; --threads:on" + matrix: "--mm:arc; --mm:arc -d:danger; --mm:refc" disabled: "freebsd" """ diff --git a/tests/stdlib/tbase64.nim b/tests/stdlib/tbase64.nim index 60fa3865d..c3bfb818e 100644 --- a/tests/stdlib/tbase64.nim +++ b/tests/stdlib/tbase64.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/assertions @@ -17,6 +18,8 @@ template main() = doAssert encode("") == "" doAssert decode("") == "" + doAssert decode(" ") == "" + const testInputExpandsTo76 = "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++" const testInputExpands = "++++++++++++++++++++++++++++++" const longText = """Man is distinguished, not only by his reason, but by this @@ -52,5 +55,9 @@ template main() = doAssert encode("", safe = true) == "" doAssert encode("the quick brown dog jumps over the lazy fox", safe = true) == "dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA==" +func mainNoSideEffects() = main() + static: main() main() +static: mainNoSideEffects() +mainNoSideEffects() diff --git a/tests/stdlib/tbitops.nim b/tests/stdlib/tbitops.nim index c90943a93..3ecab2c64 100644 --- a/tests/stdlib/tbitops.nim +++ b/tests/stdlib/tbitops.nim @@ -1,5 +1,6 @@ discard """ nimout: "OK" + matrix: "--mm:refc; --mm:orc" output: ''' OK ''' diff --git a/tests/stdlib/tbitops_utils.nim b/tests/stdlib/tbitops_utils.nim index 7a64ea68d..e3f96fecc 100644 --- a/tests/stdlib/tbitops_utils.nim +++ b/tests/stdlib/tbitops_utils.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/private/bitops_utils import std/assertions diff --git a/tests/stdlib/tcasts.nim b/tests/stdlib/tcasts.nim new file mode 100644 index 000000000..e01c7e940 --- /dev/null +++ b/tests/stdlib/tcasts.nim @@ -0,0 +1,26 @@ +import std/[strutils] +import std/[assertions, objectdollar] + +# bug #19101 +type + Small = object + a: int + + Big = object + a, b, c, d: int + +proc main = + var + n = 1'i8 + f = 2.0 + s = Small(a: 1) + b = Big(a: 12345, b: 23456, c: 34567, d: 45678) + + doAssert $cast[int](f).toBin(64) == "0100000000000000000000000000000000000000000000000000000000000000" + f = cast[float](n) + doAssert $cast[int](f).toBin(64) == "0000000000000000000000000000000000000000000000000000000000000001" + + doAssert $b == "(a: 12345, b: 23456, c: 34567, d: 45678)" + b = cast[Big](s) + doAssert $b == "(a: 1, b: 0, c: 0, d: 0)" +main() diff --git a/tests/stdlib/tcgi.nim b/tests/stdlib/tcgi.nim index 7a52dc89b..ef39450da 100644 --- a/tests/stdlib/tcgi.nim +++ b/tests/stdlib/tcgi.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/unittest import std/[cgi, strtabs, sugar] import std/assertions diff --git a/tests/stdlib/tclosures.nim b/tests/stdlib/tclosures.nim new file mode 100644 index 000000000..84b033fa8 --- /dev/null +++ b/tests/stdlib/tclosures.nim @@ -0,0 +1,47 @@ +discard """ + targets: "c js" +""" + +import std/assertions + +block: # bug #4299 + proc scopeProc() = + proc normalProc() = + discard + + proc genericProc[T]() = + normalProc() + + genericProc[string]() + + scopeProc() + +block: # bug #12492 + proc foo() = + var i = 0 + proc bar() = + inc i + + bar() + doAssert i == 1 + + foo() + static: + foo() + +block: # bug #10849 + type + Generic[T] = ref object + getState: proc(): T + + proc newGeneric[T](): Generic[T] = + var state: T + + proc getState[T](): T = + state + + Generic[T](getState: getState) + + let g = newGeneric[int]() + let state = g.getState() + doAssert state == 0 diff --git a/tests/stdlib/tcmdline.nim b/tests/stdlib/tcmdline.nim index 5c0f71772..8b428900b 100644 --- a/tests/stdlib/tcmdline.nim +++ b/tests/stdlib/tcmdline.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" joinable: false """ diff --git a/tests/stdlib/tcomplex.nim b/tests/stdlib/tcomplex.nim index c7666be84..ca83314b9 100644 --- a/tests/stdlib/tcomplex.nim +++ b/tests/stdlib/tcomplex.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/[complex, math] import std/assertions @@ -80,6 +84,9 @@ let t = polar(a) doAssert(rect(t.r, t.phi) =~ a) doAssert(rect(1.0, 2.0) =~ complex(-0.4161468365471424, 0.9092974268256817)) +doAssert(almostEqual(a, a + complex(1e-16, 1e-16))) +doAssert(almostEqual(a, a + complex(2e-15, 2e-15), unitsInLastPlace = 5)) + let i64: Complex32 = complex(0.0f, 1.0f) diff --git a/tests/stdlib/tcookies.nim b/tests/stdlib/tcookies.nim index 4fe104dfc..3ff0f3bae 100644 --- a/tests/stdlib/tcookies.nim +++ b/tests/stdlib/tcookies.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tcritbits.nim b/tests/stdlib/tcritbits.nim index 0c2e1d6fa..e6282f045 100644 --- a/tests/stdlib/tcritbits.nim +++ b/tests/stdlib/tcritbits.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tcstrutils.nim b/tests/stdlib/tcstrutils.nim index ec2b8596c..e73b2b681 100644 --- a/tests/stdlib/tcstrutils.nim +++ b/tests/stdlib/tcstrutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ diff --git a/tests/stdlib/tdb.nim b/tests/stdlib/tdb.nim new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/stdlib/tdb.nim diff --git a/tests/stdlib/tdb.nims b/tests/stdlib/tdb.nims new file mode 100644 index 000000000..d31d0b26f --- /dev/null +++ b/tests/stdlib/tdb.nims @@ -0,0 +1 @@ +--styleCheck:off \ No newline at end of file diff --git a/tests/stdlib/tdb_mysql.nim b/tests/stdlib/tdb_mysql.nim index d97358e9f..e69de29bb 100644 --- a/tests/stdlib/tdb_mysql.nim +++ b/tests/stdlib/tdb_mysql.nim @@ -1,5 +0,0 @@ -import std/db_mysql -import std/assertions - -doAssert dbQuote("SELECT * FROM foo WHERE col1 = 'bar_baz'") == "'SELECT * FROM foo WHERE col1 = \\'bar_baz\\''" -doAssert dbQuote("SELECT * FROM foo WHERE col1 LIKE '%bar_baz%'") == "'SELECT * FROM foo WHERE col1 LIKE \\'%bar_baz%\\''" diff --git a/tests/stdlib/tdecls.nim b/tests/stdlib/tdecls.nim index 5cf352cfb..42dc646f2 100644 --- a/tests/stdlib/tdecls.nim +++ b/tests/stdlib/tdecls.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import std/assertions @@ -13,18 +14,18 @@ template fun() = var b {.byaddr.}: int = s[0] doAssert a.addr == b.addr - when false: - # template specific redeclaration issue - # see https://github.com/nim-lang/Nim/issues/8275 - doAssert not compiles(block: - # redeclaration not allowed - var foo = 0 - var foo {.byaddr.} = s[0]) - - doAssert not compiles(block: - # ditto - var foo {.byaddr.} = s[0] - var foo {.byaddr.} = s[0]) + {.push warningAsError[ImplicitTemplateRedefinition]: on.} + # in the future ImplicitTemplateRedefinition will be an error anyway + doAssert not compiles(block: + # redeclaration not allowed + var foo = 0 + var foo {.byaddr.} = s[0]) + + doAssert not compiles(block: + # ditto + var foo {.byaddr.} = s[0] + var foo {.byaddr.} = s[0]) + {.pop.} block: var b {.byaddr.} = s[1] # redeclaration ok in sub scope diff --git a/tests/stdlib/tdeques.nim b/tests/stdlib/tdeques.nim index 8a788d337..39ff996d1 100644 --- a/tests/stdlib/tdeques.nim +++ b/tests/stdlib/tdeques.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--gc:refc; --gc:orc" + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ @@ -183,6 +183,61 @@ proc main() = clear(a) doAssert len(a) == 0 + block: # bug #21278 + var a = [10, 20, 30, 40].toDeque + + a.shrink(fromFirst = 0, fromLast = 1) + doAssert $a == "[10, 20, 30]" + + block: + var a, b: Deque[int] + for i in 1 .. 256: + a.addLast(i) + for i in 1 .. 255: + a.popLast + b.addLast(1) + doAssert a == b + + block: + # Issue 23275 + # Test `==`. + block: + var a, b = initDeque[int]() + doAssert a == b + doAssert a.hash == b.hash + a.addFirst(1) + doAssert a != b + doAssert a.hash != b.hash + b.addLast(1) + doAssert a == b + doAssert a.hash == b.hash + a.popFirst + b.popLast + doAssert a == b + doAssert a.hash == b.hash + a.addLast 2 + doAssert a != b + doAssert a.hash != b.hash + b.addFirst 2 + doAssert a == b + doAssert a.hash == b.hash + + block: + var a, b = initDeque[int]() + for i in countDown(100, 1): + a.addFirst(i) + for i in 1..100: + b.addLast(i) + doAssert a == b + for i in 1..99: + a.popLast + let a1 = [1].toDeque + doAssert a == a1 + doAssert a.hash == a1.hash + var c = initDeque[int]() + c.addLast(1) + doAssert a == c + doAssert a.hash == c.hash static: main() main() diff --git a/tests/stdlib/tdiff.nim b/tests/stdlib/tdiff.nim index cb9cebb3a..132f7120b 100644 --- a/tests/stdlib/tdiff.nim +++ b/tests/stdlib/tdiff.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tdistros_detect.nim b/tests/stdlib/tdistros_detect.nim new file mode 100644 index 000000000..1176c8993 --- /dev/null +++ b/tests/stdlib/tdistros_detect.nim @@ -0,0 +1,16 @@ +import std/[assertions, distros] + +when defined(windows): + doAssert detectOs(Windows) == true + doAssert detectOs(Linux) == false + doAssert detectOs(MacOSX) == false + +when defined(linux): + doAssert detectOs(Linux) == true + doAssert detectOs(Windows) == false + doAssert detectOs(MacOSX) == false + +when defined(macosx): + doAssert detectOs(MacOSX) == true + doAssert detectOs(Windows) == false + doAssert detectOs(Linux) == false diff --git a/tests/stdlib/tdochelpers.nim b/tests/stdlib/tdochelpers.nim index 15d538891..4d532b5d0 100644 --- a/tests/stdlib/tdochelpers.nim +++ b/tests/stdlib/tdochelpers.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: ''' [Suite] Integration with Nim @@ -202,3 +203,19 @@ suite "Integration with Nim": name: "Copyflag") check inputRst.fromRst == expected check inputMd.fromMd == expected + + test "prefixed module": + let inputRst = "`module std / paths`_" + let inputMd = "[module std / paths]" + let expected = LangSymbol(symKind: "module", + name: "std/paths") + check inputRst.fromRst == expected + check inputMd.fromMd == expected + + test "postfixed module": + let inputRst = "`std / paths module`_" + let inputMd = "[std / paths module]" + let expected = LangSymbol(symKind: "module", + name: "std/paths") + check inputRst.fromRst == expected + check inputMd.fromMd == expected diff --git a/tests/stdlib/teditdistance.nim b/tests/stdlib/teditdistance.nim index b3b323647..14ba6df97 100644 --- a/tests/stdlib/teditdistance.nim +++ b/tests/stdlib/teditdistance.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/editdistance import std/assertions diff --git a/tests/stdlib/tencodings.nim b/tests/stdlib/tencodings.nim index 10d79f5d0..2f4daaba3 100644 --- a/tests/stdlib/tencodings.nim +++ b/tests/stdlib/tencodings.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/encodings import std/assertions @@ -97,3 +101,7 @@ block: doAssert orig == "\195\182\195\164\195\188\195\159" doAssert ibm850 == "\148\132\129\225" doAssert convert(ibm850, current, "ibm850") == orig + +block: # fixes about #23481 + doAssertRaises EncodingError: + discard open(destEncoding="this is a invalid enc") diff --git a/tests/stdlib/tenumerate.nim b/tests/stdlib/tenumerate.nim index b15b9e2db..2789ebe3a 100644 --- a/tests/stdlib/tenumerate.nim +++ b/tests/stdlib/tenumerate.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/enumerate import std/assertions diff --git a/tests/stdlib/tenumutils.nim b/tests/stdlib/tenumutils.nim index 63c563739..2662a660d 100644 --- a/tests/stdlib/tenumutils.nim +++ b/tests/stdlib/tenumutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ @@ -34,5 +35,15 @@ template main = doAssert $b == "kb0" static: doAssert B.high.symbolName == "b2" + block: + type + Color = enum + Red = "red", Yellow = "yellow", Blue = "blue" + + var s = Red + doAssert symbolName(s) == "Red" + var x: range[Red..Blue] = Yellow + doAssert symbolName(x) == "Yellow" + static: main() main() diff --git a/tests/stdlib/tenvvars.nim b/tests/stdlib/tenvvars.nim index 47c1ad24a..1a07f02b8 100644 --- a/tests/stdlib/tenvvars.nim +++ b/tests/stdlib/tenvvars.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" joinable: false targets: "c js cpp" """ @@ -7,7 +7,10 @@ discard """ import std/envvars from std/sequtils import toSeq import stdtest/testutils -import std/assertions +import std/[assertions] + +when not defined(js): + import std/typedthreads # "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386) const unicodeUtf8 = "\xc3\x86" @@ -46,9 +49,11 @@ template main = doAssert not existsEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE") doAssert not existsEnv("NIM_TESTS_TOSENV_PUT") +static: main() main() when defined(windows): + import std/widestrs proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".} proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".} @@ -68,7 +73,7 @@ when not defined(js) and not defined(nimscript): doAssertRaises(OSError): delEnv("foo=bar") -when defined(windows): +when defined(windows) and not defined(nimscript): import std/encodings proc c_putenv(env: cstring): int32 {.importc: "putenv", header: "<stdlib.h>".} diff --git a/tests/stdlib/texitprocs.nim b/tests/stdlib/texitprocs.nim index 9d5378fe8..ea29d8f58 100644 --- a/tests/stdlib/texitprocs.nim +++ b/tests/stdlib/texitprocs.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" targets: "c cpp js" output: ''' ok4 diff --git a/tests/stdlib/tfdleak.nim b/tests/stdlib/tfdleak.nim index 1ac746e48..272a7507c 100644 --- a/tests/stdlib/tfdleak.nim +++ b/tests/stdlib/tfdleak.nim @@ -1,7 +1,7 @@ discard """ exitcode: 0 output: "" - matrix: "; -d:nimInheritHandles" + matrix: "; -d:nimInheritHandles; --mm:refc" joinable: false """ diff --git a/tests/stdlib/tfilesanddirs.nim b/tests/stdlib/tfilesanddirs.nim new file mode 100644 index 000000000..a1920d4f2 --- /dev/null +++ b/tests/stdlib/tfilesanddirs.nim @@ -0,0 +1,36 @@ +import std/[paths, files, dirs, appdirs] + +from stdtest/specialpaths import buildDir +import std/[syncio, assertions] + +block fileOperations: + let files = @[Path"these.txt", Path"are.x", Path"testing.r", Path"files.q"] + let dirs = @[Path"some", Path"created", Path"test", Path"dirs"] + + let dname = Path"__really_obscure_dir_name" + + createDir(dname.Path) + doAssert dirExists(Path(dname)) + + # Test creating files and dirs + for dir in dirs: + createDir(Path(dname/dir)) + doAssert dirExists(Path(dname/dir)) + + for file in files: + let fh = open(string(dname/file), fmReadWrite) # createFile + fh.close() + doAssert fileExists(Path(dname/file)) + +block: # getCacheDir + doAssert getCacheDir().dirExists + +block: # moveFile + let tempDir = getTempDir() / Path("D20221022T151608") + createDir(tempDir) + defer: removeDir(tempDir) + +block: # moveDir + let tempDir = getTempDir() / Path("D20220609T161443") + createDir(tempDir) + defer: removeDir(tempDir) diff --git a/tests/stdlib/tfrexp1.nim b/tests/stdlib/tfrexp1.nim index 6b4c3b6d3..aa734ddac 100644 --- a/tests/stdlib/tfrexp1.nim +++ b/tests/stdlib/tfrexp1.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "js c cpp" """ diff --git a/tests/stdlib/tgetaddrinfo.nim b/tests/stdlib/tgetaddrinfo.nim index a8bcecb0c..3a90034c8 100644 --- a/tests/stdlib/tgetaddrinfo.nim +++ b/tests/stdlib/tgetaddrinfo.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" exitcode: 0 output: "" """ diff --git a/tests/stdlib/tgetfileinfo.nim b/tests/stdlib/tgetfileinfo.nim index 0f21622d0..ae1480a4c 100644 --- a/tests/stdlib/tgetfileinfo.nim +++ b/tests/stdlib/tgetfileinfo.nim @@ -1,10 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: "pcDir\npcFile\npcLinkToDir\npcLinkToFile\n" joinable: false """ import os, strutils -import std/syncio +import std/[syncio, assertions] # Cases # 1 - String : Existing File : Symlink true # 2 - String : Existing File : Symlink false @@ -127,10 +128,37 @@ proc testGetFileInfo = echo pcLinkToDir echo pcLinkToFile + doAssert dirInfo.isSpecial == false + doAssert fileInfo.isSpecial == false + when defined(posix): + doAssert linkDirInfo.isSpecial == false + doAssert linkFileInfo.isSpecial == false + removeDir(dirPath) removeFile(filePath) when defined(posix): removeFile(linkDirPath) removeFile(linkFilePath) + # Test that `isSpecial` is set correctly + block: + when defined(posix): + let + tmp = getTempDir() + fifoPath = tmp / "test-fifo" + linkFifoPath = tmp / "test-link-fifo" + + doAssert execShellCmd("mkfifo " & fifoPath) == 0 + createSymlink(fifoPath, linkFifoPath) + + let + fifoInfo = getFileInfo(fifoPath) + linkFifoInfo = getFileInfo(linkFifoPath) + + doAssert fifoInfo.isSpecial == true + doAssert linkFifoInfo.isSpecial == true + + removeFile(fifoPath) + removeFile(linkFifoPath) + testGetFileInfo() diff --git a/tests/stdlib/tgetprotobyname.nim b/tests/stdlib/tgetprotobyname.nim index e524510b2..1fc060ffe 100644 --- a/tests/stdlib/tgetprotobyname.nim +++ b/tests/stdlib/tgetprotobyname.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import nativesockets import std/assertions diff --git a/tests/stdlib/tglobs.nim b/tests/stdlib/tglobs.nim index 69ff31938..4aa21992c 100644 --- a/tests/stdlib/tglobs.nim +++ b/tests/stdlib/tglobs.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/private/globs import std/assertions diff --git a/tests/stdlib/thashes.nim b/tests/stdlib/thashes.nim index caae79213..4555fbcb3 100644 --- a/tests/stdlib/thashes.nim +++ b/tests/stdlib/thashes.nim @@ -1,5 +1,5 @@ discard """ - targets: "c cpp js" + matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:on; --backend:c -d:nimStringHash2; --backend:cpp -d:nimStringHash2; --backend:js -d:nimStringHash2" """ import std/hashes @@ -29,6 +29,10 @@ block hashes: const wy123 = hashWangYi1(123) doAssert wy123 != 0 doAssert hashWangYi1(123) == wy123 + const wyNeg123 = hashWangYi1(-123) + doAssert wyNeg123 != 0 + when not defined(js): # TODO: fixme it doesn't work for JS + doAssert hashWangYi1(-123) == wyNeg123 # "hashIdentity value incorrect at 456" @@ -42,20 +46,31 @@ block hashes: else: doAssert hashWangYi1(456) == -6421749900419628582 +template jsNoInt64: untyped = + when defined js: + when compiles(compileOption("jsbigint64")): + when not compileOption("jsbigint64"): true + else: false + else: false + else: false +const sHash2 = (when defined(nimStringHash2) or jsNoInt64(): true else: false) + block empty: + const emptyStrHash = # Hash=int=4B on js even w/--jsbigint64:on => cast[Hash] + when sHash2: 0 else: cast[Hash](-7286425919675154353i64) var a = "" b = newSeq[char]() c = newSeq[int]() d = cstring"" e = "abcd" - doAssert hash(a) == 0 - doAssert hash(b) == 0 + doAssert hash(a) == emptyStrHash + doAssert hash(b) == emptyStrHash doAssert hash(c) == 0 - doAssert hash(d) == 0 + doAssert hash(d) == emptyStrHash doAssert hashIgnoreCase(a) == 0 doAssert hashIgnoreStyle(a) == 0 - doAssert hash(e, 3, 2) == 0 + doAssert hash(e, 3, 2) == emptyStrHash block sameButDifferent: doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) @@ -89,7 +104,10 @@ block largeSize: # longer than 4 characters proc main() = doAssert hash(0.0) == hash(0) # bug #16061 - doAssert hash(cstring"abracadabra") == 97309975 + when not sHash2: # Hash=int=4B on js even w/--jsbigint64:on => cast[Hash] + doAssert hash(cstring"abracadabra") == cast[Hash](-1119910118870047694i64) + else: + doAssert hash(cstring"abracadabra") == 97309975 doAssert hash(cstring"abracadabra") == hash("abracadabra") when sizeof(int) == 8 or defined(js): diff --git a/tests/stdlib/theapqueue.nim b/tests/stdlib/theapqueue.nim index bb40b6f93..afb09c7e3 100644 --- a/tests/stdlib/theapqueue.nim +++ b/tests/stdlib/theapqueue.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/heapqueue import std/assertions diff --git a/tests/stdlib/thighlite.nim b/tests/stdlib/thighlite.nim index 5134215c1..0cd334254 100644 --- a/tests/stdlib/thighlite.nim +++ b/tests/stdlib/thighlite.nim @@ -1,6 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" import unittest, strutils import ../../lib/packages/docutils/highlite +import std/objectdollar block: # Nim tokenizing test "string literals and escape seq": @@ -30,3 +34,12 @@ block: # Cmd (shell) tokenizing ("file.nim", gtIdentifier), ("\n", gtWhitespace), ("out: file [SuccessX]", gtProgramOutput) ]) + +block: # bug #21232 + let code = "/" + var toknizr: GeneralTokenizer + + initGeneralTokenizer(toknizr, code) + + getNextToken(toknizr, langC) + check $toknizr == """(kind: gtOperator, start: 0, length: 1, buf: "/", pos: 1, state: gtEof, lang: langC)""" diff --git a/tests/stdlib/thtmlparser.nim b/tests/stdlib/thtmlparser.nim index a27d41fe6..853a1c0cc 100644 --- a/tests/stdlib/thtmlparser.nim +++ b/tests/stdlib/thtmlparser.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" output: ''' true diff --git a/tests/stdlib/thttpclient.nim b/tests/stdlib/thttpclient.nim index d2fec6eec..0bd479670 100644 --- a/tests/stdlib/thttpclient.nim +++ b/tests/stdlib/thttpclient.nim @@ -15,6 +15,7 @@ from net import TimeoutError import nativesockets, os, httpclient, asyncdispatch import std/[assertions, syncio] +from stdtest/testutils import enableRemoteNetworking const manualTests = false @@ -52,12 +53,13 @@ proc asyncTest() {.async.} = doAssert("<title>Example Domain</title>" in body) resp = await client.request("http://example.com/404") - doAssert(resp.code.is4xx) - doAssert(resp.code == Http404) - doAssert(resp.status == $Http404) + doAssert(resp.code.is4xx or resp.code.is5xx) + doAssert(resp.code == Http404 or resp.code == Http500) + doAssert(resp.status == $Http404 or resp.status == $Http500) - resp = await client.request("https://google.com/") - doAssert(resp.code.is2xx or resp.code.is3xx) + when false: # occasionally does not give success code + resp = await client.request("https://google.com/") + doAssert(resp.code.is2xx or resp.code.is3xx) # getContent try: @@ -113,12 +115,13 @@ proc syncTest() = doAssert("<title>Example Domain</title>" in resp.body) resp = client.request("http://example.com/404") - doAssert(resp.code.is4xx) - doAssert(resp.code == Http404) - doAssert(resp.status == $Http404) + doAssert(resp.code.is4xx or resp.code.is5xx) + doAssert(resp.code == Http404 or resp.code == Http500) + doAssert(resp.status == $Http404 or resp.status == $Http500) - resp = client.request("https://google.com/") - doAssert(resp.code.is2xx or resp.code.is3xx) + when false: # occasionally does not give success code + resp = client.request("https://google.com/") + doAssert(resp.code.is2xx or resp.code.is3xx) # getContent try: @@ -178,5 +181,7 @@ proc ipv6Test() = client.close() ipv6Test() -syncTest() -waitFor(asyncTest()) + +when enableRemoteNetworking: + syncTest() + waitFor(asyncTest()) diff --git a/tests/stdlib/thttpclient_ssl.nim b/tests/stdlib/thttpclient_ssl.nim index feacd3e57..6b963f029 100644 --- a/tests/stdlib/thttpclient_ssl.nim +++ b/tests/stdlib/thttpclient_ssl.nim @@ -13,7 +13,10 @@ discard """ ## Test with: ## ./bin/nim c -d:ssl -p:. --threads:on -r tests/stdlib/thttpclient_ssl.nim -when not defined(windows): + +from stdtest/testutils import disableSSLTesting + +when not defined(windows) and not disableSSLTesting(): # Disabled on Windows due to old OpenSSL version import std/[formatfloat, syncio] import diff --git a/tests/stdlib/thttpcore.nim b/tests/stdlib/thttpcore.nim index 3b6b1efa0..93e7d85c6 100644 --- a/tests/stdlib/thttpcore.nim +++ b/tests/stdlib/thttpcore.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import httpcore, strutils import std/assertions diff --git a/tests/stdlib/timportutils.nim b/tests/stdlib/timportutils.nim index be912e702..672092282 100644 --- a/tests/stdlib/timportutils.nim +++ b/tests/stdlib/timportutils.nim @@ -1,4 +1,8 @@ -import std/importutils +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/[importutils, assertions] import stdtest/testutils import mimportutils @@ -134,5 +138,14 @@ template main = privateAccess PtA a.ha1 == 0 + block: + privateAccess PityRef + let x = PityRef[int](a: 1) # works + doAssert x.a == 1 + + privateAccess Hope + let y = Hope[int](a: 1) + doAssert y.a == 1 + static: main() main() diff --git a/tests/stdlib/tio.nim b/tests/stdlib/tio.nim index 0e20d6495..80a119763 100644 --- a/tests/stdlib/tio.nim +++ b/tests/stdlib/tio.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + # xxx move to here other tests that belong here; io is a proper module import std/os @@ -36,3 +40,21 @@ block: # readChars break doAssert n2s == @[2,2,2,1,0] doAssert s2 == s + + +import std/strutils + +block: # bug #21273 + let FILE = buildDir / "D20220119T134305.txt" + + let hex = "313632313920313632343720313632353920313632363020313632393020323035363520323037323120323131353020323239393820323331303520323332313020323332343820323332363820" + + + writeFile FILE, parseHexStr(hex) + + doAssert readFile(FILE).toHex == hex + + let f = open(FILE) + var s = newString(80) + while f.readLine(s): + doAssert s.toHex == hex diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim index a60d45aab..e425501f6 100644 --- a/tests/stdlib/tjson.nim +++ b/tests/stdlib/tjson.nim @@ -1,6 +1,5 @@ discard """ - matrix: "--mm:refc" - targets: "c cpp js" + matrix: "; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ @@ -9,6 +8,7 @@ Note: Macro tests are in tests/stdlib/tjsonmacro.nim ]# import std/[json,parsejson,strutils] +import std/private/jsutils from std/math import isNaN when not defined(js): import std/streams @@ -51,7 +51,7 @@ for i in 0 .. 10000: except: discard # memory diff should less than 4M -doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024) # todo fixme doesn;t work for ORC +doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024) # test `$` @@ -314,7 +314,8 @@ block: # bug #17383 else: testRoundtrip(int.high): "9223372036854775807" testRoundtrip(uint.high): "18446744073709551615" - when not defined(js): + whenJsNoBigInt64: discard + do: testRoundtrip(int64.high): "9223372036854775807" testRoundtrip(uint64.high): "18446744073709551615" diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index 9c1fa833d..5a1b4b294 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -1,5 +1,6 @@ discard """ output: "" + matrix: "--mm:refc; --mm:orc" targets: "c js" """ @@ -436,11 +437,7 @@ proc testJson() = block: let s = """{"a": 1, "b": 2}""" let t = parseJson(s).to(Table[string, int]) - when not defined(js): - # For some reason on the JS backend `{"b": 2, "a": 0}` is - # sometimes the value of `t`. This needs investigation. I can't - # reproduce it right now in an isolated test. - doAssert t["a"] == 1 + doAssert t["a"] == 1 doAssert t["b"] == 2 block: diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim index 54cb69560..9acf4c9e5 100644 --- a/tests/stdlib/tjsonutils.nim +++ b/tests/stdlib/tjsonutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ @@ -60,8 +61,7 @@ template fn() = testRoundtrip(pointer(nil)): """0""" testRoundtrip(cast[pointer](nil)): """0""" - # causes workaround in `fromJson` potentially related to - # https://github.com/nim-lang/Nim/issues/12282 + # refs bug #9423 testRoundtrip(Foo(1.5)): """1.5""" block: # OrderedTable @@ -410,6 +410,39 @@ template fn() = doAssert foo.c == 0 doAssert foo.c0 == 42 + + block testInvalidTupleLength: + let json = parseJson("[0]") + # Should raise ValueError instead of index error + doAssertRaises(ValueError): + discard json.jsonTo((int, int)) + + type + InnerEnum = enum + A + B + C + InnerObject = object + x: string + y: InnerEnum + + block testOptionsArePassedWhenDeserialising: + let json = parseJson("""{"x": "hello"}""") + let inner = json.jsonTo(Option[InnerObject], Joptions(allowMissingKeys: true)) + doAssert inner.isSome() + doAssert inner.get().x == "hello" + doAssert inner.get().y == A + + block testOptionsArePassedWhenSerialising: + let inner = some InnerObject(x: "hello", y: A) + let json = inner.toJson(ToJsonOptions(enumMode: joptEnumSymbol)) + doAssert $json == """{"x":"hello","y":"A"}""" + + block: # bug #21638 + type Something = object + + doAssert "{}".parseJson.jsonTo(Something) == Something() + when false: ## TODO: Implement support for nested variant objects allowing the tests ## bellow to pass. diff --git a/tests/stdlib/tlists.nim b/tests/stdlib/tlists.nim index 701fb7974..5993278c7 100644 --- a/tests/stdlib/tlists.nim +++ b/tests/stdlib/tlists.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tlocks.nim b/tests/stdlib/tlocks.nim index 9ce9afd13..1c5f67119 100644 --- a/tests/stdlib/tlocks.nim +++ b/tests/stdlib/tlocks.nim @@ -1,6 +1,6 @@ discard """ targets: "c cpp js" - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" """ #bug #6049 diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim index 7ec2fed9f..06a9a9c27 100644 --- a/tests/stdlib/tmacros.nim +++ b/tests/stdlib/tmacros.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + #[ xxx macros tests need to be reorganized to makes sure each API is tested once See also: @@ -157,3 +161,189 @@ block: # bug #19020 static: doAssert $bar.getCustomPragmaVal(typ) == "foo" doAssert $bar.getCustomPragmaVal(typ) == "foo" + +block hasCustomPragmaGeneric: + template examplePragma() {.pragma.} + type + Foo[T] {.examplePragma.} = object + x {.examplePragma.}: T + var f: Foo[string] + doAssert f.hasCustomPragma(examplePragma) + doAssert f.x.hasCustomPragma(examplePragma) + +block getCustomPragmaValGeneric: + template examplePragma(x: int) {.pragma.} + type + Foo[T] {.examplePragma(42).} = object + x {.examplePragma(25).}: T + var f: Foo[string] + doAssert f.getCustomPragmaVal(examplePragma) == 42 + doAssert f.x.getCustomPragmaVal(examplePragma) == 25 + +block: # bug #21326 + macro foo(body: untyped): untyped = + let a = body.lineInfoObj() + let aLit = a.newLit + result = quote do: + doAssert $`a` == $`aLit` + + foo: + let c = 1 + + template name(a: LineInfo): untyped = + discard a # `aLit` works though + + macro foo3(body: untyped): untyped = + let a = body.lineInfoObj() + # let ax = newLit(a) + result = getAst(name(a)) + + foo3: + let c = 1 + +block: # bug #7375 + macro fails(b: static[bool]): untyped = + doAssert b == false + result = newStmtList() + + macro foo(): untyped = + + var b = false + + ## Fails + result = quote do: + fails(`b`) + + foo() + + macro someMacro(): untyped = + template tmpl(boolean: bool) = + when boolean: + discard "it's true!" + else: + doAssert false + result = getAst(tmpl(true)) + + someMacro() + +block: + macro foo(): untyped = + result = quote do: `littleEndian` + + doAssert littleEndian == foo() + +block: + macro eqSym(x, y: untyped): untyped = + let eq = $x == $y # Unfortunately eqIdent compares to string. + result = quote do: `eq` + + var r, a, b: int + + template fma(result: var int, a, b: int, op: untyped) = + # fused multiple-add + when eqSym(op, `+=`): + discard "+=" + else: + discard "+" + + fma(r, a, b, `+=`) + +block: + template test(boolArg: bool) = + static: + doAssert typeof(boolArg) is bool + let x: bool = boolArg # compile error here, because boolArg became an int + + macro testWrapped1(boolArg: bool): untyped = + # forwarding boolArg directly works + result = getAst(test(boolArg)) + + macro testWrapped2(boolArg: bool): untyped = + # forwarding boolArg via a local variable also works + let b = boolArg + result = getAst(test(b)) + + macro testWrapped3(boolArg: bool): untyped = + # but using a literal `true` as a local variable will be converted to int + let b = true + result = getAst(test(b)) + + test(true) # ok + testWrapped1(true) # ok + testWrapped2(true) # ok + testWrapped3(true) + +block: + macro foo(): untyped = + var s = { 'a', 'b' } + quote do: + let t = `s` + doAssert $typeof(t) == "set[char]" + + foo() + +block: # bug #9607 + proc fun1(info:LineInfo): string = "bar" + proc fun2(info:int): string = "bar" + + macro echoL(args: varargs[untyped]): untyped = + let info = args.lineInfoObj + let fun1 = bindSym"fun1" + let fun2 = bindSym"fun2" + + # this would work instead + # result = newCall(bindSym"fun2", info.line.newLit) + + result = quote do: + + # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil + `fun1`(`info`) + + macro echoM(args: varargs[untyped]): untyped = + let info = args.lineInfoObj + let fun1 = bindSym"fun1" + let fun2 = bindSym"fun2" + + # this would work instead + # result = newCall(bindSym"fun2", info.line.newLit) + + result = quote do: + + # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil + `fun2`(`info`.line) + + + doAssert echoL() == "bar" + doAssert echoM() == "bar" + +block: + macro hello[T](x: T): untyped = + result = quote do: + let m: `T` = `x` + discard m + + hello(12) + +block: + proc hello(x: int, y: typedesc) = + discard + + macro main = + let x = 12 + result = quote do: + `hello`(12, type(x)) + + main() + +block: # bug #22947 + macro bar[N: static int](a: var array[N, int]) = + result = quote do: + for i in 0 ..< `N`: + `a`[i] = i + + func foo[N: static int](a: var array[N, int]) = + bar(a) + + + var a: array[4, int] + foo(a) diff --git a/tests/stdlib/tmarshal.nim b/tests/stdlib/tmarshal.nim index f972332a2..32991ccc9 100644 --- a/tests/stdlib/tmarshal.nim +++ b/tests/stdlib/tmarshal.nim @@ -3,7 +3,7 @@ discard """ """ import std/marshal -import std/[assertions, objectdollar] +import std/[assertions, objectdollar, streams] # TODO: add static tests @@ -166,6 +166,46 @@ block: let a: ref A = new(B) doAssert $$a[] == "{}" # not "{f: 0}" +# bug #16496 +block: + type + A = ref object + data: seq[int] + + B = ref object + x: A + let o = A(data: @[1, 2, 3, 4]) + let s1 = @[B(x: o), B(x: o)] + let m = $$ s1 + let s2 = to[seq[B]](m) + doAssert s2[0].x.data == s2[1].x.data + doAssert s1[0].x.data == s2[1].x.data + + +block: + type + Obj = ref object + i: int + b: bool + + let + strm = newStringStream() + + var + o = Obj(i: 1, b: false) + t1 = @[o, o] + t2: seq[Obj] + + doAssert t1[0] == t1[1] + + strm.store(t1) + strm.setPosition(0) + strm.load(t2) + strm.close() + + doAssert t2[0] == t2[1] + + template checkMarshal(data: typed) = let orig = data let m = $$orig diff --git a/tests/stdlib/tmarshalsegfault.nim b/tests/stdlib/tmarshalsegfault.nim new file mode 100644 index 000000000..71f2766c8 --- /dev/null +++ b/tests/stdlib/tmarshalsegfault.nim @@ -0,0 +1,54 @@ +# issue #12405 + +import std/[marshal, streams, times, tables, os, assertions] + +type AiredEpisodeState * = ref object + airedAt * : DateTime + tvShowId * : string + seasonNumber * : int + number * : int + title * : string + +type ShowsWatchlistState * = ref object + aired * : seq[AiredEpisodeState] + +type UiState * = ref object + shows: ShowsWatchlistState + +# Helpers to marshal and unmarshal +proc load * ( state : var UiState, file : string ) = + var strm = newFileStream( file, fmRead ) + + strm.load( state ) + + strm.close() + +proc store * ( state : UiState, file : string ) = + var strm = newFileStream( file, fmWrite ) + + strm.store( state ) + + strm.close() + +# 1. We fill the state initially +var state : UiState = UiState( shows: ShowsWatchlistState( aired: @[] ) ) + +# VERY IMPORTANT: For some reason, small numbers (like 2 or 3) don't trigger the bug. Anything above 7 or 8 on my machine triggers though +for i in 0..30: + var episode = AiredEpisodeState( airedAt: now(), tvShowId: "1", seasonNumber: 1, number: 1, title: "string" ) + + state.shows.aired.add( episode ) + +# 2. Store it in a file with the marshal module, and then load it back up +store( state, "tmarshalsegfault_data" ) +load( state, "tmarshalsegfault_data" ) +removeFile("tmarshalsegfault_data") + +# 3. VERY IMPORTANT: Without this line, for some reason, everything works fine +state.shows.aired[ 0 ] = AiredEpisodeState( airedAt: now(), tvShowId: "1", seasonNumber: 1, number: 1, title: "string" ) + +# 4. And formatting the airedAt date will now trigger the exception +for ep in state.shows.aired: + let x = $ep.seasonNumber & "x" & $ep.number & " (" & $ep.airedAt & ")" + let y = $ep.seasonNumber & "x" & $ep.number & " (" & $ep.airedAt & ")" + doAssert x == y diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 66c1f8ca0..22e5f7d88 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -1,6 +1,6 @@ discard """ targets: "c cpp js" - matrix:"; -d:danger" + matrix:"; -d:danger; --mm:refc" """ # xxx: there should be a test with `-d:nimTmathCase2 -d:danger --passc:-ffast-math`, @@ -186,7 +186,22 @@ template main() = when not defined(nimTmathCase2): doAssert classify(trunc(f_nan.float32)) == fcNan doAssert classify(trunc(0.0'f32)) == fcZero - + + block: # divmod + doAssert divmod(int.high, 1) == (int.high, 0) + doAssert divmod(-1073741823, 17) == (-63161283, -12) + doAssert divmod(int32.high, 1.int32) == (int32.high, 0.int32) + doAssert divmod(1073741823.int32, 5.int32) == (214748364.int32, 3.int32) + doAssert divmod(4611686018427387903.int64, 5.int64) == (922337203685477580.int64, 3.int64) + when not defined(js) and (not compileOption("panics")) and compileOption("overflowChecks"): + when nimvm: + discard # cannot catch OverflowDefect here + else: + doAssertRaises(OverflowDefect, (discard divmod(cint.low, -1.cint))) + doAssertRaises(OverflowDefect, (discard divmod(clong.low, -1.clong))) + doAssertRaises(OverflowDefect, (discard divmod(clonglong.low, -1.clonglong))) + doAssertRaises(DivByZeroDefect, (discard divmod(1, 0))) + block: # log doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0) doAssert log2(8.0'f64) == 3.0'f64 @@ -439,6 +454,20 @@ template main() = doAssert lgamma(-0.0) == Inf doAssert lgamma(-1.0) == Inf - static: main() main() + +when not defined(js) and not defined(danger): + block: # bug #21792 + block: + type Digit = 0..9 + var x = [Digit 4, 7] + + doAssertRaises(RangeDefect): + discard sum(x) + + block: + var x = [int8 124, 127] + + doAssertRaises(OverflowDefect): + discard sum(x) diff --git a/tests/stdlib/tmd5.nim b/tests/stdlib/tmd5.nim deleted file mode 100644 index 254eefea9..000000000 --- a/tests/stdlib/tmd5.nim +++ /dev/null @@ -1,17 +0,0 @@ -discard """ - targets: "c cpp js" -""" - -import md5 -import std/assertions - -proc main() {.raises: [].} = - doAssert(getMD5("Franz jagt im komplett verwahrlosten Taxi quer durch Bayern") == - "a3cca2b2aa1e3b5b3b5aad99a8529074") - doAssert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") == - "7e716d0e702df0505fc72e2b89467910") - doAssert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e") - -main() - -static: main() diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim index 6fee3c1ae..c79f85ebf 100644 --- a/tests/stdlib/tmemfiles2.nim +++ b/tests/stdlib/tmemfiles2.nim @@ -15,8 +15,9 @@ var if fileExists(fn): removeFile(fn) -# Create a new file, data all zeros -mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20) +# Create a new file, data all zeros, starting at size 10 +mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 10, allowRemap=true) +mm.resize 20 # resize up to 20 mm.close() # read, change diff --git a/tests/stdlib/tmemory.nim b/tests/stdlib/tmemory.nim deleted file mode 100644 index 553037011..000000000 --- a/tests/stdlib/tmemory.nim +++ /dev/null @@ -1,16 +0,0 @@ -import std/assertions - -block: # cmpMem - type - SomeHash = array[15, byte] - - var - a: SomeHash - b: SomeHash - - a[^1] = byte(1) - let c = a - - doAssert cmpMem(a.addr, b.addr, sizeof(SomeHash)) > 0 - doAssert cmpMem(b.addr, a.addr, sizeof(SomeHash)) < 0 - doAssert cmpMem(a.addr, c.addr, sizeof(SomeHash)) == 0 diff --git a/tests/stdlib/tmget.nim b/tests/stdlib/tmget.nim index 52e61fd24..f41963f02 100644 --- a/tests/stdlib/tmget.nim +++ b/tests/stdlib/tmget.nim @@ -1,16 +1,21 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''Can't access 6 10 11 +2 Can't access 6 10 11 +2 Can't access 6 10 11 +2 Can't access 6 10 11 +2 0 10 11 @@ -40,6 +45,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = newTable[int, int]() @@ -52,6 +60,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = initOrderedTable[int, int]() @@ -64,6 +75,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = newOrderedTable[int, int]() @@ -76,6 +90,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = initCountTable[int]() diff --git a/tests/stdlib/tmimetypes.nim b/tests/stdlib/tmimetypes.nim index 8263e37fd..fd66ebd97 100644 --- a/tests/stdlib/tmimetypes.nim +++ b/tests/stdlib/tmimetypes.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ @@ -10,10 +11,18 @@ template main() = var m = newMimetypes() doAssert m.getMimetype("mp4") == "video/mp4" doAssert m.getExt("application/json") == "json" + doAssert m.getMimetype("json") == "application/json" m.register("foo", "baa") doAssert m.getMimetype("foo") == "baa" + doAssert m.getMimetype("txt") == "text/plain" + doAssert m.getExt("text/plain") == "txt" # see also `runnableExamples`. # xxx we should have a way to avoid duplicating code between runnableExamples and tests + doAssert m.getMimetype("nim") == "text/nim" + doAssert m.getMimetype("nimble") == "text/nimble" + doAssert m.getMimetype("nimf") == "text/nim" + doAssert m.getMimetype("nims") == "text/nim" + static: main() main() diff --git a/tests/stdlib/tmisc_issues.nim b/tests/stdlib/tmisc_issues.nim index b5a02e614..86dcf4162 100644 --- a/tests/stdlib/tmisc_issues.nim +++ b/tests/stdlib/tmisc_issues.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ @@ -17,3 +18,22 @@ type var x: Object = Object(data: Test(Data(id: 12))) doAssert Data(x.data).id == 12 + +block: # bug #16771 + type A = object + n: int + + proc foo(a, b: var A) = + swap a, b + + var a, b: A + a.n = 42 + b.n = 1 + doAssert a.n == 42 + doAssert b.n == 1 + a.swap b + doAssert a.n == 1 + doAssert b.n == 42 + a.foo b + doAssert a.n == 42 + doAssert b.n == 1 diff --git a/tests/stdlib/tmitems.nim b/tests/stdlib/tmitems.nim index 171604e33..cc515a175 100644 --- a/tests/stdlib/tmitems.nim +++ b/tests/stdlib/tmitems.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''@[11, 12, 13] @[11, 12, 13] @[1, 3, 5] diff --git a/tests/stdlib/tmonotimes.nim b/tests/stdlib/tmonotimes.nim index f10fef591..1366dbfe9 100644 --- a/tests/stdlib/tmonotimes.nim +++ b/tests/stdlib/tmonotimes.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tnativesockets.nim b/tests/stdlib/tnativesockets.nim index b1bbf32c2..8242beb83 100644 --- a/tests/stdlib/tnativesockets.nim +++ b/tests/stdlib/tnativesockets.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/nativesockets import stdtest/testutils import std/assertions diff --git a/tests/stdlib/tnet.nim b/tests/stdlib/tnet.nim index 06ff44c3d..27a6ac49c 100644 --- a/tests/stdlib/tnet.nim +++ b/tests/stdlib/tnet.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" outputsub: "" """ diff --git a/tests/stdlib/tnet_ll.nim b/tests/stdlib/tnet_ll.nim index 2d340cea8..199946482 100644 --- a/tests/stdlib/tnet_ll.nim +++ b/tests/stdlib/tnet_ll.nim @@ -1,5 +1,6 @@ discard """ action: run + matrix: "--mm:refc; --mm:orc" output: ''' [Suite] inet_ntop tests @@ -29,7 +30,7 @@ suite "inet_ntop tests": check: ip4.s_addr == 0x10111213'u32 var buff: array[0..255, char] - let r = inet_ntop(AF_INET, cast[pointer](ip4.s_addr.addr), buff[0].addr, buff.len.int32) + let r = inet_ntop(AF_INET, cast[pointer](ip4.s_addr.addr), cast[cstring](buff[0].addr), buff.len.int32) let res = if r == nil: "" else: $r check: res == "19.18.17.16" @@ -41,7 +42,7 @@ suite "inet_ntop tests": var ip6 = [0x1000'u16, 0x1001, 0x2000, 0x2001, 0x3000, 0x3001, 0x4000, 0x4001] var buff: array[0..255, char] - let r = inet_ntop(AF_INET6, cast[pointer](ip6[0].addr), buff[0].addr, buff.len.int32) + let r = inet_ntop(AF_INET6, cast[pointer](ip6[0].addr), cast[cstring](buff[0].addr), buff.len.int32) let res = if r == nil: "" else: $r check: not ipv6Support or res == "10:110:20:120:30:130:40:140" diff --git a/tests/stdlib/tnetbind.nim b/tests/stdlib/tnetbind.nim index 734b6c5e7..84f9ac464 100644 --- a/tests/stdlib/tnetbind.nim +++ b/tests/stdlib/tnetbind.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" joinable: false """ diff --git a/tests/stdlib/tnetconnect.nim b/tests/stdlib/tnetconnect.nim index 3a80df19f..ae654aed9 100644 --- a/tests/stdlib/tnetconnect.nim +++ b/tests/stdlib/tnetconnect.nim @@ -1,9 +1,11 @@ discard """ + disabled: "i386" matrix: "-d:ssl" """ import std/net from std/strutils import `%` +from stdtest/testutils import enableRemoteNetworking # bug #15215 proc test() = @@ -24,4 +26,5 @@ proc test() = except TimeoutError, OSError: fn("www.google.com") -test() +when enableRemoteNetworking: + test() diff --git a/tests/stdlib/tnetdial.nim b/tests/stdlib/tnetdial.nim index 3b8276d6f..a1e147ad5 100644 --- a/tests/stdlib/tnetdial.nim +++ b/tests/stdlib/tnetdial.nim @@ -5,7 +5,7 @@ discard """ """ import os, net, nativesockets, asyncdispatch -import std/[assertions] +import std/[assertions, typedthreads] ## Test for net.dial diff --git a/tests/stdlib/tnre.nim b/tests/stdlib/tnre.nim index f13c16052..3b40e9e83 100644 --- a/tests/stdlib/tnre.nim +++ b/tests/stdlib/tnre.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" # Since the tests for nre are all bundled together we treat failure in one test as an nre failure # When running 'testament/tester' a failed check() in the test suite will cause the exit # codes to differ and be reported as a failure diff --git a/tests/stdlib/tntpath.nim b/tests/stdlib/tntpath.nim index dce0cf6f8..8efdd6bd0 100644 --- a/tests/stdlib/tntpath.nim +++ b/tests/stdlib/tntpath.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/private/ntpath import std/assertions diff --git a/tests/stdlib/toids.nim b/tests/stdlib/toids.nim index 95161415d..dd5b84c51 100644 --- a/tests/stdlib/toids.nim +++ b/tests/stdlib/toids.nim @@ -7,7 +7,7 @@ import std/assertions block: # genOid let x = genOid() - doAssert ($x).len == 32 + doAssert ($x).len == 24 block: let x = genOid() diff --git a/tests/stdlib/topenssl.nim b/tests/stdlib/topenssl.nim index 3209437de..af259627f 100644 --- a/tests/stdlib/topenssl.nim +++ b/tests/stdlib/topenssl.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/wordwrap import openssl import std/assertions diff --git a/tests/stdlib/toptions.nim b/tests/stdlib/toptions.nim index 6065425b9..63a10e746 100644 --- a/tests/stdlib/toptions.nim +++ b/tests/stdlib/toptions.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ @@ -195,6 +196,12 @@ proc main() = doAssert x.isNone doAssert $x == "none(cstring)" - static: main() main() + +when not defined(js): + block: # bug #22932 + var it = iterator: int {.closure.} = discard + doAssert it.option.isSome # Passes. + it = nil + doAssert it.option.isNone # Passes. diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index bd91a3de9..611659fdb 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -22,13 +22,13 @@ __really_obscure_dir_name/test Raises Raises ''' + matrix: "--mm:refc; --mm:orc" joinable: false """ # test os path creation, iteration, and deletion -import os, strutils, pathnorm from stdtest/specialpaths import buildDir -import std/[syncio, assertions] +import std/[syncio, assertions, osproc, os, strutils, pathnorm] block fileOperations: let files = @["these.txt", "are.x", "testing.r", "files.q"] @@ -160,6 +160,18 @@ block fileOperations: # createDir should not fail if `dir` is empty createDir("") + + when defined(linux): # bug #24174 + createDir("a/b") + open("a/file.txt", fmWrite).close + + if not fileExists("a/fifoFile"): + doAssert execCmd("mkfifo -m 600 a/fifoFile") == 0 + + copyDir("a/", "../dest/a/", skipSpecial = true) + copyDirWithPermissions("a/", "../dest2/a/", skipSpecial = true) + removeDir("a") + # Symlink handling in `copyFile`, `copyFileWithPermissions`, `copyFileToDir`, # `copyDir`, `copyDirWithPermissions`, `moveFile`, and `moveDir`. block: @@ -344,6 +356,8 @@ block walkDirRec: removeDir("walkdir_test") +import std/sequtils + block: # walkDir doAssertRaises(OSError): for a in walkDir("nonexistent", checkDir = true): discard @@ -358,6 +372,21 @@ block: # walkDir doAssert k == pcLinkToDir removeDir("walkdir_test") + when defined(posix): + block walkDirSpecial: + createDir("walkdir_test") + doAssert execShellCmd("mkfifo walkdir_test/fifo") == 0 + createSymlink("fifo", "walkdir_test/fifo_link") + let withSpecialFiles = toSeq(walkDir("walkdir_test", relative = true)) + doAssert (withSpecialFiles.len == 2 and + (pcFile, "fifo") in withSpecialFiles and + (pcLinkToFile, "fifo_link") in withSpecialFiles) + # now Unix special files are excluded from walkdir output: + let skipSpecialFiles = toSeq(walkDir("walkdir_test", relative = true, + skipSpecial = true)) + doAssert skipSpecialFiles.len == 0 + removeDir("walkdir_test") + block normalizedPath: doAssert normalizedPath("") == "" block relative: @@ -672,32 +701,6 @@ block: # normalizePathEnd doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\" doAssert "/".normalizePathEnd == r"\" -block: # isValidFilename - # Negative Tests. - doAssert not isValidFilename("abcd", maxLen = 2) - doAssert not isValidFilename("0123456789", maxLen = 8) - doAssert not isValidFilename("con") - doAssert not isValidFilename("aux") - doAssert not isValidFilename("prn") - doAssert not isValidFilename("OwO|UwU") - doAssert not isValidFilename(" foo") - doAssert not isValidFilename("foo ") - doAssert not isValidFilename("foo.") - doAssert not isValidFilename("con.txt") - doAssert not isValidFilename("aux.bat") - doAssert not isValidFilename("prn.exe") - doAssert not isValidFilename("nim>.nim") - doAssert not isValidFilename(" foo.log") - # Positive Tests. - doAssert isValidFilename("abcd", maxLen = 42.Positive) - doAssert isValidFilename("c0n") - doAssert isValidFilename("foo.aux") - doAssert isValidFilename("bar.prn") - doAssert isValidFilename("OwO_UwU") - doAssert isValidFilename("cron") - doAssert isValidFilename("ux.bat") - doAssert isValidFilename("nim.nim") - doAssert isValidFilename("foo.log") import sugar @@ -716,7 +719,23 @@ block: # isAdmin # In Azure on POSIX tests run as a normal user if isAzure and defined(posix): doAssert not isAdmin() -import std/sequtils + +import sugar + +block: # normalizeExe + doAssert "".dup(normalizeExe) == "" + when defined(posix): + doAssert "foo".dup(normalizeExe) == "./foo" + doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar" + when defined(windows): + doAssert "foo".dup(normalizeExe) == "foo" + +block: # isAdmin + let isAzure = existsEnv("TF_BUILD") # xxx factor with testament.specs.isAzure + # In Azure on Windows tests run as an admin user + if isAzure and defined(windows): doAssert isAdmin() + # In Azure on POSIX tests run as a normal user + if isAzure and defined(posix): doAssert not isAdmin() when doslikeFileSystem: import std/private/ntpath @@ -793,3 +812,64 @@ else: doAssert parentDirs("/home/user", fromRoot=false).toSeq == @["/home/user", "/home", "/"] doAssert parentDirs("home/user", fromRoot=true).toSeq == @["home/", "home/user"] doAssert parentDirs("home/user", fromRoot=false).toSeq == @["home/user", "home"] + + +# https://github.com/nim-lang/Nim/pull/19643#issuecomment-1235102314 +block: # isValidFilename + # Negative Tests. + doAssert not isValidFilename("abcd", maxLen = 2) + doAssert not isValidFilename("0123456789", maxLen = 8) + doAssert not isValidFilename("con") + doAssert not isValidFilename("aux") + doAssert not isValidFilename("prn") + doAssert not isValidFilename("OwO|UwU") + doAssert not isValidFilename(" foo") + doAssert not isValidFilename("foo ") + doAssert not isValidFilename("foo.") + doAssert not isValidFilename("con.txt") + doAssert not isValidFilename("aux.bat") + doAssert not isValidFilename("prn.exe") + doAssert not isValidFilename("nim>.nim") + doAssert not isValidFilename(" foo.log") + # Positive Tests. + doAssert isValidFilename("abcd", maxLen = 42.Positive) + doAssert isValidFilename("c0n") + doAssert isValidFilename("foo.aux") + doAssert isValidFilename("bar.prn") + doAssert isValidFilename("OwO_UwU") + doAssert isValidFilename("cron") + doAssert isValidFilename("ux.bat") + doAssert isValidFilename("nim.nim") + doAssert isValidFilename("foo.log") + +block: # searchExtPos + doAssert "foo.nim".searchExtPos == 3 + doAssert "/foo.nim".searchExtPos == 4 + doAssert "".searchExtPos == -1 + doAssert "/".searchExtPos == -1 + doAssert "a.b/foo".searchExtPos == -1 + doAssert ".".searchExtPos == -1 + doAssert "foo.".searchExtPos == 3 + doAssert "foo..".searchExtPos == 4 + doAssert "..".searchExtPos == -1 + doAssert "...".searchExtPos == -1 + doAssert "./".searchExtPos == -1 + doAssert "../".searchExtPos == -1 + doAssert "/.".searchExtPos == -1 + doAssert "/..".searchExtPos == -1 + doAssert ".b".searchExtPos == -1 + doAssert "..b".searchExtPos == -1 + doAssert "/.b".searchExtPos == -1 + doAssert "a/.b".searchExtPos == -1 + doAssert ".a.b".searchExtPos == 2 + doAssert "a/.b.c".searchExtPos == 4 + doAssert "a/..b".searchExtPos == -1 + doAssert "a/b..c".searchExtPos == 4 + + when doslikeFileSystem: + doAssert "c:a.b".searchExtPos == 3 + doAssert "c:.a".searchExtPos == -1 + doAssert r"c:\.a".searchExtPos == -1 + doAssert "c:..a".searchExtPos == -1 + doAssert r"c:\..a".searchExtPos == -1 + doAssert "c:.a.b".searchExtPos == 4 diff --git a/tests/stdlib/tos_unc.nim b/tests/stdlib/tos_unc.nim index fc74a4b9d..194deeb42 100644 --- a/tests/stdlib/tos_unc.nim +++ b/tests/stdlib/tos_unc.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" disabled: "posix" """ diff --git a/tests/stdlib/tosenv.nim b/tests/stdlib/tosenv.nim index f7b3bb9d6..17e397987 100644 --- a/tests/stdlib/tosenv.nim +++ b/tests/stdlib/tosenv.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads" + matrix: "--mm:refc; --mm:arc" joinable: false targets: "c js cpp" """ @@ -7,7 +7,9 @@ discard """ import std/os from std/sequtils import toSeq import stdtest/testutils -import std/assertions + +when defined(nimPreviewSlimSystem): + import std/[assertions] # "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386) const unicodeUtf8 = "\xc3\x86" @@ -50,10 +52,13 @@ static: main() main() when defined(windows): + import std/widestrs proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".} proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".} when not defined(js) and not defined(nimscript): + when defined(nimPreviewSlimSystem): + import std/typedthreads block: # bug #18533 var thr: Thread[void] proc threadFunc {.thread.} = putEnv("foo", "fooVal2") diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim index 47fec2567..da4f6252d 100644 --- a/tests/stdlib/tosproc.nim +++ b/tests/stdlib/tosproc.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" joinable: false """ @@ -93,9 +94,7 @@ else: # main driver const sourcePath = currentSourcePath() let dir = getCurrentDir() / "tests" / "osproc" - template deferScoped(cleanup, body) = - # pending https://github.com/nim-lang/RFCs/issues/236#issuecomment-646855314 - # xxx move to std/sugar or (preferably) some low level module + template deferring(cleanup, body) = try: body finally: cleanup @@ -120,7 +119,10 @@ else: # main driver runTest("exit_0", 0) runTest("exitnow_139", 139) runTest("c_exit2_139", 139) - runTest("quit_139", 139) + when defined(posix): + runTest("quit_139", 127) # The quit value gets saturated to 127 + else: + runTest("quit_139", 139) block execCmdTest: let output = compileNimProg("-d:release -d:case_testfile", "D20220705T221100") @@ -246,14 +248,14 @@ else: # main driver var x = newStringOfCap(120) block: # startProcess stdout poStdErrToStdOut (replaces old test `tstdout` + `ta_out`) var p = startProcess(output, dir, options={poStdErrToStdOut}) - deferScoped: p.close() + deferring: p.close() do: var sout: seq[string] while p.outputStream.readLine(x): sout.add x doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stderr", "to stderr", "to stdout", "to stdout", "end ta_out"] block: # startProcess stderr (replaces old test `tstderr` + `ta_out`) var p = startProcess(output, dir, options={}) - deferScoped: p.close() + deferring: p.close() do: var serr, sout: seq[string] while p.errorStream.readLine(x): serr.add x diff --git a/tests/stdlib/tosprocterminate.nim b/tests/stdlib/tosprocterminate.nim index 08b379569..93b0317f7 100644 --- a/tests/stdlib/tosprocterminate.nim +++ b/tests/stdlib/tosprocterminate.nim @@ -1,7 +1,7 @@ discard """ cmd: "nim $target $options -r $file" targets: "c cpp" - matrix: "--threads:on; " + matrix: "--mm:refc; --mm:orc" """ import os, osproc, times, std / monotimes diff --git a/tests/stdlib/tpackedsets.nim b/tests/stdlib/tpackedsets.nim index 2c69f6b1b..f519c08a7 100644 --- a/tests/stdlib/tpackedsets.nim +++ b/tests/stdlib/tpackedsets.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/packedsets import std/sets diff --git a/tests/stdlib/tparsecfg.nim b/tests/stdlib/tparsecfg.nim index 16f12bc9e..2600d6f66 100644 --- a/tests/stdlib/tparsecfg.nim +++ b/tests/stdlib/tparsecfg.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tparsecsv.nim b/tests/stdlib/tparsecsv.nim index a879019f6..5a1e41bce 100644 --- a/tests/stdlib/tparsecsv.nim +++ b/tests/stdlib/tparsecsv.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + include parsecsv import strutils, os import std/assertions diff --git a/tests/stdlib/tparseipv6.nim b/tests/stdlib/tparseipv6.nim index 9b9c464c7..31ec4ecfb 100644 --- a/tests/stdlib/tparseipv6.nim +++ b/tests/stdlib/tparseipv6.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: "all ok" """ diff --git a/tests/stdlib/tparsesql.nim b/tests/stdlib/tparsesql.nim index cfd8ad148..cd582551d 100644 --- a/tests/stdlib/tparsesql.nim +++ b/tests/stdlib/tparsesql.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import parsesql diff --git a/tests/stdlib/tparseuints.nim b/tests/stdlib/tparseuints.nim index ef8c782b3..9c71a27d6 100644 --- a/tests/stdlib/tparseuints.nim +++ b/tests/stdlib/tparseuints.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import unittest, strutils block: # parseutils diff --git a/tests/stdlib/tparseutils.nim b/tests/stdlib/tparseutils.nim index 084a85dac..b69900864 100644 --- a/tests/stdlib/tparseutils.nim +++ b/tests/stdlib/tparseutils.nim @@ -1,53 +1,112 @@ +discard """ + matrix: "--mm:refc; --mm:orc" + targets: "c cpp" +""" + import std/[parseutils, sequtils, sugar, formatfloat] import std/assertions +proc test() = + let input = "$test{} $this is ${an{ example}} " + let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"), + (ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")] + doAssert toSeq(interpolatedFragments(input)) == expected + + var value = 0 + discard parseHex("0x38", value) + doAssert value == 56 + + value = -1 + doAssert(parseSaturatedNatural("848", value) == 3) + doAssert value == 848 + + value = -1 + discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value) + doAssert value == high(int) -let input = "$test{} $this is ${an{ example}} " -let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"), - (ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")] -doAssert toSeq(interpolatedFragments(input)) == expected + value = -1 + discard parseSaturatedNatural("9223372036854775808", value) + doAssert value == high(int) -var value = 0 -discard parseHex("0x38", value) -doAssert value == 56 + value = -1 + discard parseSaturatedNatural("9223372036854775807", value) + doAssert value == high(int) -value = -1 -doAssert(parseSaturatedNatural("848", value) == 3) -doAssert value == 848 + value = -1 + discard parseSaturatedNatural("18446744073709551616", value) + doAssert value == high(int) -value = -1 -discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value) -doAssert value == high(int) + value = -1 + discard parseSaturatedNatural("18446744073709551615", value) + doAssert value == high(int) -value = -1 -discard parseSaturatedNatural("9223372036854775808", value) -doAssert value == high(int) + value = -1 + doAssert(parseSaturatedNatural("1_000_000", value) == 9) + doAssert value == 1_000_000 -value = -1 -discard parseSaturatedNatural("9223372036854775807", value) -doAssert value == high(int) + var i64Value: int64 + discard parseBiggestInt("9223372036854775807", i64Value) + doAssert i64Value == 9223372036854775807 -value = -1 -discard parseSaturatedNatural("18446744073709551616", value) -doAssert value == high(int) + block: + var f: float + let res = collect: + for x in ["9.123456789012345+","11.123456789012345+","9.123456789012345-","8.123456789012345+","9.12345678901234-","9.123456789012345"]: + (parseFloat(x, f, 0), $f) + doAssert res == @[(17, "9.123456789012344"), (18, "11.123456789012344"), + (17, "9.123456789012344"), (17, "8.123456789012344"), + (16, "9.12345678901234"), (17, "9.123456789012344")] -value = -1 -discard parseSaturatedNatural("18446744073709551615", value) -doAssert value == high(int) +test() +static: test() -value = -1 -doAssert(parseSaturatedNatural("1_000_000", value) == 9) -doAssert value == 1_000_000 +block: # With this included, static: test() crashes the compiler (from a + # VM problem with parseSize calling parseFloat). + var sz: int64 + template checkParseSize(s, expectLen, expectVal) = + if (let got = parseSize(s, sz); got != expectLen): + raise newException(IOError, "got len " & $got & " != " & $expectLen) + if sz != expectVal: + raise newException(IOError, "got sz " & $sz & " != " & $expectVal) + # STRING LEN SZ + # Good, complete parses + checkParseSize "1 b" , 4, 1 + checkParseSize "1 B" , 4, 1 + checkParseSize "1k" , 2, 1000 + checkParseSize "1 kib" , 5, 1024 + checkParseSize "1 ki" , 4, 1024 + checkParseSize "1mi" , 3, 1048576 + checkParseSize "1 mi" , 4, 1048576 + checkParseSize "1 mib" , 5, 1048576 + checkParseSize "1 Mib" , 5, 1048576 + checkParseSize "1 MiB" , 5, 1048576 + checkParseSize "1.23GiB", 7, 1320702444 # 1320702443.52 rounded + checkParseSize "0.001k" , 6, 1 + checkParseSize "0.0004k", 7, 0 + checkParseSize "0.0006k", 7, 1 + # Incomplete parses + checkParseSize "1 " , 1, 1 # Trailing white IGNORED + checkParseSize "1 B " , 4, 1 # Trailing white IGNORED + checkParseSize "1 B/s" , 4, 1 # Trailing junk IGNORED + checkParseSize "1 kX" , 3, 1000 + checkParseSize "1 kiX" , 4, 1024 + checkParseSize "1j" , 1, 1 # Unknown prefix IGNORED + checkParseSize "1 jib" , 2, 1 # Unknown prefix post space + checkParseSize "1 ji" , 3, 1 + # Bad parses; `sz` should stay last good|incomplete value + checkParseSize "-1b" , 0, 1 # Negative numbers + checkParseSize "abc" , 0, 1 # Non-numeric + checkParseSize " 12" , 0, 1 # Leading white + # Value Edge cases + checkParseSize "9223372036854775807", 19, int64.high -var i64Value: int64 -discard parseBiggestInt("9223372036854775807", i64Value) -doAssert i64Value == 9223372036854775807 +block: # bug #23936 + func parsePyFloat( + a: openArray[char], # here must be openArray instead of string to reproduce this bug + res: var BiggestFloat): int = + result = parseFloat(a, res) -block: - var f: float - let res = collect: - for x in ["9.123456789012345+","11.123456789012345+","9.123456789012345-","8.123456789012345+","9.12345678901234-","9.123456789012345"]: - (parseFloat(x, f, 0), $f) - doAssert res == @[(17, "9.123456789012344"), (18, "11.123456789012344"), - (17, "9.123456789012344"), (17, "8.123456789012344"), - (16, "9.12345678901234"), (17, "9.123456789012344")] + static: + var f = 0.0 + doAssert "1.0".parsePyFloat(f) == 3 + doAssert f == 1.0 diff --git a/tests/stdlib/tpathnorm.nim b/tests/stdlib/tpathnorm.nim index 1cd913084..3dd287a77 100644 --- a/tests/stdlib/tpathnorm.nim +++ b/tests/stdlib/tpathnorm.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" """ import std/os diff --git a/tests/stdlib/tpaths.nim b/tests/stdlib/tpaths.nim new file mode 100644 index 000000000..edb56209a --- /dev/null +++ b/tests/stdlib/tpaths.nim @@ -0,0 +1,238 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/paths +import std/assertions +import pathnorm +from std/private/ospaths2 {.all.} import joinPathImpl +import std/[sugar, sets] + + +proc normalizePath*(path: Path; dirSep = DirSep): Path = + result = Path(pathnorm.normalizePath(path.string, dirSep)) + +func joinPath*(parts: varargs[Path]): Path = + var estimatedLen = 0 + var state = 0 + for p in parts: estimatedLen += p.string.len + var res = newStringOfCap(estimatedLen) + for i in 0..high(parts): + joinPathImpl(res, state, parts[i].string) + result = Path(res) + + +func joinPath(head, tail: Path): Path {.inline.} = + head / tail + +block absolutePath: + doAssertRaises(ValueError): discard absolutePath(Path"a", Path"b") + doAssert absolutePath(Path"a") == getCurrentDir() / Path"a" + doAssert absolutePath(Path"a", Path"/b") == Path"/b" / Path"a" + when defined(posix): + doAssert absolutePath(Path"a", Path"/b/") == Path"/b" / Path"a" + doAssert absolutePath(Path"a", Path"/b/c") == Path"/b/c" / Path"a" + doAssert absolutePath(Path"/a", Path"b/") == Path"/a" + +block splitFile: + doAssert splitFile(Path"") == (Path"", Path"", "") + doAssert splitFile(Path"abc/") == (Path"abc", Path"", "") + doAssert splitFile(Path"/") == (Path"/", Path"", "") + doAssert splitFile(Path"./abc") == (Path".", Path"abc", "") + doAssert splitFile(Path".txt") == (Path"", Path".txt", "") + doAssert splitFile(Path"abc/.txt") == (Path"abc", Path".txt", "") + doAssert splitFile(Path"abc") == (Path"", Path"abc", "") + doAssert splitFile(Path"abc.txt") == (Path"", Path"abc", ".txt") + doAssert splitFile(Path"/abc.txt") == (Path"/", Path"abc", ".txt") + doAssert splitFile(Path"/foo/abc.txt") == (Path"/foo", Path"abc", ".txt") + doAssert splitFile(Path"/foo/abc.txt.gz") == (Path"/foo", Path"abc.txt", ".gz") + doAssert splitFile(Path".") == (Path"", Path".", "") + doAssert splitFile(Path"abc/.") == (Path"abc", Path".", "") + doAssert splitFile(Path"..") == (Path"", Path"..", "") + doAssert splitFile(Path"a/..") == (Path"a", Path"..", "") + doAssert splitFile(Path"/foo/abc....txt") == (Path"/foo", Path"abc...", ".txt") + +# execShellCmd is tested in tosproc + +block ospaths: + doAssert unixToNativePath(Path"") == Path"" + doAssert unixToNativePath(Path".") == Path($CurDir) + doAssert unixToNativePath(Path"..") == Path($ParDir) + doAssert isAbsolute(unixToNativePath(Path"/")) + doAssert isAbsolute(unixToNativePath(Path"/", Path"a")) + doAssert isAbsolute(unixToNativePath(Path"/a")) + doAssert isAbsolute(unixToNativePath(Path"/a", Path"a")) + doAssert isAbsolute(unixToNativePath(Path"/a/b")) + doAssert isAbsolute(unixToNativePath(Path"/a/b", Path"a")) + doAssert unixToNativePath(Path"a/b") == joinPath(Path"a", Path"b") + + when defined(macos): + doAssert unixToNativePath(Path"./") == Path":" + doAssert unixToNativePath(Path"./abc") == Path":abc" + doAssert unixToNativePath(Path"../abc") == Path"::abc" + doAssert unixToNativePath(Path"../../abc") == Path":::abc" + doAssert unixToNativePath(Path"/abc", Path"a") == Path"abc" + doAssert unixToNativePath(Path"/abc/def", Path"a") == Path"abc:def" + elif doslikeFileSystem: + doAssert unixToNativePath(Path"./") == Path(".\\") + doAssert unixToNativePath(Path"./abc") == Path(".\\abc") + doAssert unixToNativePath(Path"../abc") == Path("..\\abc") + doAssert unixToNativePath(Path"../../abc") == Path("..\\..\\abc") + doAssert unixToNativePath(Path"/abc", Path"a") == Path("a:\\abc") + doAssert unixToNativePath(Path"/abc/def", Path"a") == Path("a:\\abc\\def") + else: + #Tests for unix + doAssert unixToNativePath(Path"./") == Path"./" + doAssert unixToNativePath(Path"./abc") == Path"./abc" + doAssert unixToNativePath(Path"../abc") == Path"../abc" + doAssert unixToNativePath(Path"../../abc") == Path"../../abc" + doAssert unixToNativePath(Path"/abc", Path"a") == Path"/abc" + doAssert unixToNativePath(Path"/abc/def", Path"a") == Path"/abc/def" + + block extractFilenameTest: + doAssert extractFilename(Path"") == Path"" + when defined(posix): + doAssert extractFilename(Path"foo/bar") == Path"bar" + doAssert extractFilename(Path"foo/bar.txt") == Path"bar.txt" + doAssert extractFilename(Path"foo/") == Path"" + doAssert extractFilename(Path"/") == Path"" + when doslikeFileSystem: + doAssert extractFilename(Path(r"foo\bar")) == Path"bar" + doAssert extractFilename(Path(r"foo\bar.txt")) == Path"bar.txt" + doAssert extractFilename(Path(r"foo\")) == Path"" + doAssert extractFilename(Path(r"C:\")) == Path"" + + block lastPathPartTest: + doAssert lastPathPart(Path"") == Path"" + when defined(posix): + doAssert lastPathPart(Path"foo/bar.txt") == Path"bar.txt" + doAssert lastPathPart(Path"foo/") == Path"foo" + doAssert lastPathPart(Path"/") == Path"" + when doslikeFileSystem: + doAssert lastPathPart(Path(r"foo\bar.txt")) == Path"bar.txt" + doAssert lastPathPart(Path(r"foo\")) == Path"foo" + + template canon(x): Path = normalizePath(Path(x), '/') + doAssert canon"/foo/../bar" == Path"/bar" + doAssert canon"foo/../bar" == Path"bar" + + doAssert canon"/f/../bar///" == Path"/bar" + doAssert canon"f/..////bar" == Path"bar" + + doAssert canon"../bar" == Path"../bar" + doAssert canon"/../bar" == Path"/../bar" + + doAssert canon("foo/../../bar/") == Path"../bar" + doAssert canon("./bla/blob/") == Path"bla/blob" + doAssert canon(".hiddenFile") == Path".hiddenFile" + doAssert canon("./bla/../../blob/./zoo.nim") == Path"../blob/zoo.nim" + + doAssert canon("C:/file/to/this/long") == Path"C:/file/to/this/long" + doAssert canon("") == Path"" + doAssert canon("foobar") == Path"foobar" + doAssert canon("f/////////") == Path"f" + + doAssert relativePath(Path"/foo/bar//baz.nim", Path"/foo", '/') == Path"bar/baz.nim" + doAssert normalizePath(Path"./foo//bar/../baz", '/') == Path"foo/baz" + + doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/other/bad", '/') == Path"../../me/bar/z.nim" + + doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/other", '/') == Path"../me/bar/z.nim" + + # `//` is a UNC path, `/` is the current working directory's drive, so can't + # run this test on Windows. + when not doslikeFileSystem: + doAssert relativePath(Path"/Users///me/bar//z.nim", Path"//Users/", '/') == Path"me/bar/z.nim" + doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/me", '/') == Path"bar/z.nim" + doAssert relativePath(Path"", Path"/users/moo", '/') == Path"" + doAssert relativePath(Path"foo", Path"", '/') == Path"foo" + doAssert relativePath(Path"/foo", Path"/Foo", '/') == (when FileSystemCaseSensitive: Path"../foo" else: Path".") + doAssert relativePath(Path"/Foo", Path"/foo", '/') == (when FileSystemCaseSensitive: Path"../Foo" else: Path".") + doAssert relativePath(Path"/foo", Path"/fOO", '/') == (when FileSystemCaseSensitive: Path"../foo" else: Path".") + doAssert relativePath(Path"/foO", Path"/foo", '/') == (when FileSystemCaseSensitive: Path"../foO" else: Path".") + + doAssert relativePath(Path"foo", Path".", '/') == Path"foo" + doAssert relativePath(Path".", Path".", '/') == Path"." + doAssert relativePath(Path"..", Path".", '/') == Path".." + + doAssert relativePath(Path"foo", Path"foo") == Path"." + doAssert relativePath(Path"", Path"foo") == Path"" + doAssert relativePath(Path"././/foo", Path"foo//./") == Path"." + + doAssert relativePath(getCurrentDir() / Path"bar", Path"foo") == Path"../bar".unixToNativePath + doAssert relativePath(Path"bar", getCurrentDir() / Path"foo") == Path"../bar".unixToNativePath + + when doslikeFileSystem: + doAssert relativePath(r"c:\foo.nim".Path, r"C:\".Path) == r"foo.nim".Path + doAssert relativePath(r"c:\foo\bar\baz.nim".Path, r"c:\foo".Path) == r"bar\baz.nim".Path + doAssert relativePath(r"c:\foo\bar\baz.nim".Path, r"d:\foo".Path) == r"c:\foo\bar\baz.nim".Path + doAssert relativePath(r"\foo\baz.nim".Path, r"\foo".Path) == r"baz.nim".Path + doAssert relativePath(r"\foo\bar\baz.nim".Path, r"\bar".Path) == r"..\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foo\bar".Path) == r"baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foO\bar".Path) == r"baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\bar\bar".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foo\car".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\goo\bar".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"c:\".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\foo".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"c:\foo.nim".Path, r"\foo".Path) == r"c:\foo.nim".Path + + doAssert joinPath(Path"usr", Path"") == unixToNativePath(Path"usr") + doAssert joinPath(Path"usr", Path"") == (Path"usr").dup(add Path"") + doAssert joinPath(Path"", Path"lib") == Path"lib" + doAssert joinPath(Path"", Path"lib") == Path"".dup(add Path"lib") + doAssert joinPath(Path"", Path"/lib") == unixToNativePath(Path"/lib") + doAssert joinPath(Path"", Path"/lib") == unixToNativePath(Path"/lib") + doAssert joinPath(Path"usr/", Path"/lib") == Path"usr/".dup(add Path"/lib") + doAssert joinPath(Path"", Path"") == unixToNativePath(Path"") # issue #13455 + doAssert joinPath(Path"", Path"") == Path"".dup(add Path"") + doAssert joinPath(Path"", Path"/") == unixToNativePath(Path"/") + doAssert joinPath(Path"", Path"/") == Path"".dup(add Path"/") + doAssert joinPath(Path"/", Path"/") == unixToNativePath(Path"/") + doAssert joinPath(Path"/", Path"/") == Path"/".dup(add Path"/") + doAssert joinPath(Path"/", Path"") == unixToNativePath(Path"/") + doAssert joinPath(Path"/" / Path"") == unixToNativePath(Path"/") # weird test case... + doAssert joinPath(Path"/", Path"/a/b/c") == unixToNativePath(Path"/a/b/c") + doAssert joinPath(Path"foo/", Path"") == unixToNativePath(Path"foo/") + doAssert joinPath(Path"foo/", Path"abc") == unixToNativePath(Path"foo/abc") + doAssert joinPath(Path"foo//./", Path"abc/.//") == unixToNativePath(Path"foo/abc/") + doAssert Path"foo//./".dup(add Path"abc/.//") == unixToNativePath(Path"foo/abc/") + doAssert joinPath(Path"foo", Path"abc") == unixToNativePath(Path"foo/abc") + doAssert Path"foo".dup(add Path"abc") == unixToNativePath(Path"foo/abc") + doAssert joinPath(Path"", Path"abc") == unixToNativePath(Path"abc") + + doAssert joinPath(Path"zook/.", Path"abc") == unixToNativePath(Path"zook/abc") + + # controversial: inconsistent with `joinPath("zook/.","abc")` + # on linux, `./foo` and `foo` are treated a bit differently for executables + # but not `./foo/bar` and `foo/bar` + doAssert joinPath(Path".", Path"/lib") == unixToNativePath(Path"./lib") + doAssert joinPath(Path".", Path"abc") == unixToNativePath(Path"./abc") + + # cases related to issue #13455 + doAssert joinPath(Path"foo", Path"", Path"") == Path"foo" + doAssert joinPath(Path"foo", Path"") == Path"foo" + doAssert joinPath(Path"foo/", Path"") == unixToNativePath(Path"foo/") + doAssert joinPath(Path"foo/", Path".") == Path"foo" + doAssert joinPath(Path"foo", Path"./") == unixToNativePath(Path"foo/") + doAssert joinPath(Path"foo", Path"", Path"bar/") == unixToNativePath(Path"foo/bar/") + + # issue #13579 + doAssert joinPath(Path"/foo", Path"../a") == unixToNativePath(Path"/a") + doAssert joinPath(Path"/foo/", Path"../a") == unixToNativePath(Path"/a") + doAssert joinPath(Path"/foo/.", Path"../a") == unixToNativePath(Path"/a") + doAssert joinPath(Path"/foo/.b", Path"../a") == unixToNativePath(Path"/foo/a") + doAssert joinPath(Path"/foo///", Path"..//a/") == unixToNativePath(Path"/a/") + doAssert joinPath(Path"foo/", Path"../a") == unixToNativePath(Path"a") + + when doslikeFileSystem: + doAssert joinPath(Path"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\", Path"..\\..\\VC\\vcvarsall.bat") == r"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat".Path + doAssert joinPath(Path"C:\\foo", Path"..\\a") == r"C:\a".Path + doAssert joinPath(Path"C:\\foo\\", Path"..\\a") == r"C:\a".Path + + +block: # bug #23663 + var s: HashSet[Path] + s.incl("/a/b/c/..".Path) + doAssert "/a/b/".Path in s + doAssert "/a/b/c".Path notin s diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim index cbc8fe205..da3fc14b7 100644 --- a/tests/stdlib/tpegs.nim +++ b/tests/stdlib/tpegs.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" output: ''' PEG AST traversal output @@ -106,9 +107,9 @@ block: block: var - pStack: seq[string] = @[] - valStack: seq[float] = @[] - opStack = "" + pStack {.threadvar.}: seq[string] + valStack {.threadvar.}: seq[float] + opStack {.threadvar.}: string let parseArithExpr = pegAst.eventParser: pkNonTerminal: @@ -328,7 +329,16 @@ call() doAssert program.len == program.rawMatch(grammar, 0, c) doAssert c.ml == 1 + block: + # bug #21632 + + let p = peg""" + atext <- \w / \d + """ + + doAssert "a".match(p) + doAssert "1".match(p) + pegsTest() static: pegsTest() - diff --git a/tests/stdlib/tposix.nim b/tests/stdlib/tposix.nim index ea0472c31..060482229 100644 --- a/tests/stdlib/tposix.nim +++ b/tests/stdlib/tposix.nim @@ -1,5 +1,6 @@ discard """ -outputsub: "" + matrix: "--mm:refc; --mm:orc" + disabled: windows """ # Test Posix interface @@ -7,7 +8,7 @@ outputsub: "" when not defined(windows): import posix - import std/syncio + import std/[assertions, syncio] var u: Utsname @@ -18,3 +19,70 @@ when not defined(windows): writeLine(stdout, u.nodename) writeLine(stdout, u.release) writeLine(stdout, u.machine) + + when not (defined(nintendoswitch) or defined(macos) or defined(macosx)): + block: + type Message = object + value: int + + const MQ_PATH: cstring = "/top_level_file" + const MQ_PRIORITY: cuint = 170 + const MQ_MESSAGE_SIZE: csize_t = csize_t(sizeof(Message)) + + let mqd_a: posix.MqAttr = MqAttr(mq_maxmsg: 10, mq_msgsize: clong(MQ_MESSAGE_SIZE)) + let writable: posix.Mqd = posix.mq_open( + MQ_PATH, + posix.O_CREAT or posix.O_WRONLY or posix.O_NONBLOCK, + posix.S_IRWXU, + addr(mqd_a) + ) + let readable: posix.Mqd = posix.mq_open( + MQ_PATH, + posix.O_RDONLY or posix.O_NONBLOCK, + posix.S_IRWXU, + addr(mqd_a) + ) + + let sent: Message = Message(value: 88) + block: + let success: int = writable.mq_send( + cast[cstring](sent.addr), + MQ_MESSAGE_SIZE, + MQ_PRIORITY + ) + doAssert success == 0, $success + + block: + var buffer: Message + var priority: cuint + let bytesRead: int = readable.mq_receive( + cast[cstring](buffer.addr), + MQ_MESSAGE_SIZE, + priority + ) + doAssert buffer == sent + doAssert bytesRead == int(MQ_MESSAGE_SIZE) + + block: + var rl: RLimit + var res = getrlimit(RLIMIT_STACK, rl) + doAssert res == 0 + + # save old value + let oldrlim = rl.rlim_cur + + # set new value + rl.rlim_cur = rl.rlim_max - 1 + res = setrlimit(RLIMIT_STACK, rl) + doAssert res == 0 + + # get new value + var rl1: RLimit + res = getrlimit(RLIMIT_STACK, rl1) + doAssert res == 0 + doAssert rl1.rlim_cur == rl.rlim_max - 1 + + # restore old value + rl.rlim_cur = oldrlim + res = setrlimit(RLIMIT_STACK, rl) + doAssert res == 0 diff --git a/tests/stdlib/tpunycode.nim b/tests/stdlib/tpunycode.nim deleted file mode 100644 index dea6b2dc6..000000000 --- a/tests/stdlib/tpunycode.nim +++ /dev/null @@ -1,206 +0,0 @@ -import punycode, std/unicode -import std/assertions - -doAssert(decode(encode("", "bücher")) == "bücher") -doAssert(decode(encode("münchen")) == "münchen") -doAssert encode("xn--", "münchen") == "xn--mnchen-3ya" - -# source: https://datatracker.ietf.org/doc/html/rfc3492.html#section-7 -let punycode_testcases = [ - # (A) Arabic (Egyptian): - ( - input: - "\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" & - "\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F", - output: - "egbpdaj6bu4bxfgehfvwxn" - ), - - # (B) Chinese (simplified): - ( - input: - "\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587", - output: - "ihqwcrb4cv8a8dqg056pqjye" - ), - - # (C) Chinese (traditional): - ( - input: - "\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587", - output: - "ihqwctvzc91f659drss3x8bo0yb" - ), - - # (D) Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky - ( - input: - "\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" & - "\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" & - "\u0065\u0073\u006B\u0079", - output: - "Proprostnemluvesky-uyb24dma41a" - ), - - # (E) Hebrew: - ( - input: - "\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" & - "\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" & - "\u05D1\u05E8\u05D9\u05EA", - output: - "4dbcagdahymbxekheh6e0a7fei0b" - ), - - # (F) Hindi (Devanagari): - ( - input: - "\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" & - "\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" & - "\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" & - "\u0939\u0948\u0902", - output: - "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd" - ), - - # (G) Japanese (kanji and hiragana): - ( - input: - "\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" & - "\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B", - output: - "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa" - ), - - # (H) Korean (Hangul syllables): - ( - input: - "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" & - "\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" & - "\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C", - output: - "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c" - ), - - # (I) Russian (Cyrillic): - ( - input: - "\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" & - "\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" & - "\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" & - "\u0438", - output: - "b1abfaaepdrnnbgefbaDotcwatmq2g4l" - ), - - # (J) Spanish: Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol - ( - input: - "\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" & - "\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" & - "\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" & - "\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" & - "\u0061\u00F1\u006F\u006C", - output: - "PorqunopuedensimplementehablarenEspaol-fmd56a" - ), - - # (K) Vietnamese: - # T<adotbelow>isaoh<odotbelow>kh<ocirc>ngth<ecirchookabove>ch\ - # <ihookabove>n<oacute>iti<ecircacute>ngVi<ecircdotbelow>t - ( - input: - "\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" & - "\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" & - "\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" & - "\u0056\u0069\u1EC7\u0074", - output: - "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g" - ), - - # (L) 3<nen>B<gumi><kinpachi><sensei> - ( - input: - "\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F", - output: - "3B-ww4c5e180e575a65lsy2b" - ), - - # (M) <amuro><namie>-with-SUPER-MONKEYS - ( - input: - "\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" & - "\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" & - "\u004F\u004E\u004B\u0045\u0059\u0053", - output: - "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n" - ), - - # (N) Hello-Another-Way-<sorezore><no><basho> - ( - input: - "\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" & - "\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" & - "\u305D\u308C\u305E\u308C\u306E\u5834\u6240", - output: - "Hello-Another-Way--fc4qua05auwb3674vfr0b" - ), - - # (O) <hitotsu><yane><no><shita>2 - ( - input: - "\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032", - output: - "2-u9tlzr9756bt3uc0v" - ), - - # (P) Maji<de>Koi<suru>5<byou><mae> - ( - input: - "\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" & - "\u308B\u0035\u79D2\u524D", - output: - "MajiKoi5-783gue6qz075azm5e" - ), - - # (Q) <pafii>de<runba> - ( - input: - "\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0", - output: - "de-jg4avhby1noc0d" - ), - - # (R) <sono><supiido><de> - ( - input: - "\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067", - output: - "d9juau41awczczp" - ), - - # (S) -> $1.00 <- - ( - input: - "\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" & - "\u003C\u002D", - output: - "-> $1.00 <--" - ) -] - -block encodeTests: - for (uni, puny) in punycode_testcases: - # Need to convert both strings to lower case, since - # some of the extended encodings use upper case, but our - # code produces only lower case. Converting just puny to - # lower is also insufficient, since some of the input characters - # are upper case. - doAssert encode(uni).toLower() == puny.toLower() - -block decodeTests: - for (uni, puny) in punycode_testcases: - doAssert decode(puny) == uni - -block decodeInvalidTest: - doAssertRaises(PunyError): discard decode("xn--w&") diff --git a/tests/stdlib/tquit.nim b/tests/stdlib/tquit.nim deleted file mode 100644 index 3a7db4d4e..000000000 --- a/tests/stdlib/tquit.nim +++ /dev/null @@ -1,17 +0,0 @@ -discard """ -output: ''' -just exiting... -''' -joinable: false -""" - -# Test `addQuitProc` (now deprecated by `addExitProc`) - -import std/syncio - -proc myExit() {.noconv.} = - write(stdout, "just exiting...\n") - -{.push warning[deprecated]: off.} -addQuitProc(myExit) -{.pop.} diff --git a/tests/stdlib/trandom.nim b/tests/stdlib/trandom.nim index ef71c3442..eb32f7757 100644 --- a/tests/stdlib/trandom.nim +++ b/tests/stdlib/trandom.nim @@ -1,9 +1,10 @@ discard """ joinable: false # to avoid messing with global rand state - targets: "c js" + matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ import std/[assertions, formatfloat] import std/[random, math, stats, sets, tables] +import std/private/jsutils when not defined(js): import std/os @@ -46,6 +47,8 @@ block: type DiceRoll = range[0..6] when not defined(js): doAssert rand(DiceRoll).int == 3 + elif compileOption("jsbigint64"): + doAssert rand(DiceRoll).int == 1 else: doAssert rand(DiceRoll).int == 6 @@ -191,9 +194,7 @@ block: # bug #17467 # This used to fail for each i in 0..<26844, i.e. the 1st produced value # was predictable and < 1e-4, skewing distributions. -const withUint = false # pending exporting `proc rand[T: uint | uint64](r: var Rand; max: T): T =` - -block: # bug #16360 +block: # bug #16360, Natural overload var r = initRand() template test(a) = let a2 = a @@ -205,23 +206,38 @@ block: # bug #16360 let a3 = rand(a2) doAssert a3 <= a2 doAssert a3.type is a2.type - when withUint: - test cast[uint](int.high) - test cast[uint](int.high) + 1 - when not defined(js): - # pending bug #16411 - test uint64.high - test uint64.high - 1 - test uint.high - 2 - test uint.high - 1 - test uint.high test int.high test int.high - 1 test int.high - 2 test 0 - when withUint: - test 0'u - test 0'u64 + +block: # same as above but use slice overload + var r = initRand() + template test[T](a: T) = + let a2: T = a + block: + let a3 = r.rand(T(0) .. a2) + doAssert a3 <= a2 + doAssert a3.type is a2.type + block: + let a3 = rand(T(0) .. a2) + doAssert a3 <= a2 + doAssert a3.type is a2.type + test cast[uint](int.high) + test cast[uint](int.high) + 1 + whenJsNoBigInt64: discard + do: + test uint64.high + test uint64.high - 1 + test uint.high - 2 + test uint.high - 1 + test uint.high + test int.high + test int.high - 1 + test int.high - 2 + test 0 + test 0'u + test 0'u64 block: # bug #16296 var r = initRand() @@ -239,16 +255,12 @@ block: # bug #16296 test(int.low .. -1) test(int.low .. 1) test(int64.low .. 1'i64) - when not defined(js): - # pending bug #16411 - test(10'u64 .. uint64.high) + test(10'u64 .. uint64.high) block: # bug #17670 - when not defined(js): - # pending bug #16411 - type UInt48 = range[0'u64..2'u64^48-1] - let x = rand(UInt48) - doAssert x is UInt48 + type UInt48 = range[0'u64..2'u64^48-1] + let x = rand(UInt48) + doAssert x is UInt48 block: # bug #17898 # Checks whether `initRand()` generates unique states. @@ -272,3 +284,27 @@ block: # bug #17898 for j in 0..<numRepeat: discard rands[i].next doAssert rands[i] notin randSet + +block: # bug #22360 + const size = 1000 + var fc = 0 + var tc = 0 + + for _ in 1..size: + let s = rand(bool) + + if s: + inc tc + else: + inc fc + + when defined(js) and not compileOption("jsbigint64"): + doAssert (tc, fc) == (515, 485), $(tc, fc) + else: + doAssert (tc, fc) == (510, 490), $(tc, fc) + +block: + when defined(js) and not compileOption("jsbigint64"): + doAssert rand(int32.high) == 335507522 + else: + doAssert rand(int32.high) == 607539621 diff --git a/tests/stdlib/trat_float.nim b/tests/stdlib/trat_float.nim new file mode 100644 index 000000000..663973bf9 --- /dev/null +++ b/tests/stdlib/trat_float.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: '''type mismatch: got''' + file: "trat_float.nim" + line: "9,19" +""" +import rationals +var + # this fails - no floats as num or den + r = initRational(1.0'f, 1.0'f) diff --git a/tests/stdlib/trat_init.nim b/tests/stdlib/trat_init.nim new file mode 100644 index 000000000..2be0c0099 --- /dev/null +++ b/tests/stdlib/trat_init.nim @@ -0,0 +1,14 @@ +discard """ + output: '''true''' +""" +import rationals +var + z = Rational[int](num: 0, den: 1) + o = initRational(num=1, den=1) + a = initRational(1, 2) + +try: + var + r = initRational(1, 0) # this fails - no zero denominator +except AssertionDefect: + echo "true" diff --git a/tests/stdlib/trationals.nim b/tests/stdlib/trationals.nim index cf2e92003..22d7f5c2d 100644 --- a/tests/stdlib/trationals.nim +++ b/tests/stdlib/trationals.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/[rationals, math] import std/assertions @@ -6,6 +10,7 @@ template main() = z = Rational[int](num: 0, den: 1) o = initRational(num = 1, den = 1) a = initRational(1, 2) + u = 3u // 2 b = -1 // -2 m1 = -1 // 1 tt = 10 // 2 @@ -100,5 +105,13 @@ template main() = when sizeof(int) == 8: doAssert almostEqual(PI.toRational.toFloat, PI) + # unsigned + doAssert u == u + doAssert u + u == 3u // 1 + doAssert 3u.toRational - u == u + doAssert u * 2 == 3u // 1 + + + static: main() main() diff --git a/tests/stdlib/tre.nim b/tests/stdlib/tre.nim index 3986934c4..39637434d 100644 --- a/tests/stdlib/tre.nim +++ b/tests/stdlib/tre.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/re import std/assertions diff --git a/tests/stdlib/treadln.nim b/tests/stdlib/treadln.nim new file mode 100644 index 000000000..4a070e848 --- /dev/null +++ b/tests/stdlib/treadln.nim @@ -0,0 +1,23 @@ + +discard """ +output: ''' +test the improved readline handling that does not care whether its +Macintosh, Unix or Windows text format. +''' +""" + +import std/syncio + +# test the improved readline handling that does not care whether its +# Macintosh, Unix or Windows text format. + +var + inp: File + line: string + +if open(inp, "tests/stdlib/treadln.nim"): + while not endOfFile(inp): + line = readLine(inp) + if line.len >= 2 and line[0] == '#' and line[1] == ' ': + echo line[2..^1] + close(inp) diff --git a/tests/stdlib/tregex.nim b/tests/stdlib/tregex.nim index cf80f8122..9dd66cd60 100644 --- a/tests/stdlib/tregex.nim +++ b/tests/stdlib/tregex.nim @@ -1,5 +1,6 @@ discard """ output: "key: keyAYes!" + matrix: "--mm:refc; --mm:orc" """ # Test the new regular expression module # which is based on the PCRE library diff --git a/tests/stdlib/tregistry.nim b/tests/stdlib/tregistry.nim index 4956f8196..25aed8df8 100644 --- a/tests/stdlib/tregistry.nim +++ b/tests/stdlib/tregistry.nim @@ -1,6 +1,6 @@ discard """ disabled: "unix" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" """ when defined(windows): diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim index c85ae2b2a..3956b98f9 100644 --- a/tests/stdlib/trepr.nim +++ b/tests/stdlib/trepr.nim @@ -1,6 +1,6 @@ discard """ targets: "c cpp js" - matrix: ";--gc:arc" + matrix: "--mm:refc;--mm:arc" """ # if excessive, could remove 'cpp' from targets @@ -40,7 +40,7 @@ template main() = #[ BUG: --gc:arc returns `"abc"` - regular gc returns with address, e.g. 0x1068aae60"abc", but only + regular gc returns with address, e.g. 0x1068aae60"abc", but only for c,cpp backends (not js, vm) ]# block: @@ -271,5 +271,58 @@ func fn2(): int = ## comment result = 1""" + block: # block calls + let a = deb: + foo(a, b, (c, d)): + e + f + do: g + of h: i + elif j: k + except m: n + do () -> u: v + finally: o + + a + b: + c + d + do: + e + f + else: g + + *a: b + do: c + + doAssert a == """foo(a, b, (c, d)): + e + f +do: + g +of h: + i +elif j: + k +except m: + n +do -> u: + v +finally: + o +a + b: + c + d +do: + e + f +else: + g +*a: + b +do: + c""" + + doAssert repr(1..2) == "1 .. 2" + static: main() main() diff --git a/tests/stdlib/tropes.nim b/tests/stdlib/tropes.nim index 6d41e9e44..eb0edc364 100644 --- a/tests/stdlib/tropes.nim +++ b/tests/stdlib/tropes.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/trst.nim b/tests/stdlib/trst.nim index 818f8b8dc..ceab34bc9 100644 --- a/tests/stdlib/trst.nim +++ b/tests/stdlib/trst.nim @@ -7,6 +7,8 @@ discard """ [Suite] RST indentation +[Suite] Markdown indentation + [Suite] Warnings [Suite] RST include directive @@ -14,7 +16,10 @@ discard """ [Suite] RST escaping [Suite] RST inline markup + +[Suite] Misc isssues ''' +matrix: "--mm:refc; --mm:orc" """ # tests for rst module @@ -26,7 +31,9 @@ import os import std/[assertions, syncio] const preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled} +# legacy nimforum / old default mode: const preferRst = {roSupportMarkdown, roNimFile, roSandboxDisabled} +const pureRst = {roNimFile, roSandboxDisabled} proc toAst(input: string, rstOptions: RstParseOptions = preferMarkdown, @@ -58,13 +65,52 @@ proc toAst(input: string, result = "" var (rst, _, _) = rstParse(input, filen, line=LineRstInit, column=ColRstInit, - rstOptions, myFindFile, testMsgHandler) + rstOptions, myFindFile, nil, testMsgHandler) result = treeRepr(rst) except EParseError as e: if e.msg != "": result = e.msg suite "RST parsing": + test "Standalone punctuation is not parsed as heading overlines": + check(dedent""" + Paragraph + + !""".toAst == + dedent""" + rnInner + rnParagraph + rnLeaf 'Paragraph' + rnParagraph + rnLeaf '!' + """) + + check(dedent""" + Paragraph1 + + ... + + Paragraph2""".toAst == + dedent""" + rnInner + rnParagraph + rnLeaf 'Paragraph1' + rnParagraph + rnLeaf '...' + rnParagraph + rnLeaf 'Paragraph2' + """) + + check(dedent""" + --- + Paragraph""".toAst == + dedent""" + rnInner + rnLeaf '---' + rnLeaf ' ' + rnLeaf 'Paragraph' + """) + test "References are whitespace-neutral and case-insensitive": # refname is 'lexical-analysis', the same for all the 3 variants: check(dedent""" @@ -124,12 +170,12 @@ suite "RST parsing": check(dedent""" Paragraph:: - >x""".toAst == expected) + >x""".toAst(rstOptions = preferRst) == expected) check(dedent""" Paragraph:: - >x""".toAst == expected) + >x""".toAst(rstOptions = preferRst) == expected) test "RST quoted literal blocks, :: at a separate line": let expected = @@ -148,7 +194,7 @@ suite "RST parsing": :: >x - >>y""".toAst == expected) + >>y""".toAst(rstOptions = preferRst) == expected) check(dedent""" Paragraph @@ -156,7 +202,7 @@ suite "RST parsing": :: >x - >>y""".toAst == expected) + >>y""".toAst(rstOptions = preferRst) == expected) test "Markdown quoted blocks": check(dedent""" @@ -482,11 +528,77 @@ suite "RST parsing": rnFieldBody rnLeaf 'Nim' rnLiteralBlock - rnLeaf ' - let a = 1 + rnLeaf 'let a = 1 ```' """ + test "Markdown footnotes": + # Testing also 1) correct order of manually-numbered and automatically- + # numbered footnotes; 2) no spaces between references (html & 3 below): + + check(dedent""" + Paragraph [^1] [^html-hyphen][^3] and [^latex] + + [^1]: footnote1 + + [^html-hyphen]: footnote2 + continuation2 + + [^latex]: footnote4 + + [^3]: footnote3 + continuation3 + """.toAst == + dedent""" + rnInner + rnInner + rnLeaf 'Paragraph' + rnLeaf ' ' + rnFootnoteRef + rnInner + rnLeaf '1' + rnLeaf 'footnote-1' + rnLeaf ' ' + rnFootnoteRef + rnInner + rnLeaf '2' + rnLeaf 'footnote-htmlminushyphen' + rnFootnoteRef + rnInner + rnLeaf '3' + rnLeaf 'footnote-3' + rnLeaf ' ' + rnLeaf 'and' + rnLeaf ' ' + rnFootnoteRef + rnInner + rnLeaf '4' + rnLeaf 'footnote-latex' + rnFootnoteGroup + rnFootnote anchor='footnote-1' + rnInner + rnLeaf '1' + rnLeaf 'footnote1' + rnFootnote anchor='footnote-htmlminushyphen' + rnInner + rnLeaf '2' + rnInner + rnLeaf 'footnote2' + rnLeaf ' ' + rnLeaf 'continuation2' + rnFootnote anchor='footnote-latex' + rnInner + rnLeaf '4' + rnLeaf 'footnote4' + rnFootnote anchor='footnote-3' + rnInner + rnLeaf '3' + rnInner + rnLeaf 'footnote3' + rnLeaf ' ' + rnLeaf 'continuation3' + """) + test "Markdown code blocks with more > 3 backticks": check(dedent""" ```` @@ -526,8 +638,7 @@ suite "RST parsing": rnLeaf 'test' rnFieldBody rnLiteralBlock - rnLeaf ' - let a = 1' + rnLeaf 'let a = 1' """) check(dedent""" @@ -550,8 +661,7 @@ suite "RST parsing": rnFieldBody rnLeaf '1' rnLiteralBlock - rnLeaf ' - let a = 1' + rnLeaf 'let a = 1' """) test "additional indentation < 4 spaces is handled fine": @@ -571,8 +681,7 @@ suite "RST parsing": rnLeaf 'nim' [nil] rnLiteralBlock - rnLeaf ' - let a = 1' + rnLeaf ' let a = 1' """) # | | # | \ indentation of exactly two spaces before 'let a = 1' @@ -606,8 +715,7 @@ suite "RST parsing": rnFieldBody rnLeaf 'Nim' rnLiteralBlock - rnLeaf ' - CodeBlock()' + rnLeaf 'CodeBlock()' rnLeaf ' ' rnLeaf 'Other' rnLeaf ' ' @@ -687,6 +795,32 @@ suite "RST parsing": rnLeaf 'desc2' """) + test "definition lists work correctly with additional indentation in Markdown": + check(dedent""" + Paragraph: + -c desc1 + -b desc2 + """.toAst() == + dedent""" + rnInner + rnInner + rnLeaf 'Paragraph' + rnLeaf ':' + rnOptionList + rnOptionListItem order=1 + rnOptionGroup + rnLeaf '-' + rnLeaf 'c' + rnDescription + rnLeaf 'desc1' + rnOptionListItem order=2 + rnOptionGroup + rnLeaf '-' + rnLeaf 'b' + rnDescription + rnLeaf 'desc2' + """) + test "RST comment": check(dedent""" .. comment1 @@ -779,7 +913,7 @@ suite "RST parsing": code - """.toAst == + """.toAst(rstOptions = preferRst) == dedent""" rnInner rnLeaf 'Check' @@ -788,6 +922,32 @@ suite "RST parsing": rnLeaf 'code' """) + test "Markdown indented code blocks": + check(dedent""" + See + + some code""".toAst == + dedent""" + rnInner + rnInner + rnLeaf 'See' + rnLiteralBlock + rnLeaf 'some code' + """) + + # not a code block -- no blank line before: + check(dedent""" + See + some code""".toAst == + dedent""" + rnInner + rnLeaf 'See' + rnLeaf ' ' + rnLeaf 'some' + rnLeaf ' ' + rnLeaf 'code' + """) + suite "RST tables": test "formatting in tables works": @@ -823,10 +983,31 @@ suite "RST tables": ====== ====== Inputs Output ====== ====== - """.toAst(error=error) == "") + """.toAst(rstOptions = pureRst, error = error) == "") check(error[] == "input(2, 2) Error: Illformed table: " & "this word crosses table column from the right") + # In nimforum compatibility mode & Markdown we raise a warning instead: + let expected = dedent""" + rnTable colCount=2 + rnTableRow + rnTableDataCell + rnLeaf 'Inputs' + rnTableDataCell + rnLeaf 'Output' + """ + for opt in [preferRst, preferMarkdown]: + var warnings = new seq[string] + + check( + dedent""" + ====== ====== + Inputs Output + ====== ====== + """.toAst(rstOptions = opt, warnings = warnings) == expected) + check(warnings[] == @[ + "input(2, 2) Warning: RST style: this word crosses table column from the right"]) + test "tables with slightly overflowed cells cause an error (2)": var error = new string check("" == dedent""" @@ -835,7 +1016,7 @@ suite "RST tables": ===== ===== ====== False False False ===== ===== ====== - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(2, 8) Error: Illformed table: " & "this word crosses table column from the right") @@ -847,7 +1028,7 @@ suite "RST tables": ===== ===== ====== False False False ===== ===== ====== - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(2, 7) Error: Illformed table: " & "this word crosses table column from the left") @@ -860,7 +1041,7 @@ suite "RST tables": ===== ====== False False ===== ======= - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(5, 14) Error: Illformed table: " & "end of table column #2 should end at position 13") @@ -872,7 +1053,7 @@ suite "RST tables": ===== ======= False False ===== ====== - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(3, 14) Error: Illformed table: " & "end of table column #2 should end at position 13") @@ -1238,6 +1419,31 @@ suite "RST indentation": rnLeaf 'term3definition2' """) +suite "Markdown indentation": + test "Markdown paragraph indentation": + # Additional spaces (<=3) of indentation does not break the paragraph. + # TODO: in 2nd case de-indentation causes paragraph to break, this is + # reasonable but does not seem to conform the Markdown spec. + check(dedent""" + Start1 + stop1 + + Start2 + stop2 + """.toAst == + dedent""" + rnInner + rnParagraph + rnLeaf 'Start1' + rnLeaf ' ' + rnLeaf 'stop1' + rnParagraph + rnLeaf 'Start2' + rnParagraph + rnLeaf 'stop2' + rnLeaf ' ' + """) + suite "Warnings": test "warnings for broken footnotes/links/substitutions": let input = dedent""" @@ -1776,3 +1982,13 @@ suite "RST inline markup": rnLeaf ')' """) check(warnings[] == @["input(1, 5) Warning: broken link 'f'"]) + +suite "Misc isssues": + test "Markdown CodeblockFields in one line (lacking enclosing ```)": + let message = """ + ```llvm-profdata merge first.profraw second.profraw third.profraw <more stuff maybe> -output data.profdata```""" + + try: + echo rstgen.rstToHtml(message, {roSupportMarkdown}, nil) + except EParseError: + discard diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index b33ee82a8..6253e7146 100644 --- a/tests/stdlib/trstgen.nim +++ b/tests/stdlib/trstgen.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" outputsub: "" """ @@ -617,8 +618,8 @@ context2 This is too short to be a transition: --- - context2 +--- """ var error2 = new string let output2 = input2.toHtml(error=error2) @@ -632,7 +633,7 @@ Test literal block :: check """ - let output1 = input1.toHtml + let output1 = input1.toHtml(preferRst) doAssert "<pre>" in output1 test "Markdown code block": @@ -1127,7 +1128,7 @@ Test1 Paragraph2 ref `internal anchor`_. """ - let output9 = input9.toHtml + let output9 = input9.toHtml(preferRst) # _`internal anchor` got erased: check "href=\"#internal-anchor\"" notin output9 check "href=\"#citation-another\"" in output9 @@ -1155,7 +1156,7 @@ Test1 doAssert "<a href=\"#citation-third\">[Third]</a>" in output10 let input11 = ".. [note]\n" # should not crash - let output11 = input11.toHtml + let output11 = input11.toHtml(preferRst) doAssert "<a href=\"#citation-note\">[note]</a>" in output11 # check that references to auto-numbered footnotes work @@ -1245,7 +1246,7 @@ Test1 "input(8, 4) Warning: language 'anotherLang' not supported" ]) check(output == "<pre class = \"listing\">anything</pre>" & - "<p><pre class = \"listing\">\nsomeCode</pre> </p>") + "<p><pre class = \"listing\">someCode</pre> </p>") test "RST admonitions": # check that all admonitions are implemented @@ -1442,7 +1443,7 @@ Test1 Ref. target103_. """ - let output2 = input2.toHtml + let output2 = input2.toHtml(preferRst) # "target101" should be erased and changed to "section-xyz": doAssert "href=\"#target300\"" notin output2 doAssert "id=\"target300\"" notin output2 @@ -1684,3 +1685,8 @@ suite "local file inclusion": discard "```nim file = ./readme.md\n```".toHtml(error=error) check(error[] == "input(1, 23) Error: disabled directive: 'file'") +proc documentToHtml*(doc: string, isMarkdown: bool = false): string {.gcsafe.} = + var options = {roSupportMarkdown} + if isMarkdown: + options.incl roPreferMarkdown + result = rstToHtml(doc, options, defaultConfig()) diff --git a/tests/stdlib/tsequtils.nim b/tests/stdlib/tsequtils.nim index 176c00214..1094ae233 100644 --- a/tests/stdlib/tsequtils.nim +++ b/tests/stdlib/tsequtils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ @@ -388,6 +389,11 @@ block: # newSeqWith tests seq2D[0][1] = true doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]] +block: # bug #21538 + var x: seq[int] = @[2, 4] + var y = newSeqWith(x.pop(), true) + doAssert y == @[true, true, true, true] + block: # mapLiterals tests let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int) doAssert x is array[4, int] diff --git a/tests/stdlib/tsetutils.nim b/tests/stdlib/tsetutils.nim index 037c696c1..c8498f23e 100644 --- a/tests/stdlib/tsetutils.nim +++ b/tests/stdlib/tsetutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tsha1.nim b/tests/stdlib/tsha1.nim deleted file mode 100644 index c984d97bd..000000000 --- a/tests/stdlib/tsha1.nim +++ /dev/null @@ -1,24 +0,0 @@ -import std/sha1 -import std/assertions - -let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]") -doAssert hash1 == hash1 -doAssert parseSecureHash($hash1) == hash1 - -template checkVector(s, exp: string) = - doAssert secureHash(s) == parseSecureHash(exp) - -checkVector("", "da39a3ee5e6b4b0d3255bfef95601890afd80709") -checkVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d") -checkVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "84983e441c3bd26ebaae4aa1f95129e5e54670f1") - -proc testIsValidSha1Hash = - doAssert not isValidSha1Hash("") - doAssert not isValidSha1Hash("042D4BE2B90ED0672E717D71850ABDB0A2D19CD11") - doAssert not isValidSha1Hash("042G4BE2B90ED0672E717D71850ABDB0A2D19CD1") - doAssert isValidSha1Hash("042D4BE2B90ED0672E717D71850ABDB0A2D19CD1") - doAssert isValidSha1Hash("042d4be2b90ed0672e717d71850abdb0a2d19cd1") - doAssert isValidSha1Hash("042d4be2b90ed0672e717D71850ABDB0A2D19CD1") - -testIsValidSha1Hash() diff --git a/tests/stdlib/tsharedlist.nim b/tests/stdlib/tsharedlist.nim index 0bb3ad827..b91302d19 100644 --- a/tests/stdlib/tsharedlist.nim +++ b/tests/stdlib/tsharedlist.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:orc; --mm:refc" """ import std/sharedlist diff --git a/tests/stdlib/tsharedtable.nim b/tests/stdlib/tsharedtable.nim index 0022f7bb2..10ad5f658 100644 --- a/tests/stdlib/tsharedtable.nim +++ b/tests/stdlib/tsharedtable.nim @@ -1,5 +1,5 @@ discard """ -cmd: "nim $target --threads:on $options $file" +matrix: "--mm:refc; --mm:orc" output: ''' ''' """ diff --git a/tests/stdlib/tsince.nim b/tests/stdlib/tsince.nim index 877a2bcda..a0a4229cb 100644 --- a/tests/stdlib/tsince.nim +++ b/tests/stdlib/tsince.nim @@ -27,7 +27,6 @@ doAssert ok since (99, 3): doAssert false -when false: - # pending bug #15920 - # Error: cannot attach a custom pragma to 'fun3' - template fun3(): int {.since: (1, 3).} = 12 +template fun3(): int {.since: (1, 3).} = 12 + +doAssert declared(fun3) diff --git a/tests/stdlib/tsocketstreams.nim b/tests/stdlib/tsocketstreams.nim index 0cf952810..a37e7c34c 100644 --- a/tests/stdlib/tsocketstreams.nim +++ b/tests/stdlib/tsocketstreams.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: ''' OM NIM diff --git a/tests/stdlib/tsortcall.nim b/tests/stdlib/tsortcall.nim index 242e3fe4c..32e004921 100644 --- a/tests/stdlib/tsortcall.nim +++ b/tests/stdlib/tsortcall.nim @@ -1,5 +1,5 @@ discard """ -outputsub: "" + matrix: "--mm:refc; --mm:orc" """ import algorithm diff --git a/tests/stdlib/tsqlitebindatas.nim b/tests/stdlib/tsqlitebindatas.nim index 80d9df864..e69de29bb 100644 --- a/tests/stdlib/tsqlitebindatas.nim +++ b/tests/stdlib/tsqlitebindatas.nim @@ -1,79 +0,0 @@ -discard """ - action: "run" - exitcode: 0 -""" -import db_sqlite -import random -import os -from stdtest/specialpaths import buildDir -import std/assertions - -block tsqlitebindatas: ## db_sqlite binary data - const dbName = buildDir / "tsqlitebindatas.db" - - let origName = "Bobby" - var orig = newSeq[float64](150) - randomize() - for x in orig.mitems: - x = rand(1.0)/10.0 - - discard tryRemoveFile(dbName) - let db = open(dbName, "", "", "") - let createTableStr = sql"""CREATE TABLE test( - id INTEGER NOT NULL PRIMARY KEY, - name TEXT, - data BLOB - ) - """ - db.exec(createTableStr) - - var dbuf = newSeq[byte](orig.len*sizeof(float64)) - copyMem(addr(dbuf[0]), addr(orig[0]), dbuf.len) - - var insertStmt = db.prepare("INSERT INTO test (id, name, data) VALUES (?, ?, ?)") - insertStmt.bindParams(1, origName, dbuf) - let bres = db.tryExec(insertStmt) - doAssert(bres) - - finalize(insertStmt) - - var nameTest = db.getValue(sql"SELECT name FROM test WHERE id = ?", 1) - doAssert nameTest == origName - - var dataTest = db.getValue(sql"SELECT data FROM test WHERE id = ?", 1) - let seqSize = int(dataTest.len*sizeof(byte)/sizeof(float64)) - var res: seq[float64] = newSeq[float64](seqSize) - copyMem(addr(res[0]), addr(dataTest[0]), dataTest.len) - doAssert res.len == orig.len - doAssert res == orig - - db.close() - doAssert tryRemoveFile(dbName) - - -block: - block: - const dbName = buildDir / "db.sqlite3" - var db = db_sqlite.open(dbName, "", "", "") - var witness = false - try: - db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);")) - db.exec(sql("REPLACE INTO table (url, another_field) VALUES (?, '123');")) - except DbError as e: - witness = true - doAssert e.msg == "The number of \"?\" given exceeds the number of parameters present in the query." - finally: - db.close() - removeFile(dbName) - - doAssert witness - - block: - const dbName = buildDir / "db.sqlite3" - var db = db_sqlite.open(dbName, "", "", "") - try: - db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);")) - db.exec(sql("INSERT INTO table1 (url, other_field) VALUES (?, ?);"), "http://domain.com/test?param=1", 123) - finally: - db.close() - removeFile(dbName) diff --git a/tests/stdlib/tsqlparser.nim b/tests/stdlib/tsqlparser.nim index 11ee22e2b..6f123f21d 100644 --- a/tests/stdlib/tsqlparser.nim +++ b/tests/stdlib/tsqlparser.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''true''' """ diff --git a/tests/stdlib/tssl.nim b/tests/stdlib/tssl.nim index 6d238e6c9..1628b9326 100644 --- a/tests/stdlib/tssl.nim +++ b/tests/stdlib/tssl.nim @@ -1,10 +1,12 @@ discard """ + matrix: "--mm:refc; --mm:orc" joinable: false - disabled: "freebsd" - disabled: "openbsd" + disabled: "freebsd" # see #15713 + disabled: "openbsd" # see #15713 + disabled: "netbsd" # see #15713 """ -# disabled: pending bug #15713 -import std/[net, nativesockets, assertions] + +import std/[net, nativesockets, assertions, typedthreads] when defined(posix): import os, posix else: diff --git a/tests/stdlib/tstaticos.nim b/tests/stdlib/tstaticos.nim new file mode 100644 index 000000000..41ab995dd --- /dev/null +++ b/tests/stdlib/tstaticos.nim @@ -0,0 +1,8 @@ +import std/[assertions, staticos, os] + +block: + static: + doAssert staticDirExists("MISSINGFILE") == false + doAssert staticFileExists("MISSINGDIR") == false + doAssert staticDirExists(currentSourcePath().parentDir) + doAssert staticFileExists(currentSourcePath()) diff --git a/tests/stdlib/tstats.nim b/tests/stdlib/tstats.nim index 3ed013005..728d93d09 100644 --- a/tests/stdlib/tstats.nim +++ b/tests/stdlib/tstats.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/[stats, assertions] import std/math diff --git a/tests/stdlib/tstdlib_issues.nim b/tests/stdlib/tstdlib_issues.nim index 9db319603..b7b806db8 100644 --- a/tests/stdlib/tstdlib_issues.nim +++ b/tests/stdlib/tstdlib_issues.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" output: ''' 02 1 diff --git a/tests/stdlib/tstdlib_various.nim b/tests/stdlib/tstdlib_various.nim index ce9c9a7c5..bac5018fa 100644 --- a/tests/stdlib/tstdlib_various.nim +++ b/tests/stdlib/tstdlib_various.nim @@ -27,7 +27,6 @@ Hi Andreas! How do you feel, Rumpf? [2, 3, 4, 5] [2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6] -true <h1><a href="http://force7.de/nim">Nim</a></h1> ''' """ @@ -207,11 +206,7 @@ block tsplit2: s.add("#") s.add(w) - try: - discard "hello".split("") - echo "false" - except AssertionDefect: - echo "true" + doAssert "true".split("") == @["true"] diff --git a/tests/stdlib/tstrbasics.nim b/tests/stdlib/tstrbasics.nim index 9a624fec3..a965ff15f 100644 --- a/tests/stdlib/tstrbasics.nim +++ b/tests/stdlib/tstrbasics.nim @@ -1,6 +1,6 @@ discard """ targets: "c cpp js" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" """ import std/[strbasics, sugar, assertions] diff --git a/tests/stdlib/tstreams.nim b/tests/stdlib/tstreams.nim index 08441a766..60c63b450 100644 --- a/tests/stdlib/tstreams.nim +++ b/tests/stdlib/tstreams.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" input: "Arne" output: ''' Hello! What is your name? @@ -50,6 +50,12 @@ block tstreams3: echo line s.close + +block: + let fs = newFileStream("amissingfile.txt") + defer: fs.close() + doAssert isNil(fs) + # bug #12410 var a = newStringStream "hehohihahuhyh" @@ -86,6 +92,10 @@ static: # Ensure streams it doesnt break with nimscript on arc/orc #19716 let s = newStringStream("a") doAssert s.data == "a" +static: # issue #24054, readStr + var s = newStringStream("foo bar baz") + doAssert s.readStr(3) == "foo" + template main = var strm = newStringStream("abcde") var buffer = "12345" diff --git a/tests/stdlib/tstrformat.nim b/tests/stdlib/tstrformat.nim index b44a11e68..ff406f898 100644 --- a/tests/stdlib/tstrformat.nim +++ b/tests/stdlib/tstrformat.nim @@ -1,4 +1,6 @@ -# xxx: test js target +discard """ + matrix: "--mm:refc; --mm:orc" +""" import genericstrformat import std/[strformat, strutils, times, tables, json] @@ -475,15 +477,17 @@ proc main() = # Note: times.format adheres to the format protocol. Test that this # works: + when nimvm: + discard + else: + var dt = dateTime(2000, mJan, 01, 00, 00, 00) + check &"{dt:yyyy-MM-dd}", "2000-01-01" - var dt = initDateTime(01, mJan, 2000, 00, 00, 00) - check &"{dt:yyyy-MM-dd}", "2000-01-01" + var tm = fromUnix(0) + discard &"{tm}" - var tm = fromUnix(0) - discard &"{tm}" - - var noww = now() - check &"{noww}", $noww + var noww = now() + check &"{noww}", $noww # Unicode string tests check &"""{"αβγ"}""", "αβγ" @@ -558,5 +562,29 @@ proc main() = doAssert &"""{(if true: "'" & "'" & ')' else: "")}""" == "'')" doAssert &"{(if true: \"\'\" & \"'\" & ')' else: \"\")}" == "'')" doAssert fmt"""{(if true: "'" & ')' else: "")}""" == "')" -# xxx static: main() + + block: # issue #20381 + var ss: seq[string] + template myTemplate(s: string) = + ss.add s + ss.add s + proc foo() = + myTemplate fmt"hello" + foo() + doAssert ss == @["hello", "hello"] + + block: + proc noraises() {.raises: [].} = + const + flt = 0.0 + str = "str" + + doAssert fmt"{flt} {str}" == "0.0 str" + + noraises() + + block: + doAssert not compiles(fmt"{formatting errors detected at compile time") + +static: main() main() diff --git a/tests/stdlib/tstrformatlineinfo.nim b/tests/stdlib/tstrformatlineinfo.nim new file mode 100644 index 000000000..3a7bf0d33 --- /dev/null +++ b/tests/stdlib/tstrformatlineinfo.nim @@ -0,0 +1,8 @@ +# issue #21759 + +{.hint[ConvFromXToItselfNotNeeded]: on.} + +import std/strformat + +echo fmt"{string ""abc""}" #[tt.Hint + ^ conversion from string to itself is pointless]# diff --git a/tests/stdlib/tstrimpl.nim b/tests/stdlib/tstrimpl.nim new file mode 100644 index 000000000..a8933e53f --- /dev/null +++ b/tests/stdlib/tstrimpl.nim @@ -0,0 +1,12 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/private/strimpl + +import std/assertions + +doAssert find(cstring"Hello Nim", cstring"Nim") == 6 +doAssert find(cstring"Hello Nim", cstring"N") == 6 +doAssert find(cstring"Hello Nim", cstring"I") == -1 +doAssert find(cstring"Hello Nim", cstring"O") == -1 diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim index 232211471..b9b3c78a3 100644 --- a/tests/stdlib/tstring.nim +++ b/tests/stdlib/tstring.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--mm:refc" + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ diff --git a/tests/stdlib/tstrmiscs.nim b/tests/stdlib/tstrmiscs.nim index 76b14d27a..b42f2e1fe 100644 --- a/tests/stdlib/tstrmiscs.nim +++ b/tests/stdlib/tstrmiscs.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/strmisc import std/assertions diff --git a/tests/stdlib/tstrscans.nim b/tests/stdlib/tstrscans.nim index e30c86279..ae7fd98ca 100644 --- a/tests/stdlib/tstrscans.nim +++ b/tests/stdlib/tstrscans.nim @@ -1,5 +1,5 @@ discard """ - output: "" + matrix: "--mm:refc; --mm:orc" """ import std/[strscans, strutils, assertions] diff --git a/tests/stdlib/tstrset.nim b/tests/stdlib/tstrset.nim index feae66ff7..bbb6c2677 100644 --- a/tests/stdlib/tstrset.nim +++ b/tests/stdlib/tstrset.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + # test a simple yet highly efficient set of strings type @@ -6,7 +10,7 @@ type TRadixNode {.inheritable.} = object kind: TRadixNodeKind TRadixNodeLinear = object of TRadixNode - len: int8 + len: uint8 keys: array[0..31, char] vals: array[0..31, PRadixNode] TRadixNodeFull = object of TRadixNode @@ -24,7 +28,7 @@ proc search(r: PRadixNode, s: string): PRadixNode = case r.kind of rnLinear: var x = PRadixNodeLinear(r) - for j in 0..ze(x.len)-1: + for j in 0..int(x.len)-1: if x.keys[j] == s[i]: if s[i] == '\0': return r r = x.vals[j] @@ -63,9 +67,9 @@ proc excl*(r: var PRadixNode, s: string) = of rnFull: PRadixNodeFull(x).b['\0'] = nil of rnLinear: var x = PRadixNodeLinear(x) - for i in 0..ze(x.len)-1: + for i in 0..int(x.len)-1: if x.keys[i] == '\0': - swap(x.keys[i], x.keys[ze(x.len)-1]) + swap(x.keys[i], x.keys[int(x.len)-1]) dec(x.len) break diff --git a/tests/stdlib/tstrtabs.nim b/tests/stdlib/tstrtabs.nim index 036287bfd..d261abe76 100644 --- a/tests/stdlib/tstrtabs.nim +++ b/tests/stdlib/tstrtabs.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" sortoutput: true output: ''' key1: value1 diff --git a/tests/stdlib/tstrtabs2.nim b/tests/stdlib/tstrtabs2.nim index f055b5d33..a4030ec77 100644 --- a/tests/stdlib/tstrtabs2.nim +++ b/tests/stdlib/tstrtabs2.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ @@ -14,3 +15,18 @@ block: doAssert t["name"] == "John" m() + +proc fun()= + let ret = newStringTable(modeCaseSensitive) + ret["foo"] = "bar" + + doAssert $ret == "{foo: bar}" + + let b = ret["foo"] + doAssert b == "bar" + +proc main()= + static: fun() + fun() + +main() diff --git a/tests/stdlib/tstrutils.nim b/tests/stdlib/tstrutils.nim index 0e6384d7e..35f6bc669 100644 --- a/tests/stdlib/tstrutils.nim +++ b/tests/stdlib/tstrutils.nim @@ -1,10 +1,11 @@ discard """ - targets: "c cpp js" + matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ import std/strutils from stdtest/testutils import disableVm import std/assertions +import std/private/jsutils # xxx each instance of `disableVm` and `when not defined js:` should eventually be fixed template rejectParse(e) = @@ -52,6 +53,15 @@ template main() = doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "] doAssert s.split(' ', maxsplit = 1) == @["", "this is an example "] doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example "] + # Empty string: + doAssert "".split() == @[""] + doAssert "".split(" ") == @[""] + doAssert "".split({' '}) == @[""] + # Empty separators: + doAssert "".split({}) == @[""] + doAssert "".split("") == @[""] + doAssert s.split({}) == @[s] + doAssert s.split("") == @[s] block: # splitLines let fixture = "a\nb\rc\r\nd" @@ -62,12 +72,21 @@ template main() = block: # rsplit doAssert rsplit("foo bar", seps = Whitespace) == @["foo", "bar"] doAssert rsplit(" foo bar", seps = Whitespace, maxsplit = 1) == @[" foo", "bar"] - doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[ - " foo bar", ""] + doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[" foo bar", ""] doAssert rsplit(":foo:bar", sep = ':') == @["", "foo", "bar"] doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"] doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"] doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"] + # Empty string: + doAssert "".rsplit() == @[""] + doAssert "".rsplit(" ") == @[""] + doAssert "".rsplit({' '}) == @[""] + # Empty separators: + let s = " this is an example " + doAssert "".rsplit({}) == @[""] + doAssert "".rsplit("") == @[""] + doAssert s.rsplit({}) == @[s] + doAssert s.rsplit("") == @[s] block: # splitWhitespace let s = " this is an example " @@ -433,6 +452,9 @@ template main() = x = "1e0" x.trimZeros() doAssert x == "1e0" + x = "1.23" + x.trimZeros() + doAssert x == "1.23" block: # countLines proc assertCountLines(s: string) = doAssert s.countLines == s.splitLines.len @@ -505,8 +527,9 @@ template main() = block: # toHex doAssert(toHex(100i16, 32) == "00000000000000000000000000000064") - doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C") - when not defined js: + whenJsNoBigInt64: discard + do: + doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C") doAssert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF") doAssert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF") doAssert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF") @@ -527,11 +550,12 @@ template main() = doAssert(spaces(0) == "") block: # toBin, toOct - block:# bug #11369 + whenJsNoBigInt64: # bug #11369 + discard + do: var num: int64 = -1 - when not defined js: - doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111" - doAssert num.toOct(24) == "001777777777777777777777" + doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111" + doAssert num.toOct(24) == "001777777777777777777777" block: # replace doAssert "oo".replace("", "abc") == "oo" @@ -655,11 +679,22 @@ template main() = doAssert b == f2 doAssert c == f3 - block: # parseEnum TODO: merge above - type MyEnum = enum enA, enB, enC, enuD, enE - doAssert parseEnum[MyEnum]("enu_D") == enuD + block: + type MyEnum = enum enA, enB, enC, enuD, enE + doAssert parseEnum[MyEnum]("enu_D") == enuD - doAssert parseEnum("invalid enum value", enC) == enC + doAssert parseEnum("invalid enum value", enC) == enC + + block: # issue #22726 + type SomeEnum = enum A, B, C + + proc assignEnum(dest: var enum, s: string) = + type ty = typeof(dest) + dest = parseEnum[ty](s) + + var v: SomeEnum + v.assignEnum("A") + doAssert v == A block: # indentation doAssert 0 == indentation """ @@ -738,7 +773,8 @@ bar block: # formatSize disableVm: - when not defined(js): + whenJsNoBigInt64: discard + do: doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231 doAssert formatSize((2.234*1024*1024).int) == "2.234MiB" doAssert formatSize(4096) == "4KiB" @@ -868,5 +904,10 @@ bar doAssert nimIdentNormalize("Foo_bar") == "Foobar" doAssert nimIdentNormalize("_Foo_bar") == "_foobar" + block: # bug #19500 + doAssert "abc \0 def".find("def") == 6 + doAssert "abc \0 def".find('d') == 6 + + static: main() main() diff --git a/tests/stdlib/tstrutils2.nim b/tests/stdlib/tstrutils2.nim deleted file mode 100644 index 22a935ab8..000000000 --- a/tests/stdlib/tstrutils2.nim +++ /dev/null @@ -1,38 +0,0 @@ -discard """ - matrix: "--gc:refc; --gc:orc" -""" - -import "$lib/.." / compiler/strutils2 -import std/assertions - -block: # setLen - var a = "abc" - a.setLen 0 - a.setLen 3, isInit = false - when defined(gcRefc): # bug #19763 - doAssert a[1] == 'b' - a.setLen 0 - a.setLen 3, isInit = true - doAssert a[1] == '\0' - -block: # forceCopy - var a: string - a = "foo" - shallow(a) - var b: string - b = a - doAssert b[0].addr == a[0].addr - var c: string - c.forceCopy a - doAssert c == a - doAssert c[0].addr != a[0].addr - -block: # toLowerAscii - var a = "fooBAr" - a.toLowerAscii - doAssert a == "foobar" - -block: # dataPointer - var a: string - discard a.dataPointer - # doAssert a.dataPointer == nil # not guaranteed diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim index 9c1213901..2ea96cfbb 100644 --- a/tests/stdlib/tsugar.nim +++ b/tests/stdlib/tsugar.nim @@ -1,11 +1,34 @@ discard """ + targets: "c js" + matrix: "--mm:refc; --mm:orc" output: ''' x + y = 30 ''' """ -import std/[sugar, algorithm, random, sets, tables, strutils] +import std/[sugar, algorithm, random, sets, tables, strutils, sequtils] import std/[syncio, assertions] +type # for capture test, ref #20679 + FooCapture = ref object + x: int + +proc mainProc() = + block: # bug #16967 + var s = newSeq[proc (): int](5) + {.push exportc.} + proc bar() = + for i in 0 ..< s.len: + let foo = i + 1 + capture foo: + s[i] = proc(): int = foo + {.pop.} + + bar() + + for i, p in s.pairs: + let foo = i + 1 + doAssert p() == foo + template main() = block: # `=>` block: @@ -80,21 +103,61 @@ template main() = closure2 = () => (i, j) doAssert closure2() == (5, 3) - block: # bug #16967 - var s = newSeq[proc (): int](5) - {.push exportc.} - proc bar() = - for i in 0 ..< s.len: - let foo = i + 1 - capture foo: - s[i] = proc(): int = foo - {.pop.} + block: # issue #20679 + # this should compile. Previously was broken as `var int` is an `nnkHiddenDeref` + # which was not handled correctly - bar() + block: + var x = 5 + var s1 = newSeq[proc (): int](2) + proc function(data: var int) = + for i in 0 ..< 2: + data = (i+1) * data + capture data: + s1[i] = proc(): int = data + function(x) + doAssert s1[0]() == 5 + doAssert s1[1]() == 10 - for i, p in s.pairs: - let foo = i + 1 - doAssert p() == foo + + block: + var y = @[5, 10] + var s2 = newSeq[proc (): seq[int]](2) + proc functionS(data: var seq[int]) = + for i in 0 ..< 2: + data.add (i+1) * 5 + capture data: + s2[i] = proc(): seq[int] = data + functionS(y) + doAssert s2[0]() == @[5, 10, 5] + doAssert s2[1]() == @[5, 10, 5, 10] + + + template typeT(typ, val: untyped): untyped = + var x = val + var s = newSeq[proc (): typ](2) + + proc functionT[T](data: var T) = + for i in 0 ..< 2: + if i == 1: + data = default(T) + capture data: + s[i] = proc (): T = data + + functionT(x) + doAssert s[0]() == val + doAssert s[1]() == x # == default + doAssert s[1]() == default(typ) + + block: + var x = 1.1 + typeT(float, x) + block: + var x = "hello" + typeT(string, x) + block: + var f = FooCapture(x: 5) + typeT(FooCapture, f) block: # dup block dup_with_field: @@ -209,17 +272,16 @@ template main() = discard collect(newSeq, for i in 1..3: i) foo() -proc mainProc() = block: # dump # symbols in templates are gensym'd let - x = 10 - y = 20 + x {.inject.} = 10 + y {.inject.} = 20 dump(x + y) # x + y = 30 block: # dumpToString template square(x): untyped = x * x - let x = 10 + let x {.inject.} = 10 doAssert dumpToString(square(x)) == "square(x): x * x = 100" let s = dumpToString(doAssert 1+1 == 2) doAssert "failedAssertImpl" in s @@ -227,8 +289,22 @@ proc mainProc() = doAssertRaises(AssertionDefect): doAssert false doAssert "except AssertionDefect" in s2 -static: - main() + block: # bug #20704 + proc test() = + var xs, ys: seq[int] + for i in 0..5: + xs.add(i) + + xs.apply(proc (d: auto) = ys.add(d)) + # ^ can be turned into d => ys.add(d) when we can infer void return type, #16906 + doAssert ys == @[0, 1, 2, 3, 4, 5] + + test() + mainProc() + +when not defined(js): # TODO fixme JS VM + static: + main() + main() -mainProc() diff --git a/tests/stdlib/tsums.nim b/tests/stdlib/tsums.nim index 071e0b303..cf410cddf 100644 --- a/tests/stdlib/tsums.nim +++ b/tests/stdlib/tsums.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/sums from math import pow import std/assertions diff --git a/tests/stdlib/tsysrand.nim b/tests/stdlib/tsysrand.nim index e6b65e70f..7b7a0fc34 100644 --- a/tests/stdlib/tsysrand.nim +++ b/tests/stdlib/tsysrand.nim @@ -1,6 +1,6 @@ discard """ targets: "c cpp js" - matrix: "--experimental:vmopsDanger" + matrix: "--experimental:vmopsDanger; --experimental:vmopsDanger --mm:refc" """ import std/sysrand diff --git a/tests/stdlib/tsystem.nim b/tests/stdlib/tsystem.nim index 1a976f7a2..f634ce0c2 100644 --- a/tests/stdlib/tsystem.nim +++ b/tests/stdlib/tsystem.nim @@ -1,9 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import stdtest/testutils -import std/assertions +import std/[assertions, formatfloat] # TODO: in future work move existing `system` tests here, where they belong @@ -82,24 +83,36 @@ block: X = object a: string b: set[char] + c: int + d: float + e: int64 - var y = X(b: {'a'}) - reset(y) + var x = X(b: {'a'}, e: 10) - doAssert y.b == {} + var y = move x -block: - type - X = object - a: string - b: int - - var y = X(b: 1314) + doAssert x.a == "" + doAssert x.b == {} + doAssert x.c == 0 + doAssert x.d == 0.0 + doAssert x.e == 0 reset(y) - doAssert y.b == 0 + doAssert y.a == "" + doAssert y.b == {} + doAssert y.c == 0 + doAssert y.d == 0.0 + doAssert y.e == 0 + +block: + var x = 2 + var y = move x + doAssert y == 2 + doAssert x == 0 + reset y + doAssert y == 0 block: type @@ -162,3 +175,26 @@ block: reset(y) doAssert y.b == {} +block: # bug #20516 + type Foo = object + x {.bitsize:4.}: uint + y {.bitsize:4.}: uint + + when not defined(js): + let a = create(Foo) + +block: # bug #6549 + when not defined(js): + block: + const v = 18446744073709551615'u64 + + doAssert $v == "18446744073709551615" + doAssert $float32(v) == "1.8446744e+19", $float32(v) + doAssert $float64(v) == "1.8446744073709552e+19", $float64(v) + + block: + let v = 18446744073709551615'u64 + + doAssert $v == "18446744073709551615" + doAssert $float32(v) == "1.8446744e+19" + doAssert $float64(v) == "1.8446744073709552e+19" diff --git a/tests/stdlib/ttables.nim b/tests/stdlib/ttables.nim index ab6502411..c529aff9f 100644 --- a/tests/stdlib/ttables.nim +++ b/tests/stdlib/ttables.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import tables, hashes import std/assertions diff --git a/tests/stdlib/ttasks.nim b/tests/stdlib/ttasks.nim index 4889d49d9..ba65590d9 100644 --- a/tests/stdlib/ttasks.nim +++ b/tests/stdlib/ttasks.nim @@ -505,3 +505,57 @@ block: b.invoke() doAssert called == 36 + + block: + proc returnsSomething(a, b: int): int = a + b + + proc noArgsButReturnsSomething(): string = "abcdef" + + proc testReturnValues() = + let t = toTask returnsSomething(2233, 11) + var res: int + t.invoke(addr res) + doAssert res == 2233+11 + + let tb = toTask noArgsButReturnsSomething() + var resB: string + tb.invoke(addr resB) + doAssert resB == "abcdef" + + testReturnValues() + + +block: # bug #23635 + block: + type + Store = object + run: proc (a: int) {.nimcall, gcsafe.} + + block: + var count = 0 + proc hello(a: int) = + inc count, a + + var store = Store() + store.run = hello + + let b = toTask store.run(13) + b.invoke() + doAssert count == 13 + + block: + type + Store = object + run: proc () {.nimcall, gcsafe.} + + block: + var count = 0 + proc hello() = + inc count, 1 + + var store = Store() + store.run = hello + + let b = toTask store.run() + b.invoke() + doAssert count == 1 diff --git a/tests/stdlib/ttempfiles.nim b/tests/stdlib/ttempfiles.nim index 1159e08ef..352788c42 100644 --- a/tests/stdlib/ttempfiles.nim +++ b/tests/stdlib/ttempfiles.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" joinable: false # not strictly necessary """ diff --git a/tests/stdlib/tthreadpool.nim b/tests/stdlib/tthreadpool.nim index bc574faeb..1947074be 100644 --- a/tests/stdlib/tthreadpool.nim +++ b/tests/stdlib/tthreadpool.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on --gc:arc" + matrix: "--mm:arc; --mm:refc" disabled: "freebsd" output: "42" """ diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index 4f396c735..0f04168dc 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -1,5 +1,5 @@ discard """ - targets: "c js" + matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off -d:nimStringHash2" """ import times, strutils, unittest @@ -11,12 +11,12 @@ when not defined(js): proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} = let offset = hours * 3600 + minutes * 60 + seconds - proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime {.locks: 0.} = + proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime = result.isDst = false result.utcOffset = offset result.time = adjTime + initDuration(seconds = offset) - proc zonedTimeFromTime(time: Time): ZonedTime {.locks: 0.}= + proc zonedTimeFromTime(time: Time): ZonedTime = result.isDst = false result.utcOffset = offset result.time = time @@ -71,7 +71,7 @@ template runTimezoneTests() = "2006-01-12T22:04:05Z", 11) # RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" parseTest("2006-01-12T15:04:05.999999999Z-07:00", - "yyyy-MM-dd'T'HH:mm:ss'.999999999Z'zzz", "2006-01-12T22:04:05Z", 11) + "yyyy-MM-dd'T'HH:mm:ss.'999999999Z'zzz", "2006-01-12T22:04:05Z", 11) for tzFormat in ["z", "zz", "zzz"]: # formatting timezone as 'Z' for UTC parseTest("2001-01-12T22:04:05Z", "yyyy-MM-dd'T'HH:mm:ss" & tzFormat, @@ -742,3 +742,43 @@ block: # ttimes doAssert getWeeksInIsoYear(2014.IsoYear) == 52 doAssert getWeeksInIsoYear(2015.IsoYear) == 53 doAssert getWeeksInIsoYear(2016.IsoYear) == 52 + + block: # parse and generate iso years + # short calendar week with text + parseTest("KW 23 2023", "'KW' VV GGGG", + "2023-06-05T00:00:00Z", 155) + parseTest("KW 5 2023", "'KW' V GGGG", + "2023-01-30T00:00:00Z", 29) + parseTest("KW 05 23 Saturday", "'KW' V GG dddd", + "2023-02-04T00:00:00Z", 34) + parseTest("KW 53 20 Fri", "'KW' VV GG ddd", + "2021-01-01T00:00:00Z", 0) + + parseTestExcp("KW 23", "'KW' VV") # no year + parseTestExcp("KW 23", "'KW' V") # no year + parseTestExcp("KW 23", "'KW' GG") # no week + parseTestExcp("KW 2023", "'KW' GGGG") # no week + + var dt = initDateTime(5, mJan, 2023, 0, 0, 0, utc()) + check dt.format("V") == "1" + check dt.format("VV") == "01" + check dt.format("GG") == "23" + check dt.format("GGGG") == "2023" + check dt.format("dddd 'KW'V GGGG") == "Thursday KW1 2023" + + block: # Can be used inside gcsafe proc + proc test(): DateTime {.gcsafe.} = + result = "1970".parse("yyyy") + doAssert test().year == 1970 + + block: # test FormatLiterals + # since #23861 + block: + let dt = dateTime(2024, mJul, 21, 17, 01, 02, 123_321_123, utc()) + check dt.format("ss.fff") == "02.123" + check dt.format("fff.ffffff") == "123.123321" + block: + let dt = parse("2024.07.21", "yyyy.MM.dd") + check dt.year == 2024 + check dt.month == mJul + check dt.monthday == 21 diff --git a/tests/stdlib/ttypeinfo.nim b/tests/stdlib/ttypeinfo.nim index 5e17c151a..9bbc2e92c 100644 --- a/tests/stdlib/ttypeinfo.nim +++ b/tests/stdlib/ttypeinfo.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/typeinfo import std/assertions @@ -70,3 +74,20 @@ block: doAssert getEnumOrdinal(y, "Hello") == 0 doAssert getEnumOrdinal(y, "hello") == 1 + +block: # bug #23556 + proc test = + var + t: seq[int] + aseq = toAny(t) + + invokeNewSeq(aseq, 0) + + # Got random value only when loop 8 times. + for i in 1 .. 8: + extendSeq(aseq) + + doAssert t == @[0, 0, 0, 0, 0, 0, 0, 0] + + for i in 1 .. 7: + test() diff --git a/tests/stdlib/ttypetraits.nim b/tests/stdlib/ttypetraits.nim index 574204da6..6851b9220 100644 --- a/tests/stdlib/ttypetraits.nim +++ b/tests/stdlib/ttypetraits.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ diff --git a/tests/stdlib/tunicode.nim b/tests/stdlib/tunicode.nim index 2b1cb2385..b9e68b15b 100644 --- a/tests/stdlib/tunicode.nim +++ b/tests/stdlib/tunicode.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/unicode import std/assertions @@ -53,6 +57,7 @@ doAssert isAlpha("r") doAssert isAlpha("α") doAssert isAlpha("ϙ") doAssert isAlpha("ஶ") +doAssert isAlpha("网") doAssert(not isAlpha("$")) doAssert(not isAlpha("")) @@ -62,6 +67,7 @@ doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽") doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") doAssert isAlpha("Јамогујестистаклоитоминештети") doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ") +doAssert isAlpha("编程语言") doAssert(not isAlpha("$Foo✓")) doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞")) diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim index 8aa7f9fad..0442c7863 100644 --- a/tests/stdlib/tunittest.nim +++ b/tests/stdlib/tunittest.nim @@ -19,10 +19,12 @@ discard """ [Suite] test name filtering ''' +matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/[unittest, sequtils, assertions] +from std/unittest {.all.} import matchFilter proc doThings(spuds: var int): int = spuds = 24 diff --git a/tests/stdlib/tunittestpass.nim b/tests/stdlib/tunittestpass.nim index cff37a3b7..d8de277b7 100644 --- a/tests/stdlib/tunittestpass.nim +++ b/tests/stdlib/tunittestpass.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tunixsocket.nim b/tests/stdlib/tunixsocket.nim new file mode 100644 index 000000000..636fd08c6 --- /dev/null +++ b/tests/stdlib/tunixsocket.nim @@ -0,0 +1,35 @@ +import std/[assertions, net, os, osproc] + +# XXX: Make this test run on Windows too when we add support for Unix sockets on Windows +when defined(posix) and not defined(nimNetLite): + const nim = getCurrentCompilerExe() + let + dir = currentSourcePath().parentDir() + serverPath = dir / "unixsockettest" + + let (_, err) = execCmdEx(nim & " c " & quoteShell(dir / "unixsockettest.nim")) + doAssert err == 0 + + let svproc = startProcess(serverPath, workingDir = dir) + doAssert svproc.running() + # Wait for the server to open the socket and listen from it + sleep(400) + + block unixSocketSendRecv: + let + unixSocketPath = dir / "usox" + socket = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_NONE) + + socket.connectUnix(unixSocketPath) + # for a blocking Unix socket this should never fail + socket.send("data sent through the socket\c\l", maxRetries = 0) + var resp: string + socket.readLine(resp) + doAssert resp == "Hello from server" + + socket.send("bye\c\l") + socket.readLine(resp) + doAssert resp == "bye" + socket.close() + + svproc.close() diff --git a/tests/stdlib/turi.nim b/tests/stdlib/turi.nim index 77ba02dd1..9c717c5b1 100644 --- a/tests/stdlib/turi.nim +++ b/tests/stdlib/turi.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tuserlocks.nim b/tests/stdlib/tuserlocks.nim index ba8ea050e..927077120 100644 --- a/tests/stdlib/tuserlocks.nim +++ b/tests/stdlib/tuserlocks.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" """ import std/rlocks diff --git a/tests/stdlib/tvarargs.nim b/tests/stdlib/tvarargs.nim index 3207572b5..2edc26264 100644 --- a/tests/stdlib/tvarargs.nim +++ b/tests/stdlib/tvarargs.nim @@ -1,6 +1,6 @@ discard """ targets: "c js" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" """ import std/assertions diff --git a/tests/stdlib/tvarints.nim b/tests/stdlib/tvarints.nim index bb0d3d37f..f9624ee5b 100644 --- a/tests/stdlib/tvarints.nim +++ b/tests/stdlib/tvarints.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/varints import std/assertions @@ -29,7 +33,7 @@ block: doAssert cast[float64](got) == test block: - var hugeIntArray: array[50, byte] + var hugeIntArray: array[9, byte] var readedInt: uint64 template chk(a) = diff --git a/tests/stdlib/tvmutils.nim b/tests/stdlib/tvmutils.nim index f43557ad8..63804c136 100644 --- a/tests/stdlib/tvmutils.nim +++ b/tests/stdlib/tvmutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" joinable: false nimout: ''' 0 @@ -19,7 +20,6 @@ tvmutils.nim(29, 14) [opcIndCall] vmTrace(false) """ # line 20 (only showing a subset of nimout to avoid making the test rigid) import std/vmutils - proc main() = for i in 0..<7: echo i diff --git a/tests/stdlib/tvolatile.nim b/tests/stdlib/tvolatile.nim new file mode 100644 index 000000000..c097f9723 --- /dev/null +++ b/tests/stdlib/tvolatile.nim @@ -0,0 +1,15 @@ +import std/[volatile, assertions] + +var st: int +var foo: ptr int = addr st +volatileStore(foo, 12) +doAssert volatileLoad(foo) == 12 + +# bug #14623 +proc bar = + var st: int + var foo: ptr int = addr st + volatileStore(foo, 12) + doAssert volatileLoad(foo) == 12 + +bar() diff --git a/tests/stdlib/twchartoutf8.nim b/tests/stdlib/twchartoutf8.nim index add104b07..e437177ac 100644 --- a/tests/stdlib/twchartoutf8.nim +++ b/tests/stdlib/twchartoutf8.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''OK''' """ @@ -10,6 +11,7 @@ import std/[syncio, assertions] when not defined(windows): echo "OK" else: + import std/widestrs {.push gcsafe.} const CP_UTF8 = 65001'i32 diff --git a/tests/stdlib/twith.nim b/tests/stdlib/twith.nim index b2d72bd0c..ceadbe7bf 100644 --- a/tests/stdlib/twith.nim +++ b/tests/stdlib/twith.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/with import std/[assertions, formatfloat] @@ -22,3 +26,19 @@ with f: doAssert f.col == "(2, 3, 4)" doAssert f.pos == "(0.0, 1.0)" doAssert f.name == "bar" + +type + Baz* = object + a*, b*: int + Bar* = object + x*: int + baz*: Baz + +var bar: Bar +with bar: + x = 1 + with baz: + a = 2 + +doAssert bar.x == 1 +doAssert bar.baz.a == 2 diff --git a/tests/stdlib/twordwrap.nim b/tests/stdlib/twordwrap.nim index a08e64cf9..5d49477d3 100644 --- a/tests/stdlib/twordwrap.nim +++ b/tests/stdlib/twordwrap.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/wordwrap import std/assertions diff --git a/tests/stdlib/twrapnils.nim b/tests/stdlib/twrapnils.nim index 5d5c1ab2d..3da230b5e 100644 --- a/tests/stdlib/twrapnils.nim +++ b/tests/stdlib/twrapnils.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/wrapnils from std/options import get, isSome import std/assertions diff --git a/tests/stdlib/twrongstattype.nim b/tests/stdlib/twrongstattype.nim new file mode 100644 index 000000000..4a1fc30c6 --- /dev/null +++ b/tests/stdlib/twrongstattype.nim @@ -0,0 +1,14 @@ +# issue #24076 + +when defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd): + import std/posix + proc uid(x: uint32): Uid = Uid(x) + var y: uint32 + let myUid = geteuid() + discard myUid == uid(y) + proc dev(x: uint32): Dev = Dev(x) + let myDev = 1.Dev + discard myDev == dev(y) + proc nlink(x: uint32): Nlink = Nlink(x) + let myNlink = 1.Nlink + discard myNlink == nlink(y) diff --git a/tests/stdlib/txmltree.nim b/tests/stdlib/txmltree.nim index f6b7c62e8..add12a3fc 100644 --- a/tests/stdlib/txmltree.nim +++ b/tests/stdlib/txmltree.nim @@ -1,4 +1,8 @@ -import std/[xmltree, assertions] +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/[xmltree, assertions, xmlparser] block: @@ -83,3 +87,34 @@ block: x.add newElement("sonTag") x.add newEntity("my entity") doAssert $x == "<myTag>my text<sonTag />&my entity;</myTag>" + +block: # bug #21290 + let x = newXmlTree("foo",[ + newXmlTree("bar",[ + newText("Hola"), + newXmlTree("qux",[ + newXmlTree("plugh",[]) + ]) + ]) + ]) + + let s = $x + doAssert $parseXml(s) == s + doAssert s == """<foo> + <bar>Hola<qux> <plugh /> </qux></bar> +</foo>""" + +block: #21541 + let root = <>root() + root.add <>child(newText("hello")) + root.add <>more(newVerbatimText("hola")) + let s = $root + doAssert s == """<root> + <child>hello</child> + <more>hola</more> +</root>""" + + let temp = newVerbatimText("Hello!") + doAssert temp.text == "Hello!" + temp.text = "Hola!" + doAssert temp.text == "Hola!" diff --git a/tests/stdlib/tyield.nim b/tests/stdlib/tyield.nim index 0cf52999c..f385ddd05 100644 --- a/tests/stdlib/tyield.nim +++ b/tests/stdlib/tyield.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ diff --git a/tests/stdlib/unixsockettest.nim b/tests/stdlib/unixsockettest.nim new file mode 100644 index 000000000..8f95d0808 --- /dev/null +++ b/tests/stdlib/unixsockettest.nim @@ -0,0 +1,26 @@ +import std/[assertions, net, os] + +let unixSocketPath = getCurrentDir() / "usox" + +removeFile(unixSocketPath) + +let socket = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_NONE) +socket.bindUnix(unixSocketPath) +socket.listen() + +var + clientSocket: Socket + data: string + +socket.accept(clientSocket) +clientSocket.readLine(data) +doAssert data == "data sent through the socket" +clientSocket.send("Hello from server\c\l") + +clientSocket.readLine(data) +doAssert data == "bye" +clientSocket.send("bye\c\l") + +clientSocket.close() +socket.close() +removeFile(unixSocketPath) |