diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-02-08 17:18:17 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-02-08 17:18:17 +0100 |
commit | 0841c64a3217594d0d260a0f24616b469447c1b9 (patch) | |
tree | d16995b64b4cd42b7e3d9adf94dd7f7ff57b600c /tests | |
parent | cb9110c43d4ae9c29a0a1e0d54f7735712d4ba62 (diff) | |
parent | 444f2231c9b48c34f9bec2ce6cfa3de5ae2560b1 (diff) | |
download | Nim-0841c64a3217594d0d260a0f24616b469447c1b9.tar.gz |
Merge branch 'devel' into araq-quirky-exceptions
Diffstat (limited to 'tests')
118 files changed, 2019 insertions, 559 deletions
diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim index 2a371b788..b40c8757c 100644 --- a/tests/array/tarray.nim +++ b/tests/array/tarray.nim @@ -18,7 +18,7 @@ paper @[2, 3, 4]321 9.0 4.0 3 -@[(Field0: 1, Field1: 2), (Field0: 3, Field1: 5)] +@[(1, 2), (3, 5)] 2 @["a", "new one", "c"] @[1, 2, 3] @@ -27,6 +27,7 @@ dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajs dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf kgdchlfniambejop fjpmholcibdgeakn +2.0 ''' joinable: false """ @@ -538,3 +539,12 @@ block trelaxedindextyp: proc foo(x: seq[int]; idx: uint64) = echo x[idx] proc foo(x: string|cstring; idx: uint64) = echo x[idx] proc foo(x: openArray[int]; idx: uint64) = echo x[idx] + +block t3899: + # https://github.com/nim-lang/Nim/issues/3899 + type O = object + a: array[1..2,float] + template `[]`(x: O, i: int): float = + x.a[i] + const c = O(a: [1.0,2.0]) + echo c[2] diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim index fcb48a1f5..1e6cf3761 100644 --- a/tests/async/tasyncawait.nim +++ b/tests/async/tasyncawait.nim @@ -1,7 +1,7 @@ discard """ output: "5000" """ -import asyncdispatch, nativesockets, net, strutils, os +import asyncdispatch, asyncnet, nativesockets, net, strutils, os var msgCount = 0 @@ -12,20 +12,22 @@ const var clientCount = 0 proc sendMessages(client: AsyncFD) {.async.} = - for i in 0 .. <messagesToSend: + for i in 0 ..< messagesToSend: await send(client, "Message " & $i & "\c\L") proc launchSwarm(port: Port) {.async.} = - for i in 0 .. <swarmSize: - var sock = newAsyncNativeSocket() + for i in 0 ..< swarmSize: + var sock = createAsyncNativeSocket() await connect(sock, "localhost", port) await sendMessages(sock) closeSocket(sock) proc readMessages(client: AsyncFD) {.async.} = + # wrapping the AsyncFd into a AsyncSocket object + var sockObj = newAsyncSocket(client) while true: - var line = await recvLine(client) + var line = await recvLine(sockObj) if line == "": closeSocket(client) clientCount.inc @@ -37,7 +39,7 @@ proc readMessages(client: AsyncFD) {.async.} = doAssert false proc createServer(port: Port) {.async.} = - var server = newAsyncNativeSocket() + var server = createAsyncNativeSocket() block: var name: Sockaddr_in name.sin_family = toInt(AF_INET).uint16 diff --git a/tests/async/tasyncfilewrite.nim b/tests/async/tasyncfilewrite.nim index 373b93301..3baf2bbc6 100644 --- a/tests/async/tasyncfilewrite.nim +++ b/tests/async/tasyncfilewrite.nim @@ -9,7 +9,6 @@ import os, asyncfile, asyncdispatch const F = "test_async.txt" removeFile(F) -defer: removeFile(F) let f = openAsync(F, fmWrite) var futs = newSeq[Future[void]]() for i in 1..3: @@ -17,4 +16,4 @@ for i in 1..3: waitFor(all(futs)) f.close() echo readFile(F) - +removeFile(F) diff --git a/tests/async/twinasyncrw.nim b/tests/async/twinasyncrw.nim index 64c5d6c26..6763eb5a2 100644 --- a/tests/async/twinasyncrw.nim +++ b/tests/async/twinasyncrw.nim @@ -46,7 +46,7 @@ when defined(windows): success = false it = it.ai_next - dealloc(aiList) + freeAddrInfo(aiList) if not success: retFuture.fail(newException(OSError, osErrorMsg(lastError))) return retFuture diff --git a/tests/bind/tnicerrorforsymchoice.nim b/tests/bind/tnicerrorforsymchoice.nim index f16b323de..684b83239 100644 --- a/tests/bind/tnicerrorforsymchoice.nim +++ b/tests/bind/tnicerrorforsymchoice.nim @@ -1,10 +1,15 @@ discard """ errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe, locks: 0.}>" - line: 18 + line: 23 """ +# Fake ScgiState objects, from now-deprecated scgi module +type + ScgiState* = object of RootObj ## SCGI state object + AsyncScgiState* = object of RootObj ## SCGI state object + #bug #442 -import scgi, sockets, asyncio, strtabs +import asyncnet, strtabs proc handleSCGIRequest[TScgi: ScgiState | AsyncScgiState](s: TScgi) = discard proc handleSCGIRequest(client: AsyncSocket, headers: StringTableRef, diff --git a/tests/ccgbugs/t5701.nim b/tests/ccgbugs/t5701.nim index e69acbf31..ee6e48498 100644 --- a/tests/ccgbugs/t5701.nim +++ b/tests/ccgbugs/t5701.nim @@ -1,7 +1,7 @@ discard """ - output: '''(Field0: 1, Field1: 1) -(Field0: 2, Field1: 2) -(Field0: 3, Field1: 3) + output: '''(1, 1) +(2, 2) +(3, 3) ''' """ diff --git a/tests/ccgbugs/tmangle_field.nim b/tests/ccgbugs/tmangle_field.nim index 9e4012b8b..da2720aaa 100644 --- a/tests/ccgbugs/tmangle_field.nim +++ b/tests/ccgbugs/tmangle_field.nim @@ -3,7 +3,7 @@ discard """ # bug #5404 -import parseopt2 +import parseopt {.emit: """typedef struct { int key; @@ -12,5 +12,5 @@ import parseopt2 type foo* {.importc: "foo", nodecl.} = object key* {.importc: "key".}: cint -for kind, key, value in parseopt2.getopt(): +for kind, key, value in parseopt.getopt(): discard diff --git a/tests/ccgbugs/tsighash_typename_regression.nim b/tests/ccgbugs/tsighash_typename_regression.nim index 6e49bafc3..b93eebd20 100644 --- a/tests/ccgbugs/tsighash_typename_regression.nim +++ b/tests/ccgbugs/tsighash_typename_regression.nim @@ -15,3 +15,18 @@ proc foo[T](t: T) = foo(123) foo("baz") + +# Empty type in template is correctly disambiguated +block: + template foo() = + type M = object + discard + var y = M() + + foo() + + type M = object + x: int + + var x = M(x: 1) + doAssert(x.x == 1) diff --git a/tests/closure/texplicit_dummy_closure.nim b/tests/closure/texplicit_dummy_closure.nim index 9cd8c8ca9..02b9ac7c7 100644 --- a/tests/closure/texplicit_dummy_closure.nim +++ b/tests/closure/texplicit_dummy_closure.nim @@ -1,3 +1,6 @@ +discard """ + disabled: true +""" # This is a regression of the new lambda lifting; detected by Aporia import asyncio, sockets diff --git a/tests/collections/tcollections_to_string.nim b/tests/collections/tcollections_to_string.nim index 0c4f1e91c..686b9916b 100644 --- a/tests/collections/tcollections_to_string.nim +++ b/tests/collections/tcollections_to_string.nim @@ -9,9 +9,9 @@ import lists import critbits # Tests for tuples -doAssert $(1, 2, 3) == "(Field0: 1, Field1: 2, Field2: 3)" -doAssert $("1", "2", "3") == """(Field0: "1", Field1: "2", Field2: "3")""" -doAssert $('1', '2', '3') == """(Field0: '1', Field1: '2', Field2: '3')""" +doAssert $(1, 2, 3) == "(1, 2, 3)" +doAssert $("1", "2", "3") == """("1", "2", "3")""" +doAssert $('1', '2', '3') == """('1', '2', '3')""" # Tests for seqs doAssert $(@[1, 2, 3]) == "@[1, 2, 3]" diff --git a/tests/compiler/nim.cfg b/tests/compiler/nim.cfg new file mode 100644 index 000000000..6f49473aa --- /dev/null +++ b/tests/compiler/nim.cfg @@ -0,0 +1,7 @@ +# note: consider moving tests/compilerapi/ to tests/compiler/ since +# that's more predictable. + +# note: without this, tests may succeed locally but fail on CI (it can succeed +# locally even when compiling via `./bin/nim` because `$HOME/.nimble` is being +# used). +--path:"../../" # so we can `import compiler/foo` in this dir diff --git a/tests/compiler/tasciitables.nim b/tests/compiler/tasciitables.nim new file mode 100644 index 000000000..0a5ee0f05 --- /dev/null +++ b/tests/compiler/tasciitables.nim @@ -0,0 +1,109 @@ +import compiler/unittest_light +import compiler/asciitables + +import strformat + +proc alignTableCustom(s: string, delim = '\t', sep = ","): string = + for cell in parseTableCells(s, delim): + result.add fmt"({cell.row},{cell.col}): " + for i in cell.text.len..<cell.width: + result.add " " + result.add cell.text + if cell.col < cell.ncols-1: + result.add sep + if cell.col == cell.ncols-1 and cell.row < cell.nrows - 1: + result.add '\n' + +proc testAlignTable() = + block: # test with variable width columns + var ret = "" + ret.add "12\t143\tbcdef\n" + ret.add "2\t14394852020\tbcdef\n" + ret.add "45342\t1\tbf\n" + ret.add "45342\t1\tbsadfasdfasfdasdff\n" + ret.add "453232323232342\t1\tbsadfasdfasfdasdff\n" + ret.add "45342\t1\tbf\n" + ret.add "45342\t1\tb afasf a ff\n" + ret.add "4\t1\tbf\n" + + assertEquals alignTable(ret), + """ +12 143 bcdef +2 14394852020 bcdef +45342 1 bf +45342 1 bsadfasdfasfdasdff +453232323232342 1 bsadfasdfasfdasdff +45342 1 bf +45342 1 b afasf a ff +4 1 bf +""" + + assertEquals alignTable(ret, fill = '.', sep = ","), + """ +12.............,143........,bcdef............. +2..............,14394852020,bcdef............. +45342..........,1..........,bf................ +45342..........,1..........,bsadfasdfasfdasdff +453232323232342,1..........,bsadfasdfasfdasdff +45342..........,1..........,bf................ +45342..........,1..........,b afasf a ff...... +4..............,1..........,bf................ +""" + + assertEquals alignTableCustom(ret, sep = " "), + """ +(0,0): 12 (0,1): 143 (0,2): bcdef +(1,0): 2 (1,1): 14394852020 (1,2): bcdef +(2,0): 45342 (2,1): 1 (2,2): bf +(3,0): 45342 (3,1): 1 (3,2): bsadfasdfasfdasdff +(4,0): 453232323232342 (4,1): 1 (4,2): bsadfasdfasfdasdff +(5,0): 45342 (5,1): 1 (5,2): bf +(6,0): 45342 (6,1): 1 (6,2): b afasf a ff +(7,0): 4 (7,1): 1 (7,2): bf +""" + + block: # test with 1 column + var ret = "12\nasdfa\nadf" + assertEquals alignTable(ret), """ +12 +asdfa +adf """ + + block: # test with empty input + var ret = "" + assertEquals alignTable(ret), "" + + block: # test with 1 row + var ret = "abc\tdef" + assertEquals alignTable(ret), """ +abc def""" + + block: # test with 1 row ending in \t + var ret = "abc\tdef\t" + assertEquals alignTable(ret), """ +abc def """ + + block: # test with 1 row starting with \t + var ret = "\tabc\tdef\t" + assertEquals alignTable(ret), """ + abc def """ + + + block: # test with variable number of cols per row + var ret = """ +a1,a2,a3 + +b1 +c1,c2 +,d1 +""" + assertEquals alignTableCustom(ret, delim = ',', sep = ","), + """ +(0,0): a1,(0,1): a2,(0,2): a3 +(1,0): ,(1,1): ,(1,2): +(2,0): b1,(2,1): ,(2,2): +(3,0): c1,(3,1): c2,(3,2): +(4,0): ,(4,1): d1,(4,2): +""" + +testAlignTable() diff --git a/tests/compiler/tunittest_light.nim b/tests/compiler/tunittest_light.nim new file mode 100644 index 000000000..422474002 --- /dev/null +++ b/tests/compiler/tunittest_light.nim @@ -0,0 +1,55 @@ +import compiler/unittest_light + +proc testAssertEquals() = + assertEquals("foo", "foo") + doAssertRaises(AssertionError): + assertEquals("foo", "foo ") + +proc testMismatch() = + assertEquals(1+1, 2*1) + + let a = """ + some test with space at the end of lines + + can be hard to spot differences when diffing in a terminal + without this helper function + +""" + + let b = """ + some test with space at the end of lines + + can be hard to spot differences when diffing in a terminal + without this helper function + +""" + + let output = mismatch(a, b) + let expected = """ + +lhs:{ some test with space at the end of lines \n +\n + can be hard to spot differences when diffing in a terminal \n + without this helper function\n +\n +} +rhs:{ some test with space at the end of lines \n +\n + can be hard to spot differences when diffing in a terminal \n + without this helper function\n +\n +} +lhs.len: 144 rhs.len: 143 +first mismatch index: 110 +lhs[i]: {" "} +rhs[i]: {"\n"} +lhs[0..<i]:{ some test with space at the end of lines \n +\n + can be hard to spot differences when diffing in a terminal }""" + + if output != expected: + echo output + doAssert false + +testMismatch() +testAssertEquals() diff --git a/tests/config.nims b/tests/config.nims new file mode 100644 index 000000000..cd4ee4b08 --- /dev/null +++ b/tests/config.nims @@ -0,0 +1,7 @@ +switch("path", "$nim/testament/lib") # so we can `import stdtest/foo` in this dir + +## prevent common user config settings to interfere with testament expectations +## Indifidual tests can override this if needed to test for these options. +switch("colors", "off") +switch("listFullPaths", "off") +switch("excessiveStackTrace", "off") diff --git a/tests/cpp/t10148.nim b/tests/cpp/t10148.nim new file mode 100644 index 000000000..e8dd3098f --- /dev/null +++ b/tests/cpp/t10148.nim @@ -0,0 +1,29 @@ +discard """ + output: '''Expected successful exit''' + joinable: false +""" + +import os + +proc another_proc: string = + ## trigger many GC allocations + var x = @[""] + for i in 0..100: + x.add $i + result = "not_existent_path" + +proc findlib2: string = + let path = getEnv("MYLIB2_DOES_NOT_EXIST_PATH") + let another_path = another_proc() + GC_fullCollect() + + if path.len > 0 and dirExists(path): + path / "alib_does_not_matter.dll" + elif fileExists(another_path): + another_path + else: + quit("Expected successful exit", 0) + +proc imported_func*(a: cint): cstring {.importc, dynlib: findlib2().} + +echo imported_func(0) diff --git a/tests/cpp/t10241.nim b/tests/cpp/t10241.nim new file mode 100644 index 000000000..21d6a0f4e --- /dev/null +++ b/tests/cpp/t10241.nim @@ -0,0 +1,19 @@ +discard """ + targets: "cpp" + action: "compile" +""" + +type + String* {.importcpp: "std::string", header: "string".} = object + +proc initString*(): String + {.importcpp: "std::string()", header: "string".} + +proc append*(this: var String, str: String): var String + {.importcpp: "append", header: "string", discardable.} + +var + s1 = initString() + s2 = initString() + +s1.append s2 diff --git a/tests/deprecated/tannot.nim b/tests/deprecated/tannot.nim new file mode 100644 index 000000000..d14f6cc23 --- /dev/null +++ b/tests/deprecated/tannot.nim @@ -0,0 +1,9 @@ +discard """ + nimout: '''tannot.nim(9, 1) Warning: efgh; foo1 is deprecated [Deprecated] +tannot.nim(9, 8) Warning: abcd; foo is deprecated [Deprecated] +''' +""" + +let foo* {.deprecated: "abcd".} = 42 +var foo1* {.deprecated: "efgh".} = 42 +foo1 = foo diff --git a/tests/deprecated/tdeprecated.nim b/tests/deprecated/tdeprecated.nim index 920f350cc..ba8d579ad 100644 --- a/tests/deprecated/tdeprecated.nim +++ b/tests/deprecated/tdeprecated.nim @@ -1,8 +1,21 @@ discard """ - nimout: '''tdeprecated.nim(10, 3) Warning: a is deprecated [Deprecated] -tdeprecated.nim(17, 11) Warning: asdf; enum 'Foo' which contains field 'a' is deprecated [Deprecated] + nimout: ''' +tdeprecated.nim(23, 3) Warning: a is deprecated [Deprecated] +tdeprecated.nim(30, 11) Warning: asdf; enum 'Foo' which contains field 'a' is deprecated [Deprecated] +tdeprecated.nim(40, 16) Warning: use fooX instead; fooA is deprecated [Deprecated] +end ''' """ + + + + + + +## line 15 + + + block: var a {.deprecated.}: array[0..11, int] @@ -17,3 +30,13 @@ block t10111: var _ = a +block: # issue #8063 + type + Foo = enum + fooX + + {.deprecated: [fooA: fooX].} + let + foo: Foo = fooA + echo foo + static: echo "end" diff --git a/tests/deprecated/tnoannot.nim b/tests/deprecated/tnoannot.nim deleted file mode 100644 index ac168952e..000000000 --- a/tests/deprecated/tnoannot.nim +++ /dev/null @@ -1,7 +0,0 @@ -discard """ - errormsg: "annotation to deprecated not supported here" - line: 7 -""" - -var foo* {.deprecated.} = 42 -var foo1* {.deprecated: "no".} = 42 diff --git a/tests/destructor/helper.nim b/tests/destructor/helper.nim new file mode 100644 index 000000000..466065747 --- /dev/null +++ b/tests/destructor/helper.nim @@ -0,0 +1,3 @@ +type + MyTestObject*[T] = object + p: ptr T diff --git a/tests/destructor/tdestructor.nim b/tests/destructor/tdestructor.nim index c9f1caf2d..09dce19ab 100644 --- a/tests/destructor/tdestructor.nim +++ b/tests/destructor/tdestructor.nim @@ -7,21 +7,28 @@ mygeneric1 constructed mygeneric1 destroyed ---- mygeneric2 constructed -mygeneric2 destroyed myobj destroyed +mygeneric2 destroyed ---- mygeneric3 constructed mygeneric1 destroyed ---- -mygeneric1 destroyed ----- +mydistinctObj constructed myobj destroyed +mygeneric2 destroyed +------------------ ---- ---- myobj destroyed +mygeneric1 destroyed +myobj destroyed +myobj destroyed +myobj destroyed +--- +myobj destroyed +myobj destroyed +myobj destroyed ''' - cmd: '''nim c --newruntime $file''' - disabled: "true" """ type @@ -29,6 +36,11 @@ type x, y: int p: pointer +proc `=destroy`(o: var TMyObj) = + if o.p != nil: dealloc o.p + echo "myobj destroyed" + +type TMyGeneric1[T] = object x: T @@ -36,37 +48,40 @@ type x: A y: B +proc `=destroy`(o: var TMyGeneric1[int]) = + echo "mygeneric1 destroyed" + +proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) = + echo "mygeneric2 destroyed" + +type TMyGeneric3[A, B, C] = object x: A y: B z: C - TObjKind = enum A, B, C, D + TDistinctObjX = distinct TMyGeneric3[TMyObj, TMyGeneric2[int, int], int] + TDistinctObj = TDistinctObjX + + TObjKind = enum Z, A, B, C, D TCaseObj = object + z: TMyGeneric3[TMyObj, float, int] case kind: TObjKind + of Z: discard of A: x: TMyGeneric1[int] of B, C: y: TMyObj else: case innerKind: TObjKind + of Z: discard of A, B, C: p: TMyGeneric3[int, float, string] of D: q: TMyGeneric3[TMyObj, int, int] r: string -proc `=destroy`(o: var TMyObj) = - if o.p != nil: dealloc o.p - echo "myobj destroyed" - -proc `=destroy`(o: var TMyGeneric1[int]) = - echo "mygeneric1 destroyed" - -proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) = - echo "mygeneric2 destroyed" - proc open: TMyObj = # allow for superfluous () result = (TMyObj(x: 1, y: 2, p: alloc(3))) @@ -95,6 +110,12 @@ proc mygeneric3 = echo "mygeneric3 constructed" +proc mydistinctObj = + var x = TMyGeneric3[TMyObj, TMyGeneric2[int, int], int]( + x: open(), y: TMyGeneric2[int, int](x: 5, y: 15), z: 20) + + echo "mydistinctObj constructed" + echo "----" myobj() @@ -107,9 +128,11 @@ mygeneric2[int](10) echo "----" mygeneric3() +echo "----" +mydistinctObj() + proc caseobj = block: - echo "----" var o1 = TCaseObj(kind: A, x: TMyGeneric1[int](x: 10)) block: @@ -121,10 +144,16 @@ proc caseobj = var o3 = TCaseObj(kind: D, innerKind: B, r: "test", p: TMyGeneric3[int, float, string](x: 10, y: 1.0, z: "test")) - block: - echo "----" - var o4 = TCaseObj(kind: D, innerKind: D, r: "test", - q: TMyGeneric3[TMyObj, int, int](x: open(), y: 1, z: 0)) +echo "------------------" caseobj() +proc caseobj_test_sink: TCaseObj = + # check that lifted sink can destroy case val correctly + result = TCaseObj(kind: D, innerKind: D, r: "test", + q: TMyGeneric3[TMyObj, int, int](x: open(), y: 1, z: 0)) + result = TCaseObj(kind: B, y: open()) + + +echo "---" +discard caseobj_test_sink() \ No newline at end of file diff --git a/tests/destructor/terror_module.nim b/tests/destructor/terror_module.nim new file mode 100644 index 000000000..f3d7c9b26 --- /dev/null +++ b/tests/destructor/terror_module.nim @@ -0,0 +1,20 @@ +discard """ +joinable: false +cmd: "nim check $file" +errormsg: "type bound operation `=deepcopy` can be defined only in the same module with its type (MyTestObject)" +nimout: ''' +terror_module.nim(14, 1) Error: type bound operation `=destroy` can be defined only in the same module with its type (MyTestObject) +terror_module.nim(16, 1) Error: type bound operation `=sink` can be defined only in the same module with its type (MyTestObject) +terror_module.nim(18, 1) Error: type bound operation `=` can be defined only in the same module with its type (MyTestObject) +terror_module.nim(20, 1) Error: type bound operation `=deepcopy` can be defined only in the same module with its type (MyTestObject) +''' +""" +import helper + +proc `=destroy`[T](x: var MyTestObject[T]) = discard + +proc `=sink`[T](x: var MyTestObject[T], y:MyTestObject[T]) = discard + +proc `=`[T](x: var MyTestObject[T], y: MyTestObject[T]) = discard + +proc `=deepcopy`[T](x: ptr MyTestObject[T]): ptr MyTestObject[T] = discard diff --git a/tests/destructor/tmove_objconstr.nim b/tests/destructor/tmove_objconstr.nim index 875f78283..7e2b765fc 100644 --- a/tests/destructor/tmove_objconstr.nim +++ b/tests/destructor/tmove_objconstr.nim @@ -166,3 +166,12 @@ seq4 = var ii = 1 let arr2 = [newMySeq(2, 5.0), if i > 1: newMySeq(3, 1.0) else: newMySeq(0, 0.0)] var seqOfSeq2 = @[newMySeq(2, 5.0), newMySeq(3, 1.0)] + + +## issue #10462 +proc myfuncLoop(x: int): MySeqNonCopyable = + for i in 0..<x: + var cc = newMySeq(i, 5.0) + result = cc + +discard myfuncLoop(3) \ No newline at end of file diff --git a/tests/dir with space/more spaces/mspace.nim b/tests/dir with space/more spaces/mspace.nim new file mode 100644 index 000000000..bc2c90f5e --- /dev/null +++ b/tests/dir with space/more spaces/mspace.nim @@ -0,0 +1 @@ +proc tenTimes*(x: int): int = 10*x diff --git a/tests/dir with space/tspace.nim b/tests/dir with space/tspace.nim index 59237c9a1..87a52c271 100644 --- a/tests/dir with space/tspace.nim +++ b/tests/dir with space/tspace.nim @@ -2,5 +2,9 @@ discard """ output: "Successful" """ # Test for the compiler to be able to compile a Nim file with spaces in the directory name. +# Also test if import of a directory with a space works. +import "more spaces" / mspace + +assert tenTimes(5) == 50 echo("Successful") diff --git a/tests/discard/tneedsdiscard.nim b/tests/discard/tneedsdiscard.nim index 7d2997b3f..d9483947f 100644 --- a/tests/discard/tneedsdiscard.nim +++ b/tests/discard/tneedsdiscard.nim @@ -1,5 +1,5 @@ discard """ - errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded; start of expression here: tneedsdiscard.nim(7, 2)''' + errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded; start of expression here: tneedsdiscard.nim(7, 3)''' line: 10 """ diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim index 767845cb4..8f827110c 100644 --- a/tests/effects/teffects1.nim +++ b/tests/effects/teffects1.nim @@ -1,10 +1,10 @@ discard """ errormsg: "can raise an unlisted exception: ref IOError" - file: "system.nim" + file: "io.nim" """ type - TObj = object {.pure, inheritable.} + TObj {.pure, inheritable.} = object TObjB = object of TObj a, b, c: string diff --git a/tests/effects/teffects7.nim b/tests/effects/teffects7.nim new file mode 100644 index 000000000..1cd144459 --- /dev/null +++ b/tests/effects/teffects7.nim @@ -0,0 +1,14 @@ +discard """ + errormsg: "can raise an unlisted exception: ref FloatingPointError" + line: 10 +""" + +proc foo() {.raises: [].} = + try: + discard + except KeyError: + raise newException(FloatingPointError, "foo") + except Exception: + discard + +foo() diff --git a/tests/effects/teffects8.nim b/tests/effects/teffects8.nim new file mode 100644 index 000000000..fb3c088d6 --- /dev/null +++ b/tests/effects/teffects8.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "can raise an unlisted exception: Exception" + line: 10 +""" + +proc foo() {.raises: [].} = + try: + discard + except ValueError: + raise + +foo() diff --git a/tests/errmsgs/m8794.nim b/tests/errmsgs/m8794.nim new file mode 100644 index 000000000..12e61cf54 --- /dev/null +++ b/tests/errmsgs/m8794.nim @@ -0,0 +1,2 @@ +type Foo3* = object + a1: int diff --git a/tests/errmsgs/t10376.nim b/tests/errmsgs/t10376.nim new file mode 100644 index 000000000..a33d5e40f --- /dev/null +++ b/tests/errmsgs/t10376.nim @@ -0,0 +1,31 @@ +discard """ + errormsg: "finalizer must be a direct reference to a procedure" + line: 29 +""" + +type + A = ref object + +proc my_callback(a: A) {. nimcall .} = + discard + +proc foo(callback: proc(a: A) {. nimcall .}) = + var x1: A + new(x1, proc (x: A) {.nimcall.} = discard) + var x2: A + new(x2, func (x: A) {.nimcall.} = discard) + + var x3: A + proc foo1(a: A) {.nimcall.} = discard + new(x3, foo1) + var x4: A + func foo2(a: A) {.nimcall.} = discard + new(x4, foo2) + + var x5: A + new(x5, my_callback) + + var x6: A + new(x6, callback) + +foo(my_callback) diff --git a/tests/errmsgs/t10594.nim b/tests/errmsgs/t10594.nim new file mode 100644 index 000000000..c9506c542 --- /dev/null +++ b/tests/errmsgs/t10594.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "expression has no address" + line: 7 +""" + +template foo(v: varargs[int]) = unsafeAddr v +foo(1, 2) diff --git a/tests/errmsgs/t8610.nim b/tests/errmsgs/t8610.nim new file mode 100644 index 000000000..dd1a3ed29 --- /dev/null +++ b/tests/errmsgs/t8610.nim @@ -0,0 +1,5 @@ +discard """ + errmsg: "'typedesc' metatype is not valid here; typed '=' instead of ':'?" +""" +## issue #8610 +const Foo = int diff --git a/tests/errmsgs/t8794.nim b/tests/errmsgs/t8794.nim new file mode 100644 index 000000000..22e4014f1 --- /dev/null +++ b/tests/errmsgs/t8794.nim @@ -0,0 +1,39 @@ +discard """ + cmd: "nim check $options $file" + errormsg: "" + nimout: ''' +t8794.nim(39, 27) Error: undeclared field: 'a3' for type m8794.Foo3 [declared in m8794.nim(1, 6)] +''' +""" + + + + + + + + + + + + +## line 20 + +## issue #8794 + +import m8794 + +when false: # pending https://github.com/nim-lang/Nim/pull/10091 add this + type Foo = object + a1: int + + discard Foo().a2 + +type Foo3b = Foo3 +var x2: Foo3b + +proc getFun[T](): T = + var a: T + a + +discard getFun[type(x2)]().a3 diff --git a/tests/errmsgs/t9768.nim b/tests/errmsgs/t9768.nim new file mode 100644 index 000000000..18588c87c --- /dev/null +++ b/tests/errmsgs/t9768.nim @@ -0,0 +1,30 @@ +discard """ + errmsg: "unhandled exception:" + file: "system.nim" + nimout: ''' +stack trace: (most recent call last) +t9768.nim(28, 33) main +t9768.nim(23, 11) foo1 +''' +""" + + + + + + + + + + +## line 20 + +proc foo1(a: int): auto = + doAssert a < 4 + result = a * 2 + +proc main()= + static: + if foo1(1) > 0: discard foo1(foo1(2)) + +main() diff --git a/tests/errmsgs/tinteger_literals.nim b/tests/errmsgs/tinteger_literals.nim new file mode 100644 index 000000000..98c92a227 --- /dev/null +++ b/tests/errmsgs/tinteger_literals.nim @@ -0,0 +1,15 @@ +discard """ +cmd: "nim check $file" +errormsg: "number out of range: '300'u8'" +nimout: ''' +tinteger_literals.nim(12, 9) Error: number out of range: '18446744073709551616'u64' +tinteger_literals.nim(13, 9) Error: number out of range: '9223372036854775808'i64' +tinteger_literals.nim(14, 9) Error: number out of range: '9223372036854775808' +tinteger_literals.nim(15, 9) Error: number out of range: '300'u8' +''' +""" + +discard 18446744073709551616'u64 # high(uint64) + 1 +discard 9223372036854775808'i64 # high(int64) + 1 +discard 9223372036854775808 # high(int64) + 1 +discard 300'u8 \ No newline at end of file diff --git a/tests/errmsgs/tnested_generic_instantiation.nim b/tests/errmsgs/tnested_generic_instantiation.nim index 6aea7cbcc..77353605c 100644 --- a/tests/errmsgs/tnested_generic_instantiation.nim +++ b/tests/errmsgs/tnested_generic_instantiation.nim @@ -17,3 +17,9 @@ converter toWrapped[T](value: T): Wrapped[T] = let result = Plain() discard $result + +proc foo[T2](a: Wrapped[T2]) = + # Error: generic instantiation too nested + discard $a + +foo(result) diff --git a/tests/errmsgs/tnested_generic_instantiation2.nim b/tests/errmsgs/tnested_generic_instantiation2.nim new file mode 100644 index 000000000..d9bba15b0 --- /dev/null +++ b/tests/errmsgs/tnested_generic_instantiation2.nim @@ -0,0 +1,27 @@ +discard """ +errormsg: "generic instantiation too nested" +""" + +#[ +bug #4766 +see also: tnested_generic_instantiation.nim +]# + +proc toString*[T](x: T) = + for name, value in fieldPairs(x): + when compiles(toString(value)): + discard + toString(value) + +type + Plain = ref object + discard + + Wrapped[T] = object + value: T + +converter toWrapped[T](value: T): Wrapped[T] = + Wrapped[T](value: value) + +let result = Plain() +toString(result) diff --git a/tests/errmsgs/tunknown_named_parameter.nim b/tests/errmsgs/tunknown_named_parameter.nim index b6b855136..8a3bcaf03 100644 --- a/tests/errmsgs/tunknown_named_parameter.nim +++ b/tests/errmsgs/tunknown_named_parameter.nim @@ -2,10 +2,6 @@ discard """ cmd: "nim check $file" errormsg: "type mismatch: got <string, set[char], maxsplits: int literal(1)>" nimout: ''' -proc rsplit(s: string; sep: string; maxsplit: int = -1): seq[string] - first type mismatch at position: 2 - required type: string - but expression '{':'}' is of type: set[char] proc rsplit(s: string; sep: char; maxsplit: int = -1): seq[string] first type mismatch at position: 2 required type: char @@ -13,6 +9,10 @@ proc rsplit(s: string; sep: char; maxsplit: int = -1): seq[string] proc rsplit(s: string; seps: set[char] = Whitespace; maxsplit: int = -1): seq[string] first type mismatch at position: 3 unknown named parameter: maxsplits +proc rsplit(s: string; sep: string; maxsplit: int = -1): seq[string] + first type mismatch at position: 2 + required type: string + but expression '{':'}' is of type: set[char] expression: rsplit("abc:def", {':'}, maxsplits = 1) ''' diff --git a/tests/exception/t9657.nim b/tests/exception/t9657.nim index 5d5164f4f..c96a0a597 100644 --- a/tests/exception/t9657.nim +++ b/tests/exception/t9657.nim @@ -1,6 +1,8 @@ discard """ action: run exitcode: 1 + target: "c" """ +# todo: remove `target: "c"` workaround once #10343 is properly fixed close stdmsg writeLine stdmsg, "exception!" diff --git a/tests/exception/tdefer1.nim b/tests/exception/tdefer1.nim index b84ba7681..db46bad27 100644 --- a/tests/exception/tdefer1.nim +++ b/tests/exception/tdefer1.nim @@ -1,6 +1,5 @@ discard """ output: '''hi -hi 1 hi 2 @@ -10,13 +9,6 @@ A''' # bug #1742 -template test(): untyped = - let a = 0 - defer: echo "hi" - a - -let i = test() - import strutils let x = try: parseInt("133a") except: -1 @@ -31,7 +23,7 @@ template atFuncEnd = template testB(): untyped = let a = 0 - defer: echo "hi" # Delete this line to make it work + defer: echo "hi" a proc main = diff --git a/tests/exception/texceptions.nim b/tests/exception/texceptions.nim index b30b3874b..7bce32837 100644 --- a/tests/exception/texceptions.nim +++ b/tests/exception/texceptions.nim @@ -64,3 +64,64 @@ proc return_in_except = try: return_in_except() except: echo "RECOVER" +block: #10417 + proc moo() {.noreturn.} = discard + + let bar = + try: + 1 + except: + moo() + + doAssert(bar == 1) + +# Make sure the VM handles the exceptions correctly +block: + proc fun1(): seq[int] = + try: + try: + raise newException(ValueError, "xx") + except: + doAssert("xx" == getCurrentExceptionMsg()) + raise newException(KeyError, "yy") + except: + doAssert("yy" == getCurrentExceptionMsg()) + result.add(1212) + try: + try: + raise newException(AssertionError, "a") + finally: + result.add(42) + except AssertionError: + result.add(99) + finally: + result.add(10) + result.add(4) + result.add(0) + try: + result.add(1) + except KeyError: + result.add(-1) + except ValueError: + result.add(-1) + except IndexError: + result.add(2) + except: + result.add(3) + + try: + try: + result.add(1) + return + except: + result.add(-1) + finally: + result.add(2) + except KeyError: + doAssert(false) + finally: + result.add(3) + + let x1 = fun1() + const x2 = fun1() + doAssert(x1 == x2) diff --git a/tests/float/tfloatnan.nim b/tests/float/tfloatnan.nim index 29937a862..8f384c3d9 100644 --- a/tests/float/tfloatnan.nim +++ b/tests/float/tfloatnan.nim @@ -14,3 +14,31 @@ echo "Nim: ", f32, " (float)" let f64: float64 = NaN echo "Nim: ", f64, " (double)" + +block: # issue #10305 + # with `-O3 -ffast-math`, generated C/C++ code is not nan compliant + # user can pass `--passC:-ffast-math` if he doesn't care. + proc fun() = + # this was previously failing at compile time with a nim compiler + # that was compiled with `nim cpp -d:release` + let a1 = 0.0 + let a = 0.0/a1 + let b1 = a == 0.0 + let b2 = a == a + doAssert not b1 + doAssert not b2 + + proc fun2(i: int) = + # this was previously failing simply with `nim cpp -d:release`; the + # difference with above example is that optimization (const folding) can't + # take place in this example to hide the non-compliant nan bug. + let a = 0.0/(i.float) + let b1 = a == 0.0 + let b2 = a == a + doAssert not b1 + doAssert not b2 + + static: fun() + fun() + fun2(0) + diff --git a/tests/gc/gcbench.nim b/tests/gc/gcbench.nim index 782daf793..fc5d6864f 100644 --- a/tests/gc/gcbench.nim +++ b/tests/gc/gcbench.nim @@ -65,55 +65,58 @@ proc newNode(L, r: PNode): PNode = const kStretchTreeDepth = 18 # about 16Mb kLongLivedTreeDepth = 16 # about 4Mb - kArraySize = 500000 # about 4Mb + kArraySize = 500000 # about 4Mb kMinTreeDepth = 4 kMaxTreeDepth = 16 +when not declared(withScratchRegion): + template withScratchRegion(body: untyped) = body + # Nodes used by a tree of a given size -proc TreeSize(i: int): int = return ((1 shl (i + 1)) - 1) +proc treeSize(i: int): int = return ((1 shl (i + 1)) - 1) # Number of iterations to use for a given tree depth -proc NumIters(i: int): int = - return 2 * TreeSize(kStretchTreeDepth) div TreeSize(i) +proc numIters(i: int): int = + return 2 * treeSize(kStretchTreeDepth) div treeSize(i) # Build tree top down, assigning to older objects. -proc Populate(iDepth: int, thisNode: PNode) = +proc populate(iDepth: int, thisNode: PNode) = if iDepth <= 0: return else: new(thisNode.left) new(thisNode.right) - Populate(iDepth-1, thisNode.left) - Populate(iDepth-1, thisNode.right) + populate(iDepth-1, thisNode.left) + populate(iDepth-1, thisNode.right) # Build tree bottom-up -proc MakeTree(iDepth: int): PNode = +proc makeTree(iDepth: int): PNode = if iDepth <= 0: new(result) else: - return newNode(MakeTree(iDepth-1), MakeTree(iDepth-1)) + return newNode(makeTree(iDepth-1), makeTree(iDepth-1)) -proc PrintDiagnostics() = +proc printDiagnostics() = echo("Total memory available: " & $getTotalMem() & " bytes") echo("Free memory: " & $getFreeMem() & " bytes") -proc TimeConstruction(depth: int) = +proc timeConstruction(depth: int) = var root, tempTree: PNode iNumIters: int - iNumIters = NumIters(depth) + iNumIters = numIters(depth) echo("Creating " & $iNumIters & " trees of depth " & $depth) var t = epochTime() for i in 0..iNumIters-1: new(tempTree) - Populate(depth, tempTree) + populate(depth, tempTree) tempTree = nil echo("\tTop down construction took " & $(epochTime() - t) & "msecs") t = epochTime() for i in 0..iNumIters-1: - tempTree = MakeTree(depth) + tempTree = makeTree(depth) tempTree = nil echo("\tBottom up construction took " & $(epochTime() - t) & "msecs") @@ -127,39 +130,42 @@ proc main() = echo("Garbage Collector Test") echo(" Stretching memory with a binary tree of depth " & $kStretchTreeDepth) - PrintDiagnostics() + printDiagnostics() var t = epochTime() # Stretch the memory space quickly - tempTree = MakeTree(kStretchTreeDepth) - tempTree = nil + withScratchRegion: + tempTree = makeTree(kStretchTreeDepth) + tempTree = nil # Create a long lived object echo(" Creating a long-lived binary tree of depth " & $kLongLivedTreeDepth) new(longLivedTree) - Populate(kLongLivedTreeDepth, longLivedTree) + populate(kLongLivedTreeDepth, longLivedTree) # Create long-lived array, filling half of it echo(" Creating a long-lived array of " & $kArraySize & " doubles") - newSeq(myarray, kArraySize) - for i in 0..kArraySize div 2 - 1: - myarray[i] = 1.0 / toFloat(i) + withScratchRegion: + newSeq(myarray, kArraySize) + for i in 0..kArraySize div 2 - 1: + myarray[i] = 1.0 / toFloat(i) - PrintDiagnostics() + printDiagnostics() - var d = kMinTreeDepth - while d <= kMaxTreeDepth: - TimeConstruction(d) - inc(d, 2) + var d = kMinTreeDepth + while d <= kMaxTreeDepth: + withScratchRegion: + timeConstruction(d) + inc(d, 2) - if longLivedTree == nil or myarray[1000] != 1.0/1000.0: - echo("Failed") - # fake reference to LongLivedTree - # and array to keep them from being optimized away + if longLivedTree == nil or myarray[1000] != 1.0/1000.0: + echo("Failed") + # fake reference to LongLivedTree + # and array to keep them from being optimized away var elapsed = epochTime() - t - PrintDiagnostics() + printDiagnostics() echo("Completed in " & $elapsed & "ms. Success!") when defined(GC_setMaxPause): diff --git a/tests/gc/gcleak.nim b/tests/gc/gcleak.nim index 24ac1036a..0b2e6e14d 100644 --- a/tests/gc/gcleak.nim +++ b/tests/gc/gcleak.nim @@ -12,7 +12,7 @@ type proc makeObj(): TTestObj = result.x = "Hello" -for i in 1 .. 1_000_000: +for i in 1 .. 100_000: when defined(gcMarkAndSweep) or defined(boehmgc): GC_fullcollect() var obj = makeObj() diff --git a/tests/gc/thavlak.nim b/tests/gc/thavlak.nim index 09c07785e..2d8df7c1a 100644 --- a/tests/gc/thavlak.nim +++ b/tests/gc/thavlak.nim @@ -12,9 +12,10 @@ Found 1 loops (including artificial root node) (5)''' # bug #3184 -import tables -import sequtils -import sets +import tables, sequtils, sets, strutils + +when not declared(withScratchRegion): + template withScratchRegion(body: untyped) = body type BasicBlock = object @@ -418,8 +419,9 @@ proc run(self: var LoopTesterApp) = echo "15000 dummy loops" for i in 1..15000: - var h = newHavlakLoopFinder(self.cfg, newLsg()) - var res = h.findLoops + withScratchRegion: + var h = newHavlakLoopFinder(self.cfg, newLsg()) + var res = h.findLoops echo "Constructing CFG..." var n = 2 @@ -446,12 +448,17 @@ proc run(self: var LoopTesterApp) = var sum = 0 for i in 1..5: - write stdout, "." - flushFile(stdout) - var hlf = newHavlakLoopFinder(self.cfg, newLsg()) - sum += hlf.findLoops - #echo getOccupiedMem() + withScratchRegion: + write stdout, "." + flushFile(stdout) + var hlf = newHavlakLoopFinder(self.cfg, newLsg()) + sum += hlf.findLoops + #echo getOccupiedMem() echo "\nFound ", loops, " loops (including artificial root node) (", sum, ")" + when false: + echo("Total memory available: " & formatSize(getTotalMem()) & " bytes") + echo("Free memory: " & formatSize(getFreeMem()) & " bytes") + var l = newLoopTesterApp() l.run diff --git a/tests/gc/tlists.nim b/tests/gc/tlists.nim index 26b32396c..959cc5f7c 100644 --- a/tests/gc/tlists.nim +++ b/tests/gc/tlists.nim @@ -10,15 +10,13 @@ import lists import strutils proc mkleak() = - # allocate 10 MB via linked lists + # allocate 1 MB via linked lists let numberOfLists = 100 for i in countUp(1, numberOfLists): var leakList = initDoublyLinkedList[string]() - let numberOfLeaks = 50000 + let numberOfLeaks = 5000 for j in countUp(1, numberOfLeaks): - let leakSize = 200 - let leaked = newString(leakSize) - leakList.append(leaked) + leakList.append(newString(200)) proc mkManyLeaks() = for i in 0..0: @@ -29,7 +27,7 @@ proc mkManyLeaks() = # lists and bring the memory usage down to a few MB's. GC_fullCollect() when false: echo getOccupiedMem() - if getOccupiedMem() > 8 * 200 * 50_000 * 2: + if getOccupiedMem() > 8 * 200 * 5000 * 2: echo GC_getStatistics() quit "leaking" echo "Success" diff --git a/tests/generics/treentranttypes.nim b/tests/generics/treentranttypes.nim index 2ef049ce2..31fa25293 100644 --- a/tests/generics/treentranttypes.nim +++ b/tests/generics/treentranttypes.nim @@ -1,6 +1,6 @@ discard """ output: ''' -(Field0: 10, Field1: (Field0: "test", Field1: 1.2)) +(10, ("test", 1.2)) 3x3 Matrix [[0.0, 2.0, 3.0], [2.0, 0.0, 5.0], [2.0, 0.0, 5.0]] 2x3 Matrix [[0.0, 2.0, 3.0], [2.0, 0.0, 5.0]] diff --git a/tests/generics/tsubclassgenericerror.nim b/tests/generics/tsubclassgenericerror.nim new file mode 100644 index 000000000..87f8a8e64 --- /dev/null +++ b/tests/generics/tsubclassgenericerror.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "cannot instantiate 'GenericParentType[T]' inside of type definition: 'GenericChildType'; Maybe generic arguments are missing?" + line: 8 +""" + +type + GenericParentType[T] = ref object of RootObj + GenericChildType[T] = ref object of GenericParentType # missing the [T] + val: T + +var instance : GenericChildType[int] = nil diff --git a/tests/generics/twrong_generic_object.nim b/tests/generics/twrong_generic_object.nim index 00d90c55e..442b89ea1 100644 --- a/tests/generics/twrong_generic_object.nim +++ b/tests/generics/twrong_generic_object.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "cannot instantiate: 'GenericNodeObj'" + errormsg: "cannot instantiate: 'GenericNodeObj[T]'; Maybe generic arguments are missing?" line: 21 """ # bug #2509 diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim index 701f652df..4469fdcf5 100644 --- a/tests/iter/titervaropenarray.nim +++ b/tests/iter/titervaropenarray.nim @@ -1,5 +1,6 @@ discard """ output: "123" + targets: "C" """ # Try to break the transformation pass: iterator iterAndZero(a: var openArray[int]): int = diff --git a/tests/js/t9410.nim b/tests/js/t9410.nim index 9aca6d45b..78c329a24 100644 --- a/tests/js/t9410.nim +++ b/tests/js/t9410.nim @@ -1,13 +1,3 @@ -template doAssert(exp: untyped) = - when defined(echot9410): - let r = exp - echo $(instantiationInfo().line) & ":\n " & astToStr(exp) & "\n was " & repr(r) - when not defined(noassertt9410): - system.doAssert r - else: - when not defined(noassertt9410): - system.doAssert exp - template tests = block: var i = 0 @@ -428,6 +418,33 @@ template tests = let xptr2 = cast[type(xptr)](p2) doAssert xptr == xptr2 + + block: # var types + block t10202: + type Point = object + x: float + y: float + + var points: seq[Point] + + points.add(Point(x:1, y:2)) + + for i, p in points.mpairs: + p.x += 1 + + doAssert points[0].x == 2 + + block: + var ints = @[1, 2, 3] + for i, val in mpairs ints: + val *= 10 + doAssert ints == @[10, 20, 30] + + block: + var seqOfSeqs = @[@[1, 2], @[3, 4]] + for i, val in mpairs seqOfSeqs: + val[0] *= 10 + doAssert seqOfSeqs == @[@[10, 2], @[30, 4]] when false: block: # openarray diff --git a/tests/js/test2.nim b/tests/js/test2.nim index 0bfb99139..9ecdbb35c 100644 --- a/tests/js/test2.nim +++ b/tests/js/test2.nim @@ -9,6 +9,9 @@ js 3.14 # This file tests the JavaScript generator +doAssert getCurrentException() == nil +doAssert getCurrentExceptionMsg() == "" + # #335 proc foo() = var bar = "foo" diff --git a/tests/macros/t8997.nim b/tests/macros/t8997.nim new file mode 100644 index 000000000..b06223717 --- /dev/null +++ b/tests/macros/t8997.nim @@ -0,0 +1,26 @@ +discard """ + errormsg: "illformed AST: " + line: 24 +""" + +import macros + +type + Node* = ref object + children: seq[Node] + +proc newNode*(): Node = + Node(children: newSeq[Node]()) + +macro build*(body: untyped): untyped = + + template appendElement(tmp, childrenBlock) {.dirty.} = + bind newNode + let tmp = newNode() + tmp.children = childrenBlock # this line seems to be the problem + + let tmp = genSym(nskLet, "tmp") + let childrenBlock = newEmptyNode() + result = getAst(appendElement(tmp, childrenBlock)) + +build(body) diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim index 734503e6b..b4d708240 100644 --- a/tests/macros/tmacrotypes.nim +++ b/tests/macros/tmacrotypes.nim @@ -23,3 +23,18 @@ checkType(voidProc(), "void") checkType(intProc(10, 20.0), "int") checkType(voidProc, "procTy") checkProcType(voidProc) + +# bug #10548 +block: + var c {.compileTime.} = 0 + + macro meshImpl(arg: typed): untyped = + inc c + result = arg + + type + Blub = int32 + Mesh = meshImpl(Club) + Club = Blub + + static: doAssert(c == 1) diff --git a/tests/macros/tquotedo.nim b/tests/macros/tquotedo.nim index cd1f69116..6acb8ef4e 100644 --- a/tests/macros/tquotedo.nim +++ b/tests/macros/tquotedo.nim @@ -3,6 +3,8 @@ output: ''' 123 Hallo Welt Hallo Welt +1 +() ''' """ @@ -23,3 +25,27 @@ macro foobar(arg: untyped): untyped = foobar: echo "Hallo Welt" + +# bug #3744 +import macros +macro t(): untyped = + return quote do: + proc tp(): int = + result = 1 +t() + +echo tp() + + +# https://github.com/nim-lang/Nim/issues/9866 +type + # Foo = int # works + Foo = object # fails + +macro dispatchGen(): untyped = + var shOpt: Foo + result = quote do: + let baz = `shOpt` + echo `shOpt` + +dispatchGen() diff --git a/tests/macros/tvarargsuntyped.nim b/tests/macros/tvarargsuntyped.nim index 657ed47d6..5a06adcca 100644 --- a/tests/macros/tvarargsuntyped.nim +++ b/tests/macros/tvarargsuntyped.nim @@ -3,7 +3,9 @@ discard """ (left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8) (left: 2, r: 7, x: 8, height: 4, s: text, width: 3, y: 9, top: 1, g: 7, b: 8) (left: 2, r: 7, x: 8, height: 4, s: text, width: 3, y: 9, top: 4, g: 7, b: 8) -(left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8)''' +(left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8) +10 +hello 18.0''' """ import macros @@ -78,3 +80,29 @@ let width: cint = 3 let height: cint = 4 bar(rect(top, left, width, height), "test", point(8, 9), color(7,7,8)) + + +# bug #10075 + +import macros + +proc convert_hidden_stdconv(args: NimNode): NimNode = + var n = args + while n.len == 1 and n[0].kind == nnkHiddenStdConv: + n = n[0][1] + return n + +macro t2(s: int, v: varargs[untyped]): untyped = + let v = convert_hidden_stdconv(v) + echo v.treeRepr + let (v1, v2) = (v[0], v[1]) + quote do: + echo `v1`, " ", `v2` + +template t1(s: int, v: varargs[typed]) = + #static: + # dumpTree v + echo s + t2(s, v) + +t1(10, "hello", 18.0) diff --git a/tests/manyloc/keineschweine/enet_server/enet_server.nim b/tests/manyloc/keineschweine/enet_server/enet_server.nim index 3bb259386..336e57755 100644 --- a/tests/manyloc/keineschweine/enet_server/enet_server.nim +++ b/tests/manyloc/keineschweine/enet_server/enet_server.nim @@ -103,7 +103,7 @@ handlers[HZoneJoinReq] = proc(client: PClient; buffer: PBuffer) = when true: - import parseopt, matchers, os, json + import parseopt, os, json if enetInit() != 0: diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim index 9a5aa5496..0727c699a 100644 --- a/tests/manyloc/keineschweine/lib/sg_packets.nim +++ b/tests/manyloc/keineschweine/lib/sg_packets.nim @@ -1,4 +1,4 @@ -import genpacket_enet, sockets, md5, enet +import genpacket_enet, nativesockets, net, md5, enet defPacketImports() type diff --git a/tests/manyloc/keineschweine/server/old_dirserver.nim b/tests/manyloc/keineschweine/server/old_dirserver.nim index cfb0b0377..390b738aa 100644 --- a/tests/manyloc/keineschweine/server/old_dirserver.nim +++ b/tests/manyloc/keineschweine/server/old_dirserver.nim @@ -157,7 +157,7 @@ proc poll*(timeout: int = 250) = c.outputBuf.flush() when true: - import parseopt, matchers, strutils + import parseopt, strutils var cfgFile = "dirserver_settings.json" for kind, key, val in getOpt(): case kind diff --git a/tests/manyloc/keineschweine/server/old_sg_server.nim b/tests/manyloc/keineschweine/server/old_sg_server.nim index d046df9dd..473880e2b 100644 --- a/tests/manyloc/keineschweine/server/old_sg_server.nim +++ b/tests/manyloc/keineschweine/server/old_sg_server.nim @@ -142,7 +142,7 @@ proc poll*(timeout: int = 250) = c.outputBuf.flush() when true: - import parseopt, matchers, strutils + import parseopt, strutils var zoneCfgFile = "./server_settings.json" for kind, key, val in getOpt(): case kind diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim index 3e8609169..35ed3cbb0 100644 --- a/tests/manyloc/nake/nakefile.nim +++ b/tests/manyloc/nake/nakefile.nim @@ -76,13 +76,14 @@ task "testskel", "create skeleton test dir for testing": task "clean", "cleanup generated files": var dirs = @["nimcache", "server"/"nimcache"] - dirs.map(proc(x: var string) = + dirs.apply(proc(x: var string) = if existsDir(x): removeDir(x)) task "download", "download game assets": var skipAssets = false path = expandFilename("data") + client = newHttpClient() path.add DirSep path.add(extractFilename(GameAssets)) if existsFile(path): @@ -101,7 +102,7 @@ task "download", "download game assets": echo "Downloading from ", GameAssets if not skipAssets: echo "Downloading to ", path - downloadFile GameAssets, path + client.downloadFile(GameAssets, path) echo "Download finished" let targetDir = parentDir(parentDir(path)) @@ -126,7 +127,7 @@ task "download", "download game assets": else: return path = extractFilename(BinLibs) - downloadFile BinLibs, path + client.downloadFile(BinLibs, path) echo "Downloaded dem libs ", path when true: echo "Unpack it yourself, sorry." else: ## this crashes, dunno why diff --git a/tests/metatype/tmetatype_issues.nim b/tests/metatype/tmetatype_issues.nim index c5040f9ba..c184689a1 100644 --- a/tests/metatype/tmetatype_issues.nim +++ b/tests/metatype/tmetatype_issues.nim @@ -1,7 +1,7 @@ discard """ output:''' void -(Field0: "string", Field1: "string") +("string", "string") 1 mod 7 @[2, 2, 2, 2, 2] impl 2 called @@ -9,6 +9,7 @@ asd Foo Bar ''' +joinable: false """ import typetraits, macros diff --git a/tests/metatype/ttypetraits2.nim b/tests/metatype/ttypetraits2.nim index de80e10b1..a436da7ec 100644 --- a/tests/metatype/ttypetraits2.nim +++ b/tests/metatype/ttypetraits2.nim @@ -1,3 +1,18 @@ # todo: merge with $nimc_D/tests/metatype/ttypetraits.nim (currently disabled) from typetraits import `$` # checks fix for https://github.com/c-blake/cligen/issues/84 + +import typetraits + +block: # isNamedTuple + type Foo1 = (a:1,).type + type Foo2 = (Field0:1,).type + type Foo3 = ().type + type Foo4 = object + + doAssert (a:1,).type.isNamedTuple + doAssert Foo1.isNamedTuple + doAssert Foo2.isNamedTuple + doAssert not Foo3.isNamedTuple + doAssert not Foo4.isNamedTuple + doAssert not (1,).type.isNamedTuple diff --git a/tests/method/tmapper.nim b/tests/method/tmapper.nim index a5d03f700..9162d0eec 100644 --- a/tests/method/tmapper.nim +++ b/tests/method/tmapper.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "invalid declaration order; cannot attach 'step' to method defined here: tmapper.nim(22, 7)" + errormsg: "invalid declaration order; cannot attach 'step' to method defined here: tmapper.nim(22, 8)" line: 25 """ diff --git a/tests/misc/tdefine.nim b/tests/misc/tdefine.nim new file mode 100644 index 000000000..1378b8901 --- /dev/null +++ b/tests/misc/tdefine.nim @@ -0,0 +1,18 @@ +discard """ +joinable: false +cmd: "nim c -d:booldef -d:booldef2=false -d:intdef=2 -d:strdef=foobar -r $file" +""" + +const booldef {.booldefine.} = false +const booldef2 {.booldefine.} = true +const intdef {.intdefine.} = 0 +const strdef {.strdefine.} = "" + +doAssert defined(booldef) +doAssert defined(booldef2) +doAssert defined(intdef) +doAssert defined(strdef) +doAssert booldef +doAssert not booldef2 +doAssert intdef == 2 +doAssert strdef == "foobar" diff --git a/tests/misc/tinvalidarrayaccess.nim b/tests/misc/tinvalidarrayaccess.nim index 57ad38b85..ab44d98e8 100644 --- a/tests/misc/tinvalidarrayaccess.nim +++ b/tests/misc/tinvalidarrayaccess.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "index out of bounds: (a:0) <= (i:2) <= (b:1) " + errormsg: "index out of bounds: (a: 0) <= (i: 2) <= (b: 1) " line: 18 """ diff --git a/tests/misc/tinvalidarrayaccess2.nim b/tests/misc/tinvalidarrayaccess2.nim index 86d349457..a791dc4e7 100644 --- a/tests/misc/tinvalidarrayaccess2.nim +++ b/tests/misc/tinvalidarrayaccess2.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "index out of bounds: (a:0) <= (i:3) <= (b:1) " + errormsg: "index out of bounds: (a: 0) <= (i: 3) <= (b: 1) " line: 9 """ diff --git a/tests/misc/tparseopt.nim b/tests/misc/tparseopt.nim index cbed5d476..b5da6b572 100644 --- a/tests/misc/tparseopt.nim +++ b/tests/misc/tparseopt.nim @@ -21,63 +21,102 @@ kind: cmdShortOption key:val -- r:1 kind: cmdShortOption key:val -- r:0 kind: cmdShortOption key:val -- l: kind: cmdShortOption key:val -- r:4 -parseopt2 -first round -kind: cmdLongOption key:val -- left: -second round -kind: cmdLongOption key:val -- left: -kind: cmdLongOption key:val -- debug:3 -kind: cmdShortOption key:val -- l:4 -kind: cmdShortOption key:val -- r:2''' +''' +joinable: false """ -from parseopt import nil -from parseopt2 import nil +when defined(testament_tparseopt): + import os + proc main() = + let args = commandLineParams() + echo args + for i, ai in args: + echo "arg ", i, " ai.len:", ai.len, " :{", ai, "}" + main() +else: + from parseopt import nil + + block: + echo "parseopt" + for kind, key, val in parseopt.getopt(): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + + # pass custom cmdline arguments + echo "first round" + var argv = "--left --debug:3 -l=4 -r:2" + var p = parseopt.initOptParser(argv) + for kind, key, val in parseopt.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + break + # reset getopt iterator and check arguments are returned correctly. + echo "second round" + for kind, key, val in parseopt.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + + # bug #9619 + var x = parseopt.initOptParser(@["--foo:", "--path"], + allowWhitespaceAfterColon = false) + for kind, key, val in parseopt.getopt(x): + echo kind, " ", key -block: - echo "parseopt" - for kind, key, val in parseopt.getopt(): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val + block: + echo "parseoptNoVal" + # test NoVal mode with custom cmdline arguments + var argv = "--left --debug:3 -l -r:2 --debug 2 --debug=1 -r1 -r=0 -lr4" + var p = parseopt.initOptParser(argv, + shortNoVal = {'l'}, longNoVal = @["left"]) + for kind, key, val in parseopt.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val - # pass custom cmdline arguments - echo "first round" - var argv = "--left --debug:3 -l=4 -r:2" - var p = parseopt.initOptParser(argv) - for kind, key, val in parseopt.getopt(p): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val - break - # reset getopt iterator and check arguments are returned correctly. - echo "second round" - for kind, key, val in parseopt.getopt(p): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val + import osproc, os, strutils + from stdtest/specialpaths import buildDir + import "../.." / compiler/unittest_light - # bug #9619 - var x = parseopt.initOptParser(@["--foo:", "--path"], allowWhitespaceAfterColon = false) - for kind, key, val in parseopt.getopt(x): - echo kind, " ", key + block: # fix #9951 + template runTest(parseoptCustom) = + var p = parseoptCustom.initOptParser(@["echo \"quoted\""]) + let expected = when defined(windows): + """"echo \"quoted\""""" + else: + """'echo "quoted"'""" + assertEquals parseoptCustom.cmdLineRest(p), expected -block: - echo "parseoptNoVal" - # test NoVal mode with custom cmdline arguments - var argv = "--left --debug:3 -l -r:2 --debug 2 --debug=1 -r1 -r=0 -lr4" - var p = parseopt.initOptParser(argv, - shortNoVal = {'l'}, longNoVal = @["left"]) - for kind, key, val in parseopt.getopt(p): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val + doAssert "a5'b" == "a5\'b" -block: - echo "parseopt2" - for kind, key, val in parseopt2.getopt(): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val + let args = @["a1b", "a2 b", "", "a4\"b", "a5'b", r"a6\b", "a7\'b"] + var p2 = parseoptCustom.initOptParser(args) + let expected2 = when defined(windows): + """a1b "a2 b" "" a4\"b a5'b a6\b a7'b""" + else: + """a1b 'a2 b' '' 'a4"b' 'a5'"'"'b' 'a6\b' 'a7'"'"'b'""" + doAssert "a5'b" == "a5\'b" + assertEquals parseoptCustom.cmdLineRest(p2), expected2 + runTest(parseopt) - # pass custom cmdline arguments - echo "first round" - var argv: seq[string] = @["--left", "--debug:3", "-l=4", "-r:2"] - var p = parseopt2.initOptParser(argv) - for kind, key, val in parseopt2.getopt(p): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val - break - # reset getopt iterator and check arguments are returned correctly. - echo "second round" - for kind, key, val in parseopt2.getopt(p): - echo "kind: ", kind, "\tkey:val -- ", key, ":", val + block: # fix #9842 + let exe = buildDir / "D20190112T145450".addFileExt(ExeExt) + defer: + when not defined(windows): + # workaround #10359 ; innocuous to skip since we're saving under `buildDir` + removeFile exe + let args = @["a1b", "a2 b", "", "a4\"b", "a5'b", r"a6\b", "a7\'b"] + let cmd = "$# c -r --verbosity:0 -o:$# -d:testament_tparseopt $# $#" % + [getCurrentCompilerExe(), exe, currentSourcePath(), + args.quoteShellCommand] + var ret = execCmdEx(cmd, options = {}) + if ret.exitCode != 0: + # before bug fix, running cmd would show: + # sh: -c: line 0: unexpected EOF while looking for matching `"'\n + echo "exitCode: ", ret.exitCode, " cmd:", cmd + doAssert false + stripLineEnd(ret.output) + assertEquals ret.output, + """ +@["a1b", "a2 b", "", "a4\"b", "a5\'b", "a6\\b", "a7\'b"] +arg 0 ai.len:3 :{a1b} +arg 1 ai.len:4 :{a2 b} +arg 2 ai.len:0 :{} +arg 3 ai.len:4 :{a4"b} +arg 4 ai.len:4 :{a5'b} +arg 5 ai.len:4 :{a6\b} +arg 6 ai.len:4 :{a7'b}""" diff --git a/tests/misc/tsizeof.nim b/tests/misc/tsizeof.nim index 4422e900e..25c566171 100644 --- a/tests/misc/tsizeof.nim +++ b/tests/misc/tsizeof.nim @@ -402,6 +402,18 @@ type assert sizeof(C) == 3 + +type + MixedBitsize = object {.packed.} + a: uint32 + b {.bitsize: 8.}: uint8 + c {.bitsize: 1.}: uint8 + d {.bitsize: 7.}: uint8 + e {.bitsize: 16.}: uint16 + f: uint32 + +doAssert sizeof(MixedBitsize) == 12 + if failed: quit("FAIL") else: diff --git a/tests/modules/tmismatchedvisibility.nim b/tests/modules/tmismatchedvisibility.nim index 4bf244807..a61b28071 100644 --- a/tests/modules/tmismatchedvisibility.nim +++ b/tests/modules/tmismatchedvisibility.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "public implementation 'tmismatchedvisibility.foo(a: int)[declared in tmismatchedvisibility.nim(6, 5)]' has non-public forward declaration in " + errormsg: "public implementation 'tmismatchedvisibility.foo(a: int) [declared in tmismatchedvisibility.nim(6, 6)]' has non-public forward declaration in " line: 8 """ diff --git a/tests/niminaction/Chapter8/sdl/sdl_test.nim b/tests/niminaction/Chapter8/sdl/sdl_test.nim index a49e08911..1c4d258fb 100644 --- a/tests/niminaction/Chapter8/sdl/sdl_test.nim +++ b/tests/niminaction/Chapter8/sdl/sdl_test.nim @@ -17,12 +17,24 @@ discard pollEvent(nil) renderer.setDrawColor 29, 64, 153, 255 renderer.clear renderer.setDrawColor 255, 255, 255, 255 -var points = [ - (260'i32, 320'i32), - (260'i32, 110'i32), - (360'i32, 320'i32), - (360'i32, 110'i32) -] + +when defined(c): + # just to ensure code from NimInAction still works, but + # the `else` branch would work as well in C mode + var points = [ + (260'i32, 320'i32), + (260'i32, 110'i32), + (360'i32, 320'i32), + (360'i32, 110'i32) + ] +else: + var points = [ + (260.cint, 320.cint), + (260.cint, 110.cint), + (360.cint, 320.cint), + (360.cint, 110.cint) + ] + renderer.drawLines(addr points[0], points.len.cint) renderer.present diff --git a/tests/objects/t3734.nim b/tests/objects/t3734.nim new file mode 100644 index 000000000..cebef6081 --- /dev/null +++ b/tests/objects/t3734.nim @@ -0,0 +1,17 @@ +discard """ +output: "i0" +""" + +type + Application = object + config: void + i: int + f: void + +proc printFields(rec: Application) = + for k, v in fieldPairs(rec): + echo k, v + +var app: Application + +printFields(app) diff --git a/tests/objects/tobjcov.nim b/tests/objects/tobjcov.nim index 817c1fcda..6c587e04d 100644 --- a/tests/objects/tobjcov.nim +++ b/tests/objects/tobjcov.nim @@ -1,8 +1,12 @@ discard """ action: compile +target: "c" """ # Covariance is not type safe: +# Note: `nim cpp` makes it a compile error (after codegen), even with: +# `var f = cast[proc (x: var TA) {.nimcall.}](cast[pointer](bp))`, which +# currently removes all the `cast` in cgen'd code, hence the compile error. type TA = object of RootObj diff --git a/tests/objects/tobject.nim b/tests/objects/tobject.nim index 61ef7442e..fbf531c3d 100644 --- a/tests/objects/tobject.nim +++ b/tests/objects/tobject.nim @@ -17,3 +17,23 @@ suite "object basic methods": check($obj == "(foo: 1)") test "it should test equality based on fields": check(makeObj(1) == makeObj(1)) + +# bug #10203 + +type + TMyObj = TYourObj + TYourObj = object of RootObj + x, y: int + +proc init: TYourObj = + result.x = 0 + result.y = -1 + +proc f(x: var TYourObj) = + discard + +var m: TMyObj = init() +f(m) + +var a: TYourObj = m +var b: TMyObj = a diff --git a/tests/overload/tconverter_to_string.nim b/tests/overload/tconverter_to_string.nim new file mode 100644 index 000000000..1960372d8 --- /dev/null +++ b/tests/overload/tconverter_to_string.nim @@ -0,0 +1,22 @@ +discard """ + output: '''123 +c is not nil''' +""" + +# bug #9149 + +type + Container = ref object + data: int + +converter containerToString*(x: Container): string = $x.data + +var c = Container(data: 123) +var str = string c +echo str + +if c == nil: # this line can compile on v0.18, but not on 0.19 + echo "c is nil" + +if not c.isNil: + echo "c is not nil" diff --git a/tests/parallel/tdont_be_stupid.nim b/tests/parallel/tdont_be_stupid.nim deleted file mode 100644 index d765c11a9..000000000 --- a/tests/parallel/tdont_be_stupid.nim +++ /dev/null @@ -1,23 +0,0 @@ -discard """ -output: ''' -100 -200 -300 -400 -''' -""" - -import threadpool, os - -proc single(time: int) = - sleep time - echo time - -proc sleepsort(nums: openArray[int]) = - parallel: - var i = 0 - while i <= len(nums) + -1: - spawn single(nums[i]) - i += 1 - -sleepsort([400,100,300,200]) diff --git a/tests/parallel/twrong_refcounts.nim b/tests/parallel/twrong_refcounts.nim index ac428762d..ed3c1b894 100644 --- a/tests/parallel/twrong_refcounts.nim +++ b/tests/parallel/twrong_refcounts.nim @@ -1,7 +1,10 @@ discard """ output: "Success" + target: "c" """ +# Note: target: "cpp" fails because we can't yet have `extern "C"` mangling in +# `exportc` procs. import math, random, threadPool # --- diff --git a/tests/parser/tprecedence.nim b/tests/parser/tprecedence.nim index aff7c6aca..3e1c03dd1 100644 --- a/tests/parser/tprecedence.nim +++ b/tests/parser/tprecedence.nim @@ -40,3 +40,12 @@ proc getX(x: MyObject): lent MyField {.inline.} = let a = MyObject() echo a.getX.b.len + + +# bug #10458 +template t(x: untyped): untyped = "x" + +let + aaa = t 2 + 4 + ccc = t (1, 1) + 6 + ddd = t [0, 1, 2] + 5 diff --git a/tests/pragmas/t5149.nim b/tests/pragmas/t5149.nim new file mode 100644 index 000000000..2d242a8d5 --- /dev/null +++ b/tests/pragmas/t5149.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "{.exportc.} not allowed for type aliases" + line: 9 +""" + +type + X* = object + a: int + Y* {.exportc.} = X + +proc impl*(x: X) = + echo "it works" diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index 0bc4d2f18..7f781f6f1 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -61,6 +61,11 @@ block: # A bit more advanced case assert hasCustomPragma(type(s.field), defaultValue) + proc foo(s: var MySerializable) = + static: assert(s.a.getCustomPragmaVal(defaultValue) == 5) + + foo(s) + block: # ref types type Node = object of RootObj @@ -175,24 +180,56 @@ var foo: Something foo.cardinal = north doAssert foo.b.hasCustomPragma(thingy) == true - -proc myproc(s: string): int = +proc myproc(s: string): int = {.thingy.}: s.len doAssert myproc("123") == 3 let xx = compiles: - proc myproc_bad(s: string): int = + proc myproc_bad(s: string): int = {.not_exist.}: s.len doAssert: xx == false - -macro checkSym(s: typed{nkSym}): untyped = +macro checkSym(s: typed{nkSym}): untyped = let body = s.getImpl.body doAssert body[1].kind == nnkPragmaBlock doAssert body[1][0].kind == nnkPragma doAssert body[1][0][0] == bindSym"thingy" -checkSym(myproc) \ No newline at end of file +checkSym(myproc) + +# var and let pragmas +block: + template myAttr() {.pragma.} + template myAttr2(x: int) {.pragma.} + template myAttr3(x: string) {.pragma.} + + let a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0 + let b {.myAttr,myAttr2(2),myAttr3:"test".} = 0 + var x {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0 + var y {.myAttr,myAttr2(2),myAttr3:"test".}: int + var z {.myAttr,myAttr2(2),myAttr3:"test".} = 0 + + template check(s: untyped) = + doAssert s.hasCustomPragma(myAttr) + doAssert s.hasCustomPragma(myAttr2) + doAssert s.getCustomPragmaVal(myAttr2) == 2 + doAssert s.hasCustomPragma(myAttr3) + doAssert s.getCustomPragmaVal(myAttr3) == "test" + + check(a) + check(b) + check(x) + check(y) + check(z) + +# pragma with multiple fields +block: + template myAttr(first: string, second: int, third: float) {.pragma.} + let a {.myAttr("one", 2, 3.0).} = 0 + let ps = a.getCustomPragmaVal(myAttr) + doAssert ps.first == ps[0] and ps.first == "one" + doAssert ps.second == ps[1] and ps.second == 2 + doAssert ps.third == ps[2] and ps.third == 3.0 diff --git a/tests/proc/tillegalreturntype.nim b/tests/proc/tillegalreturntype.nim new file mode 100644 index 000000000..be9e2147e --- /dev/null +++ b/tests/proc/tillegalreturntype.nim @@ -0,0 +1,12 @@ +discard """ + cmd: "nim check $file" + errmsg: "" + nimout: '''tillegalreturntype.nim(8, 11) Error: return type 'typed' is only valid for macros and templates +tillegalreturntype.nim(11, 11) Error: return type 'untyped' is only valid for macros and templates''' +""" + +proc x(): typed = + discard + +proc y(): untyped = + discard diff --git a/tests/statictypes/tstatictypes.nim b/tests/statictypes/tstatictypes.nim index 2a3b7332d..2a4ab0c63 100644 --- a/tests/statictypes/tstatictypes.nim +++ b/tests/statictypes/tstatictypes.nim @@ -116,3 +116,41 @@ block: Tensor[B: static[Backend]; T] = object BackProp[B: static[Backend],T] = proc (gradient: Tensor[B,T]): Tensor[B,T] + +# https://github.com/nim-lang/Nim/issues/10073 +block: + proc foo[N: static int](x: var int, + y: int, + z: static int, + arr: array[N, int]): auto = + var t1 = (a: x, b: y, c: z, d: N) + var t2 = (x, y, z, N) + doAssert t1 == t2 + result = t1 + + var y = 20 + var x = foo(y, 10, 15, [1, 2, 3]) + doAssert x == (20, 10, 15, 3) + +# #7609 +block: + type + Coord[N: static[int]] = tuple[col, row: range[0'i8 .. (N.int8-1)]] + Point[N: static[int]] = range[0'i16 .. N.int16 * N.int16 - 1] + +# https://github.com/nim-lang/Nim/issues/10339 +block: + type + MicroKernel = object + a: float + b: int + + macro extractA(ukernel: static MicroKernel): untyped = + result = newLit ukernel.a + + proc tFunc[ukernel: static MicroKernel]() = + const x = ukernel.extractA + doAssert x == 5.5 + + const uk = MicroKernel(a: 5.5, b: 1) + tFunc[uk]() diff --git a/tests/stdlib/t10231.nim b/tests/stdlib/t10231.nim new file mode 100644 index 000000000..2bb64b475 --- /dev/null +++ b/tests/stdlib/t10231.nim @@ -0,0 +1,15 @@ +discard """ + target: cpp + action: run + exitcode: 0 +""" + +import os + +# consider moving this inside tosproc (taking care that it's for cpp mode) + +if paramCount() == 0: + # main process + doAssert execShellCmd(getAppFilename().quoteShell & " test") == 1 +else: + quit 1 diff --git a/tests/stdlib/tbitops.nim b/tests/stdlib/tbitops.nim index d8c6da1d4..1cbab4870 100644 --- a/tests/stdlib/tbitops.nim +++ b/tests/stdlib/tbitops.nim @@ -1,9 +1,9 @@ discard """ + nimout: "OK" output: "OK" """ import bitops - proc main() = const U8 = 0b0011_0010'u8 const I8 = 0b0011_0010'i8 @@ -79,25 +79,6 @@ proc main() = doAssert( U8.rotateLeftBits(3) == 0b10010001'u8) doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8) - static : - # test bitopts at compile time with vm - doAssert( U8.fastLog2 == 5) - doAssert( I8.fastLog2 == 5) - doAssert( U8.countLeadingZeroBits == 2) - doAssert( I8.countLeadingZeroBits == 2) - doAssert( U8.countTrailingZeroBits == 1) - doAssert( I8.countTrailingZeroBits == 1) - doAssert( U8.firstSetBit == 2) - doAssert( I8.firstSetBit == 2) - doAssert( U8.parityBits == 1) - doAssert( I8.parityBits == 1) - doAssert( U8.countSetBits == 3) - doAssert( I8.countSetBits == 3) - doAssert( U8.rotateLeftBits(3) == 0b10010001'u8) - doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8) - - - template test_undefined_impl(ffunc: untyped; expected: int; is_static: bool) = doAssert( ffunc(0'u8) == expected) doAssert( ffunc(0'i8) == expected) @@ -142,26 +123,67 @@ proc main() = doAssert( U64A.rotateLeftBits(64) == U64A) doAssert( U64A.rotateRightBits(64) == U64A) - static: # check for undefined behavior with rotate by zero. - doAssert( U8.rotateLeftBits(0) == U8) - doAssert( U8.rotateRightBits(0) == U8) - doAssert( U16.rotateLeftBits(0) == U16) - doAssert( U16.rotateRightBits(0) == U16) - doAssert( U32.rotateLeftBits(0) == U32) - doAssert( U32.rotateRightBits(0) == U32) - doAssert( U64A.rotateLeftBits(0) == U64A) - doAssert( U64A.rotateRightBits(0) == U64A) - - # check for undefined behavior with rotate by integer width. - doAssert( U8.rotateLeftBits(8) == U8) - doAssert( U8.rotateRightBits(8) == U8) - doAssert( U16.rotateLeftBits(16) == U16) - doAssert( U16.rotateRightBits(16) == U16) - doAssert( U32.rotateLeftBits(32) == U32) - doAssert( U32.rotateRightBits(32) == U32) - doAssert( U64A.rotateLeftBits(64) == U64A) - doAssert( U64A.rotateRightBits(64) == U64A) + block: + # mask operations + var v: uint8 + v.setMask(0b1100_0000) + v.setMask(0b0000_1100) + doAssert(v == 0b1100_1100) + v.flipMask(0b0101_0101) + doAssert(v == 0b1001_1001) + v.clearMask(0b1000_1000) + doAssert(v == 0b0001_0001) + v.clearMask(0b0001_0001) + doAssert(v == 0b0000_0000) + block: + # single bit operations + var v: uint8 + v.setBit(0) + doAssert v == 0x0000_0001 + v.setBit(1) + doAssert v == 0b0000_0011 + v.flipBit(7) + doAssert v == 0b1000_0011 + v.clearBit(0) + doAssert v == 0b1000_0010 + v.flipBit(1) + doAssert v == 0b1000_0000 + doAssert v.testbit(7) + doAssert not v.testbit(6) + block: + # multi bit operations + var v: uint8 + v.setBits(0, 1, 7) + doAssert v == 0b1000_0011 + v.flipBits(2, 3) + doAssert v == 0b1000_1111 + v.clearBits(7, 0, 1) + doAssert v == 0b0000_1100 + block: + # signed + var v: int8 + v.setBit(7) + doAssert v == -128 + block: + var v: uint64 + v.setBit(63) + doAssert v == 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000'u64 echo "OK" +block: # not ready for vm because exception is compile error + try: + var v: uint32 + var i = 32 + v.setBit(i) + doAssert false + except RangeError: + discard + except: + doAssert false + + main() +static: + # test everything on vm as well + main() diff --git a/tests/stdlib/tgetaddrinfo.nim b/tests/stdlib/tgetaddrinfo.nim new file mode 100644 index 000000000..39102e131 --- /dev/null +++ b/tests/stdlib/tgetaddrinfo.nim @@ -0,0 +1,36 @@ +discard """ + exitcode: 0 + output: "" +""" + +# bug: https://github.com/nim-lang/Nim/issues/10198 + +import nativesockets + +block DGRAM_UDP: + let aiList = getAddrInfo("127.0.0.1", 999.Port, AF_INET, SOCK_DGRAM, IPPROTO_UDP) + doAssert aiList != nil + doAssert aiList.ai_addr != nil + doAssert aiList.ai_addrlen == 16 + doAssert aiList.ai_next == nil + freeAddrInfo aiList + +when defined(posix): + + block RAW_ICMP: + # the port will be ignored + let aiList = getAddrInfo("127.0.0.1", 999.Port, AF_INET, SOCK_RAW, IPPROTO_ICMP) + doAssert aiList != nil + doAssert aiList.ai_addr != nil + doAssert aiList.ai_addrlen == 16 + doAssert aiList.ai_next == nil + freeAddrInfo aiList + + block RAW_ICMPV6: + # the port will be ignored + let aiList = getAddrInfo("::1", 999.Port, AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) + doAssert aiList != nil + doAssert aiList.ai_addr != nil + doAssert aiList.ai_addrlen == 28 + doAssert aiList.ai_next == nil + freeAddrInfo aiList diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index 33332447b..2e95b4833 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -516,3 +516,7 @@ when true: var w = u.to(MyDistRef) doAssert v.name == "smith" doAssert MyRef(w).name == "smith" + + block test_tuple: + doAssert $(%* (a1: 10, a2: "foo")) == """{"a1":10,"a2":"foo"}""" + doAssert $(%* (10, "foo")) == """[10,"foo"]""" diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 7c1851e7a..bdb5aa332 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -4,6 +4,8 @@ discard """ [Suite] random float +[Suite] cumsum + [Suite] random sample [Suite] ^ @@ -18,29 +20,29 @@ import sets, tables suite "random int": test "there might be some randomness": var set = initSet[int](128) - randomize() + for i in 1..1000: incl(set, random(high(int))) check len(set) == 1000 test "single number bounds work": - randomize() + var rand: int for i in 1..1000: rand = random(1000) check rand < 1000 check rand > -1 test "slice bounds work": - randomize() + var rand: int for i in 1..1000: rand = random(100..1000) check rand < 1000 check rand >= 100 - test "randomize() again gives new numbers": - randomize() + test " again gives new numbers": + var rand1 = random(1000000) os.sleep(200) - randomize() + var rand2 = random(1000000) check rand1 != rand2 @@ -48,55 +50,92 @@ suite "random int": suite "random float": test "there might be some randomness": var set = initSet[float](128) - randomize() + for i in 1..100: incl(set, random(1.0)) check len(set) == 100 test "single number bounds work": - randomize() + var rand: float for i in 1..1000: rand = random(1000.0) check rand < 1000.0 check rand > -1.0 test "slice bounds work": - randomize() + var rand: float for i in 1..1000: rand = random(100.0..1000.0) check rand < 1000.0 check rand >= 100.0 - test "randomize() again gives new numbers": - randomize() + test " again gives new numbers": + var rand1:float = random(1000000.0) os.sleep(200) - randomize() + var rand2:float = random(1000000.0) check rand1 != rand2 +suite "cumsum": + test "cumsum int seq return": + let counts = [ 1, 2, 3, 4 ] + check counts.cumsummed == [ 1, 3, 6, 10 ] + + test "cumsum float seq return": + let counts = [ 1.0, 2.0, 3.0, 4.0 ] + check counts.cumsummed == [ 1.0, 3.0, 6.0, 10.0 ] + + test "cumsum int in-place": + var counts = [ 1, 2, 3, 4 ] + counts.cumsum + check counts == [ 1, 3, 6, 10 ] + + test "cumsum float in-place": + var counts = [ 1.0, 2.0, 3.0, 4.0 ] + counts.cumsum + check counts == [ 1.0, 3.0, 6.0, 10.0 ] + suite "random sample": - test "non-uniform array sample": + test "non-uniform array sample unnormalized int CDF": let values = [ 10, 20, 30, 40, 50 ] # values - let weight = [ 4, 3, 2, 1, 0 ] # weights aka unnormalized probabilities - let weightSum = 10.0 # sum of weights + let counts = [ 4, 3, 2, 1, 0 ] # weights aka unnormalized probabilities var histo = initCountTable[int]() - for v in sample(values, weight, 5000): - histo.inc(v) - check histo.len == 4 # number of non-zero in `weight` + let cdf = counts.cumsummed # unnormalized CDF + for i in 0 ..< 5000: + histo.inc(sample(values, cdf)) + check histo.len == 4 # number of non-zero in `counts` # Any one bin is a binomial random var for n samples, each with prob p of # adding a count to k; E[k]=p*n, Var k=p*(1-p)*n, approximately Normal for # big n. So, P(abs(k - p*n)/sqrt(p*(1-p)*n))>3.0) =~ 0.0027, while # P(wholeTestFails) =~ 1 - P(binPasses)^4 =~ 1 - (1-0.0027)^4 =~ 0.01. - for i, w in weight: - if w == 0: + for i, c in counts: + if c == 0: check values[i] notin histo continue - let p = float(w) / float(weightSum) + let p = float(c) / float(cdf[^1]) let n = 5000.0 let expected = p * n let stdDev = sqrt(n * p * (1.0 - p)) check abs(float(histo[values[i]]) - expected) <= 3.0 * stdDev + test "non-uniform array sample normalized float CDF": + let values = [ 10, 20, 30, 40, 50 ] # values + let counts = [ 0.4, 0.3, 0.2, 0.1, 0 ] # probabilities + var histo = initCountTable[int]() + let cdf = counts.cumsummed # normalized CDF + for i in 0 ..< 5000: + histo.inc(sample(values, cdf)) + check histo.len == 4 # number of non-zero in ``counts`` + for i, c in counts: + if c == 0: + check values[i] notin histo + continue + let p = float(c) / float(cdf[^1]) + let n = 5000.0 + let expected = p * n + let stdDev = sqrt(n * p * (1.0 - p)) + # NOTE: like unnormalized int CDF test, P(wholeTestFails) =~ 0.01. + check abs(float(histo[values[i]]) - expected) <= 3.0 * stdDev suite "^": test "compiles for valid types": diff --git a/tests/stdlib/tmget.nim b/tests/stdlib/tmget.nim index 5792b6282..5e2e327f4 100644 --- a/tests/stdlib/tmget.nim +++ b/tests/stdlib/tmget.nim @@ -11,10 +11,10 @@ Can't access 6 Can't access 6 10 11 -Can't access 6 +0 10 11 -Can't access 6 +0 10 11 Can't access 6 @@ -85,7 +85,7 @@ block: except KeyError: echo "Can't access 6" echo x[5] - x[5] += 1 + x.inc 5, 1 var c = x[5] echo c @@ -97,7 +97,7 @@ block: except KeyError: echo "Can't access 6" echo x[5] - x[5] += 1 + x.inc 5, 1 var c = x[5] echo c diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index a7cf5d5b6..23fa4d098 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -1,13 +1,5 @@ discard """ - output: '''true -true -true -true -true -true -true -true -true + output: ''' All: __really_obscure_dir_name/are.x __really_obscure_dir_name/created @@ -27,31 +19,13 @@ __really_obscure_dir_name/created __really_obscure_dir_name/dirs __really_obscure_dir_name/some __really_obscure_dir_name/test -false -false -false -false -false -false -false -false -false -true -true Raises Raises -true -true -true -true -true -true - ''' """ # test os path creation, iteration, and deletion -import os, strutils +import os, strutils, pathnorm block fileOperations: let files = @["these.txt", "are.x", "testing.r", "files.q"] @@ -60,17 +34,17 @@ block fileOperations: let dname = "__really_obscure_dir_name" createDir(dname) - echo dirExists(dname) + doAssert dirExists(dname) # Test creating files and dirs for dir in dirs: createDir(dname/dir) - echo dirExists(dname/dir) + doAssert dirExists(dname/dir) for file in files: let fh = open(dname/file, fmReadWrite) fh.close() - echo fileExists(dname/file) + doAssert fileExists(dname/file) echo "All:" @@ -93,23 +67,23 @@ block fileOperations: # Test removal of files dirs for dir in dirs: removeDir(dname/dir) - echo dirExists(dname/dir) + doAssert: not dirExists(dname/dir) for file in files: removeFile(dname/file) - echo fileExists(dname/file) + doAssert: not fileExists(dname/file) removeDir(dname) - echo dirExists(dname) + doAssert: not dirExists(dname) # createDir should create recursive directories createDir(dirs[0] / dirs[1]) - echo dirExists(dirs[0] / dirs[1]) # true + doAssert dirExists(dirs[0] / dirs[1]) # true removeDir(dirs[0]) # createDir should properly handle trailing separator createDir(dname / "") - echo dirExists(dname) # true + doAssert dirExists(dname) # true removeDir(dname) # createDir should raise IOError if the path exists @@ -138,10 +112,10 @@ block fileOperations: copyDir("a", "../dest/a") removeDir("a") - echo dirExists("../dest/a/b") - echo fileExists("../dest/a/b/file.txt") + doAssert dirExists("../dest/a/b") + doAssert fileExists("../dest/a/b/file.txt") - echo fileExists("../dest/a/b/c/fileC.txt") + doAssert fileExists("../dest/a/b/c/fileC.txt") removeDir("../dest") # test copyDir: @@ -152,8 +126,8 @@ block fileOperations: copyDir("a/", "../dest/a/") removeDir("a") - echo dirExists("../dest/a/b") - echo fileExists("../dest/a/file.txt") + doAssert dirExists("../dest/a/b") + doAssert fileExists("../dest/a/file.txt") removeDir("../dest") import times @@ -165,9 +139,9 @@ block modificationTime: setLastModificationTime("a", tm) when defined(macosx): - echo "true" + doAssert true else: - echo getLastModificationTime("a") == tm + doAssert getLastModificationTime("a") == tm removeFile("a") block walkDirRec: @@ -263,3 +237,99 @@ block splitFile: doAssert splitFile("abc/.") == ("abc", ".", "") doAssert splitFile("..") == ("", "..", "") doAssert splitFile("a/..") == ("a", "..", "") + +# execShellCmd is tested in tosproc + +block ospaths: + doAssert unixToNativePath("") == "" + doAssert unixToNativePath(".") == $CurDir + doAssert unixToNativePath("..") == $ParDir + doAssert isAbsolute(unixToNativePath("/")) + doAssert isAbsolute(unixToNativePath("/", "a")) + doAssert isAbsolute(unixToNativePath("/a")) + doAssert isAbsolute(unixToNativePath("/a", "a")) + doAssert isAbsolute(unixToNativePath("/a/b")) + doAssert isAbsolute(unixToNativePath("/a/b", "a")) + doAssert unixToNativePath("a/b") == joinPath("a", "b") + + when defined(macos): + doAssert unixToNativePath("./") == ":" + doAssert unixToNativePath("./abc") == ":abc" + doAssert unixToNativePath("../abc") == "::abc" + doAssert unixToNativePath("../../abc") == ":::abc" + doAssert unixToNativePath("/abc", "a") == "abc" + doAssert unixToNativePath("/abc/def", "a") == "abc:def" + elif doslikeFileSystem: + doAssert unixToNativePath("./") == ".\\" + doAssert unixToNativePath("./abc") == ".\\abc" + doAssert unixToNativePath("../abc") == "..\\abc" + doAssert unixToNativePath("../../abc") == "..\\..\\abc" + doAssert unixToNativePath("/abc", "a") == "a:\\abc" + doAssert unixToNativePath("/abc/def", "a") == "a:\\abc\\def" + else: + #Tests for unix + doAssert unixToNativePath("./") == "./" + doAssert unixToNativePath("./abc") == "./abc" + doAssert unixToNativePath("../abc") == "../abc" + doAssert unixToNativePath("../../abc") == "../../abc" + doAssert unixToNativePath("/abc", "a") == "/abc" + doAssert unixToNativePath("/abc/def", "a") == "/abc/def" + + block extractFilenameTest: + doAssert extractFilename("") == "" + when defined(posix): + doAssert extractFilename("foo/bar") == "bar" + doAssert extractFilename("foo/bar.txt") == "bar.txt" + doAssert extractFilename("foo/") == "" + doAssert extractFilename("/") == "" + when doslikeFileSystem: + doAssert extractFilename(r"foo\bar") == "bar" + doAssert extractFilename(r"foo\bar.txt") == "bar.txt" + doAssert extractFilename(r"foo\") == "" + doAssert extractFilename(r"C:\") == "" + + block lastPathPartTest: + doAssert lastPathPart("") == "" + when defined(posix): + doAssert lastPathPart("foo/bar.txt") == "bar.txt" + doAssert lastPathPart("foo/") == "foo" + doAssert lastPathPart("/") == "" + when doslikeFileSystem: + doAssert lastPathPart(r"foo\bar.txt") == "bar.txt" + doAssert lastPathPart(r"foo\") == "foo" + + template canon(x): untyped = normalizePath(x, '/') + doAssert canon"/foo/../bar" == "/bar" + doAssert canon"foo/../bar" == "bar" + + doAssert canon"/f/../bar///" == "/bar" + doAssert canon"f/..////bar" == "bar" + + doAssert canon"../bar" == "../bar" + doAssert canon"/../bar" == "/../bar" + + doAssert canon("foo/../../bar/") == "../bar" + doAssert canon("./bla/blob/") == "bla/blob" + doAssert canon(".hiddenFile") == ".hiddenFile" + doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim" + + doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long" + doAssert canon("") == "" + doAssert canon("foobar") == "foobar" + doAssert canon("f/////////") == "f" + + doAssert relativePath("/foo/bar//baz.nim", "/foo", '/') == "bar/baz.nim" + doAssert normalizePath("./foo//bar/../baz", '/') == "foo/baz" + + doAssert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') == "../../me/bar/z.nim" + + doAssert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') == "../me/bar/z.nim" + doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim" + doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim" + doAssert relativePath("", "/users/moo", '/') == "" + doAssert relativePath("foo", "", '/') == "foo" + + doAssert joinPath("usr", "") == unixToNativePath"usr/" + doAssert joinPath("", "lib") == "lib" + doAssert joinPath("", "/lib") == unixToNativePath"/lib" + doAssert joinPath("usr/", "/lib") == unixToNativePath"usr/lib" diff --git a/tests/stdlib/tospaths.nim b/tests/stdlib/tospaths.nim deleted file mode 100644 index ce00b5a95..000000000 --- a/tests/stdlib/tospaths.nim +++ /dev/null @@ -1,99 +0,0 @@ -discard """ - output: "" -""" -# test the ospaths module - -import os, pathnorm - -doAssert unixToNativePath("") == "" -doAssert unixToNativePath(".") == $CurDir -doAssert unixToNativePath("..") == $ParDir -doAssert isAbsolute(unixToNativePath("/")) -doAssert isAbsolute(unixToNativePath("/", "a")) -doAssert isAbsolute(unixToNativePath("/a")) -doAssert isAbsolute(unixToNativePath("/a", "a")) -doAssert isAbsolute(unixToNativePath("/a/b")) -doAssert isAbsolute(unixToNativePath("/a/b", "a")) -doAssert unixToNativePath("a/b") == joinPath("a", "b") - -when defined(macos): - doAssert unixToNativePath("./") == ":" - doAssert unixToNativePath("./abc") == ":abc" - doAssert unixToNativePath("../abc") == "::abc" - doAssert unixToNativePath("../../abc") == ":::abc" - doAssert unixToNativePath("/abc", "a") == "abc" - doAssert unixToNativePath("/abc/def", "a") == "abc:def" -elif doslikeFileSystem: - doAssert unixToNativePath("./") == ".\\" - doAssert unixToNativePath("./abc") == ".\\abc" - doAssert unixToNativePath("../abc") == "..\\abc" - doAssert unixToNativePath("../../abc") == "..\\..\\abc" - doAssert unixToNativePath("/abc", "a") == "a:\\abc" - doAssert unixToNativePath("/abc/def", "a") == "a:\\abc\\def" -else: - #Tests for unix - doAssert unixToNativePath("./") == "./" - doAssert unixToNativePath("./abc") == "./abc" - doAssert unixToNativePath("../abc") == "../abc" - doAssert unixToNativePath("../../abc") == "../../abc" - doAssert unixToNativePath("/abc", "a") == "/abc" - doAssert unixToNativePath("/abc/def", "a") == "/abc/def" - -block extractFilenameTest: - doAssert extractFilename("") == "" - when defined(posix): - doAssert extractFilename("foo/bar") == "bar" - doAssert extractFilename("foo/bar.txt") == "bar.txt" - doAssert extractFilename("foo/") == "" - doAssert extractFilename("/") == "" - when doslikeFileSystem: - doAssert extractFilename(r"foo\bar") == "bar" - doAssert extractFilename(r"foo\bar.txt") == "bar.txt" - doAssert extractFilename(r"foo\") == "" - doAssert extractFilename(r"C:\") == "" - -block lastPathPartTest: - doAssert lastPathPart("") == "" - when defined(posix): - doAssert lastPathPart("foo/bar.txt") == "bar.txt" - doAssert lastPathPart("foo/") == "foo" - doAssert lastPathPart("/") == "" - when doslikeFileSystem: - doAssert lastPathPart(r"foo\bar.txt") == "bar.txt" - doAssert lastPathPart(r"foo\") == "foo" - -template canon(x): untyped = normalizePath(x, '/') -doAssert canon"/foo/../bar" == "/bar" -doAssert canon"foo/../bar" == "bar" - -doAssert canon"/f/../bar///" == "/bar" -doAssert canon"f/..////bar" == "bar" - -doAssert canon"../bar" == "../bar" -doAssert canon"/../bar" == "/../bar" - -doAssert canon("foo/../../bar/") == "../bar" -doAssert canon("./bla/blob/") == "bla/blob" -doAssert canon(".hiddenFile") == ".hiddenFile" -doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim" - -doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long" -doAssert canon("") == "" -doAssert canon("foobar") == "foobar" -doAssert canon("f/////////") == "f" - -doAssert relativePath("/foo/bar//baz.nim", "/foo", '/') == "bar/baz.nim" -doAssert normalizePath("./foo//bar/../baz", '/') == "foo/baz" - -doAssert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') == "../../me/bar/z.nim" - -doAssert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') == "../me/bar/z.nim" -doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim" -doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim" -doAssert relativePath("", "/users/moo", '/') == "" -doAssert relativePath("foo", "", '/') == "foo" - -doAssert joinPath("usr", "") == unixToNativePath"usr/" -doAssert joinPath("", "lib") == "lib" -doAssert joinPath("", "/lib") == unixToNativePath"/lib" -doAssert joinPath("usr/", "/lib") == unixToNativePath"usr/lib" diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim index 9d57d4574..b8d3be9bb 100644 --- a/tests/stdlib/tosproc.nim +++ b/tests/stdlib/tosproc.nim @@ -1,23 +1,99 @@ -discard """ - output: "" -""" # test the osproc module -import os, osproc +import stdtest/specialpaths +import "../.." / compiler/unittest_light -block execProcessTest: - let dir = parentDir(currentSourcePath()) - let (outp, err) = execCmdEx("nim c " & quoteShell(dir / "osproctest.nim")) - doAssert err == 0 - let exePath = dir / addFileExt("osproctest", ExeExt) - let outStr1 = execProcess(exePath, workingDir=dir, args=["foo", "b A r"], options={}) - doAssert outStr1 == dir & "\nfoo\nb A r\n" +when defined(case_testfile): # compiled test file for child process + from posix import exitnow + proc c_exit2(code: c_int): void {.importc: "_exit", header: "<unistd.h>".} + import os + var a = 0 + proc fun(b = 0) = + a.inc + if a mod 10000000 == 0: # prevents optimizing it away + echo a + fun(b+1) - const testDir = "t e st" - createDir(testDir) - doAssert dirExists(testDir) - let outStr2 = execProcess(exePath, workingDir=testDir, args=["x yz"], options={}) - doAssert outStr2 == absolutePath(testDir) & "\nx yz\n" + proc main() = + let args = commandLineParams() + echo (msg: "child binary", pid: getCurrentProcessId()) + let arg = args[0] + echo (arg: arg) + case arg + of "exit_0": + if true: quit(0) + of "exitnow_139": + if true: exitnow(139) + of "c_exit2_139": + if true: c_exit2(139) + of "quit_139": + # `exitStatusLikeShell` doesn't distinguish between a process that + # exit(139) and a process that gets killed with `SIGSEGV` because + # 139 = 11 + 128 = SIGSEGV + 128. + # However, as #10249 shows, this leads to bad debugging experience + # when a child process dies with SIGSEGV, leaving no trace of why it + # failed. The shell (and lldb debugger) solves that by inserting a + # helpful msg: `segmentation fault` when it detects a signal killed + # the child. + # todo: expose an API that will show more diagnostic, returing + # (exitCode, signal) instead of just `shellExitCode`. + if true: quit(139) + of "exit_recursion": # stack overflow by infinite recursion + fun() + echo a + of "exit_array": # bad array access + echo args[1] + main() - removeDir(testDir) - removeFile(exePath) +else: + + import os, osproc, strutils, posix + + block execShellCmdTest: + ## first, compile child program + const nim = getCurrentCompilerExe() + const sourcePath = currentSourcePath() + let output = buildDir / "D20190111T024543".addFileExt(ExeExt) + let cmd = "$# c -o:$# -d:release -d:case_testfile $#" % [nim, output, + sourcePath] + # we're testing `execShellCmd` so don't rely on it to compile test file + # note: this should be exported in posix.nim + proc c_system(cmd: cstring): cint {.importc: "system", + header: "<stdlib.h>".} + assertEquals c_system(cmd), 0 + + ## use it + template runTest(arg: string, expected: int) = + echo (arg2: arg, expected2: expected) + assertEquals execShellCmd(output & " " & arg), expected + + runTest("exit_0", 0) + runTest("exitnow_139", 139) + runTest("c_exit2_139", 139) + runTest("quit_139", 139) + runTest("exit_array", 1) + when defined(posix): # on windows, -1073741571 + runTest("exit_recursion", SIGSEGV.int + 128) # bug #10273: was returning 0 + assertEquals exitStatusLikeShell(SIGSEGV), SIGSEGV + 128.cint + + block execProcessTest: + let dir = parentDir(currentSourcePath()) + let (outp, err) = execCmdEx("nim c " & quoteShell(dir / "osproctest.nim")) + doAssert err == 0 + let exePath = dir / addFileExt("osproctest", ExeExt) + let outStr1 = execProcess(exePath, workingDir = dir, args = ["foo", + "b A r"], options = {}) + doAssert outStr1 == dir & "\nfoo\nb A r\n" + + const testDir = "t e st" + createDir(testDir) + doAssert dirExists(testDir) + let outStr2 = execProcess(exePath, workingDir = testDir, args = ["x yz"], + options = {}) + doAssert outStr2 == absolutePath(testDir) & "\nx yz\n" + + removeDir(testDir) + try: + removeFile(exePath) + except OSError: + discard diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim index 33cb581ef..c1941bd38 100644 --- a/tests/stdlib/trepr.nim +++ b/tests/stdlib/trepr.nim @@ -1,5 +1,6 @@ discard """ - output: "{a, b}{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}" + output: '''{a, b}{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'} +[1, 2, 3, 4, 5, 6]''' """ type @@ -25,3 +26,11 @@ when false: # "a", "b", "c", "d", "e" #] #echo(repr(testseq)) + +# bug #7878 +proc test(variable: var openarray[int]) = + echo repr(variable) + +var arr = [1, 2, 3, 4, 5, 6] + +test(arr) diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index 32f39953d..456ff6315 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -115,6 +115,13 @@ template runTimezoneTests() = check toTime(parsedJan).toUnix == 1451962800 check toTime(parsedJul).toUnix == 1467342000 +template usingTimezone(tz: string, body: untyped) = + when defined(linux) or defined(macosx): + let oldZone = getEnv("TZ") + putEnv("TZ", tz) + body + putEnv("TZ", oldZone) + suite "ttimes": # Generate tests for multiple timezone files where available @@ -123,37 +130,47 @@ suite "ttimes": let tz_dir = getEnv("TZDIR", "/usr/share/zoneinfo") const f = "yyyy-MM-dd HH:mm zzz" - let orig_tz = getEnv("TZ") var tz_cnt = 0 - for tz_fn in walkFiles(tz_dir & "/**/*"): - if symlinkExists(tz_fn) or tz_fn.endsWith(".tab") or - tz_fn.endsWith(".list"): + for timezone in walkFiles(tz_dir & "/**/*"): + if symlinkExists(timezone) or timezone.endsWith(".tab") or + timezone.endsWith(".list"): continue - test "test for " & tz_fn: - tz_cnt.inc - putEnv("TZ", tz_fn) - runTimezoneTests() + usingTimezone(timezone): + test "test for " & timezone: + tz_cnt.inc + runTimezoneTests() test "enough timezone files tested": check tz_cnt > 10 - test "dst handling": - putEnv("TZ", "Europe/Stockholm") - # In case of an impossible time, the time is moved to after the impossible time period - check initDateTime(26, mMar, 2017, 02, 30, 00).format(f) == "2017-03-26 03:30 +02:00" + else: + # not on Linux or macosx: run in the local timezone only + test "parseTest": + runTimezoneTests() + + test "dst handling": + usingTimezone("Europe/Stockholm"): + # In case of an impossible time, the time is moved to after the + # impossible time period + check initDateTime(26, mMar, 2017, 02, 30, 00).format(f) == + "2017-03-26 03:30 +02:00" # In case of an ambiguous time, the earlier time is choosen - check initDateTime(29, mOct, 2017, 02, 00, 00).format(f) == "2017-10-29 02:00 +02:00" + check initDateTime(29, mOct, 2017, 02, 00, 00).format(f) == + "2017-10-29 02:00 +02:00" # These are just dates on either side of the dst switch - check initDateTime(29, mOct, 2017, 01, 00, 00).format(f) == "2017-10-29 01:00 +02:00" + check initDateTime(29, mOct, 2017, 01, 00, 00).format(f) == + "2017-10-29 01:00 +02:00" check initDateTime(29, mOct, 2017, 01, 00, 00).isDst - check initDateTime(29, mOct, 2017, 03, 01, 00).format(f) == "2017-10-29 03:01 +01:00" + check initDateTime(29, mOct, 2017, 03, 01, 00).format(f) == + "2017-10-29 03:01 +01:00" check (not initDateTime(29, mOct, 2017, 03, 01, 00).isDst) - check initDateTime(21, mOct, 2017, 01, 00, 00).format(f) == "2017-10-21 01:00 +02:00" + check initDateTime(21, mOct, 2017, 01, 00, 00).format(f) == + "2017-10-21 01:00 +02:00" - test "issue #6520": - putEnv("TZ", "Europe/Stockholm") + test "issue #6520": + usingTimezone("Europe/Stockholm"): var local = fromUnix(1469275200).local var utc = fromUnix(1469275200).utc @@ -161,35 +178,28 @@ suite "ttimes": local.utcOffset = 0 check claimedOffset == utc.toTime - local.toTime - test "issue #5704": - putEnv("TZ", "Asia/Seoul") - let diff = parse("19700101-000000", "yyyyMMdd-hhmmss").toTime - parse("19000101-000000", "yyyyMMdd-hhmmss").toTime + test "issue #5704": + usingTimezone("Asia/Seoul"): + let diff = parse("19700101-000000", "yyyyMMdd-hhmmss").toTime - + parse("19000101-000000", "yyyyMMdd-hhmmss").toTime check diff == initDuration(seconds = 2208986872) - test "issue #6465": - putEnv("TZ", "Europe/Stockholm") + test "issue #6465": + usingTimezone("Europe/Stockholm"): let dt = parse("2017-03-25 12:00", "yyyy-MM-dd hh:mm") check $(dt + initTimeInterval(days = 1)) == "2017-03-26T12:00:00+02:00" check $(dt + initDuration(days = 1)) == "2017-03-26T13:00:00+02:00" - test "datetime before epoch": - check $fromUnix(-2147483648).utc == "1901-12-13T20:45:52Z" - - test "adding/subtracting time across dst": - putenv("TZ", "Europe/Stockholm") - + test "adding/subtracting time across dst": + usingTimezone("Europe/Stockholm"): let dt1 = initDateTime(26, mMar, 2017, 03, 00, 00) check $(dt1 - 1.seconds) == "2017-03-26T01:59:59+01:00" var dt2 = initDateTime(29, mOct, 2017, 02, 59, 59) check $(dt2 + 1.seconds) == "2017-10-29T02:00:00+01:00" - putEnv("TZ", orig_tz) - - else: - # not on Linux or macosx: run in the local timezone only - test "parseTest": - runTimezoneTests() + test "datetime before epoch": + check $fromUnix(-2147483648).utc == "1901-12-13T20:45:52Z" test "incorrect inputs: empty string": parseTestExcp("", "yyyy-MM-dd") @@ -253,7 +263,7 @@ suite "ttimes": parseTestExcp("+1", "mm") parseTestExcp("+1", "ss") - test "_ as a seperator": + test "_ as a separator": discard parse("2000_01_01", "YYYY'_'MM'_'dd") test "dynamic timezone": @@ -485,3 +495,96 @@ suite "ttimes": check getDayOfWeek(21, mSep, 1970) == dMon check getDayOfWeek(01, mJan, 2000) == dSat check getDayOfWeek(01, mJan, 2021) == dFri + + test "between - simple": + let x = initDateTime(10, mJan, 2018, 13, 00, 00) + let y = initDateTime(11, mJan, 2018, 12, 00, 00) + doAssert x + between(x, y) == y + + test "between - dst start": + usingTimezone("Europe/Stockholm"): + let x = initDateTime(25, mMar, 2018, 00, 00, 00) + let y = initDateTime(25, mMar, 2018, 04, 00, 00) + doAssert x + between(x, y) == y + + test "between - empty interval": + let x = now() + let y = x + doAssert x + between(x, y) == y + + test "between - dst end": + usingTimezone("Europe/Stockholm"): + let x = initDateTime(27, mOct, 2018, 02, 00, 00) + let y = initDateTime(28, mOct, 2018, 01, 00, 00) + doAssert x + between(x, y) == y + + test "between - long day": + usingTimezone("Europe/Stockholm"): + # This day is 25 hours long in Europe/Stockholm + let x = initDateTime(28, mOct, 2018, 00, 30, 00) + let y = initDateTime(29, mOct, 2018, 00, 00, 00) + doAssert between(x, y) == 24.hours + 30.minutes + doAssert x + between(x, y) == y + + test "between - offset change edge case": + # This test case is important because in this case + # `x + between(x.utc, y.utc) == y` is not true, which is very rare. + usingTimezone("America/Belem"): + let x = initDateTime(24, mOct, 1987, 00, 00, 00) + let y = initDateTime(26, mOct, 1987, 23, 00, 00) + doAssert x + between(x, y) == y + doAssert y + between(y, x) == x + + test "between - all units": + let x = initDateTime(1, mJan, 2000, 00, 00, 00, utc()) + let ti = initTimeInterval(1, 1, 1, 1, 1, 1, 1, 1, 1, 1) + let y = x + ti + doAssert between(x, y) == ti + doAssert between(y, x) == -ti + + test "between - monthday overflow": + let x = initDateTime(31, mJan, 2001, 00, 00, 00, utc()) + let y = initDateTime(1, mMar, 2001, 00, 00, 00, utc()) + doAssert x + between(x, y) == y + + test "between - misc": + block: + let x = initDateTime(31, mDec, 2000, 12, 00, 00, utc()) + let y = initDateTime(01, mJan, 2001, 00, 00, 00, utc()) + doAssert between(x, y) == 12.hours + + block: + let x = initDateTime(31, mDec, 2000, 12, 00, 00, utc()) + let y = initDateTime(02, mJan, 2001, 00, 00, 00, utc()) + doAssert between(x, y) == 1.days + 12.hours + + block: + let x = initDateTime(31, mDec, 1995, 00, 00, 00, utc()) + let y = initDateTime(01, mFeb, 2000, 00, 00, 00, utc()) + doAssert x + between(x, y) == y + + block: + let x = initDateTime(01, mDec, 1995, 00, 00, 00, utc()) + let y = initDateTime(31, mJan, 2000, 00, 00, 00, utc()) + doAssert x + between(x, y) == y + + block: + let x = initDateTime(31, mJan, 2000, 00, 00, 00, utc()) + let y = initDateTime(01, mFeb, 2000, 00, 00, 00, utc()) + doAssert x + between(x, y) == y + + block: + let x = initDateTime(01, mJan, 1995, 12, 00, 00, utc()) + let y = initDateTime(01, mFeb, 1995, 00, 00, 00, utc()) + doAssert between(x, y) == 4.weeks + 2.days + 12.hours + + block: + let x = initDateTime(31, mJan, 1995, 00, 00, 00, utc()) + let y = initDateTime(10, mFeb, 1995, 00, 00, 00, utc()) + doAssert x + between(x, y) == y + + block: + let x = initDateTime(31, mJan, 1995, 00, 00, 00, utc()) + let y = initDateTime(10, mMar, 1995, 00, 00, 00, utc()) + doAssert x + between(x, y) == y + doAssert between(x, y) == 1.months + 1.weeks diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim index c8656bbff..65baefef0 100644 --- a/tests/stdlib/tunittest.nim +++ b/tests/stdlib/tunittest.nim @@ -50,7 +50,6 @@ test "unittest multiple requires": import math, random from strutils import parseInt proc defectiveRobot() = - randomize() case random(1..4) of 1: raise newException(OSError, "CANNOT COMPUTE!") of 2: discard parseInt("Hello World!") diff --git a/tests/system/tparams.nim b/tests/system/tparams.nim index dcd620b20..b20cfce1e 100644 --- a/tests/system/tparams.nim +++ b/tests/system/tparams.nim @@ -5,7 +5,7 @@ joinable: false # not joinable because it executes itself with parameters import os import osproc -import parseopt2 +import parseopt import sequtils let argv = commandLineParams() @@ -17,6 +17,6 @@ else: let f = toSeq(getopt()) doAssert f[0].kind == cmdArgument and f[0].key == "foo bar" and f[0].val == "" doAssert f[1].kind == cmdLongOption and f[1].key == "aa" and f[1].val == "bar=a" - doAssert f[2].kind == cmdLongOption and f[2].key == "a=c" and f[2].val == "d" + doAssert f[2].kind == cmdLongOption and f[2].key == "a" and f[2].val == "c:d" doAssert f[3].kind == cmdLongOption and f[3].key == "ab" and f[3].val == "" doAssert f[4].kind == cmdShortOption and f[4].key == "c" and f[4].val == "" diff --git a/tests/system/tsystem_misc.nim b/tests/system/tsystem_misc.nim index 98bc3f4a3..a20e6b3bf 100644 --- a/tests/system/tsystem_misc.nim +++ b/tests/system/tsystem_misc.nim @@ -112,6 +112,18 @@ doAssertRaises(IndexError): foo(toOpenArray(arrNeg, -1, 0)) doAssertRaises(IndexError): foo(toOpenArray(arrNeg, -1, -3)) +doAssertRaises(Exception): + raise newException(Exception, "foo") + +block: + var didThrow = false + try: + doAssertRaises(IndexError): # should fail since it's wrong exception + raise newException(FieldError, "foo") + except AssertionError: + # ok, throwing was correct behavior + didThrow = true + doAssert didThrow type seqqType = ptr UncheckedArray[int] let qData = cast[seqqType](addr seqq[0]) @@ -136,3 +148,14 @@ let a = @[1, 2, 3] # a.boundedOpenArray(1, 2).foo() # Works echo a.boundedOpenArray(1, 2).len # Internal compiler error + +block: # `$`*[T: tuple|object](x: T) + doAssert $(foo1:0, bar1:"a") == """(foo1: 0, bar1: "a")""" + doAssert $(foo1:0, ) == """(foo1: 0)""" + doAssert $(0, "a") == """(0, "a")""" + doAssert $(0, ) == "(0,)" + type Foo = object + x:int + x2:float + doAssert $Foo(x:2) == "(x: 2, x2: 0.0)" + doAssert $() == "()" diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims index b9a6097c2..3efbb0a4c 100644 --- a/tests/test_nimscript.nims +++ b/tests/test_nimscript.nims @@ -17,7 +17,6 @@ import parseutils import deques import sequtils import strutils -import subexes import tables import unicode import uri diff --git a/tests/threads/tactors.nim b/tests/threads/tactors.nim deleted file mode 100644 index ea052b9bd..000000000 --- a/tests/threads/tactors.nim +++ /dev/null @@ -1,13 +0,0 @@ -discard """ - outputsub: "150" -""" - -import actors - -var - pool: ActorPool[int, void] -createActorPool(pool) -for i in 0 ..< 300: - pool.spawn(i, proc (x: int) {.thread.} = echo x) -pool.join() - diff --git a/tests/threads/tactors2.nim b/tests/threads/tactors2.nim deleted file mode 100644 index e8afe203c..000000000 --- a/tests/threads/tactors2.nim +++ /dev/null @@ -1,25 +0,0 @@ -discard """ - output: "1" -""" - -import actors - -type - some_type {.pure, final.} = object - bla: int - -proc thread_proc(input: some_type): some_type {.thread.} = - result.bla = 1 - -proc main() = - var actorPool: ActorPool[some_type, some_type] - createActorPool(actorPool, 1) - - var some_data: some_type - - var inchannel = spawn(actorPool, some_data, thread_proc) - var recv_data = ^inchannel - close(inchannel[]) - echo recv_data.bla - -main() diff --git a/tests/threads/trecursive_actor.nim b/tests/threads/trecursive_actor.nim deleted file mode 100644 index d7072aa53..000000000 --- a/tests/threads/trecursive_actor.nim +++ /dev/null @@ -1,20 +0,0 @@ -discard """ - disabled: yes - outputsub: "0" -""" - -import actors - -var - a: TActorPool[int, void] -createActorPool(a) - -proc task(i: int) {.thread.} = - echo i - if i != 0: a.spawn (i-1, task) - -# count from 9 till 0 and check 0 is somewhere in the output -a.spawn(9, task) -a.join() - - diff --git a/tests/trmacros/trmacros_various2.nim b/tests/trmacros/trmacros_various2.nim index d500c49de..c1367cb1b 100644 --- a/tests/trmacros/trmacros_various2.nim +++ b/tests/trmacros/trmacros_various2.nim @@ -77,3 +77,13 @@ block tstar: # check that it's been optimized properly: doAssert calls == 1 + +# bug #7524 +template in_to_out(typIn, typOut: typedesc) = + proc to_out(x: typIn{lit}): typOut = result = ord(x) + +# Generating the proc via template doesn't work +in_to_out(char, int) + +# This works +proc to_out2(x: char{lit}): int = result = ord(x) diff --git a/tests/tuples/t9177.nim b/tests/tuples/t9177.nim new file mode 100644 index 000000000..d5768b703 --- /dev/null +++ b/tests/tuples/t9177.nim @@ -0,0 +1,16 @@ +discard """ + action: run + disabled: true +""" + +block: + var x = (a: 5, b: 1) + x = (3 * x.a + 2 * x.b, x.a + x.b) + doAssert x.a == 17 + doAssert x.b == 6 +block: + # Transformation of a tuple constructor with named arguments + var x = (a: 5, b: 1) + x = (a: 3 * x.a + 2 * x.b, b: x.a + x.b) + doAssert x.a == 17 + doAssert x.b == 6 diff --git a/tests/tuples/tuple_with_nil.nim b/tests/tuples/tuple_with_nil.nim index e09c53407..1b210b2bf 100644 --- a/tests/tuples/tuple_with_nil.nim +++ b/tests/tuples/tuple_with_nil.nim @@ -4,7 +4,6 @@ import parseutils import unicode import math import fenv -#import unsigned import pegs import streams diff --git a/tests/typerel/t4799.nim b/tests/typerel/t4799.nim index 075893476..814ad361d 100644 --- a/tests/typerel/t4799.nim +++ b/tests/typerel/t4799.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" output: "OK" """ diff --git a/tests/typerel/t4799_1.nim b/tests/typerel/t4799_1.nim index 549b6bf3c..e66aa1a9a 100644 --- a/tests/typerel/t4799_1.nim +++ b/tests/typerel/t4799_1.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" outputsub: '''ObjectAssignmentError''' exitcode: "1" """ diff --git a/tests/typerel/t4799_2.nim b/tests/typerel/t4799_2.nim index cfd399a6e..ff20c2426 100644 --- a/tests/typerel/t4799_2.nim +++ b/tests/typerel/t4799_2.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" outputsub: '''ObjectAssignmentError''' exitcode: "1" """ diff --git a/tests/typerel/t4799_3.nim b/tests/typerel/t4799_3.nim index 784eee8fc..4a8a158dd 100644 --- a/tests/typerel/t4799_3.nim +++ b/tests/typerel/t4799_3.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" outputsub: '''ObjectAssignmentError''' exitcode: "1" """ diff --git a/tests/typerel/tptrs.nim b/tests/typerel/tptrs.nim new file mode 100644 index 000000000..3505a7736 --- /dev/null +++ b/tests/typerel/tptrs.nim @@ -0,0 +1,8 @@ +discard """ + errormsg: "type mismatch: got <ptr int16> but expected 'ptr int'" + line: 8 +""" + +var + n: int16 + p: ptr int = addr n diff --git a/tests/types/tillegaltyperecursion.nim b/tests/types/tillegaltyperecursion.nim index d8021c06f..4c53a8b0e 100644 --- a/tests/types/tillegaltyperecursion.nim +++ b/tests/types/tillegaltyperecursion.nim @@ -5,7 +5,7 @@ discard """ """ import events -import sockets +import net import strutils import os diff --git a/tests/vm/tbitops.nim b/tests/vm/tbitops.nim new file mode 100644 index 000000000..90d463ec9 --- /dev/null +++ b/tests/vm/tbitops.nim @@ -0,0 +1,45 @@ +discard """ +output: "" +""" + +import strutils + +const x = [1'i32, -1, -10, 10, -10, 10, -20, 30, -40, 50, 7 shl 28, -(7 shl 28), 7 shl 28, -(7 shl 28)] +const y = [-1'i32, 1, -10, -10, 10, 10, -20, -30, 40, 50, 1 shl 30, 1 shl 30, -(1 shl 30), -(1 shl 30)] + +const res_xor = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(int64(x[i] xor y[i])) + tmp + +const res_and = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(int64(x[i] and y[i])) + tmp + +const res_or = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(int64(x[i] or y[i])) + tmp + +const res_not = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(not x[i]) + tmp + +let xx = x +let yy = y + +for i in 0..<xx.len: + let z_xor = int64(xx[i] xor yy[i]) + let z_and = int64(xx[i] and yy[i]) + let z_or = int64(xx[i] or yy[i]) + let z_not = int64(not xx[i]) + doAssert(z_xor == res_xor[i], $i & ": " & $res_xor[i] & " " & $z_xor) + doAssert(z_and == res_and[i], $i & ": " & $res_and[i] & " " & $z_and) + doAssert(z_or == res_or[i], $i & ": " & $res_or[i] & " " & $z_or) + doAssert(z_not == res_not[i], $i & ": " & $res_not[i] & " " & $z_not) diff --git a/tests/vm/tcompiletimesideeffects.nim b/tests/vm/tcompiletimesideeffects.nim new file mode 100644 index 000000000..4cd57b3bd --- /dev/null +++ b/tests/vm/tcompiletimesideeffects.nim @@ -0,0 +1,42 @@ +discard """ + output: +''' +@[0, 1, 2] +@[3, 4, 5] +@[0, 1, 2] +3 +4 +''' +""" + +template runNTimes(n: int, f : untyped) : untyped = + var accum: seq[type(f)] + for i in 0..n-1: + accum.add(f) + accum + +var state {.compileTime.} : int = 0 +proc fill(): int {.compileTime.} = + result = state + inc state + +# invoke fill() at compile time as a compile time expression +const C1 = runNTimes(3, fill()) +echo C1 + +# invoke fill() at compile time as a set of compile time statements +const C2 = + block: + runNTimes(3, fill()) +echo C2 + +# invoke fill() at compile time after a compile time reset of state +const C3 = + block: + state = 0 + runNTimes(3, fill()) +echo C3 + +# evaluate fill() at compile time and use the results at runtime +echo fill() +echo fill() diff --git a/tests/vm/tconstobj.nim b/tests/vm/tconstobj.nim index 021fcb728..3cf256eed 100644 --- a/tests/vm/tconstobj.nim +++ b/tests/vm/tconstobj.nim @@ -48,3 +48,20 @@ let people = { }.toTable() echo people["001"] + +# Object downconversion should not copy + +type + SomeBaseObj {.inheritable.} = object of RootObj + txt : string + InheritedFromBase = object of SomeBaseObj + other : string + +proc initBase(sbo: var SomeBaseObj) = + sbo.txt = "Initialized string from base" + +static: + var ifb2: InheritedFromBase + initBase(SomeBaseObj(ifb2)) + echo repr(ifb2) + doAssert(ifb2.txt == "Initialized string from base") diff --git a/tests/vm/tissues.nim b/tests/vm/tissues.nim index 021b902ad..063559d2e 100644 --- a/tests/vm/tissues.nim +++ b/tests/vm/tissues.nim @@ -1,16 +1,14 @@ -discard """ - nimout: "(Field0: 2, Field1: 2, Field2: 2, Field3: 2)" -""" - import macros -block t9043: - proc foo[N: static[int]](dims: array[N, int])= +block t9043: # issue #9043 + proc foo[N: static[int]](dims: array[N, int]): string = const N1 = N const N2 = dims.len - static: echo (N, dims.len, N1, N2) + const ret = $(N, dims.len, N1, N2) + static: doAssert ret == $(N, dims.len, N1, N2) + ret - foo([1, 2]) + doAssert foo([1, 2]) == "(2, 2, 2, 2)" block t4952: proc doCheck(tree: NimNode) = diff --git a/tests/vm/tmisc_vm.nim b/tests/vm/tmisc_vm.nim index 6eb3dd627..bce0159ce 100644 --- a/tests/vm/tmisc_vm.nim +++ b/tests/vm/tmisc_vm.nim @@ -49,3 +49,23 @@ static: echo "caught Defect" except ValueError: echo "caught ValueError" + +# bug #10538 + +block: + proc fun1(): seq[int] = + try: + try: + result.add(1) + return + except: + result.add(-1) + finally: + result.add(2) + finally: + result.add(3) + result.add(4) + + let x1 = fun1() + const x2 = fun1() + doAssert(x1 == x2) diff --git a/tests/vm/treset.nim b/tests/vm/treset.nim new file mode 100644 index 000000000..56fe19b19 --- /dev/null +++ b/tests/vm/treset.nim @@ -0,0 +1,28 @@ +static: + type Obj = object + field: int + var o = Obj(field: 1) + reset(o) + doAssert o.field == 0 + +static: + var i = 2 + reset(i) + doAssert i == 0 + +static: + var i = new int + reset(i) + doAssert i.isNil + +static: + var s = @[1, 2, 3] + reset(s) + doAssert s == @[] + +static: + proc f() = + var i = 2 + reset(i) + doAssert i == 0 + f() \ No newline at end of file diff --git a/tests/vm/tvarsection.nim b/tests/vm/tvarsection.nim new file mode 100644 index 000000000..d1c4926a0 --- /dev/null +++ b/tests/vm/tvarsection.nim @@ -0,0 +1,15 @@ +discard """ + output: '''-1abc''' +""" + +var + a {.compileTime.} = 2 + b = -1 + c {.compileTime.} = 3 + d = "abc" + +static: + assert a == 2 + assert c == 3 + +echo b, d diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index bd3aa2fcd..78871d103 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -149,3 +149,14 @@ static: static: doAssert foo().i == 1 + +# #10333 +block: + const + encoding: auto = [ + ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"], + ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], + ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"], + ["", "M", "MM", "MMM", "--", "-", "--", "---", "----", "--"], + ] + doAssert encoding.len == 4 |