diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/async/tasyncdial.nim | 53 | ||||
-rw-r--r-- | tests/async/tasyncfile.nim | 5 | ||||
-rw-r--r-- | tests/async/tasyncfilewrite.nim | 17 | ||||
-rw-r--r-- | tests/async/tioselectors.nim | 7 | ||||
-rw-r--r-- | tests/collections/ttables.nim | 15 | ||||
-rw-r--r-- | tests/macros/tgettypeinst.nim | 65 | ||||
-rw-r--r-- | tests/osproc/texitsignal.nim | 36 | ||||
-rw-r--r-- | tests/parser/twrongcmdsyntax.nim | 6 | ||||
-rw-r--r-- | tests/stdlib/thttpclient.nim | 60 | ||||
-rw-r--r-- | tests/stdlib/tjsonmacro.nim | 229 | ||||
-rw-r--r-- | tests/stdlib/tnetdial.nim | 60 | ||||
-rw-r--r-- | tests/stdlib/tparseipv6.nim | 217 | ||||
-rw-r--r-- | tests/testament/specs.nim | 11 | ||||
-rw-r--r-- | tests/testament/tester.nim | 6 | ||||
-rw-r--r-- | tests/tuples/tunpack_asgn.nim | 2 | ||||
-rw-r--r-- | tests/tuples/tuple_subscript.nim | 40 |
16 files changed, 789 insertions, 40 deletions
diff --git a/tests/async/tasyncdial.nim b/tests/async/tasyncdial.nim new file mode 100644 index 000000000..d70e14020 --- /dev/null +++ b/tests/async/tasyncdial.nim @@ -0,0 +1,53 @@ +discard """ + file: "tasyncdial.nim" + output: ''' +OK AF_INET +OK AF_INET6 +''' +""" + +import + nativesockets, os, asyncdispatch + +proc setupServerSocket(hostname: string, port: Port, domain: Domain): AsyncFD = + ## Creates a socket, binds it to the specified address, and starts listening for connecitons. + ## Registers the descriptor with the dispatcher of the current thread + ## Raises OSError in case of an error. + let fd = newNativeSocket(domain) + setSockOptInt(fd, SOL_SOCKET, SO_REUSEADDR, 1) + var aiList = getAddrInfo(hostname, port, domain) + if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32: + freeAddrInfo(aiList) + raiseOSError(osLastError()) + freeAddrInfo(aiList) + if listen(fd) != 0: + raiseOSError(osLastError()) + setBlocking(fd, false) + result = fd.AsyncFD + register(result) + +proc doTest(domain: static[Domain]) {.async.} = + const + testHost = when domain == Domain.AF_INET6: "::1" else: "127.0.0.1" + testPort = Port(17384) + let serverFd = setupServerSocket(testHost, testPort, domain) + let acceptFut = serverFd.accept() + let clientFdFut = dial(testHost, testPort) + + let serverClientFd = await acceptFut + serverFd.closeSocket() + + let clientFd = await clientFdFut + + let recvFut = serverClientFd.recv(2) + await clientFd.send("Hi") + let msg = await recvFut + + serverClientFd.closeSocket() + clientFd.closeSocket() + + if msg == "Hi": + echo "OK ", domain + +waitFor(doTest(Domain.AF_INET)) +waitFor(doTest(Domain.AF_INET6)) diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim index 26a9bb391..592f0ebd8 100644 --- a/tests/async/tasyncfile.nim +++ b/tests/async/tasyncfile.nim @@ -11,9 +11,10 @@ proc main() {.async.} = # Simple write/read test. block: var file = openAsync(fn, fmReadWrite) - await file.write("test") + await file.write("testing") file.setFilePos(0) await file.write("foo") + file.setFileSize(4) file.setFilePos(0) let data = await file.readAll() doAssert data == "foot" @@ -24,7 +25,7 @@ proc main() {.async.} = var file = openAsync(fn, fmAppend) await file.write("\ntest2") let errorTest = file.readAll() - echo await errorTest + yield errorTest doAssert errorTest.failed file.close() file = openAsync(fn, fmRead) diff --git a/tests/async/tasyncfilewrite.nim b/tests/async/tasyncfilewrite.nim new file mode 100644 index 000000000..cda612bae --- /dev/null +++ b/tests/async/tasyncfilewrite.nim @@ -0,0 +1,17 @@ +discard """ + output: '''string 1 +string 2 +string 3''' +""" +# bug #5532 +import os, asyncfile, asyncdispatch + +removeFile("test.txt") +let f = openAsync("test.txt", fmWrite) +var futs = newSeq[Future[void]]() +for i in 1..3: + futs.add(f.write("string " & $i & "\n")) +waitFor(all(futs)) +f.close() +echo readFile("test.txt") + diff --git a/tests/async/tioselectors.nim b/tests/async/tioselectors.nim index 5e5a18a1b..e2b9b94d5 100644 --- a/tests/async/tioselectors.nim +++ b/tests/async/tioselectors.nim @@ -508,9 +508,10 @@ else: freeAddrInfo(aiList) # for some reason Windows select doesn't return both # descriptors from first call, so we need to make 2 calls - discard selector.select(1000) - var rcm = selector.select(1000) - assert(len(rcm) == 2) + var rcm1 = selector.select(1000) + var rcm2 = selector.select(1000) + let rcm = len(rcm1) + len(rcm2) + assert(rcm >= 2 and rcm <= 4) var sockAddress = SockAddr() var addrLen = sizeof(sockAddress).Socklen diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index a2988e841..01dab44fc 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -235,6 +235,21 @@ block withKeyTest: except KeyError: discard +block takeTest: + var t = initTable[string, int]() + t["key"] = 123 + + var val = 0 + assert(t.take("key", val)) + assert(val == 123) + + val = -1 + assert(not t.take("key", val)) + assert(val == -1) + + assert(not t.take("otherkey", val)) + assert(val == -1) + proc orderedTableSortTest() = var t = initOrderedTable[string, int](2) for key, val in items(data): t[key] = val diff --git a/tests/macros/tgettypeinst.nim b/tests/macros/tgettypeinst.nim index 255eff949..f89aa5e0b 100644 --- a/tests/macros/tgettypeinst.nim +++ b/tests/macros/tgettypeinst.nim @@ -21,49 +21,67 @@ proc symToIdent(x: NimNode): NimNode = for c in x: result.add symToIdent(c) +# check getTypeInst and getTypeImpl for given symbol x macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed = + # check that getTypeInst(x) equals inst0 let inst = x.getTypeInst - let impl = x.getTypeImpl - let inst0r = inst0.symToIdent.treeRepr let instr = inst.symToIdent.treeRepr - #echo inst0r + let inst0r = inst0.symToIdent.treeRepr #echo instr + #echo inst0r doAssert(instr == inst0r) + + # check that getTypeImpl(x) is correct + # if implX is nil then compare to inst0 + # else we expect implX to be a type definition + # and we extract the implementation from that + let impl = x.getTypeImpl var impl0 = if implX.kind == nnkNilLit: inst0 else: implX[0][2] - let impl0r = impl0.symToIdent.treerepr let implr = impl.symToIdent.treerepr - #echo impl0r + let impl0r = impl0.symToIdent.treerepr #echo implr + #echo impl0r doAssert(implr == impl0r) - template echoString(s:string) = echo s.replace("\n","\n ") + result = newStmtList() + #template echoString(s: string) = echo s.replace("\n","\n ") #result.add getAst(echoString(" " & inst0.repr)) #result.add getAst(echoString(" " & inst.repr)) #result.add getAst(echoString(" " & impl0.repr)) #result.add getAst(echoString(" " & impl.repr)) + if recurse: - template testDecl(n, m :typed) = + # now test using a newly formed variable of type getTypeInst(x) + template testDecl(n,m: typed) = testV(n, false): type _ = m result.add getAst(testDecl(inst.symToIdent, impl.symToIdent)) +# test with a variable (instance) of type template testV(inst, recurse, impl) = block: #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl) var x: inst testX(x, inst, recurse, impl) -template testT(inst, recurse) = + +# test with a newly created typedesc (myType) +# using the passed type as the implementation +template testT(impl, recurse) = block: - type myType = inst + type myType = impl testV(myType, recurse): - type _ = inst + type _ = impl +# test a built-in type whose instance is equal to the implementation template test(inst) = testT(inst, false) testV(inst, true, nil) -template test(inst, impl) = testV(inst, true, impl) + +# test a custom type with provided implementation +template test(inst, impl) = + testV(inst, true, impl) type Model = object of RootObj @@ -87,9 +105,12 @@ type value:T Foo[N:static[int],T] = object Bar[N:static[int],T] = object - #baz:Foo[N+1,GenericObject[T]] + #baz:Foo[N+1,GenericObject[T]] # currently fails baz:Foo[N,GenericObject[T]] + Generic[T] = seq[int] + Concrete = Generic[int] + test(bool) test(char) test(int) @@ -97,13 +118,17 @@ test(float) test(ptr int) test(ref int) test(array[1..10,Bar[2,Foo[3,float]]]) +test(array[MyEnum,Bar[2,Foo[3,float]]]) test(distinct Bar[2,Foo[3,float]]) test(tuple[a:int,b:Foo[-1,float]]) -#test(MyEnum): -# type _ = enum -# valueA, valueB, valueC -test(set[MyEnum]) test(seq[int]) +test(set[MyEnum]) +test(proc (a: int, b: Foo[2,float])) +test(proc (a: int, b: Foo[2,float]): Bar[3,int]) + +test(MyEnum): + type _ = enum + valueA, valueB, valueC test(Bar[2,Foo[3,float]]): type _ = object baz: Foo[2, GenericObject[Foo[3, float]]] @@ -118,8 +143,12 @@ test(Tree): value: int left: ref Tree right: ref Tree -test(proc (a: int, b: Foo[2,float])) -test(proc (a: int, b: Foo[2,float]): Bar[3,int]) +test(Concrete): + type _ = Generic[int] +test(Generic[int]): + type _ = seq[int] +test(Generic[float]): + type _ = seq[int] # bug #4862 static: diff --git a/tests/osproc/texitsignal.nim b/tests/osproc/texitsignal.nim new file mode 100644 index 000000000..c0bed70ee --- /dev/null +++ b/tests/osproc/texitsignal.nim @@ -0,0 +1,36 @@ +discard """ + output: '''true +true''' + targets: "c" +""" + +import os, osproc +when not defined(windows): + import posix + +# Checks that the environment is passed correctly in startProcess +# To do that launches a copy of itself with a new environment. + +if paramCount() == 0: + # Parent process + + let p = startProcess( + getAppFilename(), + args = @["child"], + options = {poStdErrToStdOut, poUsePath, poParentStreams} + ) + + echo p.running() + + p.kill() + + when defined(windows): + # windows kill happens using TerminateProcess(h, 0), so we should get a + # 0 here + echo p.waitForExit() == 0 + else: + # on posix (non-windows), kill sends SIGKILL + echo p.waitForExit() == 128 + SIGKILL + +else: + sleep(5000) # should get killed before this \ No newline at end of file diff --git a/tests/parser/twrongcmdsyntax.nim b/tests/parser/twrongcmdsyntax.nim new file mode 100644 index 000000000..affe72c34 --- /dev/null +++ b/tests/parser/twrongcmdsyntax.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: '''identifier expected, but found 'echo 4''' + line: 6 +""" + +echo 4 +2 diff --git a/tests/stdlib/thttpclient.nim b/tests/stdlib/thttpclient.nim index 62c1ebee7..c6a857edb 100644 --- a/tests/stdlib/thttpclient.nim +++ b/tests/stdlib/thttpclient.nim @@ -1,11 +1,13 @@ discard """ cmd: "nim c --threads:on -d:ssl $file" + exitcode: 0 + output: "OK" """ import strutils from net import TimeoutError -import httpclient, asyncdispatch +import nativesockets, os, httpclient, asyncdispatch const manualTests = false @@ -102,16 +104,52 @@ proc syncTest() = client.close() - # Timeout test. - client = newHttpClient(timeout = 1) - try: - resp = client.request("http://example.com/") - doAssert false, "TimeoutError should have been raised." - except TimeoutError: - discard - except: - doAssert false, "TimeoutError should have been raised." + when false: + # Disabled for now because it causes troubles with AppVeyor + # Timeout test. + client = newHttpClient(timeout = 1) + try: + resp = client.request("http://example.com/") + doAssert false, "TimeoutError should have been raised." + except TimeoutError: + discard + except: + doAssert false, "TimeoutError should have been raised." + +proc makeIPv6HttpServer(hostname: string, port: Port): AsyncFD = + let fd = newNativeSocket(AF_INET6) + setSockOptInt(fd, SOL_SOCKET, SO_REUSEADDR, 1) + var aiList = getAddrInfo(hostname, port, AF_INET6) + if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32: + freeAddrInfo(aiList) + raiseOSError(osLastError()) + freeAddrInfo(aiList) + if listen(fd) != 0: + raiseOSError(osLastError()) + setBlocking(fd, false) + + var serverFd = fd.AsyncFD + register(serverFd) + result = serverFd + + proc onAccept(fut: Future[AsyncFD]) {.gcsafe.} = + if not fut.failed: + let clientFd = fut.read() + clientFd.send("HTTP/1.1 200 OK\r\LContent-Length: 0\r\LConnection: Closed\r\L\r\L").callback = proc() = + clientFd.closeSocket() + serverFd.accept().callback = onAccept + serverFd.accept().callback = onAccept + +proc ipv6Test() = + var client = newAsyncHttpClient() + let serverFd = makeIPv6HttpServer("::1", Port(18473)) + var resp = waitFor client.request("http://[::1]:18473/") + doAssert(resp.status == "200 OK") + serverFd.closeSocket() + client.close() syncTest() - waitFor(asyncTest()) +ipv6Test() + +echo "OK" diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim new file mode 100644 index 000000000..323b3e1ee --- /dev/null +++ b/tests/stdlib/tjsonmacro.nim @@ -0,0 +1,229 @@ +discard """ + file: "tjsonmacro.nim" + output: "" +""" +import json, strutils + +when isMainModule: + # Tests inspired by own use case (with some additional tests). + # This should succeed. + type + Point[T] = object + x, y: T + + ReplayEventKind* = enum + FoodAppeared, FoodEaten, DirectionChanged + + ReplayEvent* = object + time*: float + case kind*: ReplayEventKind + of FoodAppeared, FoodEaten: + foodPos*: Point[float] + of DirectionChanged: + playerPos*: float + + Replay* = ref object + events*: seq[ReplayEvent] + test: int + test2: string + test3: bool + testNil: string + + var x = Replay( + events: @[ + ReplayEvent( + time: 1.2345, + kind: FoodEaten, + foodPos: Point[float](x: 5.0, y: 1.0) + ) + ], + test: 18827361, + test2: "hello world", + test3: true, + testNil: nil + ) + + let node = %x + + let y = to(node, Replay) + doAssert y.events[0].time == 1.2345 + doAssert y.events[0].kind == FoodEaten + doAssert y.events[0].foodPos.x == 5.0 + doAssert y.events[0].foodPos.y == 1.0 + doAssert y.test == 18827361 + doAssert y.test2 == "hello world" + doAssert y.test3 + doAssert y.testNil.isNil + + # Test for custom object variants (without an enum) and with an else branch. + block: + type + TestVariant = object + name: string + case age: uint8 + of 2: + preSchool: string + of 8: + primarySchool: string + else: + other: int + + var node = %{ + "name": %"Nim", + "age": %8, + "primarySchool": %"Sandtown" + } + + var result = to(node, TestVariant) + doAssert result.age == 8 + doAssert result.name == "Nim" + doAssert result.primarySchool == "Sandtown" + + node = %{ + "name": %"⚔️Foo☢️", + "age": %25, + "other": %98 + } + + result = to(node, TestVariant) + doAssert result.name == node["name"].getStr() + doAssert result.age == node["age"].getNum().uint8 + doAssert result.other == node["other"].getNum() + + # TODO: Test object variant with set in of branch. + # TODO: Should we support heterogenous arrays? + + # Tests that verify the error messages for invalid data. + block: + type + Person = object + name: string + age: int + + var node = %{ + "name": %"Dominik" + } + + try: + discard to(node, Person) + doAssert false + except KeyError as exc: + doAssert("age" in exc.msg) + except: + doAssert false + + node["age"] = %false + + try: + discard to(node, Person) + doAssert false + except JsonKindError as exc: + doAssert("age" in exc.msg) + except: + doAssert false + + type + PersonAge = enum + Fifteen, Sixteen + + PersonCase = object + name: string + case age: PersonAge + of Fifteen: + discard + of Sixteen: + id: string + + try: + discard to(node, PersonCase) + doAssert false + except JsonKindError as exc: + doAssert("age" in exc.msg) + except: + doAssert false + + # Test the example in json module. + block: + let jsonNode = parseJson(""" + { + "person": { + "name": "Nimmer", + "age": 21 + }, + "list": [1, 2, 3, 4] + } + """) + + type + Person = object + name: string + age: int + + Data1 = object # TODO: Codegen bug when changed to ``Data``. + person: Person + list: seq[int] + + var data = to(jsonNode, Data1) + doAssert data.person.name == "Nimmer" + doAssert data.person.age == 21 + doAssert data.list == @[1, 2, 3, 4] + + # Test non-variant enum fields. + block: + type + EnumType = enum + Foo, Bar + + TestEnum = object + field: EnumType + + var node = %{ + "field": %"Bar" + } + + var result = to(node, TestEnum) + doAssert result.field == Bar + + # Test ref type in field. + block: + var jsonNode = parseJson(""" + { + "person": { + "name": "Nimmer", + "age": 21 + }, + "list": [1, 2, 3, 4] + } + """) + + type + Person = ref object + name: string + age: int + + Data = object + person: Person + list: seq[int] + + var data = to(jsonNode, Data) + doAssert data.person.name == "Nimmer" + doAssert data.person.age == 21 + doAssert data.list == @[1, 2, 3, 4] + + jsonNode = parseJson(""" + { + "person": null, + "list": [1, 2, 3, 4] + } + """) + data = to(jsonNode, Data) + doAssert data.person.isNil + + block: + type + FooBar = object + field: float + + let x = parseJson("""{ "field": 5}""") + let data = to(x, FooBar) + doAssert data.field == 5.0 \ No newline at end of file diff --git a/tests/stdlib/tnetdial.nim b/tests/stdlib/tnetdial.nim new file mode 100644 index 000000000..da6088d70 --- /dev/null +++ b/tests/stdlib/tnetdial.nim @@ -0,0 +1,60 @@ +discard """ + cmd: "nim c --threads:on $file" + exitcode: 0 + output: "OK" +""" + +import os, net, nativesockets, asyncdispatch + +## Test for net.dial + +const port = Port(28431) + +proc initIPv6Server(hostname: string, port: Port): AsyncFD = + let fd = newNativeSocket(AF_INET6) + setSockOptInt(fd, SOL_SOCKET, SO_REUSEADDR, 1) + var aiList = getAddrInfo(hostname, port, AF_INET6) + if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32: + freeAddrInfo(aiList) + raiseOSError(osLastError()) + freeAddrInfo(aiList) + if listen(fd) != 0: + raiseOSError(osLastError()) + setBlocking(fd, false) + + var serverFd = fd.AsyncFD + register(serverFd) + result = serverFd + +# Since net.dial is synchronous, we use main thread to setup server, +# and dial to it from another thread. + +proc testThread() {.thread.} = + let fd = net.dial("::1", port) + var s = newString(5) + doAssert fd.recv(addr s[0], 5) == 5 + if s == "Hello": + echo "OK" + fd.close() + +proc test() = + var t: Thread[void] + createThread(t, testThread) + + let serverFd = initIPv6Server("::1", port) + var done = false + + serverFd.accept().callback = proc(fut: Future[AsyncFD]) = + serverFd.closeSocket() + if not fut.failed: + let fd = fut.read() + fd.send("Hello").callback = proc() = + fd.closeSocket() + done = true + + while not done: + poll() + + joinThread(t) + +test() diff --git a/tests/stdlib/tparseipv6.nim b/tests/stdlib/tparseipv6.nim new file mode 100644 index 000000000..3e1c23e58 --- /dev/null +++ b/tests/stdlib/tparseipv6.nim @@ -0,0 +1,217 @@ +discard """ + output: "all ok" +""" + +import net + +const + positives = [ + "::f:8:a8f:218.17.235.229", + "::b:228.19.241.2", + "::8:c:a:f:8.35.8.096", + "::3:e:a:bc:04.19.2.9", + "::2:212.242.248.19", + "::df:a5f:3.250.208.9", + "::8:c:5:e63:250.208.249.0", + "::b:f:181.12.9.98", + "::a:f8:77.08.243.232", + "::a:b:85:e4d9:252.9.229.056", + "941:c:8a:c:e::917", + "e8:7a:e:ad:88a:8:203.235.225.46", + "139c:9e::f8:254.08.21.249", + "b38:f0:e::f9:89.6.12.18", + "ef::8", + "5::ab", + "a::8:255.247.96.253", + "b:c0::c:254.248.95.254", + "::8c:2:99.251.024.3", + "98::c:247.240.249.57", + "9::9", + "628::f1ed:f", + "c::cca8", + "2::3:c", + "fde::8fcc:92:e", + "f::3", + "e85::7", + "8::b:f6", + "0::6:8ca", + "c8::6e:be8", + "87::e", + "6:9::a7:9", + "c::5", + "49::1:62", + "df:c0::f:9", + "a09a:8::21:887a", + "2:f::c", + "8bf5:5::2a6e:f8f", + "a:9e::bc:a", + "f:60::c:fd", + "59::52f:0:fa7", + "8268:6cf::f:9", + "c:abb::f", + "a:ff8d::9:7", + "05:c87::9c:9a", + "e:f::c:9a:1", + "ff6:8::962:e", + "9::bd", + "68:ec::6", + "3b8:f::94:3e9:9952", + "49b4:ae::899:b4", + "cb9:8e8:af::f4", + "8::10:9ae6:f9", + "b9::2:57", + "ff:fba9::d", + "4::a:8", + "caa:c:85a::2:3", + "5::a5:9", + "c:ad::a", + "9a:f:f65::b", + "f:df::9:0", + "c:b9::8de", + "d:f::a", + "ab88:d4:0::fc:8d", + "8f:ee2::3", + "f:f8::bf2:8c8", + "8::efc", + "e:5a::b", + "c:48::94", + "a:b:5::8", + "f:88f::f0a6", + "9:f:e::3", + "b::fedd", + "7b:f::c", + "edf4:7d::88", + "89::d", + "c0:a:62::ac", + "7:f::b", + "8::a2", + "0f::1", + "::", + "b:8::", + "44:a::", + "ef8f::", + "b:4:d::", + "a::", + "5a:8::", + "ddaf:ecbf::", + "f:bb:a1::", + "f8:f::", + "::e:38:ab:f8", + "::cd:c", + "::aa3:eb", + "::bf:9f9", + "::7ef:bf8a", + "::9", + "::a:9af", + "::315", + "::a:a", + "::aed3:a", + "f0eb:0:e8:b:c:a:254.098.233.17", + "bfa:7fc:c66d:15:e9a:ded:254.119.9.9", + "d:ffa8:9:a:879:3:202.39.08.245", + "8e:2:8:fa8a:f1d1:1aa8:252.254.245.81", + "5:d4:a:e9:8:8:06.38.98.253", + "9c5:4:a5c:f:a6:8c9d:05.250.8.2", + "d19a:2:f808:be:f:c:98.86.197.249", + "8:26ac:8:8:cb:f:242.00.254.85", + "38:e:1:0b88:f:0:8.89.248.92", + "e7:ff96:a:f:f:b:253.91.052.195", + "d:8:2:5:894:5:254.0.240.199", + "2:98:9:8aa:9c8f:fa:252.98.248.17", + "e9:d4f:890:ccbe:5:8:088.200.228.216", + "3:3:9:5:6a:df5:255.251.8.12", + "0280:3:8:8:4:9:255.000.251.249", + "8:af7:db:aa:0:9:238.248.250.255", + "ff:ee:9a:9252:a:289:059.083.18.255", + "9f6:5:fc9:b:a89:a:142.1.250.254", + "e:981a:da:bf94:9:f8:254.242.18.95", + "3c:1:4:f2:89:f:8.91.255.14", + "e::9a2:c:9.050.80.8", + "9::4a:07:fb:211.241.254.228", + "9be::2:e:215.189.48.188", + "f::f:d:069.148.99.168", + "f::a:97.18.240.47", + "c::a98e:1:251.253.252.254", + "668::82:214.87.208.9", + "9c0::cf0:ecb:253.208.238.255", + "a::0:f1:210.240.238.049", + "8::a:1:251.238.34.09", + "81:dfe::b8:8.255.249.248", + "d3::7:b:9:83.189.08.244", + "8::9:8:8:00.7.11.252", + "2:8::c:a8:250.221.9.249", + "2::f:99.8.249.247", + "c:22f5::5:2c:243.15.79.89", + "e:8e::da:251.243.255.2", + "f15f:9::a:255.70.247.218", + "f:b::9f38:31.220.94.022", + "9::9a48:03.98.249.119", + "d:d:9b87::2d:a:249.253.38.8", + "d86d:99b::a9b:5:242.236.8.244", + "eb:3::f:9cf:1.253.1.228", + "b::ba2:255.247.114.64", + "2f:ec:bcb::9:219.254.250.094", + "da8a:f6::a:e0:19.251.241.251", + "5e:c1::a:021.250.8.254", + "c:9::8c9b:248.219.212.252", + "2:a::8d4a:216.255.198.223", + "1f::66:255.30.08.150", + "bc2b:8f::2ff9:6.245.99.230", + "a:8::a8:9.251.246.255", + "f:7:7::98:06.14.1.208", + "e:2::9:218.249.255.254", + "79:f::6:250.255.98.246", + "47:9:fb9f::9:038.136.17.251", + "ed::a:247.9.23.239", + "6f::f1:88.254.119.9", + "a::d:218.199.236.0", + "fc88::9:203.196.04.95", + "::8.048.255.85", + "::253.07.255.36", + "9:d::253.7.178.229", + "::250.84.158.253", + "::8.55.204.248", + "2d:c::253.18.18.252", + "df9:88ca::248.255.108.17", + "8e9b::250.206.0.82", + "::209.8.254.209", + "::247.088.8.8", + "::cb:f:ba41:250.208.19.249", + "::fe:0e8:243.240.229.5", + "::c:223.251.5.226", + "::8:08.03.8.250", + "::f:8.88.11.255", + "::fda:48:aa:05.189.07.2", + "::8:c3f:f:240.06.212.255", + "::f:0aa:244.123.99.16", + "::c9b5:c:034.8.090.196", + "::98:c9:254.14.241.81" + ] + negatives = ["foo.bar", + "::::::::::::", + "yet another failure", + "de:6:c:ab5:6a::9:252.06.06.249", + "f9:5f7:fa38:9:b::b6:09.255.248.252", + "97:c:5b:81:8a::f5dd:144.252.250.9", + "9:8:cd:8:a9::f:247.255.09.255", + "18:1:8c:2:3::9:8.254.252.139", + "e:c298:3:e:a::bb12:254.246.05.250", + "e:e:c:8e:fd::8:253.8.49.231", + "9:97f:f:e929:8a::c9:0.8.252.10", + "0df:b24:7:89:c::2b:16.249.240.092", + "b:8f5f:485:c:9a::84c:178.7.249.34", + ] + +proc ok(pos: openarray[string]) = + for p in pos: + if not isIpAddress(p): + echo "failure ", p + +proc notok(neg: openarray[string]) = + for n in neg: + if isIpAddress(n): + echo "failure ", n + +ok(positives) +notok(negatives) +echo "all ok" diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim index 91e8b2ec7..ab24acc70 100644 --- a/tests/testament/specs.nim +++ b/tests/testament/specs.nim @@ -9,8 +9,11 @@ import parseutils, strutils, os, osproc, streams, parsecfg -const - cmdTemplate* = r"compiler" / "nim $target --lib:lib --hints:on -d:testing $options $file" + +var compilerPrefix* = "compiler" / "nim " + +proc cmdTemplate*(): string = + compilerPrefix & "$target --lib:lib --hints:on -d:testing $options $file" type TTestAction* = enum @@ -100,7 +103,7 @@ proc specDefaults*(result: var TSpec) = result.outp = "" result.nimout = "" result.ccodeCheck = "" - result.cmd = cmdTemplate + result.cmd = cmdTemplate() result.line = 0 result.column = 0 result.tfile = "" @@ -173,7 +176,7 @@ proc parseSpec*(filename: string): TSpec = raise newException(ValueError, "cannot interpret as a bool: " & e.value) of "cmd": if e.value.startsWith("nim "): - result.cmd = "compiler" / e.value + result.cmd = compilerPrefix & e.value[4..^1] else: result.cmd = e.value of "ccodecheck": result.ccodeCheck = e.value diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 2d758ef0d..0f74de013 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -34,6 +34,7 @@ Options: --failing only show failing/ignored tests --pedantic return non-zero status code if there are failures --targets:"c c++ js objc" run tests for specified targets (default: all) + --nim:path use a particular nim executable (default: compiler/nim) """ % resultsFile type @@ -367,7 +368,7 @@ proc testNoSpec(r: var TResults, test: TTest) = # does not extract the spec because the file is not supposed to have any #let tname = test.name.addFileExt(".nim") inc(r.total) - let given = callCompiler(cmdTemplate, test.name, test.options, test.target) + let given = callCompiler(cmdTemplate(), test.name, test.options, test.target) r.addResult(test, "", given.msg, given.err) if given.err == reSuccess: inc(r.passed) @@ -376,7 +377,7 @@ proc testC(r: var TResults, test: TTest) = let tname = test.name.addFileExt(".c") inc(r.total) styledEcho "Processing ", fgCyan, extractFilename(tname) - var given = callCCompiler(cmdTemplate, test.name & ".c", test.options, test.target) + var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, test.target) if given.err != reSuccess: r.addResult(test, "", given.msg, given.err) elif test.action == actionRun: @@ -424,6 +425,7 @@ proc main() = of "failing": optFailing = true of "pedantic": optPedantic = true of "targets": targets = parseTargets(p.val.string) + of "nim": compilerPrefix = p.val.string else: quit Usage p.next() if p.kind != cmdArgument: quit Usage diff --git a/tests/tuples/tunpack_asgn.nim b/tests/tuples/tunpack_asgn.nim index a48fcff5d..1dc7ff074 100644 --- a/tests/tuples/tunpack_asgn.nim +++ b/tests/tuples/tunpack_asgn.nim @@ -21,6 +21,8 @@ proc pg[T](x, y: var T) = # test as a top level statement: var x, y, a, b: int +# test for regression: +(x, y) = (1, 2) (x, y) = fooBar() echo x, " ", y diff --git a/tests/tuples/tuple_subscript.nim b/tests/tuples/tuple_subscript.nim new file mode 100644 index 000000000..021793dc3 --- /dev/null +++ b/tests/tuples/tuple_subscript.nim @@ -0,0 +1,40 @@ +discard """ + output: '''5 +5 +str2 +str2 +4''' +""" + +proc`[]` (t: tuple, key: string): string = + for name, field in fieldPairs(t): + if name == key: + return $field + return "" + + +proc`[]` [A,B](t: tuple, key: string, op: (proc(x: A): B)): B = + for name, field in fieldPairs(t): + when field is A: + if name == key: + return op(field) + +proc`[]=`[T](t: var tuple, key: string, val: T) = + for name, field in fieldPairs(t): + when field is T: + if name == key: + field = val + +var tt = (a: 1, b: "str1") + +# test built in operator +tt[0] = 5 +echo tt[0] +echo `[]`(tt, 0) + + +# test overloaded operator +tt["b"] = "str2" +echo tt["b"] +echo `[]`(tt, "b") +echo tt["b", proc(s: string) : int = s.len] \ No newline at end of file |