summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/assert/tunittests.nim3
-rw-r--r--tests/async/tasync_forward.nim9
-rw-r--r--tests/async/tasyncall.nim68
-rw-r--r--tests/async/tasyncdiscard.nim2
-rw-r--r--tests/async/tasynceverror.nim6
-rw-r--r--tests/async/tasyncexceptions.nim2
-rw-r--r--tests/async/tasyncfile.nim2
-rw-r--r--tests/async/tasynctry.nim10
-rw-r--r--tests/async/tawaitsemantics.nim59
-rw-r--r--tests/async/tgeneric_async.nim9
-rw-r--r--tests/async/tioselectors.nim408
-rw-r--r--tests/async/tioselectors.nim.cfg1
-rw-r--r--tests/async/tnewasyncudp.nim102
-rw-r--r--tests/async/treturn_await.nim23
-rw-r--r--tests/async/twinasyncrw.nim257
-rw-r--r--tests/ccgbugs/tcapture_static.nim13
-rw-r--r--tests/ccgbugs/tclosureeq.nim19
-rw-r--r--tests/ccgbugs/tescaping_temps.nim20
-rw-r--r--tests/ccgbugs/tinefficient_const_table.nim27
-rw-r--r--tests/ccgbugs/tmissingvolatile.nim2
-rw-r--r--tests/ccgbugs/tuplecast.nim8
-rw-r--r--tests/ccgbugs/tweakopenarray.nim12
-rw-r--r--tests/ccgbugs/twrong_rc_for_refarray.nim26
-rw-r--r--tests/ccgbugs/twrong_string_asgn.nim2
-rw-r--r--tests/closure/tdeeplynested.nim20
-rw-r--r--tests/closure/tflatmap.nim24
-rw-r--r--tests/closure/uclosures.nim15
-rw-r--r--tests/converter/tconverter_with_varargs.nim18
-rw-r--r--tests/converter/texplicit_conversion.nim13
-rw-r--r--tests/converter/tor_in_converter.nim23
-rw-r--r--tests/cpp/treturn_array.nim10
-rw-r--r--tests/cpp/ttemplatetype.nim9
-rw-r--r--tests/distinct/tnil.nim47
-rw-r--r--tests/enum/tenum.nim6
-rw-r--r--tests/float/tfloat4.nim32
-rw-r--r--tests/float/tfloat5.nim15
-rw-r--r--tests/float/tfloat6.nim21
-rw-r--r--tests/float/tfloat7.nim26
-rw-r--r--tests/gc/thavlak.nim457
-rw-r--r--tests/gc/tlists.nim37
-rw-r--r--tests/generics/t88.nim33
-rw-r--r--tests/generics/tforward_generic.nim28
-rw-r--r--tests/generics/tgenerictmpl2.nim31
-rw-r--r--tests/generics/ttable_alias.nim7
-rw-r--r--tests/generics/ttempl_in_generic.nim8
-rw-r--r--tests/generics/twrong_explicit_typeargs.nim16
-rw-r--r--tests/iter/tcomplex_openarray.nim33
-rw-r--r--tests/js/tclosures.nim51
-rw-r--r--tests/js/test2.nim13
-rw-r--r--tests/js/testtojsstr.nim8
-rw-r--r--tests/js/tstring_assignment.nim11
-rw-r--r--tests/lexer/tstrlits.nim6
-rw-r--r--tests/lookups/test.nim17
-rw-r--r--tests/lookups/tprefer_proc.nim4
-rw-r--r--tests/macros/tcomplexecho.nim42
-rw-r--r--tests/macros/tdumptree.nim2
-rw-r--r--tests/macros/tgettypeinst.nim122
-rw-r--r--tests/macros/tvarargsuntyped.nim79
-rw-r--r--tests/macros/typesafeprintf.nim48
-rw-r--r--tests/manyloc/keineschweine/lib/vehicles.nim2
-rw-r--r--tests/manyloc/nake/nakefile.nim4
-rw-r--r--tests/manyloc/named_argument_bug/main.nim.cfg1
-rw-r--r--tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim2
-rw-r--r--tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim2
-rw-r--r--tests/manyloc/named_argument_bug/tri_engine/gfx/tex.nim2
-rw-r--r--tests/manyloc/named_argument_bug/tri_engine/math/circle.nim4
-rw-r--r--tests/manyloc/named_argument_bug/tri_engine/math/vec.nim2
-rw-r--r--tests/metatype/tautoproc.nim2
-rw-r--r--tests/metatype/tmodulo.nim20
-rw-r--r--tests/metatype/tvoid_must_not_match.nim21
-rw-r--r--tests/method/tgeneric_methods.nim24
-rw-r--r--tests/method/tmultim6.nim20
-rw-r--r--tests/modules/texplicit_system_import.nim9
-rw-r--r--tests/newconfig/mymath.nim4
-rw-r--r--tests/newconfig/tfoo.nim6
-rw-r--r--tests/newconfig/tfoo.nims5
-rw-r--r--tests/objects/tobject3.nim2
-rw-r--r--tests/osproc/passenv.nim32
-rw-r--r--tests/overload/tissue4475.nim6
-rw-r--r--tests/overload/tstmtoverload.nim2
-rw-r--r--tests/overload/tvart_varargs.nim18
-rw-r--r--tests/parallel/twrong_refcounts.nim2
-rw-r--r--tests/parser/tdo.nim79
-rw-r--r--tests/stdlib/nre/find.nim4
-rw-r--r--tests/stdlib/thtmlparser2814.nim44
-rw-r--r--tests/stdlib/tmath.nim2
-rw-r--r--tests/stdlib/tos.nim92
-rw-r--r--tests/stdlib/tparscfg.nim58
-rw-r--r--tests/stdlib/tparseuints.nim11
-rw-r--r--tests/stdlib/trstgen.nim139
-rw-r--r--tests/stdlib/tsplit.nim2
-rw-r--r--tests/stdlib/tunittest.nim8
-rw-r--r--tests/template/mlt.nim3
-rw-r--r--tests/template/t2do.nim7
-rw-r--r--tests/template/tlt.nim7
-rw-r--r--tests/template/typedescids.nim17
-rw-r--r--tests/test_nimscript.nims25
-rw-r--r--tests/testament/categories.nim17
-rw-r--r--tests/testament/specs.nim15
-rw-r--r--tests/testament/tester.nim19
-rw-r--r--tests/threads/ttryrecv.nim2
-rw-r--r--tests/trmacros/tpatterns.nim8
-rw-r--r--tests/trmacros/tstatic_t_bug.nim24
-rw-r--r--tests/tuples/tconver_tuple.nim23
-rw-r--r--tests/tuples/tuple_with_nil.nim2
-rw-r--r--tests/tuples/twrong_generic_caching.nim4
-rw-r--r--tests/typerel/tclosure_nil_as_default.nim11
-rw-r--r--tests/typerel/temptynode.nim16
-rw-r--r--tests/typerel/tgeneric_subtype_regression.nim19
-rw-r--r--tests/types/tassignemptytuple.nim11
-rw-r--r--tests/types/typeof_produces_alias.nim25
-rw-r--r--tests/usingstmt/tthis.nim15
-rw-r--r--tests/vm/meta.nim240
-rw-r--r--tests/vm/tanonproc.nim52
-rw-r--r--tests/vm/tcomponent.nim132
-rw-r--r--tests/vm/tconst_float_as_int.nim3
-rw-r--r--tests/vm/tinheritance.nim29
-rw-r--r--tests/vm/tmitems.nim31
-rw-r--r--tests/vm/tvmmisc.nim16
-rw-r--r--tests/vm/twrong_concat.nim28
120 files changed, 3750 insertions, 104 deletions
diff --git a/tests/assert/tunittests.nim b/tests/assert/tunittests.nim
index cbbfe63c6..de917511c 100644
--- a/tests/assert/tunittests.nim
+++ b/tests/assert/tunittests.nim
@@ -1 +1,4 @@
+discard """
+output: ""
+"""
 import "../template/utemplates", "../closure/uclosures"
diff --git a/tests/async/tasync_forward.nim b/tests/async/tasync_forward.nim
new file mode 100644
index 000000000..ffb7acafd
--- /dev/null
+++ b/tests/async/tasync_forward.nim
@@ -0,0 +1,9 @@
+
+import asyncdispatch
+
+# bug #1970
+
+proc foo {.async.}
+
+proc foo {.async.} =
+  discard
diff --git a/tests/async/tasyncall.nim b/tests/async/tasyncall.nim
new file mode 100644
index 000000000..60ba557cc
--- /dev/null
+++ b/tests/async/tasyncall.nim
@@ -0,0 +1,68 @@
+discard """
+  file: "tasyncall.nim"
+  exitcode: 0
+"""
+import times, sequtils
+import asyncdispatch
+
+const
+  taskCount = 10
+  sleepDuration = 500
+
+proc futureWithValue(x: int): Future[int] {.async.} =
+  await sleepAsync(sleepDuration)
+  return x
+
+proc futureWithoutValue() {.async.} =
+  await sleepAsync(1000)
+
+proc testFuturesWithValue(x: int): seq[int] =
+  var tasks = newSeq[Future[int]](taskCount)
+
+  for i in 0..<taskCount:
+    tasks[i] = futureWithValue(x)
+
+  result = waitFor all(tasks)
+
+proc testFuturesWithoutValues() =
+  var tasks = newSeq[Future[void]](taskCount)
+
+  for i in 0..<taskCount:
+    tasks[i] = futureWithoutValue()
+
+  waitFor all(tasks)
+
+proc testVarargs(x, y, z: int): seq[int] =
+  let
+    a = futureWithValue(x)
+    b = futureWithValue(y)
+    c = futureWithValue(z)
+
+  result = waitFor all(a, b, c)
+
+block:
+  let
+    startTime = cpuTime()
+    results = testFuturesWithValue(42)
+    expected = repeat(42, taskCount)
+    execTime = cpuTime() - startTime
+
+  doAssert execTime * 1000 < taskCount * sleepDuration
+  doAssert results == expected
+
+block:
+  let startTime = cpuTime()
+  testFuturesWithoutValues()
+  let execTime = cpuTime() - startTime
+
+  doAssert execTime * 1000 < taskCount * sleepDuration
+
+block:
+  let
+    startTime = cpuTime()
+    results = testVarargs(1, 2, 3)
+    expected = @[1, 2, 3]
+    execTime = cpuTime() - startTime
+
+  doAssert execTime * 100 < taskCount * sleepDuration
+  doAssert results == expected
diff --git a/tests/async/tasyncdiscard.nim b/tests/async/tasyncdiscard.nim
index 71aba29e2..e7c87ad42 100644
--- a/tests/async/tasyncdiscard.nim
+++ b/tests/async/tasyncdiscard.nim
@@ -36,4 +36,4 @@ proc main {.async.} =
   discard await g()
   echo 6
 
-asyncCheck main()
+waitFor(main())
diff --git a/tests/async/tasynceverror.nim b/tests/async/tasynceverror.nim
index 22b4fe9a7..dd05c831b 100644
--- a/tests/async/tasynceverror.nim
+++ b/tests/async/tasynceverror.nim
@@ -1,9 +1,9 @@
 discard """
   file: "tasynceverror.nim"
   exitcode: 1
-  outputsub: "Error: unhandled exception: Connection reset by peer"
+  outputsub: "Error: unhandled exception: "
 """
-
+# error message is actually different on OSX
 import
     asyncdispatch,
     asyncnet,
@@ -43,7 +43,7 @@ else:
         await s.connect(testHost, testPort)
 
         var ps = await ls.accept()
-        SocketHandle(ls).close()
+        closeSocket(ls)
 
         await ps.send("test 1", flags={})
         s.close()
diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim
index aab08e30f..efe31ef27 100644
--- a/tests/async/tasyncexceptions.nim
+++ b/tests/async/tasyncexceptions.nim
@@ -5,6 +5,8 @@ discard """
 """
 import asyncdispatch
 
+# Note: This is a test case for a bug.
+
 proc accept(): Future[int] {.async.} =
   await sleepAsync(100)
   result = 4
diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim
index 05cda5e5f..26a9bb391 100644
--- a/tests/async/tasyncfile.nim
+++ b/tests/async/tasyncfile.nim
@@ -24,7 +24,7 @@ proc main() {.async.} =
     var file = openAsync(fn, fmAppend)
     await file.write("\ntest2")
     let errorTest = file.readAll()
-    await errorTest
+    echo await errorTest
     doAssert errorTest.failed
     file.close()
     file = openAsync(fn, fmRead)
diff --git a/tests/async/tasynctry.nim b/tests/async/tasynctry.nim
index f77198e2e..5930f296f 100644
--- a/tests/async/tasynctry.nim
+++ b/tests/async/tasynctry.nim
@@ -48,7 +48,7 @@ proc catch() {.async.} =
   except OSError, EInvalidField:
     assert false
 
-asyncCheck catch()
+waitFor catch()
 
 proc test(): Future[bool] {.async.} =
   result = false
@@ -92,13 +92,13 @@ proc test4(): Future[int] {.async.} =
     result = 2
 
 var x = test()
-assert x.read
+assert x.waitFor()
 
 x = test2()
-assert x.read
+assert x.waitFor()
 
 var y = test3()
-assert y.read == 2
+assert y.waitFor() == 2
 
 y = test4()
-assert y.read == 2
+assert y.waitFor() == 2
diff --git a/tests/async/tawaitsemantics.nim b/tests/async/tawaitsemantics.nim
new file mode 100644
index 000000000..3e0c3903e
--- /dev/null
+++ b/tests/async/tawaitsemantics.nim
@@ -0,0 +1,59 @@
+discard """
+  file: "tawaitsemantics.nim"
+  exitcode: 0
+  output: '''
+Error caught
+Test infix
+Test call
+'''
+"""
+
+import asyncdispatch
+
+# This tests the behaviour of 'await' under different circumstances.
+# For example, when awaiting Future variable and this future has failed the
+# exception shouldn't be raised as described here
+# https://github.com/nim-lang/Nim/issues/4170
+
+proc thrower(): Future[void] =
+  result = newFuture[void]()
+  result.fail(newException(Exception, "Test"))
+
+proc dummy: Future[void] =
+  result = newFuture[void]()
+  result.complete()
+
+proc testInfix() {.async.} =
+  # Test the infix operator semantics.
+  var fut = thrower()
+  var fut2 = dummy()
+  await fut or fut2 # Shouldn't raise.
+  # TODO: what about: await thrower() or fut2?
+
+proc testCall() {.async.} =
+  await thrower()
+
+proc tester() {.async.} =
+  # Test that we can handle exceptions without 'try'
+  var fut = thrower()
+  doAssert fut.finished
+  doAssert fut.failed
+  doAssert fut.error.msg == "Test"
+  await fut # We are awaiting a 'Future', so no `read` occurs.
+  doAssert fut.finished
+  doAssert fut.failed
+  doAssert fut.error.msg == "Test"
+  echo("Error caught")
+
+  fut = testInfix()
+  await fut
+  doAssert fut.finished
+  doAssert(not fut.failed)
+  echo("Test infix")
+
+  fut = testCall()
+  await fut
+  doAssert fut.failed
+  echo("Test call")
+
+waitFor(tester())
diff --git a/tests/async/tgeneric_async.nim b/tests/async/tgeneric_async.nim
new file mode 100644
index 000000000..af6370181
--- /dev/null
+++ b/tests/async/tgeneric_async.nim
@@ -0,0 +1,9 @@
+
+import asyncdispatch
+
+when true:
+  # bug #2377
+  proc test[T](v: T) {.async.} =
+    echo $v
+
+  asyncCheck test[int](1)
diff --git a/tests/async/tioselectors.nim b/tests/async/tioselectors.nim
new file mode 100644
index 000000000..2237de01a
--- /dev/null
+++ b/tests/async/tioselectors.nim
@@ -0,0 +1,408 @@
+discard """
+  file: "tioselectors.nim"
+  output: "All tests passed!"
+"""
+import ioselectors
+
+const hasThreadSupport = compileOption("threads")
+
+template processTest(t, x: untyped) =
+  #stdout.write(t)
+  #stdout.flushFile()
+  if not x: echo(t & " FAILED\r\n")
+
+when not defined(windows):
+  import os, posix, osproc, nativesockets, times
+
+  const supportedPlatform = defined(macosx) or defined(freebsd) or
+                            defined(netbsd) or defined(openbsd) or
+                            defined(linux)
+
+  proc socket_notification_test(): bool =
+    proc create_test_socket(): SocketHandle =
+      var sock = posix.socket(posix.AF_INET, posix.SOCK_STREAM,
+                              posix.IPPROTO_TCP)
+      var x: int = fcntl(sock, F_GETFL, 0)
+      if x == -1: raiseOSError(osLastError())
+      else:
+        var mode = x or O_NONBLOCK
+        if fcntl(sock, F_SETFL, mode) == -1:
+          raiseOSError(osLastError())
+      result = sock
+
+    var client_message = "SERVER HELLO =>"
+    var server_message = "CLIENT HELLO"
+    var buffer : array[128, char]
+
+    var selector = newSelector[int]()
+    var client_socket = create_test_socket()
+    var server_socket = create_test_socket()
+
+    registerHandle(selector, server_socket, {Event.Read}, 0)
+    registerHandle(selector, client_socket, {Event.Write}, 0)
+
+    var option : int32 = 1
+    if setsockopt(server_socket, cint(SOL_SOCKET), cint(SO_REUSEADDR),
+                  addr(option), sizeof(option).SockLen) < 0:
+      raiseOSError(osLastError())
+
+    var aiList = getAddrInfo("0.0.0.0", Port(13337))
+    if bindAddr(server_socket, aiList.ai_addr,
+                aiList.ai_addrlen.Socklen) < 0'i32:
+      dealloc(aiList)
+      raiseOSError(osLastError())
+    discard server_socket.listen()
+    dealloc(aiList)
+
+    aiList = getAddrInfo("127.0.0.1", Port(13337))
+    discard posix.connect(client_socket, aiList.ai_addr,
+                          aiList.ai_addrlen.Socklen)
+    dealloc(aiList)
+    discard selector.select(100)
+    var rc1 = selector.select(100)
+    assert(len(rc1) == 2)
+
+    var sockAddress: SockAddr
+    var addrLen = sizeof(sockAddress).Socklen
+    var server2_socket = accept(server_socket,
+                                cast[ptr SockAddr](addr(sockAddress)),
+                                addr(addrLen))
+    assert(server2_socket != osInvalidSocket)
+    selector.registerHandle(server2_socket, {Event.Read}, 0)
+
+    if posix.send(client_socket, addr(client_message[0]),
+                  len(client_message), 0) == -1:
+      raiseOSError(osLastError())
+
+    selector.updateHandle(client_socket, {Event.Read})
+
+    var rc2 = selector.select(100)
+    assert(len(rc2) == 1)
+
+    var read_count = posix.recv(server2_socket, addr buffer[0], 128, 0)
+    if read_count == -1:
+      raiseOSError(osLastError())
+
+    assert(read_count == len(client_message))
+    var test1 = true
+    for i in 0..<read_count:
+      if client_message[i] != buffer[i]:
+        test1 = false
+        break
+    assert(test1)
+
+    selector.updateHandle(server2_socket, {Event.Write})
+    var rc3 = selector.select(0)
+    assert(len(rc3) == 1)
+    if posix.send(server2_socket, addr(server_message[0]),
+                  len(server_message), 0) == -1:
+      raiseOSError(osLastError())
+    selector.updateHandle(server2_socket, {Event.Read})
+
+    var rc4 = selector.select(100)
+    assert(len(rc4) == 1)
+    read_count = posix.recv(client_socket, addr(buffer[0]), 128, 0)
+    if read_count == -1:
+      raiseOSError(osLastError())
+
+    assert(read_count == len(server_message))
+    var test2 = true
+    for i in 0..<read_count:
+      if server_message[i] != buffer[i]:
+        test2 = false
+        break
+    assert(test2)
+
+    selector.unregister(server_socket)
+    selector.unregister(server2_socket)
+    selector.unregister(client_socket)
+    discard posix.close(server_socket)
+    discard posix.close(server2_socket)
+    discard posix.close(client_socket)
+    assert(selector.isEmpty())
+    close(selector)
+    result = true
+
+  proc event_notification_test(): bool =
+    var selector = newSelector[int]()
+    var event = newSelectEvent()
+    selector.registerEvent(event, 1)
+    selector.flush()
+    event.setEvent()
+    var rc1 = selector.select(0)
+    event.setEvent()
+    var rc2 = selector.select(0)
+    var rc3 = selector.select(0)
+    assert(len(rc1) == 1 and len(rc2) == 1 and len(rc3) == 0)
+    var ev1 = rc1[0].data
+    var ev2 = rc2[0].data
+    assert(ev1 == 1 and ev2 == 1)
+    selector.unregister(event)
+    event.close()
+    assert(selector.isEmpty())
+    selector.close()
+    result = true
+
+  when supportedPlatform:
+    proc timer_notification_test(): bool =
+      var selector = newSelector[int]()
+      var timer = selector.registerTimer(100, false, 0)
+      var rc1 = selector.select(140)
+      var rc2 = selector.select(140)
+      assert(len(rc1) == 1 and len(rc2) == 1)
+      selector.unregister(timer)
+      selector.flush()
+      selector.registerTimer(100, true, 0)
+      var rc3 = selector.select(120)
+      var rc4 = selector.select(120)
+      assert(len(rc3) == 1 and len(rc4) == 0)
+      assert(selector.isEmpty())
+      selector.close()
+      result = true
+
+    proc process_notification_test(): bool =
+      var selector = newSelector[int]()
+      var process2 = startProcess("/bin/sleep", "", ["2"], nil,
+                           {poStdErrToStdOut, poUsePath})
+      discard startProcess("/bin/sleep", "", ["1"], nil,
+                           {poStdErrToStdOut, poUsePath})
+
+      selector.registerProcess(process2.processID, 0)
+      var rc1 = selector.select(1500)
+      var rc2 = selector.select(1500)
+      var r = len(rc1) + len(rc2)
+      assert(r == 1)
+      result = true
+
+    proc signal_notification_test(): bool =
+      var sigset1n, sigset1o, sigset2n, sigset2o: Sigset
+      var pid = posix.getpid()
+
+      discard sigemptyset(sigset1n)
+      discard sigemptyset(sigset1o)
+      discard sigemptyset(sigset2n)
+      discard sigemptyset(sigset2o)
+
+      when hasThreadSupport:
+        if pthread_sigmask(SIG_BLOCK, sigset1n, sigset1o) == -1:
+          raiseOSError(osLastError())
+      else:
+        if sigprocmask(SIG_BLOCK, sigset1n, sigset1o) == -1:
+          raiseOSError(osLastError())
+
+      var selector = newSelector[int]()
+      var s1 = selector.registerSignal(SIGUSR1, 1)
+      var s2 = selector.registerSignal(SIGUSR2, 2)
+      var s3 = selector.registerSignal(SIGTERM, 3)
+      selector.flush()
+
+      discard posix.kill(pid, SIGUSR1)
+      discard posix.kill(pid, SIGUSR2)
+      discard posix.kill(pid, SIGTERM)
+      var rc = selector.select(0)
+      selector.unregister(s1)
+      selector.unregister(s2)
+      selector.unregister(s3)
+
+      when hasThreadSupport:
+        if pthread_sigmask(SIG_BLOCK, sigset2n, sigset2o) == -1:
+          raiseOSError(osLastError())
+      else:
+        if sigprocmask(SIG_BLOCK, sigset2n, sigset2o) == -1:
+          raiseOSError(osLastError())
+
+      assert(len(rc) == 3)
+      assert(rc[0].data + rc[1].data + rc[2].data == 6) # 1 + 2 + 3
+      assert(equalMem(addr sigset1o, addr sigset2o, sizeof(Sigset)))
+      assert(selector.isEmpty())
+      result = true
+
+  when hasThreadSupport:
+
+    var counter = 0
+
+    proc event_wait_thread(event: SelectEvent) {.thread.} =
+      var selector = newSelector[int]()
+      selector.registerEvent(event, 1)
+      selector.flush()
+      var rc = selector.select(1000)
+      if len(rc) == 1:
+        inc(counter)
+      selector.unregister(event)
+      assert(selector.isEmpty())
+
+    proc mt_event_test(): bool =
+      var
+        thr: array[0..7, Thread[SelectEvent]]
+      var selector = newSelector[int]()
+      var sock = newNativeSocket()
+      var event = newSelectEvent()
+      for i in 0..high(thr):
+        createThread(thr[i], event_wait_thread, event)
+      selector.registerHandle(sock, {Event.Read}, 1)
+      discard selector.select(500)
+      selector.unregister(sock)
+      event.setEvent()
+      joinThreads(thr)
+      assert(counter == 1)
+      result = true
+
+  processTest("Socket notification test...", socket_notification_test())
+  processTest("User event notification test...", event_notification_test())
+  when hasThreadSupport:
+    processTest("Multithreaded user event notification test...",
+                mt_event_test())
+  when supportedPlatform:
+    processTest("Timer notification test...", timer_notification_test())
+    processTest("Process notification test...", process_notification_test())
+    processTest("Signal notification test...", signal_notification_test())
+  echo("All tests passed!")
+else:
+  import nativesockets, winlean, os, osproc
+
+  proc socket_notification_test(): bool =
+    proc create_test_socket(): SocketHandle =
+      var sock = newNativeSocket()
+      setBlocking(sock, false)
+      result = sock
+
+    var client_message = "SERVER HELLO =>"
+    var server_message = "CLIENT HELLO"
+    var buffer : array[128, char]
+
+    var selector = newSelector[int]()
+    var client_socket = create_test_socket()
+    var server_socket = create_test_socket()
+
+    selector.registerHandle(server_socket, {Event.Read}, 0)
+    selector.registerHandle(client_socket, {Event.Write}, 0)
+
+    var option : int32 = 1
+    if setsockopt(server_socket, cint(SOL_SOCKET), cint(SO_REUSEADDR),
+                  addr(option), sizeof(option).SockLen) < 0:
+      raiseOSError(osLastError())
+
+    var aiList = getAddrInfo("0.0.0.0", Port(13337))
+    if bindAddr(server_socket, aiList.ai_addr,
+                aiList.ai_addrlen.Socklen) < 0'i32:
+      dealloc(aiList)
+      raiseOSError(osLastError())
+    discard server_socket.listen()
+    dealloc(aiList)
+
+    aiList = getAddrInfo("127.0.0.1", Port(13337))
+    discard connect(client_socket, aiList.ai_addr,
+                    aiList.ai_addrlen.Socklen)
+    dealloc(aiList)
+    # for some reason Windows select doesn't return both
+    # descriptors from first call, so we need to make 2 calls
+    discard selector.select(100)
+    var rcm = selector.select(100)
+    assert(len(rcm) == 2)
+
+    var sockAddress = SockAddr()
+    var addrLen = sizeof(sockAddress).Socklen
+    var server2_socket = accept(server_socket,
+                                cast[ptr SockAddr](addr(sockAddress)),
+                                addr(addrLen))
+    assert(server2_socket != osInvalidSocket)
+    selector.registerHandle(server2_socket, {Event.Read}, 0)
+
+    if send(client_socket, cast[pointer](addr(client_message[0])),
+            cint(len(client_message)), 0) == -1:
+      raiseOSError(osLastError())
+
+    selector.updateHandle(client_socket, {Event.Read})
+
+    var rc2 = selector.select(100)
+    assert(len(rc2) == 1)
+
+    var read_count = recv(server2_socket, addr buffer[0], 128, 0)
+    if read_count == -1:
+      raiseOSError(osLastError())
+
+    assert(read_count == len(client_message))
+    var test1 = true
+    for i in 0..<read_count:
+      if client_message[i] != buffer[i]:
+        test1 = false
+        break
+    assert(test1)
+
+    if send(server2_socket, cast[pointer](addr(server_message[0])),
+                  cint(len(server_message)), 0) == -1:
+      raiseOSError(osLastError())
+
+    var rc3 = selector.select(0)
+    assert(len(rc3) == 1)
+    read_count = recv(client_socket, addr(buffer[0]), 128, 0)
+    if read_count == -1:
+      raiseOSError(osLastError())
+
+    assert(read_count == len(server_message))
+    var test2 = true
+    for i in 0..<read_count:
+      if server_message[i] != buffer[i]:
+        test2 = false
+        break
+    assert(test2)
+
+    selector.unregister(server_socket)
+    selector.unregister(server2_socket)
+    selector.unregister(client_socket)
+    close(server_socket)
+    close(server2_socket)
+    close(client_socket)
+    assert(selector.isEmpty())
+    close(selector)
+    result = true
+
+  proc event_notification_test(): bool =
+    var selector = newSelector[int]()
+    var event = newSelectEvent()
+    selector.registerEvent(event, 1)
+    selector.flush()
+    event.setEvent()
+    var rc1 = selector.select(0)
+    event.setEvent()
+    var rc2 = selector.select(0)
+    var rc3 = selector.select(0)
+    assert(len(rc1) == 1 and len(rc2) == 1 and len(rc3) == 0)
+    var ev1 = rc1[0].data
+    var ev2 = rc2[0].data
+    assert(ev1 == 1 and ev2 == 1)
+    selector.unregister(event)
+    event.close()
+    assert(selector.isEmpty())
+    selector.close()
+    result = true
+
+  when hasThreadSupport:
+    var counter = 0
+
+    proc event_wait_thread(event: SelectEvent) {.thread.} =
+      var selector = newSelector[int]()
+      selector.registerEvent(event, 1)
+      selector.flush()
+      var rc = selector.select(500)
+      if len(rc) == 1:
+        inc(counter)
+      selector.unregister(event)
+      assert(selector.isEmpty())
+
+    proc mt_event_test(): bool =
+      var thr: array[0..7, Thread[SelectEvent]]
+      var event = newSelectEvent()
+      for i in 0..high(thr):
+        createThread(thr[i], event_wait_thread, event)
+      event.setEvent()
+      joinThreads(thr)
+      assert(counter == 1)
+      result = true
+
+  processTest("Socket notification test...", socket_notification_test())
+  processTest("User event notification test...", event_notification_test())
+  when hasThreadSupport:
+    processTest("Multithreaded user event notification test...",
+                 mt_event_test())
+  echo("All tests passed!")
diff --git a/tests/async/tioselectors.nim.cfg b/tests/async/tioselectors.nim.cfg
new file mode 100644
index 000000000..b1b896858
--- /dev/null
+++ b/tests/async/tioselectors.nim.cfg
@@ -0,0 +1 @@
+threads:on -d:threadsafe
diff --git a/tests/async/tnewasyncudp.nim b/tests/async/tnewasyncudp.nim
new file mode 100644
index 000000000..7025fa20d
--- /dev/null
+++ b/tests/async/tnewasyncudp.nim
@@ -0,0 +1,102 @@
+discard """
+  file: "tnewasyncudp.nim"
+  output: "5000"
+"""
+import asyncdispatch, nativesockets, net, strutils, os
+
+when defined(windows):
+  import winlean
+else:
+  import posix
+
+var msgCount = 0
+var recvCount = 0
+
+const
+  messagesToSend = 100
+  swarmSize = 50
+  serverPort = 10333
+
+var
+  sendports = 0
+  recvports = 0
+
+proc saveSendingPort(port: int) =
+  sendports = sendports + port
+
+proc saveReceivedPort(port: int) =
+  recvports = recvports + port
+
+proc prepareAddress(intaddr: uint32, intport: uint16): ptr Sockaddr_in =
+  result = cast[ptr Sockaddr_in](alloc0(sizeof(Sockaddr_in)))
+  when defined(windows):
+    result.sin_family = toInt(nativesockets.AF_INET).int16
+  else:
+    result.sin_family = toInt(nativesockets.AF_INET)
+  result.sin_port = htons(intport)
+  result.sin_addr.s_addr = htonl(intaddr)
+
+proc launchSwarm(name: ptr SockAddr) {.async.} =
+  var i = 0
+  var k = 0
+  while i < swarmSize:
+    var peeraddr = prepareAddress(INADDR_ANY, 0)
+    var sock = newAsyncNativeSocket(nativesockets.AF_INET,
+                                    nativesockets.SOCK_DGRAM,
+                                    Protocol.IPPROTO_UDP)
+    if bindAddr(sock.SocketHandle, cast[ptr SockAddr](peeraddr),
+              sizeof(Sockaddr_in).Socklen) < 0'i32:
+      raiseOSError(osLastError())
+    let sockport = getSockName(sock.SocketHandle).int
+    k = 0
+    while k < messagesToSend:
+      var message = "Message " & $(i * messagesToSend + k)
+      await sendTo(sock, addr message[0], len(message),
+                   name, sizeof(Sockaddr_in).SockLen)
+      saveSendingPort(sockport)
+      inc(k)
+    closeSocket(sock)
+    inc(i)
+
+proc readMessages(server: AsyncFD) {.async.} =
+  var buffer: array[16384, char]
+  var slen = sizeof(Sockaddr_in).SockLen
+  var saddr = Sockaddr_in()
+  var maxResponses = (swarmSize * messagesToSend)
+
+  var i = 0
+  while i < maxResponses:
+    zeroMem(addr(buffer[0]), 16384)
+    zeroMem(cast[pointer](addr(saddr)), sizeof(Sockaddr_in))
+    var size = await recvFromInto(server, cast[cstring](addr buffer[0]),
+                                  16384, cast[ptr SockAddr](addr(saddr)),
+                                  addr(slen))
+    size = 0
+    var grammString = $buffer
+    if grammString.startswith("Message ") and
+       saddr.sin_addr.s_addr == 0x100007F:
+      inc(msgCount)
+      saveReceivedPort(ntohs(saddr.sin_port).int)
+      inc(recvCount)
+    inc(i)
+
+proc createServer() {.async.} =
+  var name = prepareAddress(INADDR_ANY, serverPort)
+  var server = newAsyncNativeSocket(nativesockets.AF_INET,
+                                    nativesockets.SOCK_DGRAM,
+                                    Protocol.IPPROTO_UDP)
+  if bindAddr(server.SocketHandle, cast[ptr SockAddr](name),
+              sizeof(Sockaddr_in).Socklen) < 0'i32:
+    raiseOSError(osLastError())
+  asyncCheck readMessages(server)
+
+var name = prepareAddress(0x7F000001, serverPort) # 127.0.0.1
+asyncCheck createServer()
+asyncCheck launchSwarm(cast[ptr SockAddr](name))
+while true:
+  poll()
+  if recvCount == swarmSize * messagesToSend:
+    break
+assert msgCount == swarmSize * messagesToSend
+assert sendports == recvports
+echo msgCount
diff --git a/tests/async/treturn_await.nim b/tests/async/treturn_await.nim
new file mode 100644
index 000000000..8d266d665
--- /dev/null
+++ b/tests/async/treturn_await.nim
@@ -0,0 +1,23 @@
+
+# bug #4371
+
+import strutils, asyncdispatch, asynchttpserver
+
+type
+  List[A] = ref object
+    value: A
+    next: List[A]
+  StrPair* = tuple[k, v: string]
+  Context* = object
+    position*: int
+    accept*: bool
+    headers*: List[StrPair]
+  Handler* = proc(req: ref Request, ctx: Context): Future[Context]
+
+proc logging*(handler: Handler): auto =
+  proc h(req: ref Request, ctx: Context): Future[Context] {.async.} =
+    let ret = handler(req, ctx)
+    debugEcho "$3 $1 $2".format(req.reqMethod, req.url.path, req.hostname)
+    return await ret
+
+  return h
diff --git a/tests/async/twinasyncrw.nim b/tests/async/twinasyncrw.nim
new file mode 100644
index 000000000..17b7d1cf5
--- /dev/null
+++ b/tests/async/twinasyncrw.nim
@@ -0,0 +1,257 @@
+discard """
+  file: "twinasyncrw.nim"
+  output: "5000"
+"""
+when defined(windows):
+  import asyncdispatch, nativesockets, net, strutils, os, winlean
+
+  var msgCount = 0
+
+  const
+    swarmSize = 50
+    messagesToSend = 100
+
+  var clientCount = 0
+
+  proc winConnect*(socket: AsyncFD, address: string, port: Port,
+    domain = Domain.AF_INET): Future[void] =
+    var retFuture = newFuture[void]("winConnect")
+    proc cb(fd: AsyncFD): bool =
+      var ret = SocketHandle(fd).getSockOptInt(cint(SOL_SOCKET), cint(SO_ERROR))
+      if ret == 0:
+          # We have connected.
+          retFuture.complete()
+          return true
+      else:
+          retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
+          return true
+
+    var aiList = getAddrInfo(address, port, domain)
+    var success = false
+    var lastError: OSErrorCode = OSErrorCode(0)
+    var it = aiList
+    while it != nil:
+      var ret = nativesockets.connect(socket.SocketHandle, it.ai_addr, it.ai_addrlen.Socklen)
+      if ret == 0:
+        # Request to connect completed immediately.
+        success = true
+        retFuture.complete()
+        break
+      else:
+        lastError = osLastError()
+        if lastError.int32 == WSAEWOULDBLOCK:
+          success = true
+          addWrite(socket, cb)
+          break
+        else:
+          success = false
+      it = it.ai_next
+
+    dealloc(aiList)
+    if not success:
+      retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+    return retFuture
+
+  proc winRecv*(socket: AsyncFD, size: int,
+             flags = {SocketFlag.SafeDisconn}): Future[string] =
+    var retFuture = newFuture[string]("recv")
+
+    var readBuffer = newString(size)
+
+    proc cb(sock: AsyncFD): bool =
+      result = true
+      let res = recv(sock.SocketHandle, addr readBuffer[0], size.cint,
+                     flags.toOSFlags())
+      if res < 0:
+        let lastError = osLastError()
+        if flags.isDisconnectionError(lastError):
+          retFuture.complete("")
+        else:
+          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+      elif res == 0:
+        # Disconnected
+        retFuture.complete("")
+      else:
+        readBuffer.setLen(res)
+        retFuture.complete(readBuffer)
+    # TODO: The following causes a massive slowdown.
+    #if not cb(socket):
+    addRead(socket, cb)
+    return retFuture
+
+  proc winRecvInto*(socket: AsyncFD, buf: cstring, size: int,
+                  flags = {SocketFlag.SafeDisconn}): Future[int] =
+    var retFuture = newFuture[int]("winRecvInto")
+
+    proc cb(sock: AsyncFD): bool =
+      result = true
+      let res = nativesockets.recv(sock.SocketHandle, buf, size.cint,
+                                   flags.toOSFlags())
+      if res < 0:
+        let lastError = osLastError()
+        if flags.isDisconnectionError(lastError):
+          retFuture.complete(0)
+        else:
+          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+      else:
+        retFuture.complete(res)
+    # TODO: The following causes a massive slowdown.
+    #if not cb(socket):
+    addRead(socket, cb)
+    return retFuture
+
+  proc winSend*(socket: AsyncFD, data: string,
+             flags = {SocketFlag.SafeDisconn}): Future[void] =
+    var retFuture = newFuture[void]("winSend")
+
+    var written = 0
+
+    proc cb(sock: AsyncFD): bool =
+      result = true
+      let netSize = data.len-written
+      var d = data.cstring
+      let res = nativesockets.send(sock.SocketHandle, addr d[written], netSize.cint, 0)
+      if res < 0:
+        let lastError = osLastError()
+        if flags.isDisconnectionError(lastError):
+          retFuture.complete()
+        else:
+          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+      else:
+        written.inc(res)
+        if res != netSize:
+          result = false # We still have data to send.
+        else:
+          retFuture.complete()
+    # TODO: The following causes crashes.
+    #if not cb(socket):
+    addWrite(socket, cb)
+    return retFuture
+
+  proc winAcceptAddr*(socket: AsyncFD, flags = {SocketFlag.SafeDisconn}):
+      Future[tuple[address: string, client: AsyncFD]] =
+    var retFuture = newFuture[tuple[address: string,
+        client: AsyncFD]]("winAcceptAddr")
+    proc cb(sock: AsyncFD): bool =
+      result = true
+      if not retFuture.finished:
+        var sockAddress = Sockaddr()
+        var addrLen = sizeof(sockAddress).Socklen
+        var client = nativesockets.accept(sock.SocketHandle,
+                                          cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
+        if client == osInvalidSocket:
+          retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
+        else:
+          retFuture.complete((getAddrString(cast[ptr SockAddr](addr sockAddress)), client.AsyncFD))
+
+    addRead(socket, cb)
+    return retFuture
+
+  proc winAccept*(socket: AsyncFD,
+      flags = {SocketFlag.SafeDisconn}): Future[AsyncFD] =
+    ## Accepts a new connection. Returns a future containing the client socket
+    ## corresponding to that connection.
+    ## The future will complete when the connection is successfully accepted.
+    var retFut = newFuture[AsyncFD]("winAccept")
+    var fut = winAcceptAddr(socket, flags)
+    fut.callback =
+      proc (future: Future[tuple[address: string, client: AsyncFD]]) =
+        assert future.finished
+        if future.failed:
+          retFut.fail(future.error)
+        else:
+          retFut.complete(future.read.client)
+    return retFut
+
+
+  proc winRecvLine*(socket: AsyncFD): Future[string] {.async.} =
+    ## Reads a line of data from ``socket``. Returned future will complete once
+    ## a full line is read or an error occurs.
+    ##
+    ## If a full line is read ``\r\L`` is not
+    ## added to ``line``, however if solely ``\r\L`` is read then ``line``
+    ## will be set to it.
+    ##
+    ## If the socket is disconnected, ``line`` will be set to ``""``.
+    ##
+    ## If the socket is disconnected in the middle of a line (before ``\r\L``
+    ## is read) then line will be set to ``""``.
+    ## The partial line **will be lost**.
+    ##
+    ## **Warning**: This assumes that lines are delimited by ``\r\L``.
+    ##
+    ## **Note**: This procedure is mostly used for testing. You likely want to
+    ## use ``asyncnet.recvLine`` instead.
+
+    template addNLIfEmpty(): stmt =
+      if result.len == 0:
+        result.add("\c\L")
+
+    result = ""
+    var c = ""
+    while true:
+      c = await winRecv(socket, 1)
+      if c.len == 0:
+        return ""
+      if c == "\r":
+        c = await winRecv(socket, 1)
+        assert c == "\l"
+        addNLIfEmpty()
+        return
+      elif c == "\L":
+        addNLIfEmpty()
+        return
+      add(result, c)
+
+  proc sendMessages(client: AsyncFD) {.async.} =
+    for i in 0 .. <messagesToSend:
+      await winSend(client, "Message " & $i & "\c\L")
+
+  proc launchSwarm(port: Port) {.async.} =
+    for i in 0 .. <swarmSize:
+      var sock = newNativeSocket()
+      setBlocking(sock, false)
+
+      await winConnect(AsyncFD(sock), "localhost", port)
+      await sendMessages(AsyncFD(sock))
+      discard closeSocket(sock)
+
+  proc readMessages(client: AsyncFD) {.async.} =
+    while true:
+      var line = await winRecvLine(client)
+      if line == "":
+        closeSocket(client)
+        clientCount.inc
+        break
+      else:
+        if line.startswith("Message "):
+          msgCount.inc
+        else:
+          doAssert false
+
+  proc createServer(port: Port) {.async.} =
+    var server = newNativeSocket()
+    setBlocking(server, false)
+    block:
+      var name = Sockaddr_in()
+      name.sin_family = toInt(Domain.AF_INET).int16
+      name.sin_port = htons(uint16(port))
+      name.sin_addr.s_addr = htonl(INADDR_ANY)
+      if bindAddr(server, cast[ptr SockAddr](addr(name)),
+                  sizeof(name).Socklen) < 0'i32:
+        raiseOSError(osLastError())
+
+    discard server.listen()
+    while true:
+      asyncCheck readMessages(await winAccept(AsyncFD(server)))
+
+  asyncCheck createServer(Port(10335))
+  asyncCheck launchSwarm(Port(10335))
+  while true:
+    poll()
+    if clientCount == swarmSize: break
+
+  assert msgCount == swarmSize * messagesToSend
+  echo msgCount
+else:
+  echo(5000)
diff --git a/tests/ccgbugs/tcapture_static.nim b/tests/ccgbugs/tcapture_static.nim
new file mode 100644
index 000000000..2afb8de47
--- /dev/null
+++ b/tests/ccgbugs/tcapture_static.nim
@@ -0,0 +1,13 @@
+discard """
+  output: '''hi'''
+"""
+
+# bug #4551
+
+proc foo() =
+    let arr = ["hi"]
+    for i, v in arr:
+        let bar = proc =
+            echo v
+        bar()
+foo()
diff --git a/tests/ccgbugs/tclosureeq.nim b/tests/ccgbugs/tclosureeq.nim
new file mode 100644
index 000000000..0486a9559
--- /dev/null
+++ b/tests/ccgbugs/tclosureeq.nim
@@ -0,0 +1,19 @@
+discard """
+  output: '''true
+true'''
+"""
+
+# bug #4186
+type
+  Predicate[T] = proc(item: T): bool
+
+proc a[T](): Predicate[T] =
+  return nil
+
+proc b[T](): Predicate[T] =
+  return a[T]()
+
+echo b[int]() == nil  # ok
+
+let x = b[int]()
+echo x == nil     #won't compile
diff --git a/tests/ccgbugs/tescaping_temps.nim b/tests/ccgbugs/tescaping_temps.nim
new file mode 100644
index 000000000..ef078913b
--- /dev/null
+++ b/tests/ccgbugs/tescaping_temps.nim
@@ -0,0 +1,20 @@
+
+# bug #4505
+
+proc f(t: tuple[]) = discard
+f((block: ()))
+
+# bug #4230
+# If we make `test` function return nothing - the bug disappears
+proc test(dothejob: proc()): int {.discardable.} =
+    dothejob()
+
+test proc() =
+    let f = 15
+    if f > 10:
+        test proc() = discard
+    # If we remove elif branch of the condition - the bug disappears
+    elif f < 3:
+        test proc() = discard
+    else:
+        test proc() = discard
diff --git a/tests/ccgbugs/tinefficient_const_table.nim b/tests/ccgbugs/tinefficient_const_table.nim
new file mode 100644
index 000000000..149b8bcff
--- /dev/null
+++ b/tests/ccgbugs/tinefficient_const_table.nim
@@ -0,0 +1,27 @@
+discard """
+  output: '''a
+long
+list
+of
+words'''
+  cmd: r"nim c --hints:on $options -d:release $file"
+  ccodecheck: "! @'genericSeqAssign'"
+"""
+
+
+# bug #4354
+import tables
+import sets
+import strutils
+
+#const FRUITS = ["banana", "apple", "grapes"]
+#let FRUITS = ["banana", "apple", "grapes"].toSet
+const FRUITS = {"banana":0, "apple":0, "grapes":0}.toTable
+
+proc main() =
+    let L = "a long list of words".split()
+    for word in L:
+        if word notin FRUITS:
+            echo(word)
+
+main()
diff --git a/tests/ccgbugs/tmissingvolatile.nim b/tests/ccgbugs/tmissingvolatile.nim
index 4d25e5c22..d61778ed4 100644
--- a/tests/ccgbugs/tmissingvolatile.nim
+++ b/tests/ccgbugs/tmissingvolatile.nim
@@ -1,7 +1,7 @@
 discard """
   output: "1"
   cmd: r"nim c --hints:on $options -d:release $file"
-  ccodecheck: "'NI volatile state;'"
+  ccodecheck: "'NI volatile state0;'"
 """
 
 # bug #1539
diff --git a/tests/ccgbugs/tuplecast.nim b/tests/ccgbugs/tuplecast.nim
new file mode 100644
index 000000000..d60e8c490
--- /dev/null
+++ b/tests/ccgbugs/tuplecast.nim
@@ -0,0 +1,8 @@
+
+# bug #4345
+
+# only needs to compile
+proc f(): tuple[a, b: uint8] = (1'u8, 2'u8)
+
+let a, b = f()
+let c = cast[int](b)
diff --git a/tests/ccgbugs/tweakopenarray.nim b/tests/ccgbugs/tweakopenarray.nim
new file mode 100644
index 000000000..51d781331
--- /dev/null
+++ b/tests/ccgbugs/tweakopenarray.nim
@@ -0,0 +1,12 @@
+# bug #4089
+
+type
+  Proc = proc(args: openArray[Bar]): Bar
+
+  Foo = object
+    p: Proc
+
+  Bar = object
+    f: Foo
+
+proc bar(val: Foo): Bar = Bar()
diff --git a/tests/ccgbugs/twrong_rc_for_refarray.nim b/tests/ccgbugs/twrong_rc_for_refarray.nim
new file mode 100644
index 000000000..99bdac5e1
--- /dev/null
+++ b/tests/ccgbugs/twrong_rc_for_refarray.nim
@@ -0,0 +1,26 @@
+discard """
+  output: '''m[0][0] = 1.0
+m[0][0] = 2.0'''
+"""
+# bug #4653
+type
+  Vector = ref array[2, float64]
+  Matrix = ref array[2, Vector]
+
+proc newVector(): Vector =
+  new(result)
+
+proc newMatrix(): Matrix =
+  new(result)
+  for ix in 0 .. 1:
+    result[ix] = newVector()
+
+let m = newMatrix()
+
+m[0][0] = 1.0
+echo "m[0][0] = ", m[0][0]
+
+GC_fullCollect()
+
+m[0][0] = 2.0
+echo "m[0][0] = ", m[0][0]
diff --git a/tests/ccgbugs/twrong_string_asgn.nim b/tests/ccgbugs/twrong_string_asgn.nim
index b62e70e7c..669b7f8f5 100644
--- a/tests/ccgbugs/twrong_string_asgn.nim
+++ b/tests/ccgbugs/twrong_string_asgn.nim
@@ -16,4 +16,4 @@ x.callback =
   proc () =
     finished = true
 
-while not finished: discard
+while not finished: poll()
diff --git a/tests/closure/tdeeplynested.nim b/tests/closure/tdeeplynested.nim
new file mode 100644
index 000000000..ddf4fa6a4
--- /dev/null
+++ b/tests/closure/tdeeplynested.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''int: 108'''
+"""
+
+# bug #4070
+
+proc id(f: (proc())): auto =
+  return f
+
+proc foo(myinteger: int): (iterator(): int) =
+  return iterator(): int {.closure.} =
+           proc bar() =
+             proc kk() =
+               echo "int: ", myinteger
+
+             kk()
+
+           id(bar)()
+
+discard foo(108)()
diff --git a/tests/closure/tflatmap.nim b/tests/closure/tflatmap.nim
new file mode 100644
index 000000000..240756424
--- /dev/null
+++ b/tests/closure/tflatmap.nim
@@ -0,0 +1,24 @@
+
+# bug #3995
+
+import future
+
+type
+  RNG* = tuple[]
+  Rand*[A] = (RNG) -> (A, RNG)
+
+proc nextInt*(r: RNG): (int, RNG) =
+  (1, ())
+
+proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
+  (rng: RNG) => (
+    let (a, rng2) = f(rng);
+    let g1 = g(a);
+    g1(rng2)
+  )
+
+proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
+  let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
+  flatMap(s, g)
+
+let f = nextInt.map(i => i - i mod 2)
diff --git a/tests/closure/uclosures.nim b/tests/closure/uclosures.nim
index 817bfec6b..f259cfeb9 100644
--- a/tests/closure/uclosures.nim
+++ b/tests/closure/uclosures.nim
@@ -1,12 +1,23 @@
+# This test is included from within tunittests
 import unittest
 
-test "loop variables are captured by copy":
+test "loop variables are captured by ref":
   var funcs: seq[proc (): int {.closure.}] = @[]
 
   for i in 0..10:
     let ii = i
     funcs.add do -> int: return ii * ii
 
+  check funcs[0]() == 100
+  check funcs[3]() == 100
+
+test "loop variables in closureScope are captured by copy":
+  var funcs: seq[proc (): int {.closure.}] = @[]
+
+  for i in 0..10:
+    closureScope:
+      let ii = i
+      funcs.add do -> int: return ii * ii
+
   check funcs[0]() == 0
   check funcs[3]() == 9
-
diff --git a/tests/converter/tconverter_with_varargs.nim b/tests/converter/tconverter_with_varargs.nim
new file mode 100644
index 000000000..6d7e31e85
--- /dev/null
+++ b/tests/converter/tconverter_with_varargs.nim
@@ -0,0 +1,18 @@
+
+# bug #888
+
+type
+  PyRef = object
+  PPyRef* = ref PyRef
+
+converter to_py*(i: int) : PPyRef = nil
+
+when false:
+  proc to_tuple*(vals: openarray[PPyRef]): PPyRef =
+    discard
+
+proc abc(args: varargs[PPyRef]) =
+  #let args_tup = to_tuple(args)
+  discard
+
+abc(1, 2)
diff --git a/tests/converter/texplicit_conversion.nim b/tests/converter/texplicit_conversion.nim
new file mode 100644
index 000000000..6b2e96faf
--- /dev/null
+++ b/tests/converter/texplicit_conversion.nim
@@ -0,0 +1,13 @@
+discard """
+  output: "234"
+"""
+
+# bug #4432
+
+import strutils
+
+converter toInt(s: string): int =
+  result = parseInt(s)
+
+let x = (int)"234"
+echo x
diff --git a/tests/converter/tor_in_converter.nim b/tests/converter/tor_in_converter.nim
new file mode 100644
index 000000000..5674526a1
--- /dev/null
+++ b/tests/converter/tor_in_converter.nim
@@ -0,0 +1,23 @@
+discard """
+  output: '''test
+test'''
+"""
+# bug #4537
+
+# nim js --d:nodejs
+
+type
+  Str = distinct string
+
+when true:
+  # crashes
+  converter convert(s: string | cstring): Str = Str($s)
+else:
+  # works!
+  converter convert(s: string): Str = Str($s)
+  converter convert(s: cstring): Str = Str($s)
+
+proc echoStr(s: Str) = echo s.string
+
+echoStr("test")
+echoStr("test".cstring)
diff --git a/tests/cpp/treturn_array.nim b/tests/cpp/treturn_array.nim
new file mode 100644
index 000000000..ba4fbd6cc
--- /dev/null
+++ b/tests/cpp/treturn_array.nim
@@ -0,0 +1,10 @@
+
+# bug #2259
+type Mat4f* = array[0..15, float]
+
+proc get_rot_mat*(): Mat4f = discard
+var mat: Mat4f = get_rot_mat()
+
+# bug #1389
+proc calcSizes(): array[2, int] = discard
+let sizes: array[2, int] = calcSizes()
diff --git a/tests/cpp/ttemplatetype.nim b/tests/cpp/ttemplatetype.nim
new file mode 100644
index 000000000..7f56a225d
--- /dev/null
+++ b/tests/cpp/ttemplatetype.nim
@@ -0,0 +1,9 @@
+type
+  Map {.importcpp: "std::map", header: "<map>".} [T,U] = object
+
+proc cInitMap(T: typedesc, U: typedesc): Map[T,U] {.importcpp: "std::map<'*1,'*2>()", nodecl.}
+
+proc initMap[T, U](): Map[T, U] =
+  result = cInitMap(T, U)
+
+var x: Map[cstring, cint] = initMap[cstring, cint]()
diff --git a/tests/distinct/tnil.nim b/tests/distinct/tnil.nim
new file mode 100644
index 000000000..ed0ac995a
--- /dev/null
+++ b/tests/distinct/tnil.nim
@@ -0,0 +1,47 @@
+discard """
+  file: "tnil.nim"
+  output: '''0x1
+
+nil
+
+nil
+
+'''
+"""
+
+type
+  MyPointer = distinct pointer
+  MyString = distinct string
+  MyStringNotNil = distinct (string not nil)
+  MyInt = distinct int
+
+proc foo(a: MyPointer) =
+  echo a.repr
+
+foo(cast[MyPointer](1))
+foo(cast[MyPointer](nil))
+foo(nil)
+
+var p: MyPointer
+p = cast[MyPointer](1)
+p = cast[MyPointer](nil)
+p = nil.MyPointer
+p = nil
+
+var c: MyString
+c = "Test".MyString
+c = nil.MyString
+c = nil
+
+p = nil
+doAssert(compiles(c = p) == false)
+
+var n: MyStringNotNil = "Test".MyStringNotNil # Cannot prove warning ...
+n = "Test".MyStringNotNil
+doAssert(compiles(n = nil.MyStringNotNil) == false)
+doAssert(compiles(n = nil.MyStringNotNil) == false)
+doAssert(compiles(n = nil) == false)
+
+var i: MyInt
+i = 1.MyInt
+doAssert(compiles(i = nil) == false)
diff --git a/tests/enum/tenum.nim b/tests/enum/tenum.nim
index b081212e6..6d9bdd539 100644
--- a/tests/enum/tenum.nim
+++ b/tests/enum/tenum.nim
@@ -6,3 +6,9 @@ type
 var
   en: E
 en = a
+
+# Bug #4066
+import macros
+macro genEnum(): untyped = newNimNode(nnkEnumTy).add(newEmptyNode(), newIdentNode("geItem1"))
+type GeneratedEnum = genEnum()
+doAssert(type(geItem1) is GeneratedEnum)
diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim
index 960c4e5f7..006b4d88f 100644
--- a/tests/float/tfloat4.nim
+++ b/tests/float/tfloat4.nim
@@ -1,3 +1,8 @@
+discard """
+  file: "tfloat4.nim"
+  output: "passed all tests."
+  exitcode: 0
+"""
 import math, strutils
 
 proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "<stdio.h>", varargs.}
@@ -11,8 +16,9 @@ proc floatToStr(f: float64): string =
       return
     add(result, ch)
 
+
 let testFloats = [
-  "0", "-1", "1", "1.", ".3", "3.3", "-.3", "-99.99",
+  "0", "-0", "0.", "0.0", "-0.", "-0.0", "-1", "1", "1.", ".3", "3.3", "-.3", "-99.99",
   "1.1e10", "-2e100", "1.234e-10", "1.234e+10",
   "-inf", "inf", "+inf",
   "3.14159265358979323846264338327950288",
@@ -25,18 +31,20 @@ let testFloats = [
 ]
 
 for num in testFloats:
-  assert num.parseFloat.floatToStr.parseFloat == num.parseFloat
+  doAssert num.parseFloat.floatToStr.parseFloat == num.parseFloat
 
-assert "0".parseFloat == 0.0
-assert "-.1".parseFloat == -0.1
-assert "2.5e1".parseFloat == 25.0
-assert "1e10".parseFloat == 10_000_000_000.0
-assert "0.000_005".parseFloat == 5.000_000e-6
-assert "1.234_567e+2".parseFloat == 123.4567
-assert "1e1_00".parseFloat == "1e100".parseFloat
-assert "3.1415926535897932384626433".parseFloat ==
+doAssert "0".parseFloat == 0.0
+doAssert "-.1".parseFloat == -0.1
+doAssert "2.5e1".parseFloat == 25.0
+doAssert "1e10".parseFloat == 10_000_000_000.0
+doAssert "0.000_005".parseFloat == 5.000_000e-6
+doAssert "1.234_567e+2".parseFloat == 123.4567
+doAssert "1e1_00".parseFloat == "1e100".parseFloat
+doAssert "3.1415926535897932384626433".parseFloat ==
        3.1415926535897932384626433
-assert "2.71828182845904523536028747".parseFloat ==
+doAssert "2.71828182845904523536028747".parseFloat ==
        2.71828182845904523536028747
-assert 0.00097656250000000021684043449710088680149056017398834228515625 ==
+doAssert 0.00097656250000000021684043449710088680149056017398834228515625 ==
      "0.00097656250000000021684043449710088680149056017398834228515625".parseFloat
+
+echo("passed all tests.")
diff --git a/tests/float/tfloat5.nim b/tests/float/tfloat5.nim
new file mode 100644
index 000000000..aa7dc6c53
--- /dev/null
+++ b/tests/float/tfloat5.nim
@@ -0,0 +1,15 @@
+discard """
+  file: "tfloat5.nim"
+  output: '''0 : 0.0
+0 : 0.0
+0 : 0.0
+0 : 0.0'''
+"""
+
+import parseutils
+
+var f: float
+echo "*".parseFloat(f), " : ", f
+echo "/".parseFloat(f), " : ", f
+echo "+".parseFloat(f), " : ", f
+echo "-".parseFloat(f), " : ", f
diff --git a/tests/float/tfloat6.nim b/tests/float/tfloat6.nim
new file mode 100644
index 000000000..721abd721
--- /dev/null
+++ b/tests/float/tfloat6.nim
@@ -0,0 +1,21 @@
+discard """
+  file: "tfloat6.nim"
+  output: '''1e-06 : 1e-06
+1e-06 : 1e-06
+0.001 : 0.001
+1e-06 : 1e-06
+1e-06 : 1e-06
+10.000001 : 10.000001
+100.000001 : 100.000001'''
+"""
+
+import strutils
+
+echo "0.00_0001".parseFloat(), " : ", 1E-6
+echo "0.00__00_01".parseFloat(), " : ", 1E-6
+echo "0.0_01".parseFloat(), " : ", 0.001
+echo "0.00_000_1".parseFloat(), " : ", 1E-6
+echo "0.00000_1".parseFloat(), " : ", 1E-6
+
+echo "1_0.00_0001".parseFloat(), " : ", 10.000001
+echo "1__00.00_0001".parseFloat(), " : ", 1_00.000001
diff --git a/tests/float/tfloat7.nim b/tests/float/tfloat7.nim
new file mode 100644
index 000000000..2337d1dd4
--- /dev/null
+++ b/tests/float/tfloat7.nim
@@ -0,0 +1,26 @@
+discard """
+  file: "tfloat6.nim"
+  output: '''passed.
+passed.
+passed.
+passed.
+passed.
+passed.
+passed.'''
+"""
+
+import strutils
+template expect_fail(x: expr) =
+  try:
+    discard x
+    echo("expected to fail!")
+  except ValueError:
+    echo("passed.")
+
+expect_fail("1_0._00_0001".parseFloat())
+expect_fail("_1_0_00.0001".parseFloat())
+expect_fail("10.00.01".parseFloat())
+expect_fail("10.00E_01".parseFloat())
+expect_fail("10.00E_01".parseFloat())
+expect_fail("10.00E".parseFloat())
+expect_fail("10.00A".parseFloat())
diff --git a/tests/gc/thavlak.nim b/tests/gc/thavlak.nim
new file mode 100644
index 000000000..efab49e36
--- /dev/null
+++ b/tests/gc/thavlak.nim
@@ -0,0 +1,457 @@
+discard """
+  output: '''Welcome to LoopTesterApp, Nim edition
+Constructing Simple CFG...
+15000 dummy loops
+Constructing CFG...
+Performing Loop Recognition
+1 Iteration
+Another 50 iterations...
+..................................................
+Found 1 loops (including artificial root node) (50)'''
+"""
+
+# bug #3184
+
+import tables
+import sequtils
+import sets
+
+type
+  BasicBlock = object
+    inEdges: seq[ref BasicBlock]
+    outEdges: seq[ref BasicBlock]
+    name: int
+
+proc newBasicBlock(name: int): ref BasicBlock =
+  new(result)
+  result.inEdges = newSeq[ref BasicBlock]()
+  result.outEdges = newSeq[ref BasicBlock]()
+  result.name = name
+
+proc hash(x: ref BasicBlock): int {.inline.} =
+  result = x.name
+
+type
+  BasicBlockEdge = object
+    fr: ref BasicBlock
+    to: ref BasicBlock
+
+  Cfg = object
+    basicBlockMap: Table[int, ref BasicBlock]
+    edgeList: seq[BasicBlockEdge]
+    startNode: ref BasicBlock
+
+proc newCfg(): Cfg =
+  result.basicBlockMap = initTable[int, ref BasicBlock]()
+  result.edgeList = newSeq[BasicBlockEdge]()
+
+proc createNode(self: var Cfg, name: int): ref BasicBlock =
+  result = self.basicBlockMap.getOrDefault(name)
+  if result == nil:
+    result = newBasicBlock(name)
+    self.basicBlockMap.add name, result
+
+  if self.startNode == nil:
+    self.startNode = result
+
+proc addEdge(self: var Cfg, edge: BasicBlockEdge) =
+  self.edgeList.add(edge)
+
+proc getNumNodes(self: Cfg): int =
+  self.basicBlockMap.len
+
+proc newBasicBlockEdge(cfg: var Cfg, fromName: int, toName: int): BasicBlockEdge =
+  result.fr = cfg.createNode(fromName)
+  result.to = cfg.createNode(toName)
+  result.fr.outEdges.add(result.to)
+  result.to.inEdges.add(result.fr)
+  cfg.addEdge(result)
+
+type
+  SimpleLoop = object
+    basicBlocks: seq[ref BasicBlock] # TODO: set here
+    children: seq[ref SimpleLoop] # TODO: set here
+    parent: ref SimpleLoop
+    header: ref BasicBlock
+    isRoot: bool
+    isReducible: bool
+    counter: int
+    nestingLevel: int
+    depthLevel: int
+
+proc newSimpleLoop(): ref SimpleLoop =
+  new(result)
+  result.basicBlocks = newSeq[ref BasicBlock]()
+  result.children = newSeq[ref SimpleLoop]()
+  result.parent = nil
+  result.header = nil
+  result.isRoot = false
+  result.isReducible = true
+  result.counter = 0
+  result.nestingLevel = 0
+  result.depthLevel = 0
+
+proc addNode(self: ref SimpleLoop, bb: ref BasicBlock) =
+  self.basicBlocks.add bb
+
+proc addChildLoop(self: ref SimpleLoop, loop: ref SimpleLoop) =
+  self.children.add loop
+
+proc setParent(self: ref SimpleLoop, parent: ref SimpleLoop) =
+  self.parent = parent
+  self.parent.addChildLoop(self)
+
+proc setHeader(self: ref SimpleLoop, bb: ref BasicBlock) =
+  self.basicBlocks.add(bb)
+  self.header = bb
+
+proc setNestingLevel(self: ref SimpleLoop, level: int) =
+  self.nestingLevel = level
+  if level == 0: self.isRoot = true
+
+var loop_counter: int = 0
+
+type
+  Lsg = object
+    loops: seq[ref SimpleLoop]
+    root: ref SimpleLoop
+
+proc createNewLoop(self: var Lsg): ref SimpleLoop =
+  result = newSimpleLoop()
+  loop_counter += 1
+  result.counter = loop_counter
+
+proc addLoop(self: var Lsg, l: ref SimpleLoop) =
+  self.loops.add l
+
+proc newLsg(): Lsg =
+  result.loops = newSeq[ref SimpleLoop]()
+  result.root = result.createNewLoop()
+  result.root.setNestingLevel(0)
+  result.addLoop(result.root)
+
+proc getNumLoops(self: Lsg): int =
+  self.loops.len
+
+type
+  UnionFindNode = object
+    parent: ref UnionFindNode
+    bb: ref BasicBlock
+    l: ref SimpleLoop
+    dfsNumber: int
+
+proc newUnionFindNode(): ref UnionFindNode =
+  new(result)
+  when false:
+    result.parent = nil
+    result.bb = nil
+    result.l = nil
+    result.dfsNumber = 0
+
+proc initNode(self: ref UnionFindNode, bb: ref BasicBlock, dfsNumber: int) =
+  self.parent = self
+  self.bb = bb
+  self.dfsNumber = dfsNumber
+
+proc findSet(self: ref UnionFindNode): ref UnionFindNode =
+  var nodeList = newSeq[ref UnionFindNode]()
+  result = self
+
+  while result != result.parent:
+    var parent = result.parent
+    if parent != parent.parent: nodeList.add result
+    result = parent
+
+  for iter in nodeList: iter.parent = result.parent
+
+proc union(self: ref UnionFindNode, unionFindNode: ref UnionFindNode) =
+  self.parent = unionFindNode
+
+
+const
+  BB_TOP          = 0 # uninitialized
+  BB_NONHEADER    = 1 # a regular BB
+  BB_REDUCIBLE    = 2 # reducible loop
+  BB_SELF         = 3 # single BB loop
+  BB_IRREDUCIBLE  = 4 # irreducible loop
+  BB_DEAD         = 5 # a dead BB
+  BB_LAST         = 6 # Sentinel
+
+  # # Marker for uninitialized nodes.
+  UNVISITED = -1
+
+  # # Safeguard against pathologic algorithm behavior.
+  MAXNONBACKPREDS = (32 * 1024)
+
+type
+  HavlakLoopFinder = object
+    cfg: Cfg
+    lsg: Lsg
+
+proc newHavlakLoopFinder(cfg: Cfg, lsg: Lsg): HavlakLoopFinder =
+  result.cfg = cfg
+  result.lsg = lsg
+
+proc isAncestor(w: int, v: int, last: seq[int]): bool =
+  w <= v and v <= last[w]
+
+proc dfs(currentNode: ref BasicBlock, nodes: var seq[ref UnionFindNode], number: var Table[ref BasicBlock, int], last: var seq[int], current: int): int =
+  var stack = @[(currentNode, current)]
+  while stack.len > 0:
+    let (currentNode, current) = stack.pop()
+    nodes[current].initNode(currentNode, current)
+    number[currentNode] = current
+
+    result = current
+    for target in currentNode.outEdges:
+      if number[target] == UNVISITED:
+        stack.add((target, result+1))
+        #result = dfs(target, nodes, number, last, result + 1)
+  last[number[currentNode]] = result
+
+proc findLoops(self: var HavlakLoopFinder): int =
+  var startNode = self.cfg.startNode
+  if startNode == nil: return 0
+  var size = self.cfg.getNumNodes
+
+  var nonBackPreds    = newSeq[HashSet[int]]()
+  var backPreds       = newSeq[seq[int]]()
+  var number          = initTable[ref BasicBlock, int]()
+  var header          = newSeq[int](size)
+  var types           = newSeq[int](size)
+  var last            = newSeq[int](size)
+  var nodes           = newSeq[ref UnionFindNode]()
+
+  for i in 1..size:
+    nonBackPreds.add initSet[int](1)
+    backPreds.add newSeq[int]()
+    nodes.add newUnionFindNode()
+
+  # Step a:
+  #   - initialize all nodes as unvisited.
+  #   - depth-first traversal and numbering.
+  #   - unreached BB's are marked as dead.
+  #
+  for v in self.cfg.basicBlockMap.values: number[v] = UNVISITED
+  var res = dfs(startNode, nodes, number, last, 0)
+
+  # Step b:
+  #   - iterate over all nodes.
+  #
+  #   A backedge comes from a descendant in the DFS tree, and non-backedges
+  #   from non-descendants (following Tarjan).
+  #
+  #   - check incoming edges 'v' and add them to either
+  #     - the list of backedges (backPreds) or
+  #     - the list of non-backedges (nonBackPreds)
+  #
+  for w in 0 .. <size:
+    header[w] = 0
+    types[w]  = BB_NONHEADER
+
+    var nodeW = nodes[w].bb
+    if nodeW != nil:
+      for nodeV in nodeW.inEdges:
+        var v = number[nodeV]
+        if v != UNVISITED:
+          if isAncestor(w, v, last):
+            backPreds[w].add v
+          else:
+            nonBackPreds[w].incl v
+    else:
+      types[w] = BB_DEAD
+
+  # Start node is root of all other loops.
+  header[0] = 0
+
+  # Step c:
+  #
+  # The outer loop, unchanged from Tarjan. It does nothing except
+  # for those nodes which are the destinations of backedges.
+  # For a header node w, we chase backward from the sources of the
+  # backedges adding nodes to the set P, representing the body of
+  # the loop headed by w.
+  #
+  # By running through the nodes in reverse of the DFST preorder,
+  # we ensure that inner loop headers will be processed before the
+  # headers for surrounding loops.
+
+  for w in countdown(size - 1, 0):
+    # this is 'P' in Havlak's paper
+    var nodePool = newSeq[ref UnionFindNode]()
+
+    var nodeW = nodes[w].bb
+    if nodeW != nil: # dead BB
+      # Step d:
+      for v in backPreds[w]:
+        if v != w:
+          nodePool.add nodes[v].findSet
+        else:
+          types[w] = BB_SELF
+
+      # Copy nodePool to workList.
+      #
+      var workList = newSeq[ref UnionFindNode]()
+      for x in nodePool: workList.add x
+
+      if nodePool.len != 0: types[w] = BB_REDUCIBLE
+
+      # work the list...
+      #
+      while workList.len > 0:
+        var x = workList[0]
+        workList.del(0)
+
+        # Step e:
+        #
+        # Step e represents the main difference from Tarjan's method.
+        # Chasing upwards from the sources of a node w's backedges. If
+        # there is a node y' that is not a descendant of w, w is marked
+        # the header of an irreducible loop, there is another entry
+        # into this loop that avoids w.
+        #
+
+        # The algorithm has degenerated. Break and
+        # return in this case.
+        #
+        var nonBackSize = nonBackPreds[x.dfsNumber].len
+        if nonBackSize > MAXNONBACKPREDS: return 0
+
+        for iter in nonBackPreds[x.dfsNumber]:
+          var y = nodes[iter]
+          var ydash = y.findSet
+
+          if not isAncestor(w, ydash.dfsNumber, last):
+            types[w] = BB_IRREDUCIBLE
+            nonBackPreds[w].incl ydash.dfsNumber
+          else:
+            if ydash.dfsNumber != w and not nodePool.contains(ydash):
+              workList.add ydash
+              nodePool.add ydash
+
+      # Collapse/Unionize nodes in a SCC to a single node
+      # For every SCC found, create a loop descriptor and link it in.
+      #
+      if (nodePool.len > 0) or (types[w] == BB_SELF):
+        var l = self.lsg.createNewLoop
+
+        l.setHeader(nodeW)
+        l.isReducible = types[w] != BB_IRREDUCIBLE
+
+        # At this point, one can set attributes to the loop, such as:
+        #
+        # the bottom node:
+        #    iter  = backPreds(w).begin();
+        #    loop bottom is: nodes(iter).node;
+        #
+        # the number of backedges:
+        #    backPreds(w).size()
+        #
+        # whether this loop is reducible:
+        #    types(w) != BB_IRREDUCIBLE
+        #
+        nodes[w].l = l
+
+        for node in nodePool:
+          # Add nodes to loop descriptor.
+          header[node.dfsNumber] = w
+          node.union(nodes[w])
+
+          # Nested loops are not added, but linked together.
+          var node_l = node.l
+          if node_l != nil:
+            node_l.setParent(l)
+          else:
+            l.addNode(node.bb)
+
+        self.lsg.addLoop(l)
+
+  result = self.lsg.getNumLoops
+
+
+type
+  LoopTesterApp = object
+    cfg: Cfg
+    lsg: Lsg
+
+proc newLoopTesterApp(): LoopTesterApp =
+  result.cfg = newCfg()
+  result.lsg = newLsg()
+
+proc buildDiamond(self: var LoopTesterApp, start: int): int =
+  var bb0 = start
+  var x1 = newBasicBlockEdge(self.cfg, bb0, bb0 + 1)
+  var x2 = newBasicBlockEdge(self.cfg, bb0, bb0 + 2)
+  var x3 = newBasicBlockEdge(self.cfg, bb0 + 1, bb0 + 3)
+  var x4 = newBasicBlockEdge(self.cfg, bb0 + 2, bb0 + 3)
+  result = bb0 + 3
+
+proc buildConnect(self: var LoopTesterApp, start1: int, end1: int) =
+  var x1 = newBasicBlockEdge(self.cfg, start1, end1)
+
+proc buildStraight(self: var LoopTesterApp, start: int, n: int): int =
+  for i in 0..n-1:
+    self.buildConnect(start + i, start + i + 1)
+  result = start + n
+
+proc buildBaseLoop(self: var LoopTesterApp, from1: int): int =
+  var header   = self.buildStraight(from1, 1)
+  var diamond1 = self.buildDiamond(header)
+  var d11      = self.buildStraight(diamond1, 1)
+  var diamond2 = self.buildDiamond(d11)
+  var footer   = self.buildStraight(diamond2, 1)
+
+  self.buildConnect(diamond2, d11)
+  self.buildConnect(diamond1, header)
+  self.buildConnect(footer, from1)
+  result = self.buildStraight(footer, 1)
+
+proc run(self: var LoopTesterApp) =
+  echo "Welcome to LoopTesterApp, Nim edition"
+  echo "Constructing Simple CFG..."
+
+  var x1 = self.cfg.createNode(0)
+  var x2 = self.buildBaseLoop(0)
+  var x3 = self.cfg.createNode(1)
+  self.buildConnect(0, 2)
+
+  echo "15000 dummy loops"
+
+  for i in 1..15000:
+    var h = newHavlakLoopFinder(self.cfg, newLsg())
+    var res = h.findLoops
+
+  echo "Constructing CFG..."
+  var n = 2
+
+  for parlooptrees in 1..10:
+    var x6 = self.cfg.createNode(n + 1)
+    self.buildConnect(2, n + 1)
+    n += 1
+    for i in 1..100:
+      var top = n
+      n = self.buildStraight(n, 1)
+      for j in 1..25: n = self.buildBaseLoop(n)
+      var bottom = self.buildStraight(n, 1)
+      self.buildConnect n, top
+      n = bottom
+    self.buildConnect(n, 1)
+
+  echo "Performing Loop Recognition\n1 Iteration"
+
+  var h = newHavlakLoopFinder(self.cfg, newLsg())
+  var loops = h.findLoops
+
+  echo "Another 50 iterations..."
+
+  var sum = 0
+  for i in 1..50:
+    write stdout, "."
+    flushFile(stdout)
+    var hlf = newHavlakLoopFinder(self.cfg, newLsg())
+    sum += hlf.findLoops
+    #echo getOccupiedMem()
+  echo "\nFound ", loops, " loops (including artificial root node) (", sum, ")"
+
+var l = newLoopTesterApp()
+l.run
diff --git a/tests/gc/tlists.nim b/tests/gc/tlists.nim
new file mode 100644
index 000000000..26b32396c
--- /dev/null
+++ b/tests/gc/tlists.nim
@@ -0,0 +1,37 @@
+discard """
+    output: '''Success'''
+"""
+
+# bug #3793
+
+import os
+import math
+import lists
+import strutils
+
+proc mkleak() =
+    # allocate 10 MB via linked lists
+    let numberOfLists = 100
+    for i in countUp(1, numberOfLists):
+        var leakList = initDoublyLinkedList[string]()
+        let numberOfLeaks = 50000
+        for j in countUp(1, numberOfLeaks):
+            let leakSize = 200
+            let leaked = newString(leakSize)
+            leakList.append(leaked)
+
+proc mkManyLeaks() =
+    for i in 0..0:
+        when false: echo getOccupiedMem()
+        mkleak()
+        when false: echo getOccupiedMem()
+        # Force a full collection. This should free all of the
+        # 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:
+          echo GC_getStatistics()
+          quit "leaking"
+    echo "Success"
+
+mkManyLeaks()
diff --git a/tests/generics/t88.nim b/tests/generics/t88.nim
new file mode 100644
index 000000000..35bdeb8f1
--- /dev/null
+++ b/tests/generics/t88.nim
@@ -0,0 +1,33 @@
+# Issue 88
+
+type
+  BaseClass[V] = object of RootObj
+    b: V
+
+proc new[V](t: typedesc[BaseClass], v: V): BaseClass[V] =
+  BaseClass[V](b: v)
+
+proc baseMethod[V](v: BaseClass[V]): V = v.b
+proc overridedMethod[V](v: BaseClass[V]): V = v.baseMethod
+
+type
+  ChildClass[V] = object of BaseClass[V]
+    c: V
+
+proc new[V](t: typedesc[ChildClass], v1, v2: V): ChildClass[V] =
+  ChildClass[V](b: v1, c: v2)
+
+proc overridedMethod[V](v: ChildClass[V]): V = v.c
+
+let c = ChildClass[string].new("Base", "Child")
+
+assert c.baseMethod == "Base"
+assert c.overridedMethod == "Child"
+
+
+# bug #4528
+type GenericBase[T] = ref object of RootObj
+type GenericSubclass[T] = ref object of GenericBase[T]
+proc foo[T](g: GenericBase[T]) = discard
+var bar: GenericSubclass[int]
+foo(bar)
diff --git a/tests/generics/tforward_generic.nim b/tests/generics/tforward_generic.nim
new file mode 100644
index 000000000..169279cb3
--- /dev/null
+++ b/tests/generics/tforward_generic.nim
@@ -0,0 +1,28 @@
+discard """
+  output: '''b()
+720 120.0'''
+"""
+
+# bug #3055
+proc b(t: int | string)
+proc a(t: int) = b(t)
+proc b(t: int | string) = echo "b()"
+a(1)
+
+# test recursive generics still work:
+proc fac[T](x: T): T =
+  if x == 0: return 1
+  else: return fac(x-1)*x
+
+echo fac(6), " ", fac(5.0)
+
+when false:
+  # This still doesn't work...
+  # test recursive generic with forwarding:
+  proc fac2[T](x: T): T
+
+  echo fac2(6), " ", fac2(5.0)
+
+  proc fac2[T](x: T): T =
+    if x == 0: return 1
+    else: return fac2(x-1)*x
diff --git a/tests/generics/tgenerictmpl2.nim b/tests/generics/tgenerictmpl2.nim
new file mode 100644
index 000000000..0ecaf9ded
--- /dev/null
+++ b/tests/generics/tgenerictmpl2.nim
@@ -0,0 +1,31 @@
+discard """
+  output: '''1
+1
+1
+1
+999
+999
+999
+2'''
+"""
+
+# test if we can pass explicit generic arguments to generic templates
+# based on bug report #3496
+
+proc     tproc[T](t: T = 999) = echo t
+template ttmpl[T](t: T = 999) = echo t
+
+tproc(1)
+tproc[int](1)
+ttmpl(1)
+ttmpl[int](1) #<- crash case #1
+
+tproc[int]()
+discard tproc[int]
+ttmpl[int]()  #<- crash case #2
+ttmpl[int]    #<- crash case #3
+
+# but still allow normal use of [] on non-generic templates
+
+template tarr: expr = [1, 2, 3, 4]
+echo tarr[1]
diff --git a/tests/generics/ttable_alias.nim b/tests/generics/ttable_alias.nim
new file mode 100644
index 000000000..992ca85e0
--- /dev/null
+++ b/tests/generics/ttable_alias.nim
@@ -0,0 +1,7 @@
+# bug #4589
+
+import tables
+type SimpleTable*[TKey, TVal] = TableRef[TKey, TVal]
+template newSimpleTable*(TKey, TVal: typedesc): SimpleTable[TKey, TVal] = newTable[TKey, TVal]()
+var fontCache : SimpleTable[string, SimpleTable[int32, int]]
+fontCache = newSimpleTable(string, SimpleTable[int32, int])
diff --git a/tests/generics/ttempl_in_generic.nim b/tests/generics/ttempl_in_generic.nim
new file mode 100644
index 000000000..f04b9d216
--- /dev/null
+++ b/tests/generics/ttempl_in_generic.nim
@@ -0,0 +1,8 @@
+
+# bug #4600
+template foo(x: untyped): untyped = echo 1
+template foo(x,y: untyped): untyped = echo 2
+
+proc bar1[T](x: T) = foo(x)
+proc bar2(x: float) = foo(x,x)
+proc bar3[T](x: T) = foo(x,x)
diff --git a/tests/generics/twrong_explicit_typeargs.nim b/tests/generics/twrong_explicit_typeargs.nim
new file mode 100644
index 000000000..e47b38e99
--- /dev/null
+++ b/tests/generics/twrong_explicit_typeargs.nim
@@ -0,0 +1,16 @@
+discard """
+  errormsg: "cannot instantiate: 'newImage[string]'"
+  line: 16
+"""
+
+# bug #4084
+type
+  Image[T] = object
+    data: seq[T]
+
+proc newImage[T: int32|int64](w, h: int): ref Image[T] =
+  new(result)
+  result.data = newSeq[T](w * h)
+
+var correct = newImage[int32](320, 200)
+var wrong = newImage[string](320, 200)
diff --git a/tests/iter/tcomplex_openarray.nim b/tests/iter/tcomplex_openarray.nim
new file mode 100644
index 000000000..6fc191e90
--- /dev/null
+++ b/tests/iter/tcomplex_openarray.nim
@@ -0,0 +1,33 @@
+
+# bug #3221
+
+import algorithm, math, sequtils
+
+
+iterator permutations[T](ys: openarray[T]): seq[T] =
+  var
+    d = 1
+    c = newSeq[int](ys.len)
+    xs = newSeq[T](ys.len)
+  for i, y in ys: xs[i] = y
+  yield xs
+  block outer:
+    while true:
+      while d > 1:
+        dec d
+        c[d] = 0
+      while c[d] >= d:
+        inc d
+        if d >= ys.len: break outer
+      let i = if (d and 1) == 1: c[d] else: 0
+      swap xs[i], xs[d]
+      yield xs
+      inc c[d]
+
+proc dig_vectors(): void =
+  var v_nums: seq[int]
+  v_nums = newSeq[int](1)
+  for perm in permutations(toSeq(0 .. 1)):
+    v_nums[0] = 1
+
+dig_vectors()
diff --git a/tests/js/tclosures.nim b/tests/js/tclosures.nim
new file mode 100644
index 000000000..0ec4f4743
--- /dev/null
+++ b/tests/js/tclosures.nim
@@ -0,0 +1,51 @@
+discard """
+  action: run
+"""
+
+import math, random, strutils
+const consolePrefix = "jsCallbacks"
+
+asm """
+    var callback = []
+    function regCallback (fn) { callback.push (fn); }
+    function runCallbacks () {
+        var result = "\n"
+        var n = 0
+        for (var fn in callback) {
+            n += 1
+            result += "("+String (n)+")"
+            result += callback [fn] ()
+            result += "\n"
+        }
+        return result
+    }
+    function print (text) { console.log (text); }
+"""
+
+proc consoleprint (str:cstring): void {.importc: "print", noDecl.}
+proc print* (a: varargs[string, `$`]) = consoleprint "$1: $2" % [consolePrefix, join (a, " ")]
+
+type CallbackProc {.importc.} = proc () : cstring
+
+proc regCallback (fn:CallbackProc) {.importc.}
+proc runCallbacks ():cstring {.importc.}
+
+proc `*` (s:string, n:Natural) : string = s.repeat (n)
+
+proc outer (i:Natural) : (string, int) =
+    let c = $char (random (93) + 33)
+    let n = random (40)
+    let s = c * n
+    proc inner () : cstring = ("[$1]" % $n) & s & " <--"
+    regCallback (inner)
+    return (s, n)
+
+var expected = "\n"
+for i in 1 .. 10:
+    let (s, n) = outer (i)
+    expected &= ("($1)[$2]" % [$i, $n]) & s & " <--"
+    expected &= "\n"
+
+let results = runCallbacks ()
+
+doAssert(expected == results)
diff --git a/tests/js/test2.nim b/tests/js/test2.nim
index f6976d058..0f460d6f8 100644
--- a/tests/js/test2.nim
+++ b/tests/js/test2.nim
@@ -1,7 +1,8 @@
 discard """
   output: '''foo
 js 3.14
-7'''
+7
+1'''
 """
 
 # This file tests the JavaScript generator
@@ -29,3 +30,13 @@ proc test(x: C, T: typedesc): T =
   cast[T](x)
 
 echo 7.test(int8)
+
+# #4222
+const someConst = [ "1"]
+
+proc procThatRefersToConst() # Forward decl
+procThatRefersToConst() # Call bar before it is defined
+
+proc procThatRefersToConst() =
+  var i = 0 # Use a var index, otherwise nim will constfold foo[0]
+  echo someConst[i] # JS exception here: foo is still not initialized (undefined)
diff --git a/tests/js/testtojsstr.nim b/tests/js/testtojsstr.nim
new file mode 100644
index 000000000..03ac89e20
--- /dev/null
+++ b/tests/js/testtojsstr.nim
@@ -0,0 +1,8 @@
+discard """
+  output = "И\n"
+"""
+
+let s: string = "И\n"
+let cs = s.cstring
+
+echo $s
diff --git a/tests/js/tstring_assignment.nim b/tests/js/tstring_assignment.nim
new file mode 100644
index 000000000..bdd93e6b5
--- /dev/null
+++ b/tests/js/tstring_assignment.nim
@@ -0,0 +1,11 @@
+discard """
+  output: '''true'''
+"""
+
+# bug #4471
+when true:
+  let s1 = "123"
+  var s2 = s1
+  s2.setLen(0)
+  # fails - s1.len == 0
+  echo s1.len == 3
diff --git a/tests/lexer/tstrlits.nim b/tests/lexer/tstrlits.nim
index f5b7ce937..cc8872f60 100644
--- a/tests/lexer/tstrlits.nim
+++ b/tests/lexer/tstrlits.nim
@@ -1,6 +1,6 @@
 discard """
   file: "tstrlits.nim"
-  output: "a\"\"long string\"\"\"\"\"abc\"def"
+  output: "a\"\"long string\"\"\"\"\"abc\"def_'2'●"
 """
 # Test the new different string literals
 
@@ -11,9 +11,13 @@ const
 
   raw = r"abc""def"
 
+  escaped = "\x5f'\50'\u25cf"
+
+
 stdout.write(rawQuote)
 stdout.write(tripleEmpty)
 stdout.write(raw)
+stdout.write(escaped)
 #OUT a""long string"""""abc"def
 
 
diff --git a/tests/lookups/test.nim b/tests/lookups/test.nim
new file mode 100644
index 000000000..a17d235a4
--- /dev/null
+++ b/tests/lookups/test.nim
@@ -0,0 +1,17 @@
+# This file needs to be called 'test' nim to provoke a clash
+# with the unittest.test name. Issue #
+
+import unittest, macros
+
+# bug #4555
+
+macro memo(n: untyped): typed =
+  result = n
+
+proc fastFib(n: int): int {.memo.} = 40
+proc fib(n: int): int = 40
+
+suite "memoization":
+  test "recursive function memoization":
+    check fastFib(40) == fib(40)
+
diff --git a/tests/lookups/tprefer_proc.nim b/tests/lookups/tprefer_proc.nim
new file mode 100644
index 000000000..57ee8e539
--- /dev/null
+++ b/tests/lookups/tprefer_proc.nim
@@ -0,0 +1,4 @@
+
+# bug #4353
+import random
+echo random[int](low(int) .. high(int))
diff --git a/tests/macros/tcomplexecho.nim b/tests/macros/tcomplexecho.nim
new file mode 100644
index 000000000..f7f933c1c
--- /dev/null
+++ b/tests/macros/tcomplexecho.nim
@@ -0,0 +1,42 @@
+discard """
+  output: '''3
+OK
+56
+123
+56
+61'''
+"""
+
+import macros
+
+# Bug from the forum
+macro addEcho1(s: untyped): stmt =
+  s.body.add(newCall("echo", newStrLitNode("OK")))
+  result = s
+
+proc f1() {.addEcho1.} =
+  let i = 1+2
+  echo i
+
+f1()
+
+# bug #537
+proc test(): seq[NimNode] {.compiletime.} =
+  result = @[]
+  result.add parseExpr("echo 56")
+  result.add parseExpr("echo 123")
+  result.add parseExpr("echo 56")
+
+proc foo(): seq[NimNode] {.compiletime.} =
+  result = @[]
+  result.add test()
+  result.add parseExpr("echo(5+56)")
+
+macro bar(): stmt =
+  result = newNimNode(nnkStmtList)
+  let x = foo()
+  for xx in x:
+    result.add xx
+  echo treeRepr(result)
+
+bar()
diff --git a/tests/macros/tdumptree.nim b/tests/macros/tdumptree.nim
index e5160b7ba..58b011b45 100644
--- a/tests/macros/tdumptree.nim
+++ b/tests/macros/tdumptree.nim
@@ -3,7 +3,7 @@ msg: '''StmtList
   VarSection
     IdentDefs
       Ident !"x"
-      nil
+      Empty
       Call
         DotExpr
           Ident !"foo"
diff --git a/tests/macros/tgettypeinst.nim b/tests/macros/tgettypeinst.nim
new file mode 100644
index 000000000..22e03a119
--- /dev/null
+++ b/tests/macros/tgettypeinst.nim
@@ -0,0 +1,122 @@
+discard """
+"""
+
+import macros, strUtils
+
+proc symToIdent(x: NimNode): NimNode =
+  case x.kind:
+    of nnkCharLit..nnkUInt64Lit:
+      result = newNimNode(x.kind)
+      result.intVal = x.intVal
+    of nnkFloatLit..nnkFloat64Lit:
+      result = newNimNode(x.kind)
+      result.floatVal = x.floatVal
+    of nnkStrLit..nnkTripleStrLit:
+      result = newNimNode(x.kind)
+      result.strVal = x.strVal
+    of nnkIdent, nnkSym:
+      result = newIdentNode($x)
+    else:
+      result = newNimNode(x.kind)
+      for c in x:
+        result.add symToIdent(c)
+
+macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed =
+  let inst = x.getTypeInst
+  let impl = x.getTypeImpl
+  let inst0r = inst0.symToIdent.treeRepr
+  let instr = inst.symToIdent.treeRepr
+  #echo inst0r
+  #echo instr
+  doAssert(instr == inst0r)
+  var impl0 =
+    if implX.kind == nnkNilLit: inst0
+    else: implX[0][2]
+  let impl0r = impl0.symToIdent.treerepr
+  let implr = impl.symToIdent.treerepr
+  #echo impl0r
+  #echo implr
+  doAssert(implr == impl0r)
+  template echoString(s:string) = echo s.replace("\n","\n  ")
+  result = newStmtList()
+  #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) =
+      testV(n, false):
+        type _ = m
+    result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
+
+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) =
+  block:
+    type myType = inst
+    testV(myType, recurse):
+      type _ = inst
+
+template test(inst) =
+  testT(inst, false)
+  testV(inst, true, nil)
+template test(inst, impl) = testV(inst, true, impl)
+
+type
+  Model = object of RootObj
+  User = object of Model
+    name : string
+    password : string
+
+  Tree = object of RootObj
+    value : int
+    left,right : ref Tree
+
+  MyEnum = enum
+    valueA, valueB, valueC
+
+  MySet = set[MyEnum]
+  MySeq = seq[int]
+  MyIntPtr = ptr int
+  MyIntRef = ref int
+
+  GenericObject[T] = object
+    value:T
+  Foo[N:static[int],T] = object
+  Bar[N:static[int],T] = object
+    #baz:Foo[N+1,GenericObject[T]]
+    baz:Foo[N,GenericObject[T]]
+
+test(bool)
+test(char)
+test(int)
+test(float)
+test(ptr int)
+test(ref int)
+test(array[1..10,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(Bar[2,Foo[3,float]]):
+  type _ = object
+    baz: Foo[2, GenericObject[Foo[3, float]]]
+test(Model):
+  type _ = object of RootObj
+test(User):
+  type _ = object of Model
+    name: string
+    password: string
+test(Tree):
+  type _ = object of RootObj
+    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])
diff --git a/tests/macros/tvarargsuntyped.nim b/tests/macros/tvarargsuntyped.nim
new file mode 100644
index 000000000..b7d2bc001
--- /dev/null
+++ b/tests/macros/tvarargsuntyped.nim
@@ -0,0 +1,79 @@
+discard """
+  output: '''Let's go!
+(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)'''
+"""
+
+import macros
+
+proc internalBar(top, left, width, height: cint, s: string, x, y: int, r,g,b: int) =
+  echo locals()
+
+# we need these dummy constructors due to the wrong implementation
+# of 'varargs[untyped]' in the compiler:
+
+proc point(x, y: int): int = discard
+proc color(r, g, b: int): int = discard
+proc rect(a, b, c, d: int): int = discard
+
+template declareUnpackingMacro(nimname,extname) =
+  macro nimname(n: varargs[untyped]): untyped =
+    var s: string = astToStr(extname) & "("
+    var first = true
+    echo repr n
+    for x in n.children:
+      var unpack = false
+      if x.kind in nnkCallKinds:
+        case $x[0]
+        of "point":
+          expectLen(x, 3)
+          unpack = true
+        of "rect":
+          expectLen(x, 5)
+          unpack = true
+        of "color":
+          expectLen(x, 4)
+          unpack = true
+        else: discard
+      if unpack:
+        for i in 1..<x.len:
+          if first:
+            first = false
+          else:
+            add(s, ", ")
+          add(s, repr(x[i]))
+      else:
+        if first:
+          first = false
+        else:
+          add(s, ", ")
+        add(s, repr(x))
+
+    add(s, ")")
+    echo s
+    result = parseStmt(s)
+
+declareUnpackingMacro(bar,internalBar)
+
+type MyInt = distinct int
+
+proc myInt(i: int): MyInt = cast[MyInt](i)
+
+converter toCInt(mi: MyInt): cint = cast[cint](mi)
+
+echo "Let's go!"
+
+bar(rect(1, 2, 3, 4), "test", point(8, 9), color(7,7,8))
+
+bar(1,2,3,4,"text",8,9,7,7,8)
+
+bar(myInt(4),2,3,4,"text",8,9,7,7,8)
+
+let top: cint = 1
+let left: cint = 2
+let width: cint = 3
+let height: cint = 4
+
+bar(rect(top, left, width, height), "test", point(8, 9), color(7,7,8))
diff --git a/tests/macros/typesafeprintf.nim b/tests/macros/typesafeprintf.nim
new file mode 100644
index 000000000..2f4622f3e
--- /dev/null
+++ b/tests/macros/typesafeprintf.nim
@@ -0,0 +1,48 @@
+discard """
+  output: '''test 10'''
+"""
+
+# bug #1152
+
+import macros, typetraits
+proc printfImpl(formatstr: cstring) {.importc: "printf", varargs.}
+
+iterator tokenize(format: string): char =
+  var i = 0
+  while true:
+    case format[i]
+    of '%':
+      case format[i+1]
+      of '\0': break
+      else: yield format[i+1]
+      i.inc
+    of '\0': break
+    else: discard
+    i.inc
+
+macro printf(formatString: string{lit}, args: varargs[typed]): untyped =
+  var i = 0
+  let err = getType(bindSym"ValueError")
+  for c in tokenize(formatString.strVal):
+    var expectedType = case c
+      of 'c': getType(bindSym"char")
+      of 'd', 'i', 'x', 'X': getType(bindSym"int")
+      of 'f', 'e', 'E', 'g', 'G': getType(bindSym"float")
+      of 's': getType(bindSym"string")
+      of 'p': getType(bindSym"pointer")
+      else: err
+
+    var actualType = getType(args[i])
+    inc i
+
+    if sameType(expectedType, err):
+      error c & " is not a valid format character"
+    elif not sameType(expectedType, actualType):
+      error "type mismatch for argument " & $i & ". expected type: " &
+            $expectedType & ", actual type: " & $actualType
+
+  # keep the original callsite, but use cprintf instead
+  result = callsite()
+  result[0] = bindSym"printfImpl"
+
+printf("test %d\n", 10)
diff --git a/tests/manyloc/keineschweine/lib/vehicles.nim b/tests/manyloc/keineschweine/lib/vehicles.nim
index 94ebf9f57..ddfb43b38 100644
--- a/tests/manyloc/keineschweine/lib/vehicles.nim
+++ b/tests/manyloc/keineschweine/lib/vehicles.nim
@@ -1,6 +1,6 @@
 import
   sfml, chipmunk,
-  sg_assets, sfml_stuff, keineschweine
+  sg_assets, sfml_stuff, "../keineschweine"
 
 
 proc accel*(obj: PVehicle, dt: float) =
diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim
index e91b86986..2055d7834 100644
--- a/tests/manyloc/nake/nakefile.nim
+++ b/tests/manyloc/nake/nakefile.nim
@@ -1,5 +1,5 @@
 import nake
-import httpclient, zip/zipfiles, times, math, sequtils
+import httpclient, zip/zipfiles, times, random, sequtils
 nakeImports
 
 randomize()
@@ -145,7 +145,7 @@ task "download", "download game assets":
     echo "Extracted the libs dir. Copy the ones you need to this dir."
 
 task "zip-lib", "zip up the libs dir":
-  var z: TZipArchive
+  var z: ZipArchive
   if not z.open("libs-" & getDateStr() & ".zip", fmReadWrite):
     quit "Could not open zip"
   for file in walkDirRec("libs", {pcFile, pcDir}):
diff --git a/tests/manyloc/named_argument_bug/main.nim.cfg b/tests/manyloc/named_argument_bug/main.nim.cfg
index 27cf8e688..7df7a0e97 100644
--- a/tests/manyloc/named_argument_bug/main.nim.cfg
+++ b/tests/manyloc/named_argument_bug/main.nim.cfg
@@ -1,2 +1,3 @@
 # this file only exists to mark 'main.nim' as the main file
 
+--path:"$projectpath"
diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim
index 22d36ef4d..7d787c07b 100644
--- a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim
+++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/gl.nim
@@ -6,7 +6,7 @@ export
   opengl
 
 type
-  EGL* = object of E_Base
+  EGL* = object of Exception
   EGL_code* = object of EGL
     code*: EGL_err
   EGL_err {.pure.} = enum
diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim
index 89bb76064..970885b3d 100644
--- a/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim
+++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/gl/shader.nim
@@ -8,7 +8,7 @@ type
   TShaderType* {.pure.} = enum
     frag = GL_FRAGMENT_SHADER,
     vert   = GL_VERTEX_SHADER
-  E_Shader* = object of E_Base
+  E_Shader* = object of Exception
   E_UnknownShaderType* = object of E_Shader
 
 converter pathToShaderType*(s: string): TShaderType =
diff --git a/tests/manyloc/named_argument_bug/tri_engine/gfx/tex.nim b/tests/manyloc/named_argument_bug/tri_engine/gfx/tex.nim
index e5043ae34..282a1ac99 100644
--- a/tests/manyloc/named_argument_bug/tri_engine/gfx/tex.nim
+++ b/tests/manyloc/named_argument_bug/tri_engine/gfx/tex.nim
@@ -25,7 +25,7 @@ proc whiteTex*(): TTex =
   setTexParams()
 
   var pixel = [255'u8, 255'u8, 255'u8, 255'u8]
-  ?glTexImage2D(GLtexture2D, 0, GL_RGBA, 1, 1, 0, GL_BGRA, cGLUnsignedByte, pixel[0].addr)
+  ?glTexImage2D(GLtexture2D, 0, GLint GL_RGBA, 1, 1, 0, GL_BGRA, cGLUnsignedByte, pixel[0].addr)
   ?glBindTexture(GLtexture2D, 0)
 
   result = gWhiteTex
diff --git a/tests/manyloc/named_argument_bug/tri_engine/math/circle.nim b/tests/manyloc/named_argument_bug/tri_engine/math/circle.nim
index 7e7517998..b95cfa379 100644
--- a/tests/manyloc/named_argument_bug/tri_engine/math/circle.nim
+++ b/tests/manyloc/named_argument_bug/tri_engine/math/circle.nim
@@ -1,6 +1,6 @@
 import
-  tri_engine/config,
-  tri_engine/math/vec
+  ../config,
+  vec
 
 type
   TCircle* = tuple[p: TV2[TR], r: TR]
diff --git a/tests/manyloc/named_argument_bug/tri_engine/math/vec.nim b/tests/manyloc/named_argument_bug/tri_engine/math/vec.nim
index 3b57acb8e..926958fe4 100644
--- a/tests/manyloc/named_argument_bug/tri_engine/math/vec.nim
+++ b/tests/manyloc/named_argument_bug/tri_engine/math/vec.nim
@@ -1,6 +1,6 @@
 import
   macros,
-  tri_engine/config
+  "../config"
 
 type
   TV2*[T:SomeNumber=TR] = array[0..1, T]
diff --git a/tests/metatype/tautoproc.nim b/tests/metatype/tautoproc.nim
index ef5377096..2c8f6a3f7 100644
--- a/tests/metatype/tautoproc.nim
+++ b/tests/metatype/tautoproc.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "empty"
+  output: "void"
 """
 
 # bug #898
diff --git a/tests/metatype/tmodulo.nim b/tests/metatype/tmodulo.nim
new file mode 100644
index 000000000..08bcc7935
--- /dev/null
+++ b/tests/metatype/tmodulo.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''1 mod 7'''
+"""
+
+# bug #3706
+
+type Modulo[M: static[int]] = distinct int
+
+proc modulo(a: int, M: static[int]): Modulo[M] = Modulo[M](a %% M)
+
+proc `+`[M: static[int]](a, b: Modulo[M]): Modulo[M] = (a.int + b.int).modulo(M)
+
+proc `$`*[M: static[int]](a: Modulo[M]): string = $(a.int) & " mod " & $(M)
+
+when isMainModule:
+  let
+    a = 3.modulo(7)
+    b = 5.modulo(7)
+  echo a + b
+
diff --git a/tests/metatype/tvoid_must_not_match.nim b/tests/metatype/tvoid_must_not_match.nim
new file mode 100644
index 000000000..240c3f751
--- /dev/null
+++ b/tests/metatype/tvoid_must_not_match.nim
@@ -0,0 +1,21 @@
+discard """
+  errormsg: "type mismatch: got (Future[system.int], void)"
+  line: 20
+"""
+
+type
+  Future[T] = object
+    value: T
+
+proc complete[T](x: T) =
+  echo "completed"
+  let y = x
+
+
+proc complete*[T](future: var Future[T], val: T) =
+  future.value = val
+
+var a: Future[int]
+
+complete(a):
+  echo "yielding void"
diff --git a/tests/method/tgeneric_methods.nim b/tests/method/tgeneric_methods.nim
new file mode 100644
index 000000000..76a68fbb0
--- /dev/null
+++ b/tests/method/tgeneric_methods.nim
@@ -0,0 +1,24 @@
+discard """
+  output: "wow2"
+"""
+type
+  First[T] = ref object of RootObj
+    value: T
+
+  Second[T] = ref object of First[T]
+    value2: T
+
+method wow[T](y: int; x: First[T]) {.base.} =
+  echo "wow1"
+
+method wow[T](y: int; x: Second[T]) =
+  echo "wow2"
+
+var
+  x: Second[int]
+new(x)
+
+proc takeFirst(x: First[int]) =
+  wow(2, x)
+
+takeFirst(x)
diff --git a/tests/method/tmultim6.nim b/tests/method/tmultim6.nim
index 97ed2845c..2c622b832 100644
--- a/tests/method/tmultim6.nim
+++ b/tests/method/tmultim6.nim
@@ -4,27 +4,27 @@ discard """
 # Test multi methods
 
 type
-  TThing = object {.inheritable.}
-  TUnit[T] = object of TThing
+  Thing = object {.inheritable.}
+  Unit[T] = object of Thing
     x: T
-  TParticle = object of TThing
+  Particle = object of Thing
     a, b: int
 
-method collide(a, b: TThing) {.base, inline.} =
+method collide(a, b: Thing) {.base, inline.} =
   quit "to override!"
 
-method collide[T](a: TThing, b: TUnit[T]) {.inline.} =
+method collide[T](a: Thing, b: Unit[T]) {.inline.} =
   write stdout, "collide: thing, unit | "
 
-method collide[T](a: TUnit[T], b: TThing) {.inline.} =
+method collide[T](a: Unit[T], b: Thing) {.inline.} =
   write stdout, "collide: unit, thing | "
 
-proc test(a, b: TThing) {.inline.} =
+proc test(a, b: Thing) {.inline.} =
   collide(a, b)
 
 var
-  a: TThing
-  b, c: TUnit[string]
-collide(b, TThing(c))
+  a: Thing
+  b, c: Unit[string]
+collide(b, Thing(c))
 test(b, c)
 collide(a, b)
diff --git a/tests/modules/texplicit_system_import.nim b/tests/modules/texplicit_system_import.nim
new file mode 100644
index 000000000..bc4d018bf
--- /dev/null
+++ b/tests/modules/texplicit_system_import.nim
@@ -0,0 +1,9 @@
+##.
+import system except `+`
+discard """
+  errormsg: "undeclared identifier: '+'"
+  line: 9
+"""
+# Testament requires that the initial """ occurs before the 40th byte
+# in the file. No kidding...
+echo 4+5
diff --git a/tests/newconfig/mymath.nim b/tests/newconfig/mymath.nim
new file mode 100644
index 000000000..5668b448b
--- /dev/null
+++ b/tests/newconfig/mymath.nim
@@ -0,0 +1,4 @@
+
+
+proc ln*(x: float): float =
+  return 0.5
diff --git a/tests/newconfig/tfoo.nim b/tests/newconfig/tfoo.nim
index d593d4a75..2e10167b1 100644
--- a/tests/newconfig/tfoo.nim
+++ b/tests/newconfig/tfoo.nim
@@ -1,10 +1,12 @@
 discard """
   cmd: "nim default $file"
-  output: '''hello world!'''
+  output: '''hello world! 0.5'''
   msg: '''[NimScript] exec: gcc -v'''
 """
 
 when not defined(definedefine):
   {.fatal: "wrong nim script configuration".}
 
-echo "hello world!"
+import math
+
+echo "hello world! ", ln 2.0
diff --git a/tests/newconfig/tfoo.nims b/tests/newconfig/tfoo.nims
index 519a868d5..057c0ed92 100644
--- a/tests/newconfig/tfoo.nims
+++ b/tests/newconfig/tfoo.nims
@@ -8,6 +8,11 @@ import ospaths
 
 --forceBuild
 
+warning("uninit", off)
+hint("processing", off)
+#--verbosity:2
+patchFile("stdlib", "math", "mymath")
+
 task listDirs, "lists every subdirectory":
   for x in listDirs("."):
     echo "DIR ", x
diff --git a/tests/objects/tobject3.nim b/tests/objects/tobject3.nim
index 2d9c8d023..15dd8ea24 100644
--- a/tests/objects/tobject3.nim
+++ b/tests/objects/tobject3.nim
@@ -49,7 +49,7 @@ proc makeDesktop(): PDesktop = new(TDesktop)
 
 proc makeWindow(): PWindow = new(TWindow)
 
-proc thisCausesError(a: var PView, b: PView) =
+proc thisCausesError(a: PView, b: PView) =
   discard
 
 var dd = makeDesktop()
diff --git a/tests/osproc/passenv.nim b/tests/osproc/passenv.nim
new file mode 100644
index 000000000..815f7536f
--- /dev/null
+++ b/tests/osproc/passenv.nim
@@ -0,0 +1,32 @@
+discard """
+  file: "passenv.nim"
+  output: "123"
+  targets: "c c++ objc"
+"""
+
+import osproc, os, strtabs
+
+# Checks that the environment is passed correctly in startProcess
+# To do that launches a copy of itself with a new environment.
+
+if paramCount() == 0:
+  # Parent process
+
+  let env = newStringTable()
+  env["A"] = "1"
+  env["B"] = "2"
+  env["C"] = "3"
+
+  let p = startProcess(
+    getAppFilename(),
+    args = @["child"],
+    env = env,
+    options = {poStdErrToStdOut, poUsePath, poParentStreams}
+  )
+
+  discard p.waitForExit
+
+else:
+  # Child process
+  # should output "123"
+  echo getEnv("A") & getEnv("B") & getEnv("C")
diff --git a/tests/overload/tissue4475.nim b/tests/overload/tissue4475.nim
new file mode 100644
index 000000000..34618cac5
--- /dev/null
+++ b/tests/overload/tissue4475.nim
@@ -0,0 +1,6 @@
+# Bug: https://github.com/nim-lang/Nim/issues/4475
+# Fix: https://github.com/nim-lang/Nim/pull/4477
+
+proc test(x: varargs[string], y: int) = discard
+
+test(y = 1)
diff --git a/tests/overload/tstmtoverload.nim b/tests/overload/tstmtoverload.nim
index f1944b637..75584bcab 100644
--- a/tests/overload/tstmtoverload.nim
+++ b/tests/overload/tstmtoverload.nim
@@ -10,7 +10,7 @@ template test(loopCount: int, extraI: int, testBody: stmt): stmt =
 
 template test(loopCount: int, extraF: float, testBody: stmt): stmt =
   block:
-    test(loopCount, round(extraF), testBody)
+    test(loopCount, round(extraF).int, testBody)
 
 template test(loopCount: int, testBody: stmt): stmt =
   block:
diff --git a/tests/overload/tvart_varargs.nim b/tests/overload/tvart_varargs.nim
new file mode 100644
index 000000000..c0c460c76
--- /dev/null
+++ b/tests/overload/tvart_varargs.nim
@@ -0,0 +1,18 @@
+
+# bug #4545
+type SomeObject = object
+    a : int
+
+type AbstractObject = object
+  objet: ptr SomeObject
+
+proc convert(this: var SomeObject): AbstractObject =
+  AbstractObject(objet: this.addr)
+
+proc varargProc(args: varargs[AbstractObject, convert]): int =
+  for arg in args:
+    result += arg.objet.a
+
+var obj = SomeObject(a: 17)
+
+discard varargProc(obj)
diff --git a/tests/parallel/twrong_refcounts.nim b/tests/parallel/twrong_refcounts.nim
index db32a96d8..57e0588a0 100644
--- a/tests/parallel/twrong_refcounts.nim
+++ b/tests/parallel/twrong_refcounts.nim
@@ -2,7 +2,7 @@ discard """
   output: "Success"
 """
 
-import math, threadPool
+import math, random, threadPool
 
 # ---
 
diff --git a/tests/parser/tdo.nim b/tests/parser/tdo.nim
new file mode 100644
index 000000000..7bd1f7411
--- /dev/null
+++ b/tests/parser/tdo.nim
@@ -0,0 +1,79 @@
+discard """
+  output: '''true
+true
+true
+true inner B'''
+"""
+
+template withValue(a, b, c, d, e: untyped) =
+  if c:
+    d
+  else:
+    e
+
+template withValue(a, b, c, d: untyped) =
+  if c:
+    d
+
+const
+  EVENT_READ = 1
+  EVENT_WRITE = 2
+  FLAG_HANDLE = 3
+  EVENT_MASK = 3
+
+var s: string
+
+proc main =
+  var value = false
+  var fd = 8888
+  var event = 0
+  s.withValue(fd, value) do:
+    if value:
+      var oe = (EVENT_MASK)
+      if (oe xor event) != 0:
+        if (oe and EVENT_READ) != 0 and (event and EVENT_READ) == 0:
+          discard
+        if (oe and EVENT_WRITE) != 0 and (event and EVENT_WRITE) == 0:
+          discard
+        if (oe and EVENT_READ) == 0 and (event and EVENT_READ) != 0:
+          discard
+        if (oe and EVENT_WRITE) == 0 and (event and EVENT_WRITE) != 0:
+          discard
+    else:
+      raise newException(ValueError, "error")
+  do:
+    raise newException(ValueError, "Descriptor is not registered in queue")
+
+proc main2 =
+  var unused = 8
+  # test 'then' branch:
+  s.withValue(unused, true) do:
+    echo "true"
+  do:
+    echo "false"
+
+  # test overloading:
+  s.withValue(unused, false) do:
+    echo "cannot come here"
+
+  # test 'else' branch:
+  s.withValue(unused, false) do:
+    echo "false"
+  do:
+    echo "true"
+
+  # test proper nesting:
+  s.withValue(unused, false) do:
+    echo "false"
+    s.withValue(unused, false) do:
+      echo "false inner A"
+    do:
+      echo "true inner A"
+  do:
+    echo "true"
+    s.withValue(unused, false) do:
+      echo "false inner B"
+    do:
+      echo "true inner B"
+
+main2()
diff --git a/tests/stdlib/nre/find.nim b/tests/stdlib/nre/find.nim
index 05bfb848a..94fdd0bc1 100644
--- a/tests/stdlib/nre/find.nim
+++ b/tests/stdlib/nre/find.nim
@@ -1,4 +1,6 @@
-import unittest, sequtils, nre, optional_nonstrict
+import unittest, sequtils
+import nre except toSeq
+import optional_nonstrict
 
 suite "find":
   test "find text":
diff --git a/tests/stdlib/thtmlparser2814.nim b/tests/stdlib/thtmlparser2814.nim
new file mode 100644
index 000000000..968d390f1
--- /dev/null
+++ b/tests/stdlib/thtmlparser2814.nim
@@ -0,0 +1,44 @@
+discard """
+  output: true
+"""
+import htmlparser
+import xmltree
+import strutils
+from streams import newStringStream
+
+
+## builds the two cases below and test that
+## ``//[dd,li]`` has "<p>that</p>" as children
+##
+##  <dl>
+##    <dt>this</dt>
+##    <dd>
+##      <p>that</p>
+##    </dd>
+##  </dl>
+
+##
+## <ul>
+##   <li>
+##     <p>that</p>
+##   </li>
+## </ul>
+
+
+for ltype in [["dl","dd"], ["ul","li"]]:
+  let desc_item = if ltype[0]=="dl": "<dt>this</dt>" else: ""
+  let item = "$1<$2><p>that</p></$2>" % [desc_item, ltype[1]]
+  let list = """ <$1>
+   $2
+</$1> """ % [ltype[0], item]
+
+  var errors : seq[string] = @[]
+
+  let parseH = parseHtml(newStringStream(list),"statichtml", errors =errors)
+
+  if $parseH.findAll(ltype[1])[0].child("p") != "<p>that</p>":
+    echo "case " & ltype[0] & " failed !"
+    quit(2)
+
+
+echo "true"
diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim
index 1ac9c8092..538582ba8 100644
--- a/tests/stdlib/tmath.nim
+++ b/tests/stdlib/tmath.nim
@@ -1,4 +1,4 @@
-import math
+import math, random
 import unittest
 import sets
 
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index cae388792..1ddaacfcb 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -1,12 +1,88 @@
-# test some things of the os module
+discard """
+  output: '''true
+true
+true
+true
+true
+true
+true
+true
+true
+All:
+__really_obscure_dir_name/are.x
+__really_obscure_dir_name/created
+__really_obscure_dir_name/dirs
+__really_obscure_dir_name/files.q
+__really_obscure_dir_name/some
+__really_obscure_dir_name/test
+__really_obscure_dir_name/testing.r
+__really_obscure_dir_name/these.txt
+Files:
+__really_obscure_dir_name/are.x
+__really_obscure_dir_name/files.q
+__really_obscure_dir_name/testing.r
+__really_obscure_dir_name/these.txt
+Dirs:
+__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
+'''
+"""
+# test os path creation, iteration, and deletion
 
 import os
 
-proc walkDirTree(root: string) =
-  for k, f in walkDir(root):
-    case k
-    of pcFile, pcLinkToFile: echo(f)
-    of pcDir: walkDirTree(f)
-    of pcLinkToDir: discard
+let files = @["these.txt", "are.x", "testing.r", "files.q"]
+let dirs = @["some", "created", "test", "dirs"]
 
-walkDirTree(".")
+let dname = "__really_obscure_dir_name"
+
+createDir(dname)
+echo dirExists(dname)
+
+# Test creating files and dirs
+for dir in dirs:
+  createDir(dname/dir)
+  echo dirExists(dname/dir)
+
+for file in files:
+  let fh = open(dname/file, fmReadWrite)
+  fh.close()
+  echo fileExists(dname/file)
+
+echo "All:"
+
+for path in walkPattern(dname/"*"):
+  echo path
+
+echo "Files:"
+
+for path in walkFiles(dname/"*"):
+  echo path
+
+echo "Dirs:"
+
+for path in walkDirs(dname/"*"):
+  echo path
+
+# Test removal of files dirs
+for dir in dirs:
+  removeDir(dname/dir)
+  echo dirExists(dname/dir)
+
+for file in files:
+  removeFile(dname/file)
+  echo fileExists(dname/file)
+
+removeDir(dname)
+echo dirExists(dname)
diff --git a/tests/stdlib/tparscfg.nim b/tests/stdlib/tparscfg.nim
index 4c11ccf61..7022d071b 100644
--- a/tests/stdlib/tparscfg.nim
+++ b/tests/stdlib/tparscfg.nim
@@ -1,25 +1,37 @@
+import parsecfg
 
-import
-  os, parsecfg, strutils, streams
+## Creating a configuration file.
+var dict1=newConfig()
+dict1.setSectionKey("","charset","utf-8")
+dict1.setSectionKey("Package","name","hello")
+dict1.setSectionKey("Package","--threads","on")
+dict1.setSectionKey("Author","name","lihf8515")
+dict1.setSectionKey("Author","qq","10214028")
+dict1.setSectionKey("Author","email","lihaifeng@wxm.com")
+dict1.writeConfig("config.ini")
+
+## Reading a configuration file.
+var dict2 = loadConfig("config.ini")
+var charset = dict2.getSectionValue("","charset")
+var threads = dict2.getSectionValue("Package","--threads")
+var pname = dict2.getSectionValue("Package","name")
+var name = dict2.getSectionValue("Author","name")
+var qq = dict2.getSectionValue("Author","qq")
+var email = dict2.getSectionValue("Author","email")
+echo charset
+echo threads
+echo pname
+echo name
+echo qq
+echo email
+
+## Modifying a configuration file.
+var dict3 = loadConfig("config.ini")
+dict3.setSectionKey("Author","name","lhf")
+dict3.writeConfig("config.ini")
+
+## Deleting a section key in a configuration file.
+var dict4 = loadConfig("config.ini")
+dict4.delSectionKey("Author","email")
+dict4.writeConfig("config.ini")
 
-var f = newFileStream(paramStr(1), fmRead)
-if f != nil:
-  var p: TCfgParser
-  open(p, f, paramStr(1))
-  while true:
-    var e = next(p)
-    case e.kind
-    of cfgEof:
-      echo("EOF!")
-      break
-    of cfgSectionStart:   ## a ``[section]`` has been parsed
-      echo("new section: " & e.section)
-    of cfgKeyValuePair:
-      echo("key-value-pair: " & e.key & ": " & e.value)
-    of cfgOption:
-      echo("command: " & e.key & ": " & e.value)
-    of cfgError:
-      echo(e.msg)
-  close(p)
-else:
-  echo("cannot open: " & paramStr(1))
diff --git a/tests/stdlib/tparseuints.nim b/tests/stdlib/tparseuints.nim
new file mode 100644
index 000000000..5be3bcbd0
--- /dev/null
+++ b/tests/stdlib/tparseuints.nim
@@ -0,0 +1,11 @@
+discard """
+  action: run
+"""
+import unittest, strutils
+
+suite "parseutils":
+  test "uint":
+    check: parseBiggestUInt("0") == 0'u64
+    check: parseBiggestUInt("18446744073709551615") == 0xFFFF_FFFF_FFFF_FFFF'u64
+    expect(ValueError):
+      discard parseBiggestUInt("18446744073709551616")
diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim
new file mode 100644
index 000000000..c702ccc2a
--- /dev/null
+++ b/tests/stdlib/trstgen.nim
@@ -0,0 +1,139 @@
+# tests for rstgen module.
+
+import ../../lib/packages/docutils/rstgen
+import unittest
+
+suite "YAML syntax highlighting":
+  test "Basics":
+    let input = """.. code-block:: yaml
+    %YAML 1.2
+    ---
+    a string: string
+    a list:
+      - item 1
+      - item 2
+    a map:
+    ? key
+    : value
+    ..."""
+    let output = rstTohtml(input, {}, defaultConfig())
+    assert output == """<pre class = "listing"><span class="Directive">%YAML 1.2</span>
+<span class="Keyword">---</span>
+<span class="StringLit">a string</span><span class="Punctuation">:</span> <span class="StringLit">string</span>
+<span class="StringLit">a list</span><span class="Punctuation">:</span>
+  <span class="Punctuation">-</span> <span class="StringLit">item 1</span>
+  <span class="Punctuation">-</span> <span class="StringLit">item 2</span>
+<span class="StringLit">a map</span><span class="Punctuation">:</span>
+<span class="Punctuation">?</span> <span class="StringLit">key</span>
+<span class="Punctuation">:</span> <span class="StringLit">value</span>
+<span class="Keyword">...</span></pre>"""
+  
+  test "Block scalars":
+    let input = """.. code-block:: yaml
+    a literal block scalar: |
+      some text
+      # not a comment
+     # a comment, since less indented
+      # another comment
+    a folded block scalar: >2
+       some text
+      # not a comment since indented as specified
+     # a comment
+    another literal block scalar:
+      |+ # comment after header
+     allowed, since more indented than parent"""
+    let output = rstToHtml(input, {}, defaultConfig())
+    assert output == """<pre class = "listing"><span class="StringLit">a literal block scalar</span><span class="Punctuation">:</span> <span class="Command">|</span><span class="Command"></span><span class="LongStringLit">
+  some text
+  # not a comment
+ </span><span class="Comment"># a comment, since less indented</span>
+  <span class="Comment"># another comment</span>
+<span class="StringLit">a folded block scalar</span><span class="Punctuation">:</span> <span class="Command">&gt;2</span><span class="Command"></span><span class="LongStringLit">
+   some text
+  # not a comment since indented as specified
+ </span><span class="Comment"># a comment</span>
+<span class="StringLit">another literal block scalar</span><span class="Punctuation">:</span>
+  <span class="Command">|+</span> <span class="Comment"># comment after header</span><span class="LongStringLit">
+ allowed, since more indented than parent</span></pre>"""
+ 
+  test "Directives":
+    let input = """.. code-block:: yaml
+    %YAML 1.2
+    ---
+    %not a directive
+    ...
+    %a directive
+    ...
+    a string
+    % not a directive
+    ...
+    %TAG ! !foo:"""
+    let output = rstToHtml(input, {}, defaultConfig())
+    assert output == """<pre class = "listing"><span class="Directive">%YAML 1.2</span>
+<span class="Keyword">---</span>
+<span class="StringLit">%not a directive</span>
+<span class="Keyword">...</span>
+<span class="Directive">%a directive</span>
+<span class="Keyword">...</span>
+<span class="StringLit">a string</span>
+<span class="StringLit">% not a directive</span>
+<span class="Keyword">...</span>
+<span class="Directive">%TAG ! !foo:</span></pre>"""
+
+  test "Flow Style and Numbers":
+    let input = """.. code-block:: yaml
+    {
+      "quoted string": 42,
+      'single quoted string': false,
+      [ list, "with", 'entries' ]: 73.32e-73,
+      more numbers: [-783, 11e78],
+      not numbers: [ 42e, 0023, +32.37, 8 ball]
+    }"""
+    let output = rstToHtml(input, {}, defaultConfig())
+    assert output == """<pre class = "listing"><span class="Punctuation">{</span>
+  <span class="StringLit">&quot;</span><span class="StringLit">quoted string&quot;</span><span class="Punctuation">:</span> <span class="DecNumber">42</span><span class="Punctuation">,</span>
+  <span class="StringLit">'single quoted string'</span><span class="Punctuation">:</span> <span class="StringLit">false</span><span class="Punctuation">,</span>
+  <span class="Punctuation">[</span> <span class="StringLit">list</span><span class="Punctuation">,</span> <span class="StringLit">&quot;</span><span class="StringLit">with&quot;</span><span class="Punctuation">,</span> <span class="StringLit">'entries'</span> <span class="Punctuation">]</span><span class="Punctuation">:</span> <span class="FloatNumber">73.32e-73</span><span class="Punctuation">,</span>
+  <span class="StringLit">more numbers</span><span class="Punctuation">:</span> <span class="Punctuation">[</span><span class="DecNumber">-783</span><span class="Punctuation">,</span> <span class="FloatNumber">11e78</span><span class="Punctuation">]</span><span class="Punctuation">,</span>
+  <span class="StringLit">not numbers</span><span class="Punctuation">:</span> <span class="Punctuation">[</span> <span class="StringLit">42e</span><span class="Punctuation">,</span> <span class="StringLit">0023</span><span class="Punctuation">,</span> <span class="StringLit">+32.37</span><span class="Punctuation">,</span> <span class="StringLit">8 ball</span><span class="Punctuation">]</span>
+<span class="Punctuation">}</span></pre>"""
+  
+  test "Anchors, Aliases, Tags":
+    let input = """.. code-block:: yaml
+    --- !!map
+    !!str string: !<tag:yaml.org,2002:int> 42
+    ? &anchor !!seq []:
+    : !localtag foo
+    alias: *anchor
+    """
+    let output = rstToHtml(input, {}, defaultConfig())
+    assert output == """<pre class = "listing"><span class="Keyword">---</span> <span class="TagStart">!!map</span>
+<span class="TagStart">!!str</span> <span class="StringLit">string</span><span class="Punctuation">:</span> <span class="TagStart">!&lt;tag:yaml.org,2002:int&gt;</span> <span class="DecNumber">42</span>
+<span class="Punctuation">?</span> <span class="Label">&amp;anchor</span> <span class="TagStart">!!seq</span> <span class="Punctuation">[</span><span class="Punctuation">]</span><span class="Punctuation">:</span>
+<span class="Punctuation">:</span> <span class="TagStart">!localtag</span> <span class="StringLit">foo</span>
+<span class="StringLit">alias</span><span class="Punctuation">:</span> <span class="Reference">*anchor</span></pre>"""
+
+  test "Edge cases":
+    let input = """.. code-block:: yaml
+    ...
+     %a string:
+      a:string:not:a:map
+    ...
+    not a list:
+      -2
+      -3
+      -4
+    example.com/not/a#comment:
+      ?not a map key
+    """
+    let output = rstToHtml(input, {}, defaultConfig())
+    assert output == """<pre class = "listing"><span class="Keyword">...</span>
+ <span class="StringLit">%a string</span><span class="Punctuation">:</span>
+  <span class="StringLit">a:string:not:a:map</span>
+<span class="Keyword">...</span>
+<span class="StringLit">not a list</span><span class="Punctuation">:</span>
+  <span class="DecNumber">-2</span>
+  <span class="DecNumber">-3</span>
+  <span class="DecNumber">-4</span>
+<span class="StringLit">example.com/not/a#comment</span><span class="Punctuation">:</span>
+  <span class="StringLit">?not a map key</span></pre>"""
\ No newline at end of file
diff --git a/tests/stdlib/tsplit.nim b/tests/stdlib/tsplit.nim
index 5a1cd2f5f..44da58aca 100644
--- a/tests/stdlib/tsplit.nim
+++ b/tests/stdlib/tsplit.nim
@@ -9,7 +9,7 @@ for w in split("|abc|xy|z", {'|'}):
   s.add("#")
   s.add(w)
 
-if s == "#abc#xy#z":
+if s == "##abc#xy#z":
   echo "true"
 else:
   echo "false"
diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim
index 4b210c23b..e87cd3508 100644
--- a/tests/stdlib/tunittest.nim
+++ b/tests/stdlib/tunittest.nim
@@ -26,7 +26,7 @@ test "unittest multiple requires":
   require(true)
 
 
-import math
+import math, random
 from strutils import parseInt
 proc defectiveRobot() =
   randomize()
@@ -83,3 +83,9 @@ suite "suite with both":
 
   test "unittest with both 2":
     check c == 2
+
+suite "bug #4494":
+    test "Uniqueness check":
+      var tags = @[1, 2, 3, 4, 5]
+      check:
+        allIt(0..3, tags[it] != tags[it + 1])
diff --git a/tests/template/mlt.nim b/tests/template/mlt.nim
new file mode 100644
index 000000000..e567cf085
--- /dev/null
+++ b/tests/template/mlt.nim
@@ -0,0 +1,3 @@
+
+type Point* = ref object of RootObj
+proc `>`*(p1, p2: Point): bool = false
diff --git a/tests/template/t2do.nim b/tests/template/t2do.nim
index b87e3328c..ec364c5f3 100644
--- a/tests/template/t2do.nim
+++ b/tests/template/t2do.nim
@@ -15,8 +15,9 @@ template toFloatHelper(result: expr; tooSmall, tooLarge: stmt) {.immediate.} =
     tooLarge
 
 proc toFloat*(a: int): float =
-  toFloatHelper(result)
-    do: raise newException(ValueError, "number too small"):
-        raise newException(ValueError, "number too large")
+  toFloatHelper(result) do:
+    raise newException(ValueError, "number too small")
+  do:
+    raise newException(ValueError, "number too large")
 
 echo toFloat(8)
diff --git a/tests/template/tlt.nim b/tests/template/tlt.nim
new file mode 100644
index 000000000..75c7dd991
--- /dev/null
+++ b/tests/template/tlt.nim
@@ -0,0 +1,7 @@
+
+import mlt
+# bug #4564
+type Bar* = ref object of RootObj
+proc foo(a: Bar): int = 0
+var a: Bar
+let b = a.foo() > 0
diff --git a/tests/template/typedescids.nim b/tests/template/typedescids.nim
new file mode 100644
index 000000000..ebed49b17
--- /dev/null
+++ b/tests/template/typedescids.nim
@@ -0,0 +1,17 @@
+discard """
+  output: '''2 3'''
+"""
+
+# bug #4097
+
+var i {.compileTime.} = 2
+
+template defineId*(t: typedesc): stmt =
+  const id {.genSym.} = i
+  static: inc(i)
+  proc idFor*(T: typedesc[t]): int {.inline, raises: [].} = id
+
+defineId(int8)
+defineId(int16)
+
+echo idFor(int8), " ", idFor(int16)
diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims
new file mode 100644
index 000000000..436e990ef
--- /dev/null
+++ b/tests/test_nimscript.nims
@@ -0,0 +1,25 @@
+# This nimscript is used to test if the following modules can be imported
+# http://nim-lang.org/docs/nims.html
+
+import algorithm
+import base64
+import colors
+import hashes
+import lists
+import math
+# import marshal
+import options
+import ospaths
+# import parsecfg
+# import parseopt
+import parseutils
+# import pegs
+import queues
+import sequtils
+import strutils
+import subexes
+import tables
+import unicode
+import uri
+
+echo "Nimscript imports are successful."
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 150c55edc..e534cc161 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -152,6 +152,9 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
   testWithoutBoehm "closureleak"
   testWithoutMs "refarrayleak"
 
+  testWithoutBoehm "tlists"
+  testWithoutBoehm "thavlak"
+
   test "stackrefleak"
   test "cyclecollector"
 
@@ -223,7 +226,7 @@ proc jsTests(r: var TResults, cat: Category, options: string) =
                    "varres/tvartup", "misc/tints", "misc/tunsignedinc"]:
     test "tests/" & testfile & ".nim"
 
-  for testfile in ["pure/strutils", "pure/json"]:
+  for testfile in ["pure/strutils", "pure/json", "pure/random", "pure/times"]:
     test "lib/" & testfile & ".nim"
 
 # ------------------------- manyloc -------------------------------------------
@@ -257,12 +260,14 @@ proc compileExample(r: var TResults, pattern, options: string, cat: Category) =
     testNoSpec r, makeTest(test, options, cat)
 
 proc testStdlib(r: var TResults, pattern, options: string, cat: Category) =
+  var disabledSet = disabledFiles.toSet()
   for test in os.walkFiles(pattern):
-    let contents = readFile(test).string
-    if contents.contains("when isMainModule"):
-      testSpec r, makeTest(test, options, cat, actionRunNoSpec)
-    else:
-      testNoSpec r, makeTest(test, options, cat, actionCompile)
+    if test notin disabledSet:
+      let contents = readFile(test).string
+      if contents.contains("when isMainModule"):
+        testSpec r, makeTest(test, options, cat, actionRunNoSpec)
+      else:
+        testNoSpec r, makeTest(test, options, cat, actionCompile)
 
 # ----------------------------- nimble ----------------------------------------
 type PackageFilter = enum
diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim
index bab17d2cd..b9519c70f 100644
--- a/tests/testament/specs.nim
+++ b/tests/testament/specs.nim
@@ -107,6 +107,15 @@ proc specDefaults*(result: var TSpec) =
   result.tline = 0
   result.tcolumn = 0
 
+proc parseTargets*(value: string): set[TTarget] =
+  for v in value.normalize.split:
+    case v
+    of "c": result.incl(targetC)
+    of "cpp", "c++": result.incl(targetCpp)
+    of "objc": result.incl(targetObjC)
+    of "js": result.incl(targetJS)
+    else: echo "target ignored: " & v
+
 proc parseSpec*(filename: string): TSpec =
   specDefaults(result)
   result.file = filename
@@ -146,7 +155,11 @@ proc parseSpec*(filename: string): TSpec =
       result.nimout = e.value
     of "disabled":
       if parseCfgBool(e.value): result.err = reIgnored
-    of "cmd": result.cmd = e.value
+    of "cmd":
+      if e.value.startsWith("nim "):
+        result.cmd = "compiler" / e.value
+      else:
+        result.cmd = e.value
     of "ccodecheck": result.ccodeCheck = e.value
     of "target", "targets":
       for v in e.value.normalize.split:
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index b1e8ac099..83e59a6c1 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -12,7 +12,7 @@
 import
   parseutils, strutils, pegs, os, osproc, streams, parsecfg, json,
   marshal, backend, parseopt, specs, htmlgen, browsers, terminal,
-  algorithm, compiler/nodejs, re, times
+  algorithm, compiler/nodejs, re, times, sets
 
 const
   resultsFile = "testresults.html"
@@ -33,6 +33,7 @@ Options:
   --print                   also print results to the console
   --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)
 """ % resultsFile
 
 type
@@ -60,6 +61,8 @@ let
   pegSuccess = peg"'Hint: operation successful'.*"
   pegOfInterest = pegLineError / pegOtherError
 
+var targets = {low(TTarget)..high(TTarget)}
+
 proc callCompiler(cmdTemplate, filename, options: string,
                   target: TTarget): TSpec =
   let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target],
@@ -275,7 +278,13 @@ proc analyzeAndConsolidateOutput(s: string): string =
 
 proc testSpec(r: var TResults, test: TTest) =
   # major entry point for a single test
+  if test.target notin targets:
+    r.addResult(test, "", "", reIgnored)
+    inc(r.skipped)
+    return
+
   let tname = test.name.addFileExt(".nim")
+  #echo "TESTING ", tname
   inc(r.total)
   var expected: TSpec
   if test.action != actionRunNoSpec:
@@ -336,7 +345,7 @@ proc testSpec(r: var TResults, test: TTest) =
                         reExitCodesDiffer)
       return
 
-    if bufB != expectedOut:
+    if bufB != expectedOut and expected.action != actionRunNoSpec:
       if not (expected.substr and expectedOut in bufB):
         given.err = reOutputsDiffer
         r.addResult(test, expected.outp, bufB, reOutputsDiffer)
@@ -379,6 +388,10 @@ proc makeTest(test, options: string, cat: Category, action = actionCompile,
   result = TTest(cat: cat, name: test, options: options,
                  target: target, action: action, startTime: epochTime())
 
+const
+  # array of modules disabled from compilation test of stdlib.
+  disabledFiles = ["-"]
+
 include categories
 
 # proc runCaasTests(r: var TResults) =
@@ -394,6 +407,7 @@ proc main() =
   var optPrintResults = false
   var optFailing = false
   var optPedantic = false
+
   var p = initOptParser()
   p.next()
   while p.kind == cmdLongoption:
@@ -401,6 +415,7 @@ proc main() =
     of "print", "verbose": optPrintResults = true
     of "failing": optFailing = true
     of "pedantic": optPedantic = true
+    of "targets": targets = parseTargets(p.val.string)
     else: quit Usage
     p.next()
   if p.kind != cmdArgument: quit Usage
diff --git a/tests/threads/ttryrecv.nim b/tests/threads/ttryrecv.nim
index be79fadae..4a98e6c27 100644
--- a/tests/threads/ttryrecv.nim
+++ b/tests/threads/ttryrecv.nim
@@ -4,7 +4,7 @@ discard """
 
 # bug #1816
 
-from math import random
+from random import random
 from os import sleep
 
 type PComm = ptr Channel[int]
diff --git a/tests/trmacros/tpatterns.nim b/tests/trmacros/tpatterns.nim
index 6bc8772e3..907973637 100644
--- a/tests/trmacros/tpatterns.nim
+++ b/tests/trmacros/tpatterns.nim
@@ -1,6 +1,7 @@
 discard """
   output: '''48
-hel'''
+hel
+lo'''
 """
 
 template optZero{x+x}(x: int): int = x*3
@@ -15,3 +16,8 @@ s[0] = "hello"
 s[0] = substr(s[0], 0, 2)
 
 echo s[0]
+
+# Test varargs matching
+proc someVarargProc(k: varargs[string]) = doAssert(false) # this should not get called
+template someVarargProcSingleArg{someVarargProc([a])}(a: string) = echo a
+someVarargProc("lo")
diff --git a/tests/trmacros/tstatic_t_bug.nim b/tests/trmacros/tstatic_t_bug.nim
new file mode 100644
index 000000000..cdfa53514
--- /dev/null
+++ b/tests/trmacros/tstatic_t_bug.nim
@@ -0,0 +1,24 @@
+discard """
+  output: "optimized"
+"""
+# bug #4227
+type Vector64[N: static[int]] = array[N, int]
+
+proc `*`*[N: static[int]](a: Vector64[N]; b: float64): Vector64[N] =
+  result = a
+
+proc `+=`*[N: static[int]](a: var Vector64[N]; b: Vector64[N]) =
+  echo "regular"
+
+proc linearCombinationMut[N: static[int]](a: float64, v: var Vector64[N], w: Vector64[N])  {. inline .} =
+  echo "optimized"
+
+template rewriteLinearCombinationMut*{v += `*`(w, a)}(a: float64, v: var Vector64, w: Vector64): auto =
+  linearCombinationMut(a, v, w)
+
+proc main() =
+  const scaleVal = 9.0
+  var a, b: Vector64[7]
+  a += b * scaleval
+
+main()
diff --git a/tests/tuples/tconver_tuple.nim b/tests/tuples/tconver_tuple.nim
new file mode 100644
index 000000000..306da77fe
--- /dev/null
+++ b/tests/tuples/tconver_tuple.nim
@@ -0,0 +1,23 @@
+# Bug 4479
+
+type
+  MyTuple = tuple
+    num: int
+    strings: seq[string]
+    ints: seq[int]
+
+var foo = MyTuple((
+  num: 7,
+  strings: @[],
+  ints: @[],
+))
+
+var bar = (
+  num: 7,
+  strings: @[],
+  ints: @[],
+).MyTuple
+
+var fooUnnamed = MyTuple((7, @[], @[]))
+var n = 7
+var fooSym = MyTuple((num: n, strings: @[], ints: @[]))
diff --git a/tests/tuples/tuple_with_nil.nim b/tests/tuples/tuple_with_nil.nim
index 442fbab92..9b5d583d3 100644
--- a/tests/tuples/tuple_with_nil.nim
+++ b/tests/tuples/tuple_with_nil.nim
@@ -4,7 +4,7 @@ import parseutils
 import unicode
 import math
 import fenv
-import unsigned
+#import unsigned
 import pegs
 import streams
 
diff --git a/tests/tuples/twrong_generic_caching.nim b/tests/tuples/twrong_generic_caching.nim
new file mode 100644
index 000000000..32ef344d2
--- /dev/null
+++ b/tests/tuples/twrong_generic_caching.nim
@@ -0,0 +1,4 @@
+
+import parsecfg
+
+import asynchttpserver
diff --git a/tests/typerel/tclosure_nil_as_default.nim b/tests/typerel/tclosure_nil_as_default.nim
new file mode 100644
index 000000000..fe9f42b14
--- /dev/null
+++ b/tests/typerel/tclosure_nil_as_default.nim
@@ -0,0 +1,11 @@
+
+# bug #4328
+type
+    foo[T] = object
+        z: T
+
+proc test[T](x: foo[T], p: proc(a: T) = nil) =
+    discard
+
+var d: foo[int]
+d.test()  # <- param omitted
diff --git a/tests/typerel/temptynode.nim b/tests/typerel/temptynode.nim
new file mode 100644
index 000000000..b32b16121
--- /dev/null
+++ b/tests/typerel/temptynode.nim
@@ -0,0 +1,16 @@
+discard """
+  line: 16
+  errormsg: "type mismatch: got (void)"
+"""
+
+# bug #950
+
+import macros
+
+proc blah(x: proc (a, b: int): int) =
+  echo x(5, 5)
+
+macro test(): stmt =
+  result = newNimNode(nnkEmpty)
+
+blah(test())
diff --git a/tests/typerel/tgeneric_subtype_regression.nim b/tests/typerel/tgeneric_subtype_regression.nim
new file mode 100644
index 000000000..e279c0ad4
--- /dev/null
+++ b/tests/typerel/tgeneric_subtype_regression.nim
@@ -0,0 +1,19 @@
+discard """
+  errormsg: "type mismatch: got (FooRef[system.string])"
+  line: 15
+"""
+
+# bug #4478
+
+type
+  Foo[T] = object
+  FooRef[T] = ref Foo[T]
+
+proc takeFoo[T](foo: Foo[T]): int = discard
+
+proc g(x: FooRef[string]) =
+  echo x.takeFoo() != 8
+
+var x: FooRef[string]
+
+g(x)
diff --git a/tests/types/tassignemptytuple.nim b/tests/types/tassignemptytuple.nim
new file mode 100644
index 000000000..bdfc653a5
--- /dev/null
+++ b/tests/types/tassignemptytuple.nim
@@ -0,0 +1,11 @@
+discard """
+  file: "tassignemptytuple.nim"
+  line: 11
+  errormsg: "cannot infer the type of the tuple"
+"""
+
+var
+  foo: seq[int]
+  bar: tuple[a: seq[int], b: set[char]]
+
+(foo, bar) = (@[], (@[], {}))
diff --git a/tests/types/typeof_produces_alias.nim b/tests/types/typeof_produces_alias.nim
new file mode 100644
index 000000000..44cb00c94
--- /dev/null
+++ b/tests/types/typeof_produces_alias.nim
@@ -0,0 +1,25 @@
+
+# bug #4124
+
+import sequtils
+
+type
+    Foo = distinct string
+
+var
+  foo: Foo
+
+type
+    Alias = (type(foo))
+var
+  a: Alias
+
+a = foo
+
+when true:
+  var xs = @[1,2,3]
+
+  proc asFoo(i: string): Foo =
+      Foo(i)
+
+  var xx = xs.mapIt(asFoo($(it + 5)))
diff --git a/tests/usingstmt/tthis.nim b/tests/usingstmt/tthis.nim
new file mode 100644
index 000000000..83d75d08c
--- /dev/null
+++ b/tests/usingstmt/tthis.nim
@@ -0,0 +1,15 @@
+
+# bug #4177
+
+type
+  Parent = object of RootObj
+    parentField: int
+  Child = object of Parent
+    childField: int
+
+{.this: self.}
+proc sumFields(self: Child): int =
+  result = parentField + childField # Error: undeclared identifier: 'parentField'
+
+proc sumFieldsWorks(self: Child): int =
+  result = self.parentField + childField
diff --git a/tests/vm/meta.nim b/tests/vm/meta.nim
new file mode 100644
index 000000000..2aa01b5b3
--- /dev/null
+++ b/tests/vm/meta.nim
@@ -0,0 +1,240 @@
+#
+# meta.nim
+#
+
+import tables
+import macros
+
+type
+  NodeSeq* = seq[NimNode]
+  Ident* = tuple[name: string, exported: bool]
+  Bracket* = seq[Ident]
+  Field* = tuple[identifier: Ident, type_name: string, default: string]
+  FieldSeq* = seq[Field]
+  TypeDef* = object
+    identifier*: Ident
+    fields*: FieldSeq
+    is_ref*: bool
+    object_type*: string
+    base_type*: string
+  TypeDefSeq* = seq[TypeDef]
+  Proc* = tuple[identifier: Ident, params: FieldSeq,
+                returns: Ident, generics: FieldSeq, body: NimNode]
+  ProcSeq* = seq[Proc]
+
+# Ident procs
+proc newIdent*(name: string, exported = false): Ident =
+  result.name = name
+  result.exported = exported
+
+proc newIdent*(node: NimNode): Ident =
+  case node.kind:
+    of nnkPostfix:
+      result = newIdent(node[1])
+      result.exported = true
+    of nnkIdent, nnkSym:
+      result.name = $(node)
+    else:
+      let msg = "newIdent cannot initialize from node kind: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+proc render*(i: Ident): NimNode {.compileTime.} =
+  if i.name == nil:
+    return newNimNode(nnkEmpty)
+
+  if i.exported:
+    result = newNimNode(nnkPostfix)
+    result.add(ident "*")
+    result.add(ident i.name)
+  else:
+    result = ident i.name
+
+proc `$`*(identifier: Ident): string = identifier.name
+
+converter toString*(x: Ident): string = x.name
+
+proc newBracket*(node: NimNode): Bracket =
+  result = @[]
+  case node.kind:
+    of nnkBracket:
+      for child in node:
+        if child.kind != nnkIdent:
+          let msg = "Bracket members can only be nnkIdent not kind: " & $(node.kind)
+          raise newException(ValueError, msg)
+        result.add(newIdent(child))
+    else:
+      let msg = "newBracket must initialize from node kind nnkBracket not: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+# Field procs
+proc newField*(identifier: Ident, type_name: string, default: string = nil): Field =
+  result.identifier = identifier
+  result.type_name = type_name
+  result.default = default
+
+proc newField*(node: NimNode): Field =
+  case node.kind:
+    of nnkIdentDefs:
+      if node.len > 3:
+        let msg = "newField cannot initialize from nnkIdentDefs with multiple names"
+        raise newException(ValueError, msg)
+      result.identifier = newIdent(node[0])
+      result.type_name = $(node[1])
+      case node[2].kind:
+        of nnkIdent:
+          result.default = $(node[2])
+        else:
+          result.default = nil
+    else:
+      let msg = "newField cannot initialize from node kind: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+# FieldSeq procs
+proc newFieldSeq*(node: NimNode): FieldSeq =
+  result = @[]
+  case node.kind:
+    of nnkIdentDefs:
+      let
+        type_name = $(node[node.len - 2])
+        default_node = node[node.len - 1]
+      var default: string
+      case default_node.kind:
+        of nnkIdent:
+          default = $(default_node)
+        else:
+          default = nil
+      for i in 0..node.len - 3:
+        let name = newIdent(node[i])
+        result.add(newField(name, type_name, default))
+    of nnkRecList, nnkVarSection, nnkGenericParams:
+      for child in node:
+        result = result & newFieldSeq(child)
+    else:
+      let msg = "newFieldSeq cannot initialize from node kind: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+proc render*(f: Field): NimNode {.compileTime.} =
+  let identifier = f.identifier.render()
+  let type_name = if f.type_name != nil: ident(f.type_name) else: newEmptyNode()
+  let default = if f.default != nil: ident(f.default) else: newEmptyNode()
+  newIdentDefs(identifier, type_name, default)
+
+proc render*(fs: FieldSeq): NimNode {.compileTime.} =
+  result = newNimNode(nnkRecList)
+  for field in fs:
+    result.add(field.render())
+
+# TypeDef procs
+proc newTypeDef*(identifier: Ident, is_ref = false,
+                object_type = "object",
+                base_type: string = nil): TypeDef {.compileTime.} =
+  result.identifier = identifier
+  result.fields = @[]
+  result.is_ref = is_ref
+  result.object_type = "object"
+  result.base_type = base_type
+
+proc newTypeDef*(node: NimNode): TypeDef {.compileTime.} =
+  case node.kind:
+    of nnkTypeDef:
+      result.identifier = newIdent($(node[0]))
+      var object_node: NimNode
+      case node[2].kind:
+        of nnkRefTy:
+          object_node = node[2][0]
+          result.is_ref = true
+        of nnkObjectTy:
+          object_node = node[2]
+          result.is_ref = false
+        else:
+          let msg = "newTypeDef could not parse RefTy/ObjectTy, found: " & $(node[2].kind)
+          raise newException(ValueError, msg)
+      case object_node[1].kind:
+        of nnkOfInherit:
+          result.base_type = $(object_node[1][0])
+        else:
+          result.base_type = "object"
+      result.fields = newFieldSeq(object_node[2])
+    else:
+      let msg = "newTypeDef cannot initialize from node kind: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+proc render*(typedef: TypeDef): NimNode {.compileTime.} =
+  result = newNimNode(nnkTypeDef)
+  result.add(typedef.identifier.render)
+  result.add(newEmptyNode())
+  let object_node = newNimNode(nnkObjectTy)
+  object_node.add(newEmptyNode())
+  if typedef.base_type == nil:
+    object_node.add(newEmptyNode())
+  else:
+    var base_type = newNimNode(nnkOfInherit)
+    base_type.add(ident(typedef.base_type))
+    object_node.add(base_type)
+  let fields = typedef.fields.render()
+  object_node.add(fields)
+  if typedef.is_ref:
+    let ref_node = newNimNode(nnkRefTy)
+    ref_node.add(object_node)
+    result.add(ref_node)
+  else:
+    result.add(object_node)
+
+proc newTypeDefSeq*(node: NimNode): TypeDefSeq =
+  result = @[]
+  case node.kind:
+    of nnkTypeSection:
+      for child in node:
+        result.add(newTypeDef(child))
+    else:
+      let msg = "newTypeSection could not parse TypeDef, found: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+proc render*(typeseq: TypeDefSeq): NimNode {.compileTime.} =
+  result = newNimNode(nnkTypeSection)
+  for typedef in typeseq:
+    result.add(typedef.render())
+
+proc newProc*(identifier: Ident, params: FieldSeq = nil,
+              returns: Ident, generics: FieldSeq = nil): Proc =
+  result.identifier = identifier
+  result.params = params
+  result.returns = returns
+  result.generics = generics
+
+proc newProc*(node: NimNode): Proc =
+  case node.kind:
+    of nnkProcDef, nnkMethodDef:
+      result.identifier = newIdent(node[0])
+      case node[2].kind:
+        of nnkGenericParams:
+          result.generics = newFieldSeq(node[2])
+        else: result.generics = nil
+      let formal_params = node[3]
+      case formal_params[0].kind:
+        of nnkIdent:
+          result.returns = newIdent(formal_params[0])
+        else: discard
+      result.params = @[]
+      for i in 1..formal_params.len - 1:
+        let param = formal_params[i]
+        for field in newFieldSeq(param):
+          result.params.add(field)
+      result.body = node[6]
+    else:
+      let msg = "newProc cannot initialize from node kind: " & $(node.kind)
+      raise newException(ValueError, msg)
+
+proc render*(procdef: Proc): NimNode {.compileTime.} =
+  result = newNimNode(nnkProcDef)
+  result.add(procdef.identifier.render())
+  result.add(newEmptyNode())
+  result.add(newEmptyNode())
+  let formal_params = newNimNode(nnkFormalParams)
+  formal_params.add(procdef.returns.render())
+  for param in procdef.params:
+    formal_params.add(param.render())
+  result.add(formal_params)
+  result.add(newEmptyNode())
+  result.add(newEmptyNode())
+  result.add(procdef.body)
diff --git a/tests/vm/tanonproc.nim b/tests/vm/tanonproc.nim
new file mode 100644
index 000000000..474b768ca
--- /dev/null
+++ b/tests/vm/tanonproc.nim
@@ -0,0 +1,52 @@
+discard """
+  output: '''`Test`'''
+"""
+
+# bug #3561
+
+import macros, future, strutils
+
+type
+  Option[T] = ref object
+    case valid: bool
+    of true:
+      data: T
+    else:
+      discard
+
+proc some[T](v: T): Option[T] = Option[T](valid: true, data: v)
+proc none[T](v: T): Option[T] = Option[T](valid: false)
+proc none(T: typedesc): Option[T] = Option[T](valid: false)
+
+proc map[T,U](o: Option[T], f: T -> U): Option[U] =
+  case o.valid
+  of true:
+    f(o.data).some
+  else:
+    U.none
+
+proc notEmpty(o: Option[string]): Option[string] =
+  case o.valid
+  of true:
+    if o.data.strip == "": string.none else: o.data.strip.some
+  else:
+    o
+
+proc getOrElse[T](o: Option[T], def: T): T =
+  case o.valid
+  of true:
+    o.data
+  else:
+    def
+
+proc quoteStr(s: string): Option[string] =
+  s.some.notEmpty.map(v => "`" & v & "`")
+
+macro str(s: string): stmt =
+  let x = s.strVal
+  let y = quoteStr(x)
+  let sn = newStrLitNode(y.getOrElse("NONE"))
+  result = quote do:
+    echo `sn`
+
+str"Test"
diff --git a/tests/vm/tcomponent.nim b/tests/vm/tcomponent.nim
new file mode 100644
index 000000000..efeba2a6d
--- /dev/null
+++ b/tests/vm/tcomponent.nim
@@ -0,0 +1,132 @@
+discard """
+  output: '''`:)` @ 0,0
+FOO: blah'''
+"""
+
+#
+# magic.nim
+#
+
+# bug #3729
+
+import macros, sequtils, tables
+import strutils
+import future, meta
+
+type
+  Component = object
+    fields: FieldSeq
+    field_index: seq[string]
+    procs: ProcSeq
+    procs_index: seq[string]
+
+  Registry = object
+    field_index: seq[string]
+    procs_index: seq[string]
+    components: Table[string, Component]
+    builtin: Component
+
+proc newRegistry(): Registry =
+  result.field_index = @[]
+  result.procs_index = @[]
+  result.components = initTable[string, Component]()
+
+var registry {.compileTime.} = newRegistry()
+
+proc validateComponent(r: var Registry, name: string, c: Component) =
+  if r.components.hasKey(name):
+    let msg = "`component` macro cannot consume duplicated identifier: " & name
+    raise newException(ValueError, msg)
+
+  for field_name in c.field_index:
+    if r.field_index.contains(field_name):
+      let msg = "`component` macro cannot delcare duplicated field: " & field_name
+      raise newException(ValueError, msg)
+    r.field_index.add(field_name)
+
+  for proc_name in c.procs_index:
+    if r.procs_index.contains(proc_name):
+      let msg = "`component` macro cannot delcare duplicated proc: " & proc_name
+      raise newException(ValueError, msg)
+    r.procs_index.add(proc_name)
+
+proc addComponent(r: var Registry, name: string, c: Component) =
+  r.validateComponent(name, c)
+  r.components.add(name, c)
+
+proc parse_component(body: NimNode): Component =
+  result.field_index = @[]
+  result.procs_index = @[]
+  for node in body:
+    case node.kind:
+      of nnkVarSection:
+        result.fields = newFieldSeq(node)
+        for field in result.fields:
+          result.field_index.add(field.identifier.name)
+      of nnkMethodDef, nnkProcDef:
+        let new_proc = meta.newProc(node)
+        result.procs = result.procs & @[new_proc]
+        for procdef in result.procs:
+          result.procs_index.add(procdef.identifier.name)
+      else: discard
+
+macro component*(name: expr, body: stmt): stmt {.immediate.} =
+  let component = parse_component(body)
+  registry.addComponent($name, component)
+  parseStmt("discard")
+
+macro component_builtins(body: stmt): stmt {.immediate.} =
+  let builtin = parse_component(body)
+  registry.field_index = builtin.field_index
+  registry.procs_index = builtin.procs_index
+  registry.builtin = builtin
+
+proc bind_methods*(component: var Component, identifier: Ident): seq[NimNode] =
+  result = @[]
+  for procdef in component.procs.mitems:
+    let this_field = newField(newIdent("this"), identifier)
+    procdef.params.insert(this_field, 0)
+    result.add(procdef.render())
+
+macro bind_components*(type_name, component_names: expr): stmt {.immediate.} =
+  result = newStmtList()
+  let identifier = newIdent(type_name)
+  let components = newBracket(component_names)
+  var entity_type = newTypeDef(identifier, true, "object", "RootObj")
+  entity_type.fields = registry.builtin.fields
+  for component_name, component in registry.components:
+    if components.contains(newIdent(component_name)):
+      entity_type.fields = entity_type.fields & component.fields
+  # TODO why doesn't the following snippet work instead of the one above?
+  # for name in components:
+  #   echo "Registering $1 to $2" % [name.name, identifier.name]
+  #   let component = registry.components[name.name]
+  #   entity_type.fields = entity_type.fields & component.fields
+  let type_section: TypeDefSeq = @[entity_type]
+  result.add type_section.render
+  var builtin = registry.builtin
+  let builtin_methods = bind_methods(builtin, identifier)
+  for builtin_proc in builtin_methods:
+    result.add(builtin_proc)
+  echo "SIGSEV here"
+  for component in registry.components.mvalues():
+    for method_proc in bind_methods(component, identifier):
+      result.add(method_proc)
+
+component_builtins:
+  proc foo(msg: string) =
+    echo "FOO: $1" % msg
+
+component position:
+  var x*, y*: int
+
+component name:
+  var name*: string
+  proc render*(x, y: int) = echo "`$1` @ $2,$3" % [this.name, $x, $y]
+
+bind_components(Entity, [position, name])
+
+var e = new(Entity)
+e.name = ":)"
+e.render(e.x, e.y)
+e.foo("blah")
diff --git a/tests/vm/tconst_float_as_int.nim b/tests/vm/tconst_float_as_int.nim
new file mode 100644
index 000000000..ed84ec194
--- /dev/null
+++ b/tests/vm/tconst_float_as_int.nim
@@ -0,0 +1,3 @@
+
+# bug #4619
+const x: float = 0
diff --git a/tests/vm/tinheritance.nim b/tests/vm/tinheritance.nim
new file mode 100644
index 000000000..d465e22b9
--- /dev/null
+++ b/tests/vm/tinheritance.nim
@@ -0,0 +1,29 @@
+discard """
+  msg: '''Hello fred , managed by sally
+Hello sally , managed by bob'''
+"""
+# bug #3973
+
+type
+  EmployeeCode = enum
+    ecCode1,
+    ecCode2
+
+  Person* = object of RootObj
+    name* : string
+    last_name*: string
+
+  Employee* = object of Person
+    empl_code* : EmployeeCode
+    mgr_name* : string
+
+proc test() =
+  var
+    empl1 = Employee(name: "fred", last_name: "smith", mgr_name: "sally", empl_code: ecCode1)
+    empl2 = Employee(name: "sally", last_name: "jones", mgr_name: "bob", empl_code: ecCode2)
+
+  echo "Hello ", empl1.name, " , managed by ", empl1.mgr_name
+  echo "Hello ", empl2.name, " , managed by ", empl2.mgr_name
+
+static:
+  test()
diff --git a/tests/vm/tmitems.nim b/tests/vm/tmitems.nim
new file mode 100644
index 000000000..4ee225eed
--- /dev/null
+++ b/tests/vm/tmitems.nim
@@ -0,0 +1,31 @@
+discard """
+  msg: '''13'''
+  output: '''3
+3
+3'''
+"""
+# bug #3731
+var list {.compileTime.} = newSeq[int]()
+
+macro calc*(): stmt {.immediate.} =
+  list.add(1)
+  for c in list.mitems:
+    c = 13
+
+  for c in list:
+    echo c
+
+calc()
+
+# bug #3859
+import macros
+macro m: stmt =
+  var s = newseq[NimNode](3)
+  # var s: array[3,NimNode]                 # not working either
+  for i in 0..<s.len: s[i] = newLit(3)    # works
+  #for x in s.mitems: x = newLit(3)
+  result = newStmtList()
+  for i in s:
+    result.add newCall(bindsym"echo", i)
+
+m()
diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim
new file mode 100644
index 000000000..b7112b099
--- /dev/null
+++ b/tests/vm/tvmmisc.nim
@@ -0,0 +1,16 @@
+
+
+# bug #4462
+import macros
+
+proc foo(t: typedesc) {.compileTime.} =
+  echo getType(t).treeRepr
+
+static:
+  foo(int)
+
+# #4412
+proc default[T](t: typedesc[T]): T {.inline.} = discard
+
+static:
+  var x = default(type(0))
diff --git a/tests/vm/twrong_concat.nim b/tests/vm/twrong_concat.nim
new file mode 100644
index 000000000..538ea2527
--- /dev/null
+++ b/tests/vm/twrong_concat.nim
@@ -0,0 +1,28 @@
+discard """
+  output: '''success'''
+"""
+
+# bug #3804
+
+#import sequtils
+
+type AnObj = ref object
+  field: string
+
+#proc aBug(objs: seq[AnObj]) {.compileTime.} =
+#  discard objs.mapIt(it.field & " bug")
+
+proc sameBug(objs: seq[AnObj]) {.compileTime.} =
+  var strSeq = newSeq[string](objs.len)
+  strSeq[0] = objs[0].field & " bug"
+
+static:
+  var objs: seq[AnObj] = @[]
+  objs.add(AnObj(field: "hello"))
+
+  sameBug(objs)
+  # sameBug(objs)
+  echo objs[0].field
+  assert(objs[0].field == "hello") # fails, because (objs[0].field == "hello bug") - mutated!
+
+echo "success"