summary refs log tree commit diff stats
path: root/tests/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/stdlib')
-rw-r--r--tests/stdlib/concurrency/atomicSample.nim9
-rw-r--r--tests/stdlib/concurrency/tatomic_import.nim11
-rw-r--r--tests/stdlib/concurrency/tatomics.nim30
-rw-r--r--tests/stdlib/concurrency/tatomics_size.nim5
-rw-r--r--tests/stdlib/config.nims5
-rw-r--r--tests/stdlib/mgenast.nim57
-rw-r--r--tests/stdlib/mimportutils.nim38
-rw-r--r--tests/stdlib/mintsets.nim1
-rw-r--r--tests/stdlib/nre/misc.nim4
-rw-r--r--tests/stdlib/t10231.nim1
-rw-r--r--tests/stdlib/t14139.nim3
-rw-r--r--tests/stdlib/t15663.nim4
-rw-r--r--tests/stdlib/t19304.nim7
-rw-r--r--tests/stdlib/t20023.nim10
-rw-r--r--tests/stdlib/t21251.nim6
-rw-r--r--tests/stdlib/t21406.nim7
-rw-r--r--tests/stdlib/t21564.nim32
-rw-r--r--tests/stdlib/t7686.nim3
-rw-r--r--tests/stdlib/t8925.nim2
-rw-r--r--tests/stdlib/t9091.nim36
-rw-r--r--tests/stdlib/t9710.nim11
-rw-r--r--tests/stdlib/talgorithm.nim6
-rw-r--r--tests/stdlib/tarithmetics.nim50
-rw-r--r--tests/stdlib/tasynchttpserver.nim18
-rw-r--r--tests/stdlib/tasynchttpserver_transferencoding.nim58
-rw-r--r--tests/stdlib/tbase64.nim33
-rw-r--r--tests/stdlib/tbitops.nim6
-rw-r--r--tests/stdlib/tbitops_utils.nim19
-rw-r--r--tests/stdlib/tcasts.nim26
-rw-r--r--tests/stdlib/tcgi.nim5
-rw-r--r--tests/stdlib/tchannels.nim33
-rw-r--r--tests/stdlib/tchannels_pthread.nim322
-rw-r--r--tests/stdlib/tchannels_simple.nim67
-rw-r--r--tests/stdlib/tclosures.nim47
-rw-r--r--tests/stdlib/tcmdline.nim2
-rw-r--r--tests/stdlib/tcomplex.nim9
-rw-r--r--tests/stdlib/tcookies.nim2
-rw-r--r--tests/stdlib/tcritbits.nim2
-rw-r--r--tests/stdlib/tcstring.nim3
-rw-r--r--tests/stdlib/tcstrutils.nim3
-rw-r--r--tests/stdlib/tdb.nim0
-rw-r--r--tests/stdlib/tdb.nims1
-rw-r--r--tests/stdlib/tdb_mysql.nim0
-rw-r--r--tests/stdlib/tdecls.nim50
-rw-r--r--tests/stdlib/tdecode_helpers.nim2
-rw-r--r--tests/stdlib/tdeques.nim108
-rw-r--r--tests/stdlib/tdiff.nim2
-rw-r--r--tests/stdlib/tdistros_detect.nim16
-rw-r--r--tests/stdlib/tdochelpers.nim221
-rw-r--r--tests/stdlib/teditdistance.nim5
-rw-r--r--tests/stdlib/tencodings.nim107
-rw-r--r--tests/stdlib/tenumerate.nim5
-rw-r--r--tests/stdlib/tenumutils.nim12
-rw-r--r--tests/stdlib/tenvvars.nim162
-rw-r--r--tests/stdlib/texitprocs.nim1
-rw-r--r--tests/stdlib/tfdleak.nim7
-rw-r--r--tests/stdlib/tfdleak_multiple.nim1
-rw-r--r--tests/stdlib/tfenv.nim1
-rw-r--r--tests/stdlib/tfilesanddirs.nim36
-rw-r--r--tests/stdlib/tfrexp1.nim2
-rw-r--r--tests/stdlib/tgenast.nim274
-rw-r--r--tests/stdlib/tgetaddrinfo.nim2
-rw-r--r--tests/stdlib/tgetfileinfo.nim30
-rw-r--r--tests/stdlib/tgetprotobyname.nim13
-rw-r--r--tests/stdlib/tglobs.nim25
-rw-r--r--tests/stdlib/thashes.nim76
-rw-r--r--tests/stdlib/theapqueue.nim6
-rw-r--r--tests/stdlib/thighlite.nim45
-rw-r--r--tests/stdlib/thtmlparser.nim3
-rw-r--r--tests/stdlib/thttpclient.nim33
-rw-r--r--tests/stdlib/thttpclient_ssl.nim25
-rw-r--r--tests/stdlib/thttpclient_standalone.nim52
-rw-r--r--tests/stdlib/thttpcore.nim5
-rw-r--r--tests/stdlib/timportutils.nim151
-rw-r--r--tests/stdlib/tio.nim23
-rw-r--r--tests/stdlib/tisolation.nim50
-rw-r--r--tests/stdlib/tjsbigints.nim8
-rw-r--r--tests/stdlib/tjson.nim84
-rw-r--r--tests/stdlib/tjsonmacro.nim12
-rw-r--r--tests/stdlib/tjsonutils.nim157
-rw-r--r--tests/stdlib/tlists.nim39
-rw-r--r--tests/stdlib/tlocks.nim7
-rw-r--r--tests/stdlib/tlwip.nim2
-rw-r--r--tests/stdlib/tmacros.nim337
-rw-r--r--tests/stdlib/tmarshal.nim97
-rw-r--r--tests/stdlib/tmarshalsegfault.nim54
-rw-r--r--tests/stdlib/tmath.nim114
-rw-r--r--tests/stdlib/tmd5.nim7
-rw-r--r--tests/stdlib/tmemfiles1.nim2
-rw-r--r--tests/stdlib/tmemfiles2.nim8
-rw-r--r--tests/stdlib/tmemlinesBuf.nim10
-rw-r--r--tests/stdlib/tmemmapstreams.nim2
-rw-r--r--tests/stdlib/tmemory.nim15
-rw-r--r--tests/stdlib/tmersenne.nim2
-rw-r--r--tests/stdlib/tmget.nim17
-rw-r--r--tests/stdlib/tmimetypes.nim15
-rw-r--r--tests/stdlib/tmisc_issues.nim39
-rw-r--r--tests/stdlib/tmitems.nim3
-rw-r--r--tests/stdlib/tmonotimes.nim2
-rw-r--r--tests/stdlib/tnativesockets.nim45
-rw-r--r--tests/stdlib/tnet.nim39
-rw-r--r--tests/stdlib/tnet_ll.nim95
-rw-r--r--tests/stdlib/tnetbind.nim1
-rw-r--r--tests/stdlib/tnetconnect.nim10
-rw-r--r--tests/stdlib/tnetdial.nim4
-rw-r--r--tests/stdlib/tnre.nim1
-rw-r--r--tests/stdlib/tntpath.nim50
-rw-r--r--tests/stdlib/tobjectdollar.nim14
-rw-r--r--tests/stdlib/toids.nim11
-rw-r--r--tests/stdlib/topenssl.nim13
-rw-r--r--tests/stdlib/toptions.nim12
-rw-r--r--tests/stdlib/tos.nim311
-rw-r--r--tests/stdlib/tos_unc.nim2
-rw-r--r--tests/stdlib/tosenv.nim163
-rw-r--r--tests/stdlib/toserrors.nim9
-rw-r--r--tests/stdlib/tosproc.nim57
-rw-r--r--tests/stdlib/tosprocterminate.nim3
-rw-r--r--tests/stdlib/tpackedsets.nim6
-rw-r--r--tests/stdlib/tparsecfg.nim25
-rw-r--r--tests/stdlib/tparsecsv.nim5
-rw-r--r--tests/stdlib/tparseipv6.nim95
-rw-r--r--tests/stdlib/tparsesql.nim120
-rw-r--r--tests/stdlib/tparseuints.nim4
-rw-r--r--tests/stdlib/tparseutils.nim135
-rw-r--r--tests/stdlib/tparsopt.nim2
-rw-r--r--tests/stdlib/tpathnorm.nim36
-rw-r--r--tests/stdlib/tpaths.nim238
-rw-r--r--tests/stdlib/tpegs.nim209
-rw-r--r--tests/stdlib/tposix.nim71
-rw-r--r--tests/stdlib/tprelude.nim2
-rw-r--r--tests/stdlib/tpunycode.nim5
-rw-r--r--tests/stdlib/tquit.nim15
-rw-r--r--tests/stdlib/trandom.nim166
-rw-r--r--tests/stdlib/trat_float.nim9
-rw-r--r--tests/stdlib/trat_init.nim14
-rw-r--r--tests/stdlib/trationals.nim14
-rw-r--r--tests/stdlib/tre.nim20
-rw-r--r--tests/stdlib/treadln.nim23
-rw-r--r--tests/stdlib/tregex.nim3
-rw-r--r--tests/stdlib/tregistry.nim16
-rw-r--r--tests/stdlib/trepr.nim203
-rw-r--r--tests/stdlib/tropes.nim2
-rw-r--r--tests/stdlib/trst.nim1924
-rw-r--r--tests/stdlib/trstgen.nim612
-rw-r--r--tests/stdlib/tsequtils.nim180
-rw-r--r--tests/stdlib/tsetutils.nim2
-rw-r--r--tests/stdlib/tsha1.nim13
-rw-r--r--tests/stdlib/tsharedlist.nim54
-rw-r--r--tests/stdlib/tsharedtable.nim3
-rw-r--r--tests/stdlib/tsince.nim8
-rw-r--r--tests/stdlib/tsocketstreams.nim1
-rw-r--r--tests/stdlib/tsortcall.nim2
-rw-r--r--tests/stdlib/tsqlitebindatas.nim50
-rw-r--r--tests/stdlib/tsqlparser.nim1
-rw-r--r--tests/stdlib/tssl.nim14
-rw-r--r--tests/stdlib/tstackframes.nim2
-rw-r--r--tests/stdlib/tstaticos.nim8
-rw-r--r--tests/stdlib/tstats.nim107
-rw-r--r--tests/stdlib/tstdlib_issues.nim5
-rw-r--r--tests/stdlib/tstdlib_various.nim45
-rw-r--r--tests/stdlib/tstrbasics.nim6
-rw-r--r--tests/stdlib/tstreams.nim35
-rw-r--r--tests/stdlib/tstrformat.nim109
-rw-r--r--tests/stdlib/tstrformatlineinfo.nim8
-rw-r--r--tests/stdlib/tstrimpl.nim12
-rw-r--r--tests/stdlib/tstring.nim2
-rw-r--r--tests/stdlib/tstrmiscs.nim7
-rw-r--r--tests/stdlib/tstrscans.nim64
-rw-r--r--tests/stdlib/tstrset.nim16
-rw-r--r--tests/stdlib/tstrtabs.nim3
-rw-r--r--tests/stdlib/tstrtabs.nims2
-rw-r--r--tests/stdlib/tstrtabs2.nim32
-rw-r--r--tests/stdlib/tstrutils.nim277
-rw-r--r--tests/stdlib/tstrutils2.nim32
-rw-r--r--tests/stdlib/tsugar.nim119
-rw-r--r--tests/stdlib/tsums.nim5
-rw-r--r--tests/stdlib/tsysrand.nim4
-rw-r--r--tests/stdlib/tsystem.nim200
-rw-r--r--tests/stdlib/ttables.nim5
-rw-r--r--tests/stdlib/ttasks.nim561
-rw-r--r--tests/stdlib/ttempfiles.nim51
-rw-r--r--tests/stdlib/tterminal.nim1
-rw-r--r--tests/stdlib/tterminal_12759.nim1
-rw-r--r--tests/stdlib/ttestutils.nim40
-rw-r--r--tests/stdlib/tthreadpool.nim4
-rw-r--r--tests/stdlib/ttimes.nim146
-rw-r--r--tests/stdlib/ttypeinfo.nim26
-rw-r--r--tests/stdlib/ttypeinfo.nims1
-rw-r--r--tests/stdlib/ttypetraits.nim94
-rw-r--r--tests/stdlib/tunicode.nim15
-rw-r--r--tests/stdlib/tunidecode.nim1
-rw-r--r--tests/stdlib/tunittest.nim4
-rw-r--r--tests/stdlib/tunittestpass.nim1
-rw-r--r--tests/stdlib/tunittesttemplate.nim4
-rw-r--r--tests/stdlib/tunixsocket.nim35
-rw-r--r--tests/stdlib/turi.nim36
-rw-r--r--tests/stdlib/tuserlocks.nim12
-rw-r--r--tests/stdlib/tvarargs.nim4
-rw-r--r--tests/stdlib/tvarints.nim87
-rw-r--r--tests/stdlib/tvmutils.nim31
-rw-r--r--tests/stdlib/tvolatile.nim15
-rw-r--r--tests/stdlib/twchartoutf8.nim7
-rw-r--r--tests/stdlib/twith.nim21
-rw-r--r--tests/stdlib/twordwrap.nim5
-rw-r--r--tests/stdlib/twrapnils.nim287
-rw-r--r--tests/stdlib/twrongstattype.nim14
-rw-r--r--tests/stdlib/txmltree.nim37
-rw-r--r--tests/stdlib/tyield.nim258
-rw-r--r--tests/stdlib/unixsockettest.nim26
-rw-r--r--tests/stdlib/uselocks.nim5
210 files changed, 10025 insertions, 1630 deletions
diff --git a/tests/stdlib/concurrency/atomicSample.nim b/tests/stdlib/concurrency/atomicSample.nim
new file mode 100644
index 000000000..d56d867df
--- /dev/null
+++ b/tests/stdlib/concurrency/atomicSample.nim
@@ -0,0 +1,9 @@
+import atomics
+
+type
+  AtomicWithGeneric*[T] = object
+    value: Atomic[T]
+
+proc initAtomicWithGeneric*[T](value: T): AtomicWithGeneric[T] =
+  result.value.store(value)
+
diff --git a/tests/stdlib/concurrency/tatomic_import.nim b/tests/stdlib/concurrency/tatomic_import.nim
new file mode 100644
index 000000000..e8faaae20
--- /dev/null
+++ b/tests/stdlib/concurrency/tatomic_import.nim
@@ -0,0 +1,11 @@
+import atomicSample
+
+block crossFileObjectContainingAGenericWithAComplexObject:
+  discard initAtomicWithGeneric[string]("foo")
+
+block crossFileObjectContainingAGenericWithAnInteger:
+  discard initAtomicWithGeneric[int](1)
+  discard initAtomicWithGeneric[int8](1)
+  discard initAtomicWithGeneric[int16](1)
+  discard initAtomicWithGeneric[int32](1)
+  discard initAtomicWithGeneric[int64](1)
diff --git a/tests/stdlib/concurrency/tatomics.nim b/tests/stdlib/concurrency/tatomics.nim
index 260d00990..08f2e7d3e 100644
--- a/tests/stdlib/concurrency/tatomics.nim
+++ b/tests/stdlib/concurrency/tatomics.nim
@@ -1,6 +1,14 @@
+discard """
+  # test C with -d:nimUseCppAtomics as well to check nothing breaks
+  matrix: "--mm:refc; --mm:orc; --mm:refc -d:nimUseCppAtomics; --mm:orc -d:nimUseCppAtomics"
+  targets: "c cpp"
+"""
+
 # test atomic operations
 
-import atomics, bitops
+import std/[atomics, bitops]
+import std/assertions
+
 
 type
   Object = object
@@ -607,3 +615,23 @@ block clear:
   doAssert not location.testAndSet
   location.clear(moRelease)
   doAssert not location.testAndSet
+
+block: # bug #18844
+  when not defined(cpp): # cpp pending pr #18836
+    type
+      Deprivation = object of RootObj
+        memes: Atomic[int]
+      Zoomer = object
+        dopamine: Deprivation
+
+    block:
+      var x = Deprivation()
+      var y = Zoomer()
+      doAssert x.memes.load == 0
+      doAssert y.dopamine.memes.load == 0
+
+    block:
+      var x: Deprivation
+      var y: Zoomer
+      doAssert x.memes.load == 0
+      doAssert y.dopamine.memes.load == 0
diff --git a/tests/stdlib/concurrency/tatomics_size.nim b/tests/stdlib/concurrency/tatomics_size.nim
index 49387c0c1..f64adb308 100644
--- a/tests/stdlib/concurrency/tatomics_size.nim
+++ b/tests/stdlib/concurrency/tatomics_size.nim
@@ -1,7 +1,10 @@
 discard """
+  # test C with -d:nimUseCppAtomics as well to check nothing breaks
+  matrix: "--mm:refc; --mm:orc; --mm:refc -d:nimUseCppAtomics; --mm:orc -d:nimUseCppAtomics"
   targets: "c cpp"
 """
 import std/atomics
+import std/assertions
 
 block testSize: # issue 12726
   type
@@ -15,4 +18,4 @@ block testSize: # issue 12726
       f: AtomicFlag
   static:
     doAssert sizeof(Node) == sizeof(pointer)
-    doAssert sizeof(MyChannel) == sizeof(pointer) * 2
\ No newline at end of file
+    doAssert sizeof(MyChannel) == sizeof(pointer) * 2
diff --git a/tests/stdlib/config.nims b/tests/stdlib/config.nims
new file mode 100644
index 000000000..dffae2812
--- /dev/null
+++ b/tests/stdlib/config.nims
@@ -0,0 +1,5 @@
+switch("styleCheck", "usages")
+switch("styleCheck", "error")
+switch("define", "nimPreviewSlimSystem")
+switch("define", "nimPreviewCstringConversion")
+switch("define", "nimPreviewProcConversion")
diff --git a/tests/stdlib/mgenast.nim b/tests/stdlib/mgenast.nim
new file mode 100644
index 000000000..b0904847e
--- /dev/null
+++ b/tests/stdlib/mgenast.nim
@@ -0,0 +1,57 @@
+import std/genasts
+import std/macros
+
+# Using a enum instead of, say, int, to make apparent potential bugs related to
+# forgetting converting to NimNode via newLit, see bug #9607
+
+type Foo* = enum kfoo0, kfoo1, kfoo2, kfoo3, kfoo4
+
+proc myLocalPriv(): auto = kfoo1
+proc myLocalPriv2(): auto = kfoo1
+macro bindme2*(): untyped =
+  genAst: myLocalPriv()
+macro bindme3*(): untyped =
+  ## myLocalPriv must be captured explicitly
+  genAstOpt({kDirtyTemplate}, myLocalPriv): myLocalPriv()
+
+macro bindme4*(): untyped =
+  ## calling this won't compile because `myLocalPriv` isn't captured
+  genAstOpt({kDirtyTemplate}): myLocalPriv()
+
+macro bindme5UseExpose*(): untyped =
+  genAst: myLocalPriv2()
+
+macro bindme5UseExposeFalse*(): untyped =
+  genAstOpt({kDirtyTemplate}): myLocalPriv2()
+
+# example from bug #7889
+from std/streams import newStringStream, readData, writeData
+
+macro bindme6UseExpose*(): untyped =
+  genAst:
+    var tst = "sometext"
+    var ss = newStringStream("anothertext")
+    when defined(gcArc) or defined(gcOrc):
+      prepareMutation(tst)
+    writeData(ss, tst[0].addr, 2)
+    discard readData(ss, tst[0].addr, 2)
+
+macro bindme6UseExposeFalse*(): untyped =
+  ## with `kDirtyTemplate`, requires passing all referenced symbols
+  ## which can be tedious
+  genAstOpt({kDirtyTemplate}, newStringStream, writeData, readData):
+    var tst = "sometext"
+    var ss = newStringStream("anothertext")
+    when defined(gcArc) or defined(gcOrc):
+      prepareMutation(tst)
+    writeData(ss, tst[0].addr, 2)
+    discard readData(ss, tst[0].addr, 2)
+
+
+proc locafun1(): auto = "in locafun1"
+proc locafun2(): auto = "in locafun2"
+# locafun3 in caller scope only
+macro mixinExample*(): untyped =
+  genAst:
+    mixin locafun1
+    (locafun1(), locafun2(), locafun3())
diff --git a/tests/stdlib/mimportutils.nim b/tests/stdlib/mimportutils.nim
new file mode 100644
index 000000000..678d9ec02
--- /dev/null
+++ b/tests/stdlib/mimportutils.nim
@@ -0,0 +1,38 @@
+type
+  A* = object
+    a0*: int
+    ha1: float
+  B = object
+    b0*: int
+    hb1: float
+  C* = ref object
+    c0: int
+    hc1: float
+  D* = ptr object
+    d0: int
+    hd1: float
+  PA* = ref A
+  PtA* = ptr A
+  E*[T] = object
+    he1: int
+  FSub[T1, T2] = object
+    h3: T1
+    h4: T2
+  F*[T1, T2] = ref FSub[T1, T2]
+  G*[T] = ref E[T]
+  H3*[T] = object
+    h5: T
+  H2*[T] = H3[T]
+  H1*[T] = ref H2[T]
+  H*[T] = H1[T]
+
+  Pity[T] = object
+    a: T
+  PityRef*[T] = ref Pity[T]
+  Hope*[T] = ref object
+    a: T
+
+type BAalias* = typeof(B.default)
+  # typeof is not a transparent abstraction, creates a `tyAlias`
+
+proc initB*(): B = B()
diff --git a/tests/stdlib/mintsets.nim b/tests/stdlib/mintsets.nim
index b4d9ed516..98786e9ba 100644
--- a/tests/stdlib/mintsets.nim
+++ b/tests/stdlib/mintsets.nim
@@ -1,4 +1,5 @@
 import std/intsets
+import std/assertions
 
 proc test1*[]() =
   let a = initIntSet()
diff --git a/tests/stdlib/nre/misc.nim b/tests/stdlib/nre/misc.nim
index dbb0ecdf9..b7df08ee9 100644
--- a/tests/stdlib/nre/misc.nim
+++ b/tests/stdlib/nre/misc.nim
@@ -6,8 +6,8 @@ block: # Misc tests
     check("перевірка".replace(re"(*U)\w", "") == "")
 
   block: # empty or non-empty match
-    check("abc".findall(re"|.").join(":") == ":a::b::c:")
-    check("abc".findall(re".|").join(":") == "a:b:c:")
+    check("abc".findAll(re"|.").join(":") == ":a::b::c:")
+    check("abc".findAll(re".|").join(":") == "a:b:c:")
 
     check("abc".replace(re"|.", "x") == "xxxxxxx")
     check("abc".replace(re".|", "x") == "xxxx")
diff --git a/tests/stdlib/t10231.nim b/tests/stdlib/t10231.nim
index 3b2b684f3..3d09721aa 100644
--- a/tests/stdlib/t10231.nim
+++ b/tests/stdlib/t10231.nim
@@ -5,6 +5,7 @@ discard """
 """
 
 import os
+import std/assertions
 
 # consider moving this inside tosproc (taking care that it's for cpp mode)
 
diff --git a/tests/stdlib/t14139.nim b/tests/stdlib/t14139.nim
index 07d2ff137..866bdb45f 100644
--- a/tests/stdlib/t14139.nim
+++ b/tests/stdlib/t14139.nim
@@ -1,4 +1,5 @@
-import heapqueue
+import std/heapqueue
+import std/assertions
 
 var test_queue : HeapQueue[int]
 
diff --git a/tests/stdlib/t15663.nim b/tests/stdlib/t15663.nim
index 1ad5677fd..8e8bfd9a8 100644
--- a/tests/stdlib/t15663.nim
+++ b/tests/stdlib/t15663.nim
@@ -3,5 +3,7 @@ discard """
   output: "Test"
 """
 
+import std/widestrs
+
 let ws = newWideCString("Test")
-echo ws
\ No newline at end of file
+echo ws
diff --git a/tests/stdlib/t19304.nim b/tests/stdlib/t19304.nim
new file mode 100644
index 000000000..5e8795ac5
--- /dev/null
+++ b/tests/stdlib/t19304.nim
@@ -0,0 +1,7 @@
+import times
+
+type DjangoDateTime* = distinct DateTime
+
+# proc toTime*(x: DjangoDateTime): Time  {.borrow.} # <-- works
+proc format*(x: DjangoDateTime, f: TimeFormat,
+    loc: DateTimeLocale = DefaultLocale): string {.borrow.}
diff --git a/tests/stdlib/t20023.nim b/tests/stdlib/t20023.nim
new file mode 100644
index 000000000..8f12f8993
--- /dev/null
+++ b/tests/stdlib/t20023.nim
@@ -0,0 +1,10 @@
+import std/[tables, hashes, assertions]
+
+
+let t = ()
+var a = toTable({t:t})
+del(a,t)
+let b = default(typeof(a))
+
+doAssert a==b , "tables are not equal"
+doAssert hash(a) == hash(b), "table hashes are not equal"
diff --git a/tests/stdlib/t21251.nim b/tests/stdlib/t21251.nim
new file mode 100644
index 000000000..4402e9b7e
--- /dev/null
+++ b/tests/stdlib/t21251.nim
@@ -0,0 +1,6 @@
+import std / [tables, sets, sharedtables]
+
+var shared: SharedTable[int, int]
+shared.init
+
+shared[1] = 1
diff --git a/tests/stdlib/t21406.nim b/tests/stdlib/t21406.nim
new file mode 100644
index 000000000..86bf7b0c7
--- /dev/null
+++ b/tests/stdlib/t21406.nim
@@ -0,0 +1,7 @@
+import std/[times, strformat]
+import std/assertions
+
+let aTime = getTime()
+doAssert fmt"{aTime}" == $aTime
+let aNow = now()
+doAssert fmt"{aNow}" == $aNow
diff --git a/tests/stdlib/t21564.nim b/tests/stdlib/t21564.nim
new file mode 100644
index 000000000..0a5777d12
--- /dev/null
+++ b/tests/stdlib/t21564.nim
@@ -0,0 +1,32 @@
+discard """
+targets: "c js"
+"""
+
+import bitops
+import std/assertions
+
+proc main() =
+  block: # bug #21564
+    # tesk `bitops.bitsliced` patch
+    doAssert(0x17.bitsliced(4..7) == 0x01)
+    doAssert(0x17.bitsliced(0..3) == 0x07)
+
+  block:
+    # test in-place `bitops.bitslice`
+    var t = 0x12F4
+    t.bitslice(4..7)
+
+    doAssert(t == 0xF)
+
+  block:
+    # test `bitops.toMask` patch via bitops.masked
+    doAssert(0x12FFFF34.masked(8..23) == 0x00FFFF00)
+
+  block: # bug #22687
+    var a: uint8 = 0b1111_1111
+    doAssert a.bitsliced(4..7).int == 15
+
+main()
+
+static:
+  main()
diff --git a/tests/stdlib/t7686.nim b/tests/stdlib/t7686.nim
index c174dfb51..9902cfcb5 100644
--- a/tests/stdlib/t7686.nim
+++ b/tests/stdlib/t7686.nim
@@ -1,4 +1,5 @@
-import strutils
+import std/strutils
+import std/assertions
 
 type
   MyEnum = enum
diff --git a/tests/stdlib/t8925.nim b/tests/stdlib/t8925.nim
index dbf55fd88..c55e93e73 100644
--- a/tests/stdlib/t8925.nim
+++ b/tests/stdlib/t8925.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "type mismatch between pattern '$i' (position: 1) and HourRange var 'hour'"
+  errormsg: "type mismatch between pattern '$$i' (position: 1) and HourRange var 'hour'"
   file: "strscans.nim"
 """
 
diff --git a/tests/stdlib/t9091.nim b/tests/stdlib/t9091.nim
deleted file mode 100644
index 8419479a7..000000000
--- a/tests/stdlib/t9091.nim
+++ /dev/null
@@ -1,36 +0,0 @@
-discard """
-  targets:  "c"
-  output:   "test AObj"
-  action:   "compile"
-  exitcode: 0
-  timeout:  60.0
-"""
-import streams
-
-block:
-  type Mine = ref object
-    a: int
-
-  proc write(io: Stream, t: Mine) =
-    io.write("sure")
-
-  let str = newStringStream()
-  let mi = new Mine
-
-  str.write(mi)
-
-block:
-  type
-    AObj = object
-      x: int
-
-  proc foo(a: int): string = ""
-
-  proc test(args: varargs[string, foo]) =
-    echo "varargs"
-
-  proc test(a: AObj) =
-    echo "test AObj"
-
-  let x = AObj()
-  test(x)
diff --git a/tests/stdlib/t9710.nim b/tests/stdlib/t9710.nim
deleted file mode 100644
index f3ed860df..000000000
--- a/tests/stdlib/t9710.nim
+++ /dev/null
@@ -1,11 +0,0 @@
-discard """
-  cmd:      "nim c -r --debugger:native --panics:on $options $file"
-  targets:  "c"
-  nimout:   ""
-  action:   "run"
-  exitcode: 0
-  timeout:  60.0
-"""
-
-for i in 1 || 200:
-  discard i
diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim
index 5bb5a6bdf..e2024df0c 100644
--- a/tests/stdlib/talgorithm.nim
+++ b/tests/stdlib/talgorithm.nim
@@ -1,11 +1,13 @@
 discard """
   targets: "c js"
+  matrix: "--mm:refc; --mm:orc"
   output:'''@["3", "2", "1"]
 '''
 """
 #12928,10456
 
 import std/[sequtils, algorithm, json, sugar]
+import std/assertions
 
 proc test() = 
   try: 
@@ -101,10 +103,10 @@ block:
     doAssert binarySearch(noData, 7) == -1
     let oneData = @[1]
     doAssert binarySearch(oneData, 1) == 0
-    doAssert binarySearch(onedata, 7) == -1
+    doAssert binarySearch(oneData, 7) == -1
     let someData = @[1, 3, 4, 7]
     doAssert binarySearch(someData, 1) == 0
-    doAssert binarySearch(somedata, 7) == 3
+    doAssert binarySearch(someData, 7) == 3
     doAssert binarySearch(someData, -1) == -1
     doAssert binarySearch(someData, 5) == -1
     doAssert binarySearch(someData, 13) == -1
diff --git a/tests/stdlib/tarithmetics.nim b/tests/stdlib/tarithmetics.nim
new file mode 100644
index 000000000..0a6dd1fcf
--- /dev/null
+++ b/tests/stdlib/tarithmetics.nim
@@ -0,0 +1,50 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+import std/assertions
+# TODO: in future work move existing arithmetic tests (tests/arithm/*) into this file
+# FYI https://github.com/nim-lang/Nim/pull/17767
+
+template main =
+  # put all arithmetic tests
+
+  block tshr:
+    block: # Signed types
+      let
+        a1 = -3
+        a2 = -2
+        b1 = -4'i8
+        b2 = 1'i8
+        c1 = -5'i16
+        c2 = 1'i16
+        d1 = -7i32
+        d2 = 1'i32
+        e1 = -9'i64
+        e2 = 1'i64
+      doAssert a1 shr a2 == -1
+      doAssert b1 shr b2 == -2
+      doAssert c1 shr c2 == -3
+      doAssert d1 shr d2 == -4
+      doAssert e1 shr e2 == -5
+
+    block: # Unsigned types
+      let
+        a1 = 3'u
+        a2 = 2'u
+        b1 = 2'u8
+        b2 = 1'u8
+        c1 = 5'u16
+        c2 = 1'u16
+        d1 = 6'u32
+        d2 = 1'u32
+        e1 = 8'u64
+        e2 = 1'u64
+      doAssert a1 shr a2 == 0
+      doAssert b1 shr b2 == 1
+      doAssert c1 shr c2 == 2
+      doAssert d1 shr d2 == 3
+      doAssert e1 shr e2 == 4
+
+static: main()
+main()
diff --git a/tests/stdlib/tasynchttpserver.nim b/tests/stdlib/tasynchttpserver.nim
index 77ad7a071..5a7e2da40 100644
--- a/tests/stdlib/tasynchttpserver.nim
+++ b/tests/stdlib/tasynchttpserver.nim
@@ -7,6 +7,7 @@ discard """
 
 import strutils
 from net import TimeoutError
+import std/assertions
 
 import httpclient, asynchttpserver, asyncdispatch, asyncfutures
 
@@ -39,7 +40,7 @@ proc test200() {.async.} =
     return clientResponse
 
   proc test(response: AsyncResponse, body: string) {.async.} =
-    doAssert(response.status == Http200)
+    doAssert(response.status == $Http200)
     doAssert(body == "Hello World, 200")
     doAssert(response.headers.hasKey("Content-Length"))
     doAssert(response.headers["Content-Length"] == "16")
@@ -60,7 +61,7 @@ proc test404() {.async.} =
     return clientResponse
 
   proc test(response: AsyncResponse, body: string) {.async.} =
-    doAssert(response.status == Http404)
+    doAssert(response.status == $Http404)
     doAssert(body == "Hello World, 404")
     doAssert(response.headers.hasKey("Content-Length"))
     doAssert(response.headers["Content-Length"] == "16")
@@ -81,7 +82,7 @@ proc testCustomEmptyHeaders() {.async.} =
     return clientResponse
 
   proc test(response: AsyncResponse, body: string) {.async.} =
-    doAssert(response.status == Http200)
+    doAssert(response.status == $Http200)
     doAssert(body == "Hello World, 200")
     doAssert(response.headers.hasKey("Content-Length"))
     doAssert(response.headers["Content-Length"] == "16")
@@ -104,16 +105,17 @@ proc testCustomContentLength() {.async.} =
     return clientResponse
 
   proc test(response: AsyncResponse, body: string) {.async.} =
-    doAssert(response.status == Http200)
+    doAssert(response.status == $Http200)
     doAssert(body == "")
     doAssert(response.headers.hasKey("Content-Length"))
     doAssert(response.headers["Content-Length"] == "0")
+    doAssert contentLength(response) == 0 # bug #22778
 
   runTest(handler, request, test)
 
-waitfor(test200())
-waitfor(test404())
-waitfor(testCustomEmptyHeaders())
-waitfor(testCustomContentLength())
+waitFor(test200())
+waitFor(test404())
+waitFor(testCustomEmptyHeaders())
+waitFor(testCustomContentLength())
 
 echo "OK"
diff --git a/tests/stdlib/tasynchttpserver_transferencoding.nim b/tests/stdlib/tasynchttpserver_transferencoding.nim
index 34f3cef11..886ba0f33 100644
--- a/tests/stdlib/tasynchttpserver_transferencoding.nim
+++ b/tests/stdlib/tasynchttpserver_transferencoding.nim
@@ -1,8 +1,14 @@
+discard """
+  matrix: "--mm:arc; --mm:arc -d:danger; --mm:refc"
+  disabled: "freebsd"
+"""
+
 import httpclient, asynchttpserver, asyncdispatch, asyncfutures
 import net
 
 import std/asyncnet
 import std/nativesockets
+import std/assertions
 
 const postBegin = """
 POST / HTTP/1.1
@@ -10,34 +16,38 @@ Transfer-Encoding:chunked
 
 """
 
-template genTest(input, expected) =
-  var sanity = false
-  proc handler(request: Request) {.async.} =
-      doAssert(request.body == expected)
-      doAssert(request.headers.hasKey("Transfer-Encoding"))
-      doAssert(not request.headers.hasKey("Content-Length"))
-      sanity = true
-      await request.respond(Http200, "Good")
+template genTest(input, expected: string) =
+  proc handler(request: Request, future: Future[bool]) {.async, gcsafe.} =
+    doAssert(request.body == expected)
+    doAssert(request.headers.hasKey("Transfer-Encoding"))
+    doAssert(not request.headers.hasKey("Content-Length"))
+    future.complete(true)
+    await request.respond(Http200, "Good")
+
+  proc sendData(data: string, port: Port) {.async.} =
+    var socket = newSocket()
+    defer: socket.close()
+
+    socket.connect("127.0.0.1", port)
+    socket.send(data)
 
-  proc runSleepLoop(server: AsyncHttpServer) {.async.} = 
+  proc runTest(): Future[bool] {.async.} =
+    var handlerFuture = newFuture[bool]("runTest")
+    let data = postBegin & input
+    let server = newAsyncHttpServer()
     server.listen(Port(0))
-    proc wrapper() = 
-      waitFor server.acceptRequest(handler)
-    asyncdispatch.callSoon wrapper
 
-  let server = newAsyncHttpServer()
-  waitFor runSleepLoop(server)
-  let port = getLocalAddr(server.getSocket.getFd, AF_INET)[1]
-  let data = postBegin & input
-  var socket = newSocket()
-  socket.connect("127.0.0.1", port)
-  socket.send(data)
-  waitFor sleepAsync(10)
-  socket.close()
-  server.close()
+    proc wrapper(request: Request): Future[void] {.gcsafe, closure.} =
+      handler(request, handlerFuture)
+    
+    asyncCheck sendData(data, server.getPort)
+    asyncCheck server.acceptRequest(wrapper)
+    doAssert await handlerFuture
+    
+    server.close()
+    return true
 
-  # Verify we ran the handler and its asserts
-  doAssert(sanity)
+  doAssert waitFor runTest()
 
 block:
   const expected = "hello=world"
diff --git a/tests/stdlib/tbase64.nim b/tests/stdlib/tbase64.nim
index 19b126437..c3bfb818e 100644
--- a/tests/stdlib/tbase64.nim
+++ b/tests/stdlib/tbase64.nim
@@ -1,14 +1,12 @@
 discard """
-  output: '''YQ=='''
-  nimout: '''YQ=='''
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c js"
 """
-import base64
+import std/assertions
+import std/base64
 
-import base64
-static: echo encode("a")
-echo encode("a")
-
-proc main() =
+template main() =
+  doAssert encode("a") == "YQ=="
   doAssert encode("Hello World") == "SGVsbG8gV29ybGQ="
   doAssert encode("leasure.") == "bGVhc3VyZS4="
   doAssert encode("easure.") == "ZWFzdXJlLg=="
@@ -20,6 +18,8 @@ proc main() =
   doAssert encode("") == ""
   doAssert decode("") == ""
 
+  doAssert decode(" ") == ""
+
   const testInputExpandsTo76 = "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
   const testInputExpands = "++++++++++++++++++++++++++++++"
   const longText = """Man is distinguished, not only by his reason, but by this
@@ -30,19 +30,15 @@ proc main() =
   const tests = ["", "abc", "xyz", "man", "leasure.", "sure.", "easure.",
                  "asure.", longText, testInputExpandsTo76, testInputExpands]
 
-  doAssert encodeMIME("foobarbaz", lineLen=4) == "Zm9v\r\nYmFy\r\nYmF6"
+  doAssert encodeMime("foobarbaz", lineLen=4) == "Zm9v\r\nYmFy\r\nYmF6"
   doAssert decode("Zm9v\r\nYmFy\r\nYmF6") == "foobarbaz"
 
   for t in items(tests):
     doAssert decode(encode(t)) == t
-    doAssert decode(encodeMIME(t, lineLen=40)) == t
-    doAssert decode(encodeMIME(t, lineLen=76)) == t
+    doAssert decode(encodeMime(t, lineLen=40)) == t
+    doAssert decode(encodeMime(t, lineLen=76)) == t
 
-  const invalid = "SGVsbG\x008gV29ybGQ="
-  try:
-    doAssert decode(invalid) == "will throw error"
-  except ValueError:
-    discard
+  doAssertRaises(ValueError): discard decode("SGVsbG\x008gV29ybGQ=")
 
   block base64urlSafe:
     doAssert encode("c\xf7>", safe = true) == "Y_c-"
@@ -59,4 +55,9 @@ proc main() =
     doAssert encode("", safe = true) == ""
     doAssert encode("the quick brown dog jumps over the lazy fox", safe = true) == "dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA=="
 
+func mainNoSideEffects() = main()
+
+static: main()
 main()
+static: mainNoSideEffects()
+mainNoSideEffects()
diff --git a/tests/stdlib/tbitops.nim b/tests/stdlib/tbitops.nim
index 6b5e0aeb9..3ecab2c64 100644
--- a/tests/stdlib/tbitops.nim
+++ b/tests/stdlib/tbitops.nim
@@ -1,10 +1,12 @@
 discard """
   nimout: "OK"
+  matrix: "--mm:refc; --mm:orc"
   output: '''
 OK
 '''
 """
 import bitops
+import std/assertions
 
 proc main() =
   const U8 = 0b0011_0010'u8
@@ -263,8 +265,8 @@ proc main() =
     doAssert v == 0b1000_0010
     v.flipBit(1)
     doAssert v == 0b1000_0000
-    doAssert v.testbit(7)
-    doAssert not v.testbit(6)
+    doAssert v.testBit(7)
+    doAssert not v.testBit(6)
   block:
     # multi bit operations
     var v: uint8
diff --git a/tests/stdlib/tbitops_utils.nim b/tests/stdlib/tbitops_utils.nim
new file mode 100644
index 000000000..e3f96fecc
--- /dev/null
+++ b/tests/stdlib/tbitops_utils.nim
@@ -0,0 +1,19 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/private/bitops_utils
+import std/assertions
+
+template chk(a, b) =
+  let a2 = castToUnsigned(a)
+  doAssert a2 == b
+  doAssert type(a2) is type(b)
+  doAssert type(b) is type(a2)
+
+chk 1'i8, 1'u8
+chk -1'i8, 255'u8
+chk 1'u8, 1'u8
+chk 1'u, 1'u
+chk -1, cast[uint](-1)
+chk -1'i64, cast[uint64](-1)
diff --git a/tests/stdlib/tcasts.nim b/tests/stdlib/tcasts.nim
new file mode 100644
index 000000000..e01c7e940
--- /dev/null
+++ b/tests/stdlib/tcasts.nim
@@ -0,0 +1,26 @@
+import std/[strutils]
+import std/[assertions, objectdollar]
+
+# bug #19101
+type
+  Small = object
+    a: int
+
+  Big = object
+    a, b, c, d: int
+
+proc main =
+  var
+    n = 1'i8
+    f = 2.0
+    s = Small(a: 1)
+    b = Big(a: 12345, b: 23456, c: 34567, d: 45678)
+
+  doAssert $cast[int](f).toBin(64) == "0100000000000000000000000000000000000000000000000000000000000000"
+  f = cast[float](n)
+  doAssert $cast[int](f).toBin(64) == "0000000000000000000000000000000000000000000000000000000000000001"
+
+  doAssert $b == "(a: 12345, b: 23456, c: 34567, d: 45678)"
+  b = cast[Big](s)
+  doAssert $b == "(a: 1, b: 0, c: 0, d: 0)"
+main()
diff --git a/tests/stdlib/tcgi.nim b/tests/stdlib/tcgi.nim
index 993728712..ef39450da 100644
--- a/tests/stdlib/tcgi.nim
+++ b/tests/stdlib/tcgi.nim
@@ -1,5 +1,10 @@
+discard """

+  matrix: "--mm:refc; --mm:orc"

+"""

+

 import std/unittest

 import std/[cgi, strtabs, sugar]

+import std/assertions

 

 block: # Test cgi module

   const queryString = "foo=bar&фу=бар&checked=✓&list=1,2,3&with_space=text%20with%20space"

diff --git a/tests/stdlib/tchannels.nim b/tests/stdlib/tchannels.nim
deleted file mode 100644
index 33108c50c..000000000
--- a/tests/stdlib/tchannels.nim
+++ /dev/null
@@ -1,33 +0,0 @@
-discard """
-  timeout:  5.0 # but typically < 1s
-  disabled: "freebsd"
-  matrix: "--gc:arc --threads:on; --gc:arc --threads:on -d:danger"
-"""
-
-when true:
-  # bug #17380: this was either blocking (without -d:danger) or crashing with SIGSEGV (with -d:danger)
-  import std/[channels, isolation]
-  const
-    N1 = 10
-    N2 = 100
-  var
-    sender: array[N1, Thread[void]]
-    receiver: array[5, Thread[void]] 
-
-  var chan = newChannel[seq[string]](N1 * N2) # large enough to not block
-  proc sendHandler() =
-    chan.send(isolate(@["Hello, Nim"]))
-  proc recvHandler() =
-    template fn =
-      let x = chan.recv()
-    fn()
-
-  template benchmark() =
-    for t in mitems(sender):
-      t.createThread(sendHandler)
-    joinThreads(sender)
-    for t in mitems(receiver):
-      t.createThread(recvHandler)
-    joinThreads(receiver)
-  for i in 0..<N2:
-    benchmark()
diff --git a/tests/stdlib/tchannels_pthread.nim b/tests/stdlib/tchannels_pthread.nim
deleted file mode 100644
index 3bc000551..000000000
--- a/tests/stdlib/tchannels_pthread.nim
+++ /dev/null
@@ -1,322 +0,0 @@
-discard """
-  targets: "c cpp"
-  matrix: "--gc:orc --threads:on; --gc:orc --threads:on -d:blockingTest"
-  disabled: "windows"
-  disabled: "bsd"
-  disabled: "osx"
-"""
-
-include std/channels
-
-import std/unittest
-
-
-type
-  ChannelBufKind = enum
-    Unbuffered # Unbuffered (blocking) channel
-    Buffered   # Buffered (non-blocking channel)
-
-
-proc capacity(chan: ChannelRaw): int {.inline.} = chan.size
-func isBuffered(chan: ChannelRaw): bool =
-  chan.size - 1 > 0
-
-when defined(blockingTest):
-  const nonBlocking = false
-else:
-  const nonBlocking = true
-
-type
-  Pthread {.importc: "pthread_t", header: "<sys/types.h>".} = distinct culong
-  PthreadAttr* {.byref, importc: "pthread_attr_t", header: "<sys/types.h>".} = object
-  Errno* = distinct cint
-
-proc pthread_create[T](
-      thread: var Pthread,
-      attr: ptr PthreadAttr, # In Nim this is a var and how Nim sets a custom stack
-      fn: proc (x: ptr T): pointer {.thread, noconv.},
-      arg: ptr T
-  ): Errno {.header: "<sys/types.h>".}
-
-proc pthread_join(
-      thread: Pthread,
-      thread_exit_status: ptr pointer
-    ): Errno {.header: "<pthread.h>".}
-
-template channel_send_loop(chan: ChannelRaw,
-                      data: sink pointer,
-                      size: int,
-                      body: untyped): untyped =
-  while not sendMpmc(chan, data, size, nonBlocking):
-    body
-
-template channel_receive_loop(chan: ChannelRaw,
-                        data: pointer,
-                        size: int,
-                        body: untyped): untyped =
-  while not recvMpmc(chan, data, size, nonBlocking):
-    body
-
-
-# Without threads:on or release,
-# worker threads will crash on popFrame
-
-import std/unittest
-
-type ThreadArgs = object
-  ID: int
-  chan: ChannelRaw
-
-template Worker(id: int, body: untyped): untyped {.dirty.} =
-  if args.ID == id:
-    body
-
-
-const Sender = 1
-const Receiver = 0
-
-proc runSuite(
-            name: string,
-            fn: proc(args: ptr ThreadArgs): pointer {.noconv, gcsafe.}
-          ) =
-  var chan: ChannelRaw
-
-  for i in Unbuffered .. Buffered:
-    if i == Unbuffered:
-      chan = allocChannel(size = 32, n = 1)
-      check:
-        peek(chan) == 0
-        capacity(chan) == 1
-        isBuffered(chan) == false
-        isUnbuffered(chan) == true
-
-    else:
-      chan = allocChannel(size = int.sizeof.int, n = 7)
-      check:
-        peek(chan) == 0
-        capacity(chan) == 7
-        isBuffered(chan) == true
-        isUnbuffered(chan) == false
-
-      var threads: array[2, Pthread]
-      var args = [
-        ThreadArgs(ID: 0, chan: chan),
-        ThreadArgs(ID: 1, chan: chan)
-      ]
-
-      discard pthread_create(threads[0], nil, fn, args[0].addr)
-      discard pthread_create(threads[1], nil, fn, args[1].addr)
-
-      discard pthread_join(threads[0], nil)
-      discard pthread_join(threads[1], nil)
-
-    freeChannel(chan)
-
-# ----------------------------------------------------------------------------------
-
-proc thread_func(args: ptr ThreadArgs): pointer {.noconv.} =
-
-  # Worker RECEIVER:
-  # ---------
-  # <- chan
-  # <- chan
-  # <- chan
-  #
-  # Worker SENDER:
-  # ---------
-  # chan <- 42
-  # chan <- 53
-  # chan <- 64
-  #
-
-  Worker(Receiver):
-    var val: int
-    for j in 0 ..< 3:
-      channel_receive_loop(args.chan, val.addr, val.sizeof.int):
-        # Busy loop, normally it should yield
-        discard
-      check: val == 42 + j*11
-
-  Worker(Sender):
-    var val: int
-    check: peek(args.chan) == 0
-    for j in 0 ..< 3:
-      val = 42 + j*11
-      channel_send_loop(args.chan, val.addr, val.sizeof.int):
-        # Busy loop, normally it should yield
-        discard
-
-  return nil
-
-runSuite("[ChannelRaw] 2 threads can send data", thread_func)
-
-# ----------------------------------------------------------------------------------
-
-iterator pairs(chan: ChannelRaw, T: typedesc): (int, T) =
-  var i = 0
-  var x: T
-  while not isClosed(chan) or peek(chan) > 0:
-    let r = recvMpmc(chan, x.addr, x.sizeof.int, true)
-    # printf("x: %d, r: %d\n", x, r)
-    if r:
-      yield (i, x)
-      inc i
-
-proc thread_func_2(args: ptr ThreadArgs): pointer {.noconv.} =
-  # Worker RECEIVER:
-  # ---------
-  # <- chan until closed and empty
-  #
-  # Worker SENDER:
-  # ---------
-  # chan <- 42, 53, 64, ...
-
-  const N = 100
-
-  Worker(Receiver):
-    for j, val in pairs(args.chan, int):
-      # TODO: Need special handling that doesn't allocate
-      #       in thread with no GC
-      #       when check fails
-      #
-      check: val == 42 + j*11
-
-  Worker(Sender):
-    var val: int
-    check: peek(args.chan) == 0
-    for j in 0 ..< N:
-      val = 42 + j*11
-      channel_send_loop(args.chan, val.addr, int.sizeof.int):
-        discard
-    discard channelCloseMpmc(args.chan)
-
-  return nil
-
-runSuite("[ChannelRaw] channel_close, freeChannel, channelCache", thread_func_2)
-
-# ----------------------------------------------------------------------------------
-
-proc isCached(chan: ChannelRaw): bool =
-  assert not chan.isNil
-
-  var p = channelCache
-  while not p.isNil:
-    if chan.itemsize == p.chanSize and
-        chan.size == p.chanN:
-      for i in 0 ..< p.numCached:
-        if chan == p.cache[i]:
-          return true
-      # No more channel in cache can match
-      return false
-    p = p.next
-  return false
-
-block: # [ChannelRaw] ChannelRaw caching implementation
-
-  # Start from clean cache slate
-  freeChannelCache()
-
-  block: # Explicit caches allocation
-    check:
-      allocChannelCache(int sizeof(char), 4)
-      allocChannelCache(int sizeof(int), 8)
-      allocChannelCache(int sizeof(ptr float64), 16)
-
-      # Don't create existing channel cache
-      not allocChannelCache(int sizeof(char), 4)
-      not allocChannelCache(int sizeof(int), 8)
-      not allocChannelCache(int sizeof(ptr float64), 16)
-
-    check:
-      channelCacheLen == 3
-
-  # ---------------------------------
-  var chan, stash: array[10, ChannelRaw]
-
-  block: # Implicit caches allocation
-
-    chan[0] = allocChannel(sizeof(char), 4)
-    chan[1] = allocChannel(sizeof(int32), 8)
-    chan[2] = allocChannel(sizeof(ptr float64), 16)
-
-    chan[3] = allocChannel(sizeof(char), 5)
-    chan[4] = allocChannel(sizeof(int64), 8)
-    chan[5] = allocChannel(sizeof(ptr float32), 24)
-
-    # We have caches ready to store specific channel kinds
-    check: channelCacheLen == 6 # Cumulated with previous test
-    # But they are not in cache while in use
-    check:
-      not chan[0].isCached
-      not chan[1].isCached
-      not chan[2].isCached
-      not chan[3].isCached
-      not chan[4].isCached
-      not chan[5].isCached
-
-  block: # Freed channels are returned to cache
-    stash[0..5] = chan.toOpenArray(0, 5)
-    for i in 0 .. 5:
-      # Free the channels
-      freeChannel(chan[i])
-
-    check:
-      stash[0].isCached
-      stash[1].isCached
-      stash[2].isCached
-      stash[3].isCached
-      stash[4].isCached
-      stash[5].isCached
-
-  block: # Cached channels are being reused
-
-    chan[6] = allocChannel(sizeof(char), 4)
-    chan[7] = allocChannel(sizeof(int32), 8)
-    chan[8] = allocChannel(sizeof(ptr float32), 16)
-    chan[9] = allocChannel(sizeof(ptr float64), 16)
-
-    # All (itemsize, queue size, implementation) were already allocated
-    check: channelCacheLen == 6
-
-    # We reused old channels from cache
-    check:
-      chan[6] == stash[0]
-      chan[7] == stash[1]
-      chan[8] == stash[2]
-      # chan[9] - required a fresh alloc
-
-  block: # Clearing the cache
-
-    stash[6..9] = chan.toOpenArray(6, 9)
-
-    for i in 6 .. 9:
-      freeChannel(chan[i])
-
-    check:
-      stash[6].isCached
-      stash[7].isCached
-      stash[8].isCached
-      stash[9].isCached
-
-    freeChannelCache()
-
-    # Check that nothing is cached anymore
-    for i in 0 .. 9:
-      check: not stash[i].isCached
-    # And length is reset to 0
-    check: channelCacheLen == 0
-
-    # Cache can grow again
-    chan[0] = allocChannel(sizeof((int, float, int32, uint)), 1)
-    chan[1] = allocChannel(sizeof(int32), 0)
-    chan[2] = allocChannel(sizeof(int32), 0)
-
-    check: channelCacheLen == 2
-
-    # Interleave cache clear and channel free
-    freeChannelCache()
-    check: channelCacheLen == 0
-
-    freeChannel(chan[0])
-    freeChannel(chan[1])
-    freeChannel(chan[2])
diff --git a/tests/stdlib/tchannels_simple.nim b/tests/stdlib/tchannels_simple.nim
deleted file mode 100644
index 56e5fb8f1..000000000
--- a/tests/stdlib/tchannels_simple.nim
+++ /dev/null
@@ -1,67 +0,0 @@
-discard """
-  matrix: "--threads:on --gc:orc; --threads:on --gc:arc"
-  disabled: "freebsd"
-"""
-
-import std/channels
-import std/os
-
-var chan = newChannel[string]()
-
-# This proc will be run in another thread using the threads module.
-proc firstWorker() =
-  chan.send("Hello World!")
-
-# This is another proc to run in a background thread. This proc takes a while
-# to send the message since it sleeps for 2 seconds (or 2000 milliseconds).
-proc secondWorker() =
-  sleep(2000)
-  chan.send("Another message")
-
-
-# Launch the worker.
-var worker1: Thread[void]
-createThread(worker1, firstWorker)
-
-# Block until the message arrives, then print it out.
-let dest = chan.recv()
-doAssert dest == "Hello World!"
-
-# Wait for the thread to exit before moving on to the next example.
-worker1.joinThread()
-
-# Launch the other worker.
-var worker2: Thread[void]
-createThread(worker2, secondWorker)
-# This time, use a non-blocking approach with tryRecv.
-# Since the main thread is not blocked, it could be used to perform other
-# useful work while it waits for data to arrive on the channel.
-
-var messages: seq[string]
-var msg = ""
-while true:
-  let tried = chan.tryRecv(msg)
-  if tried:
-    messages.add move(msg)
-    break
-  
-  messages.add "Pretend I'm doing useful work..."
-  # For this example, sleep in order not to flood stdout with the above
-  # message.
-  sleep(400)
-
-# Wait for the second thread to exit before cleaning up the channel.
-worker2.joinThread()
-
-# Clean up the channel.
-doAssert chan.close()
-doAssert messages[^1] == "Another message"
-doAssert messages.len >= 2
-
-
-block:
-  let chan0 = newChannel[int]()
-  let chan1 = chan0
-  block:
-    let chan3 = chan0
-    let chan4 = chan0
diff --git a/tests/stdlib/tclosures.nim b/tests/stdlib/tclosures.nim
new file mode 100644
index 000000000..84b033fa8
--- /dev/null
+++ b/tests/stdlib/tclosures.nim
@@ -0,0 +1,47 @@
+discard """
+  targets: "c js"
+"""
+
+import std/assertions
+
+block: # bug #4299
+  proc scopeProc() =
+    proc normalProc() =
+      discard
+
+    proc genericProc[T]() =
+      normalProc()
+
+    genericProc[string]()
+
+  scopeProc()
+
+block: # bug #12492
+  proc foo() =
+    var i = 0
+    proc bar() =
+      inc i
+
+    bar()
+    doAssert i == 1
+
+  foo()
+  static:
+    foo()
+
+block: # bug #10849
+  type
+    Generic[T] = ref object
+      getState: proc(): T
+
+  proc newGeneric[T](): Generic[T] =
+    var state: T
+
+    proc getState[T](): T =
+      state
+
+    Generic[T](getState: getState)
+
+  let g = newGeneric[int]()
+  let state = g.getState()
+  doAssert state == 0
diff --git a/tests/stdlib/tcmdline.nim b/tests/stdlib/tcmdline.nim
index bc78d6057..8b428900b 100644
--- a/tests/stdlib/tcmdline.nim
+++ b/tests/stdlib/tcmdline.nim
@@ -1,9 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
   joinable: false
 """
 
 import std/os
+import std/assertions
 
 var params = paramCount()
 doAssert params == 0
diff --git a/tests/stdlib/tcomplex.nim b/tests/stdlib/tcomplex.nim
index 15267b905..ca83314b9 100644
--- a/tests/stdlib/tcomplex.nim
+++ b/tests/stdlib/tcomplex.nim
@@ -1,5 +1,9 @@
-import std/[complex, math]
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
 
+import std/[complex, math]
+import std/assertions
 
 proc `=~`[T](x, y: Complex[T]): bool =
   result = abs(x.re-y.re) < 1e-6 and abs(x.im-y.im) < 1e-6
@@ -80,6 +84,9 @@ let t = polar(a)
 doAssert(rect(t.r, t.phi) =~ a)
 doAssert(rect(1.0, 2.0) =~ complex(-0.4161468365471424, 0.9092974268256817))
 
+doAssert(almostEqual(a, a + complex(1e-16, 1e-16)))
+doAssert(almostEqual(a, a + complex(2e-15, 2e-15), unitsInLastPlace = 5))
+
 
 let
   i64: Complex32 = complex(0.0f, 1.0f)
diff --git a/tests/stdlib/tcookies.nim b/tests/stdlib/tcookies.nim
index 0a36cbebc..3ff0f3bae 100644
--- a/tests/stdlib/tcookies.nim
+++ b/tests/stdlib/tcookies.nim
@@ -1,9 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 
 import std/[cookies, times, strtabs]
+import std/assertions
 
 let expire = fromUnix(0) + 1.seconds
 
diff --git a/tests/stdlib/tcritbits.nim b/tests/stdlib/tcritbits.nim
index b350cb280..e6282f045 100644
--- a/tests/stdlib/tcritbits.nim
+++ b/tests/stdlib/tcritbits.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/[sequtils,critbits]
+import std/assertions
 
 template main =
   var r: CritBitTree[void]
diff --git a/tests/stdlib/tcstring.nim b/tests/stdlib/tcstring.nim
index 98da5d5c4..d7fdd7738 100644
--- a/tests/stdlib/tcstring.nim
+++ b/tests/stdlib/tcstring.nim
@@ -1,10 +1,11 @@
 discard """
   targets: "c cpp js"
-  matrix: "; --gc:arc"
+  matrix: "--gc:refc; --gc:arc"
 """
 
 from std/sugar import collect
 from stdtest/testutils import whenRuntimeJs, whenVMorJs
+import std/assertions
 
 template testMitems() =
   block:
diff --git a/tests/stdlib/tcstrutils.nim b/tests/stdlib/tcstrutils.nim
index ba3b1de68..e73b2b681 100644
--- a/tests/stdlib/tcstrutils.nim
+++ b/tests/stdlib/tcstrutils.nim
@@ -1,9 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c cpp js"
 """
 
 import std/cstrutils
-
+import std/assertions
 
 proc main() =
   let s = cstring "abcdef"
diff --git a/tests/stdlib/tdb.nim b/tests/stdlib/tdb.nim
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/stdlib/tdb.nim
diff --git a/tests/stdlib/tdb.nims b/tests/stdlib/tdb.nims
new file mode 100644
index 000000000..d31d0b26f
--- /dev/null
+++ b/tests/stdlib/tdb.nims
@@ -0,0 +1 @@
+--styleCheck:off
\ No newline at end of file
diff --git a/tests/stdlib/tdb_mysql.nim b/tests/stdlib/tdb_mysql.nim
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/stdlib/tdb_mysql.nim
diff --git a/tests/stdlib/tdecls.nim b/tests/stdlib/tdecls.nim
index 3567639e0..42dc646f2 100644
--- a/tests/stdlib/tdecls.nim
+++ b/tests/stdlib/tdecls.nim
@@ -1,6 +1,11 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+import std/assertions
 import std/decls
 
-block:
+template fun() =
   var s = @[10,11,12]
   var a {.byaddr.} = s[0]
   a+=100
@@ -9,6 +14,8 @@ block:
   var b {.byaddr.}: int = s[0]
   doAssert a.addr == b.addr
 
+  {.push warningAsError[ImplicitTemplateRedefinition]: on.}
+  # in the future ImplicitTemplateRedefinition will be an error anyway
   doAssert not compiles(block:
     # redeclaration not allowed
     var foo = 0
@@ -18,6 +25,7 @@ block:
     # ditto
     var foo {.byaddr.} = s[0]
     var foo {.byaddr.} = s[0])
+  {.pop.}
 
   block:
     var b {.byaddr.} = s[1] # redeclaration ok in sub scope
@@ -34,37 +42,9 @@ block:
   doAssert compiles(block:
     var b2 {.byaddr.}: int = s[2])
 
-## We can define custom pragmas in user code
-template byUnsafeAddr(lhs, typ, expr) =
-  when typ is type(nil):
-    let tmp = unsafeAddr(expr)
-  else:
-    let tmp: ptr typ = unsafeAddr(expr)
-  template lhs: untyped = tmp[]
-
-block:
-  let s = @["foo", "bar"]
-  let a {.byUnsafeAddr.} = s[0]
-  doAssert a == "foo"
-  doAssert a[0].unsafeAddr == s[0][0].unsafeAddr
-
-block: # nkAccQuoted
-  # shows using a keyword, which requires nkAccQuoted
-  template `cast`(lhs, typ, expr) =
-    when typ is type(nil):
-      let tmp = unsafeAddr(expr)
-    else:
-      let tmp: ptr typ = unsafeAddr(expr)
-    template lhs: untyped = tmp[]
-
-  block:
-    let s = @["foo", "bar"]
-    let a {.`byUnsafeAddr`.} = s[0]
-    doAssert a == "foo"
-    doAssert a[0].unsafeAddr == s[0][0].unsafeAddr
-
-  block:
-    let s = @["foo", "bar"]
-    let a {.`cast`.} = s[0]
-    doAssert a == "foo"
-    doAssert a[0].unsafeAddr == s[0][0].unsafeAddr
+proc fun2() = fun()
+fun()
+fun2()
+static: fun2()
+when false: # pending bug #13887
+  static: fun()
diff --git a/tests/stdlib/tdecode_helpers.nim b/tests/stdlib/tdecode_helpers.nim
index 626a014fc..1c0735e05 100644
--- a/tests/stdlib/tdecode_helpers.nim
+++ b/tests/stdlib/tdecode_helpers.nim
@@ -1,5 +1,5 @@
 import std/private/decode_helpers
-
+import std/assertions
 
 block:
   var i = 0
diff --git a/tests/stdlib/tdeques.nim b/tests/stdlib/tdeques.nim
index 99208d4cf..39ff996d1 100644
--- a/tests/stdlib/tdeques.nim
+++ b/tests/stdlib/tdeques.nim
@@ -1,8 +1,11 @@
 discard """
-  targets: "c js"
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
 """
 
 import std/deques
+from std/sequtils import toSeq
+import std/assertions
 
 block:
   proc index(self: Deque[int], idx: Natural): int =
@@ -125,7 +128,7 @@ block:
   foo(1, 5)
   foo(3, 2)
 
-import sets
+import std/sets
 
 block t13310:
   proc main() =
@@ -137,3 +140,104 @@ block t13310:
 
   static:
     main()
+
+
+proc main() =
+  block:
+    let a = [10, 20, 30].toDeque
+    doAssert toSeq(a.pairs) == @[(0, 10), (1, 20), (2, 30)]
+
+  block:
+    let q = [7, 9].toDeque
+    doAssert 7 in q
+    doAssert q.contains(7)
+    doAssert 8 notin q
+
+  block:
+    let a = [10, 20, 30, 40, 50].toDeque
+    doAssert $a == "[10, 20, 30, 40, 50]"
+    doAssert a.peekFirst == 10
+    doAssert len(a) == 5
+
+  block:
+    let a = [10, 20, 30, 40, 50].toDeque
+    doAssert $a == "[10, 20, 30, 40, 50]"
+    doAssert a.peekLast == 50
+    doAssert len(a) == 5
+
+  block:
+    var a = [10, 20, 30, 40, 50].toDeque
+    doAssert $a == "[10, 20, 30, 40, 50]"
+    doAssert a.popFirst == 10
+    doAssert $a == "[20, 30, 40, 50]"
+
+  block:
+    var a = [10, 20, 30, 40, 50].toDeque
+    doAssert $a == "[10, 20, 30, 40, 50]"
+    doAssert a.popLast == 50
+    doAssert $a == "[10, 20, 30, 40]"
+
+  block:
+    var a = [10, 20, 30, 40, 50].toDeque
+    doAssert $a == "[10, 20, 30, 40, 50]"
+    clear(a)
+    doAssert len(a) == 0
+
+  block: # bug #21278
+    var a = [10, 20, 30, 40].toDeque
+
+    a.shrink(fromFirst = 0, fromLast = 1)
+    doAssert $a == "[10, 20, 30]"
+
+  block:
+    var a, b: Deque[int]
+    for i in 1 .. 256:
+      a.addLast(i)
+    for i in 1 .. 255:
+      a.popLast
+    b.addLast(1)
+    doAssert a == b
+
+  block:
+    # Issue 23275
+    # Test `==`.
+    block:
+      var a, b = initDeque[int]()
+      doAssert a == b
+      doAssert a.hash == b.hash
+      a.addFirst(1)
+      doAssert a != b
+      doAssert a.hash != b.hash
+      b.addLast(1)
+      doAssert a == b
+      doAssert a.hash == b.hash
+      a.popFirst
+      b.popLast
+      doAssert a == b
+      doAssert a.hash == b.hash
+      a.addLast 2
+      doAssert a != b
+      doAssert a.hash != b.hash
+      b.addFirst 2
+      doAssert a == b
+      doAssert a.hash == b.hash
+
+    block:
+      var a, b = initDeque[int]()
+      for i in countDown(100, 1):
+        a.addFirst(i)
+      for i in 1..100:
+        b.addLast(i)
+      doAssert a == b
+      for i in 1..99:
+        a.popLast
+      let a1 = [1].toDeque
+      doAssert a == a1
+      doAssert a.hash == a1.hash
+      var c = initDeque[int]()
+      c.addLast(1)
+      doAssert a == c
+      doAssert a.hash == c.hash
+
+static: main()
+main()
diff --git a/tests/stdlib/tdiff.nim b/tests/stdlib/tdiff.nim
index 694ac6198..132f7120b 100644
--- a/tests/stdlib/tdiff.nim
+++ b/tests/stdlib/tdiff.nim
@@ -1,9 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import experimental/diff
 import std/strutils
+import std/assertions
 
 proc testHelper(f: seq[Item]): string =
   for it in f:
diff --git a/tests/stdlib/tdistros_detect.nim b/tests/stdlib/tdistros_detect.nim
new file mode 100644
index 000000000..1176c8993
--- /dev/null
+++ b/tests/stdlib/tdistros_detect.nim
@@ -0,0 +1,16 @@
+import std/[assertions, distros]
+
+when defined(windows):
+    doAssert detectOs(Windows) == true
+    doAssert detectOs(Linux) == false
+    doAssert detectOs(MacOSX) == false
+
+when defined(linux):
+    doAssert detectOs(Linux) == true
+    doAssert detectOs(Windows) == false
+    doAssert detectOs(MacOSX) == false
+
+when defined(macosx):
+    doAssert detectOs(MacOSX) == true
+    doAssert detectOs(Windows) == false
+    doAssert detectOs(Linux) == false
diff --git a/tests/stdlib/tdochelpers.nim b/tests/stdlib/tdochelpers.nim
new file mode 100644
index 000000000..4d532b5d0
--- /dev/null
+++ b/tests/stdlib/tdochelpers.nim
@@ -0,0 +1,221 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  output: '''
+
+[Suite] Integration with Nim
+'''
+"""
+
+# tests for dochelpers.nim module
+
+import ../../lib/packages/docutils/[rstast, rst, dochelpers]
+import unittest
+import std/assertions
+
+proc testMsgHandler(filename: string, line, col: int, msgkind: MsgKind,
+                    arg: string) =
+  doAssert msgkind == mwBrokenLink
+
+proc fromRst(text: string): LangSymbol =
+  let r = rstParse(text, "-input-", LineRstInit, ColRstInit,
+                   {roNimFile},
+                   msgHandler=testMsgHandler)
+  assert r.node.kind == rnRstRef
+  result = toLangSymbol(r.node)
+
+proc fromMd(text: string): LangSymbol =
+  let r = rstParse(text, "-input-", LineRstInit, ColRstInit,
+                   {roPreferMarkdown, roSupportMarkdown, roNimFile},
+                   msgHandler=testMsgHandler)
+  assert r.node.kind == rnPandocRef
+  assert r.node.len == 2
+  # this son is the target:
+  assert r.node.sons[1].kind == rnInner
+  result = toLangSymbol(r.node.sons[1])
+
+suite "Integration with Nim":
+  test "simple symbol parsing (shortest form)":
+    let expected = LangSymbol(symKind: "", name: "g")
+    check "g_".fromRst == expected
+    check "[g]".fromMd == expected
+    # test also alternative syntax variants of Pandoc Markdown:
+    check "[g][]".fromMd == expected
+    check "[this symbol][g]".fromMd == expected
+
+  test "simple symbol parsing (group of words)":
+    #let input1 = "`Y`_".rstParseTest
+    let expected1 = LangSymbol(symKind: "", name: "Y")
+    check "`Y`_".fromRst == expected1
+    check "[Y]".fromMd == expected1
+
+    # this means not a statement 'type', it's a backticked identifier `type`:
+    let expected2 = LangSymbol(symKind: "", name: "type")
+    check "`type`_".fromRst == expected2
+    check "[type]".fromMd == expected2
+
+    let expected3 = LangSymbol(symKind: "", name: "[]")
+    check "`[]`_".fromRst == expected3
+    # Markdown syntax for this case is NOT [[]]
+    check "[`[]`]".fromMd == expected3
+
+    let expected4 = LangSymbol(symKind: "", name: "Xyz")
+    check "`X Y Z`_".fromRst == expected4
+    check "[X Y Z]".fromMd == expected4
+
+  test "simple proc parsing":
+    let expected = LangSymbol(symKind: "proc", name: "f")
+    check "`proc f`_".fromRst == expected
+    check "[proc f]".fromMd == expected
+
+  test "another backticked name":
+    let expected = LangSymbol(symKind: "template", name: "type")
+    check """`template \`type\``_""".fromRst == expected
+    # no backslash in Markdown:
+    check """[template `type`]""".fromMd == expected
+
+  test "simple proc parsing with parameters":
+    let expected = LangSymbol(symKind: "proc", name: "f",
+                              parametersProvided: true)
+    check "`proc f*()`_".fromRst == expected
+    check "`proc f()`_".fromRst == expected
+    check "[proc f*()]".fromMd == expected
+    check "[proc f()]".fromMd == expected
+
+  test "symbol parsing with 1 parameter":
+    let expected = LangSymbol(symKind: "", name: "f",
+                              parameters: @[("G[int]", "")],
+                              parametersProvided: true)
+    check "`f(G[int])`_".fromRst == expected
+    check "[f(G[int])]".fromMd == expected
+
+  test "more proc parsing":
+    let input1 = "`proc f[T](x:G[T]):M[T]`_".fromRst
+    let input2 = "`proc f[ T ] ( x: G [T] ): M[T]`_".fromRst
+    let input3 = "`proc f*[T](x: G[T]): M[T]`_".fromRst
+    let expected = LangSymbol(symKind: "proc",
+                              name: "f",
+                              generics: "[T]",
+                              parameters: @[("x", "G[T]")],
+                              parametersProvided: true,
+                              outType: "M[T]")
+    check(input1 == expected)
+    check(input2 == expected)
+    check(input3 == expected)
+
+  test "advanced proc parsing with Nim identifier normalization":
+    let inputRst = """`proc binarySearch*[T, K](a: openarray[T]; key: K;
+                       cmp: proc (x: T; y: K): int)`_"""
+    let inputMd = """[proc binarySearch*[T, K](a: openarray[T]; key: K;
+                       cmp: proc (x: T; y: K): int)]"""
+    let expected = LangSymbol(symKind: "proc",
+                              name: "binarysearch",
+                              generics: "[T,K]",
+                              parameters: @[
+                                ("a", "openarray[T]"),
+                                ("key", "K"),
+                                ("cmp", "proc(x:T;y:K):int")],
+                              parametersProvided: true,
+                              outType: "")
+    check(inputRst.fromRst == expected)
+    check(inputMd.fromMd == expected)
+
+  test "the same without proc":
+    let input = """`binarySearch*[T, K](a: openarray[T]; key: K;
+                    cmp: proc (x: T; y: K): int {.closure.})`_"""
+    let expected = LangSymbol(symKind: "",
+                              name: "binarysearch",
+                              generics: "[T,K]",
+                              parameters: @[
+                                ("a", "openarray[T]"),
+                                ("key", "K"),
+                                ("cmp", "proc(x:T;y:K):int")],
+                              parametersProvided: true,
+                              outType: "")
+    check(input.fromRst == expected)
+    let inputMd = """[binarySearch*[T, K](a: openarray[T]; key: K;
+                      cmp: proc (x: T; y: K): int {.closure.})]"""
+    check(inputMd.fromMd == expected)
+
+  test "operator $ with and without backticks":
+    let input1 = """`func \`$\`*[T](a: \`open Array\`[T]): string`_"""
+    let input1md = "[func `$`*[T](a: `open Array`[T]): string]"
+    let input2 = """`func $*[T](a: \`open Array\`[T]): string`_"""
+    let input2md = "[func $*[T](a: `open Array`[T]): string]"
+    let expected = LangSymbol(symKind: "func",
+                              name: "$",
+                              generics: "[T]",
+                              parameters: @[("a", "openarray[T]")],
+                              parametersProvided: true,
+                              outType: "string")
+    check input1.fromRst == expected
+    check input2.fromRst == expected
+    check input1md.fromMd == expected
+    check input2md.fromMd == expected
+
+  test "operator [] with and without backticks":
+    let input1 = """`func \`[]\`[T](a: \`open Array\`[T], idx: int): T`_"""
+    let input1md = "[func `[]`[T](a: `open Array`[T], idx: int): T]"
+    let input2 = """`func [][T](a: \`open Array\`[T], idx: int): T`_"""
+    let input2md = "[func [][T](a: `open Array`[T], idx: int): T]"
+    let expected = LangSymbol(symKind: "func",
+                              name: "[]",
+                              generics: "[T]",
+                              parameters: @[("a", "openarray[T]"),
+                                            ("idx", "int")],
+                              parametersProvided: true,
+                              outType: "T")
+    check input1.fromRst == expected
+    check input2.fromRst == expected
+    check input1md.fromMd == expected
+    check input2md.fromMd == expected
+
+  test "postfix symbol specifier #1":
+    let input = "`walkDir iterator`_"
+    let inputMd = "[walkDir iterator]"
+    let expected = LangSymbol(symKind: "iterator",
+                              name: "walkdir")
+    check input.fromRst == expected
+    check inputMd.fromMd == expected
+
+  test "postfix symbol specifier #2":
+    let input1 = """`\`[]\`[T](a: \`open Array\`[T], idx: int): T func`_"""
+    let input1md = "[`[]`[T](a: `open Array`[T], idx: int): T func]"
+    let input2 = """`[][T](a: \`open Array\`[T], idx: int): T func`_"""
+    # note again that ` is needed between 1st and second [
+    let input2md = "[`[]`[T](a: `open Array`[T], idx: int): T func]"
+    let expected = LangSymbol(symKind: "func",
+                              name: "[]",
+                              generics: "[T]",
+                              parameters: @[("a", "openarray[T]"),
+                                            ("idx", "int")],
+                              parametersProvided: true,
+                              outType: "T")
+    check input1.fromRst == expected
+    check input2.fromRst == expected
+    check input1md.fromMd == expected
+    check input2md.fromMd == expected
+
+  test "type of type":
+    let inputRst = "`CopyFlag enum`_"
+    let inputMd = "[CopyFlag enum]"
+    let expected = LangSymbol(symKind: "type",
+                              symTypeKind: "enum",
+                              name: "Copyflag")
+    check inputRst.fromRst == expected
+    check inputMd.fromMd == expected
+
+  test "prefixed module":
+    let inputRst = "`module std / paths`_"
+    let inputMd = "[module std / paths]"
+    let expected = LangSymbol(symKind: "module",
+                              name: "std/paths")
+    check inputRst.fromRst == expected
+    check inputMd.fromMd == expected
+
+  test "postfixed module":
+    let inputRst = "`std / paths module`_"
+    let inputMd = "[std / paths module]"
+    let expected = LangSymbol(symKind: "module",
+                              name: "std/paths")
+    check inputRst.fromRst == expected
+    check inputMd.fromMd == expected
diff --git a/tests/stdlib/teditdistance.nim b/tests/stdlib/teditdistance.nim
index 433535635..14ba6df97 100644
--- a/tests/stdlib/teditdistance.nim
+++ b/tests/stdlib/teditdistance.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/editdistance
+import std/assertions
 
 doAssert editDistance("", "") == 0
 doAssert editDistance("kitten", "sitting") == 3 # from Wikipedia
diff --git a/tests/stdlib/tencodings.nim b/tests/stdlib/tencodings.nim
new file mode 100644
index 000000000..2f4daaba3
--- /dev/null
+++ b/tests/stdlib/tencodings.nim
@@ -0,0 +1,107 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/encodings
+import std/assertions
+
+var fromGBK = open("utf-8", "gbk")
+var toGBK = open("gbk", "utf-8")
+
+var fromGB2312 = open("utf-8", "gb2312")
+var toGB2312 = open("gb2312", "utf-8")
+
+
+block:
+  let data = "\215\237\186\243\178\187\214\170\204\236\212\218\203\174\163\172\194\250\180\178\208\199\195\206\209\185\208\199\186\211"
+  doAssert fromGBK.convert(data) == "醉后不知天在水,满床星梦压星河"
+
+block:
+  let data = "万两黄金容易得,知心一个也难求"
+  doAssert toGBK.convert(data) == "\205\242\193\189\187\198\189\240\200\221\210\215\181\195\163\172\214\170\208\196\210\187\184\246\210\178\196\209\199\243"
+
+
+block:
+  let data = "\215\212\208\197\200\203\201\250\182\254\176\217\196\234\163\172\187\225\181\177\203\174\187\247\200\253\199\167\192\239"
+  doAssert fromGB2312.convert(data) == "自信人生二百年,会当水击三千里"
+
+block:
+  let data = "谁怕?一蓑烟雨任平生"
+  doAssert toGB2312.convert(data) == "\203\173\197\194\163\191\210\187\203\242\209\204\211\234\200\206\198\189\201\250"
+
+
+when defined(windows):
+  block should_throw_on_unsupported_conversions:
+    let original = "some string"
+
+    doAssertRaises(EncodingError):
+      discard convert(original, "utf-8", "utf-32")
+
+    doAssertRaises(EncodingError):
+      discard convert(original, "utf-8", "unicodeFFFE")
+
+    doAssertRaises(EncodingError):
+      discard convert(original, "utf-8", "utf-32BE")
+
+    doAssertRaises(EncodingError):
+      discard convert(original, "unicodeFFFE", "utf-8")
+
+    doAssertRaises(EncodingError):
+      discard convert(original, "utf-32", "utf-8")
+
+    doAssertRaises(EncodingError):
+      discard convert(original, "utf-32BE", "utf-8")
+
+  block should_convert_from_utf16_to_utf8:
+    let original = "\x42\x04\x35\x04\x41\x04\x42\x04" # utf-16 little endian test string "тест"
+    let result = convert(original, "utf-8", "utf-16")
+    doAssert(result == "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82")
+
+  block should_convert_from_utf16_to_win1251:
+    let original = "\x42\x04\x35\x04\x41\x04\x42\x04" # utf-16 little endian test string "тест"
+    let result = convert(original, "windows-1251", "utf-16")
+    doAssert(result == "\xf2\xe5\xf1\xf2")
+
+  block should_convert_from_win1251_to_koi8r:
+    let original = "\xf2\xe5\xf1\xf2" # win1251 test string "тест"
+    let result = convert(original, "koi8-r", "windows-1251")
+    doAssert(result == "\xd4\xc5\xd3\xd4")
+
+  block should_convert_from_koi8r_to_win1251:
+    let original = "\xd4\xc5\xd3\xd4" # koi8r test string "тест"
+    let result = convert(original, "windows-1251", "koi8-r")
+    doAssert(result == "\xf2\xe5\xf1\xf2")
+
+  block should_convert_from_utf8_to_win1251:
+    let original = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82" # utf-8 test string "тест"
+    let result = convert(original, "windows-1251", "utf-8")
+    doAssert(result == "\xf2\xe5\xf1\xf2")
+
+  block should_convert_from_utf8_to_utf16:
+    let original = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82" # utf-8 test string "тест"
+    let result = convert(original, "utf-16", "utf-8")
+    doAssert(result == "\x42\x04\x35\x04\x41\x04\x42\x04")
+
+  block should_handle_empty_string_for_any_conversion:
+    let original = ""
+    var result = convert(original, "utf-16", "utf-8")
+    doAssert(result == "")
+    result = convert(original, "utf-8", "utf-16")
+    doAssert(result == "")
+    result = convert(original, "windows-1251", "koi8-r")
+    doAssert(result == "")
+
+
+block:
+  let
+    orig = "öäüß"
+    cp1252 = convert(orig, "CP1252", "UTF-8")
+    ibm850 = convert(cp1252, "ibm850", "CP1252")
+    current = getCurrentEncoding()
+  doAssert orig == "\195\182\195\164\195\188\195\159"
+  doAssert ibm850 == "\148\132\129\225"
+  doAssert convert(ibm850, current, "ibm850") == orig
+
+block: # fixes about #23481
+  doAssertRaises EncodingError:
+    discard open(destEncoding="this is a invalid enc")
diff --git a/tests/stdlib/tenumerate.nim b/tests/stdlib/tenumerate.nim
index 7a1c2d10a..2789ebe3a 100644
--- a/tests/stdlib/tenumerate.nim
+++ b/tests/stdlib/tenumerate.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/enumerate
+import std/assertions
 
 let a = @[1, 3, 5, 7]
 
diff --git a/tests/stdlib/tenumutils.nim b/tests/stdlib/tenumutils.nim
index 11142216c..2662a660d 100644
--- a/tests/stdlib/tenumutils.nim
+++ b/tests/stdlib/tenumutils.nim
@@ -1,9 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/enumutils
 from std/sequtils import toSeq
+import std/assertions
 
 template main =
   block: # items
@@ -33,5 +35,15 @@ template main =
     doAssert $b == "kb0"
     static: doAssert B.high.symbolName == "b2"
 
+  block:
+    type
+      Color = enum
+        Red = "red", Yellow = "yellow", Blue = "blue"
+
+    var s = Red
+    doAssert symbolName(s) == "Red"
+    var x: range[Red..Blue] = Yellow
+    doAssert symbolName(x) == "Yellow"
+
 static: main()
 main()
diff --git a/tests/stdlib/tenvvars.nim b/tests/stdlib/tenvvars.nim
new file mode 100644
index 000000000..1a07f02b8
--- /dev/null
+++ b/tests/stdlib/tenvvars.nim
@@ -0,0 +1,162 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  joinable: false
+  targets: "c js cpp"
+"""
+
+import std/envvars
+from std/sequtils import toSeq
+import stdtest/testutils
+import std/[assertions]
+
+when not defined(js):
+  import std/typedthreads
+
+# "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386)
+const unicodeUtf8 = "\xc3\x86"
+
+template main =
+  block: # delEnv, existsEnv, getEnv, envPairs
+    for val in ["val", "", unicodeUtf8]: # ensures empty val works too
+      const key = "NIM_TESTS_TOSENV_KEY"
+      doAssert not existsEnv(key)
+
+      putEnv(key, "tempval")
+      doAssert existsEnv(key)
+      doAssert getEnv(key) == "tempval"
+
+      putEnv(key, val) # change a key that already exists
+      doAssert existsEnv(key)
+      doAssert getEnv(key) == val
+
+      doAssert (key, val) in toSeq(envPairs())
+      delEnv(key)
+      doAssert (key, val) notin toSeq(envPairs())
+      doAssert not existsEnv(key)
+      delEnv(key) # deleting an already deleted env var
+      doAssert not existsEnv(key)
+
+    block:
+      doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "") == ""
+      doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", " ") == " "
+      doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "defval") == "defval"
+
+    whenVMorJs: discard # xxx improve
+    do:
+      doAssertRaises(OSError, putEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE", "NEW_DUMMY_VALUE"))
+      doAssertRaises(OSError, putEnv("", "NEW_DUMMY_VALUE"))
+      doAssert not existsEnv("")
+      doAssert not existsEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE")
+      doAssert not existsEnv("NIM_TESTS_TOSENV_PUT")
+
+static: main()
+main()
+
+when defined(windows):
+  import std/widestrs
+  proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".}
+proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
+
+when not defined(js) and not defined(nimscript):
+  block: # bug #18533
+    var thr: Thread[void]
+    proc threadFunc {.thread.} = putEnv("foo", "fooVal2")
+
+    putEnv("foo", "fooVal1")
+    doAssert getEnv("foo") == "fooVal1"
+    createThread(thr, threadFunc)
+    joinThreads(thr)
+    when defined(windows):
+      doAssert getEnv("foo") == $c_wgetenv("foo".newWideCString)
+    else:
+      doAssert getEnv("foo") == $c_getenv("foo".cstring)
+
+    doAssertRaises(OSError): delEnv("foo=bar")
+
+when defined(windows) and not defined(nimscript):
+  import std/encodings
+
+  proc c_putenv(env: cstring): int32 {.importc: "putenv", header: "<stdlib.h>".}
+  proc c_wputenv(env: WideCString): int32 {.importc: "_wputenv", header: "<stdlib.h>".}
+
+  block: # Bug #20083
+    # These test that `getEnv`, `putEnv` and `existsEnv` handle Unicode
+    # characters correctly. This means that module X in the process calling the
+    # CRT environment variable API will get the correct string. Raw CRT API
+    # calls below represent module X.
+
+    # Getting an env. var. with unicode characters returns the correct UTF-8
+    # encoded string.
+    block:
+      const envName = "twin_envvars1"
+      doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
+      doAssert existsEnv(envName)
+      doAssert getEnv(envName) == unicodeUtf8
+
+    # Putting an env. var. with unicode characters gives the correct UTF-16
+    # encoded string from low-level routine.
+    block:
+      const envName = "twin_envvars2"
+      putEnv(envName, unicodeUtf8)
+      doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
+
+    # Env. name containing Unicode characters is retrieved correctly
+    block:
+      const envName = unicodeUtf8 & "1"
+      doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
+      doAssert existsEnv(envName)
+      doAssert getEnv(envName) == unicodeUtf8
+
+    # Env. name containing Unicode characters is set correctly
+    block:
+      const envName = unicodeUtf8 & "2"
+      putEnv(envName, unicodeUtf8)
+      doAssert existsEnv(envName)
+      doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
+
+    # Env. name containing Unicode characters and empty value is set correctly
+    block:
+      const envName = unicodeUtf8 & "3"
+      putEnv(envName, "")
+      doAssert existsEnv(envName)
+      doAssert $c_wgetenv(envName.newWideCString) == ""
+
+    # It's hard to test on Windows code pages, because there is no "change
+    # a process' locale" API.
+    if getCurrentEncoding(true) == "windows-1252":
+      const
+        unicodeAnsi = "\xc6" # `unicodeUtf8` in `windows-1252` encoding
+
+      # Test that env. var. ANSI API has correct encoding
+      block:
+        const
+          envName = unicodeUtf8 & "4"
+          envNameAnsi = unicodeAnsi & "4"
+        putEnv(envName, unicodeUtf8)
+        doAssert $c_getenv(envNameAnsi.cstring) == unicodeAnsi
+
+      block:
+        const
+          envName = unicodeUtf8 & "5"
+          envNameAnsi = unicodeAnsi & "5"
+        doAssert c_putenv((envNameAnsi & "=" & unicodeAnsi).cstring) == 0
+        doAssert getEnv(envName) == unicodeUtf8
+
+      # Env. name containing Unicode characters and empty value is set correctly;
+      # and, if env. name. characters cannot be represented in codepage, don't
+      # raise an error.
+      #
+      # `win_setenv.nim` converts UTF-16 to ANSI when setting empty env. var. The
+      # windows-1250 locale has no representation of `abreveUtf8` below, so the
+      # conversion will fail, but this must not be fatal. It is expected that the
+      # routine ignores updating MBCS environment (`environ` global) and carries
+      # on.
+      block:
+        const
+          # "LATIN SMALL LETTER A WITH BREVE" in UTF-8
+          abreveUtf8 = "\xc4\x83"
+          envName = abreveUtf8 & "6"
+        putEnv(envName, "")
+        doAssert existsEnv(envName)
+        doAssert $c_wgetenv(envName.newWideCString) == ""
+        doAssert getEnv(envName) == ""
diff --git a/tests/stdlib/texitprocs.nim b/tests/stdlib/texitprocs.nim
index 9d5378fe8..ea29d8f58 100644
--- a/tests/stdlib/texitprocs.nim
+++ b/tests/stdlib/texitprocs.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 targets: "c cpp js"
 output: '''
 ok4
diff --git a/tests/stdlib/tfdleak.nim b/tests/stdlib/tfdleak.nim
index 79d7ee0d0..272a7507c 100644
--- a/tests/stdlib/tfdleak.nim
+++ b/tests/stdlib/tfdleak.nim
@@ -1,12 +1,15 @@
 discard """
   exitcode: 0
   output: ""
-  matrix: "; -d:nimInheritHandles"
+  matrix: "; -d:nimInheritHandles; --mm:refc"
   joinable: false
 """
 
 import os, osproc, strutils, nativesockets, net, selectors, memfiles,
        asyncdispatch, asyncnet
+
+import std/[assertions, syncio]
+
 when defined(windows):
   import winlean
 
@@ -56,7 +59,7 @@ proc isValidHandle(f: int): bool =
 proc main() =
   if paramCount() == 0:
     # Parent process
-    let f = system.open("__test_fdleak", fmReadWrite)
+    let f = syncio.open("__test_fdleak", fmReadWrite)
     defer: close f
 
     leakCheck(f.getOsFileHandle, "system.open()")
diff --git a/tests/stdlib/tfdleak_multiple.nim b/tests/stdlib/tfdleak_multiple.nim
index 22387607f..c26681217 100644
--- a/tests/stdlib/tfdleak_multiple.nim
+++ b/tests/stdlib/tfdleak_multiple.nim
@@ -3,6 +3,7 @@ joinable: false
 """
 
 import os, osproc, strutils
+import std/assertions
 
 const Iterations = 200
 
diff --git a/tests/stdlib/tfenv.nim b/tests/stdlib/tfenv.nim
index 5bcd1ea7c..a486b8a9d 100644
--- a/tests/stdlib/tfenv.nim
+++ b/tests/stdlib/tfenv.nim
@@ -1,4 +1,5 @@
 import std/fenv
+import std/assertions
 
 
 func is_significant(x: float): bool =
diff --git a/tests/stdlib/tfilesanddirs.nim b/tests/stdlib/tfilesanddirs.nim
new file mode 100644
index 000000000..a1920d4f2
--- /dev/null
+++ b/tests/stdlib/tfilesanddirs.nim
@@ -0,0 +1,36 @@
+import std/[paths, files, dirs, appdirs]
+
+from stdtest/specialpaths import buildDir
+import std/[syncio, assertions]
+
+block fileOperations:
+  let files = @[Path"these.txt", Path"are.x", Path"testing.r", Path"files.q"]
+  let dirs = @[Path"some", Path"created", Path"test", Path"dirs"]
+
+  let dname = Path"__really_obscure_dir_name"
+
+  createDir(dname.Path)
+  doAssert dirExists(Path(dname))
+ 
+  # Test creating files and dirs
+  for dir in dirs:
+    createDir(Path(dname/dir))
+    doAssert dirExists(Path(dname/dir))
+
+  for file in files:
+    let fh = open(string(dname/file), fmReadWrite) # createFile
+    fh.close()
+    doAssert fileExists(Path(dname/file))
+
+block: # getCacheDir
+  doAssert getCacheDir().dirExists
+
+block: # moveFile
+  let tempDir = getTempDir() / Path("D20221022T151608")
+  createDir(tempDir)
+  defer: removeDir(tempDir)
+
+block: # moveDir
+  let tempDir = getTempDir() / Path("D20220609T161443")
+  createDir(tempDir)
+  defer: removeDir(tempDir)
diff --git a/tests/stdlib/tfrexp1.nim b/tests/stdlib/tfrexp1.nim
index 85110231d..aa734ddac 100644
--- a/tests/stdlib/tfrexp1.nim
+++ b/tests/stdlib/tfrexp1.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "js c cpp"
 """
 
 import std/math
+import std/assertions
 
 const manualTest = false
 
diff --git a/tests/stdlib/tgenast.nim b/tests/stdlib/tgenast.nim
new file mode 100644
index 000000000..d99c9312e
--- /dev/null
+++ b/tests/stdlib/tgenast.nim
@@ -0,0 +1,274 @@
+discard """
+  matrix: "--mm:orc; --mm:refc"
+"""
+
+# xxx also test on js
+
+import std/genasts
+import std/macros
+from std/strformat import `&`
+import std/assertions
+import ./mgenast
+
+proc main =
+  block:
+    macro bar(x0: static Foo, x1: Foo, x2: Foo, xignored: Foo): untyped =
+      let s0 = "not captured!"
+      let s1 = "not captured!"
+      let xignoredLocal = kfoo4
+
+      # newLit optional:
+      let x3 = newLit kfoo4
+      let x3b = kfoo4
+
+      result = genAstOpt({kDirtyTemplate}, s1=true, s2="asdf", x0, x1=x1, x2, x3, x3b):
+        doAssert not declared(xignored)
+        doAssert not declared(xignoredLocal)
+        (s1, s2, s0, x0, x1, x2, x3, x3b)
+
+    let s0 = "caller scope!"
+
+    doAssert bar(kfoo1, kfoo2, kfoo3, kfoo4) ==
+      (true, "asdf", "caller scope!", kfoo1, kfoo2, kfoo3, kfoo4, kfoo4)
+
+  block:
+    # doesn't have limitation mentioned in https://github.com/nim-lang/RFCs/issues/122#issue-401636535
+    macro abc(name: untyped): untyped =
+      result = genAst(name):
+        type name = object
+
+    abc(Bar)
+    doAssert Bar.default == Bar()
+
+  block:
+    # backticks parser limitations / ambiguities not are an issue with `genAst`:
+    # (#10326 #9745 are fixed but `quote do` still has underlying ambiguity issue
+    # with backticks)
+    type Foo = object
+      a: int
+
+    macro m1(): untyped =
+      # result = quote do: # Error: undeclared identifier: 'a1'
+      result = genAst:
+        template `a1=`(x: var Foo, val: int) =
+          x.a = val
+
+    m1()
+    var x0: Foo
+    x0.a1 = 10
+    doAssert x0 == Foo(a: 10)
+
+  block:
+    # avoids bug #7375
+    macro fun(b: static[bool], b2: bool): untyped =
+      result = newStmtList()
+    macro foo(c: bool): untyped =
+      var b = false
+      result = genAst(b, c):
+        fun(b, c)
+
+    foo(true)
+
+  block:
+    # avoids bug #7589
+    # since `==` works with genAst, the problem goes away
+    macro foo2(): untyped =
+      # result = quote do: # Error: '==' cannot be passed to a procvar
+      result = genAst:
+        `==`(3,4)
+    doAssert not foo2()
+
+  block:
+    # avoids bug #7726
+    # expressions such as `a.len` are just passed as arguments to `genAst`, and
+    # caller scope is not polluted with definitions such as `let b = newLit a.len`
+    macro foo(): untyped =
+      let a = @[1, 2, 3, 4, 5]
+      result = genAst(a, b = a.len): # shows 2 ways to get a.len
+        (a.len, b)
+    doAssert foo() == (5, 5)
+
+  block:
+    # avoids bug #9607
+    proc fun1(info:LineInfo): string = "bar1"
+    proc fun2(info:int): string = "bar2"
+
+    macro bar2(args: varargs[untyped]): untyped =
+      let info = args.lineInfoObj
+      let fun1 = bindSym"fun1" # optional; we can remove this and also the
+      # capture of fun1, as show in next example
+      result = genAst(info, fun1):
+        (fun1(info), fun2(info.line))
+    doAssert bar2() == ("bar1", "bar2")
+
+    macro bar3(args: varargs[untyped]): untyped =
+      let info = args.lineInfoObj
+      result = genAst(info):
+        (fun1(info), fun2(info.line))
+    doAssert bar3() == ("bar1", "bar2")
+
+    macro bar(args: varargs[untyped]): untyped =
+      let info = args.lineInfoObj
+      let fun1 = bindSym"fun1"
+      let fun2 = bindSym"fun2"
+      result = genAstOpt({kDirtyTemplate}, info):
+        (fun1(info), fun2(info.line))
+    doAssert bar() == ("bar1", "bar2")
+
+  block:
+    # example from bug #7889 works
+    # after changing method call syntax to regular call syntax; this is a
+    # limitation described in bug #7085
+    # note that `quote do` would also work after that change in this example.
+    doAssert bindme2() == kfoo1
+    doAssert bindme3() == kfoo1
+    doAssert not compiles(bindme4()) # correctly gives Error: undeclared identifier: 'myLocalPriv'
+    proc myLocalPriv2(): auto = kfoo2
+    doAssert bindme5UseExpose() == kfoo1
+
+    # example showing hijacking behavior when using `kDirtyTemplate`
+    doAssert bindme5UseExposeFalse() == kfoo2
+      # local `myLocalPriv2` hijacks symbol `mgenast.myLocalPriv2`. In most
+      # use cases this is probably not what macro writer intends as it's
+      # surprising; hence `kDirtyTemplate` is not the default.
+
+    when nimvm: # disabled because `newStringStream` is used
+      discard
+    else:
+      bindme6UseExpose()
+      bindme6UseExposeFalse()
+
+  block:
+    macro mbar(x3: Foo, x3b: static Foo): untyped =
+      var x1=kfoo3
+      var x2=newLit kfoo3
+      var x4=kfoo3
+      var xLocal=kfoo3
+
+      proc funLocal(): auto = kfoo4
+
+      result = genAst(x1, x2, x3, x4):
+        # local x1 overrides remote x1
+        when false:
+          # one advantage of using `kDirtyTemplate` is that these would hold:
+          doAssert not declared xLocal
+          doAssert not compiles(echo xLocal)
+          # however, even without it, we at least correctly generate CT error
+          # if trying to use un-captured symbol; this correctly gives:
+          # Error: internal error: environment misses: xLocal
+          echo xLocal
+
+        proc foo1(): auto =
+          # note that `funLocal` is captured implicitly, according to hygienic
+          # template rules; with `kDirtyTemplate` it would not unless
+          # captured in `genAst` capture list explicitly
+          (a0: xRemote, a1: x1, a2: x2, a3: x3, a4: x4, a5: funLocal())
+
+      return result
+
+    proc main()=
+      var xRemote=kfoo1
+      var x1=kfoo2
+      mbar(kfoo4, kfoo4)
+      doAssert foo1() == (a0: kfoo1, a1: kfoo3, a2: kfoo3, a3: kfoo4, a4: kfoo3, a5: kfoo4)
+
+    main()
+
+  block:
+    # With `kDirtyTemplate`, the example from #8220 works.
+    # See https://nim-lang.github.io/Nim/strformat.html#limitations for
+    # an explanation of why {.dirty.} is needed.
+    macro foo(): untyped =
+      result = genAstOpt({kDirtyTemplate}):
+        let bar = "Hello, World"
+        &"Let's interpolate {bar} in the string"
+    doAssert foo() == "Let's interpolate Hello, World in the string"
+
+
+  block: # nested application of genAst
+    macro createMacro(name, obj, field: untyped): untyped =
+      result = genAst(obj = newDotExpr(obj, field), lit = 10, name, field):
+        # can't reuse `result` here, would clash
+        macro name(arg: untyped): untyped =
+          genAst(arg2=arg): # somehow `arg2` rename is needed
+            (obj, astToStr(field), lit, arg2)
+
+    var x = @[1, 2, 3]
+    createMacro foo, x, len
+    doAssert (foo 20) == (3, "len", 10, 20)
+
+  block: # test with kNoNewLit
+    macro bar(): untyped =
+      let s1 = true
+      template boo(x): untyped =
+        fun(x)
+      result = genAstOpt({kNoNewLit}, s1=newLit(s1), s1b=s1): (s1, s1b)
+    doAssert bar() == (true, 1)
+
+  block: # sanity check: check passing `{}` also works
+    macro bar(): untyped =
+      result = genAstOpt({}, s1=true): s1
+    doAssert bar() == true
+
+  block: # test passing function and type symbols
+    proc z1(): auto = 41
+    type Z4 = type(1'i8)
+    macro bar(Z1: typedesc): untyped =
+      proc z2(): auto = 42
+      proc z3[T](a: T): auto = 43
+      let Z2 = genAst():
+        type(true)
+      let z4 = genAst():
+        proc myfun(): auto = 44
+        myfun
+      type Z3 = type(1'u8)
+      result = genAst(z4, Z1, Z2):
+        # z1, z2, z3, Z3, Z4 are captured automatically
+        # z1, z2, z3 can optionally be specified in capture list
+        (z1(), z2(), z3('a'), z4(), $Z1, $Z2, $Z3, $Z4)
+    type Z1 = type('c')
+    doAssert bar(Z1) == (41, 42, 43, 44, "char", "bool", "uint8", "int8")
+
+  block: # fix bug #11986
+    proc foo(): auto =
+      var s = { 'a', 'b' }
+      # var n = quote do: `s` # would print {97, 98}
+      var n = genAst(s): s
+      n.repr
+    static: doAssert foo() == "{'a', 'b'}"
+
+  block: # also from #11986
+    macro foo(): untyped =
+      var s = { 'a', 'b' }
+      # quote do:
+      #   let t = `s`
+      #   $typeof(t) # set[range 0..65535(int)]
+      genAst(s):
+        let t = s
+        $typeof(t)
+    doAssert foo() == "set[char]"
+
+  block:
+    macro foo(): untyped =
+      type Foo = object
+      template baz2(a: int): untyped = a*10
+      macro baz3(a: int): untyped = newLit 13
+      result = newStmtList()
+
+      result.add genAst(Foo, baz2, baz3) do: # shows you can pass types, templates etc
+        var x: Foo
+        $($typeof(x), baz2(3), baz3(4))
+
+      let ret = genAst() do: # shows you don't have to, since they're inject'd
+        var x: Foo
+        $($typeof(x), baz2(3), baz3(4))
+    doAssert foo() == """("Foo", 30, 13)"""
+
+  block: # illustrates how symbol visiblity can be controlled precisely using `mixin`
+    proc locafun1(): auto = "in locafun1 (caller scope)" # this will be used because of `mixin locafun1` => explicit hijacking is ok
+    proc locafun2(): auto = "in locafun2 (caller scope)" # this won't be used => no hijacking
+    proc locafun3(): auto = "in locafun3 (caller scope)"
+    doAssert mixinExample() == ("in locafun1 (caller scope)", "in locafun2", "in locafun3 (caller scope)")
+
+static: main()
+main()
diff --git a/tests/stdlib/tgetaddrinfo.nim b/tests/stdlib/tgetaddrinfo.nim
index ed8ec8b68..3a90034c8 100644
--- a/tests/stdlib/tgetaddrinfo.nim
+++ b/tests/stdlib/tgetaddrinfo.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   exitcode: 0
   output: ""
 """
@@ -6,6 +7,7 @@ discard """
 # bug: https://github.com/nim-lang/Nim/issues/10198
 
 import nativesockets
+import std/assertions
 
 block DGRAM_UDP:
   let aiList = getAddrInfo("127.0.0.1", 999.Port, AF_INET, SOCK_DGRAM, IPPROTO_UDP)
diff --git a/tests/stdlib/tgetfileinfo.nim b/tests/stdlib/tgetfileinfo.nim
index 19de193e4..ae1480a4c 100644
--- a/tests/stdlib/tgetfileinfo.nim
+++ b/tests/stdlib/tgetfileinfo.nim
@@ -1,8 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: "pcDir\npcFile\npcLinkToDir\npcLinkToFile\n"
+  joinable: false
 """
 
 import os, strutils
+import std/[syncio, assertions]
 # Cases
 #  1 - String : Existing File : Symlink true
 #  2 - String : Existing File : Symlink false
@@ -125,10 +128,37 @@ proc testGetFileInfo =
       echo pcLinkToDir
       echo pcLinkToFile
 
+    doAssert dirInfo.isSpecial == false
+    doAssert fileInfo.isSpecial == false
+    when defined(posix):
+      doAssert linkDirInfo.isSpecial == false
+      doAssert linkFileInfo.isSpecial == false
+
     removeDir(dirPath)
     removeFile(filePath)
     when defined(posix):
       removeFile(linkDirPath)
       removeFile(linkFilePath)
 
+  # Test that `isSpecial` is set correctly
+  block:
+    when defined(posix):
+      let
+        tmp = getTempDir()
+        fifoPath     = tmp / "test-fifo"
+        linkFifoPath = tmp / "test-link-fifo"
+
+      doAssert execShellCmd("mkfifo " & fifoPath) == 0
+      createSymlink(fifoPath, linkFifoPath)
+
+      let
+        fifoInfo = getFileInfo(fifoPath)
+        linkFifoInfo = getFileInfo(linkFifoPath)
+
+      doAssert fifoInfo.isSpecial == true
+      doAssert linkFifoInfo.isSpecial == true
+
+      removeFile(fifoPath)
+      removeFile(linkFifoPath)
+
 testGetFileInfo()
diff --git a/tests/stdlib/tgetprotobyname.nim b/tests/stdlib/tgetprotobyname.nim
index b4df05102..1fc060ffe 100644
--- a/tests/stdlib/tgetprotobyname.nim
+++ b/tests/stdlib/tgetprotobyname.nim
@@ -1,18 +1,9 @@
 discard """
-  cmd:      "nim c -r --styleCheck:hint --panics:on $options $file"
-  targets:  "c"
-  nimout:   ""
-  action:   "run"
-  exitcode: 0
-  timeout:  60.0
+  matrix: "--mm:refc; --mm:orc"
 """
 
 import nativesockets
-
-
-when not defined(netbsd):
-  # Ref: https://github.com/nim-lang/Nim/issues/15452 - NetBSD doesn't define an `ip` protocol
-  doAssert getProtoByName("ip") == 0
+import std/assertions
 
 doAssert getProtoByName("ipv6") == 41
 doAssert getProtoByName("tcp") == 6
diff --git a/tests/stdlib/tglobs.nim b/tests/stdlib/tglobs.nim
new file mode 100644
index 000000000..4aa21992c
--- /dev/null
+++ b/tests/stdlib/tglobs.nim
@@ -0,0 +1,25 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/private/globs
+import std/assertions
+
+template main =
+  when defined(windows):
+    doAssert nativeToUnixPath("C:") == "/C"
+    doAssert nativeToUnixPath(r"D:\") == "/D/"
+    doAssert nativeToUnixPath(r"E:\a") == "/E/a"
+    doAssert nativeToUnixPath(r"E:\a1\") == "/E/a1/"
+    doAssert nativeToUnixPath(r"E:\a1\bc") == "/E/a1/bc"
+    doAssert nativeToUnixPath(r"\a1\bc") == "/a1/bc"
+    doAssert nativeToUnixPath(r"a1\bc") == "a1/bc"
+    doAssert nativeToUnixPath("a1") == "a1"
+    doAssert nativeToUnixPath("") == ""
+    doAssert nativeToUnixPath(".") == "."
+    doAssert nativeToUnixPath("..") == ".."
+    doAssert nativeToUnixPath(r"..\") == "../"
+    doAssert nativeToUnixPath(r"..\..\.\") == "../.././"
+
+static: main()
+main()
diff --git a/tests/stdlib/thashes.nim b/tests/stdlib/thashes.nim
index a4487c8c0..4555fbcb3 100644
--- a/tests/stdlib/thashes.nim
+++ b/tests/stdlib/thashes.nim
@@ -1,9 +1,10 @@
 discard """
-  targets: "c cpp js"
+  matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:on; --backend:c -d:nimStringHash2; --backend:cpp -d:nimStringHash2; --backend:js -d:nimStringHash2"
 """
 
 import std/hashes
-
+from stdtest/testutils import disableVm, whenVMorJs
+import std/assertions
 
 when not defined(js) and not defined(cpp):
   block:
@@ -28,6 +29,10 @@ block hashes:
     const wy123 = hashWangYi1(123)
     doAssert wy123 != 0
     doAssert hashWangYi1(123) == wy123
+    const wyNeg123 = hashWangYi1(-123)
+    doAssert wyNeg123 != 0
+    when not defined(js): # TODO: fixme it doesn't work for JS
+      doAssert hashWangYi1(-123) == wyNeg123
 
 
   # "hashIdentity value incorrect at 456"
@@ -41,20 +46,31 @@ block hashes:
     else:
       doAssert hashWangYi1(456) == -6421749900419628582
 
+template jsNoInt64: untyped =
+  when defined js:
+    when compiles(compileOption("jsbigint64")):
+      when not compileOption("jsbigint64"): true
+      else: false
+    else: false
+  else: false
+const sHash2 = (when defined(nimStringHash2) or jsNoInt64(): true else: false)
+
 block empty:
+  const emptyStrHash = # Hash=int=4B on js even w/--jsbigint64:on => cast[Hash]
+    when sHash2: 0 else: cast[Hash](-7286425919675154353i64)
   var
     a = ""
     b = newSeq[char]()
     c = newSeq[int]()
     d = cstring""
     e = "abcd"
-  doAssert hash(a) == 0
-  doAssert hash(b) == 0
+  doAssert hash(a) == emptyStrHash
+  doAssert hash(b) == emptyStrHash
   doAssert hash(c) == 0
-  doAssert hash(d) == 0
+  doAssert hash(d) == emptyStrHash
   doAssert hashIgnoreCase(a) == 0
   doAssert hashIgnoreStyle(a) == 0
-  doAssert hash(e, 3, 2) == 0
+  doAssert hash(e, 3, 2) == emptyStrHash
 
 block sameButDifferent:
   doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13)
@@ -87,7 +103,11 @@ block largeSize: # longer than 4 characters
 
 proc main() =
   doAssert hash(0.0) == hash(0)
-  doAssert hash(cstring"abracadabra") == 97309975
+  # bug #16061
+  when not sHash2: # Hash=int=4B on js even w/--jsbigint64:on => cast[Hash]
+    doAssert hash(cstring"abracadabra") == cast[Hash](-1119910118870047694i64)
+  else:
+    doAssert hash(cstring"abracadabra") == 97309975
   doAssert hash(cstring"abracadabra") == hash("abracadabra")
 
   when sizeof(int) == 8 or defined(js):
@@ -176,5 +196,47 @@ proc main() =
     doAssert hash(Obj5(t: false, x: 1)) == hash(Obj5(t: true, y: 1))
     doAssert hash(Obj5(t: false, x: 1)) != hash(Obj5(t: true, y: 2))
 
+  block: # hash(ref|ptr|pointer)
+    var a: array[10, uint8]
+    # disableVm:
+    whenVMorJs:
+      # pending fix proposed in https://github.com/nim-lang/Nim/issues/15952#issuecomment-786312417
+      discard
+    do:
+      doAssert a[0].addr.hash != a[1].addr.hash
+      doAssert cast[pointer](a[0].addr).hash == a[0].addr.hash
+
+  block: # hash(ref)
+    type A = ref object
+      x: int
+    let a = A(x: 3)
+    disableVm: # xxx Error: VM does not support 'cast' from tyRef to tyPointer
+      let ha = a.hash
+      doAssert ha != A(x: 3).hash # A(x: 3) is a different ref object from `a`.
+      a.x = 4
+      doAssert ha == a.hash # the hash only depends on the address
+
+  block: # hash(proc)
+    proc fn(a: int): auto = a*2
+    doAssert fn isnot "closure"
+    doAssert fn is (proc)
+    const fn2 = fn
+    let fn3 = fn
+    whenVMorJs: discard
+    do:
+      doAssert hash(fn2) == hash(fn)
+      doAssert hash(fn3) == hash(fn)
+
+  block: # hash(closure)
+    proc outer() =
+      var a = 0
+      proc inner() = a.inc
+      doAssert inner is "closure"
+      let inner2 = inner
+      whenVMorJs: discard
+      do:
+        doAssert hash(inner2) == hash(inner)
+    outer()
+
 static: main()
 main()
diff --git a/tests/stdlib/theapqueue.nim b/tests/stdlib/theapqueue.nim
index 3b68166af..afb09c7e3 100644
--- a/tests/stdlib/theapqueue.nim
+++ b/tests/stdlib/theapqueue.nim
@@ -1,5 +1,9 @@
-import std/heapqueue
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
 
+import std/heapqueue
+import std/assertions
 
 proc toSortedSeq[T](h: HeapQueue[T]): seq[T] =
   var tmp = h
diff --git a/tests/stdlib/thighlite.nim b/tests/stdlib/thighlite.nim
new file mode 100644
index 000000000..0cd334254
--- /dev/null
+++ b/tests/stdlib/thighlite.nim
@@ -0,0 +1,45 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import unittest, strutils
+import ../../lib/packages/docutils/highlite
+import std/objectdollar
+
+block: # Nim tokenizing
+  test "string literals and escape seq":
+    check("\"ok1\\nok2\\nok3\"".tokenize(langNim) ==
+       @[("\"ok1", gtStringLit), ("\\n", gtEscapeSequence), ("ok2", gtStringLit),
+         ("\\n", gtEscapeSequence), ("ok3\"", gtStringLit)
+      ])
+    check("\"\"\"ok1\\nok2\\nok3\"\"\"".tokenize(langNim) ==
+       @[("\"\"\"ok1\\nok2\\nok3\"\"\"", gtLongStringLit)
+      ])
+
+  test "whitespace at beginning of line is preserved":
+    check("  discard 1".tokenize(langNim) ==
+       @[("  ", gtWhitespace), ("discard", gtKeyword), (" ", gtWhitespace),
+         ("1", gtDecNumber)
+       ])
+
+block: # Cmd (shell) tokenizing
+  test "cmd with dollar and output":
+    check(
+      dedent"""
+        $ nim c file.nim
+        out: file [SuccessX]"""
+        .tokenize(langConsole) ==
+      @[("$ ", gtPrompt), ("nim", gtProgram),
+        (" ", gtWhitespace), ("c", gtOption), (" ", gtWhitespace),
+        ("file.nim", gtIdentifier), ("\n", gtWhitespace),
+        ("out: file [SuccessX]", gtProgramOutput)
+      ])
+
+block: # bug #21232
+  let code = "/"
+  var toknizr: GeneralTokenizer
+
+  initGeneralTokenizer(toknizr, code)
+
+  getNextToken(toknizr, langC)
+  check $toknizr == """(kind: gtOperator, start: 0, length: 1, buf: "/", pos: 1, state: gtEof, lang: langC)"""
diff --git a/tests/stdlib/thtmlparser.nim b/tests/stdlib/thtmlparser.nim
index f35785b25..853a1c0cc 100644
--- a/tests/stdlib/thtmlparser.nim
+++ b/tests/stdlib/thtmlparser.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
   output: '''
 true
@@ -11,7 +12,7 @@ import htmlparser
 import xmltree
 import strutils
 from streams import newStringStream
-
+import std/assertions
 
 block t2813:
   const
diff --git a/tests/stdlib/thttpclient.nim b/tests/stdlib/thttpclient.nim
index e81590d95..0bd479670 100644
--- a/tests/stdlib/thttpclient.nim
+++ b/tests/stdlib/thttpclient.nim
@@ -14,6 +14,9 @@ from net import TimeoutError
 
 import nativesockets, os, httpclient, asyncdispatch
 
+import std/[assertions, syncio]
+from stdtest/testutils import enableRemoteNetworking
+
 const manualTests = false
 
 proc makeIPv6HttpServer(hostname: string, port: Port,
@@ -21,7 +24,7 @@ proc makeIPv6HttpServer(hostname: string, port: Port,
   let fd = createNativeSocket(AF_INET6)
   setSockOptInt(fd, SOL_SOCKET, SO_REUSEADDR, 1)
   var aiList = getAddrInfo(hostname, port, AF_INET6)
-  if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
+  if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.SockLen) < 0'i32:
     freeAddrInfo(aiList)
     raiseOSError(osLastError())
   freeAddrInfo(aiList)
@@ -50,12 +53,13 @@ proc asyncTest() {.async.} =
   doAssert("<title>Example Domain</title>" in body)
 
   resp = await client.request("http://example.com/404")
-  doAssert(resp.code.is4xx)
-  doAssert(resp.code == Http404)
-  doAssert(resp.status == $Http404)
+  doAssert(resp.code.is4xx or resp.code.is5xx)
+  doAssert(resp.code == Http404 or resp.code == Http500)
+  doAssert(resp.status == $Http404 or resp.status == $Http500)
 
-  resp = await client.request("https://google.com/")
-  doAssert(resp.code.is2xx or resp.code.is3xx)
+  when false: # occasionally does not give success code 
+    resp = await client.request("https://google.com/")
+    doAssert(resp.code.is2xx or resp.code.is3xx)
 
   # getContent
   try:
@@ -111,12 +115,13 @@ proc syncTest() =
   doAssert("<title>Example Domain</title>" in resp.body)
 
   resp = client.request("http://example.com/404")
-  doAssert(resp.code.is4xx)
-  doAssert(resp.code == Http404)
-  doAssert(resp.status == $Http404)
+  doAssert(resp.code.is4xx or resp.code.is5xx)
+  doAssert(resp.code == Http404 or resp.code == Http500)
+  doAssert(resp.status == $Http404 or resp.status == $Http500)
 
-  resp = client.request("https://google.com/")
-  doAssert(resp.code.is2xx or resp.code.is3xx)
+  when false: # occasionally does not give success code
+    resp = client.request("https://google.com/")
+    doAssert(resp.code.is2xx or resp.code.is3xx)
 
   # getContent
   try:
@@ -176,5 +181,7 @@ proc ipv6Test() =
   client.close()
 
 ipv6Test()
-syncTest()
-waitFor(asyncTest())
+
+when enableRemoteNetworking:
+  syncTest()
+  waitFor(asyncTest())
diff --git a/tests/stdlib/thttpclient_ssl.nim b/tests/stdlib/thttpclient_ssl.nim
index 1c531eae9..6b963f029 100644
--- a/tests/stdlib/thttpclient_ssl.nim
+++ b/tests/stdlib/thttpclient_ssl.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim $target --threads:on -d:ssl $options $file"
+  cmd: "nim $target --mm:refc -d:ssl $options $file"
   disabled: "openbsd"
 """
 
@@ -13,9 +13,12 @@ discard """
 ## Test with:
 ## ./bin/nim c -d:ssl -p:. --threads:on -r tests/stdlib/thttpclient_ssl.nim
 
-when not defined(windows):
-  # Disabled on Windows due to old OpenSSL version
 
+from stdtest/testutils import disableSSLTesting
+
+when not defined(windows) and not disableSSLTesting():
+  # Disabled on Windows due to old OpenSSL version
+  import std/[formatfloat, syncio]
   import
     httpclient,
     net,
@@ -129,3 +132,19 @@ when not defined(windows):
           msg.contains("certificate verify failed")):
           echo "CVerifyPeer exception: " & msg
           check(false)
+
+    test "HttpClient with CVerifyPeerUseEnvVars":
+      const port = 12346.Port
+      let t = spawn runServer(port)
+      sleep(100)
+
+      putEnv("SSL_CERT_FILE", getCurrentDir() / certFile)
+      var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeerUseEnvVars))
+      try:
+        log "client: connect"
+        discard client.getContent("https://127.0.0.1:12346")
+      except:
+        let msg = getCurrentExceptionMsg()
+        log "client: exception: " & msg
+        log "getContent should not have raised an exception"
+        fail()
diff --git a/tests/stdlib/thttpclient_standalone.nim b/tests/stdlib/thttpclient_standalone.nim
index 44a88e91e..2f432eede 100644
--- a/tests/stdlib/thttpclient_standalone.nim
+++ b/tests/stdlib/thttpclient_standalone.nim
@@ -2,22 +2,58 @@ discard """
   cmd: "nim c --threads:on $file"
 """
 
-import asynchttpserver, httpclient, asyncdispatch
+import asynchttpserver, httpclient, asyncdispatch, strutils, net
+
+import std/assertions
 
 block: # bug #16436
-  proc startServer() {.async.} =
+  proc startServer(): AsyncHttpServer =
+    result = newAsyncHttpServer()
+    result.listen(Port(0))
+
+  proc processRequest(server: AsyncHttpServer) {.async.} =
     proc cb(req: Request) {.async.} =
       let headers = { "Content-length": "15"} # Provide invalid content-length
       await req.respond(Http200, "Hello World", headers.newHttpHeaders())
 
-    var server = newAsyncHttpServer()
-    await server.serve(Port(5555), cb)
+    await server.acceptRequest(cb)
 
-  proc runClient() {.async.} =
+  proc runClient(port: Port) {.async.} =
     let c = newAsyncHttpClient(headers = {"Connection": "close"}.newHttpHeaders)
-    let r = await c.getContent("http://127.0.0.1:5555")
+    discard await c.getContent("http://127.0.0.1:" & $port)
     doAssert false, "should fail earlier"
 
-  asyncCheck startServer()
+  let server = startServer()
+  asyncCheck processRequest(server)
+  let port = server.getPort()
   doAssertRaises(ProtocolError):
-    waitFor runClient()
+    waitFor runClient(port)
+
+block: # bug #14794 (And test for presence of content-length header when using postContent)
+  proc startServer(): AsyncHttpServer =
+    result = newAsyncHttpServer()
+    result.listen(Port(0))
+
+  proc runServer(server: AsyncHttpServer) {.async.} =
+    proc cb(req: Request) {.async.} =
+      doAssert(req.body.endsWith(httpNewLine), "Multipart body does not end with a newline.")
+      # this next line is probably not required because asynchttpserver does not call
+      # the callback when there is no content-length header.  It instead errors with 
+      # Error: unhandled exception: 411 Length Required
+      # Added for good measure in case the server becomes more permissive.
+      doAssert(req.headers.hasKey("content-length"), "Content-Length header is not present.")
+      asyncCheck req.respond(Http200, "OK")
+
+    await server.acceptRequest(cb)
+
+  proc runClient(port: Port) {.async.} =
+    let c = newAsyncHttpClient()
+    let data = newMultipartData()
+    data.add("file.txt", "This is intended to be an example text file.\r\nThis would be the second line.\r\n")
+    discard await c.postContent("http://127.0.0.1:" & $port, multipart = data)
+    c.close()
+
+  let server = startServer()
+  let port = server.getPort()
+  asyncCheck runServer(server)
+  waitFor runClient(port)
diff --git a/tests/stdlib/thttpcore.nim b/tests/stdlib/thttpcore.nim
index 6f88e9536..93e7d85c6 100644
--- a/tests/stdlib/thttpcore.nim
+++ b/tests/stdlib/thttpcore.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import httpcore, strutils
+import std/assertions
 
 block:
   block HttpCode:
diff --git a/tests/stdlib/timportutils.nim b/tests/stdlib/timportutils.nim
new file mode 100644
index 000000000..672092282
--- /dev/null
+++ b/tests/stdlib/timportutils.nim
@@ -0,0 +1,151 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/[importutils, assertions]
+import stdtest/testutils
+import mimportutils
+
+template main =
+  block: # privateAccess
+    assertAll:
+      var a: A
+      var b = initB() # B is private
+      compiles(a.a0)
+      compiles(b.b0)
+      not compiles(a.ha1)
+      not compiles(b.hb1)
+
+    block:
+      assertAll:
+        privateAccess A
+        compiles(a.ha1)
+        a.ha1 == 0.0
+        not compiles(a.hb1)
+        privateAccess b.typeof
+        b.hb1 = 3
+        type B2 = b.typeof
+        let b2 = B2(b0: 4, hb1: 5)
+        b.hb1 == 3
+        b2 == B2(b0: 4, hb1: 5)
+
+    assertAll:
+      not compiles(a.ha1)
+      not compiles(b.hb1)
+
+    block:
+      assertAll:
+        not compiles(C(c0: 1, hc1: 2))
+        privateAccess C
+        let c = C(c0: 1, hc1: 2)
+        c.hc1 == 2
+
+    block:
+      assertAll:
+        not compiles(E[int](he1: 1))
+        privateAccess E[int]
+        var e = E[int](he1: 1)
+        e.he1 == 1
+        e.he1 = 2
+        e.he1 == 2
+        e.he1 += 3
+        e.he1 == 5
+        # xxx caveat: this currently compiles but in future, we may want
+        # to make `privateAccess E[int]` only affect a specific instantiation;
+        # note that `privateAccess E` does work to cover all instantiations.
+        var e2 = E[float](he1: 1)
+
+    block:
+      assertAll:
+        not compiles(E[int](he1: 1))
+        privateAccess E
+        var e = E[int](he1: 1)
+        e.he1 == 1
+
+    block:
+      assertAll:
+        not compiles(F[int, int](h3: 1))
+        privateAccess F[int, int]
+        var e = F[int, int](h3: 1)
+        e.h3 == 1
+
+    block:
+      assertAll:
+        not compiles(F[int, int](h3: 1))
+        privateAccess F[int, int].default[].typeof
+        var e = F[int, int](h3: 1)
+        e.h3 == 1
+
+    block:
+      assertAll:
+        var a = G[int]()
+        var b = a.addr
+        privateAccess b.type
+        discard b.he1
+        discard b[][].he1
+
+    block:
+      assertAll:
+        privateAccess H[int]
+        var a = H[int](h5: 2)
+
+    block:
+      assertAll:
+        privateAccess PA
+        var pa = PA(a0: 1, ha1: 2)
+        pa.ha1 == 2
+        pa.ha1 = 3
+        pa.ha1 == 3
+
+    block:
+      assertAll:
+        var b = BAalias()
+        not compiles(b.hb1)
+        privateAccess BAalias
+        discard b.hb1
+
+    block:
+      assertAll:
+        var a = A(a0: 1)
+        var a2 = a.addr
+        not compiles(a2.ha1)
+        privateAccess PtA
+        a2.type is PtA
+        a2.ha1 = 2
+        a2.ha1 == 2
+        a.ha1 = 3
+        a2.ha1 == 3
+
+    block:
+      disableVm:
+        assertAll:
+          var a = A.create()
+          defer: dealloc(a)
+          a is PtA
+          a.typeof is PtA
+          not compiles(a.ha1)
+          privateAccess a.typeof
+          a.ha1 = 2
+          a.ha1 == 2
+          a[].ha1 = 3
+          a.ha1 == 3
+
+    block:
+      disableVm:
+        assertAll:
+          var a = A.create()
+          defer: dealloc(a)
+          privateAccess PtA
+          a.ha1 == 0
+
+    block:
+      privateAccess PityRef
+      let x = PityRef[int](a: 1)  # works
+      doAssert x.a == 1
+
+      privateAccess Hope
+      let y = Hope[int](a: 1)
+      doAssert y.a == 1
+
+static: main()
+main()
diff --git a/tests/stdlib/tio.nim b/tests/stdlib/tio.nim
index 0da64f9c2..80a119763 100644
--- a/tests/stdlib/tio.nim
+++ b/tests/stdlib/tio.nim
@@ -1,7 +1,12 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 # xxx move to here other tests that belong here; io is a proper module
 
 import std/os
 from stdtest/specialpaths import buildDir
+import std/[assertions, syncio]
 
 block: # readChars
   let file = buildDir / "D20201118T205105.txt"
@@ -35,3 +40,21 @@ block: # readChars
         break
     doAssert n2s == @[2,2,2,1,0]
     doAssert s2 == s
+
+
+import std/strutils
+
+block: # bug #21273
+  let FILE = buildDir / "D20220119T134305.txt"
+
+  let hex = "313632313920313632343720313632353920313632363020313632393020323035363520323037323120323131353020323239393820323331303520323332313020323332343820323332363820"
+
+
+  writeFile FILE, parseHexStr(hex)
+
+  doAssert readFile(FILE).toHex == hex
+
+  let f = open(FILE)
+  var s = newString(80)
+  while f.readLine(s):
+    doAssert s.toHex == hex
diff --git a/tests/stdlib/tisolation.nim b/tests/stdlib/tisolation.nim
index 11c51fe05..18b83ea2e 100644
--- a/tests/stdlib/tisolation.nim
+++ b/tests/stdlib/tisolation.nim
@@ -4,71 +4,91 @@ discard """
 """
 
 import std/[isolation, json]
+import std/[assertions, objectdollar]
 
 
+proc main(moveZeroesOut: static bool) =
+  block:
+    type
+      Empty = ref object
+
+
+    var x = isolate(Empty())
+    discard extract(x)
 
-proc main() =
   block: # string literals
     var data = isolate("string")
     doAssert data.extract == "string"
-    doAssert data.extract == ""
+    if moveZeroesOut:
+      doAssert data.extract == ""
 
   block: # string literals
     var data = isolate("")
     doAssert data.extract == ""
-    doAssert data.extract == ""
+    if moveZeroesOut:
+      doAssert data.extract == ""
 
   block:
     var src = "string"
     var data = isolate(move src)
     doAssert data.extract == "string"
-    doAssert src.len == 0
+    if moveZeroesOut:
+      doAssert src.len == 0
 
   block: # int literals
     var data = isolate(1)
     doAssert data.extract == 1
-    doAssert data.extract == 0
+    if moveZeroesOut:
+      doAssert data.extract == 0
 
   block: # float literals
     var data = isolate(1.6)
     doAssert data.extract == 1.6
-    doAssert data.extract == 0.0
+    if moveZeroesOut:
+      doAssert data.extract == 0.0
 
   block:
     var data = isolate(@["1", "2"])
     doAssert data.extract == @["1", "2"]
-    doAssert data.extract == @[]
+    if moveZeroesOut:
+      doAssert data.extract == @[]
 
   block:
     var data = isolate(@["1", "2", "3", "4", "5"])
     doAssert data.extract == @["1", "2", "3", "4", "5"]
-    doAssert data.extract == @[]
+    if moveZeroesOut:
+      doAssert data.extract == @[]
 
   block:
     var data = isolate(@["", ""])
     doAssert data.extract == @["", ""]
-    doAssert data.extract == @[]
+    if moveZeroesOut:
+      doAssert data.extract == @[]
 
   block:
     var src = @["1", "2"]
     var data = isolate(move src)
     doAssert data.extract == @["1", "2"]
-    doAssert src.len == 0
+    if moveZeroesOut:
+      doAssert src.len == 0
 
   block:
     var data = isolate(@[1, 2])
     doAssert data.extract == @[1, 2]
-    doAssert data.extract == @[]
+    if moveZeroesOut:
+      doAssert data.extract == @[]
 
   block:
     var data = isolate(["1", "2"])
     doAssert data.extract == ["1", "2"]
-    doAssert data.extract == ["", ""]
+    if moveZeroesOut:
+      doAssert data.extract == ["", ""]
 
   block:
     var data = isolate([1, 2])
     doAssert data.extract == [1, 2]
-    doAssert data.extract == [0, 0]
+    if moveZeroesOut:
+      doAssert data.extract == [0, 0]
 
   block:
     type
@@ -111,5 +131,5 @@ proc main() =
     doAssert $x == """@[(value: "1234")]"""
 
 
-static: main()
-main()
+static: main(moveZeroesOut = false)
+main(moveZeroesOut = true)
diff --git a/tests/stdlib/tjsbigints.nim b/tests/stdlib/tjsbigints.nim
index 34c5ddfbf..29b0ac3e7 100644
--- a/tests/stdlib/tjsbigints.nim
+++ b/tests/stdlib/tjsbigints.nim
@@ -2,7 +2,7 @@ discard """
   targets: "js"
 """
 
-import std/jsbigints
+import std/[jsbigints, assertions]
 
 
 let big1: JsBigInt = big"2147483647"
@@ -26,7 +26,7 @@ doAssert big1.toCstring(10) == "2147483647".cstring
 doAssert big2 ** big3 == big(443556)
 var huge = big"999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
 huge.inc
-huge = huge + big"-999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
+huge = huge + -999999999999999999999999999999999999999999999999999999999999999999999999999999999999999'big
 doAssert huge == big"1"
 var list: seq[JsBigInt]
 for i in big"0" .. big"5":
@@ -40,7 +40,7 @@ for i in big"0" ..< big"5":
 doAssert list == @[big"0", big"1", big"2", big"3", big"4"]
 
 block:
-  let b = big"2"
-  doAssert -b ** big"3" == big"-8"
+  let b = 2'big
+  doAssert -b ** 3'big == -8'big
   doAssert -b ** big"2" == big"4" # not -4 because of precedence
   doAssert -big"3" == big"-3"
diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim
index ceb9efb0e..e425501f6 100644
--- a/tests/stdlib/tjson.nim
+++ b/tests/stdlib/tjson.nim
@@ -1,5 +1,5 @@
 discard """
-  targets: "c cpp js"
+  matrix: "; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
 """
 
 
@@ -8,14 +8,31 @@ Note: Macro tests are in tests/stdlib/tjsonmacro.nim
 ]#
 
 import std/[json,parsejson,strutils]
+import std/private/jsutils
+from std/math import isNaN
 when not defined(js):
   import std/streams
+import stdtest/testutils
+from std/fenv import epsilon
+import std/[assertions, objectdollar]
 
 proc testRoundtrip[T](t: T, expected: string) =
+  # checks that `T => json => T2 => json2` is such that json2 = json
   let j = %t
   doAssert $j == expected, $j
   doAssert %(j.to(T)) == j
 
+proc testRoundtripVal[T](t: T, expected: string) =
+  # similar to testRoundtrip, but also checks that the `T => json => T2` is such that `T2 == T`
+  # note that this isn't always possible, e.g. for pointer-like types or nans
+  let j = %t
+  doAssert $j == expected, $j
+  let j2 = ($j).parseJson
+  doAssert $j2 == expected, $(j2, t)
+  let t2 = j2.to(T)
+  doAssert t2 == t
+  doAssert $(%* t2) == expected # sanity check, because -0.0 = 0.0 but their json representation differs
+
 let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd", "c": "\ud83c\udf83", "d": "\u00E6"}"""
 # nil passthrough
 doAssert(testJson{"doesnt_exist"}{"anything"}.isNil)
@@ -297,6 +314,69 @@ block: # bug #17383
   else:
     testRoundtrip(int.high): "9223372036854775807"
     testRoundtrip(uint.high): "18446744073709551615"
-  when not defined(js):
+  whenJsNoBigInt64: discard
+  do:
     testRoundtrip(int64.high): "9223372036854775807"
     testRoundtrip(uint64.high): "18446744073709551615"
+
+block: # bug #18007
+  testRoundtrip([NaN, Inf, -Inf, 0.0, -0.0, 1.0]): """["nan","inf","-inf",0.0,-0.0,1.0]"""
+  # pending https://github.com/nim-lang/Nim/issues/18025 use:
+  # testRoundtrip([float32(NaN), Inf, -Inf, 0.0, -0.0, 1.0])
+  let inf = float32(Inf)
+  testRoundtrip([float32(NaN), inf, -inf, 0.0, -0.0, 1.0]): """["nan","inf","-inf",0.0,-0.0,1.0]"""
+  when not defined(js): # because of Infinity vs inf
+    testRoundtripVal([inf, -inf, 0.0, -0.0, 1.0]): """["inf","-inf",0.0,-0.0,1.0]"""
+  let a = parseJson($(%NaN)).to(float)
+  doAssert a.isNaN
+
+  whenRuntimeJs: discard # refs bug #18009
+  do:
+    testRoundtripVal(0.0): "0.0"
+    testRoundtripVal(-0.0): "-0.0"
+
+block: # bug #15397, bug #13196
+  testRoundtripVal(1.0 + epsilon(float64)): "1.0000000000000002"
+  testRoundtripVal(0.12345678901234567890123456789): "0.12345678901234568"
+
+block:
+  let a = "18446744073709551615"
+  let b = a.parseJson
+  doAssert b.kind == JString
+  let c = $b
+  when defined(js):
+    doAssert c == "18446744073709552000"
+  else:
+    doAssert c == "18446744073709551615"
+
+block:
+  let a = """
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
+"""
+
+  when not defined(js):
+    try:
+      discard parseJson(a)
+    except JsonParsingError:
+      doAssert getCurrentExceptionMsg().contains("] expected")
diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim
index 779c0ce65..5a1b4b294 100644
--- a/tests/stdlib/tjsonmacro.nim
+++ b/tests/stdlib/tjsonmacro.nim
@@ -1,9 +1,11 @@
 discard """
   output: ""
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import json, strutils, options, tables
+import std/assertions
 
 # The definition of the `%` proc needs to be here, since the `% c` calls below
 # can only find our custom `%` proc for `Pix` if defined in global scope.
@@ -259,7 +261,7 @@ proc testJson() =
         colors: array[2, BirdColor]
 
     var red = BirdColor(name: "red", rgb: [1.0, 0.0, 0.0])
-    var blue = Birdcolor(name: "blue", rgb: [0.0, 0.0, 1.0])
+    var blue = BirdColor(name: "blue", rgb: [0.0, 0.0, 1.0])
     var b = Bird(age: 3, height: 1.734, name: "bardo", colors: [red, blue])
     let jnode = %b
     let data = jnode.to(Bird)
@@ -435,11 +437,7 @@ proc testJson() =
   block:
     let s = """{"a": 1, "b": 2}"""
     let t = parseJson(s).to(Table[string, int])
-    when not defined(js):
-      # For some reason on the JS backend `{"b": 2, "a": 0}` is
-      # sometimes the value of `t`. This needs investigation. I can't
-      # reproduce it right now in an isolated test.
-      doAssert t["a"] == 1
+    doAssert t["a"] == 1
     doAssert t["b"] == 2
 
   block:
@@ -497,7 +495,7 @@ proc testJson() =
     doAssert array[3, float](t.arr) == [1.0,2.0,7.0]
 
     doAssert MyRef(t.person).name == "boney"
-    doAssert MyObj(t.distFruit).color == 11
+    doAssert MyObj(t.distfruit).color == 11
     doAssert t.dog.name == "honey"
     doAssert t.fruit.color == 10
     doAssert seq[string](t.emails) == @["abc", "123"]
diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim
index 5cd975cab..9acf4c9e5 100644
--- a/tests/stdlib/tjsonutils.nim
+++ b/tests/stdlib/tjsonutils.nim
@@ -1,19 +1,37 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c cpp js"
 """
 
 import std/jsonutils
 import std/json
+from std/math import isNaN, signbit
+from std/fenv import epsilon
+from stdtest/testutils import whenRuntimeJs
+import std/[assertions, objectdollar]
 
 proc testRoundtrip[T](t: T, expected: string) =
+  # checks that `T => json => T2 => json2` is such that json2 = json
   let j = t.toJson
-  doAssert $j == expected, $j
+  doAssert $j == expected, "\n" & $j & "\n" & expected
   doAssert j.jsonTo(T).toJson == j
   var t2: T
   t2.fromJson(j)
   doAssert t2.toJson == j
 
+proc testRoundtripVal[T](t: T, expected: string) =
+  # similar to testRoundtrip, but also checks that the `T => json => T2` is such that `T2 == T`
+  # note that this isn't always possible, e.g. for pointer-like types.
+  let j = t.toJson
+  let j2 = $j
+  doAssert j2 == expected, j2
+  let j3 = j2.parseJson
+  let t2 = j3.jsonTo(T)
+  doAssert t2 == t
+  doAssert $t2.toJson == j2 # still needed, because -0.0 = 0.0 but their json representation differs
+
 import tables, sets, algorithm, sequtils, options, strtabs
+from strutils import contains
 
 type Foo = ref object
   id: int
@@ -21,7 +39,14 @@ type Foo = ref object
 proc `==`(a, b: Foo): bool =
   a.id == b.id
 
-template fn() = 
+type MyEnum = enum me0, me1 = "me1Alt", me2, me3, me4
+
+proc `$`(a: MyEnum): string =
+  # putting this here pending https://github.com/nim-lang/Nim/issues/13747
+  if a == me2: "me2Modif"
+  else: system.`$`(a)
+
+template fn() =
   block: # toJson, jsonTo
     type Foo = distinct float
     testRoundtrip('x', """120""")
@@ -36,42 +61,77 @@ template fn() =
         testRoundtrip(pointer(nil)): """0"""
         testRoundtrip(cast[pointer](nil)): """0"""
 
-    # causes workaround in `fromJson` potentially related to
-    # https://github.com/nim-lang/Nim/issues/12282
+    # refs bug #9423
     testRoundtrip(Foo(1.5)): """1.5"""
 
-  block:
+  block: # OrderedTable
     testRoundtrip({"z": "Z", "y": "Y"}.toOrderedTable): """{"z":"Z","y":"Y"}"""
+    doAssert toJson({"z": 10, "": 11}.newTable).`$`.contains """"":11""" # allows hash to change
+    testRoundtrip({"z".cstring: 1, "".cstring: 2}.toOrderedTable): """{"z":1,"":2}"""
     testRoundtrip({"z": (f1: 'f'), }.toTable): """{"z":{"f1":102}}"""
 
-  block:
+  block: # StringTable
     testRoundtrip({"name": "John", "city": "Monaco"}.newStringTable): """{"mode":"modeCaseSensitive","table":{"city":"Monaco","name":"John"}}"""
 
   block: # complex example
     let t = {"z": "Z", "y": "Y"}.newStringTable
     type A = ref object
       a1: string
-    let a = (1.1, "fo", 'x', @[10,11], [true, false], [t,newStringTable()], [0'i8,3'i8], -4'i16, (foo: 0.5'f32, bar: A(a1: "abc"), bar2: A.default))
+    let a = (1.1, "fo", 'x', @[10,11], [true, false], [t,newStringTable()], [0'i8,3'i8], -4'i16, (foo: 0.5'f32, bar: A(a1: "abc"), bar2: A.default, cstring1: "foo", cstring2: "", cstring3: cstring(nil)))
     testRoundtrip(a):
-      """[1.1,"fo",120,[10,11],[true,false],[{"mode":"modeCaseSensitive","table":{"y":"Y","z":"Z"}},{"mode":"modeCaseSensitive","table":{}}],[0,3],-4,{"foo":0.5,"bar":{"a1":"abc"},"bar2":null}]"""
+      """[1.1,"fo",120,[10,11],[true,false],[{"mode":"modeCaseSensitive","table":{"y":"Y","z":"Z"}},{"mode":"modeCaseSensitive","table":{}}],[0,3],-4,{"foo":0.5,"bar":{"a1":"abc"},"bar2":null,"cstring1":"foo","cstring2":"","cstring3":null}]"""
 
   block:
     # edge case when user defined `==` doesn't handle `nil` well, e.g.:
     # https://github.com/nim-lang/nimble/blob/63695f490728e3935692c29f3d71944d83bb1e83/src/nimblepkg/version.nim#L105
     testRoundtrip(@[Foo(id: 10), nil]): """[{"id":10},null]"""
 
-  block:
+  block: # enum
     type Foo = enum f1, f2, f3, f4, f5
     type Bar = enum b1, b2, b3, b4
     let a = [f2: b2, f3: b3, f4: b4]
     doAssert b2.ord == 1 # explains the `1`
     testRoundtrip(a): """[1,2,3]"""
 
+  block: # JsonNode
+    let a = ((1, 2.5, "abc").toJson, (3, 4.5, "foo"))
+    testRoundtripVal(a): """[[1,2.5,"abc"],[3,4.5,"foo"]]"""
+
+    block:
+      template toInt(a): untyped = cast[int](a)
+
+      let a = 3.toJson
+      let b = (a, a)
+
+      let c1 = b.toJson
+      doAssert c1[0].toInt == a.toInt
+      doAssert c1[1].toInt == a.toInt
+
+      let c2 = b.toJson(ToJsonOptions(jsonNodeMode: joptJsonNodeAsCopy))
+      doAssert c2[0].toInt != a.toInt
+      doAssert c2[1].toInt != c2[0].toInt
+      doAssert c2[1] == c2[0]
+
+      let c3 = b.toJson(ToJsonOptions(jsonNodeMode: joptJsonNodeAsObject))
+      doAssert $c3 == """[{"isUnquoted":false,"kind":2,"num":3},{"isUnquoted":false,"kind":2,"num":3}]"""
+
+  block: # ToJsonOptions
+    let a = (me1, me2)
+    doAssert $a.toJson() == "[1,2]"
+    doAssert $a.toJson(ToJsonOptions(enumMode: joptEnumSymbol)) == """["me1","me2"]"""
+    doAssert $a.toJson(ToJsonOptions(enumMode: joptEnumString)) == """["me1Alt","me2Modif"]"""
+
+  block: # set
+    type Foo = enum f1, f2, f3, f4, f5
+    type Goo = enum g1 = 10, g2 = 15, g3 = 17, g4
+    let a = ({f1, f3}, {1'u8, 7'u8}, {'0'..'9'}, {123'u16, 456, 789, 1121, 1122, 1542}, {g2, g3})
+    testRoundtrip(a): """[[0,2],[1,7],[48,49,50,51,52,53,54,55,56,57],[123,456,789,1121,1122,1542],[15,17]]"""
+
   block: # bug #17383
     block:
       let a = (int32.high, uint32.high)
       testRoundtrip(a): "[2147483647,4294967295]"
-    when not defined(js):
+    when int.sizeof > 4:
       block:
         let a = (int64.high, uint64.high)
         testRoundtrip(a): "[9223372036854775807,18446744073709551615]"
@@ -82,6 +142,36 @@ template fn() =
       else:
         testRoundtrip(a): "[9223372036854775807,18446744073709551615]"
 
+  block: # bug #18007
+    testRoundtrip((NaN, Inf, -Inf, 0.0, -0.0, 1.0)): """["nan","inf","-inf",0.0,-0.0,1.0]"""
+    testRoundtrip((float32(NaN), Inf, -Inf, 0.0, -0.0, 1.0)): """["nan","inf","-inf",0.0,-0.0,1.0]"""
+    testRoundtripVal((Inf, -Inf, 0.0, -0.0, 1.0)): """["inf","-inf",0.0,-0.0,1.0]"""
+    doAssert ($NaN.toJson).parseJson.jsonTo(float).isNaN
+
+  block: # bug #18009; unfixable unless we change parseJson (which would have overhead),
+         # but at least we can guarantee that the distinction between 0.0 and -0.0 is preserved.
+    let a = (0, 0.0, -0.0, 0.5, 1, 1.0)
+    testRoundtripVal(a): "[0,0.0,-0.0,0.5,1,1.0]"
+    let a2 = $($a.toJson).parseJson
+    whenRuntimeJs:
+      doAssert a2 == "[0,0,-0.0,0.5,1,1]"
+    do:
+      doAssert a2 == "[0,0.0,-0.0,0.5,1,1.0]"
+    let b = a2.parseJson.jsonTo(type(a))
+    doAssert not b[1].signbit
+    doAssert b[2].signbit
+    doAssert not b[3].signbit
+
+  block: # bug #15397, bug #13196
+    let a = 0.1
+    let x = 0.12345678901234567890123456789
+    let b = (a + 0.2, 0.3, x)
+    testRoundtripVal(b): "[0.30000000000000004,0.3,0.12345678901234568]"
+
+    testRoundtripVal(0.12345678901234567890123456789): "0.12345678901234568"
+    testRoundtripVal(epsilon(float64)): "2.220446049250313e-16"
+    testRoundtripVal(1.0 + epsilon(float64)): "1.0000000000000002"
+
   block: # case object
     type Foo = object
       x0: float
@@ -222,6 +312,18 @@ template fn() =
       doAssert guide == AboutLifeUniverseAndEverythingElse(
         question: "6*9=?", answer: 42)
 
+      block refObject: #bug 17986
+        type A = ref object
+          case is_a: bool
+          of true:
+            a: int
+          else:
+            b: int
+
+        var a = A()
+        fromJson(a, """{"is_a": true, "a":1, "extra_key": 1}""".parseJson, Joptions(allowExtraKeys: true))
+        doAssert $a[] == "(is_a: true, a: 1)"
+
     block testAllowMissingKeys:
       var guide = AboutLifeUniverseAndEverythingElse(
         question: "6*9=?", answer: 54)
@@ -308,6 +410,39 @@ template fn() =
       doAssert foo.c == 0
       doAssert foo.c0 == 42
 
+
+    block testInvalidTupleLength:
+      let json = parseJson("[0]")
+      # Should raise ValueError instead of index error
+      doAssertRaises(ValueError):
+        discard json.jsonTo((int, int))
+
+    type
+      InnerEnum = enum
+        A
+        B
+        C
+      InnerObject = object
+        x: string
+        y: InnerEnum
+
+    block testOptionsArePassedWhenDeserialising:
+      let json = parseJson("""{"x": "hello"}""")
+      let inner = json.jsonTo(Option[InnerObject], Joptions(allowMissingKeys: true))
+      doAssert inner.isSome()
+      doAssert inner.get().x == "hello"
+      doAssert inner.get().y == A
+
+    block testOptionsArePassedWhenSerialising:
+      let inner = some InnerObject(x: "hello", y: A)
+      let json = inner.toJson(ToJsonOptions(enumMode: joptEnumSymbol))
+      doAssert $json == """{"x":"hello","y":"A"}"""
+
+    block: # bug #21638
+      type Something = object
+
+      doAssert "{}".parseJson.jsonTo(Something) == Something()
+
     when false:
       ## TODO: Implement support for nested variant objects allowing the tests
       ## bellow to pass.
@@ -332,7 +467,7 @@ template fn() =
           """{"b": true, "bt": false, "btf": "test"}"""
         testRoundtrip(Variant(b: true, bt: true, btt: 'c')):
           """{"b": true, "bt": true, "btt": "c"}"""
-        
+
         # TODO: Add additional tests with missing and extra JSON keys, both when
         # allowed and forbidden analogous to the tests for the not nested
         # variant objects.
diff --git a/tests/stdlib/tlists.nim b/tests/stdlib/tlists.nim
index 54fa8b24f..5993278c7 100644
--- a/tests/stdlib/tlists.nim
+++ b/tests/stdlib/tlists.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/[lists, sequtils]
+import std/assertions
 
 const
   data = [1, 2, 3, 4, 5, 6]
@@ -233,6 +235,43 @@ template main =
     doAssert l.toSeq == [1]
     doAssert l.remove(l.head) == true
     doAssert l.toSeq == []
+  
+  block issue19297: # add (appends a shallow copy)
+    var a: SinglyLinkedList[int]
+    var b: SinglyLinkedList[int]
+
+    doAssert a.toSeq == @[]
+    a.add(1)
+    doAssert a.toSeq == @[1]
+    a.add(b)
+    doAssert a.toSeq == @[1]
+    a.add(2)
+    doAssert a.toSeq == @[1, 2]
+  
+  block issue19314: # add (appends a shallow copy)
+    var a: DoublyLinkedList[int]
+    var b: DoublyLinkedList[int]
+
+    doAssert a.toSeq == @[]
+    a.add(1)
+    doAssert a.toSeq == @[1]
+    a.add(b)
+    doAssert a.toSeq == @[1]
+    a.add(2)
+    doAssert a.toSeq == @[1, 2]
+
+  block RemoveLastNodeFromSinglyLinkedList:
+    var list = initSinglyLinkedList[string]()
+    let n1 = newSinglyLinkedNode("sonic")
+    let n2 = newSinglyLinkedNode("the")
+    let n3 = newSinglyLinkedNode("tiger")
+    let n4 = newSinglyLinkedNode("hedgehog")
+    list.add(n1)
+    list.add(n2)
+    list.add(n3)
+    list.remove(n3)
+    list.add(n4)
+    doAssert list.toSeq == @["sonic", "the", "hedgehog"]
 
 static: main()
 main()
diff --git a/tests/stdlib/tlocks.nim b/tests/stdlib/tlocks.nim
index e567cfde8..1c5f67119 100644
--- a/tests/stdlib/tlocks.nim
+++ b/tests/stdlib/tlocks.nim
@@ -1,10 +1,11 @@
 discard """
-  output: '''3'''
-  cmd: "nim $target --threads:on $options $file"
+  targets: "c cpp js"
+  matrix: "--mm:refc; --mm:orc"
 """
 
 #bug #6049
 import uselocks
+import std/assertions
 
 var m = createMyType[int]()
-echo $m.use()
+doAssert m.use() == 3
diff --git a/tests/stdlib/tlwip.nim b/tests/stdlib/tlwip.nim
index 7f7822236..fc53be592 100644
--- a/tests/stdlib/tlwip.nim
+++ b/tests/stdlib/tlwip.nim
@@ -1,6 +1,6 @@
 discard """
   targets: "c"
-  cmd: "nim $target --os:freertos --gc:arc $options $file"
+  cmd: "nim $target --compileOnly --os:freertos --gc:arc $options $file"
   disabled: "bsd"
   disabled: "windows"
   action: compile
diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim
index effe1032f..06a9a9c27 100644
--- a/tests/stdlib/tmacros.nim
+++ b/tests/stdlib/tmacros.nim
@@ -1,4 +1,15 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+#[
+xxx macros tests need to be reorganized to makes sure each API is tested once
+See also:
+  tests/macros/tdumpast.nim for treeRepr + friends
+]#
+
 import std/macros
+import std/assertions
 
 block: # hasArgOfName
   macro m(u: untyped): untyped =
@@ -10,3 +21,329 @@ block: # hasArgOfName
 
 block: # bug #17454
   proc f(v: NimNode): string {.raises: [].} = $v
+
+block: # unpackVarargs
+  block:
+    proc bar1(a: varargs[int]): string =
+      for ai in a: result.add " " & $ai
+    proc bar2(a: varargs[int]) =
+      let s1 = bar1(a)
+      let s2 = unpackVarargs(bar1, a) # `unpackVarargs` makes no difference here
+      doAssert s1 == s2
+    bar2(1, 2, 3)
+    bar2(1)
+    bar2()
+
+  block:
+    template call1(fun: typed; args: varargs[untyped]): untyped =
+      unpackVarargs(fun, args)
+    template call2(fun: typed; args: varargs[untyped]): untyped =
+      # fun(args) # works except for last case with empty `args`, pending bug #9996
+      when varargsLen(args) > 0: fun(args)
+      else: fun()
+
+    proc fn1(a = 0, b = 1) = discard (a, b)
+
+    call1(fn1)
+    call1(fn1, 10)
+    call1(fn1, 10, 11)
+
+    call2(fn1)
+    call2(fn1, 10)
+    call2(fn1, 10, 11)
+
+  block:
+    template call1(fun: typed; args: varargs[typed]): untyped =
+      unpackVarargs(fun, args)
+    template call2(fun: typed; args: varargs[typed]): untyped =
+      # xxx this would give a confusing error message:
+      # required type for a: varargs[typed] [varargs] but expression '[10]' is of type: varargs[typed] [varargs]
+      when varargsLen(args) > 0: fun(args)
+      else: fun()
+    macro toString(a: varargs[typed, `$`]): string =
+      var msg = genSym(nskVar, "msg")
+      result = newStmtList()
+      result.add quote do:
+        var `msg` = ""
+      for ai in a:
+        result.add quote do: `msg`.add $`ai`
+      result.add quote do: `msg`
+    doAssert call1(toString) == ""
+    doAssert call1(toString, 10) == "10"
+    doAssert call1(toString, 10, 11) == "1011"
+
+block: # SameType
+  type
+    A = int
+    B = distinct int
+    C = object
+    Generic[T, Y] = object
+  macro isSameType(a, b: typed): untyped =
+    newLit(sameType(a, b))
+
+  static:
+    assert Generic[int, int].isSameType(Generic[int, int])
+    assert Generic[A, string].isSameType(Generic[int, string])
+    assert not Generic[A, string].isSameType(Generic[B, string])
+    assert not Generic[int, string].isSameType(Generic[int, int])
+    assert isSameType(int, A)
+    assert isSameType(10, 20)
+    assert isSameType("Hello", "world")
+    assert not isSameType("Hello", cstring"world")
+    assert not isSameType(int, B)
+    assert not isSameType(int, Generic[int, int])
+    assert not isSameType(C, string)
+    assert not isSameType(C, int)
+
+
+  #[
+    # compiler sameType fails for the following, read more in `types.nim`'s `sameTypeAux`.
+    type
+      D[T] = C
+      G[T] = T
+    static:
+      assert isSameType(D[int], C)
+      assert isSameType(D[int], D[float])
+      assert isSameType(G[float](1.0), float(1.0))
+      assert isSameType(float(1.0), G[float](1.0))
+  ]#
+
+  type Tensor[T] = object
+    data: T
+
+  macro testTensorInt(x: typed): untyped =
+    let
+      tensorIntType = getTypeInst(Tensor[int])[1]
+      xTyp = x.getTypeInst
+    
+    newLit(xTyp.sameType(tensorIntType))
+
+  var
+    x: Tensor[int]
+    x1 = Tensor[float]()
+    x2 = Tensor[A]()
+    x3 = Tensor[B]()
+
+  static: 
+    assert testTensorInt(x)
+    assert not testTensorInt(x1)
+    assert testTensorInt(x2)
+    assert not testTensorInt(x3)
+
+block: # extractDocCommentsAndRunnables
+  macro checkRunnables(prc: untyped) =
+    let runnables = prc.body.extractDocCommentsAndRunnables()
+    doAssert runnables[0][0].eqIdent("runnableExamples")
+
+  macro checkComments(comment: static[string], prc: untyped) =
+    let comments = prc.body.extractDocCommentsAndRunnables()
+    doAssert comments[0].strVal == comment
+    
+  proc a() {.checkRunnables.} =
+    runnableExamples: discard
+    discard
+
+  proc b() {.checkRunnables.} =
+    runnableExamples "-d:ssl": discard
+    discard
+    
+  proc c() {.checkComments("Hello world").} =
+    ## Hello world
+
+block: # bug #19020
+  type
+    foo = object
+
+  template typ(T:typedesc) {.pragma.}
+
+  proc bar() {.typ: foo.} = discard
+
+  static:
+    doAssert $bar.getCustomPragmaVal(typ) == "foo"
+  doAssert $bar.getCustomPragmaVal(typ) == "foo"
+
+block hasCustomPragmaGeneric:
+  template examplePragma() {.pragma.}
+  type
+    Foo[T] {.examplePragma.} = object
+      x {.examplePragma.}: T
+  var f: Foo[string]
+  doAssert f.hasCustomPragma(examplePragma)
+  doAssert f.x.hasCustomPragma(examplePragma)
+
+block getCustomPragmaValGeneric:
+  template examplePragma(x: int) {.pragma.}
+  type
+    Foo[T] {.examplePragma(42).} = object
+      x {.examplePragma(25).}: T
+  var f: Foo[string]
+  doAssert f.getCustomPragmaVal(examplePragma) == 42
+  doAssert f.x.getCustomPragmaVal(examplePragma) == 25
+
+block: # bug #21326
+  macro foo(body: untyped): untyped =
+    let a = body.lineInfoObj()
+    let aLit = a.newLit
+    result = quote do:
+      doAssert $`a` == $`aLit`
+
+  foo:
+    let c = 1
+
+  template name(a: LineInfo): untyped =
+    discard a # `aLit` works though
+
+  macro foo3(body: untyped): untyped =
+    let a = body.lineInfoObj()
+    # let ax = newLit(a)
+    result = getAst(name(a))
+
+  foo3:
+    let c = 1
+
+block: # bug #7375
+  macro fails(b: static[bool]): untyped =
+    doAssert b == false
+    result = newStmtList()
+
+  macro foo(): untyped =
+
+    var b = false
+
+    ## Fails
+    result = quote do:
+      fails(`b`)
+
+  foo()
+
+  macro someMacro(): untyped =
+    template tmpl(boolean: bool) =
+      when boolean:
+        discard "it's true!"
+      else:
+        doAssert false
+    result = getAst(tmpl(true))
+
+  someMacro()
+
+block:
+  macro foo(): untyped =
+    result = quote do: `littleEndian`
+
+  doAssert littleEndian == foo()
+
+block:
+  macro eqSym(x, y: untyped): untyped =
+    let eq = $x == $y # Unfortunately eqIdent compares to string.
+    result = quote do: `eq`
+
+  var r, a, b: int
+
+  template fma(result: var int, a, b: int, op: untyped) =
+    # fused multiple-add
+    when eqSym(op, `+=`):
+      discard "+="
+    else:
+      discard "+"
+
+  fma(r, a, b, `+=`)
+
+block:
+  template test(boolArg: bool) =
+    static:
+      doAssert typeof(boolArg) is bool
+    let x: bool = boolArg # compile error here, because boolArg became an int
+
+  macro testWrapped1(boolArg: bool): untyped =
+    # forwarding boolArg directly works
+    result = getAst(test(boolArg))
+
+  macro testWrapped2(boolArg: bool): untyped =
+    # forwarding boolArg via a local variable also works
+    let b = boolArg
+    result = getAst(test(b))
+
+  macro testWrapped3(boolArg: bool): untyped =
+    # but using a literal `true` as a local variable will be converted to int
+    let b = true
+    result = getAst(test(b))
+
+  test(true) # ok
+  testWrapped1(true) # ok
+  testWrapped2(true) # ok
+  testWrapped3(true) 
+
+block:
+  macro foo(): untyped =
+    var s = { 'a', 'b' }
+    quote do:              
+      let t = `s`         
+      doAssert $typeof(t) == "set[char]"
+
+  foo()
+
+block: # bug #9607
+  proc fun1(info:LineInfo): string = "bar"
+  proc fun2(info:int): string = "bar"
+
+  macro echoL(args: varargs[untyped]): untyped =
+    let info = args.lineInfoObj
+    let fun1 = bindSym"fun1"
+    let fun2 = bindSym"fun2"
+
+    # this would work instead
+    # result = newCall(bindSym"fun2", info.line.newLit)
+
+    result = quote do:
+
+      # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil
+      `fun1`(`info`)
+
+  macro echoM(args: varargs[untyped]): untyped =
+    let info = args.lineInfoObj
+    let fun1 = bindSym"fun1"
+    let fun2 = bindSym"fun2"
+
+    # this would work instead
+    # result = newCall(bindSym"fun2", info.line.newLit)
+
+    result = quote do:
+
+      # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil
+      `fun2`(`info`.line)
+
+
+  doAssert echoL() == "bar"
+  doAssert echoM() == "bar"
+
+block:
+  macro hello[T](x: T): untyped =
+    result = quote do:
+      let m: `T` = `x`
+      discard m
+
+  hello(12)
+
+block:
+  proc hello(x: int, y: typedesc) =
+    discard
+
+  macro main =
+    let x = 12
+    result = quote do:
+      `hello`(12, type(x))
+
+  main()
+
+block: # bug #22947
+  macro bar[N: static int](a: var array[N, int]) =
+    result = quote do:
+      for i in 0 ..< `N`:
+        `a`[i] = i
+
+  func foo[N: static int](a: var array[N, int]) =
+    bar(a)
+
+
+  var a: array[4, int]
+  foo(a)
diff --git a/tests/stdlib/tmarshal.nim b/tests/stdlib/tmarshal.nim
index 508205c3a..32991ccc9 100644
--- a/tests/stdlib/tmarshal.nim
+++ b/tests/stdlib/tmarshal.nim
@@ -1,15 +1,24 @@
+discard """
+  matrix: "--mm:orc; --mm:refc"
+"""
+
 import std/marshal
+import std/[assertions, objectdollar, streams]
 
 # TODO: add static tests
 
 proc testit[T](x: T): string = $$to[T]($$x)
 
-let test1: array[0..1, array[0..4, string]] = [
-  ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"]]
-doAssert testit(test1) ==
-  """[["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"]]"""
-let test2: tuple[name: string, s: int] = ("tuple test", 56)
-doAssert testit(test2) == """{"Field0": "tuple test", "Field1": 56}"""
+template check1 =
+  let test1: array[0..1, array[0..4, string]] = [
+    ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"]]
+  doAssert testit(test1) ==
+    """[["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"]]"""
+  let test2: tuple[name: string, s: int] = ("tuple test", 56)
+  doAssert testit(test2) == """{"Field0": "tuple test", "Field1": 56}"""
+
+static: check1()
+check1()
 
 type
   TE = enum
@@ -132,6 +141,16 @@ block:
   let test = to[LegacyEntry](str)
   doAssert $test == """(numeric: "")"""
 
+block:
+  let str = """{"numeric": null}"""
+
+  type
+    LegacyEntry = object
+      numeric: seq[int]
+
+  var test = to[LegacyEntry](str)
+  doAssert $test == """(numeric: @[])"""
+
 # bug #16022
 block:
   let p: proc (): string = proc (): string = "hello world"
@@ -146,3 +165,69 @@ block:
 
   let a: ref A = new(B)
   doAssert $$a[] == "{}" # not "{f: 0}"
+
+# bug #16496
+block:
+  type
+    A = ref object
+      data: seq[int]
+
+    B = ref object
+      x: A
+  let o = A(data: @[1, 2, 3, 4])
+  let s1 = @[B(x: o), B(x: o)]
+  let m  = $$ s1
+  let s2 = to[seq[B]](m)
+  doAssert s2[0].x.data == s2[1].x.data
+  doAssert s1[0].x.data == s2[1].x.data
+
+
+block:
+  type
+    Obj = ref object
+      i: int
+      b: bool
+
+  let
+    strm = newStringStream()
+
+  var
+    o = Obj(i: 1, b: false)
+    t1 = @[o, o]
+    t2: seq[Obj]
+
+  doAssert t1[0] == t1[1]
+
+  strm.store(t1)
+  strm.setPosition(0)
+  strm.load(t2)
+  strm.close()
+
+  doAssert t2[0] == t2[1]
+
+
+template checkMarshal(data: typed) =
+  let orig = data
+  let m = $$orig
+
+  let old = to[typeof(orig)](m)
+  doAssert data == old
+
+template main() =
+  type
+    Book = object
+      page: int
+      name: string
+
+  let book = Book(page: 12, name: "persona")
+
+  checkMarshal(486)
+  checkMarshal(3.14)
+  checkMarshal("azure sky")
+  checkMarshal(book)
+  checkMarshal([1, 2, 3])
+  checkMarshal(@[1.5, 2.7, 3.9, 4.2])
+  checkMarshal(@["dream", "is", "possible"])
+
+static: main()
+main()
diff --git a/tests/stdlib/tmarshalsegfault.nim b/tests/stdlib/tmarshalsegfault.nim
new file mode 100644
index 000000000..71f2766c8
--- /dev/null
+++ b/tests/stdlib/tmarshalsegfault.nim
@@ -0,0 +1,54 @@
+# issue #12405
+
+import std/[marshal, streams, times, tables, os, assertions]
+
+type AiredEpisodeState * = ref object
+    airedAt * : DateTime
+    tvShowId * : string
+    seasonNumber * : int
+    number * : int
+    title * : string
+
+type ShowsWatchlistState * = ref object
+    aired * : seq[AiredEpisodeState]
+
+type UiState * = ref object
+    shows: ShowsWatchlistState
+
+# Helpers to marshal and unmarshal
+proc load * ( state : var UiState, file : string ) =
+    var strm = newFileStream( file, fmRead )
+
+    strm.load( state )
+
+    strm.close()
+
+proc store * ( state : UiState, file : string ) =
+    var strm = newFileStream( file, fmWrite )
+
+    strm.store( state )
+
+    strm.close()
+
+# 1. We fill the state initially
+var state : UiState = UiState( shows: ShowsWatchlistState( aired: @[] ) )
+
+# VERY IMPORTANT: For some reason, small numbers (like 2 or 3) don't trigger the bug. Anything above 7 or 8 on my machine triggers though
+for i in 0..30:
+    var episode = AiredEpisodeState( airedAt: now(), tvShowId: "1", seasonNumber: 1, number: 1, title: "string" )
+
+    state.shows.aired.add( episode )
+
+# 2. Store it in a file with the marshal module, and then load it back up
+store( state, "tmarshalsegfault_data" )
+load( state, "tmarshalsegfault_data" )
+removeFile("tmarshalsegfault_data")
+
+# 3. VERY IMPORTANT: Without this line, for some reason, everything works fine
+state.shows.aired[ 0 ] = AiredEpisodeState( airedAt: now(), tvShowId: "1", seasonNumber: 1, number: 1, title: "string" )
+
+# 4. And formatting the airedAt date will now trigger the exception
+for ep in state.shows.aired:
+    let x = $ep.seasonNumber & "x" & $ep.number & " (" & $ep.airedAt & ")"
+    let y = $ep.seasonNumber & "x" & $ep.number & " (" & $ep.airedAt & ")"
+    doAssert x == y
diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim
index 49b4c82f1..22e5f7d88 100644
--- a/tests/stdlib/tmath.nim
+++ b/tests/stdlib/tmath.nim
@@ -1,12 +1,14 @@
 discard """
   targets: "c cpp js"
-  matrix:"; -d:danger"
+  matrix:"; -d:danger; --mm:refc"
 """
 
 # xxx: there should be a test with `-d:nimTmathCase2 -d:danger --passc:-ffast-math`,
 # but it requires disabling certain lines with `when not defined(nimTmathCase2)`
 
 import std/math
+import std/assertions
+
 
 # Function for approximate comparison of floats
 proc `==~`(x, y: float): bool = abs(x - y) < 1e-9
@@ -29,10 +31,6 @@ template main() =
       doAssert erf(6.0) > erf(5.0)
       doAssert erfc(6.0) < erfc(5.0)
 
-  when not defined(js) and not defined(windows): # xxx pending bug #17017
-    doAssert gamma(-1.0).isNaN
-
-
   block: # sgn() tests
     doAssert sgn(1'i8) == 1
     doAssert sgn(1'i16) == 1
@@ -46,6 +44,7 @@ template main() =
     doAssert sgn(123.9834'f64) == 1
     doAssert sgn(0'i32) == 0
     doAssert sgn(0'f32) == 0
+    doAssert sgn(-0.0'f64) == 0
     doAssert sgn(NegInf) == -1
     doAssert sgn(Inf) == 1
     doAssert sgn(NaN) == 0
@@ -109,6 +108,46 @@ template main() =
     doAssert euclDiv(-9, -3) == 3
     doAssert euclMod(-9, -3) == 0
 
+  block: # ceilDiv
+    doAssert ceilDiv(8,  3) ==  3
+    doAssert ceilDiv(8,  4) ==  2
+    doAssert ceilDiv(8,  5) ==  2
+    doAssert ceilDiv(11, 3) ==  4
+    doAssert ceilDiv(12, 3) ==  4
+    doAssert ceilDiv(13, 3) ==  5
+    doAssert ceilDiv(41, 7) ==  6
+    doAssert ceilDiv(0,  1) ==  0
+    doAssert ceilDiv(1,  1) ==  1
+    doAssert ceilDiv(1,  2) ==  1
+    doAssert ceilDiv(2,  1) ==  2
+    doAssert ceilDiv(2,  2) ==  1
+    doAssert ceilDiv(0, high(int)) == 0
+    doAssert ceilDiv(1, high(int)) == 1
+    doAssert ceilDiv(0, high(int) - 1) == 0
+    doAssert ceilDiv(1, high(int) - 1) == 1
+    doAssert ceilDiv(high(int) div 2, high(int) div 2 + 1) == 1
+    doAssert ceilDiv(high(int) div 2, high(int) div 2 + 2) == 1
+    doAssert ceilDiv(high(int) div 2 + 1, high(int) div 2) == 2
+    doAssert ceilDiv(high(int) div 2 + 2, high(int) div 2) == 2
+    doAssert ceilDiv(high(int) div 2 + 1, high(int) div 2 + 1) == 1
+    doAssert ceilDiv(high(int), 1) == high(int)
+    doAssert ceilDiv(high(int) - 1, 1) == high(int) - 1
+    doAssert ceilDiv(high(int) - 1, 2) == high(int) div 2
+    doAssert ceilDiv(high(int) - 1, high(int)) == 1
+    doAssert ceilDiv(high(int) - 1, high(int) - 1) == 1
+    doAssert ceilDiv(high(int) - 1, high(int) - 2) == 2
+    doAssert ceilDiv(high(int), high(int)) == 1
+    doAssert ceilDiv(high(int), high(int) - 1) == 2
+    doAssert ceilDiv(255'u8,  1'u8) == 255'u8
+    doAssert ceilDiv(254'u8,  2'u8) == 127'u8
+    when not defined(danger):
+      doAssertRaises(AssertionDefect): discard ceilDiv(41,  0)
+      doAssertRaises(AssertionDefect): discard ceilDiv(41, -1)
+      doAssertRaises(AssertionDefect): discard ceilDiv(-1,  1)
+      doAssertRaises(AssertionDefect): discard ceilDiv(-1, -1)
+      doAssertRaises(AssertionDefect): discard ceilDiv(254'u8, 3'u8)
+      doAssertRaises(AssertionDefect): discard ceilDiv(255'u8, 2'u8)
+
   block: # splitDecimal() tests
     doAssert splitDecimal(54.674).intpart == 54.0
     doAssert splitDecimal(54.674).floatpart ==~ 0.674
@@ -147,7 +186,22 @@ template main() =
     when not defined(nimTmathCase2):
       doAssert classify(trunc(f_nan.float32)) == fcNan
     doAssert classify(trunc(0.0'f32)) == fcZero
-
+  
+  block: # divmod
+    doAssert divmod(int.high, 1) == (int.high, 0)
+    doAssert divmod(-1073741823, 17) == (-63161283, -12)
+    doAssert divmod(int32.high, 1.int32) == (int32.high, 0.int32)
+    doAssert divmod(1073741823.int32, 5.int32) == (214748364.int32, 3.int32)
+    doAssert divmod(4611686018427387903.int64, 5.int64) == (922337203685477580.int64, 3.int64)
+    when not defined(js) and (not compileOption("panics")) and compileOption("overflowChecks"):
+      when nimvm:
+        discard # cannot catch OverflowDefect here
+      else:
+        doAssertRaises(OverflowDefect, (discard divmod(cint.low, -1.cint)))
+        doAssertRaises(OverflowDefect, (discard divmod(clong.low, -1.clong)))
+        doAssertRaises(OverflowDefect, (discard divmod(clonglong.low, -1.clonglong)))
+        doAssertRaises(DivByZeroDefect, (discard divmod(1, 0)))
+  
   block: # log
     doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0)
     doAssert log2(8.0'f64) == 3.0'f64
@@ -358,7 +412,7 @@ template main() =
     doAssert almostEqual(prod([1.5, 3.4]), 5.1)
     let x: seq[float] = @[]
     doAssert prod(x) == 1.0
-  
+
   block: # clamp range
     doAssert clamp(10, 1..5) == 5
     doAssert clamp(3, 1..5) == 3
@@ -370,8 +424,50 @@ template main() =
     doAssert a1.clamp(a2..a4) == a2
     doAssert clamp((3, 0), (1, 0) .. (2, 9)) == (2, 9)
 
-  when not defined(windows): # xxx pending bug #17017
-    doAssert sqrt(-1.0).isNaN
+  block: # edge cases
+    doAssert sqrt(-4.0).isNaN
+
+    doAssert ln(0.0) == -Inf
+    doAssert ln(-0.0) == -Inf
+    doAssert ln(-12.0).isNaN
+
+    doAssert log10(0.0) == -Inf
+    doAssert log10(-0.0) == -Inf
+    doAssert log10(-12.0).isNaN
+
+    doAssert log2(0.0) == -Inf
+    doAssert log2(-0.0) == -Inf
+    doAssert log2(-12.0).isNaN
+
+    when nimvm: discard
+    else:
+      doAssert frexp(0.0) == (0.0, 0)
+      doAssert frexp(-0.0) == (-0.0, 0)
+      doAssert classify(frexp(-0.0)[0]) == fcNegZero
+
+    when not defined(js):
+      doAssert gamma(0.0) == Inf
+      doAssert gamma(-0.0) == -Inf
+      doAssert gamma(-1.0).isNaN
+
+      doAssert lgamma(0.0) == Inf
+      doAssert lgamma(-0.0) == Inf
+      doAssert lgamma(-1.0) == Inf
 
 static: main()
 main()
+
+when not defined(js) and not defined(danger):
+  block: # bug #21792
+    block:
+      type Digit = 0..9
+      var x = [Digit 4, 7]
+
+      doAssertRaises(RangeDefect):
+        discard sum(x)
+
+    block:
+      var x = [int8 124, 127]
+
+      doAssertRaises(OverflowDefect):
+        discard sum(x)
diff --git a/tests/stdlib/tmd5.nim b/tests/stdlib/tmd5.nim
deleted file mode 100644
index 88a7b8d37..000000000
--- a/tests/stdlib/tmd5.nim
+++ /dev/null
@@ -1,7 +0,0 @@
-import md5
-
-doAssert(getMD5("Franz jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
-  "a3cca2b2aa1e3b5b3b5aad99a8529074")
-doAssert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
-  "7e716d0e702df0505fc72e2b89467910")
-doAssert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
diff --git a/tests/stdlib/tmemfiles1.nim b/tests/stdlib/tmemfiles1.nim
index 21a65369f..33657256c 100644
--- a/tests/stdlib/tmemfiles1.nim
+++ b/tests/stdlib/tmemfiles1.nim
@@ -1,4 +1,6 @@
 import memfiles, os
+import std/syncio
+
 var
   mm: MemFile
   fn = "test.mmap"
diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim
index 1b249898e..c79f85ebf 100644
--- a/tests/stdlib/tmemfiles2.nim
+++ b/tests/stdlib/tmemfiles2.nim
@@ -4,6 +4,9 @@ discard """
 Half read size: 10 Data: Hello'''
 """
 import memfiles, os
+import std/syncio
+
+
 const
   fn = "test.mmap"
 var
@@ -12,8 +15,9 @@ var
 
 if fileExists(fn): removeFile(fn)
 
-# Create a new file, data all zeros
-mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20)
+# Create a new file, data all zeros, starting at size 10
+mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 10, allowRemap=true)
+mm.resize 20  # resize up to 20
 mm.close()
 
 # read, change
diff --git a/tests/stdlib/tmemlinesBuf.nim b/tests/stdlib/tmemlinesBuf.nim
index ea607525d..7bd89d4f2 100644
--- a/tests/stdlib/tmemlinesBuf.nim
+++ b/tests/stdlib/tmemlinesBuf.nim
@@ -1,9 +1,4 @@
-discard """
-output: "15"
-disabled: "appveyor"
-"""
-
-import memfiles
+import std/[memfiles, assertions]
 var inp = memfiles.open("tests/stdlib/tmemlinesBuf.nim")
 var buffer: string = ""
 var lineCount = 0
@@ -11,5 +6,4 @@ for line in lines(inp, buffer):
   lineCount += 1
 
 close(inp)
-
-echo lineCount
+doAssert lineCount == 9, $lineCount # this file's number of lines
diff --git a/tests/stdlib/tmemmapstreams.nim b/tests/stdlib/tmemmapstreams.nim
index dd011d777..9cfae62c7 100644
--- a/tests/stdlib/tmemmapstreams.nim
+++ b/tests/stdlib/tmemmapstreams.nim
@@ -12,6 +12,8 @@ Readed line: Hello!
 Position after reading line: 7'''
 """
 import os, streams, memfiles
+import std/syncio
+
 const
   fn = "test.mmapstream"
 var
diff --git a/tests/stdlib/tmemory.nim b/tests/stdlib/tmemory.nim
deleted file mode 100644
index 25b5d526a..000000000
--- a/tests/stdlib/tmemory.nim
+++ /dev/null
@@ -1,15 +0,0 @@
-
-block: # cmpMem
-  type
-    SomeHash = array[15, byte]
-
-  var
-    a: SomeHash
-    b: SomeHash
-
-  a[^1] = byte(1)
-  let c = a
-
-  doAssert cmpMem(a.addr, b.addr, sizeof(SomeHash)) > 0
-  doAssert cmpMem(b.addr, a.addr, sizeof(SomeHash)) < 0
-  doAssert cmpMem(a.addr, c.unsafeAddr, sizeof(SomeHash)) == 0
diff --git a/tests/stdlib/tmersenne.nim b/tests/stdlib/tmersenne.nim
index 2707aa2f2..64450a045 100644
--- a/tests/stdlib/tmersenne.nim
+++ b/tests/stdlib/tmersenne.nim
@@ -1,4 +1,5 @@
 import std/mersenne
+import std/assertions
 
 template main() =
   var mt = newMersenneTwister(2525)
@@ -7,5 +8,6 @@ template main() =
   doAssert mt.getNum == 1071751096'u32
   doAssert mt.getNum == 3805347140'u32
 
+
 static: main()
 main()
diff --git a/tests/stdlib/tmget.nim b/tests/stdlib/tmget.nim
index 52e61fd24..f41963f02 100644
--- a/tests/stdlib/tmget.nim
+++ b/tests/stdlib/tmget.nim
@@ -1,16 +1,21 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: '''Can't access 6
 10
 11
+2
 Can't access 6
 10
 11
+2
 Can't access 6
 10
 11
+2
 Can't access 6
 10
 11
+2
 0
 10
 11
@@ -40,6 +45,9 @@ block:
   x[5] += 1
   var c = x[5]
   echo c
+  x.mgetOrPut(7).inc
+  x.mgetOrPut(7).inc
+  echo x[7]
 
 block:
   var x = newTable[int, int]()
@@ -52,6 +60,9 @@ block:
   x[5] += 1
   var c = x[5]
   echo c
+  x.mgetOrPut(7).inc
+  x.mgetOrPut(7).inc
+  echo x[7]
 
 block:
   var x = initOrderedTable[int, int]()
@@ -64,6 +75,9 @@ block:
   x[5] += 1
   var c = x[5]
   echo c
+  x.mgetOrPut(7).inc
+  x.mgetOrPut(7).inc
+  echo x[7]
 
 block:
   var x = newOrderedTable[int, int]()
@@ -76,6 +90,9 @@ block:
   x[5] += 1
   var c = x[5]
   echo c
+  x.mgetOrPut(7).inc
+  x.mgetOrPut(7).inc
+  echo x[7]
 
 block:
   var x = initCountTable[int]()
diff --git a/tests/stdlib/tmimetypes.nim b/tests/stdlib/tmimetypes.nim
index cd41e614b..fd66ebd97 100644
--- a/tests/stdlib/tmimetypes.nim
+++ b/tests/stdlib/tmimetypes.nim
@@ -1,13 +1,28 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/mimetypes
+import std/assertions
+
+
 template main() =
   var m = newMimetypes()
   doAssert m.getMimetype("mp4") == "video/mp4"
+  doAssert m.getExt("application/json") == "json"
+  doAssert m.getMimetype("json") == "application/json"
+  m.register("foo", "baa")
+  doAssert m.getMimetype("foo") == "baa"
+  doAssert m.getMimetype("txt") == "text/plain"
+  doAssert m.getExt("text/plain") == "txt"
   # see also `runnableExamples`.
   # xxx we should have a way to avoid duplicating code between runnableExamples and tests
 
+  doAssert m.getMimetype("nim") == "text/nim"
+  doAssert m.getMimetype("nimble") == "text/nimble"
+  doAssert m.getMimetype("nimf") == "text/nim"
+  doAssert m.getMimetype("nims") == "text/nim"
+
 static: main()
 main()
diff --git a/tests/stdlib/tmisc_issues.nim b/tests/stdlib/tmisc_issues.nim
new file mode 100644
index 000000000..86dcf4162
--- /dev/null
+++ b/tests/stdlib/tmisc_issues.nim
@@ -0,0 +1,39 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+
+import std/assertions
+
+# bug #20227
+type
+  Data = object
+    id: int
+
+  Test = distinct Data
+
+  Object = object
+    data: Test
+
+
+var x: Object = Object(data: Test(Data(id: 12)))
+doAssert Data(x.data).id == 12
+
+block: # bug #16771
+  type A = object
+    n: int
+
+  proc foo(a, b: var A) =
+    swap a, b
+
+  var a, b: A
+  a.n = 42
+  b.n = 1
+  doAssert a.n == 42
+  doAssert b.n == 1
+  a.swap b
+  doAssert a.n == 1
+  doAssert b.n == 42
+  a.foo b
+  doAssert a.n == 42
+  doAssert b.n == 1
diff --git a/tests/stdlib/tmitems.nim b/tests/stdlib/tmitems.nim
index c0ced7cab..cc515a175 100644
--- a/tests/stdlib/tmitems.nim
+++ b/tests/stdlib/tmitems.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: '''@[11, 12, 13]
 @[11, 12, 13]
 @[1, 3, 5]
@@ -62,6 +63,7 @@ block:
 
 block:
   var x = "foobar"
+  prepareMutation(x)
   var y = cast[cstring](addr x[0])
   for c in y.mitems:
     inc c
@@ -75,6 +77,7 @@ block:
 
 block:
   var x = "foobar"
+  prepareMutation(x)
   var y = cast[cstring](addr x[0])
   for i, c in y.mpairs:
     inc c, i
diff --git a/tests/stdlib/tmonotimes.nim b/tests/stdlib/tmonotimes.nim
index 2933bb686..1366dbfe9 100644
--- a/tests/stdlib/tmonotimes.nim
+++ b/tests/stdlib/tmonotimes.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/[monotimes, times]
+import std/assertions
 
 let d = initDuration(nanoseconds = 10)
 let t1 = getMonoTime()
diff --git a/tests/stdlib/tnativesockets.nim b/tests/stdlib/tnativesockets.nim
index b0cfd09cf..8242beb83 100644
--- a/tests/stdlib/tnativesockets.nim
+++ b/tests/stdlib/tnativesockets.nim
@@ -1,29 +1,30 @@
 discard """
-  cmd:      "nim c -r --styleCheck:hint --panics:on $options $file"
-  targets:  "c"
-  nimout:   ""
-  action:   "run"
-  exitcode: 0
-  timeout:  60.0
+  matrix: "--mm:refc; --mm:orc"
 """
 
-import nativesockets
+import std/nativesockets
+import stdtest/testutils
+import std/assertions
 
+block:
+  let hostname = getHostname()
+  doAssert hostname.len > 0
 
 when defined(windows):
-  doAssert toInt(IPPROTO_IP) == 0.cint
-  doAssert toInt(IPPROTO_ICMP) == 1.cint
-  doAssert toInt(IPPROTO_TCP) == 6.cint
-  doAssert toInt(IPPROTO_UDP) == 17.cint
-  doAssert toInt(IPPROTO_IPV6) == 41.cint
-  doAssert toInt(IPPROTO_ICMPV6) == 58.cint
-  doAssert toInt(IPPROTO_RAW) == 20.cint
+  assertAll:
+    toInt(IPPROTO_IP) == 0
+    toInt(IPPROTO_ICMP) == 1
+    toInt(IPPROTO_TCP) == 6
+    toInt(IPPROTO_UDP) == 17
+    toInt(IPPROTO_IPV6) == 41
+    toInt(IPPROTO_ICMPV6) == 58
+    toInt(IPPROTO_RAW) == 20
 
-  # no changes to enum value
-  doAssert ord(IPPROTO_TCP) == 6
-  doAssert ord(IPPROTO_UDP) == 17
-  doAssert ord(IPPROTO_IP) == 18
-  doAssert ord(IPPROTO_IPV6) == 19
-  doAssert ord(IPPROTO_RAW) == 20
-  doAssert ord(IPPROTO_ICMP) == 21
-  doAssert ord(IPPROTO_ICMPV6) == 22
+    # no changes to enum value
+    ord(IPPROTO_TCP) == 6
+    ord(IPPROTO_UDP) == 17
+    ord(IPPROTO_IP) == 18
+    ord(IPPROTO_IPV6) == 19
+    ord(IPPROTO_RAW) == 20
+    ord(IPPROTO_ICMP) == 21
+    ord(IPPROTO_ICMPV6) == 22
diff --git a/tests/stdlib/tnet.nim b/tests/stdlib/tnet.nim
index b19d31f6c..27a6ac49c 100644
--- a/tests/stdlib/tnet.nim
+++ b/tests/stdlib/tnet.nim
@@ -1,9 +1,11 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 outputsub: ""
 """
 
 import net, nativesockets
 import unittest
+import std/assertions
 
 block: # isIpAddress tests
   block: # 127.0.0.1 is valid
@@ -50,6 +52,41 @@ block: # parseIpAddress tests
     expect(ValueError):
       discard parseIpAddress("gggg:cdba:0000:0000:0000:0000:3257:9652")
 
+  block: # ipv4-compatible ipv6 address (embedded ipv4 address)
+    check parseIpAddress("::ffff:10.0.0.23") == parseIpAddress("::ffff:0a00:0017")
+
+  block: # octal number in ipv4 address
+    expect(ValueError):
+      discard parseIpAddress("010.8.8.8")
+    expect(ValueError):
+      discard parseIpAddress("8.010.8.8")
+
+  block: # hexadecimal number in ipv4 address
+    expect(ValueError):
+      discard parseIpAddress("0xc0.168.0.1")
+    expect(ValueError):
+      discard parseIpAddress("192.0xa8.0.1")
+
+  block: # less than 4 numbers in ipv4 address
+    expect(ValueError):
+      discard parseIpAddress("127.0.1")
+
+  block: # octal number in embedded ipv4 address
+    expect(ValueError):
+      discard parseIpAddress("::ffff:010.8.8.8")
+    expect(ValueError):
+      discard parseIpAddress("::ffff:8.010.8.8")
+
+  block: # hexadecimal number in embedded ipv4 address
+    expect(ValueError):
+      discard parseIpAddress("::ffff:0xc0.168.0.1")
+    expect(ValueError):
+      discard parseIpAddress("::ffff:192.0xa8.0.1")
+
+  block: # less than 4 numbers in embedded ipv4 address
+    expect(ValueError):
+      discard parseIpAddress("::ffff:127.0.1")
+
 block: # "IpAddress/Sockaddr conversion"
   proc test(ipaddrstr: string) =
     var ipaddr_1 = parseIpAddress(ipaddrstr)
@@ -58,7 +95,7 @@ block: # "IpAddress/Sockaddr conversion"
     doAssert($ipaddrstr == $ipaddr_1)
 
     var sockaddr: Sockaddr_storage
-    var socklen: Socklen
+    var socklen: SockLen
     var ipaddr_2: IpAddress
     var port_2: Port
 
diff --git a/tests/stdlib/tnet_ll.nim b/tests/stdlib/tnet_ll.nim
index affa21947..199946482 100644
--- a/tests/stdlib/tnet_ll.nim
+++ b/tests/stdlib/tnet_ll.nim
@@ -1,43 +1,52 @@
-discard """

-  action: run

-  output: '''

-

-[Suite] inet_ntop tests

-'''

-"""

-

-when defined(windows):

-  import winlean

-elif defined(posix):

-  import posix

-else:

-  {.error: "Unsupported OS".}

-

-import unittest, strutils

-

-suite "inet_ntop tests":

-

-  setup:

-    when defined(windows):

-      var wsa: WSAData

-      discard wsaStartup(0x101'i16, wsa.addr)

-  

-  test "IP V4":

-    var ip4 = 0x10111213

-    var buff: array[0..255, char]

-    let r = inet_ntop(AF_INET, ip4.addr, buff[0].addr, buff.sizeof.int32)

-    let res = if r == nil: "" else: $r

-    check: res == "19.18.17.16"

-      

-

-  test "IP V6":

-    when defined(windows):

-      let ipv6Support = (getVersion() and 0xff) > 0x5

-    else:

-      let ipv6Support = true

-          

-    var ip6 = [0x1000'u16, 0x1001, 0x2000, 0x2001, 0x3000, 0x3001, 0x4000, 0x4001]

-    var buff: array[0..255, char]

-    let r = inet_ntop(AF_INET6, ip6[0].addr, buff[0].addr, buff.sizeof.int32)

-    let res = if r == nil: "" else: $r

-    check: not ipv6Support or res == "10:110:20:120:30:130:40:140"

+discard """
+  action: run
+  matrix: "--mm:refc; --mm:orc"
+  output: '''
+
+[Suite] inet_ntop tests
+'''
+"""
+
+when defined(windows):
+  import winlean
+elif defined(posix):
+  import posix
+else:
+  {.error: "Unsupported OS".}
+
+import unittest, strutils
+
+suite "inet_ntop tests":
+
+  setup:
+    when defined(windows):
+      var wsa: WSAData
+      discard wsaStartup(0x101'i16, wsa.addr)
+  
+  test "IP V4":
+    # regular
+    var ip4 = InAddr()
+    ip4.s_addr = 0x10111213'u32
+    check: ip4.s_addr == 0x10111213'u32
+
+    var buff: array[0..255, char]
+    let r = inet_ntop(AF_INET, cast[pointer](ip4.s_addr.addr), cast[cstring](buff[0].addr), buff.len.int32)
+    let res = if r == nil: "" else: $r
+    check: res == "19.18.17.16"
+      
+  test "IP V6":
+    when defined(windows):
+      let ipv6Support = (getVersion() and 0xff) > 0x5
+    else:
+      let ipv6Support = true
+          
+    var ip6 = [0x1000'u16, 0x1001, 0x2000, 0x2001, 0x3000, 0x3001, 0x4000, 0x4001]
+    var buff: array[0..255, char]
+    let r = inet_ntop(AF_INET6, cast[pointer](ip6[0].addr), cast[cstring](buff[0].addr), buff.len.int32)
+    let res = if r == nil: "" else: $r
+    check: not ipv6Support or res == "10:110:20:120:30:130:40:140"
+
+  test "InAddr":
+    # issue 19244
+    var ip4 = InAddr(s_addr: 0x10111213'u32)
+    check: ip4.s_addr == 0x10111213'u32
diff --git a/tests/stdlib/tnetbind.nim b/tests/stdlib/tnetbind.nim
index 734b6c5e7..84f9ac464 100644
--- a/tests/stdlib/tnetbind.nim
+++ b/tests/stdlib/tnetbind.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 joinable: false
 """
 
diff --git a/tests/stdlib/tnetconnect.nim b/tests/stdlib/tnetconnect.nim
index b74545710..ae654aed9 100644
--- a/tests/stdlib/tnetconnect.nim
+++ b/tests/stdlib/tnetconnect.nim
@@ -1,9 +1,11 @@
 discard """
+  disabled: "i386"
   matrix: "-d:ssl"
 """
 
 import std/net
 from std/strutils import `%`
+from stdtest/testutils import enableRemoteNetworking
 
 # bug #15215
 proc test() =
@@ -17,10 +19,12 @@ proc test() =
     wrapSocket(ctx, socket)
 
   # trying 2 sites makes it more resilent: refs #17458 this could give:
-  # Error: unhandled exception: Call to 'connect' timed out. [TimeoutError]
+  # * Call to 'connect' timed out. [TimeoutError]
+  # * No route to host [OSError]
   try:
     fn("www.nim-lang.org")
-  except TimeoutError:
+  except TimeoutError, OSError:
     fn("www.google.com")
 
-test()
+when enableRemoteNetworking:
+  test()
diff --git a/tests/stdlib/tnetdial.nim b/tests/stdlib/tnetdial.nim
index f940bd630..a1e147ad5 100644
--- a/tests/stdlib/tnetdial.nim
+++ b/tests/stdlib/tnetdial.nim
@@ -2,10 +2,10 @@ discard """
   cmd: "nim c --threads:on $file"
   exitcode: 0
   output: "OK"
-  disabled: "travis"
 """
 
 import os, net, nativesockets, asyncdispatch
+import std/[assertions, typedthreads]
 
 ## Test for net.dial
 
@@ -15,7 +15,7 @@ proc initIPv6Server(hostname: string, port: Port): AsyncFD =
   let fd = createNativeSocket(AF_INET6)
   setSockOptInt(fd, SOL_SOCKET, SO_REUSEADDR, 1)
   var aiList = getAddrInfo(hostname, port, AF_INET6)
-  if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
+  if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.SockLen) < 0'i32:
     freeAddrInfo(aiList)
     raiseOSError(osLastError())
   freeAddrInfo(aiList)
diff --git a/tests/stdlib/tnre.nim b/tests/stdlib/tnre.nim
index f13c16052..3b40e9e83 100644
--- a/tests/stdlib/tnre.nim
+++ b/tests/stdlib/tnre.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 # Since the tests for nre are all bundled together we treat failure in one test as an nre failure
 # When running 'testament/tester' a failed check() in the test suite will cause the exit
 # codes to differ and be reported as a failure
diff --git a/tests/stdlib/tntpath.nim b/tests/stdlib/tntpath.nim
new file mode 100644
index 000000000..8efdd6bd0
--- /dev/null
+++ b/tests/stdlib/tntpath.nim
@@ -0,0 +1,50 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/private/ntpath
+import std/assertions
+
+block: # From Python's `Lib/test/test_ntpath.py`
+  doAssert splitDrive(r"c:\foo\bar") == (r"c:", r"\foo\bar")
+  doAssert splitDrive(r"c:/foo/bar") == (r"c:", r"/foo/bar")
+  doAssert splitDrive(r"\\conky\mountpoint\foo\bar") == (r"\\conky\mountpoint", r"\foo\bar")
+  doAssert splitDrive(r"//conky/mountpoint/foo/bar") == (r"//conky/mountpoint", r"/foo/bar")
+  doAssert splitDrive(r"\\\conky\mountpoint\foo\bar") == (r"", r"\\\conky\mountpoint\foo\bar")
+  doAssert splitDrive(r"///conky/mountpoint/foo/bar") == (r"", r"///conky/mountpoint/foo/bar")
+  doAssert splitDrive(r"\\conky\\mountpoint\foo\bar") == (r"", r"\\conky\\mountpoint\foo\bar")
+  doAssert splitDrive(r"//conky//mountpoint/foo/bar") == (r"", r"//conky//mountpoint/foo/bar")
+  # Issue #19911: UNC part containing U+0130
+  doAssert splitDrive(r"//conky/MOUNTPOİNT/foo/bar") == (r"//conky/MOUNTPOİNT", r"/foo/bar")
+  # gh-81790: support device namespace, including UNC drives.
+  doAssert splitDrive(r"//?/c:") == (r"//?/c:", r"")
+  doAssert splitDrive(r"//?/c:/") == (r"//?/c:", r"/")
+  doAssert splitDrive(r"//?/c:/dir") == (r"//?/c:", r"/dir")
+  doAssert splitDrive(r"//?/UNC") == (r"", r"//?/UNC")
+  doAssert splitDrive(r"//?/UNC/") == (r"", r"//?/UNC/")
+  doAssert splitDrive(r"//?/UNC/server/") == (r"//?/UNC/server/", r"")
+  doAssert splitDrive(r"//?/UNC/server/share") == (r"//?/UNC/server/share", r"")
+  doAssert splitDrive(r"//?/UNC/server/share/dir") == (r"//?/UNC/server/share", r"/dir")
+  doAssert splitDrive(r"//?/VOLUME{00000000-0000-0000-0000-000000000000}/spam") == (r"//?/VOLUME{00000000-0000-0000-0000-000000000000}", r"/spam")
+  doAssert splitDrive(r"//?/BootPartition/") == (r"//?/BootPartition", r"/")
+
+  doAssert splitDrive(r"\\?\c:") == (r"\\?\c:", r"")
+  doAssert splitDrive(r"\\?\c:\") == (r"\\?\c:", r"\")
+  doAssert splitDrive(r"\\?\c:\dir") == (r"\\?\c:", r"\dir")
+  doAssert splitDrive(r"\\?\UNC") == (r"", r"\\?\UNC")
+  doAssert splitDrive(r"\\?\UNC\") == (r"", r"\\?\UNC\")
+  doAssert splitDrive(r"\\?\UNC\server\") == (r"\\?\UNC\server\", r"")
+  doAssert splitDrive(r"\\?\UNC\server\share") == (r"\\?\UNC\server\share", r"")
+  doAssert splitDrive(r"\\?\UNC\server\share\dir") == (r"\\?\UNC\server\share", r"\dir")
+  doAssert splitDrive(r"\\?\VOLUME{00000000-0000-0000-0000-000000000000}\spam") == (r"\\?\VOLUME{00000000-0000-0000-0000-000000000000}", r"\spam")
+  doAssert splitDrive(r"\\?\BootPartition\") == (r"\\?\BootPartition", r"\")
+
+block:
+  doAssert splitDrive(r"C:") == (r"C:", r"")
+  doAssert splitDrive(r"C:\") == (r"C:", r"\")
+  doAssert splitDrive(r"non/absolute/path") == (r"", r"non/absolute/path")
+
+  # Special for `\`-rooted paths on Windows. I don't know if this is correct,
+  # rbut `\` is not recognized as a drive, in contrast to `C:` or `\?\c:`.
+  # This behavior is the same for Python's `splitdrive` function.
+  doAssert splitDrive(r"\\") == (r"", r"\\")
diff --git a/tests/stdlib/tobjectdollar.nim b/tests/stdlib/tobjectdollar.nim
new file mode 100644
index 000000000..cf78fa255
--- /dev/null
+++ b/tests/stdlib/tobjectdollar.nim
@@ -0,0 +1,14 @@
+discard """
+  matrix: "-d:nimPreviewSlimSystem"
+"""
+
+import std/assertions
+
+type Foo = object
+  a, b: int
+
+let x = Foo(a: 23, b: 45)
+doAssert not compiles($x)
+import std/objectdollar
+doAssert compiles($x)
+doAssert $x == "(a: 23, b: 45)"
diff --git a/tests/stdlib/toids.nim b/tests/stdlib/toids.nim
index f162dbe57..dd5b84c51 100644
--- a/tests/stdlib/toids.nim
+++ b/tests/stdlib/toids.nim
@@ -1,6 +1,15 @@
-import std/oids
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
 
+import std/oids
+import std/assertions
 
 block: # genOid
   let x = genOid()
   doAssert ($x).len == 24
+
+block:
+  let x = genOid()
+  let y = parseOid(cstring($x))
+  doAssert x == y
diff --git a/tests/stdlib/topenssl.nim b/tests/stdlib/topenssl.nim
index 75e1ba868..af259627f 100644
--- a/tests/stdlib/topenssl.nim
+++ b/tests/stdlib/topenssl.nim
@@ -1,5 +1,10 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/wordwrap
 import openssl
+import std/assertions
 
 const PubKey = r"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAknKWvrdnncCIzBnIGrZ5qtZrPH+Yo3t7ag9WZIu6Gmc/JgIDDaZhJeyGW0YSnifeAEhooWvM4jDWhTEARzktalSHqYtmwI/1Oxwp6NTYH8akMe2LCpZ5pX9FVA6m9o2tkbdXatbDKRqeD4UA8Ow7Iyrdo6eb1SU8vk+26i+uXHTtsb25p8uf2ppOJrJCy+1vr8Gsnuwny1UdoYZTxMsxRFPf+UX/LrSXMHVq/oPVa3SJ4VHMpYrG/httAugVP6K58xiZ93jst63/dd0JL85mWJu1uS3uz92aL5O97xzth3wR4BbdmDUlN4LuTIwi6DtEcC7gUOTnOzH4zgp2b5RyHwIDAQAB"
 const PrivateKey = r"MIIEpAIBAAKCAQEAknKWvrdnncCIzBnIGrZ5qtZrPH+Yo3t7ag9WZIu6Gmc/JgIDDaZhJeyGW0YSnifeAEhooWvM4jDWhTEARzktalSHqYtmwI/1Oxwp6NTYH8akMe2LCpZ5pX9FVA6m9o2tkbdXatbDKRqeD4UA8Ow7Iyrdo6eb1SU8vk+26i+uXHTtsb25p8uf2ppOJrJCy+1vr8Gsnuwny1UdoYZTxMsxRFPf+UX/LrSXMHVq/oPVa3SJ4VHMpYrG/httAugVP6K58xiZ93jst63/dd0JL85mWJu1uS3uz92aL5O97xzth3wR4BbdmDUlN4LuTIwi6DtEcC7gUOTnOzH4zgp2b5RyHwIDAQABAoIBACSOxmLFlfAjaALLTNCeTLEA5bQshgYJhT1sprxixQpiS7lJN0npBsdYzBFs5KjmetzHNpdVOcgdOO/204L0Gwo4H8WLLxNS3HztAulEeM813zc3fUYfWi6eHshk//j8VR/TDNd21TElm99z7FA4KGsXAE0iQhxrN0aqz5aWYIhjprtHA5KxXIiESnTkof5Cud8oXEnPiwPGNhq93QeQzh7xQIKSaDKBcdAa6edTFhzc4RLUQRfrik/GqJzouEDQ9v6H/uiOLTB3FxxwErQIf6dvSVhD9gs1nSLQfyj3S2Hxe9S2zglTl07EsawTQUxtVQkdZUOok67c7CPBxecZ2wECgYEA2c31gr/UJwczT+P/AE52GkHHETXMxqE3Hnh9n4CitfAFSD5X0VwZvGjZIlln2WjisTd92Ymf65eDylX2kCm93nzZ2GfXgS4zl4oY1N87+VeNQlx9f2+6GU7Hs0HFdfu8bGd+0sOuWA1PFqQCobxCACMPTkuzsG9M7knUTN59HS8CgYEArCEoP4ReYoOFveXUE0AteTPb4hryvR9VDEolP+LMoiPe8AzBMeB5fP493TPdjtnWmrPCXNLc7UAFSj2CZsRhau4PuiqnNrsb5iz/7iXVl3E8wZvS4w7WYpO4m33L0cijA6MdcdqilQu4Z5tw4nG45lAW9UYyOc9D4hJTzgtGHhECgYA6QyDoj931brSoK0ocT+DB11Sj4utbOuberMaV8zgTSRhwodSl+WgdAUMMMDRacPcrBrgQiAMSZ15msqYZHEFhEa7Id8arFKvSXquTzf9iDKyJ0unzO/ThLjS3W+GxVNyrdufzA0tQ3IaKfOcDUrOpC7fdbtyrVqqSl4dF5MI9GwKBgQCl3OF6qyOEDDZgsUk1L59h7k3QR6VmBf4e9IeGUxZamvQlHjU/yY1nm1mjgGnbUB/SPKtqZKoMV6eBTVoNiuhQcItpGda9D3mnx+7p3T0/TBd+fJeuwcplfPDjrEktogcq5w/leQc3Ve7gr1EMcwb3r28f8/9L42QHQR/OKODs8QKBgQCFAvxDRPyYg7V/AgD9rt1KzXi4+b3Pls5NXZa2g/w+hmdhHUNxV5IGmHlqFnptGyshgYgQGxMMkW0iJ1j8nLamFnkbFQOp5/UKbdPLRKiB86oPpxsqYtPXucDUqEfcMsp57mD1CpGVODbspogFpSUvQpMECkhvI0XLMbolMdo53g=="
@@ -12,8 +17,8 @@ proc rsaPublicEncrypt(fr: string): string =
   doAssert rsa != nil
   doAssert BIO_free(bio) >= 0
   result = newString(RSA_size(rsa))
-  let frdata = cast[ptr cuchar](fr.cstring)
-  var todata = cast[ptr cuchar](result.cstring)
+  let frdata = cast[ptr uint8](fr.cstring)
+  var todata = cast[ptr uint8](result.cstring)
   doAssert RSA_public_encrypt(fr.len.cint, frdata, todata, rsa, RSA_PKCS1_PADDING) != -1
   RSA_free(rsa)
 
@@ -26,8 +31,8 @@ proc rasPrivateDecrypt(fr: string): string =
   doAssert BIO_free(bio) >= 0
   let rsaLen = RSA_size(rsa)
   result = newString(rsaLen)
-  let frdata = cast[ptr cuchar](fr.cstring)
-  var todata = cast[ptr cuchar](result.cstring)
+  let frdata = cast[ptr uint8](fr.cstring)
+  var todata = cast[ptr uint8](result.cstring)
   let lenOrig = RSA_private_decrypt(rsaLen, frdata, todata, rsa, RSA_PKCS1_PADDING)
   doAssert lenOrig >= 0 and lenOrig < result.len
   doAssert result[lenOrig] == '\0'
diff --git a/tests/stdlib/toptions.nim b/tests/stdlib/toptions.nim
index 71c52a07e..63a10e746 100644
--- a/tests/stdlib/toptions.nim
+++ b/tests/stdlib/toptions.nim
@@ -1,9 +1,13 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/[json, options]
 
+import std/assertions
+import std/objectdollar
+
 
 # RefPerson is used to test that overloaded `==` operator is not called by
 # options. It is defined here in the global scope, because otherwise the test
@@ -192,6 +196,12 @@ proc main() =
         doAssert x.isNone
         doAssert $x == "none(cstring)"
 
-
 static: main()
 main()
+
+when not defined(js):
+  block: # bug #22932
+    var it = iterator: int {.closure.} = discard
+    doAssert it.option.isSome # Passes.
+    it = nil
+    doAssert it.option.isNone # Passes.
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index 3f62a098f..611659fdb 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -22,11 +22,13 @@ __really_obscure_dir_name/test
 Raises
 Raises
 '''
+  matrix: "--mm:refc; --mm:orc"
+  joinable: false
 """
 # test os path creation, iteration, and deletion
 
-import os, strutils, pathnorm
 from stdtest/specialpaths import buildDir
+import std/[syncio, assertions, osproc, os, strutils, pathnorm]
 
 block fileOperations:
   let files = @["these.txt", "are.x", "testing.r", "files.q"]
@@ -38,7 +40,7 @@ block fileOperations:
   doAssert dirExists(dname)
 
   block: # copyFile, copyFileToDir
-    doAssertRaises(OSError): copyFile(dname/"nonexistant.txt", dname/"nonexistant.txt")
+    doAssertRaises(OSError): copyFile(dname/"nonexistent.txt", dname/"nonexistent.txt")
     let fname = "D20201009T112235"
     let fname2 = "D20201009T112235.2"
     let str = "foo1\0foo2\nfoo3\0"
@@ -155,6 +157,21 @@ block fileOperations:
   doAssert fileExists("../dest/a/file.txt")
   removeDir("../dest")
 
+  # createDir should not fail if `dir` is empty
+  createDir("")
+
+
+  when defined(linux): # bug #24174
+    createDir("a/b")
+    open("a/file.txt", fmWrite).close
+
+    if not fileExists("a/fifoFile"):
+      doAssert execCmd("mkfifo -m 600 a/fifoFile") == 0
+
+    copyDir("a/", "../dest/a/", skipSpecial = true)
+    copyDirWithPermissions("a/", "../dest2/a/", skipSpecial = true)
+    removeDir("a")
+
   # Symlink handling in `copyFile`, `copyFileWithPermissions`, `copyFileToDir`,
   # `copyDir`, `copyDirWithPermissions`, `moveFile`, and `moveDir`.
   block:
@@ -164,7 +181,7 @@ block fileOperations:
     const subDir2 = dname/"sub2"
     const brokenSymlinkName = "D20210101T191320_BROKEN_SYMLINK"
     const brokenSymlink = dname/brokenSymlinkName
-    const brokenSymlinkSrc = "D20210101T191320_nonexistant"
+    const brokenSymlinkSrc = "D20210101T191320_nonexistent"
     const brokenSymlinkCopy = brokenSymlink & "_COPY"
     const brokenSymlinkInSubDir = subDir/brokenSymlinkName
     const brokenSymlinkInSubDir2 = subDir2/brokenSymlinkName
@@ -261,6 +278,51 @@ block fileOperations:
 
     removeDir(dname)
 
+block: # moveFile
+  let tempDir = getTempDir() / "D20210609T151608"
+  createDir(tempDir)
+  defer: removeDir(tempDir)
+
+  writeFile(tempDir / "a.txt", "")
+  moveFile(tempDir / "a.txt", tempDir / "b.txt")
+  doAssert not fileExists(tempDir / "a.txt")
+  doAssert fileExists(tempDir / "b.txt")
+  removeFile(tempDir / "b.txt")
+
+  createDir(tempDir / "moveFile_test")
+  writeFile(tempDir / "moveFile_test/a.txt", "")
+  moveFile(tempDir / "moveFile_test/a.txt", tempDir / "moveFile_test/b.txt")
+  doAssert not fileExists(tempDir / "moveFile_test/a.txt")
+  doAssert fileExists(tempDir / "moveFile_test/b.txt")
+  removeDir(tempDir / "moveFile_test")
+
+  createDir(tempDir / "moveFile_test")
+  writeFile(tempDir / "a.txt", "")
+  moveFile(tempDir / "a.txt", tempDir / "moveFile_test/b.txt")
+  doAssert not fileExists(tempDir / "a.txt")
+  doAssert fileExists(tempDir / "moveFile_test/b.txt")
+  removeDir(tempDir / "moveFile_test")
+
+block: # moveDir
+  let tempDir = getTempDir() / "D20210609T161443"
+  createDir(tempDir)
+  defer: removeDir(tempDir)
+
+  createDir(tempDir / "moveDir_test")
+  moveDir(tempDir / "moveDir_test/", tempDir / "moveDir_test_dest")
+  doAssert not dirExists(tempDir / "moveDir_test")
+  doAssert dirExists(tempDir / "moveDir_test_dest")
+  removeDir(tempDir / "moveDir_test_dest")
+
+  createDir(tempDir / "moveDir_test")
+  writeFile(tempDir / "moveDir_test/a.txt", "")
+  moveDir(tempDir / "moveDir_test", tempDir / "moveDir_test_dest")
+  doAssert not dirExists(tempDir / "moveDir_test")
+  doAssert not fileExists(tempDir / "moveDir_test/a.txt")
+  doAssert dirExists(tempDir / "moveDir_test_dest")
+  doAssert fileExists(tempDir / "moveDir_test_dest/a.txt")
+  removeDir(tempDir / "moveDir_test_dest")
+
 import times
 block modificationTime:
   # Test get/set modification times
@@ -285,7 +347,7 @@ block walkDirRec:
     doAssert p.startsWith("walkdir_test")
 
   var s: seq[string]
-  for p in walkDirRec("walkdir_test", {pcFile}, {pcDir}, relative=true):
+  for p in walkDirRec("walkdir_test", {pcFile}, {pcDir}, relative = true):
     s.add(p)
 
   doAssert s.len == 2
@@ -294,11 +356,13 @@ block walkDirRec:
 
   removeDir("walkdir_test")
 
+import std/sequtils
+
 block: # walkDir
   doAssertRaises(OSError):
-    for a in walkDir("nonexistant", checkDir = true): discard
+    for a in walkDir("nonexistent", checkDir = true): discard
   doAssertRaises(OSError):
-    for p in walkDirRec("nonexistant", checkDir = true): discard
+    for p in walkDirRec("nonexistent", checkDir = true): discard
 
   when not defined(windows):
     block walkDirRelative:
@@ -308,6 +372,21 @@ block: # walkDir
         doAssert k == pcLinkToDir
       removeDir("walkdir_test")
 
+  when defined(posix):
+    block walkDirSpecial:
+      createDir("walkdir_test")
+      doAssert execShellCmd("mkfifo walkdir_test/fifo") == 0
+      createSymlink("fifo", "walkdir_test/fifo_link")
+      let withSpecialFiles = toSeq(walkDir("walkdir_test", relative = true))
+      doAssert (withSpecialFiles.len == 2 and
+                (pcFile, "fifo") in withSpecialFiles and
+                (pcLinkToFile, "fifo_link") in withSpecialFiles)
+      # now Unix special files are excluded from walkdir output:
+      let skipSpecialFiles = toSeq(walkDir("walkdir_test", relative = true,
+                                           skipSpecial = true))
+      doAssert skipSpecialFiles.len == 0
+      removeDir("walkdir_test")
+
 block normalizedPath:
   doAssert normalizedPath("") == ""
   block relative:
@@ -462,7 +541,11 @@ block ospaths:
   doAssert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') == "../../me/bar/z.nim"
 
   doAssert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') == "../me/bar/z.nim"
-  doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim"
+
+  # `//` is a UNC path, `/` is the current working directory's drive, so can't
+  # run this test on Windows.
+  when not doslikeFileSystem:
+    doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim"
   doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
   doAssert relativePath("", "/users/moo", '/') == ""
   doAssert relativePath("foo", "", '/') == "foo"
@@ -507,19 +590,19 @@ block ospaths:
   doAssert joinPath("/", "") == unixToNativePath"/"
   doAssert joinPath("/" / "") == unixToNativePath"/" # weird test case...
   doAssert joinPath("/", "/a/b/c") == unixToNativePath"/a/b/c"
-  doAssert joinPath("foo/","") == unixToNativePath"foo/"
-  doAssert joinPath("foo/","abc") == unixToNativePath"foo/abc"
-  doAssert joinPath("foo//./","abc/.//") == unixToNativePath"foo/abc/"
-  doAssert joinPath("foo","abc") == unixToNativePath"foo/abc"
-  doAssert joinPath("","abc") == unixToNativePath"abc"
+  doAssert joinPath("foo/", "") == unixToNativePath"foo/"
+  doAssert joinPath("foo/", "abc") == unixToNativePath"foo/abc"
+  doAssert joinPath("foo//./", "abc/.//") == unixToNativePath"foo/abc/"
+  doAssert joinPath("foo", "abc") == unixToNativePath"foo/abc"
+  doAssert joinPath("", "abc") == unixToNativePath"abc"
 
-  doAssert joinPath("gook/.","abc") == unixToNativePath"gook/abc"
+  doAssert joinPath("zook/.", "abc") == unixToNativePath"zook/abc"
 
-  # controversial: inconsistent with `joinPath("gook/.","abc")`
+  # controversial: inconsistent with `joinPath("zook/.","abc")`
   # on linux, `./foo` and `foo` are treated a bit differently for executables
   # but not `./foo/bar` and `foo/bar`
   doAssert joinPath(".", "/lib") == unixToNativePath"./lib"
-  doAssert joinPath(".","abc") == unixToNativePath"./abc"
+  doAssert joinPath(".", "abc") == unixToNativePath"./abc"
 
   # cases related to issue #13455
   doAssert joinPath("foo", "", "") == "foo"
@@ -549,27 +632,15 @@ block getTempDir:
       if existsEnv("TMPDIR"):
         let origTmpDir = getEnv("TMPDIR")
         putEnv("TMPDIR", "/mytmp")
-        doAssert getTempDir() == "/mytmp"
+        doAssert getTempDir() == "/mytmp/"
         delEnv("TMPDIR")
-        doAssert getTempDir() == "/tmp"
+        doAssert getTempDir() == "/tmp/"
         putEnv("TMPDIR", origTmpDir)
       else:
-        doAssert getTempDir() == "/tmp"
-
-block osenv:
-  block delEnv:
-    const dummyEnvVar = "DUMMY_ENV_VAR" # This env var wouldn't be likely to exist to begin with
-    doAssert existsEnv(dummyEnvVar) == false
-    putEnv(dummyEnvVar, "1")
-    doAssert existsEnv(dummyEnvVar) == true
-    delEnv(dummyEnvVar)
-    doAssert existsEnv(dummyEnvVar) == false
-    delEnv(dummyEnvVar)         # deleting an already deleted env var
-    doAssert existsEnv(dummyEnvVar) == false
-  block:
-    doAssert getEnv("DUMMY_ENV_VAR_NONEXISTENT", "") == ""
-    doAssert getEnv("DUMMY_ENV_VAR_NONEXISTENT", " ") == " "
-    doAssert getEnv("DUMMY_ENV_VAR_NONEXISTENT", "Arrakis") == "Arrakis"
+        doAssert getTempDir() == "/tmp/"
+
+block: # getCacheDir
+  doAssert getCacheDir().dirExists
 
 block isRelativeTo:
   doAssert isRelativeTo("/foo", "/")
@@ -588,7 +659,18 @@ block: # quoteShellWindows
   doAssert quoteShellWindows("aaa\"") == "aaa\\\""
   doAssert quoteShellWindows("") == "\"\""
 
-block: # quoteShellWindows
+block: # quoteShellCommand
+  when defined(windows):
+    doAssert quoteShellCommand(["a b c", "d", "e"]) == """"a b c" d e"""
+    doAssert quoteShellCommand(["""ab"c""", r"\", "d"]) == """ab\"c \ d"""
+    doAssert quoteShellCommand(["""ab"c""", """ \""", "d"]) == """ab\"c " \\" d"""
+    doAssert quoteShellCommand(["""a\\\b""", """de fg""", "h"]) == """a\\\b "de fg" h"""
+    doAssert quoteShellCommand(["""a\"b""", "c", "d"]) == """a\\\"b c d"""
+    doAssert quoteShellCommand(["""a\\b c""", "d", "e"]) == """"a\\b c" d e"""
+    doAssert quoteShellCommand(["""a\\b\ c""", "d", "e"]) == """"a\\b\ c" d e"""
+    doAssert quoteShellCommand(["ab", ""]) == """ab """""
+
+block: # quoteShellPosix
   doAssert quoteShellPosix("aaa") == "aaa"
   doAssert quoteShellPosix("aaa a") == "'aaa a'"
   doAssert quoteShellPosix("") == "''"
@@ -619,7 +701,121 @@ block: # normalizePathEnd
     doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\"
     doAssert "/".normalizePathEnd == r"\"
 
-block: # isValidFilename
+
+import sugar
+
+block: # normalizeExe
+  doAssert "".dup(normalizeExe) == ""
+  when defined(posix):
+    doAssert "foo".dup(normalizeExe) == "./foo"
+    doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar"
+  when defined(windows):
+    doAssert "foo".dup(normalizeExe) == "foo"
+
+block: # isAdmin
+  let isAzure = existsEnv("TF_BUILD") # xxx factor with testament.specs.isAzure
+  # In Azure on Windows tests run as an admin user
+  if isAzure and defined(windows): doAssert isAdmin()
+  # In Azure on POSIX tests run as a normal user
+  if isAzure and defined(posix): doAssert not isAdmin()
+
+
+import sugar
+
+block: # normalizeExe
+  doAssert "".dup(normalizeExe) == ""
+  when defined(posix):
+    doAssert "foo".dup(normalizeExe) == "./foo"
+    doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar"
+  when defined(windows):
+    doAssert "foo".dup(normalizeExe) == "foo"
+
+block: # isAdmin
+  let isAzure = existsEnv("TF_BUILD") # xxx factor with testament.specs.isAzure
+  # In Azure on Windows tests run as an admin user
+  if isAzure and defined(windows): doAssert isAdmin()
+  # In Azure on POSIX tests run as a normal user
+  if isAzure and defined(posix): doAssert not isAdmin()
+
+when doslikeFileSystem:
+  import std/private/ntpath
+
+  block: # Bug #19103 UNC paths
+
+    # Easiest way of generating a valid, readable and writable UNC path
+    let tempDir = r"\\?\" & getTempDir()
+    doAssert dirExists tempDir
+    createDir tempDir / "test"
+    removeDir tempDir / "test"
+    createDir tempDir / "recursive" / "test"
+    removeDir tempDir / "recursive" / "test"
+
+    let tempDir2 = getTempDir()
+    let (drive, pathNoDrive) = splitDrive(tempDir2)
+    setCurrentDir drive
+    doAssert cmpIgnoreCase(getCurrentDir().splitDrive.drive, drive) == 0
+
+    # Test `\Users` path syntax on Windows by stripping away drive. `\`
+    # resolves to the drive in current working directory. This drive will be
+    # the same as `tempDir2` because of the `setCurrentDir` above.
+    doAssert pathNoDrive[0] == '\\'
+    createDir pathNoDrive / "test"
+    doAssert dirExists pathNoDrive / "test"
+    removeDir pathNoDrive / "test"
+
+    doAssert splitPath("//?/c:") == ("//?/c:", "")
+
+    doAssert relativePath("//?/c:///Users//me", "//?/c:", '/') == "Users/me"
+
+    doAssert parentDir(r"\\?\c:") == r""
+    doAssert parentDir(r"//?/c:/Users") == r"\\?\c:"
+    doAssert parentDir(r"\\localhost\c$") == r""
+    doAssert parentDir(r"\Users") == r"\"
+
+    doAssert tailDir("//?/c:") == ""
+    doAssert tailDir("//?/c:/Users") == "Users"
+    doAssert tailDir(r"\\localhost\c$\Windows\System32") == r"Windows\System32"
+
+    doAssert isRootDir("//?/c:")
+    doAssert isRootDir("//?/UNC/localhost/c$")
+    doAssert not isRootDir(r"\\?\c:\Users")
+
+    doAssert parentDirs(r"C:\Users", fromRoot = true).toSeq == @[r"C:\", r"C:\Users"]
+    doAssert parentDirs(r"C:\Users", fromRoot = false).toSeq == @[r"C:\Users", r"C:"]
+    doAssert parentDirs(r"\\?\c:\Users", fromRoot = true).toSeq ==
+      @[r"\\?\c:\", r"\\?\c:\Users"]
+    doAssert parentDirs(r"\\?\c:\Users", fromRoot = false).toSeq ==
+      @[r"\\?\c:\Users", r"\\?\c:"]
+    doAssert parentDirs(r"//localhost/c$/Users", fromRoot = true).toSeq ==
+      @[r"//localhost/c$/", r"//localhost/c$/Users"]
+    doAssert parentDirs(r"//?/UNC/localhost/c$/Users", fromRoot = false).toSeq ==
+      @[r"//?/UNC/localhost/c$/Users", r"\\?\UNC\localhost\c$"]
+    doAssert parentDirs(r"\Users", fromRoot = true).toSeq == @[r"\", r"\Users"]
+    doAssert parentDirs(r"\Users", fromRoot = false).toSeq == @[r"\Users", r"\"]
+
+    doAssert r"//?/c:" /../ "d/e" == r"\\?\c:\d\e"
+    doAssert r"//?/c:/Users" /../ "d/e" == r"\\?\c:\d\e"
+    doAssert r"\\localhost\c$" /../ "d/e" == r"\\localhost\c$\d\e"
+
+    doAssert splitFile("//?/c:") == ("//?/c:", "", "")
+    doAssert splitFile("//?/c:/Users") == ("//?/c:", "Users", "")
+    doAssert splitFile(r"\\localhost\c$\test.txt") == (r"\\localhost\c$", "test", ".txt")
+
+else:
+  block: # parentDirs
+    doAssert parentDirs("/home", fromRoot=true).toSeq == @["/", "/home"]
+    doAssert parentDirs("/home", fromRoot=false).toSeq == @["/home", "/"]
+    doAssert parentDirs("home", fromRoot=true).toSeq == @["home"]
+    doAssert parentDirs("home", fromRoot=false).toSeq == @["home"]
+
+    doAssert parentDirs("/home/user", fromRoot=true).toSeq == @["/", "/home/", "/home/user"]
+    doAssert parentDirs("/home/user", fromRoot=false).toSeq == @["/home/user", "/home", "/"]
+    doAssert parentDirs("home/user", fromRoot=true).toSeq == @["home/", "home/user"]
+    doAssert parentDirs("home/user", fromRoot=false).toSeq == @["home/user", "home"]
+
+
+# https://github.com/nim-lang/Nim/pull/19643#issuecomment-1235102314
+block:  # isValidFilename
   # Negative Tests.
   doAssert not isValidFilename("abcd", maxLen = 2)
   doAssert not isValidFilename("0123456789", maxLen = 8)
@@ -646,19 +842,34 @@ block: # isValidFilename
   doAssert isValidFilename("nim.nim")
   doAssert isValidFilename("foo.log")
 
-import sugar
+block: # searchExtPos
+  doAssert "foo.nim".searchExtPos == 3
+  doAssert "/foo.nim".searchExtPos == 4
+  doAssert "".searchExtPos == -1
+  doAssert "/".searchExtPos == -1
+  doAssert "a.b/foo".searchExtPos == -1
+  doAssert ".".searchExtPos == -1
+  doAssert "foo.".searchExtPos == 3
+  doAssert "foo..".searchExtPos == 4
+  doAssert "..".searchExtPos == -1
+  doAssert "...".searchExtPos == -1
+  doAssert "./".searchExtPos == -1
+  doAssert "../".searchExtPos == -1
+  doAssert "/.".searchExtPos == -1
+  doAssert "/..".searchExtPos == -1
+  doAssert ".b".searchExtPos == -1
+  doAssert "..b".searchExtPos == -1
+  doAssert "/.b".searchExtPos == -1
+  doAssert "a/.b".searchExtPos == -1
+  doAssert ".a.b".searchExtPos == 2
+  doAssert "a/.b.c".searchExtPos == 4
+  doAssert "a/..b".searchExtPos == -1
+  doAssert "a/b..c".searchExtPos == 4
 
-block: # normalizeExe
-  doAssert "".dup(normalizeExe) == ""
-  when defined(posix):
-    doAssert "foo".dup(normalizeExe) == "./foo"
-    doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar"
-  when defined(windows):
-    doAssert "foo".dup(normalizeExe) == "foo"
-
-block: # isAdmin
-  let isAzure = existsEnv("TF_BUILD") # xxx factor with testament.specs.isAzure
-  # In Azure on Windows tests run as an admin user
-  if isAzure and defined(windows): doAssert isAdmin()
-  # In Azure on POSIX tests run as a normal user
-  if isAzure and defined(posix): doAssert not isAdmin()
+  when doslikeFileSystem:
+    doAssert "c:a.b".searchExtPos == 3
+    doAssert "c:.a".searchExtPos == -1
+    doAssert r"c:\.a".searchExtPos == -1
+    doAssert "c:..a".searchExtPos == -1
+    doAssert r"c:\..a".searchExtPos == -1
+    doAssert "c:.a.b".searchExtPos == 4
diff --git a/tests/stdlib/tos_unc.nim b/tests/stdlib/tos_unc.nim
index e55de11ce..194deeb42 100644
--- a/tests/stdlib/tos_unc.nim
+++ b/tests/stdlib/tos_unc.nim
@@ -1,9 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   disabled: "posix"
 """
 
 # bug 10952, UNC paths
 import os
+import std/assertions
 
 doAssert r"\\hostname\foo\bar" / "baz" == r"\\hostname\foo\bar\baz"
 doAssert r"\\?\C:\foo" / "bar" == r"\\?\C:\foo\bar"
diff --git a/tests/stdlib/tosenv.nim b/tests/stdlib/tosenv.nim
new file mode 100644
index 000000000..17e397987
--- /dev/null
+++ b/tests/stdlib/tosenv.nim
@@ -0,0 +1,163 @@
+discard """
+  matrix: "--mm:refc; --mm:arc"
+  joinable: false
+  targets: "c js cpp"
+"""
+
+import std/os
+from std/sequtils import toSeq
+import stdtest/testutils
+
+when defined(nimPreviewSlimSystem):
+  import std/[assertions]
+
+# "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386)
+const unicodeUtf8 = "\xc3\x86"
+
+template main =
+  block: # delEnv, existsEnv, getEnv, envPairs
+    for val in ["val", "", unicodeUtf8]: # ensures empty val works too
+      const key = "NIM_TESTS_TOSENV_KEY"
+      doAssert not existsEnv(key)
+
+      putEnv(key, "tempval")
+      doAssert existsEnv(key)
+      doAssert getEnv(key) == "tempval"
+
+      putEnv(key, val) # change a key that already exists
+      doAssert existsEnv(key)
+      doAssert getEnv(key) == val
+
+      doAssert (key, val) in toSeq(envPairs())
+      delEnv(key)
+      doAssert (key, val) notin toSeq(envPairs())
+      doAssert not existsEnv(key)
+      delEnv(key) # deleting an already deleted env var
+      doAssert not existsEnv(key)
+
+    block:
+      doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "") == ""
+      doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", " ") == " "
+      doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "defval") == "defval"
+
+    whenVMorJs: discard # xxx improve
+    do:
+      doAssertRaises(OSError, putEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE", "NEW_DUMMY_VALUE"))
+      doAssertRaises(OSError, putEnv("", "NEW_DUMMY_VALUE"))
+      doAssert not existsEnv("")
+      doAssert not existsEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE")
+      doAssert not existsEnv("NIM_TESTS_TOSENV_PUT")
+
+static: main()
+main()
+
+when defined(windows):
+  import std/widestrs
+  proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".}
+proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
+
+when not defined(js) and not defined(nimscript):
+  when defined(nimPreviewSlimSystem):
+    import std/typedthreads
+  block: # bug #18533
+    var thr: Thread[void]
+    proc threadFunc {.thread.} = putEnv("foo", "fooVal2")
+
+    putEnv("foo", "fooVal1")
+    doAssert getEnv("foo") == "fooVal1"
+    createThread(thr, threadFunc)
+    joinThreads(thr)
+    when defined(windows):
+      doAssert getEnv("foo") == $c_wgetenv("foo".newWideCString)
+    else:
+      doAssert getEnv("foo") == $c_getenv("foo".cstring)
+
+    doAssertRaises(OSError): delEnv("foo=bar")
+
+when defined(windows) and not defined(nimscript):
+  import std/encodings
+
+  proc c_putenv(env: cstring): int32 {.importc: "putenv", header: "<stdlib.h>".}
+  proc c_wputenv(env: WideCString): int32 {.importc: "_wputenv", header: "<stdlib.h>".}
+
+  block: # Bug #20083
+    # These test that `getEnv`, `putEnv` and `existsEnv` handle Unicode
+    # characters correctly. This means that module X in the process calling the
+    # CRT environment variable API will get the correct string. Raw CRT API
+    # calls below represent module X.
+
+    # Getting an env. var. with unicode characters returns the correct UTF-8
+    # encoded string.
+    block:
+      const envName = "twin_envvars1"
+      doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
+      doAssert existsEnv(envName)
+      doAssert getEnv(envName) == unicodeUtf8
+
+    # Putting an env. var. with unicode characters gives the correct UTF-16
+    # encoded string from low-level routine.
+    block:
+      const envName = "twin_envvars2"
+      putEnv(envName, unicodeUtf8)
+      doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
+
+    # Env. name containing Unicode characters is retrieved correctly
+    block:
+      const envName = unicodeUtf8 & "1"
+      doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
+      doAssert existsEnv(envName)
+      doAssert getEnv(envName) == unicodeUtf8
+
+    # Env. name containing Unicode characters is set correctly
+    block:
+      const envName = unicodeUtf8 & "2"
+      putEnv(envName, unicodeUtf8)
+      doAssert existsEnv(envName)
+      doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
+
+    # Env. name containing Unicode characters and empty value is set correctly
+    block:
+      const envName = unicodeUtf8 & "3"
+      putEnv(envName, "")
+      doAssert existsEnv(envName)
+      doAssert $c_wgetenv(envName.newWideCString) == ""
+
+    # It's hard to test on Windows code pages, because there is no "change
+    # a process' locale" API.
+    if getCurrentEncoding(true) == "windows-1252":
+      const
+        unicodeAnsi = "\xc6" # `unicodeUtf8` in `windows-1252` encoding
+
+      # Test that env. var. ANSI API has correct encoding
+      block:
+        const
+          envName = unicodeUtf8 & "4"
+          envNameAnsi = unicodeAnsi & "4"
+        putEnv(envName, unicodeUtf8)
+        doAssert $c_getenv(envNameAnsi.cstring) == unicodeAnsi
+
+      block:
+        const
+          envName = unicodeUtf8 & "5"
+          envNameAnsi = unicodeAnsi & "5"
+        doAssert c_putenv((envNameAnsi & "=" & unicodeAnsi).cstring) == 0
+        doAssert getEnv(envName) == unicodeUtf8
+
+      # Env. name containing Unicode characters and empty value is set correctly;
+      # and, if env. name. characters cannot be represented in codepage, don't
+      # raise an error.
+      #
+      # `win_setenv.nim` converts UTF-16 to ANSI when setting empty env. var. The
+      # windows-1250 locale has no representation of `abreveUtf8` below, so the
+      # conversion will fail, but this must not be fatal. It is expected that the
+      # routine ignores updating MBCS environment (`environ` global) and carries
+      # on.
+      block:
+        const
+          # "LATIN SMALL LETTER A WITH BREVE" in UTF-8
+          abreveUtf8 = "\xc4\x83"
+          envName = abreveUtf8 & "6"
+        putEnv(envName, "")
+        doAssert existsEnv(envName)
+        doAssert $c_wgetenv(envName.newWideCString) == ""
+        doAssert getEnv(envName) == ""
diff --git a/tests/stdlib/toserrors.nim b/tests/stdlib/toserrors.nim
new file mode 100644
index 000000000..e907dfe63
--- /dev/null
+++ b/tests/stdlib/toserrors.nim
@@ -0,0 +1,9 @@
+discard """
+  action: compile
+"""
+
+import std/oserrors
+
+let x1 = osLastError()
+raiseOSError(x1)
+echo osErrorMsg(x1)
diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim
index 96cff1468..da4f6252d 100644
--- a/tests/stdlib/tosproc.nim
+++ b/tests/stdlib/tosproc.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 joinable: false
 """
 
@@ -9,10 +10,11 @@ because it'd need cleanup up stdout
 see also: tests/osproc/*.nim; consider merging those into a single test here
 (easier to factor and test more things as a single self contained test)
 ]#
+import std/[assertions, syncio]
 
 when defined(case_testfile): # compiled test file for child process
   from posix import exitnow
-  proc c_exit2(code: c_int): void {.importc: "_exit", header: "<unistd.h>".}
+  proc c_exit2(code: cint): void {.importc: "_exit", header: "<unistd.h>".}
   import os
   var a = 0
   proc fun(b = 0) =
@@ -29,6 +31,12 @@ when defined(case_testfile): # compiled test file for child process
     case arg
     of "exit_0":
       if true: quit(0)
+    of "exit_1":
+      if true: quit(1)
+    of "exit_2":
+      if true: quit(2)
+    of "exit_42":
+      if true: quit(42)
     of "exitnow_139":
       if true: exitnow(139)
     of "c_exit2_139":
@@ -86,9 +94,7 @@ else: # main driver
   const sourcePath = currentSourcePath()
   let dir = getCurrentDir() / "tests" / "osproc"
 
-  template deferScoped(cleanup, body) =
-    # pending https://github.com/nim-lang/RFCs/issues/236#issuecomment-646855314
-    # xxx move to std/sugar or (preferably) some low level module
+  template deferring(cleanup, body) =
     try: body
     finally: cleanup
 
@@ -113,7 +119,17 @@ else: # main driver
     runTest("exit_0", 0)
     runTest("exitnow_139", 139)
     runTest("c_exit2_139", 139)
-    runTest("quit_139", 139)
+    when defined(posix):
+      runTest("quit_139", 127) # The quit value gets saturated to 127
+    else:
+      runTest("quit_139", 139)
+
+  block execCmdTest:
+    let output = compileNimProg("-d:release -d:case_testfile", "D20220705T221100")
+    doAssert execCmd(output & " exit_0") == 0
+    doAssert execCmd(output & " exit_1") == 1
+    doAssert execCmd(output & " exit_2") == 2
+    doAssert execCmd(output & " exit_42") == 42
 
   import std/streams
 
@@ -206,8 +222,8 @@ else: # main driver
       var line = newStringOfCap(120)
       while true:
         if outp.readLine(line):
-          result[0].string.add(line.string)
-          result[0].string.add("\n")
+          result[0].add(line)
+          result[0].add("\n")
         else:
           result[1] = peekExitCode(p)
           if result[1] != -1: break
@@ -232,14 +248,14 @@ else: # main driver
     var x = newStringOfCap(120)
     block: # startProcess stdout poStdErrToStdOut (replaces old test `tstdout` + `ta_out`)
       var p = startProcess(output, dir, options={poStdErrToStdOut})
-      deferScoped: p.close()
+      deferring: p.close()
       do:
         var sout: seq[string]
         while p.outputStream.readLine(x): sout.add x
         doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stderr", "to stderr", "to stdout", "to stdout", "end ta_out"]
     block: # startProcess stderr (replaces old test `tstderr` + `ta_out`)
       var p = startProcess(output, dir, options={})
-      deferScoped: p.close()
+      deferring: p.close()
       do:
         var serr, sout: seq[string]
         while p.errorStream.readLine(x): serr.add x
@@ -272,10 +288,29 @@ else: # main driver
     stripLineEnd(result[0])
     doAssert result == ("12", 0)
     when not defined(windows):
-      doAssert execCmdEx("ls --nonexistant").exitCode != 0
+      doAssert execCmdEx("ls --nonexistent").exitCode != 0
     when false:
       # bug: on windows, this raises; on posix, passes
-      doAssert execCmdEx("nonexistant").exitCode != 0
+      doAssert execCmdEx("nonexistent").exitCode != 0
     when defined(posix):
       doAssert execCmdEx("echo $FO", env = newStringTable({"FO": "B"})) == ("B\n", 0)
       doAssert execCmdEx("echo $PWD", workingDir = "/") == ("/\n", 0)
+
+  block: # bug #17749
+    let output = compileNimProg("-d:case_testfile4", "D20210417T011153")
+    var p = startProcess(output, dir)
+    let inp = p.inputStream
+    var count = 0
+    when defined(windows):
+      # xxx we should make osproc.hsWriteData raise IOError on windows, consistent
+      # with posix; we could also (in addition) make IOError a subclass of OSError.
+      type SIGPIPEError = OSError
+    else:
+      type SIGPIPEError = IOError
+    doAssertRaises(SIGPIPEError):
+      for i in 0..<100000:
+        count.inc
+        inp.writeLine "ok" # was giving SIGPIPE and crashing
+    doAssert count >= 100
+    doAssert waitForExit(p) == QuitFailure
+    close(p) # xxx isn't that missing in other places?
diff --git a/tests/stdlib/tosprocterminate.nim b/tests/stdlib/tosprocterminate.nim
index 8e9041b81..93b0317f7 100644
--- a/tests/stdlib/tosprocterminate.nim
+++ b/tests/stdlib/tosprocterminate.nim
@@ -1,10 +1,11 @@
 discard """
   cmd: "nim $target $options -r $file"
   targets: "c cpp"
-  matrix: "--threads:on; "
+  matrix: "--mm:refc; --mm:orc"
 """
 
 import os, osproc, times, std / monotimes
+import std/assertions
 
 when defined(windows):
   const ProgramWhichDoesNotEnd = "notepad"
diff --git a/tests/stdlib/tpackedsets.nim b/tests/stdlib/tpackedsets.nim
index d0149adc5..f519c08a7 100644
--- a/tests/stdlib/tpackedsets.nim
+++ b/tests/stdlib/tpackedsets.nim
@@ -1,9 +1,15 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/packedsets
 import std/sets
 
 import sequtils
 import algorithm
 
+import std/assertions
+
 block basicIntSetTests:
   var y = initPackedSet[int]()
   y.incl(1)
diff --git a/tests/stdlib/tparsecfg.nim b/tests/stdlib/tparsecfg.nim
index 5c077bbda..2600d6f66 100644
--- a/tests/stdlib/tparsecfg.nim
+++ b/tests/stdlib/tparsecfg.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
-import parsecfg, streams
+import parsecfg, streams, sequtils
+import std/assertions
 
 when not defined(js):
   from stdtest/specialpaths import buildDir
@@ -39,19 +41,14 @@ var ss = newStringStream()
 dict1.writeConfig(ss)
 
 ## Reading a configuration file.
-var dict2 = loadConfig(newStringStream(ss.data))
-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")
-doAssert charset == "utf-8"
-doAssert threads == "on"
-doAssert pname == "hello"
-doAssert name == "lihf8515"
-doAssert qq == "10214028"
-doAssert email == "lihaifeng@wxm.com"
+let dict2 = loadConfig(newStringStream(ss.data))
+doAssert dict2.getSectionValue("", "charset") == "utf-8"
+doAssert dict2.getSectionValue("Package", "--threads") == "on"
+doAssert dict2.getSectionValue("Package", "name") == "hello"
+doAssert dict2.getSectionValue("Author", "name") == "lihf8515"
+doAssert dict2.getSectionValue("Author", "qq") == "10214028"
+doAssert dict2.getSectionValue("Author", "email") == "lihaifeng@wxm.com"
+doAssert toSeq(dict2.sections) == @["", "Package", "Author"]
 
 ## Modifying a configuration file.
 var dict3 = loadConfig(newStringStream(ss.data))
diff --git a/tests/stdlib/tparsecsv.nim b/tests/stdlib/tparsecsv.nim
index 0d004d45d..5a1e41bce 100644
--- a/tests/stdlib/tparsecsv.nim
+++ b/tests/stdlib/tparsecsv.nim
@@ -1,5 +1,10 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 include parsecsv
 import strutils, os
+import std/assertions
 
 block: # Tests for reading the header row
   let content = "\nOne,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n"
diff --git a/tests/stdlib/tparseipv6.nim b/tests/stdlib/tparseipv6.nim
index 3e1c23e58..31ec4ecfb 100644
--- a/tests/stdlib/tparseipv6.nim
+++ b/tests/stdlib/tparseipv6.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: "all ok"
 """
 
@@ -8,23 +9,23 @@ const
   positives = [
     "::f:8:a8f:218.17.235.229",
     "::b:228.19.241.2",
-    "::8:c:a:f:8.35.8.096",
-    "::3:e:a:bc:04.19.2.9",
+    "::8:c:a:f:8.35.8.96",
+    "::3:e:a:bc:4.19.2.9",
     "::2:212.242.248.19",
     "::df:a5f:3.250.208.9",
     "::8:c:5:e63:250.208.249.0",
     "::b:f:181.12.9.98",
-    "::a:f8:77.08.243.232",
-    "::a:b:85:e4d9:252.9.229.056",
+    "::a:f8:77.8.243.232",
+    "::a:b:85:e4d9:252.9.229.56",
     "941:c:8a:c:e::917",
     "e8:7a:e:ad:88a:8:203.235.225.46",
-    "139c:9e::f8:254.08.21.249",
+    "139c:9e::f8:254.8.21.249",
     "b38:f0:e::f9:89.6.12.18",
     "ef::8",
     "5::ab",
     "a::8:255.247.96.253",
     "b:c0::c:254.248.95.254",
-    "::8c:2:99.251.024.3",
+    "::8c:2:99.251.24.3",
     "98::c:247.240.249.57",
     "9::9",
     "628::f1ed:f",
@@ -106,68 +107,68 @@ const
     "::315",
     "::a:a",
     "::aed3:a",
-    "f0eb:0:e8:b:c:a:254.098.233.17",
+    "f0eb:0:e8:b:c:a:254.98.233.17",
     "bfa:7fc:c66d:15:e9a:ded:254.119.9.9",
-    "d:ffa8:9:a:879:3:202.39.08.245",
+    "d:ffa8:9:a:879:3:202.39.8.245",
     "8e:2:8:fa8a:f1d1:1aa8:252.254.245.81",
-    "5:d4:a:e9:8:8:06.38.98.253",
-    "9c5:4:a5c:f:a6:8c9d:05.250.8.2",
+    "5:d4:a:e9:8:8:6.38.98.253",
+    "9c5:4:a5c:f:a6:8c9d:5.250.8.2",
     "d19a:2:f808:be:f:c:98.86.197.249",
-    "8:26ac:8:8:cb:f:242.00.254.85",
+    "8:26ac:8:8:cb:f:242.0.254.85",
     "38:e:1:0b88:f:0:8.89.248.92",
-    "e7:ff96:a:f:f:b:253.91.052.195",
+    "e7:ff96:a:f:f:b:253.91.52.195",
     "d:8:2:5:894:5:254.0.240.199",
     "2:98:9:8aa:9c8f:fa:252.98.248.17",
-    "e9:d4f:890:ccbe:5:8:088.200.228.216",
+    "e9:d4f:890:ccbe:5:8:88.200.228.216",
     "3:3:9:5:6a:df5:255.251.8.12",
-    "0280:3:8:8:4:9:255.000.251.249",
+    "0280:3:8:8:4:9:255.0.251.249",
     "8:af7:db:aa:0:9:238.248.250.255",
-    "ff:ee:9a:9252:a:289:059.083.18.255",
+    "ff:ee:9a:9252:a:289:59.83.18.255",
     "9f6:5:fc9:b:a89:a:142.1.250.254",
     "e:981a:da:bf94:9:f8:254.242.18.95",
     "3c:1:4:f2:89:f:8.91.255.14",
-    "e::9a2:c:9.050.80.8",
+    "e::9a2:c:9.50.80.8",
     "9::4a:07:fb:211.241.254.228",
     "9be::2:e:215.189.48.188",
-    "f::f:d:069.148.99.168",
+    "f::f:d:69.148.99.168",
     "f::a:97.18.240.47",
     "c::a98e:1:251.253.252.254",
     "668::82:214.87.208.9",
     "9c0::cf0:ecb:253.208.238.255",
-    "a::0:f1:210.240.238.049",
-    "8::a:1:251.238.34.09",
+    "a::0:f1:210.240.238.49",
+    "8::a:1:251.238.34.9",
     "81:dfe::b8:8.255.249.248",
-    "d3::7:b:9:83.189.08.244",
-    "8::9:8:8:00.7.11.252",
+    "d3::7:b:9:83.189.8.244",
+    "8::9:8:8:0.7.11.252",
     "2:8::c:a8:250.221.9.249",
     "2::f:99.8.249.247",
     "c:22f5::5:2c:243.15.79.89",
     "e:8e::da:251.243.255.2",
     "f15f:9::a:255.70.247.218",
-    "f:b::9f38:31.220.94.022",
-    "9::9a48:03.98.249.119",
+    "f:b::9f38:31.220.94.22",
+    "9::9a48:3.98.249.119",
     "d:d:9b87::2d:a:249.253.38.8",
     "d86d:99b::a9b:5:242.236.8.244",
     "eb:3::f:9cf:1.253.1.228",
     "b::ba2:255.247.114.64",
-    "2f:ec:bcb::9:219.254.250.094",
+    "2f:ec:bcb::9:219.254.250.94",
     "da8a:f6::a:e0:19.251.241.251",
-    "5e:c1::a:021.250.8.254",
+    "5e:c1::a:21.250.8.254",
     "c:9::8c9b:248.219.212.252",
     "2:a::8d4a:216.255.198.223",
-    "1f::66:255.30.08.150",
+    "1f::66:255.30.8.150",
     "bc2b:8f::2ff9:6.245.99.230",
     "a:8::a8:9.251.246.255",
-    "f:7:7::98:06.14.1.208",
+    "f:7:7::98:6.14.1.208",
     "e:2::9:218.249.255.254",
     "79:f::6:250.255.98.246",
-    "47:9:fb9f::9:038.136.17.251",
+    "47:9:fb9f::9:38.136.17.251",
     "ed::a:247.9.23.239",
     "6f::f1:88.254.119.9",
     "a::d:218.199.236.0",
-    "fc88::9:203.196.04.95",
-    "::8.048.255.85",
-    "::253.07.255.36",
+    "fc88::9:203.196.4.95",
+    "::8.48.255.85",
+    "::253.7.255.36",
     "9:d::253.7.178.229",
     "::250.84.158.253",
     "::8.55.204.248",
@@ -175,39 +176,47 @@ const
     "df9:88ca::248.255.108.17",
     "8e9b::250.206.0.82",
     "::209.8.254.209",
-    "::247.088.8.8",
+    "::247.88.8.8",
     "::cb:f:ba41:250.208.19.249",
     "::fe:0e8:243.240.229.5",
     "::c:223.251.5.226",
-    "::8:08.03.8.250",
+    "::8:8.3.8.250",
     "::f:8.88.11.255",
-    "::fda:48:aa:05.189.07.2",
-    "::8:c3f:f:240.06.212.255",
+    "::fda:48:aa:5.189.7.2",
+    "::8:c3f:f:240.6.212.255",
     "::f:0aa:244.123.99.16",
-    "::c9b5:c:034.8.090.196",
+    "::c9b5:c:34.8.90.196",
     "::98:c9:254.14.241.81"
   ]
   negatives = ["foo.bar",
     "::::::::::::",
     "yet another failure",
-    "de:6:c:ab5:6a::9:252.06.06.249",
-    "f9:5f7:fa38:9:b::b6:09.255.248.252",
+    "de:6:c:ab5:6a::9:252.6.6.249",
+    "f9:5f7:fa38:9:b::b6:9.255.248.252",
     "97:c:5b:81:8a::f5dd:144.252.250.9",
-    "9:8:cd:8:a9::f:247.255.09.255",
+    "9:8:cd:8:a9::f:247.255.9.255",
     "18:1:8c:2:3::9:8.254.252.139",
-    "e:c298:3:e:a::bb12:254.246.05.250",
+    "e:c298:3:e:a::bb12:254.246.5.250",
     "e:e:c:8e:fd::8:253.8.49.231",
     "9:97f:f:e929:8a::c9:0.8.252.10",
-    "0df:b24:7:89:c::2b:16.249.240.092",
+    "0df:b24:7:89:c::2b:16.249.240.92",
     "b:8f5f:485:c:9a::84c:178.7.249.34",
+    "::3:e:a:bc:091.19.2.9",
+    "::a:f8:77.08.243.232",
+    "::8c:2:99.251.029.3",
+    "::8:c:a:f:8.35.8.096",
+    "d:ffa8:9:a:879:3:0202.39.8.245",
+    "139c:9e::f8:254.07.21.249",
+    "f0eb:0:e8:b:c:a:254.233.043.17",
+    "::a:b:85:e4d9:252.9.229.056",
   ]
 
-proc ok(pos: openarray[string]) =
+proc ok(pos: openArray[string]) =
   for p in pos:
     if not isIpAddress(p):
       echo "failure ", p
 
-proc notok(neg: openarray[string]) =
+proc notok(neg: openArray[string]) =
   for n in neg:
     if isIpAddress(n):
       echo "failure ", n
diff --git a/tests/stdlib/tparsesql.nim b/tests/stdlib/tparsesql.nim
index ba9e601a1..cd582551d 100644
--- a/tests/stdlib/tparsesql.nim
+++ b/tests/stdlib/tparsesql.nim
@@ -1,10 +1,23 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 import parsesql
+import std/assertions
 
-doAssert $parseSQL("SELECT foo FROM table;") == "select foo from table;"
-doAssert $parseSQL("""
+doAssert treeRepr(parseSql("INSERT INTO STATS VALUES (10, 5.5); ")
+) == """
+
+nkStmtList
+  nkInsert
+    nkIdent STATS
+    nkNone
+    nkValueList
+      nkIntegerLit 10
+      nkNumericLit 5.5"""
+
+doAssert $parseSql("SELECT foo FROM table;") == "select foo from table;"
+doAssert $parseSql("""
 SELECT
   CustomerName,
   ContactName,
@@ -20,26 +33,26 @@ SELECT
   Country
 FROM table;""") == "select CustomerName, ContactName, Address, City, PostalCode, Country, CustomerName, ContactName, Address, City, PostalCode, Country from table;"
 
-doAssert $parseSQL("SELECT foo FROM table limit 10") == "select foo from table limit 10;"
-doAssert $parseSQL("SELECT foo, bar, baz FROM table limit 10") == "select foo, bar, baz from table limit 10;"
-doAssert $parseSQL("SELECT foo AS bar FROM table") == "select foo as bar from table;"
-doAssert $parseSQL("SELECT foo AS foo_prime, bar AS bar_prime, baz AS baz_prime FROM table") == "select foo as foo_prime, bar as bar_prime, baz as baz_prime from table;"
-doAssert $parseSQL("SELECT * FROM table") == "select * from table;"
-doAssert $parseSQL("SELECT count(*) FROM table") == "select count(*) from table;"
-doAssert $parseSQL("SELECT count(*) as 'Total' FROM table") == "select count(*) as 'Total' from table;"
-doAssert $parseSQL("SELECT count(*) as 'Total', sum(a) as 'Aggr' FROM table") == "select count(*) as 'Total', sum(a) as 'Aggr' from table;"
+doAssert $parseSql("SELECT foo FROM table limit 10") == "select foo from table limit 10;"
+doAssert $parseSql("SELECT foo, bar, baz FROM table limit 10") == "select foo, bar, baz from table limit 10;"
+doAssert $parseSql("SELECT foo AS bar FROM table") == "select foo as bar from table;"
+doAssert $parseSql("SELECT foo AS foo_prime, bar AS bar_prime, baz AS baz_prime FROM table") == "select foo as foo_prime, bar as bar_prime, baz as baz_prime from table;"
+doAssert $parseSql("SELECT * FROM table") == "select * from table;"
+doAssert $parseSql("SELECT count(*) FROM table") == "select count(*) from table;"
+doAssert $parseSql("SELECT count(*) as 'Total' FROM table") == "select count(*) as 'Total' from table;"
+doAssert $parseSql("SELECT count(*) as 'Total', sum(a) as 'Aggr' FROM table") == "select count(*) as 'Total', sum(a) as 'Aggr' from table;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 WHERE a = b and c = d
 """) == "select * from table where a = b and c = d;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 WHERE not b
 """) == "select * from table where not b;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT
   *
 FROM
@@ -48,63 +61,63 @@ WHERE
   a and not b
 """) == "select * from table where a and not b;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 ORDER BY 1
 """) == "select * from table order by 1;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 GROUP BY 1
 ORDER BY 1
 """) == "select * from table group by 1 order by 1;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 ORDER BY 1
 LIMIT 100
 """) == "select * from table order by 1 limit 100;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 WHERE a = b and c = d or n is null and not b + 1 = 3
 """) == "select * from table where a = b and c = d or n is null and not b + 1 = 3;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 WHERE (a = b and c = d) or (n is null and not b + 1 = 3)
 """) == "select * from table where(a = b and c = d) or (n is null and not b + 1 = 3);"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM table
 HAVING a = b and c = d
 """) == "select * from table having a = b and c = d;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT a, b FROM table
 GROUP BY a
 """) == "select a, b from table group by a;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT a, b FROM table
 GROUP BY 1, 2
 """) == "select a, b from table group by 1, 2;"
 
-doAssert $parseSQL("SELECT t.a FROM t as t") == "select t.a from t as t;"
+doAssert $parseSql("SELECT t.a FROM t as t") == "select t.a from t as t;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT a, b FROM (
   SELECT * FROM t
 )
 """) == "select a, b from(select * from t);"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT a, b FROM (
   SELECT * FROM t
 ) as foo
 """) == "select a, b from(select * from t) as foo;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT a, b FROM (
   SELECT * FROM (
     SELECT * FROM (
@@ -116,49 +129,49 @@ SELECT a, b FROM (
 ) as inner5
 """) == "select a, b from(select * from(select * from(select * from(select * from innerTable as inner1) as inner2) as inner3) as inner4) as inner5;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT a, b FROM
   (SELECT * FROM a),
   (SELECT * FROM b),
   (SELECT * FROM c)
 """) == "select a, b from(select * from a),(select * from b),(select * from c);"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM Products
 WHERE Price BETWEEN 10 AND 20;
 """) == "select * from Products where Price between 10 and 20;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT id FROM a
 JOIN b
 ON a.id == b.id
 """) == "select id from a join b on a.id == b.id;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT id FROM a
 JOIN (SELECT id from c) as b
 ON a.id == b.id
 """) == "select id from a join(select id from c) as b on a.id == b.id;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT id FROM a
 INNER JOIN b
 ON a.id == b.id
 """) == "select id from a inner join b on a.id == b.id;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT id FROM a
 OUTER JOIN b
 ON a.id == b.id
 """) == "select id from a outer join b on a.id == b.id;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT id FROM a
 CROSS JOIN b
 ON a.id == b.id
 """) == "select id from a cross join b on a.id == b.id;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
 CREATE TABLE holidays (
   num_weeks int,
@@ -168,31 +181,54 @@ CREATE INDEX table1_attr1 ON table1(attr1);
 SELECT * FROM myTab WHERE col1 = 'happy';
 """) == "create type happiness as enum ('happy' , 'very happy' , 'ecstatic' ); create table holidays(num_weeks  int , happiness  happiness );; create index table1_attr1 on table1(attr1 );; select * from myTab where col1 = 'happy';"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
 VALUES ('Cardinal', 'Tom B. Erichsen', 'Skagen 21', 'Stavanger', '4006', 'Norway');
 """) == "insert into Customers (CustomerName , ContactName , Address , City , PostalCode , Country ) values ('Cardinal' , 'Tom B. Erichsen' , 'Skagen 21' , 'Stavanger' , '4006' , 'Norway' );"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 INSERT INTO TableName DEFAULT VALUES
 """) == "insert into TableName default values;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 UPDATE Customers
 SET ContactName = 'Alfred Schmidt', City= 'Frankfurt'
 WHERE CustomerID = 1;
 """) == "update Customers set ContactName  = 'Alfred Schmidt' , City  = 'Frankfurt' where CustomerID = 1;"
 
-doAssert $parseSQL("DELETE FROM table_name;") == "delete from table_name;"
+doAssert treeRepr(parseSql("""UPDATE Customers
+                              SET ContactName = 'Alice', City= 'Frankfurt';""")
+) == """
+
+nkStmtList
+  nkUpdate
+    nkIdent Customers
+    nkAsgn
+      nkIdent ContactName
+      nkStringLit Alice
+    nkAsgn
+      nkIdent City
+      nkStringLit Frankfurt
+    nkNone"""
+
+doAssert $parseSql("DELETE FROM table_name;") == "delete from table_name;"
+
+doAssert treeRepr(parseSql("DELETE FROM table_name;")
+) == """
+
+nkStmtList
+  nkDelete
+    nkIdent table_name
+    nkNone"""
 
-doAssert $parseSQL("DELETE * FROM table_name;") == "delete from table_name;"
+doAssert $parseSql("DELETE * FROM table_name;") == "delete from table_name;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 --Select all:
 SELECT * FROM Customers;
 """) == "select * from Customers;"
 
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT * FROM Customers WHERE (CustomerName LIKE 'L%'
 OR CustomerName LIKE 'R%' /*OR CustomerName LIKE 'S%'
 OR CustomerName LIKE 'T%'*/ OR CustomerName LIKE 'W%')
@@ -201,9 +237,9 @@ ORDER BY CustomerName;
 """) == "select * from Customers where(CustomerName like 'L%' or CustomerName like 'R%' or CustomerName like 'W%') and Country = 'USA' order by CustomerName;"
 
 # parse quoted keywords as identifires
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT `SELECT`, `FROM` as `GROUP` FROM `WHERE`;
 """) == """select "SELECT", "FROM" as "GROUP" from "WHERE";"""
-doAssert $parseSQL("""
+doAssert $parseSql("""
 SELECT "SELECT", "FROM" as "GROUP" FROM "WHERE";
 """) == """select "SELECT", "FROM" as "GROUP" from "WHERE";"""
diff --git a/tests/stdlib/tparseuints.nim b/tests/stdlib/tparseuints.nim
index ef8c782b3..9c71a27d6 100644
--- a/tests/stdlib/tparseuints.nim
+++ b/tests/stdlib/tparseuints.nim
@@ -1,3 +1,7 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import unittest, strutils
 
 block: # parseutils
diff --git a/tests/stdlib/tparseutils.nim b/tests/stdlib/tparseutils.nim
index 3bc54dff1..b69900864 100644
--- a/tests/stdlib/tparseutils.nim
+++ b/tests/stdlib/tparseutils.nim
@@ -1,43 +1,112 @@
-import parseutils
-import sequtils
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp"
+"""
 
-let input = "$test{}  $this is ${an{  example}}  "
-let expected = @[(ikVar, "test"), (ikStr, "{}  "), (ikVar, "this"),
-                  (ikStr, " is "), (ikExpr, "an{  example}"), (ikStr, "  ")]
-doAssert toSeq(interpolatedFragments(input)) == expected
+import std/[parseutils, sequtils, sugar, formatfloat]
+import std/assertions
 
-var value = 0
-discard parseHex("0x38", value)
-doAssert value == 56
+proc test() =
+  let input = "$test{}  $this is ${an{  example}}  "
+  let expected = @[(ikVar, "test"), (ikStr, "{}  "), (ikVar, "this"),
+                    (ikStr, " is "), (ikExpr, "an{  example}"), (ikStr, "  ")]
+  doAssert toSeq(interpolatedFragments(input)) == expected
 
-value = -1
-doAssert(parseSaturatedNatural("848", value) == 3)
-doAssert value == 848
+  var value = 0
+  discard parseHex("0x38", value)
+  doAssert value == 56
 
-value = -1
-discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value)
-doAssert value == high(int)
+  value = -1
+  doAssert(parseSaturatedNatural("848", value) == 3)
+  doAssert value == 848
 
-value = -1
-discard parseSaturatedNatural("9223372036854775808", value)
-doAssert value == high(int)
+  value = -1
+  discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value)
+  doAssert value == high(int)
 
-value = -1
-discard parseSaturatedNatural("9223372036854775807", value)
-doAssert value == high(int)
+  value = -1
+  discard parseSaturatedNatural("9223372036854775808", value)
+  doAssert value == high(int)
 
-value = -1
-discard parseSaturatedNatural("18446744073709551616", value)
-doAssert value == high(int)
+  value = -1
+  discard parseSaturatedNatural("9223372036854775807", value)
+  doAssert value == high(int)
 
-value = -1
-discard parseSaturatedNatural("18446744073709551615", value)
-doAssert value == high(int)
+  value = -1
+  discard parseSaturatedNatural("18446744073709551616", value)
+  doAssert value == high(int)
 
-value = -1
-doAssert(parseSaturatedNatural("1_000_000", value) == 9)
-doAssert value == 1_000_000
+  value = -1
+  discard parseSaturatedNatural("18446744073709551615", value)
+  doAssert value == high(int)
 
-var i64Value: int64
-discard parseBiggestInt("9223372036854775807", i64Value)
-doAssert i64Value == 9223372036854775807
+  value = -1
+  doAssert(parseSaturatedNatural("1_000_000", value) == 9)
+  doAssert value == 1_000_000
+
+  var i64Value: int64
+  discard parseBiggestInt("9223372036854775807", i64Value)
+  doAssert i64Value == 9223372036854775807
+
+  block:
+    var f: float
+    let res = collect:
+      for x in ["9.123456789012345+","11.123456789012345+","9.123456789012345-","8.123456789012345+","9.12345678901234-","9.123456789012345"]:
+        (parseFloat(x, f, 0), $f)
+    doAssert res == @[(17, "9.123456789012344"), (18, "11.123456789012344"),
+                      (17, "9.123456789012344"), (17, "8.123456789012344"),
+                      (16, "9.12345678901234"), (17, "9.123456789012344")]
+
+test()
+static: test()
+
+block:  # With this included, static: test() crashes the compiler (from a
+        # VM problem with parseSize calling parseFloat).
+  var sz: int64
+  template checkParseSize(s, expectLen, expectVal) =
+    if (let got = parseSize(s, sz); got != expectLen):
+      raise newException(IOError, "got len " & $got & " != " & $expectLen)
+    if sz != expectVal:
+      raise newException(IOError, "got sz " & $sz & " != " & $expectVal)
+  #              STRING    LEN SZ
+  # Good, complete parses
+  checkParseSize "1  b"   , 4, 1
+  checkParseSize "1  B"   , 4, 1
+  checkParseSize "1k"     , 2, 1000
+  checkParseSize "1 kib"  , 5, 1024
+  checkParseSize "1 ki"   , 4, 1024
+  checkParseSize "1mi"    , 3, 1048576
+  checkParseSize "1 mi"   , 4, 1048576
+  checkParseSize "1 mib"  , 5, 1048576
+  checkParseSize "1 Mib"  , 5, 1048576
+  checkParseSize "1 MiB"  , 5, 1048576
+  checkParseSize "1.23GiB", 7, 1320702444 # 1320702443.52 rounded
+  checkParseSize "0.001k" , 6, 1
+  checkParseSize "0.0004k", 7, 0
+  checkParseSize "0.0006k", 7, 1
+  # Incomplete parses
+  checkParseSize "1  "    , 1, 1          # Trailing white IGNORED
+  checkParseSize "1  B "  , 4, 1          # Trailing white IGNORED
+  checkParseSize "1  B/s" , 4, 1          # Trailing junk IGNORED
+  checkParseSize "1 kX"   , 3, 1000
+  checkParseSize "1 kiX"  , 4, 1024
+  checkParseSize "1j"     , 1, 1          # Unknown prefix IGNORED
+  checkParseSize "1 jib"  , 2, 1          # Unknown prefix post space
+  checkParseSize "1  ji"  , 3, 1
+  # Bad parses; `sz` should stay last good|incomplete value
+  checkParseSize "-1b"    , 0, 1          # Negative numbers
+  checkParseSize "abc"    , 0, 1          # Non-numeric
+  checkParseSize " 12"    , 0, 1          # Leading white
+  # Value Edge cases
+  checkParseSize "9223372036854775807", 19, int64.high
+
+block: # bug #23936
+  func parsePyFloat(
+      a: openArray[char],  # here must be openArray instead of string to reproduce this bug
+      res: var BiggestFloat): int =
+    result = parseFloat(a, res)
+
+  static:
+    var f = 0.0
+    doAssert "1.0".parsePyFloat(f) == 3
+    doAssert f == 1.0
diff --git a/tests/stdlib/tparsopt.nim b/tests/stdlib/tparsopt.nim
index 54a470cb3..f3a9a9798 100644
--- a/tests/stdlib/tparsopt.nim
+++ b/tests/stdlib/tparsopt.nim
@@ -9,6 +9,8 @@ disabled: true
 import
   parseopt
 
+import std/[assertions, syncio]
+
 proc writeHelp() =
   writeLine(stdout, "Usage: tparsopt [options] filename [options]")
 
diff --git a/tests/stdlib/tpathnorm.nim b/tests/stdlib/tpathnorm.nim
new file mode 100644
index 000000000..3dd287a77
--- /dev/null
+++ b/tests/stdlib/tpathnorm.nim
@@ -0,0 +1,36 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/os
+import std/assertions
+
+when doslikeFileSystem:
+  import std/pathnorm
+
+  template initVars =
+    var state {.inject.} = 0
+    var result {.inject.}: string
+
+  block: # / -> /
+    initVars
+    addNormalizePath("//?/c:/./foo//bar/../baz", result, state, '/')
+    doAssert result == "//?/c:/foo/baz"
+    addNormalizePath("me", result, state, '/')
+    doAssert result == "//?/c:/foo/baz/me"
+
+  block: # / -> \
+    initVars
+    addNormalizePath(r"//?/c:/./foo//bar/../baz", result, state, '\\')
+    doAssert result == r"\\?\c:\foo\baz"
+    addNormalizePath("me", result, state, '\\')
+    doAssert result == r"\\?\c:\foo\baz\me"
+
+  block: # Append path component to UNC drive
+    initVars
+    addNormalizePath(r"//?/c:", result, state, '\\')
+    doAssert result == r"\\?\c:"
+    addNormalizePath("Users", result, state, '\\')
+    doAssert result == r"\\?\c:\Users"
+    addNormalizePath("me", result, state, '\\')
+    doAssert result == r"\\?\c:\Users\me"
diff --git a/tests/stdlib/tpaths.nim b/tests/stdlib/tpaths.nim
new file mode 100644
index 000000000..edb56209a
--- /dev/null
+++ b/tests/stdlib/tpaths.nim
@@ -0,0 +1,238 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/paths
+import std/assertions
+import pathnorm
+from std/private/ospaths2 {.all.} import joinPathImpl
+import std/[sugar, sets]
+
+
+proc normalizePath*(path: Path; dirSep = DirSep): Path =
+  result = Path(pathnorm.normalizePath(path.string, dirSep))
+
+func joinPath*(parts: varargs[Path]): Path =
+  var estimatedLen = 0
+  var state = 0
+  for p in parts: estimatedLen += p.string.len
+  var res = newStringOfCap(estimatedLen)
+  for i in 0..high(parts):
+    joinPathImpl(res, state, parts[i].string)
+  result = Path(res)
+
+
+func joinPath(head, tail: Path): Path {.inline.} =
+  head / tail
+
+block absolutePath:
+  doAssertRaises(ValueError): discard absolutePath(Path"a", Path"b")
+  doAssert absolutePath(Path"a") == getCurrentDir() / Path"a"
+  doAssert absolutePath(Path"a", Path"/b") == Path"/b" / Path"a"
+  when defined(posix):
+    doAssert absolutePath(Path"a", Path"/b/") == Path"/b" / Path"a"
+    doAssert absolutePath(Path"a", Path"/b/c") == Path"/b/c" / Path"a"
+    doAssert absolutePath(Path"/a", Path"b/") == Path"/a"
+
+block splitFile:
+  doAssert splitFile(Path"") == (Path"", Path"", "")
+  doAssert splitFile(Path"abc/") == (Path"abc", Path"", "")
+  doAssert splitFile(Path"/") == (Path"/", Path"", "")
+  doAssert splitFile(Path"./abc") == (Path".", Path"abc", "")
+  doAssert splitFile(Path".txt") == (Path"", Path".txt", "")
+  doAssert splitFile(Path"abc/.txt") == (Path"abc", Path".txt", "")
+  doAssert splitFile(Path"abc") == (Path"", Path"abc", "")
+  doAssert splitFile(Path"abc.txt") == (Path"", Path"abc", ".txt")
+  doAssert splitFile(Path"/abc.txt") == (Path"/", Path"abc", ".txt")
+  doAssert splitFile(Path"/foo/abc.txt") == (Path"/foo", Path"abc", ".txt")
+  doAssert splitFile(Path"/foo/abc.txt.gz") == (Path"/foo", Path"abc.txt", ".gz")
+  doAssert splitFile(Path".") == (Path"", Path".", "")
+  doAssert splitFile(Path"abc/.") == (Path"abc", Path".", "")
+  doAssert splitFile(Path"..") == (Path"", Path"..", "")
+  doAssert splitFile(Path"a/..") == (Path"a", Path"..", "")
+  doAssert splitFile(Path"/foo/abc....txt") == (Path"/foo", Path"abc...", ".txt")
+
+# execShellCmd is tested in tosproc
+
+block ospaths:
+  doAssert unixToNativePath(Path"") == Path""
+  doAssert unixToNativePath(Path".") == Path($CurDir)
+  doAssert unixToNativePath(Path"..") == Path($ParDir)
+  doAssert isAbsolute(unixToNativePath(Path"/"))
+  doAssert isAbsolute(unixToNativePath(Path"/", Path"a"))
+  doAssert isAbsolute(unixToNativePath(Path"/a"))
+  doAssert isAbsolute(unixToNativePath(Path"/a", Path"a"))
+  doAssert isAbsolute(unixToNativePath(Path"/a/b"))
+  doAssert isAbsolute(unixToNativePath(Path"/a/b", Path"a"))
+  doAssert unixToNativePath(Path"a/b") == joinPath(Path"a", Path"b")
+
+  when defined(macos):
+    doAssert unixToNativePath(Path"./") == Path":"
+    doAssert unixToNativePath(Path"./abc") == Path":abc"
+    doAssert unixToNativePath(Path"../abc") == Path"::abc"
+    doAssert unixToNativePath(Path"../../abc") == Path":::abc"
+    doAssert unixToNativePath(Path"/abc", Path"a") == Path"abc"
+    doAssert unixToNativePath(Path"/abc/def", Path"a") == Path"abc:def"
+  elif doslikeFileSystem:
+    doAssert unixToNativePath(Path"./") == Path(".\\")
+    doAssert unixToNativePath(Path"./abc") == Path(".\\abc")
+    doAssert unixToNativePath(Path"../abc") == Path("..\\abc")
+    doAssert unixToNativePath(Path"../../abc") == Path("..\\..\\abc")
+    doAssert unixToNativePath(Path"/abc", Path"a") == Path("a:\\abc")
+    doAssert unixToNativePath(Path"/abc/def", Path"a") == Path("a:\\abc\\def")
+  else:
+    #Tests for unix
+    doAssert unixToNativePath(Path"./") == Path"./"
+    doAssert unixToNativePath(Path"./abc") == Path"./abc"
+    doAssert unixToNativePath(Path"../abc") == Path"../abc"
+    doAssert unixToNativePath(Path"../../abc") == Path"../../abc"
+    doAssert unixToNativePath(Path"/abc", Path"a") == Path"/abc"
+    doAssert unixToNativePath(Path"/abc/def", Path"a") == Path"/abc/def"
+
+  block extractFilenameTest:
+    doAssert extractFilename(Path"") == Path""
+    when defined(posix):
+      doAssert extractFilename(Path"foo/bar") == Path"bar"
+      doAssert extractFilename(Path"foo/bar.txt") == Path"bar.txt"
+      doAssert extractFilename(Path"foo/") == Path""
+      doAssert extractFilename(Path"/") == Path""
+    when doslikeFileSystem:
+      doAssert extractFilename(Path(r"foo\bar")) == Path"bar"
+      doAssert extractFilename(Path(r"foo\bar.txt")) == Path"bar.txt"
+      doAssert extractFilename(Path(r"foo\")) == Path""
+      doAssert extractFilename(Path(r"C:\")) == Path""
+
+  block lastPathPartTest:
+    doAssert lastPathPart(Path"") == Path""
+    when defined(posix):
+      doAssert lastPathPart(Path"foo/bar.txt") == Path"bar.txt"
+      doAssert lastPathPart(Path"foo/") == Path"foo"
+      doAssert lastPathPart(Path"/") == Path""
+    when doslikeFileSystem:
+      doAssert lastPathPart(Path(r"foo\bar.txt")) == Path"bar.txt"
+      doAssert lastPathPart(Path(r"foo\")) == Path"foo"
+
+  template canon(x): Path = normalizePath(Path(x), '/')
+  doAssert canon"/foo/../bar" == Path"/bar"
+  doAssert canon"foo/../bar" == Path"bar"
+
+  doAssert canon"/f/../bar///" == Path"/bar"
+  doAssert canon"f/..////bar" == Path"bar"
+
+  doAssert canon"../bar" == Path"../bar"
+  doAssert canon"/../bar" == Path"/../bar"
+
+  doAssert canon("foo/../../bar/") == Path"../bar"
+  doAssert canon("./bla/blob/") == Path"bla/blob"
+  doAssert canon(".hiddenFile") == Path".hiddenFile"
+  doAssert canon("./bla/../../blob/./zoo.nim") == Path"../blob/zoo.nim"
+
+  doAssert canon("C:/file/to/this/long") == Path"C:/file/to/this/long"
+  doAssert canon("") == Path""
+  doAssert canon("foobar") == Path"foobar"
+  doAssert canon("f/////////") == Path"f"
+
+  doAssert relativePath(Path"/foo/bar//baz.nim", Path"/foo", '/') == Path"bar/baz.nim"
+  doAssert normalizePath(Path"./foo//bar/../baz", '/') == Path"foo/baz"
+
+  doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/other/bad", '/') == Path"../../me/bar/z.nim"
+
+  doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/other", '/') == Path"../me/bar/z.nim"
+
+  # `//` is a UNC path, `/` is the current working directory's drive, so can't
+  # run this test on Windows.
+  when not doslikeFileSystem:
+    doAssert relativePath(Path"/Users///me/bar//z.nim", Path"//Users/", '/') == Path"me/bar/z.nim"
+  doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/me", '/') == Path"bar/z.nim"
+  doAssert relativePath(Path"", Path"/users/moo", '/') == Path""
+  doAssert relativePath(Path"foo", Path"", '/') == Path"foo"
+  doAssert relativePath(Path"/foo", Path"/Foo", '/') == (when FileSystemCaseSensitive: Path"../foo" else: Path".")
+  doAssert relativePath(Path"/Foo", Path"/foo", '/') == (when FileSystemCaseSensitive: Path"../Foo" else: Path".")
+  doAssert relativePath(Path"/foo", Path"/fOO", '/') == (when FileSystemCaseSensitive: Path"../foo" else: Path".")
+  doAssert relativePath(Path"/foO", Path"/foo", '/') == (when FileSystemCaseSensitive: Path"../foO" else: Path".")
+
+  doAssert relativePath(Path"foo", Path".", '/') == Path"foo"
+  doAssert relativePath(Path".", Path".", '/') == Path"."
+  doAssert relativePath(Path"..", Path".", '/') == Path".."
+
+  doAssert relativePath(Path"foo", Path"foo") == Path"."
+  doAssert relativePath(Path"", Path"foo") == Path""
+  doAssert relativePath(Path"././/foo", Path"foo//./") == Path"."
+
+  doAssert relativePath(getCurrentDir() / Path"bar", Path"foo") == Path"../bar".unixToNativePath
+  doAssert relativePath(Path"bar", getCurrentDir() / Path"foo") == Path"../bar".unixToNativePath
+
+  when doslikeFileSystem:
+    doAssert relativePath(r"c:\foo.nim".Path, r"C:\".Path) == r"foo.nim".Path
+    doAssert relativePath(r"c:\foo\bar\baz.nim".Path, r"c:\foo".Path) == r"bar\baz.nim".Path
+    doAssert relativePath(r"c:\foo\bar\baz.nim".Path, r"d:\foo".Path) == r"c:\foo\bar\baz.nim".Path
+    doAssert relativePath(r"\foo\baz.nim".Path, r"\foo".Path) == r"baz.nim".Path
+    doAssert relativePath(r"\foo\bar\baz.nim".Path, r"\bar".Path) == r"..\foo\bar\baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foo\bar".Path) == r"baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foO\bar".Path) == r"baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\bar\bar".Path) == r"\\foo\bar\baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foo\car".Path) == r"\\foo\bar\baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\goo\bar".Path) == r"\\foo\bar\baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"c:\".Path) == r"\\foo\bar\baz.nim".Path
+    doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\foo".Path) == r"\\foo\bar\baz.nim".Path
+    doAssert relativePath(r"c:\foo.nim".Path, r"\foo".Path) == r"c:\foo.nim".Path
+
+  doAssert joinPath(Path"usr", Path"") == unixToNativePath(Path"usr")
+  doAssert joinPath(Path"usr", Path"") == (Path"usr").dup(add Path"")
+  doAssert joinPath(Path"", Path"lib") == Path"lib"
+  doAssert joinPath(Path"", Path"lib") == Path"".dup(add Path"lib")
+  doAssert joinPath(Path"", Path"/lib") == unixToNativePath(Path"/lib")
+  doAssert joinPath(Path"", Path"/lib") == unixToNativePath(Path"/lib")
+  doAssert joinPath(Path"usr/", Path"/lib") == Path"usr/".dup(add Path"/lib")
+  doAssert joinPath(Path"", Path"") == unixToNativePath(Path"") # issue #13455
+  doAssert joinPath(Path"", Path"") == Path"".dup(add Path"")
+  doAssert joinPath(Path"", Path"/") == unixToNativePath(Path"/")
+  doAssert joinPath(Path"", Path"/") == Path"".dup(add Path"/")
+  doAssert joinPath(Path"/", Path"/") == unixToNativePath(Path"/")
+  doAssert joinPath(Path"/", Path"/") == Path"/".dup(add Path"/")
+  doAssert joinPath(Path"/", Path"") == unixToNativePath(Path"/")
+  doAssert joinPath(Path"/" / Path"") == unixToNativePath(Path"/") # weird test case...
+  doAssert joinPath(Path"/", Path"/a/b/c") == unixToNativePath(Path"/a/b/c")
+  doAssert joinPath(Path"foo/", Path"") == unixToNativePath(Path"foo/")
+  doAssert joinPath(Path"foo/", Path"abc") == unixToNativePath(Path"foo/abc")
+  doAssert joinPath(Path"foo//./", Path"abc/.//") == unixToNativePath(Path"foo/abc/")
+  doAssert Path"foo//./".dup(add Path"abc/.//") == unixToNativePath(Path"foo/abc/")
+  doAssert joinPath(Path"foo", Path"abc") == unixToNativePath(Path"foo/abc")
+  doAssert Path"foo".dup(add Path"abc") == unixToNativePath(Path"foo/abc")
+  doAssert joinPath(Path"", Path"abc") == unixToNativePath(Path"abc")
+
+  doAssert joinPath(Path"zook/.", Path"abc") == unixToNativePath(Path"zook/abc")
+
+  # controversial: inconsistent with `joinPath("zook/.","abc")`
+  # on linux, `./foo` and `foo` are treated a bit differently for executables
+  # but not `./foo/bar` and `foo/bar`
+  doAssert joinPath(Path".", Path"/lib") == unixToNativePath(Path"./lib")
+  doAssert joinPath(Path".", Path"abc") == unixToNativePath(Path"./abc")
+
+  # cases related to issue #13455
+  doAssert joinPath(Path"foo", Path"", Path"") == Path"foo"
+  doAssert joinPath(Path"foo", Path"") == Path"foo"
+  doAssert joinPath(Path"foo/", Path"") == unixToNativePath(Path"foo/")
+  doAssert joinPath(Path"foo/", Path".") == Path"foo"
+  doAssert joinPath(Path"foo", Path"./") == unixToNativePath(Path"foo/")
+  doAssert joinPath(Path"foo", Path"", Path"bar/") == unixToNativePath(Path"foo/bar/")
+
+  # issue #13579
+  doAssert joinPath(Path"/foo", Path"../a") == unixToNativePath(Path"/a")
+  doAssert joinPath(Path"/foo/", Path"../a") == unixToNativePath(Path"/a")
+  doAssert joinPath(Path"/foo/.", Path"../a") == unixToNativePath(Path"/a")
+  doAssert joinPath(Path"/foo/.b", Path"../a") == unixToNativePath(Path"/foo/a")
+  doAssert joinPath(Path"/foo///", Path"..//a/") == unixToNativePath(Path"/a/")
+  doAssert joinPath(Path"foo/", Path"../a") == unixToNativePath(Path"a")
+
+  when doslikeFileSystem:
+    doAssert joinPath(Path"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\", Path"..\\..\\VC\\vcvarsall.bat") == r"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat".Path
+    doAssert joinPath(Path"C:\\foo", Path"..\\a") == r"C:\a".Path
+    doAssert joinPath(Path"C:\\foo\\", Path"..\\a") == r"C:\a".Path
+
+
+block: # bug #23663
+  var s: HashSet[Path]
+  s.incl("/a/b/c/..".Path)
+  doAssert "/a/b/".Path in s
+  doAssert "/a/b/c".Path notin s
diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim
index 99b7dc6f4..da3fc14b7 100644
--- a/tests/stdlib/tpegs.nim
+++ b/tests/stdlib/tpegs.nim
@@ -1,5 +1,6 @@
 discard """
-  targets: "c js"
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
   output: '''
 PEG AST traversal output
 ------------------------
@@ -51,8 +52,10 @@ Event parser output
 '''
 """
 
-import strutils, streams
-import pegs
+when defined(nimHasEffectsOf):
+  {.experimental: "strictEffects".}
+
+import std/[strutils, streams, pegs, assertions]
 
 const
   indent = "  "
@@ -104,9 +107,9 @@ block:
 
 block:
   var
-    pStack: seq[string] = @[]
-    valStack: seq[float] = @[]
-    opStack = ""
+    pStack {.threadvar.}: seq[string]
+    valStack {.threadvar.}: seq[float]
+    opStack {.threadvar.}: string
   let
     parseArithExpr = pegAst.eventParser:
       pkNonTerminal:
@@ -125,7 +128,7 @@ block:
                 discard
             of "Sum", "Product":
               try:
-                let val = matchStr.parseFloat
+                let val {.used.} = matchStr.parseFloat
               except ValueError:
                 if valStack.len > 1 and opStack.len > 0:
                   valStack[^2] = case opStack[^1]
@@ -147,3 +150,195 @@ block:
   echo "-------------------"
   let pLen = parseArithExpr(txt)
   doAssert txt.len == pLen
+
+
+import std/importutils
+
+block:
+  proc pegsTest() =
+    privateAccess(NonTerminal)
+    privateAccess(Captures)
+
+    if "test" =~ peg"s <- {{\ident}}": # bug #19104
+      doAssert matches[0] == "test"
+      doAssert matches[1] == "test", $matches[1]
+
+    doAssert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27"
+    doAssert match("(a b c)", peg"'(' @ ')'")
+    doAssert match("W_HI_Le", peg"\y 'while'")
+    doAssert(not match("W_HI_L", peg"\y 'while'"))
+    doAssert(not match("W_HI_Le", peg"\y v'while'"))
+    doAssert match("W_HI_Le", peg"y'while'")
+
+    doAssert($ +digits == $peg"\d+")
+    doAssert "0158787".match(peg"\d+")
+    doAssert "ABC 0232".match(peg"\w+\s+\d+")
+    doAssert "ABC".match(peg"\d+ / \w+")
+
+    var accum: seq[string] = @[]
+    for word in split("00232this02939is39an22example111", peg"\d+"):
+      accum.add(word)
+    doAssert(accum == @["this", "is", "an", "example"])
+
+    doAssert matchLen("key", ident) == 3
+
+    var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident)
+    doAssert matchLen("key1=  cal9", pattern) == 11
+
+    var ws = newNonTerminal("ws", 1, 1)
+    ws.rule = *whitespace
+
+    var expr = newNonTerminal("expr", 1, 1)
+    expr.rule = sequence(capture(ident), *sequence(
+                  nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr)))
+
+    var c: Captures
+    var s = "a+b +  c +d+e+f"
+    doAssert rawMatch(s, expr.rule, 0, c) == len(s)
+    var a = ""
+    for i in 0..c.ml-1:
+      a.add(substr(s, c.matches[i][0], c.matches[i][1]))
+    doAssert a == "abcdef"
+    #echo expr.rule
+
+    #const filename = "lib/devel/peg/grammar.txt"
+    #var grammar = parsePeg(newFileStream(filename, fmRead), filename)
+    #echo "a <- [abc]*?".match(grammar)
+    doAssert find("_____abc_______", term("abc"), 2) == 5
+    doAssert match("_______ana", peg"A <- 'ana' / . A")
+    doAssert match("abcs%%%", peg"A <- ..A / .A / '%'")
+
+    var matches: array[0..MaxSubpatterns-1, string]
+    if "abc" =~ peg"{'a'}'bc' 'xyz' / {\ident}":
+      doAssert matches[0] == "abc"
+    else:
+      doAssert false
+
+    var g2 = peg"""S <- A B / C D
+                   A <- 'a'+
+                   B <- 'b'+
+                   C <- 'c'+
+                   D <- 'd'+
+                """
+    doAssert($g2 == "((A B) / (C D))")
+    doAssert match("cccccdddddd", g2)
+    doAssert("var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2") ==
+           "var1<-keykey; var2<-key2key2")
+    doAssert("var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2") ==
+           "$1<-$2$2; $1<-$2$2")
+    doAssert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}")
+
+    if "aaaaaa" =~ peg"'aa' !. / ({'a'})+":
+      doAssert matches[0] == "a"
+    else:
+      doAssert false
+
+    if match("abcdefg", peg"c {d} ef {g}", matches, 2):
+      doAssert matches[0] == "d"
+      doAssert matches[1] == "g"
+    else:
+      doAssert false
+
+    accum = @[]
+    for x in findAll("abcdef", peg".", 3):
+      accum.add(x)
+    doAssert(accum == @["d", "e", "f"])
+
+    for x in findAll("abcdef", peg"^{.}", 3):
+      doAssert x == "d"
+
+    if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')":
+      doAssert matches[0] == "f"
+      doAssert matches[1] == "a, b"
+    else:
+      doAssert false
+
+    doAssert match("eine übersicht und außerdem", peg"(\letter \white*)+")
+    # ß is not a lower cased letter?!
+    doAssert match("eine übersicht und auerdem", peg"(\lower \white*)+")
+    doAssert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+")
+    doAssert(not match("456678", peg"(\letter)+"))
+
+    doAssert("var1 = key; var2 = key2".replacef(
+      peg"\skip(\s*) {\ident}'='{\ident}", "$1<-$2$2") ==
+           "var1<-keykey;var2<-key2key2")
+
+    doAssert match("prefix/start", peg"^start$", 7)
+
+    if "foo" =~ peg"{'a'}?.*":
+      doAssert matches[0].len == 0
+    else: doAssert false
+
+    if "foo" =~ peg"{''}.*":
+      doAssert matches[0] == ""
+    else: doAssert false
+
+    if "foo" =~ peg"{'foo'}":
+      doAssert matches[0] == "foo"
+    else: doAssert false
+
+    let empty_test = peg"^\d*"
+    let str = "XYZ"
+
+    doAssert(str.find(empty_test) == 0)
+    doAssert(str.match(empty_test))
+
+    proc handleMatches(m: int, n: int, c: openArray[string]): string =
+      result = ""
+
+      if m > 0:
+        result.add ", "
+
+      result.add case n:
+        of 2: toLowerAscii(c[0]) & ": '" & c[1] & "'"
+        of 1: toLowerAscii(c[0]) & ": ''"
+        else: ""
+
+    doAssert("Var1=key1;var2=Key2;   VAR3".
+      replace(peg"{\ident}('='{\ident})* ';'* \s*",
+      handleMatches) == "var1: 'key1', var2: 'Key2', var3: ''")
+
+
+    doAssert "test1".match(peg"""{@}$""")
+    doAssert "test2".match(peg"""{(!$ .)*} $""")
+
+    doAssert "abbb".match(peg"{a} {b} $2 $^1")
+    doAssert "abBA".match(peg"{a} {b} i$2 i$^2")
+
+    doAssert "abba".match(peg"{a} {b} $^1 {} $^1")
+
+    block:
+      let grammar = peg"""
+program <- {''} stmt* $
+stmt <- call / block
+call <- 'call()' EOL
+EOL <- \n / $
+block <- 'block:' \n indBody
+indBody <- {$^1 ' '+} stmt ($^1 stmt)* {}
+"""
+      let program = """
+call()
+block:
+  block:
+    call()
+    call()
+  call()
+call()
+"""
+      var c: Captures
+      doAssert program.len == program.rawMatch(grammar, 0, c)
+      doAssert c.ml == 1
+
+    block:
+      # bug #21632
+
+      let p = peg"""
+        atext <- \w / \d
+      """
+
+      doAssert "a".match(p)
+      doAssert "1".match(p)
+
+  pegsTest()
+  static:
+    pegsTest()
diff --git a/tests/stdlib/tposix.nim b/tests/stdlib/tposix.nim
index 14f1fd6e2..060482229 100644
--- a/tests/stdlib/tposix.nim
+++ b/tests/stdlib/tposix.nim
@@ -1,5 +1,6 @@
 discard """
-outputsub: ""
+  matrix: "--mm:refc; --mm:orc"
+  disabled: windows
 """
 
 # Test Posix interface
@@ -7,6 +8,7 @@ outputsub: ""
 when not defined(windows):
 
   import posix
+  import std/[assertions, syncio]
 
   var
     u: Utsname
@@ -17,3 +19,70 @@ when not defined(windows):
   writeLine(stdout, u.nodename)
   writeLine(stdout, u.release)
   writeLine(stdout, u.machine)
+
+  when not (defined(nintendoswitch) or defined(macos) or defined(macosx)):
+    block:
+      type Message = object
+        value: int
+
+      const MQ_PATH: cstring = "/top_level_file"
+      const MQ_PRIORITY: cuint = 170
+      const MQ_MESSAGE_SIZE: csize_t = csize_t(sizeof(Message))
+
+      let mqd_a: posix.MqAttr = MqAttr(mq_maxmsg: 10, mq_msgsize: clong(MQ_MESSAGE_SIZE))
+      let writable: posix.Mqd = posix.mq_open(
+        MQ_PATH,
+        posix.O_CREAT or posix.O_WRONLY or posix.O_NONBLOCK,
+        posix.S_IRWXU,
+        addr(mqd_a)
+      )
+      let readable: posix.Mqd = posix.mq_open(
+        MQ_PATH,
+        posix.O_RDONLY or posix.O_NONBLOCK,
+        posix.S_IRWXU,
+        addr(mqd_a)
+      )
+
+      let sent: Message = Message(value: 88)
+      block:
+        let success: int = writable.mq_send(
+          cast[cstring](sent.addr),
+          MQ_MESSAGE_SIZE,
+          MQ_PRIORITY
+        )
+        doAssert success == 0, $success
+
+      block:
+        var buffer: Message
+        var priority: cuint
+        let bytesRead: int = readable.mq_receive(
+          cast[cstring](buffer.addr),
+          MQ_MESSAGE_SIZE,
+          priority
+        )
+        doAssert buffer == sent
+        doAssert bytesRead == int(MQ_MESSAGE_SIZE)
+
+  block:
+    var rl: RLimit
+    var res = getrlimit(RLIMIT_STACK, rl)
+    doAssert res == 0
+
+    # save old value
+    let oldrlim = rl.rlim_cur
+
+    # set new value
+    rl.rlim_cur = rl.rlim_max - 1
+    res = setrlimit(RLIMIT_STACK, rl)
+    doAssert res == 0
+
+    # get new value
+    var rl1: RLimit
+    res = getrlimit(RLIMIT_STACK, rl1)
+    doAssert res == 0
+    doAssert rl1.rlim_cur == rl.rlim_max - 1
+
+    # restore old value
+    rl.rlim_cur = oldrlim
+    res = setrlimit(RLIMIT_STACK, rl)
+    doAssert res == 0
diff --git a/tests/stdlib/tprelude.nim b/tests/stdlib/tprelude.nim
index a60bcf70a..47f46b511 100644
--- a/tests/stdlib/tprelude.nim
+++ b/tests/stdlib/tprelude.nim
@@ -8,6 +8,8 @@ when defined nimTestTpreludeCase1:
 else:
   include prelude
 
+import std/assertions
+
 template main() =
   doAssert toSeq(1..3) == @[1,2,3]
 static: main()
diff --git a/tests/stdlib/tpunycode.nim b/tests/stdlib/tpunycode.nim
deleted file mode 100644
index 596c5ef63..000000000
--- a/tests/stdlib/tpunycode.nim
+++ /dev/null
@@ -1,5 +0,0 @@
-import punycode
-
-doAssert(decode(encode("", "bücher")) == "bücher")
-doAssert(decode(encode("münchen")) == "münchen")
-doAssert encode("xn--", "münchen") == "xn--mnchen-3ya"
diff --git a/tests/stdlib/tquit.nim b/tests/stdlib/tquit.nim
deleted file mode 100644
index 81726fd7f..000000000
--- a/tests/stdlib/tquit.nim
+++ /dev/null
@@ -1,15 +0,0 @@
-discard """
-output: '''
-just exiting...
-'''
-joinable: false
-"""
-
-# Test `addQuitProc` (now deprecated by `addExitProc`)
-
-proc myExit() {.noconv.} =
-  write(stdout, "just exiting...\n")
-
-{.push warning[deprecated]: off.}
-addQuitProc(myExit)
-{.pop.}
diff --git a/tests/stdlib/trandom.nim b/tests/stdlib/trandom.nim
index 9fc68fca1..eb32f7757 100644
--- a/tests/stdlib/trandom.nim
+++ b/tests/stdlib/trandom.nim
@@ -1,9 +1,12 @@
 discard """
-  joinable: false
-  targets: "c js"
+  joinable: false # to avoid messing with global rand state
+  matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
 """
-
-import std/[random, math, os, stats, sets, tables]
+import std/[assertions, formatfloat]
+import std/[random, math, stats, sets, tables]
+import std/private/jsutils
+when not defined(js):
+  import std/os
 
 randomize(233)
 
@@ -21,9 +24,10 @@ proc main() =
   doAssert a in [[0,1], [1,0]]
 
   doAssert rand(0) == 0
-  doAssert sample("a") == 'a'
+  when not defined(nimscript):
+    doAssert sample("a") == 'a'
 
-  when compileOption("rangeChecks"):
+  when compileOption("rangeChecks") and not defined(nimscript):
     doAssertRaises(RangeDefect):
       discard rand(-1)
 
@@ -37,11 +41,16 @@ main()
 
 block:
   when not defined(js):
-    doAssert almostEqual(rand(12.5), 4.012897747078944)
-    doAssert almostEqual(rand(2233.3322), 879.702755321298)
+    doAssert almostEqual(rand(12.5), 7.355175342026979)
+    doAssert almostEqual(rand(2233.3322), 499.342386778917)
 
   type DiceRoll = range[0..6]
-  doAssert rand(DiceRoll).int == 4
+  when not defined(js):
+    doAssert rand(DiceRoll).int == 3
+  elif compileOption("jsbigint64"):
+    doAssert rand(DiceRoll).int == 1
+  else:
+    doAssert rand(DiceRoll).int == 6
 
 var rs: RunningStat
 for j in 1..5:
@@ -87,7 +96,7 @@ block: # random int
 
   block: # again gives new numbers
     var rand1 = rand(1000000)
-    when not defined(js):
+    when not (defined(js) or defined(nimscript)):
       os.sleep(200)
 
     var rand2 = rand(1000000)
@@ -117,7 +126,7 @@ block: # random float
 
   block: # again gives new numbers
     var rand1: float = rand(1000000.0)
-    when not defined(js):
+    when not (defined(js) or defined(nimscript)):
       os.sleep(200)
 
     var rand2: float = rand(1000000.0)
@@ -164,3 +173,138 @@ block: # random sample
       let stdDev = sqrt(n * p * (1.0 - p))
       # NOTE: like unnormalized int CDF test, P(wholeTestFails) =~ 0.01.
       doAssert abs(float(histo[values[i]]) - expected) <= 3.0 * stdDev
+
+block:
+  # 0 is a valid seed
+  var r = initRand(0)
+  doAssert r.rand(1.0) != r.rand(1.0)
+  r = initRand(10)
+  doAssert r.rand(1.0) != r.rand(1.0)
+  # changing the seed changes the sequence
+  var r1 = initRand(123)
+  var r2 = initRand(124)
+  doAssert r1.rand(1.0) != r2.rand(1.0)
+
+block: # bug #17467
+  let n = 1000
+  for i in -n .. n:
+    var r = initRand(i)
+    let x = r.rand(1.0)
+    doAssert x > 1e-4, $(x, i)
+      # This used to fail for each i in 0..<26844, i.e. the 1st produced value
+      # was predictable and < 1e-4, skewing distributions.
+
+block: # bug #16360, Natural overload
+  var r = initRand()
+  template test(a) =
+    let a2 = a
+    block:
+      let a3 = r.rand(a2)
+      doAssert a3 <= a2
+      doAssert a3.type is a2.type
+    block:
+      let a3 = rand(a2)
+      doAssert a3 <= a2
+      doAssert a3.type is a2.type
+  test int.high
+  test int.high - 1
+  test int.high - 2
+  test 0
+
+block: # same as above but use slice overload
+  var r = initRand()
+  template test[T](a: T) =
+    let a2: T = a
+    block:
+      let a3 = r.rand(T(0) .. a2)
+      doAssert a3 <= a2
+      doAssert a3.type is a2.type
+    block:
+      let a3 = rand(T(0) .. a2)
+      doAssert a3 <= a2
+      doAssert a3.type is a2.type
+  test cast[uint](int.high)
+  test cast[uint](int.high) + 1
+  whenJsNoBigInt64: discard
+  do:
+    test uint64.high
+    test uint64.high - 1
+  test uint.high - 2
+  test uint.high - 1
+  test uint.high
+  test int.high
+  test int.high - 1
+  test int.high - 2
+  test 0
+  test 0'u
+  test 0'u64
+
+block: # bug #16296
+  var r = initRand()
+  template test(x) =
+    let a2 = x
+    let a3 = r.rand(a2)
+    doAssert a3 <= a2.b
+    doAssert a3 >= a2.a
+    doAssert a3.type is a2.a.type
+  test(-2 .. int.high-1)
+  test(int.low .. int.high)
+  test(int.low+1 .. int.high)
+  test(int.low .. int.high-1)
+  test(int.low .. 0)
+  test(int.low .. -1)
+  test(int.low .. 1)
+  test(int64.low .. 1'i64)
+  test(10'u64 .. uint64.high)
+
+block: # bug #17670
+  type UInt48 = range[0'u64..2'u64^48-1]
+  let x = rand(UInt48)
+  doAssert x is UInt48
+
+block: # bug #17898
+  # Checks whether `initRand()` generates unique states.
+  # size should be 2^64, but we don't have time and space.
+
+  # Disable this test for js until js gets proper skipRandomNumbers.
+  when not defined(js):
+    const size = 1000
+    var
+      rands: array[size, Rand]
+      randSet: HashSet[Rand]
+    for i in 0..<size:
+      rands[i] = initRand()
+      randSet.incl rands[i]
+
+    doAssert randSet.len == size
+
+    # Checks random number sequences overlapping.
+    const numRepeat = 100
+    for i in 0..<size:
+      for j in 0..<numRepeat:
+        discard rands[i].next
+        doAssert rands[i] notin randSet
+
+block: # bug #22360
+  const size = 1000
+  var fc = 0
+  var tc = 0
+
+  for _ in 1..size:
+    let s = rand(bool)
+
+    if s:
+      inc tc
+    else:
+      inc fc
+
+  when defined(js) and not compileOption("jsbigint64"):
+    doAssert (tc, fc) == (515, 485), $(tc, fc)
+  else:
+    doAssert (tc, fc) == (510, 490), $(tc, fc)
+
+block:
+  when defined(js) and not compileOption("jsbigint64"):
+    doAssert rand(int32.high) == 335507522
+  else:
+    doAssert rand(int32.high) == 607539621
diff --git a/tests/stdlib/trat_float.nim b/tests/stdlib/trat_float.nim
new file mode 100644
index 000000000..663973bf9
--- /dev/null
+++ b/tests/stdlib/trat_float.nim
@@ -0,0 +1,9 @@
+discard """
+  errormsg: '''type mismatch: got'''
+  file: "trat_float.nim"
+  line: "9,19"
+"""
+import rationals
+var
+  # this fails - no floats as num or den
+  r = initRational(1.0'f, 1.0'f)
diff --git a/tests/stdlib/trat_init.nim b/tests/stdlib/trat_init.nim
new file mode 100644
index 000000000..2be0c0099
--- /dev/null
+++ b/tests/stdlib/trat_init.nim
@@ -0,0 +1,14 @@
+discard """
+  output: '''true'''
+"""
+import rationals
+var
+  z = Rational[int](num: 0, den: 1)
+  o = initRational(num=1, den=1)
+  a = initRational(1, 2)
+
+try:
+  var
+    r = initRational(1, 0)  # this fails - no zero denominator
+except AssertionDefect:
+  echo "true"
diff --git a/tests/stdlib/trationals.nim b/tests/stdlib/trationals.nim
index 0a3a95a9a..22d7f5c2d 100644
--- a/tests/stdlib/trationals.nim
+++ b/tests/stdlib/trationals.nim
@@ -1,10 +1,16 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/[rationals, math]
+import std/assertions
 
 template main() =
   var
     z = Rational[int](num: 0, den: 1)
     o = initRational(num = 1, den = 1)
     a = initRational(1, 2)
+    u = 3u // 2
     b = -1 // -2
     m1 = -1 // 1
     tt = 10 // 2
@@ -99,5 +105,13 @@ template main() =
   when sizeof(int) == 8:
     doAssert almostEqual(PI.toRational.toFloat, PI)
 
+  # unsigned
+  doAssert u == u
+  doAssert u + u == 3u // 1
+  doAssert 3u.toRational - u == u
+  doAssert u * 2 == 3u // 1
+
+
+
 static: main()
 main()
diff --git a/tests/stdlib/tre.nim b/tests/stdlib/tre.nim
index ea1b5af32..39637434d 100644
--- a/tests/stdlib/tre.nim
+++ b/tests/stdlib/tre.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/re
+import std/assertions
 
 proc testAll() =
   doAssert match("(a b c)", rex"\( .* \)")
@@ -99,10 +104,19 @@ proc testAll() =
       accum.add($x)
     doAssert(accum == @["a","b","c"])
 
-  block:
-    # bug #9306
+  block: # bug #9306
     doAssert replace("bar", re"^", "foo") == "foobar"
-    doAssert replace("foo", re"", "-") == "-foo"
     doAssert replace("foo", re"$", "bar") == "foobar"
 
+
+  block: # bug #9437
+    doAssert replace("foo", re"", "-") == "-f-o-o-"
+    doAssert replace("ooo", re"o", "-") == "---"
+
+  block: # bug #14468
+    accum = @[]
+    for word in split("this is an example", re"\b"):
+      accum.add(word)
+    doAssert(accum == @["this", " ", "is", " ", "an", " ", "example"])
+
 testAll()
diff --git a/tests/stdlib/treadln.nim b/tests/stdlib/treadln.nim
new file mode 100644
index 000000000..4a070e848
--- /dev/null
+++ b/tests/stdlib/treadln.nim
@@ -0,0 +1,23 @@
+
+discard """
+output: '''
+test the improved readline handling that does not care whether its
+Macintosh, Unix or Windows text format.
+'''
+"""
+
+import std/syncio
+
+# test the improved readline handling that does not care whether its
+# Macintosh, Unix or Windows text format.
+
+var
+  inp: File
+  line: string
+
+if open(inp, "tests/stdlib/treadln.nim"):
+  while not endOfFile(inp):
+    line = readLine(inp)
+    if line.len >= 2 and line[0] == '#' and line[1] == ' ':
+      echo line[2..^1]
+  close(inp)
diff --git a/tests/stdlib/tregex.nim b/tests/stdlib/tregex.nim
index 21f4e6743..9dd66cd60 100644
--- a/tests/stdlib/tregex.nim
+++ b/tests/stdlib/tregex.nim
@@ -1,5 +1,6 @@
 discard """
   output: "key: keyAYes!"
+  matrix: "--mm:refc; --mm:orc"
 """
 # Test the new regular expression module
 # which is based on the PCRE library
@@ -11,7 +12,7 @@ when defined(powerpc64):
 else:
   import
     re
-
+  import std/syncio
   if "keyA = valueA" =~ re"\s*(\w+)\s*\=\s*(\w+)":
     write(stdout, "key: ", matches[0])
   elif "# comment!" =~ re.re"\s*(\#.*)":
diff --git a/tests/stdlib/tregistry.nim b/tests/stdlib/tregistry.nim
new file mode 100644
index 000000000..25aed8df8
--- /dev/null
+++ b/tests/stdlib/tregistry.nim
@@ -0,0 +1,16 @@
+discard """
+  disabled: "unix"
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+when defined(windows):
+  import std/registry
+  import std/assertions
+
+  block: # bug #14010
+    let path = "Environment"
+    let key = "D20210328T202842_key"
+    let val = "D20210328T202842_val"
+    let handle = HKEY_CURRENT_USER
+    setUnicodeValue("Environment", key, val, handle)
+    doAssert getUnicodeValue(path, key, handle) == val
diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim
index 357854d67..3956b98f9 100644
--- a/tests/stdlib/trepr.nim
+++ b/tests/stdlib/trepr.nim
@@ -1,13 +1,16 @@
 discard """
   targets: "c cpp js"
-  matrix: ";--gc:arc"
+  matrix: "--mm:refc;--mm:arc"
 """
 
 # if excessive, could remove 'cpp' from targets
 
-from strutils import endsWith, contains
+from strutils import endsWith, contains, strip
 from std/macros import newLit
-macro deb(a): string = newLit a.repr
+import std/assertions
+
+macro deb(a): string = newLit a.repr.strip
+macro debTyped(a: typed): string = newLit a.repr.strip
 
 template main() =
   doAssert repr({3,5}) == "{3, 5}"
@@ -37,7 +40,7 @@ template main() =
   #[
   BUG:
   --gc:arc returns `"abc"`
-  regular gc returns with address, e.g. 0x1068aae60"abc", but only 
+  regular gc returns with address, e.g. 0x1068aae60"abc", but only
   for c,cpp backends (not js, vm)
   ]#
   block:
@@ -62,22 +65,21 @@ template main() =
   doAssert repr(arr) == "[1, 2, 3]"
 
   block: # bug #7878
-    proc reprOpenarray(variable: var openarray[int]): string = repr(variable)
+    proc reprOpenarray(variable: var openArray[int]): string = repr(variable)
     when defined(js): discard # BUG: doesn't work
     else:
       doAssert reprOpenarray(arr) == "[1, 2, 3]"
 
-  block: # bug #17292
+  block: # bug #17292 repr with `do`
     template foo(a, b, c, d) = discard
     block:
       let a = deb:
         foo(1, 2, 3, 4)
-      doAssert a == "\nfoo(1, 2, 3, 4)"
+      doAssert a == "foo(1, 2, 3, 4)"
     block:
       let a = deb:
         foo(1, 2, 3): 4
       doAssert a == """
-
 foo(1, 2, 3):
   4"""
 
@@ -86,7 +88,6 @@ foo(1, 2, 3):
         foo(1, 2): 3
         do: 4
       doAssert a == """
-
 foo(1, 2):
   3
 do:
@@ -98,7 +99,6 @@ do:
         do: 3
         do: 4
       doAssert a == """
-
 foo(1):
   3
 do:
@@ -118,7 +118,6 @@ do:
           4
 
       doAssert a == """
-
 foo(1):
   3
 do:
@@ -135,7 +134,6 @@ do:
         do: 3
         do: 4
       doAssert a == """
-
 foo:
   1
 do:
@@ -145,5 +143,186 @@ do:
 do:
   4"""
 
+  block: # bug #17292 repr with `(discard)` (`discard` would result in illegal code)
+    let a = deb:
+      let f {.inject.} = () => (discard)
+    doAssert a == """
+let f {.inject.} = () =>
+    (discard )"""
+
+    let a2 = deb:
+      block:
+        discard
+      discard
+
+      block:
+        when true: discard
+
+      # let a = b => discard # illegal
+      discard b => (discard) # legal
+
+      block:
+        return
+    doAssert a2 == """
+block:
+  discard
+discard
+block:
+  when true:
+    discard
+discard b =>
+    (discard )
+block:
+  return"""
+
+  block: # bug #17292 (bug 4)
+    let a = deb:
+      proc `=destroy`() = discard
+      proc `'foo`(): int = discard
+      proc `foo bar baz`(): int = discard
+    let a2 = """
+proc `=destroy`() =
+  discard
+
+proc `'foo`(): int =
+  discard
+
+proc `foo bar baz`(): int =
+  discard"""
+    doAssert a2 == a
+
+  block: # setters: `foo=`
+    let a = deb:
+      proc `foo=`() = discard
+    doAssert a == """
+proc `foo=`() =
+  discard"""
+
+  block: # bug #14850
+    block:
+      let a = deb:
+        template bar(): untyped =
+          foo1:
+            discard
+            4
+          foo2(1):
+            discard
+            4
+          foo3(1):
+            discard
+            4
+          do: 1
+          do: 2
+          x.add foo4
+          x.add: foo5: 3
+          x.add foo6 do: 4
+          a.add(foo7 do:
+            echo "baz"
+            4)
+
+      doAssert a == """
+template bar(): untyped =
+  foo1:
+    discard
+    4
+  foo2(1):
+    discard
+    4
+  foo3(1):
+    discard
+    4
+  do:
+    1
+  do:
+    2
+  x.add foo4
+  x.add:
+    foo5:
+      3
+  x.add foo6 do:
+    4
+  a.add(foo7 do:
+    echo "baz"
+    4)"""
+
+  block: # one liner doc comments
+    let a1 = deb:
+      func fn1(): int = 1  ## comment
+      func fn2(): int = 1
+        ## comment
+    let a2 = debTyped:
+      func fn1(): int = 1  ## comment
+      func fn2(): int = 1
+        ## comment
+    doAssert a1 == """
+func fn1(): int =
+  ## comment
+  1
+
+func fn2(): int =
+  ## comment
+  1"""
+    doAssert a2 == """
+func fn1(): int =
+  ## comment
+  result = 1
+
+func fn2(): int =
+  ## comment
+  result = 1"""
+
+  block: # block calls
+    let a = deb:
+      foo(a, b, (c, d)):
+        e
+        f
+      do: g
+      of h: i
+      elif j: k
+      except m: n
+      do () -> u: v
+      finally: o
+
+      a + b:
+        c
+        d
+      do:
+        e
+        f
+      else: g
+
+      *a: b
+      do: c
+
+    doAssert a == """foo(a, b, (c, d)):
+  e
+  f
+do:
+  g
+of h:
+  i
+elif j:
+  k
+except m:
+  n
+do -> u:
+  v
+finally:
+  o
+a + b:
+  c
+  d
+do:
+  e
+  f
+else:
+  g
+*a:
+  b
+do:
+  c"""
+
+  doAssert repr(1..2) == "1 .. 2"
+
 static: main()
 main()
diff --git a/tests/stdlib/tropes.nim b/tests/stdlib/tropes.nim
index 5a9150a33..eb0edc364 100644
--- a/tests/stdlib/tropes.nim
+++ b/tests/stdlib/tropes.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/ropes
+import std/assertions
 
 template main() =
   block:
diff --git a/tests/stdlib/trst.nim b/tests/stdlib/trst.nim
index 0645e4150..ceab34bc9 100644
--- a/tests/stdlib/trst.nim
+++ b/tests/stdlib/trst.nim
@@ -1,22 +1,1565 @@
 discard """
   output: '''
 
+[Suite] RST parsing
+
+[Suite] RST tables
+
+[Suite] RST indentation
+
+[Suite] Markdown indentation
+
+[Suite] Warnings
+
 [Suite] RST include directive
+
+[Suite] RST escaping
+
+[Suite] RST inline markup
+
+[Suite] Misc isssues
 '''
+matrix: "--mm:refc; --mm:orc"
 """
 
 # tests for rst module
 
-import ../../lib/packages/docutils/rstgen
-import ../../lib/packages/docutils/rst
-import unittest
+import ../../lib/packages/docutils/[rstgen, rst, rstast]
+import unittest, strutils
+import std/private/miscdollars
 import os
+import std/[assertions, syncio]
+
+const preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled}
+# legacy nimforum / old default mode:
+const preferRst = {roSupportMarkdown, roNimFile, roSandboxDisabled}
+const pureRst = {roNimFile, roSandboxDisabled}
+
+proc toAst(input: string,
+            rstOptions: RstParseOptions = preferMarkdown,
+            error: ref string = nil,
+            warnings: ref seq[string] = nil): string =
+  ## If `error` is nil then no errors should be generated.
+  ## The same goes for `warnings`.
+  proc testMsgHandler(filename: string, line, col: int, msgkind: MsgKind,
+                      arg: string) =
+    let mc = msgkind.whichMsgClass
+    let a = $msgkind % arg
+    var message: string
+    toLocation(message, filename, line, col + ColRstOffset)
+    message.add " $1: $2" % [$mc, a]
+    if mc == mcError:
+      if error == nil:
+        raise newException(EParseError, "[unexpected error] " & message)
+      error[] = message
+      # we check only first error because subsequent ones may be meaningless
+      raise newException(EParseError, "")
+    else:
+      doAssert warnings != nil, "unexpected RST warning '" & message & "'"
+      warnings[].add message
+  try:
+    const filen = "input"
+
+    proc myFindFile(filename: string): string =
+      # we don't find any files in online mode:
+      result = ""
+
+    var (rst, _, _) = rstParse(input, filen, line=LineRstInit, column=ColRstInit,
+                               rstOptions, myFindFile, nil, testMsgHandler)
+    result = treeRepr(rst)
+  except EParseError as e:
+    if e.msg != "":
+      result = e.msg
+
+suite "RST parsing":
+  test "Standalone punctuation is not parsed as heading overlines":
+    check(dedent"""
+        Paragraph
+
+        !""".toAst ==
+      dedent"""
+        rnInner
+          rnParagraph
+            rnLeaf  'Paragraph'
+          rnParagraph
+            rnLeaf  '!'
+      """)
+
+    check(dedent"""
+        Paragraph1
+
+        ...
+
+        Paragraph2""".toAst ==
+      dedent"""
+        rnInner
+          rnParagraph
+            rnLeaf  'Paragraph1'
+          rnParagraph
+            rnLeaf  '...'
+          rnParagraph
+            rnLeaf  'Paragraph2'
+      """)
+
+    check(dedent"""
+        ---
+        Paragraph""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  '---'
+          rnLeaf  ' '
+          rnLeaf  'Paragraph'
+      """)
+
+  test "References are whitespace-neutral and case-insensitive":
+    # refname is 'lexical-analysis', the same for all the 3 variants:
+    check(dedent"""
+        Lexical Analysis
+        ================
+
+        Ref. `Lexical Analysis`_ or `Lexical analysis`_ or `lexical analysis`_.
+        """.toAst ==
+      dedent"""
+        rnInner
+          rnHeadline  level=1  anchor='lexical-analysis'
+            rnLeaf  'Lexical'
+            rnLeaf  ' '
+            rnLeaf  'Analysis'
+          rnParagraph
+            rnLeaf  'Ref'
+            rnLeaf  '.'
+            rnLeaf  ' '
+            rnInternalRef
+              rnInner
+                rnLeaf  'Lexical'
+                rnLeaf  ' '
+                rnLeaf  'Analysis'
+              rnLeaf  'lexical-analysis'
+            rnLeaf  ' '
+            rnLeaf  'or'
+            rnLeaf  ' '
+            rnInternalRef
+              rnInner
+                rnLeaf  'Lexical'
+                rnLeaf  ' '
+                rnLeaf  'analysis'
+              rnLeaf  'lexical-analysis'
+            rnLeaf  ' '
+            rnLeaf  'or'
+            rnLeaf  ' '
+            rnInternalRef
+              rnInner
+                rnLeaf  'lexical'
+                rnLeaf  ' '
+                rnLeaf  'analysis'
+              rnLeaf  'lexical-analysis'
+            rnLeaf  '.'
+            rnLeaf  ' '
+      """)
+
+  test "RST quoted literal blocks":
+    let expected =
+      dedent"""
+        rnInner
+          rnLeaf  'Paragraph'
+          rnLeaf  ':'
+          rnLiteralBlock
+            rnLeaf  '>x'
+        """
+
+    check(dedent"""
+        Paragraph::
+
+        >x""".toAst(rstOptions = preferRst) == expected)
+
+    check(dedent"""
+        Paragraph::
+
+            >x""".toAst(rstOptions = preferRst) == expected)
+
+  test "RST quoted literal blocks, :: at a separate line":
+    let expected =
+      dedent"""
+        rnInner
+          rnInner
+            rnLeaf  'Paragraph'
+          rnLiteralBlock
+            rnLeaf  '>x
+        >>y'
+      """
+
+    check(dedent"""
+        Paragraph
+
+        ::
+
+        >x
+        >>y""".toAst(rstOptions = preferRst) == expected)
+
+    check(dedent"""
+        Paragraph
+
+        ::
+
+          >x
+          >>y""".toAst(rstOptions = preferRst) == expected)
+
+  test "Markdown quoted blocks":
+    check(dedent"""
+        Paragraph.
+        >x""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  'Paragraph'
+          rnLeaf  '.'
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=1
+              rnLeaf  'x'
+      """)
+
+    # bug #17987
+    check(dedent"""
+        foo https://github.com/nim-lang/Nim/issues/8258
+
+        > bar""".toAst ==
+      dedent"""
+        rnInner
+          rnInner
+            rnLeaf  'foo'
+            rnLeaf  ' '
+            rnStandaloneHyperlink
+              rnLeaf  'https://github.com/nim-lang/Nim/issues/8258'
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=1
+              rnLeaf  'bar'
+      """)
+
+    let expected = dedent"""
+        rnInner
+          rnLeaf  'Paragraph'
+          rnLeaf  '.'
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=1
+              rnInner
+                rnLeaf  'x1'
+                rnLeaf  ' '
+                rnLeaf  'x2'
+            rnMarkdownBlockQuoteItem  quotationDepth=2
+              rnInner
+                rnLeaf  'y1'
+                rnLeaf  ' '
+                rnLeaf  'y2'
+            rnMarkdownBlockQuoteItem  quotationDepth=1
+              rnLeaf  'z'
+        """
+
+    check(dedent"""
+        Paragraph.
+        >x1 x2
+        >>y1 y2
+        >z""".toAst == expected)
+
+    check(dedent"""
+        Paragraph.
+        > x1 x2
+        >> y1 y2
+        > z""".toAst == expected)
+
+    check(dedent"""
+        >x
+        >y
+        >z""".toAst ==
+      dedent"""
+        rnMarkdownBlockQuote
+          rnMarkdownBlockQuoteItem  quotationDepth=1
+            rnInner
+              rnLeaf  'x'
+              rnLeaf  ' '
+              rnLeaf  'y'
+              rnLeaf  ' '
+              rnLeaf  'z'
+      """)
+
+    check(dedent"""
+        > z
+        > > >y
+        """.toAst ==
+      dedent"""
+        rnMarkdownBlockQuote
+          rnMarkdownBlockQuoteItem  quotationDepth=1
+            rnLeaf  'z'
+          rnMarkdownBlockQuoteItem  quotationDepth=3
+            rnLeaf  'y'
+        """)
+
+  test "Markdown quoted blocks: lazy":
+    let expected = dedent"""
+        rnInner
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=2
+              rnInner
+                rnLeaf  'x'
+                rnLeaf  ' '
+                rnLeaf  'continuation1'
+                rnLeaf  ' '
+                rnLeaf  'continuation2'
+          rnParagraph
+            rnLeaf  'newParagraph'
+      """
+    check(dedent"""
+        >>x
+        continuation1
+        continuation2
+
+        newParagraph""".toAst == expected)
+
+    check(dedent"""
+        >> x
+        continuation1
+        continuation2
+
+        newParagraph""".toAst == expected)
+
+    # however mixing more than 1 non-lazy line and lazy one(s) splits quote
+    # in our parser, which appeared the easiest way to handle such cases:
+    var warnings = new seq[string]
+    check(dedent"""
+        >> x
+        >> continuation1
+        continuation2
+
+        newParagraph""".toAst(warnings=warnings) ==
+      dedent"""
+        rnInner
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=2
+              rnLeaf  'x'
+            rnMarkdownBlockQuoteItem  quotationDepth=2
+              rnInner
+                rnLeaf  'continuation1'
+                rnLeaf  ' '
+                rnLeaf  'continuation2'
+          rnParagraph
+            rnLeaf  'newParagraph'
+        """)
+    check(warnings[] == @[
+        "input(2, 1) Warning: RST style: two or more quoted lines " &
+        "are followed by unquoted line 3"])
+
+  test "Markdown quoted blocks: not lazy":
+    # here is where we deviate from CommonMark specification: 'bar' below is
+    # not considered as continuation of 2-level '>> foo' quote.
+    check(dedent"""
+        >>> foo
+        > bar
+        >> baz
+        """.toAst() ==
+      dedent"""
+        rnMarkdownBlockQuote
+          rnMarkdownBlockQuoteItem  quotationDepth=3
+            rnLeaf  'foo'
+          rnMarkdownBlockQuoteItem  quotationDepth=1
+            rnLeaf  'bar'
+          rnMarkdownBlockQuoteItem  quotationDepth=2
+            rnLeaf  'baz'
+        """)
+
+
+  test "Markdown quoted blocks: inline markup works":
+    check(dedent"""
+        > hi **bold** text
+        """.toAst == dedent"""
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=1
+              rnInner
+                rnLeaf  'hi'
+                rnLeaf  ' '
+                rnStrongEmphasis
+                  rnLeaf  'bold'
+                rnLeaf  ' '
+                rnLeaf  'text'
+        """)
+
+  test "Markdown quoted blocks: blank line separator":
+    let expected = dedent"""
+      rnInner
+        rnMarkdownBlockQuote
+          rnMarkdownBlockQuoteItem  quotationDepth=1
+            rnInner
+              rnLeaf  'x'
+              rnLeaf  ' '
+              rnLeaf  'y'
+        rnMarkdownBlockQuote
+          rnMarkdownBlockQuoteItem  quotationDepth=1
+            rnInner
+              rnLeaf  'z'
+              rnLeaf  ' '
+              rnLeaf  't'
+      """
+    check(dedent"""
+        >x
+        >y
+
+        > z
+        > t""".toAst == expected)
+
+    check(dedent"""
+        >x
+        y
+
+        > z
+         t""".toAst == expected)
+
+  test "Markdown quoted blocks: nested body blocks/elements work #1":
+    let expected = dedent"""
+      rnMarkdownBlockQuote
+        rnMarkdownBlockQuoteItem  quotationDepth=1
+          rnBulletList
+            rnBulletItem
+              rnInner
+                rnLeaf  'x'
+            rnBulletItem
+              rnInner
+                rnLeaf  'y'
+      """
+
+    check(dedent"""
+        > - x
+          - y
+        """.toAst == expected)
+
+    # TODO: if bug #17340 point 28 is resolved then this may work:
+    # check(dedent"""
+    #     > - x
+    #     - y
+    #     """.toAst == expected)
+
+    check(dedent"""
+        > - x
+        > - y
+        """.toAst == expected)
+
+    check(dedent"""
+        >
+        > - x
+        >
+        > - y
+        >
+        """.toAst == expected)
+
+  test "Markdown quoted blocks: nested body blocks/elements work #2":
+    let expected = dedent"""
+      rnAdmonition  adType=note
+        [nil]
+        [nil]
+        rnDefList
+          rnDefItem
+            rnDefName
+              rnLeaf  'deflist'
+              rnLeaf  ':'
+            rnDefBody
+              rnMarkdownBlockQuote
+                rnMarkdownBlockQuoteItem  quotationDepth=2
+                  rnInner
+                    rnLeaf  'quote'
+                    rnLeaf  ' '
+                    rnLeaf  'continuation'
+      """
+
+    check(dedent"""
+        .. Note:: deflist:
+                    >> quote
+                    continuation
+        """.toAst(rstOptions = preferRst) == expected)
+
+    check(dedent"""
+        .. Note::
+           deflist:
+             >> quote
+             continuation
+        """.toAst(rstOptions = preferRst) == expected)
+
+    check(dedent"""
+        .. Note::
+           deflist:
+             >> quote
+             >> continuation
+        """.toAst(rstOptions = preferRst) == expected)
+
+    # spaces are not significant between `>`:
+    check(dedent"""
+        .. Note::
+           deflist:
+             > > quote
+             > > continuation
+        """.toAst(rstOptions = preferRst) == expected)
+
+  test "Markdown quoted blocks: de-indent handled well":
+    check(dedent"""
+        >
+        >   - x
+        >   - y
+        >
+        > Paragraph.
+        """.toAst(rstOptions = preferRst) == dedent"""
+          rnMarkdownBlockQuote
+            rnMarkdownBlockQuoteItem  quotationDepth=1
+              rnInner
+                rnBlockQuote
+                  rnBulletList
+                    rnBulletItem
+                      rnInner
+                        rnLeaf  'x'
+                    rnBulletItem
+                      rnInner
+                        rnLeaf  'y'
+                rnParagraph
+                  rnLeaf  'Paragraph'
+                  rnLeaf  '.'
+          """)
+
+  let expectCodeBlock = dedent"""
+      rnCodeBlock
+        [nil]
+        rnFieldList
+          rnField
+            rnFieldName
+              rnLeaf  'default-language'
+            rnFieldBody
+              rnLeaf  'Nim'
+        rnLiteralBlock
+          rnLeaf  'let a = 1
+      ```'
+      """
+
+  test "Markdown footnotes":
+    # Testing also 1) correct order of manually-numbered and automatically-
+    # numbered footnotes; 2) no spaces between references (html & 3 below):
+
+    check(dedent"""
+        Paragraph [^1] [^html-hyphen][^3] and [^latex]
+
+        [^1]: footnote1
+
+        [^html-hyphen]: footnote2
+           continuation2
+
+        [^latex]: footnote4
+
+        [^3]: footnote3
+            continuation3
+        """.toAst ==
+      dedent"""
+        rnInner
+          rnInner
+            rnLeaf  'Paragraph'
+            rnLeaf  ' '
+            rnFootnoteRef
+              rnInner
+                rnLeaf  '1'
+              rnLeaf  'footnote-1'
+            rnLeaf  ' '
+            rnFootnoteRef
+              rnInner
+                rnLeaf  '2'
+              rnLeaf  'footnote-htmlminushyphen'
+            rnFootnoteRef
+              rnInner
+                rnLeaf  '3'
+              rnLeaf  'footnote-3'
+            rnLeaf  ' '
+            rnLeaf  'and'
+            rnLeaf  ' '
+            rnFootnoteRef
+              rnInner
+                rnLeaf  '4'
+              rnLeaf  'footnote-latex'
+          rnFootnoteGroup
+            rnFootnote  anchor='footnote-1'
+              rnInner
+                rnLeaf  '1'
+              rnLeaf  'footnote1'
+            rnFootnote  anchor='footnote-htmlminushyphen'
+              rnInner
+                rnLeaf  '2'
+              rnInner
+                rnLeaf  'footnote2'
+                rnLeaf  ' '
+                rnLeaf  'continuation2'
+            rnFootnote  anchor='footnote-latex'
+              rnInner
+                rnLeaf  '4'
+              rnLeaf  'footnote4'
+            rnFootnote  anchor='footnote-3'
+              rnInner
+                rnLeaf  '3'
+              rnInner
+                rnLeaf  'footnote3'
+                rnLeaf  ' '
+                rnLeaf  'continuation3'
+      """)
+
+  test "Markdown code blocks with more > 3 backticks":
+    check(dedent"""
+        ````
+        let a = 1
+        ```
+        ````""".toAst == expectCodeBlock)
+
+  test "Markdown code blocks with ~~~":
+    check(dedent"""
+        ~~~
+        let a = 1
+        ```
+        ~~~""".toAst == expectCodeBlock)
+    check(dedent"""
+        ~~~~~
+        let a = 1
+        ```
+        ~~~~~""".toAst == expectCodeBlock)
+
+  test "Markdown code blocks with Nim-specific arguments":
+    check(dedent"""
+        ```nim number-lines=1 test
+        let a = 1
+        ```""".toAst ==
+      dedent"""
+        rnCodeBlock
+          rnDirArg
+            rnLeaf  'nim'
+          rnFieldList
+            rnField
+              rnFieldName
+                rnLeaf  'number-lines'
+              rnFieldBody
+                rnLeaf  '1'
+            rnField
+              rnFieldName
+                rnLeaf  'test'
+              rnFieldBody
+          rnLiteralBlock
+            rnLeaf  'let a = 1'
+        """)
+
+    check(dedent"""
+        ```nim test = "nim c $1"  number-lines = 1
+        let a = 1
+        ```""".toAst ==
+      dedent"""
+        rnCodeBlock
+          rnDirArg
+            rnLeaf  'nim'
+          rnFieldList
+            rnField
+              rnFieldName
+                rnLeaf  'test'
+              rnFieldBody
+                rnLeaf  '"nim c $1"'
+            rnField
+              rnFieldName
+                rnLeaf  'number-lines'
+              rnFieldBody
+                rnLeaf  '1'
+          rnLiteralBlock
+            rnLeaf  'let a = 1'
+        """)
+
+  test "additional indentation < 4 spaces is handled fine":
+    check(dedent"""
+        Indentation
+
+          ```nim
+            let a = 1
+          ```""".toAst ==
+      dedent"""
+        rnInner
+          rnParagraph
+            rnLeaf  'Indentation'
+          rnParagraph
+            rnCodeBlock
+              rnDirArg
+                rnLeaf  'nim'
+              [nil]
+              rnLiteralBlock
+                rnLeaf  '  let a = 1'
+      """)
+      # | |
+      # |  \ indentation of exactly two spaces before 'let a = 1'
+
+  test "no blank line is required before or after Markdown code block":
+    let inputBacktick = dedent"""
+        Some text
+        ```
+        CodeBlock()
+        ```
+        Other text"""
+    let inputTilde = dedent"""
+        Some text
+        ~~~~~~~~~
+        CodeBlock()
+        ~~~~~~~~~
+        Other text"""
+    let expected = dedent"""
+        rnInner
+          rnParagraph
+            rnLeaf  'Some'
+            rnLeaf  ' '
+            rnLeaf  'text'
+          rnParagraph
+            rnCodeBlock
+              [nil]
+              rnFieldList
+                rnField
+                  rnFieldName
+                    rnLeaf  'default-language'
+                  rnFieldBody
+                    rnLeaf  'Nim'
+              rnLiteralBlock
+                rnLeaf  'CodeBlock()'
+            rnLeaf  ' '
+            rnLeaf  'Other'
+            rnLeaf  ' '
+            rnLeaf  'text'
+      """
+    check inputBacktick.toAst == expected
+    check inputTilde.toAst == expected
+
+  test "option list has priority over definition list":
+    for opt in [preferMarkdown, preferRst]:
+      check(dedent"""
+          --defusages
+                        file
+          -o            set
+          """.toAst(rstOptions = opt) ==
+        dedent"""
+          rnOptionList
+            rnOptionListItem  order=1
+              rnOptionGroup
+                rnLeaf  '--'
+                rnLeaf  'defusages'
+              rnDescription
+                rnInner
+                  rnLeaf  'file'
+            rnOptionListItem  order=2
+              rnOptionGroup
+                rnLeaf  '-'
+                rnLeaf  'o'
+              rnDescription
+                rnLeaf  'set'
+          """)
+
+  test "items of 1 option list can be separated by blank lines":
+    check(dedent"""
+        -a  desc1
+
+        -b  desc2
+        """.toAst ==
+      dedent"""
+        rnOptionList
+          rnOptionListItem  order=1
+            rnOptionGroup
+              rnLeaf  '-'
+              rnLeaf  'a'
+            rnDescription
+              rnLeaf  'desc1'
+          rnOptionListItem  order=2
+            rnOptionGroup
+              rnLeaf  '-'
+              rnLeaf  'b'
+            rnDescription
+              rnLeaf  'desc2'
+      """)
+
+  test "definition list does not gobble up the following blocks":
+    check(dedent"""
+        defName
+            defBody
+
+        -b  desc2
+        """.toAst(rstOptions = preferRst) ==
+      dedent"""
+        rnInner
+          rnDefList
+            rnDefItem
+              rnDefName
+                rnLeaf  'defName'
+              rnDefBody
+                rnInner
+                  rnLeaf  'defBody'
+          rnOptionList
+            rnOptionListItem  order=1
+              rnOptionGroup
+                rnLeaf  '-'
+                rnLeaf  'b'
+              rnDescription
+                rnLeaf  'desc2'
+      """)
+
+  test "definition lists work correctly with additional indentation in Markdown":
+    check(dedent"""
+        Paragraph:
+          -c  desc1
+          -b  desc2
+        """.toAst() ==
+      dedent"""
+        rnInner
+          rnInner
+            rnLeaf  'Paragraph'
+            rnLeaf  ':'
+          rnOptionList
+            rnOptionListItem  order=1
+              rnOptionGroup
+                rnLeaf  '-'
+                rnLeaf  'c'
+              rnDescription
+                rnLeaf  'desc1'
+            rnOptionListItem  order=2
+              rnOptionGroup
+                rnLeaf  '-'
+                rnLeaf  'b'
+              rnDescription
+                rnLeaf  'desc2'
+      """)
+
+  test "RST comment":
+    check(dedent"""
+        .. comment1
+         comment2
+        someParagraph""".toAst ==
+      dedent"""
+        rnLeaf  'someParagraph'
+        """)
+
+    check(dedent"""
+        ..
+         comment1
+         comment2
+        someParagraph""".toAst ==
+      dedent"""
+        rnLeaf  'someParagraph'
+        """)
+
+  test "check that additional line right after .. ends comment":
+    check(dedent"""
+        ..
+
+         notAcomment1
+         notAcomment2
+        someParagraph""".toAst(rstOptions = preferRst) ==
+      dedent"""
+        rnInner
+          rnBlockQuote
+            rnInner
+              rnLeaf  'notAcomment1'
+              rnLeaf  ' '
+              rnLeaf  'notAcomment2'
+          rnParagraph
+            rnLeaf  'someParagraph'
+        """)
+
+  test "check that additional line right after .. ends comment (Markdown mode)":
+    # in Markdown small indentation does not matter so this should
+    # just be split to 2 paragraphs.
+    check(dedent"""
+        ..
+
+         notAcomment1
+         notAcomment2
+        someParagraph""".toAst ==
+      dedent"""
+        rnInner
+          rnInner
+            rnLeaf  'notAcomment1'
+            rnLeaf  ' '
+            rnLeaf  'notAcomment2'
+          rnParagraph
+            rnLeaf  'someParagraph'
+        """)
+
+  test "but blank lines after 2nd non-empty line don't end the comment":
+    check(dedent"""
+        ..
+           comment1
+
+
+         comment2
+        someParagraph""".toAst ==
+      dedent"""
+        rnLeaf  'someParagraph'
+        """)
+
+  test "using .. as separator b/w directives and block quotes":
+    check(dedent"""
+        .. note:: someNote
+
+        ..
+
+          someBlockQuote""".toAst(rstOptions = preferRst) ==
+      dedent"""
+        rnInner
+          rnAdmonition  adType=note
+            [nil]
+            [nil]
+            rnLeaf  'someNote'
+          rnBlockQuote
+            rnInner
+              rnLeaf  'someBlockQuote'
+        """)
+
+  test "no redundant blank lines in literal blocks":
+    check(dedent"""
+      Check::
+
+
+        code
+
+      """.toAst(rstOptions = preferRst) ==
+      dedent"""
+        rnInner
+          rnLeaf  'Check'
+          rnLeaf  ':'
+          rnLiteralBlock
+            rnLeaf  'code'
+      """)
+
+  test "Markdown indented code blocks":
+    check(dedent"""
+      See
+
+          some code""".toAst ==
+      dedent"""
+        rnInner
+          rnInner
+            rnLeaf  'See'
+          rnLiteralBlock
+            rnLeaf  'some code'
+      """)
+
+    # not a code block -- no blank line before:
+    check(dedent"""
+      See
+          some code""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  'See'
+          rnLeaf  ' '
+          rnLeaf  'some'
+          rnLeaf  ' '
+          rnLeaf  'code'
+      """)
+
+suite "RST tables":
+
+  test "formatting in tables works":
+    check(
+      dedent"""
+        =========  ===
+        `build`    `a`
+        =========  ===
+        """.toAst ==
+      dedent"""
+        rnTable  colCount=2
+          rnTableRow
+            rnTableDataCell
+              rnInlineCode
+                rnDirArg
+                  rnLeaf  'nim'
+                [nil]
+                rnLiteralBlock
+                  rnLeaf  'build'
+            rnTableDataCell
+              rnInlineCode
+                rnDirArg
+                  rnLeaf  'nim'
+                [nil]
+                rnLiteralBlock
+                  rnLeaf  'a'
+      """)
+
+  test "tables with slightly overflowed cells cause an error (1)":
+    var error = new string
+    check(
+      dedent"""
+        ======   ======
+         Inputs  Output
+        ======   ======
+        """.toAst(rstOptions = pureRst, error = error) == "")
+    check(error[] == "input(2, 2) Error: Illformed table: " &
+                     "this word crosses table column from the right")
+
+    # In nimforum compatibility mode & Markdown we raise a warning instead:
+    let expected = dedent"""
+      rnTable  colCount=2
+        rnTableRow
+          rnTableDataCell
+            rnLeaf  'Inputs'
+          rnTableDataCell
+            rnLeaf  'Output'
+      """
+    for opt in [preferRst, preferMarkdown]:
+      var warnings = new seq[string]
+
+      check(
+        dedent"""
+          ======   ======
+           Inputs  Output
+          ======   ======
+          """.toAst(rstOptions = opt, warnings = warnings) == expected)
+      check(warnings[] == @[
+        "input(2, 2) Warning: RST style: this word crosses table column from the right"])
+
+  test "tables with slightly overflowed cells cause an error (2)":
+    var error = new string
+    check("" == dedent"""
+      =====  =====  ======
+      Input  Output
+      =====  =====  ======
+      False  False  False
+      =====  =====  ======
+      """.toAst(rstOptions = pureRst, error = error))
+    check(error[] == "input(2, 8) Error: Illformed table: " &
+                     "this word crosses table column from the right")
+
+  test "tables with slightly underflowed cells cause an error":
+    var error = new string
+    check("" == dedent"""
+      =====  =====  ======
+      Input Output
+      =====  =====  ======
+      False  False  False
+      =====  =====  ======
+      """.toAst(rstOptions = pureRst, error = error))
+    check(error[] == "input(2, 7) Error: Illformed table: " &
+                     "this word crosses table column from the left")
+
+  test "tables with unequal underlines should be reported (1)":
+    var error = new string
+    error[] = "none"
+    check("" == dedent"""
+      =====  ======
+      Input  Output
+      =====  ======
+      False  False
+      =====  =======
+      """.toAst(rstOptions = pureRst, error = error))
+    check(error[] == "input(5, 14) Error: Illformed table: " &
+                     "end of table column #2 should end at position 13")
+
+  test "tables with unequal underlines should be reported (2)":
+    var error = new string
+    check("" == dedent"""
+      =====  ======
+      Input  Output
+      =====  =======
+      False  False
+      =====  ======
+      """.toAst(rstOptions = pureRst, error = error))
+    check(error[] == "input(3, 14) Error: Illformed table: " &
+                     "end of table column #2 should end at position 13")
+
+  test "tables with empty first cells":
+    check(
+      dedent"""
+          = = =
+          x y z
+              t
+          = = =
+          """.toAst ==
+      dedent"""
+        rnTable  colCount=3
+          rnTableRow
+            rnTableDataCell
+              rnLeaf  'x'
+            rnTableDataCell
+              rnInner
+                rnLeaf  'y'
+                rnLeaf  ' '
+            rnTableDataCell
+              rnInner
+                rnLeaf  'z'
+                rnLeaf  ' '
+                rnLeaf  't'
+        """)
+
+  test "tables with spanning cells & separators":
+    check(
+      dedent"""
+        =====  =====  ======
+           Inputs     Output
+        ------------  ------
+          A      B    A or B
+        =====  =====  ======
+        False  False  False
+        True   False  True
+        -----  -----  ------
+        False  True   True
+        True   True   True
+        =====  =====  ======
+        """.toAst ==
+      dedent"""
+        rnTable  colCount=3
+          rnTableRow
+            rnTableHeaderCell  span=2
+              rnLeaf  'Inputs'
+            rnTableHeaderCell  span=1
+              rnLeaf  'Output'
+          rnTableRow  endsHeader
+            rnTableHeaderCell
+              rnLeaf  'A'
+            rnTableHeaderCell
+              rnLeaf  'B'
+            rnTableHeaderCell
+              rnInner
+                rnLeaf  'A'
+                rnLeaf  ' '
+                rnLeaf  'or'
+                rnLeaf  ' '
+                rnLeaf  'B'
+          rnTableRow
+            rnTableDataCell
+              rnLeaf  'False'
+            rnTableDataCell
+              rnLeaf  'False'
+            rnTableDataCell
+              rnLeaf  'False'
+          rnTableRow
+            rnTableDataCell  span=1
+              rnLeaf  'True'
+            rnTableDataCell  span=1
+              rnLeaf  'False'
+            rnTableDataCell  span=1
+              rnLeaf  'True'
+          rnTableRow
+            rnTableDataCell
+              rnLeaf  'False'
+            rnTableDataCell
+              rnLeaf  'True'
+            rnTableDataCell
+              rnLeaf  'True'
+          rnTableRow
+            rnTableDataCell
+              rnLeaf  'True'
+            rnTableDataCell
+              rnLeaf  'True'
+            rnTableDataCell
+              rnLeaf  'True'
+      """)
+
+  test "tables with spanning cells with uneqal underlines cause an error":
+    var error = new string
+    check(
+      dedent"""
+        =====  =====  ======
+           Inputs     Output
+        ------------- ------
+          A      B    A or B
+        =====  =====  ======
+        """.toAst(error=error) == "")
+    check(error[] == "input(3, 1) Error: Illformed table: " &
+                     "spanning underline does not match main table columns")
+
+  let expTable = dedent"""
+      rnTable  colCount=2
+        rnTableRow
+          rnTableDataCell
+            rnLeaf  'Inputs'
+          rnTableDataCell
+            rnLeaf  'Output'
+      """
+
+  test "only tables with `=` columns specs are allowed (1)":
+    var warnings = new seq[string]
+    check(
+      dedent"""
+        ------  ------
+        Inputs  Output
+        ------  ------
+        """.toAst(warnings=warnings) ==
+      expTable)
+    check(warnings[] ==
+          @["input(1, 1) Warning: RST style: " &
+              "only tables with `=` columns specification are allowed",
+            "input(3, 1) Warning: RST style: " &
+              "only tables with `=` columns specification are allowed"])
+
+  test "only tables with `=` columns specs are allowed (2)":
+    var warnings = new seq[string]
+    check(
+      dedent"""
+        ======  ======
+        Inputs  Output
+        ~~~~~~  ~~~~~~
+        """.toAst(warnings=warnings) ==
+      expTable)
+    check(warnings[] ==
+          @["input(3, 1) Warning: RST style: "&
+              "only tables with `=` columns specification are allowed"])
+
+
+suite "RST indentation":
+  test "nested bullet lists":
+    let input = dedent """
+      * - bullet1
+        - bullet2
+      * - bullet3
+        - bullet4
+      """
+    let output = input.toAst
+    check(output == dedent"""
+      rnBulletList
+        rnBulletItem
+          rnBulletList
+            rnBulletItem
+              rnInner
+                rnLeaf  'bullet1'
+            rnBulletItem
+              rnInner
+                rnLeaf  'bullet2'
+        rnBulletItem
+          rnBulletList
+            rnBulletItem
+              rnInner
+                rnLeaf  'bullet3'
+            rnBulletItem
+              rnInner
+                rnLeaf  'bullet4'
+      """)
+
+  test "nested markup blocks":
+    let input = dedent"""
+      #) .. Hint:: .. Error:: none
+      #) .. Warning:: term0
+                        Definition0
+      #) some
+         paragraph1
+      #) term1
+           Definition1
+         term2
+           Definition2
+    """
+    check(input.toAst(rstOptions = preferRst) == dedent"""
+      rnEnumList  labelFmt=1)
+        rnEnumItem
+          rnAdmonition  adType=hint
+            [nil]
+            [nil]
+            rnAdmonition  adType=error
+              [nil]
+              [nil]
+              rnLeaf  'none'
+        rnEnumItem
+          rnAdmonition  adType=warning
+            [nil]
+            [nil]
+            rnDefList
+              rnDefItem
+                rnDefName
+                  rnLeaf  'term0'
+                rnDefBody
+                  rnInner
+                    rnLeaf  'Definition0'
+        rnEnumItem
+          rnInner
+            rnLeaf  'some'
+            rnLeaf  ' '
+            rnLeaf  'paragraph1'
+        rnEnumItem
+          rnDefList
+            rnDefItem
+              rnDefName
+                rnLeaf  'term1'
+              rnDefBody
+                rnInner
+                  rnLeaf  'Definition1'
+            rnDefItem
+              rnDefName
+                rnLeaf  'term2'
+              rnDefBody
+                rnInner
+                  rnLeaf  'Definition2'
+      """)
+
+  test "code-block parsing":
+    let input1 = dedent"""
+      .. code-block:: nim
+          :test: "nim c $1"
+
+        template additive(typ: typedesc) =
+          discard
+      """
+    let input2 = dedent"""
+      .. code-block:: nim
+        :test: "nim c $1"
+
+        template additive(typ: typedesc) =
+          discard
+      """
+    let input3 = dedent"""
+      .. code-block:: nim
+         :test: "nim c $1"
+         template additive(typ: typedesc) =
+           discard
+      """
+    let inputWrong = dedent"""
+      .. code-block:: nim
+       :test: "nim c $1"
+
+         template additive(typ: typedesc) =
+           discard
+      """
+    let ast = dedent"""
+      rnCodeBlock
+        rnDirArg
+          rnLeaf  'nim'
+        rnFieldList
+          rnField
+            rnFieldName
+              rnLeaf  'test'
+            rnFieldBody
+              rnInner
+                rnLeaf  '"'
+                rnLeaf  'nim'
+                rnLeaf  ' '
+                rnLeaf  'c'
+                rnLeaf  ' '
+                rnLeaf  '$'
+                rnLeaf  '1'
+                rnLeaf  '"'
+          rnField
+            rnFieldName
+              rnLeaf  'default-language'
+            rnFieldBody
+              rnLeaf  'Nim'
+        rnLiteralBlock
+          rnLeaf  'template additive(typ: typedesc) =
+        discard'
+      """
+    check input1.toAst == ast
+    check input2.toAst == ast
+    check input3.toAst == ast
+    # "template..." should be parsed as a definition list attached to ":test:":
+    check inputWrong.toAst != ast
+
+  test "Markdown definition lists work in conjunction with bullet lists":
+    check(dedent"""
+        * some term
+          : the definition
+
+        Paragraph.""".toAst ==
+      dedent"""
+        rnInner
+          rnBulletList
+            rnBulletItem
+              rnMdDefList
+                rnDefItem
+                  rnDefName
+                    rnLeaf  'some'
+                    rnLeaf  ' '
+                    rnLeaf  'term'
+                  rnDefBody
+                    rnInner
+                      rnLeaf  'the'
+                      rnLeaf  ' '
+                      rnLeaf  'definition'
+          rnParagraph
+            rnLeaf  'Paragraph'
+            rnLeaf  '.'
+      """)
+
+  test "Markdown definition lists work with blank lines and extra paragraphs":
+    check(dedent"""
+        Term1
+
+        :   Definition1
+
+        Term2 *inline markup*
+
+        :   Definition2
+
+            Paragraph2
+
+        Term3
+        : * point1
+          * point2
+        : term3definition2
+      """.toAst == dedent"""
+        rnMdDefList
+          rnDefItem
+            rnDefName
+              rnLeaf  'Term1'
+            rnDefBody
+              rnInner
+                rnLeaf  'Definition1'
+          rnDefItem
+            rnDefName
+              rnLeaf  'Term2'
+              rnLeaf  ' '
+              rnEmphasis
+                rnLeaf  'inline'
+                rnLeaf  ' '
+                rnLeaf  'markup'
+            rnDefBody
+              rnParagraph
+                rnLeaf  'Definition2'
+              rnParagraph
+                rnLeaf  'Paragraph2'
+          rnDefItem
+            rnDefName
+              rnLeaf  'Term3'
+            rnDefBody
+              rnBulletList
+                rnBulletItem
+                  rnInner
+                    rnLeaf  'point1'
+                rnBulletItem
+                  rnInner
+                    rnLeaf  'point2'
+            rnDefBody
+              rnInner
+                rnLeaf  'term3definition2'
+      """)
+
+suite "Markdown indentation":
+  test "Markdown paragraph indentation":
+    # Additional spaces (<=3) of indentation does not break the paragraph.
+    # TODO: in 2nd case de-indentation causes paragraph to break, this is
+    # reasonable but does not seem to conform the Markdown spec.
+    check(dedent"""
+      Start1
+        stop1
+
+        Start2
+      stop2
+      """.toAst ==
+      dedent"""
+        rnInner
+          rnParagraph
+            rnLeaf  'Start1'
+            rnLeaf  ' '
+            rnLeaf  'stop1'
+          rnParagraph
+            rnLeaf  'Start2'
+          rnParagraph
+            rnLeaf  'stop2'
+            rnLeaf  ' '
+      """)
+
+suite "Warnings":
+  test "warnings for broken footnotes/links/substitutions":
+    let input = dedent"""
+      firstParagraph
+
+      footnoteRef [som]_
+
+      link `a broken Link`_
+
+      substitution |undefined subst|
+
+      link short.link_
+
+      lastParagraph
+      """
+    var warnings = new seq[string]
+    let output = input.toAst(rstOptions=preferRst, warnings=warnings)
+    check(warnings[] == @[
+        "input(3, 14) Warning: broken link 'citation-som'",
+        "input(5, 7) Warning: broken link 'a broken Link'",
+        "input(7, 15) Warning: unknown substitution 'undefined subst'",
+        "input(9, 6) Warning: broken link 'short.link'"
+        ])
+
+  test "Pandoc Markdown concise link warning points to target":
+    var warnings = new seq[string]
+    check(
+      "ref [here][target]".toAst(warnings=warnings) ==
+      dedent"""
+        rnInner
+          rnLeaf  'ref'
+          rnLeaf  ' '
+          rnPandocRef
+            rnInner
+              rnLeaf  'here'
+            rnInner
+              rnLeaf  'target'
+      """)
+    check warnings[] == @["input(1, 12) Warning: broken link 'target'"]
+
+  test "With include directive and blank lines at the beginning":
+    "other.rst".writeFile(dedent"""
+
+
+        firstParagraph
+
+        here brokenLink_""")
+    let input = ".. include:: other.rst"
+    var warnings = new seq[string]
+    let output = input.toAst(warnings=warnings)
+    check warnings[] == @["other.rst(5, 6) Warning: broken link 'brokenLink'"]
+    check(output == dedent"""
+      rnInner
+        rnParagraph
+          rnLeaf  'firstParagraph'
+        rnParagraph
+          rnLeaf  'here'
+          rnLeaf  ' '
+          rnRstRef
+            rnLeaf  'brokenLink'
+      """)
+    removeFile("other.rst")
+
+  test "warnings for ambiguous links (references + anchors)":
+    # Reference like `x`_ generates a link alias x that may clash with others
+    let input = dedent"""
+      Manual reference: `foo <#foo,string,string>`_
+
+      .. _foo:
+
+      Paragraph.
+
+      Ref foo_
+      """
+    var warnings = new seq[string]
+    let output = input.toAst(warnings=warnings)
+    check(warnings[] == @[
+      dedent """
+      input(7, 5) Warning: ambiguous doc link `foo`
+        clash:
+          (3, 8): (manual directive anchor)
+          (1, 45): (implicitly-generated hyperlink alias)"""
+    ])
+    # reference should be resolved to the manually set anchor:
+    check(output ==
+      dedent"""
+        rnInner
+          rnParagraph
+            rnLeaf  'Manual'
+            rnLeaf  ' '
+            rnLeaf  'reference'
+            rnLeaf  ':'
+            rnLeaf  ' '
+            rnHyperlink
+              rnInner
+                rnLeaf  'foo'
+              rnInner
+                rnLeaf  '#foo,string,string'
+          rnParagraph  anchor='foo'
+            rnLeaf  'Paragraph'
+            rnLeaf  '.'
+          rnParagraph
+            rnLeaf  'Ref'
+            rnLeaf  ' '
+            rnInternalRef
+              rnInner
+                rnLeaf  'foo'
+              rnLeaf  'foo'
+            rnLeaf  ' '
+      """)
 
 suite "RST include directive":
   test "Include whole":
     "other.rst".writeFile("**test1**")
     let input = ".. include:: other.rst"
-    doAssert "<strong>test1</strong>" == rstTohtml(input, {}, defaultConfig())
+    doAssert "<strong>test1</strong>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
     removeFile("other.rst")
 
   test "Include starting from":
@@ -30,7 +1573,7 @@ OtherStart
 .. include:: other.rst
              :start-after: OtherStart
 """
-    doAssert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
+    check "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
     removeFile("other.rst")
 
   test "Include everything before":
@@ -44,7 +1587,7 @@ And this should **NOT** be visible in `docs.html`
 .. include:: other.rst
              :end-before: OtherEnd
 """
-    doAssert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
+    doAssert "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
     removeFile("other.rst")
 
 
@@ -62,7 +1605,7 @@ And this should **NOT** be visible in `docs.html`
              :start-after: OtherStart
              :end-before: OtherEnd
 """
-    doAssert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
+    check "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
     removeFile("other.rst")
 
 
@@ -82,5 +1625,370 @@ And this should **NOT** be visible in `docs.html`
              :start-after: OtherStart
              :end-before: OtherEnd
 """
-    doAssert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
+    doAssert "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
     removeFile("other.rst")
+
+suite "RST escaping":
+  test "backspaces":
+    check("""\ this""".toAst == dedent"""
+      rnLeaf  'this'
+      """)
+
+    check("""\\ this""".toAst == dedent"""
+      rnInner
+        rnLeaf  '\'
+        rnLeaf  ' '
+        rnLeaf  'this'
+      """)
+
+    check("""\\\ this""".toAst == dedent"""
+      rnInner
+        rnLeaf  '\'
+        rnLeaf  'this'
+      """)
+
+    check("""\\\\ this""".toAst == dedent"""
+      rnInner
+        rnLeaf  '\'
+        rnLeaf  '\'
+        rnLeaf  ' '
+        rnLeaf  'this'
+      """)
+
+suite "RST inline markup":
+  test "* and ** surrounded by spaces are not inline markup":
+    check("a * b * c ** d ** e".toAst == dedent"""
+      rnInner
+        rnLeaf  'a'
+        rnLeaf  ' '
+        rnLeaf  '*'
+        rnLeaf  ' '
+        rnLeaf  'b'
+        rnLeaf  ' '
+        rnLeaf  '*'
+        rnLeaf  ' '
+        rnLeaf  'c'
+        rnLeaf  ' '
+        rnLeaf  '**'
+        rnLeaf  ' '
+        rnLeaf  'd'
+        rnLeaf  ' '
+        rnLeaf  '**'
+        rnLeaf  ' '
+        rnLeaf  'e'
+      """)
+
+  test "end-string has repeating symbols":
+    check("*emphasis content****".toAst == dedent"""
+      rnEmphasis
+        rnLeaf  'emphasis'
+        rnLeaf  ' '
+        rnLeaf  'content'
+        rnLeaf  '***'
+      """)
+
+    check("""*emphasis content\****""".toAst == dedent"""
+      rnEmphasis
+        rnLeaf  'emphasis'
+        rnLeaf  ' '
+        rnLeaf  'content'
+        rnLeaf  '*'
+        rnLeaf  '**'
+      """)  # exact configuration of leafs with * is not really essential,
+            # only total number of * is essential
+
+    check("**strong content****".toAst == dedent"""
+      rnStrongEmphasis
+        rnLeaf  'strong'
+        rnLeaf  ' '
+        rnLeaf  'content'
+        rnLeaf  '**'
+      """)
+
+    check("""**strong content*\****""".toAst == dedent"""
+      rnStrongEmphasis
+        rnLeaf  'strong'
+        rnLeaf  ' '
+        rnLeaf  'content'
+        rnLeaf  '*'
+        rnLeaf  '*'
+        rnLeaf  '*'
+      """)
+
+    check("``lit content`````".toAst == dedent"""
+      rnInlineLiteral
+        rnLeaf  'lit'
+        rnLeaf  ' '
+        rnLeaf  'content'
+        rnLeaf  '```'
+      """)
+
+  test "interpreted text parsing: code fragments":
+    check(dedent"""
+        .. default-role:: option
+
+        `--gc:refc`""".toAst ==
+      dedent"""
+        rnInner
+          rnDefaultRole
+            rnDirArg
+              rnLeaf  'option'
+            [nil]
+            [nil]
+          rnParagraph
+            rnCodeFragment
+              rnInner
+                rnLeaf  '--'
+                rnLeaf  'gc'
+                rnLeaf  ':'
+                rnLeaf  'refc'
+              rnLeaf  'option'
+        """)
+
+  test """interpreted text can be ended with \` """:
+    let output = (".. default-role:: literal\n" & """`\``""").toAst
+    check(output.endsWith """
+  rnParagraph
+    rnInlineLiteral
+      rnLeaf  '`'""" & "\n")
+
+    let output2 = """`\``""".toAst
+    check(output2 == dedent"""
+      rnInlineCode
+        rnDirArg
+          rnLeaf  'nim'
+        [nil]
+        rnLiteralBlock
+          rnLeaf  '`'
+      """)
+
+    let output3 = """`proc \`+\``""".toAst
+    check(output3 == dedent"""
+      rnInlineCode
+        rnDirArg
+          rnLeaf  'nim'
+        [nil]
+        rnLiteralBlock
+          rnLeaf  'proc `+`'
+      """)
+
+    check("""`\\`""".toAst ==
+      dedent"""
+        rnInlineCode
+          rnDirArg
+            rnLeaf  'nim'
+          [nil]
+          rnLiteralBlock
+            rnLeaf  '\\'
+        """)
+
+  test "Markdown-style code/backtick":
+    # no whitespace is required before `
+    check("`try`...`except`".toAst ==
+      dedent"""
+        rnInner
+          rnInlineCode
+            rnDirArg
+              rnLeaf  'nim'
+            [nil]
+            rnLiteralBlock
+              rnLeaf  'try'
+          rnLeaf  '...'
+          rnInlineCode
+            rnDirArg
+              rnLeaf  'nim'
+            [nil]
+            rnLiteralBlock
+              rnLeaf  'except'
+        """)
+
+
+  test """inline literals can contain \ anywhere""":
+    check("""``\``""".toAst == dedent"""
+      rnInlineLiteral
+        rnLeaf  '\'
+      """)
+
+    check("""``\\``""".toAst == dedent"""
+      rnInlineLiteral
+        rnLeaf  '\'
+        rnLeaf  '\'
+      """)
+
+    check("""``\```""".toAst == dedent"""
+      rnInlineLiteral
+        rnLeaf  '\'
+        rnLeaf  '`'
+      """)
+
+    check("""``\\```""".toAst == dedent"""
+      rnInlineLiteral
+        rnLeaf  '\'
+        rnLeaf  '\'
+        rnLeaf  '`'
+      """)
+
+    check("""``\````""".toAst == dedent"""
+      rnInlineLiteral
+        rnLeaf  '\'
+        rnLeaf  '`'
+        rnLeaf  '`'
+      """)
+
+  test "references with _ at the end":
+    check(dedent"""
+      .. _lnk: https
+
+      lnk_""".toAst ==
+      dedent"""
+        rnHyperlink
+          rnInner
+            rnLeaf  'lnk'
+          rnInner
+            rnLeaf  'https'
+      """)
+
+  test "not a hyper link":
+    check(dedent"""
+      .. _lnk: https
+
+      lnk___""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  'lnk'
+          rnLeaf  '___'
+      """)
+
+  test "no punctuation in the end of a standalone URI is allowed":
+    check(dedent"""
+        [see (http://no.org)], end""".toAst(rstOptions = preferRst) ==
+      dedent"""
+        rnInner
+          rnLeaf  '['
+          rnLeaf  'see'
+          rnLeaf  ' '
+          rnLeaf  '('
+          rnStandaloneHyperlink
+            rnLeaf  'http://no.org'
+          rnLeaf  ')'
+          rnLeaf  ']'
+          rnLeaf  ','
+          rnLeaf  ' '
+          rnLeaf  'end'
+        """)
+
+    # but `/` at the end is OK
+    check(
+      dedent"""
+        See http://no.org/ end""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  'See'
+          rnLeaf  ' '
+          rnStandaloneHyperlink
+            rnLeaf  'http://no.org/'
+          rnLeaf  ' '
+          rnLeaf  'end'
+        """)
+
+    # a more complex URL with some made-up ending '&='.
+    # Github Markdown would include final &= and
+    # so would rst2html.py in contradiction with RST spec.
+    check(
+      dedent"""
+        See https://www.google.com/url?sa=t&source=web&cd=&cad=rja&url=https%3A%2F%2Fnim-lang.github.io%2FNim%2Frst.html%23features&usg=AO&= end""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  'See'
+          rnLeaf  ' '
+          rnStandaloneHyperlink
+            rnLeaf  'https://www.google.com/url?sa=t&source=web&cd=&cad=rja&url=https%3A%2F%2Fnim-lang.github.io%2FNim%2Frst.html%23features&usg=AO'
+          rnLeaf  '&'
+          rnLeaf  '='
+          rnLeaf  ' '
+          rnLeaf  'end'
+        """)
+
+  test "Markdown-style link can be split to a few lines":
+    check(dedent"""
+        is [term-rewriting
+        macros](manual.html#term-rewriting-macros)""".toAst ==
+      dedent"""
+        rnInner
+          rnLeaf  'is'
+          rnLeaf  ' '
+          rnHyperlink
+            rnLeaf  'term-rewriting macros'
+            rnLeaf  'manual.html#term-rewriting-macros'
+      """)
+
+  test "URL with balanced parentheses (Markdown rule)":
+    # 2 balanced parens, 1 unbalanced:
+    check(dedent"""
+        https://en.wikipedia.org/wiki/APL_((programming_language)))""".toAst ==
+      dedent"""
+        rnInner
+          rnStandaloneHyperlink
+            rnLeaf  'https://en.wikipedia.org/wiki/APL_((programming_language))'
+          rnLeaf  ')'
+      """)
+
+    # the same for Markdown-style link:
+    check(dedent"""
+        [foo [bar]](https://en.wikipedia.org/wiki/APL_((programming_language))))""".toAst ==
+      dedent"""
+        rnInner
+          rnHyperlink
+            rnLeaf  'foo [bar]'
+            rnLeaf  'https://en.wikipedia.org/wiki/APL_((programming_language))'
+          rnLeaf  ')'
+      """)
+
+    # unbalanced (here behavior is more RST-like actually):
+    check(dedent"""
+        https://en.wikipedia.org/wiki/APL_(programming_language(""".toAst ==
+      dedent"""
+        rnInner
+          rnStandaloneHyperlink
+            rnLeaf  'https://en.wikipedia.org/wiki/APL_(programming_language'
+          rnLeaf  '('
+      """)
+
+    # unbalanced [, but still acceptable:
+    check(dedent"""
+        [my {link example](http://example.com/bracket_(symbol_[))""".toAst ==
+      dedent"""
+        rnHyperlink
+          rnLeaf  'my {link example'
+          rnLeaf  'http://example.com/bracket_(symbol_[)'
+      """)
+
+  test "not a Markdown link":
+    # bug #17340 (27) `f` will be considered as a protocol and blocked as unsafe
+    var warnings = new seq[string]
+    check("[T](f: var Foo)".toAst(warnings = warnings) ==
+      dedent"""
+        rnInner
+          rnLeaf  '['
+          rnLeaf  'T'
+          rnLeaf  ']'
+          rnLeaf  '('
+          rnLeaf  'f'
+          rnLeaf  ':'
+          rnLeaf  ' '
+          rnLeaf  'var'
+          rnLeaf  ' '
+          rnLeaf  'Foo'
+          rnLeaf  ')'
+      """)
+    check(warnings[] == @["input(1, 5) Warning: broken link 'f'"])
+
+suite "Misc isssues":
+  test "Markdown CodeblockFields in one line (lacking enclosing ```)":
+    let message = """
+    ```llvm-profdata merge first.profraw second.profraw third.profraw <more stuff maybe> -output data.profdata```"""
+
+    try:
+      echo rstgen.rstToHtml(message, {roSupportMarkdown}, nil)
+    except EParseError:
+      discard
diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim
index cf82cdf91..6253e7146 100644
--- a/tests/stdlib/trstgen.nim
+++ b/tests/stdlib/trstgen.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 outputsub: ""
 """
 
@@ -8,9 +9,15 @@ import ../../lib/packages/docutils/rstgen
 import ../../lib/packages/docutils/rst
 import unittest, strutils, strtabs
 import std/private/miscdollars
+import std/assertions
+
+const
+  NoSandboxOpts = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled}
+  preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile}
+  preferRst = {roSupportMarkdown, roNimFile}
 
 proc toHtml(input: string,
-            rstOptions: RstParseOptions = {roSupportMarkdown},
+            rstOptions: RstParseOptions = preferMarkdown,
             error: ref string = nil,
             warnings: ref seq[string] = nil): string =
   ## If `error` is nil then no errors should be generated.
@@ -23,18 +30,30 @@ proc toHtml(input: string,
     toLocation(message, filename, line, col + ColRstOffset)
     message.add " $1: $2" % [$mc, a]
     if mc == mcError:
-      doAssert error != nil, "unexpected RST error '" & message & "'"
+      if error == nil:
+        raise newException(EParseError, "[unexpected error] " & message)
       error[] = message
       # we check only first error because subsequent ones may be meaningless
-      raise newException(EParseError, message)
+      raise newException(EParseError, "")
     else:
       doAssert warnings != nil, "unexpected RST warning '" & message & "'"
       warnings[].add message
   try:
     result = rstToHtml(input, rstOptions, defaultConfig(),
                        msgHandler=testMsgHandler)
-  except EParseError:
-    discard
+  except EParseError as e:
+    if e.msg != "":
+      result = e.msg
+
+# inline code tags (for parsing originated from highlite.nim)
+proc id(str: string): string = """<span class="Identifier">"""  & str & "</span>"
+proc op(str: string): string = """<span class="Operator">"""    & str & "</span>"
+proc pu(str: string): string = """<span class="Punctuation">""" & str & "</span>"
+proc optionListLabel(opt: string): string =
+  """<div class="option-list-label"><tt><span class="option">""" &
+  opt &
+  "</span></tt></div>"
+
 
 suite "YAML syntax highlighting":
   test "Basics":
@@ -131,6 +150,25 @@ suite "YAML syntax highlighting":
   <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 "Directives: warnings":
+    let input = dedent"""
+      .. non-existent-warning: Paragraph.
+
+      .. another.wrong:warning::: Paragraph.
+      """
+    var warnings = new seq[string]
+    let output = input.toHtml(warnings=warnings)
+    check output == ""
+    doAssert warnings[].len == 2
+    check "(1, 24) Warning: RST style:" in warnings[0]
+    check "double colon :: may be missing at end of 'non-existent-warning'" in warnings[0]
+    check "(3, 25) Warning: RST style:" in warnings[1]
+    check "RST style: too many colons for a directive (should be ::)" in warnings[1]
+
+  test "not a directive":
+    let input = "..warning:: I am not a warning."
+    check input.toHtml == input
+
   test "Anchors, Aliases, Tags":
     let input = """.. code-block:: yaml
     --- !!map
@@ -196,13 +234,18 @@ suite "RST/Markdown general":
 |              | F2 without pipe
 not in table"""
     let output1 = input1.toHtml
-    doAssert output1 == """<table border="1" class="docutils"><tr><th>A1 header</th><th>A2 | not fooled</th></tr>
+    #[
+    TODO: `\|` inside a table cell should render as `|`
+        `|` outside a table cell should render as `\|`
+    consistently with markdown, see https://stackoverflow.com/a/66557930/1426932
+    ]#
+    check(output1 == """
+<table border="1" class="docutils"><tr><th>A1 header</th><th>A2 | not fooled</th></tr>
 <tr><td>C1</td><td>C2 <strong>bold</strong></td></tr>
-<tr><td>D1 <tt class="docutils literal"><span class="pre">code |</span></tt></td><td>D2</td></tr>
+<tr><td>D1 <tt class="docutils literal"><span class="pre">""" & id"code" & " " & op"\|" & """</span></tt></td><td>D2</td></tr>
 <tr><td>E1 | text</td><td></td></tr>
 <tr><td></td><td>F2 without pipe</td></tr>
-</table><p>not in table</p>
-"""
+</table><p>not in table</p>""")
     let input2 = """
 | A1 header | A2 |
 | --- | --- |"""
@@ -223,7 +266,7 @@ A2     A3
 A4     A5
 ====   === """
     let output1 = rstToLatex(input1, {})
-    doAssert "{|X|X|}" in output1  # 2 columns
+    doAssert "{LL}" in output1  # 2 columns
     doAssert count(output1, "\\\\") == 4  # 4 rows
     for cell in ["H0", "H1", "A0", "A1", "A2", "A3", "A4", "A5"]:
       doAssert cell in output1
@@ -238,7 +281,7 @@ A0     A1   X
        Ax   Y
 ====   ===  = """
     let output2 = rstToLatex(input2, {})
-    doAssert "{|X|X|X|}" in output2  # 3 columns
+    doAssert "{LLL}" in output2  # 3 columns
     doAssert count(output2, "\\\\") == 2  # 2 rows
     for cell in ["H0", "H1", "H", "A0", "A1", "X", "Ax", "Y"]:
       doAssert cell in output2
@@ -348,7 +391,7 @@ Some chapter
       ~~~~~
 
       """
-    let output9good = input9good.toHtml
+    let output9good = input9good.toHtml(preferRst)
     doAssert "<h1 id=\"level1\">Level1</h1>" in output9good
     doAssert "<h2 id=\"level2\">Level2</h2>" in output9good
     doAssert "<h3 id=\"level3\">Level3</h3>" in output9good
@@ -363,7 +406,7 @@ Some chapter
 
       Level2
       ------
-      
+
       Level3
       ~~~~~~
 
@@ -372,21 +415,22 @@ Some chapter
 
       More
       ~~~~
-      
+
       Another
       -------
 
       """
     var error9Bad = new string
-    let output9Bad = input9bad.toHtml(error=error9Bad)
+    let output9Bad = input9Bad.toHtml(preferRst, error=error9Bad)
     check(error9Bad[] == "input(15, 1) Error: new section expected (section " &
             "level inconsistent: underline ~~~~~ unexpectedly found, while " &
             "the following intermediate section level(s) are missing on " &
             "lines 12..15: underline -----)")
 
+  test "RST sections overline":
     # the same as input9good but with overline headings
     # first overline heading has a special meaning: document title
-    let input10 = dedent """
+    let input = dedent """
       ======
       Title0
       ======
@@ -418,22 +462,23 @@ Some chapter
       ~~~~~
 
       """
-    var option: bool
     var rstGenera: RstGenerator
-    var output10: string
-    rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", {})
-    rstGenera.renderRstToOut(rstParse(input10, "", 1, 1, option, {}), output10)
+    var output: string
+    let (rst, files, _) = rstParse(input, "", 1, 1, {})
+    rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", filenames = files)
+    rstGenera.renderRstToOut(rst, output)
     doAssert rstGenera.meta[metaTitle] == "Title0"
-    doAssert rstGenera.meta[metaSubTitle] == "SubTitle0"
-    doAssert "<h1 id=\"level1\"><center>Level1</center></h1>" in output10
-    doAssert "<h2 id=\"level2\">Level2</h2>" in output10
-    doAssert "<h3 id=\"level3\"><center>Level3</center></h3>" in output10
-    doAssert "<h1 id=\"l1\"><center>L1</center></h1>" in output10
-    doAssert "<h2 id=\"another2\">Another2</h2>" in output10
-    doAssert "<h3 id=\"more3\"><center>More3</center></h3>" in output10
-
+    doAssert rstGenera.meta[metaSubtitle] == "SubTitle0"
+    doAssert "<h1 id=\"level1\"><center>Level1</center></h1>" in output
+    doAssert "<h2 id=\"level2\">Level2</h2>" in output
+    doAssert "<h3 id=\"level3\"><center>Level3</center></h3>" in output
+    doAssert "<h1 id=\"l1\"><center>L1</center></h1>" in output
+    doAssert "<h2 id=\"another2\">Another2</h2>" in output
+    doAssert "<h3 id=\"more3\"><center>More3</center></h3>" in output
+
+  test "RST sections overline 2":
     # check that a paragraph prevents interpreting overlines as document titles
-    let input11 = dedent """
+    let input = dedent """
       Paragraph
 
       ======
@@ -444,18 +489,19 @@ Some chapter
       SubTitle0
       +++++++++
       """
-    var option11: bool
-    var rstGenera11: RstGenerator
-    var output11: string
-    rstGenera11.initRstGenerator(outHtml, defaultConfig(), "input", {})
-    rstGenera11.renderRstToOut(rstParse(input11, "", 1, 1, option11, {}), output11)
-    doAssert rstGenera11.meta[metaTitle] == ""
-    doAssert rstGenera11.meta[metaSubTitle] == ""
-    doAssert "<h1 id=\"title0\"><center>Title0</center></h1>" in output11
-    doAssert "<h2 id=\"subtitle0\"><center>SubTitle0</center></h2>" in output11
-
+    var rstGenera: RstGenerator
+    var output: string
+    let (rst, files, _) = rstParse(input, "", 1, 1, {})
+    rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", filenames=files)
+    rstGenera.renderRstToOut(rst, output)
+    doAssert rstGenera.meta[metaTitle] == ""
+    doAssert rstGenera.meta[metaSubtitle] == ""
+    doAssert "<h1 id=\"title0\"><center>Title0</center></h1>" in output
+    doAssert "<h2 id=\"subtitle0\"><center>SubTitle0</center></h2>" in output
+
+  test "RST+Markdown sections":
     # check that RST and Markdown headings don't interfere
-    let input12 = dedent """
+    let input = dedent """
       ======
       Title0
       ======
@@ -473,14 +519,14 @@ Some chapter
       MySection2a
       -----------
       """
-    var option12: bool
-    var rstGenera12: RstGenerator
-    var output12: string
-    rstGenera12.initRstGenerator(outHtml, defaultConfig(), "input", {})
-    rstGenera12.renderRstToOut(rstParse(input12, "", 1, 1, option12, {roSupportMarkdown}), output12)
-    doAssert rstGenera12.meta[metaTitle] == "Title0"
-    doAssert rstGenera12.meta[metaSubTitle] == ""
-    doAssert output12 ==
+    var rstGenera: RstGenerator
+    var output: string
+    let (rst, files, _) = rstParse(input, "", 1, 1, {roSupportMarkdown})
+    rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", filenames=files)
+    rstGenera.renderRstToOut(rst, output)
+    doAssert rstGenera.meta[metaTitle] == "Title0"
+    doAssert rstGenera.meta[metaSubtitle] == ""
+    doAssert output ==
              "\n<h1 id=\"mysection1a\">MySection1a</h1>" & # RST
              "\n<h1 id=\"mysection1b\">MySection1b</h1>" & # Markdown
              "\n<h1 id=\"mysection1c\">MySection1c</h1>" & # RST
@@ -492,6 +538,63 @@ Some chapter
     let output1 = input1.toHtml
     doAssert output1 == "GC_step"
 
+  test "RST anchors/links to headings":
+    # Currently in TOC mode anchors are modified (for making links from
+    # the TOC unique)
+    let inputNoToc = dedent"""
+        Type relations
+        ==============
+
+        Convertible relation
+        --------------------
+
+        Ref. `Convertible relation`_
+        """
+    let outputNoToc = inputNoToc.toHtml
+    check outputNoToc.count("id=\"type-relations\"") == 1
+    check outputNoToc.count("id=\"convertible-relation\"") == 1
+    check outputNoToc.count("href=\"#convertible-relation\"") == 1
+
+    let inputTocCases = @[
+      dedent"""
+        .. contents::
+
+        Type relations
+        ==============
+
+        Convertible relation
+        --------------------
+
+        Ref. `Convertible relation`_
+
+        Guards and locks
+        ================
+        """,
+      dedent"""
+        Ref. `Convertible relation`_
+
+        .. contents::
+
+        Type relations
+        ==============
+
+        Convertible relation
+        --------------------
+
+        Guards and locks
+        ================
+        """
+    ]
+    for inputToc in inputTocCases:
+      let outputToc = inputToc.toHtml
+      check outputToc.count("id=\"type-relations\"") == 1
+      check outputToc.count("id=\"type-relations-convertible-relation\"") == 1
+      check outputToc.count("id=\"convertible-relation\">") == 0
+      # Besides "Ref.", heading also contains link to itself:
+      check outputToc.count(
+          "href=\"#type-relations-convertible-relation\">") == 2
+      check outputToc.count("href=\"#convertible-relation\"") == 0
+
   test "RST links":
     let input1 = """
 Want to learn about `my favorite programming language`_?
@@ -508,15 +611,15 @@ context1
 
 context2
 """
-    let output1 = input1.toHtml
+    let output1 = input1.toHtml(preferRst)
     doAssert "<hr" in output1
 
     let input2 = """
 This is too short to be a transition:
 
 ---
-
 context2
+---
 """
     var error2 = new string
     let output2 = input2.toHtml(error=error2)
@@ -530,7 +633,7 @@ Test literal block
 ::
 
   check """
-    let output1 = input1.toHtml
+    let output1 = input1.toHtml(preferRst)
     doAssert "<pre>" in output1
 
   test "Markdown code block":
@@ -538,9 +641,14 @@ Test literal block
 ```
 let x = 1
 ``` """
-    let output1 = input1.toHtml
+    let output1 = input1.toHtml({roSupportMarkdown, roPreferMarkdown})
     doAssert "<pre" in output1 and "class=\"Keyword\"" notin output1
 
+    # Check Nim highlighting by default in .nim files:
+    let output1nim = input1.toHtml({roSupportMarkdown, roPreferMarkdown,
+                                    roNimFile})
+    doAssert "<pre" in output1nim and "class=\"Keyword\"" in output1nim
+
     let input2 = """
 Parse the block with language specifier:
 ```Nim
@@ -549,8 +657,72 @@ let x = 1
     let output2 = input2.toHtml
     doAssert "<pre" in output2 and "class=\"Keyword\"" in output2
 
+  test "interpreted text":
+    check("""`foo.bar`""".toHtml ==
+      """<tt class="docutils literal"><span class="pre">""" &
+      id"foo" & op"." & id"bar" & "</span></tt>")
+    check("""`foo\`\`bar`""".toHtml ==
+      """<tt class="docutils literal"><span class="pre">""" &
+      id"foo" & pu"`" & pu"`" & id"bar" & "</span></tt>")
+    check("""`foo\`bar`""".toHtml ==
+      """<tt class="docutils literal"><span class="pre">""" &
+      id"foo" & pu"`" & id"bar" & "</span></tt>")
+    check("""`\`bar`""".toHtml ==
+      """<tt class="docutils literal"><span class="pre">""" &
+      pu"`" & id"bar" & "</span></tt>")
+    check("""`a\b\x\\ar`""".toHtml ==
+      """<tt class="docutils literal"><span class="pre">""" &
+      id"a" & op"""\""" & id"b" & op"""\""" & id"x" & op"""\\""" & id"ar" &
+      "</span></tt>")
+
+  test "inline literal":
+    check """``foo.bar``""".toHtml == """<tt class="docutils literal"><span class="pre">foo.bar</span></tt>"""
+    check """``foo\bar``""".toHtml == """<tt class="docutils literal"><span class="pre">foo\bar</span></tt>"""
+    check """``f\`o\\o\b`ar``""".toHtml == """<tt class="docutils literal"><span class="pre">f\`o\\o\b`ar</span></tt>"""
+
+  test "default-role":
+    # nim(default) -> literal -> nim -> code(=literal)
+    let input = dedent"""
+      Par1 `value1`.
+
+      .. default-role:: literal
+
+      Par2 `value2`.
+
+      .. default-role:: nim
+
+      Par3 `value3`.
+
+      .. default-role:: code
+
+      Par4 `value4`."""
+    let p1 = """Par1 <tt class="docutils literal"><span class="pre">""" & id"value1" & "</span></tt>."
+    let p2 = """<p>Par2 <tt class="docutils literal"><span class="pre">value2</span></tt>.</p>"""
+    let p3 = """<p>Par3 <tt class="docutils literal"><span class="pre">""" & id"value3" & "</span></tt>.</p>"
+    let p4 = """<p>Par4 <tt class="docutils literal"><span class="pre">value4</span></tt>.</p>"""
+    let expected = p1 & p2 & "\n" & p3 & "\n" & p4
+    check(
+      input.toHtml(NoSandboxOpts) == expected
+    )
+
+  test "role directive":
+    let input = dedent"""
+      .. role:: y(code)
+         :language: yaml
+
+      .. role:: brainhelp(code)
+         :language: brainhelp
+    """
+    var warnings = new seq[string]
+    let output = input.toHtml(
+      NoSandboxOpts,
+      warnings=warnings
+    )
+    check(warnings[].len == 1 and "language 'brainhelp' not supported" in warnings[0])
+
   test "RST comments":
     let input1 = """
+
 Check that comment disappears:
 
 ..
@@ -558,8 +730,8 @@ Check that comment disappears:
     let output1 = input1.toHtml
     doAssert output1 == "Check that comment disappears:"
 
-  test "RST line blocks":
-    let input1 = """
+  test "RST line blocks + headings":
+    let input = """
 =====
 Test1
 =====
@@ -570,28 +742,29 @@ Test1
 | other line
 
 """
-    var option: bool
     var rstGenera: RstGenerator
-    var output1: string
-    rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", {})
-    rstGenera.renderRstToOut(rstParse(input1, "", 1, 1, option, {}), output1)
+    var output: string
+    let (rst, files, _) = rstParse(input, "", 1, 1, {})
+    rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", filenames=files)
+    rstGenera.renderRstToOut(rst, output)
     doAssert rstGenera.meta[metaTitle] == "Test1"
       # check that title was not overwritten to '|'
-    doAssert output1 == "<p><br/><br/>line block<br/>other line<br/></p>"
-    let output1l = rstToLatex(input1, {})
+    doAssert output == "<p><br/><br/>line block<br/>other line<br/></p>"
+    let output1l = rstToLatex(input, {})
     doAssert "line block\n\n" in output1l
     doAssert "other line\n\n" in output1l
     doAssert output1l.count("\\vspace") == 2 + 2  # +2 surrounding paddings
 
+  test "RST line blocks":
     let input2 = dedent"""
       Paragraph1
-      
+
       |
 
       Paragraph2"""
 
     let output2 = input2.toHtml
-    doAssert "Paragraph1<p><br/></p> <p>Paragraph2</p>\n" == output2
+    doAssert "Paragraph1<p><br/></p> <p>Paragraph2</p>" == output2
 
     let input3 = dedent"""
       | xxx
@@ -606,7 +779,7 @@ Test1
     # check that '|   ' with a few spaces is still parsed as new line
     let input4 = dedent"""
       | xxx
-      |      
+      |
       |     zzz"""
 
     let output4 = input4.toHtml
@@ -756,9 +929,9 @@ Test1
     let output8 = input8.toHtml(warnings = warnings8)
     check(warnings8[].len == 1)
     check("input(6, 1) Warning: RST style: \n" &
-          "  not enough indentation on line 6" in warnings8[0])
+          "not enough indentation on line 6" in warnings8[0])
     doAssert output8 == "Paragraph.<ol class=\"upperalpha simple\">" &
-        "<li>stringA</li>\n<li>stringB</li>\n</ol>\n<p>C. string1 string2 </p>\n"
+        "<li>stringA</li>\n<li>stringB</li>\n</ol>\n<p>C. string1 string2 </p>"
 
   test "Markdown enumerated lists":
     let input1 = dedent """
@@ -812,7 +985,7 @@ Test1
 
       Ref. [#note]_
       """
-    let output1 = input1.toHtml
+    let output1 = input1.toHtml(preferRst)
     doAssert output1.count(">[1]</a>") == 1
     doAssert output1.count(">[2]</a>") == 2
     doAssert "href=\"#footnote-note\"" in output1
@@ -830,8 +1003,8 @@ Test1
 
       Not references[#note]_[1 #]_ [wrong citation]_ and [not&allowed]_.
       """
-    let output2 = input2.toHtml
-    doAssert output2 == "Not references[#note]_[1 #]_ [wrong citation]_ and [not&amp;allowed]_. "
+    let output2 = input2.toHtml(preferRst)
+    doAssert output2 == "Not references[#note]_[1 #]_ [wrong citation]_ and [not&amp;allowed]_."
 
     # check that auto-symbol footnotes work:
     let input3 = dedent """
@@ -846,7 +1019,7 @@ Test1
 
       And [*]_.
       """
-    let output3 = input3.toHtml
+    let output3 = input3.toHtml(preferRst)
     # both references and footnotes. Footnotes have link to themselves.
     doAssert output3.count("href=\"#footnotesym-1\">[*]</a>") == 2
     doAssert output3.count("href=\"#footnotesym-2\">[**]</a>") == 2
@@ -876,7 +1049,7 @@ Test1
 
       Ref. [#note]_ and [#]_ and [#]_.
       """
-    let output4 = input4.toHtml
+    let output4 = input4.toHtml(preferRst)
     doAssert ">[-1]" notin output1
     let order = @[
         "footnote-3", "[3]", "Manual1.",
@@ -901,8 +1074,8 @@ Test1
       Ref. [#note]_
       """
     var error5 = new string
-    let output5 = input5.toHtml(error=error5)
-    check(error5[] == "input(6, 1) Error: mismatch in number of footnotes " &
+    let output5 = input5.toHtml(preferRst, error=error5)
+    check(error5[] == "input(1, 1) Error: mismatch in number of footnotes " &
             "and their refs: 1 (lines 2) != 0 (lines ) for auto-numbered " &
             "footnotes")
 
@@ -915,8 +1088,8 @@ Test1
       Ref. [*]_
       """
     var error6 = new string
-    let output6 = input6.toHtml(error=error6)
-    check(error6[] == "input(6, 1) Error: mismatch in number of footnotes " &
+    let output6 = input6.toHtml(preferRst, error=error6)
+    check(error6[] == "input(1, 1) Error: mismatch in number of footnotes " &
             "and their refs: 1 (lines 3) != 2 (lines 2, 6) for auto-symbol " &
             "footnotes")
 
@@ -925,7 +1098,7 @@ Test1
 
       Ref. [some:citation-2020]_.
       """
-    let output7 = input7.toHtml
+    let output7 = input7.toHtml(preferRst)
     doAssert output7.count("href=\"#citation-somecoloncitationminus2020\"") == 2
     doAssert output7.count("[Some:CITATION-2020]") == 1
     doAssert output7.count("[some:citation-2020]") == 1
@@ -938,9 +1111,8 @@ Test1
       Ref. [som]_.
       """
     var warnings8 = new seq[string]
-    let output8 = input8.toHtml(warnings=warnings8)
-    check(warnings8[] == @["input(4, 1) Warning: unknown substitution " &
-            "\'citation-som\'"])
+    let output8 = input8.toHtml(preferRst, warnings=warnings8)
+    check(warnings8[] == @["input(3, 7) Warning: broken link 'citation-som'"])
 
     # check that footnote group does not break parsing of other directives:
     let input9 = dedent """
@@ -956,9 +1128,10 @@ Test1
 
       Paragraph2 ref `internal anchor`_.
       """
-    let output9 = input9.toHtml
-    #doAssert "id=\"internal-anchor\"" in output9
-    #doAssert "internal anchor" notin output9
+    let output9 = input9.toHtml(preferRst)
+    # _`internal anchor` got erased:
+    check "href=\"#internal-anchor\"" notin output9
+    check "href=\"#citation-another\"" in output9
     doAssert output9.count("<hr class=\"footnote\">" &
                            "<div class=\"footnote-group\">") == 1
     doAssert output9.count("<div class=\"footnote-label\">") == 3
@@ -974,7 +1147,7 @@ Test1
 
             .. [Third] Citation.
       """
-    let output10 = input10.toHtml
+    let output10 = input10.toHtml(preferRst)
     doAssert output10.count("<hr class=\"footnote\">" &
                             "<div class=\"footnote-group\">") == 3
     doAssert output10.count("<div class=\"footnote-label\">") == 3
@@ -983,7 +1156,7 @@ Test1
     doAssert "<a href=\"#citation-third\">[Third]</a>" in output10
 
     let input11 = ".. [note]\n"  # should not crash
-    let output11 = input11.toHtml
+    let output11 = input11.toHtml(preferRst)
     doAssert "<a href=\"#citation-note\">[note]</a>" in output11
 
     # check that references to auto-numbered footnotes work
@@ -994,7 +1167,7 @@ Test1
       .. [#] Body3
       .. [2] Body2.
       """
-    let output12 = input12.toHtml
+    let output12 = input12.toHtml(preferRst)
     let orderAuto = @[
         "#footnoteauto-1", "[1]",
         "#footnoteauto-2", "[3]",
@@ -1019,6 +1192,62 @@ Test1
     let output0 = input0.toHtml
     doAssert "<p>Paragraph1</p>" in output0
 
+  test "Nim code-block :number-lines:":
+    let input = dedent """
+      .. code-block:: nim
+         :number-lines: 55
+
+         x
+         y
+      """
+    check "<pre class=\"line-nums\">55\n56\n</pre>" in input.toHtml
+
+  test "Nim code-block indentation":
+    let input = dedent """
+      .. code-block:: nim
+        :number-lines: 55
+
+       x
+      """
+    let output = input.toHtml
+    check "<pre class=\"line-nums\">55\n</pre>" in output
+    check "<span class=\"Identifier\">x</span>" in output
+
+  test "Nim code-block indentation":
+    let input = dedent """
+      .. code-block:: nim
+        :number-lines: 55
+         let a = 1
+      """
+    var error = new string
+    let output = input.toHtml(error=error)
+    check(error[] == "input(2, 3) Error: invalid field: " &
+                     "extra arguments were given to number-lines: ' let a = 1'")
+    check "" == output
+
+  test "code-block warning":
+    let input = dedent """
+      .. code:: Nim
+         :unsupportedField: anything
+
+      .. code:: unsupportedLang
+
+         anything
+
+      ```anotherLang
+      someCode
+      ```
+      """
+    let warnings = new seq[string]
+    let output = input.toHtml(warnings=warnings)
+    check(warnings[] == @[
+        "input(2, 4) Warning: field 'unsupportedField' not supported",
+        "input(4, 11) Warning: language 'unsupportedLang' not supported",
+        "input(8, 4) Warning: language 'anotherLang' not supported"
+        ])
+    check(output == "<pre class = \"listing\">anything</pre>" &
+                    "<p><pre class = \"listing\">someCode</pre> </p>")
+
   test "RST admonitions":
     # check that all admonitions are implemented
     let input0 = dedent """
@@ -1033,7 +1262,9 @@ Test1
       .. tip:: endOf tip
       .. warning:: endOf warning
     """
-    let output0 = input0.toHtml
+    let output0 = input0.toHtml(
+      NoSandboxOpts
+    )
     for a in ["admonition", "attention", "caution", "danger", "error", "hint",
         "important", "note", "tip", "warning" ]:
       doAssert "endOf " & a & "</div>" in output0
@@ -1044,7 +1275,9 @@ Test1
 
       Test paragraph.
     """
-    let output1 = input1.toHtml
+    let output1 = input1.toHtml(
+      NoSandboxOpts
+    )
     doAssert "endOfError</div>" in output1
     doAssert "<p>Test paragraph. </p>" in output1
     doAssert "class=\"admonition admonition-error\"" in output1
@@ -1056,7 +1289,9 @@ Test1
 
       Test paragraph.
     """
-    let output2 = input2.toHtml
+    let output2 = input2.toHtml(
+      NoSandboxOpts
+    )
     doAssert "endOfError Test2p.</div>" in output2
     doAssert "<p>Test paragraph. </p>" in output2
     doAssert "class=\"admonition admonition-error\"" in output2
@@ -1064,7 +1299,9 @@ Test1
     let input3 = dedent """
       .. note:: endOfNote
     """
-    let output3 = input3.toHtml
+    let output3 = input3.toHtml(
+      NoSandboxOpts
+    )
     doAssert "endOfNote</div>" in output3
     doAssert "class=\"admonition admonition-info\"" in output3
 
@@ -1149,14 +1386,16 @@ Test1
 
       That was a transition.
     """
-    let output1 = input1.toHtml
+    let output1 = input1.toHtml(
+      preferRst
+    )
     doAssert "<p id=\"target000\""     in output1
     doAssert "<ul id=\"target001\""    in output1
     doAssert "<ol id=\"target002\""    in output1
     doAssert "<dl id=\"target003\""    in output1
     doAssert "<p id=\"target004\""     in output1
     doAssert "<table id=\"target005\"" in output1  # field list
-    doAssert "<table id=\"target006\"" in output1  # option list
+    doAssert "<div id=\"target006\""   in output1  # option list
     doAssert "<pre id=\"target007\""   in output1
     doAssert "<blockquote id=\"target009\"" in output1
     doAssert "<table id=\"target010\"" in output1  # just table
@@ -1177,12 +1416,12 @@ Test1
     """
     let output1 = input1.toHtml
     # "target101" should be erased and changed to "section-xyz":
-    doAssert "href=\"#target101\"" notin output1
-    doAssert "id=\"target101\""    notin output1
-    doAssert "href=\"#target102\"" notin output1
-    doAssert "id=\"target102\""    notin output1
-    doAssert "id=\"section-xyz\""     in output1
-    doAssert "href=\"#section-xyz\""  in output1
+    check "href=\"#target101\"" notin output1
+    check "id=\"target101\""    notin output1
+    check "href=\"#target102\"" notin output1
+    check "id=\"target102\""    notin output1
+    check "id=\"section-xyz\""     in output1
+    check "href=\"#section-xyz\""  in output1
 
     let input2 = dedent """
       .. _target300:
@@ -1204,7 +1443,7 @@ Test1
       Ref. target103_.
 
     """
-    let output2 = input2.toHtml
+    let output2 = input2.toHtml(preferRst)
     # "target101" should be erased and changed to "section-xyz":
     doAssert "href=\"#target300\"" notin output2
     doAssert "id=\"target300\""    notin output2
@@ -1252,13 +1491,134 @@ Test1
     let output1 = input1.toHtml
     doAssert "id=\"secdot1\"" in output1
     doAssert "id=\"Z2minusothercolonsecplusc-2\"" in output1
-    doAssert "id=\"linkdot1-2021\"" in output1
+    check "id=\"linkdot1-2021\"" in output1
     let ref1 = "<a class=\"reference internal\" href=\"#secdot1\">sec.1</a>"
     let ref2 = "<a class=\"reference internal\" href=\"#Z2minusothercolonsecplusc-2\">2-other:sec+c_2</a>"
     let ref3 = "<a class=\"reference internal\" href=\"#linkdot1-2021\">link.1_2021</a>"
     let refline = "Ref. " & ref1 & "! and " & ref2 & ";and " & ref3 & "."
     doAssert refline in output1
 
+  test "Option lists 1":
+    # check that "* b" is not consumed by previous bullet item because of
+    # incorrect indentation handling in option lists
+    let input = dedent """
+      * a
+        -m   desc
+        -n   very long
+             desc
+      * b"""
+    let output = input.toHtml
+    check(output.count("<ul") == 1)
+    check(output.count("<li>") == 2)
+    check(output.count("<div class=\"option-list\"") == 1)
+    check(optionListLabel("-m") &
+          """<div class="option-list-description">desc</div></div>""" in
+          output)
+    check(optionListLabel("-n") &
+          """<div class="option-list-description">very long desc</div></div>""" in
+          output)
+
+  test "Option lists 2":
+    # check that 2nd option list is not united with the 1st
+    let input = dedent """
+      * a
+        -m   desc
+        -n   very long
+             desc
+      -d  option"""
+    let output = input.toHtml
+    check(output.count("<ul") == 1)
+    check output.count("<div class=\"option-list\"") == 2
+    check(optionListLabel("-m") &
+          """<div class="option-list-description">desc</div></div>""" in
+          output)
+    check(optionListLabel("-n") &
+          """<div class="option-list-description">very long desc</div></div>""" in
+          output)
+    check(optionListLabel("-d") &
+          """<div class="option-list-description">option</div></div>""" in
+          output)
+    check "<p>option</p>" notin output
+
+  test "Option list 3 (double /)":
+    let input = dedent """
+      * a
+        //compile  compile1
+        //doc      doc1
+                   cont
+      -d  option"""
+    let output = input.toHtml
+    check(output.count("<ul") == 1)
+    check output.count("<div class=\"option-list\"") == 2
+    check(optionListLabel("compile") &
+          """<div class="option-list-description">compile1</div></div>""" in
+          output)
+    check(optionListLabel("doc") &
+          """<div class="option-list-description">doc1 cont</div></div>""" in
+          output)
+    check(optionListLabel("-d") &
+          """<div class="option-list-description">option</div></div>""" in
+          output)
+    check "<p>option</p>" notin output
+
+  test "Roles: subscript prefix/postfix":
+    let expected = "See <sub>some text</sub>."
+    check "See :subscript:`some text`.".toHtml == expected
+    check "See `some text`:subscript:.".toHtml == expected
+
+  test "Roles: correct parsing from beginning of line":
+    let expected = "<sup>3</sup>He is an isotope of helium."
+    check """:superscript:`3`\ He is an isotope of helium.""".toHtml == expected
+    check """:sup:`3`\ He is an isotope of helium.""".toHtml == expected
+    check """`3`:sup:\ He is an isotope of helium.""".toHtml == expected
+    check """`3`:superscript:\ He is an isotope of helium.""".toHtml == expected
+
+  test "Roles: warnings":
+    let input = dedent"""
+      See function :py:func:`spam`.
+
+      See also `egg`:py:class:.
+      """
+    var warnings = new seq[string]
+    let output = input.toHtml(warnings=warnings)
+    doAssert warnings[].len == 2
+    check "(1, 14) Warning: " in warnings[0]
+    check "language 'py:func' not supported" in warnings[0]
+    check "(3, 15) Warning: " in warnings[1]
+    check "language 'py:class' not supported" in warnings[1]
+    check("""<p>See function <span class="py:func">spam</span>.</p>""" & "\n" &
+          """<p>See also <span class="py:class">egg</span>. </p>""" ==
+          output)
+
+  test "(not) Roles: check escaping 1":
+    let expected = """See :subscript:<tt class="docutils literal">""" &
+                   """<span class="pre">""" & id"some" & " " & id"text" &
+                   "</span></tt>."
+    check """See \:subscript:`some text`.""".toHtml == expected
+    check """See :subscript\:`some text`.""".toHtml == expected
+
+  test "(not) Roles: check escaping 2":
+    check("""See :subscript:\`some text\`.""".toHtml ==
+          "See :subscript:`some text`.")
+
+  test "Field list":
+    check(":field: text".toHtml ==
+            """<table class="docinfo" frame="void" rules="none">""" &
+            """<col class="docinfo-name" /><col class="docinfo-content" />""" &
+            """<tbody valign="top"><tr><th class="docinfo-name">field:</th>""" &
+            """<td>text</td></tr>""" & "\n</tbody></table>")
+
+  test "Field list: body after newline":
+    let output = dedent"""
+      :field:
+        text1""".toHtml
+    check "<table class=\"docinfo\"" in output
+    check ">field:</th>" in output
+    check "<td>text1</td>" in output
+
+  test "Field list (incorrect)":
+    check ":field:text".toHtml == ":field:text"
+
 suite "RST/Code highlight":
   test "Basic Python code highlight":
     let pythonCode = """
@@ -1274,3 +1634,59 @@ suite "RST/Code highlight":
 
     check strip(rstToHtml(pythonCode, {}, newStringTable(modeCaseSensitive))) ==
       strip(expected)
+
+
+suite "invalid targets":
+  test "invalid image target":
+    let input1 = dedent """.. image:: /images/myimage.jpg
+      :target: https://bar.com
+      :alt: Alt text for the image"""
+    let output1 = input1.toHtml
+    check output1 == """<a class="reference external" href="https://bar.com"><img src="/images/myimage.jpg" alt="Alt text for the image"/></a>"""
+
+    let input2 = dedent """.. image:: /images/myimage.jpg
+      :target: javascript://bar.com
+      :alt: Alt text for the image"""
+    let output2 = input2.toHtml
+    check output2 == """<img src="/images/myimage.jpg" alt="Alt text for the image"/>"""
+
+    let input3 = dedent """.. image:: /images/myimage.jpg
+      :target: bar.com
+      :alt: Alt text for the image"""
+    let output3 = input3.toHtml
+    check output3 == """<a class="reference external" href="bar.com"><img src="/images/myimage.jpg" alt="Alt text for the image"/></a>"""
+
+  test "invalid links":
+    check("(([Nim](https://nim-lang.org/)))".toHtml ==
+        """((<a class="reference external" href="https://nim-lang.org/">Nim</a>))""")
+    # unknown protocol is treated just like plain text, not a link
+    var warnings = new seq[string]
+    check("(([Nim](javascript://nim-lang.org/)))".toHtml(warnings=warnings) ==
+        """(([Nim](javascript://nim-lang.org/)))""")
+    check(warnings[] == @["input(1, 9) Warning: broken link 'javascript'"])
+    warnings[].setLen 0
+    check("`Nim <javascript://nim-lang.org/>`_".toHtml(warnings=warnings) ==
+      """Nim &lt;javascript://nim-lang.org/&gt;""")
+    check(warnings[] == @["input(1, 33) Warning: broken link 'javascript'"])
+
+suite "local file inclusion":
+  test "cannot include files in sandboxed mode":
+    var error = new string
+    discard ".. include:: ./readme.md".toHtml(error=error)
+    check(error[] == "input(1, 11) Error: disabled directive: 'include'")
+
+  test "code-block file directive is disabled":
+    var error = new string
+    discard ".. code-block:: nim\n    :file: ./readme.md".toHtml(error=error)
+    check(error[] == "input(2, 20) Error: disabled directive: 'file'")
+
+  test "code-block file directive is disabled - Markdown":
+    var error = new string
+    discard "```nim file = ./readme.md\n```".toHtml(error=error)
+    check(error[] == "input(1, 23) Error: disabled directive: 'file'")
+
+proc documentToHtml*(doc: string, isMarkdown: bool = false): string {.gcsafe.} =
+  var options = {roSupportMarkdown}
+  if isMarkdown:
+    options.incl roPreferMarkdown
+  result = rstToHtml(doc, options, defaultConfig())
diff --git a/tests/stdlib/tsequtils.nim b/tests/stdlib/tsequtils.nim
index 385e6e651..1094ae233 100644
--- a/tests/stdlib/tsequtils.nim
+++ b/tests/stdlib/tsequtils.nim
@@ -1,6 +1,18 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c js"
+"""
+
+# xxx move all tests under `main`
+
 import std/sequtils
 import strutils
 from algorithm import sorted
+import std/assertions
+
+{.experimental: "strictEffects".}
+{.push warningAsError[Effect]: on.}
+{.experimental: "strictFuncs".}
 
 # helper for testing double substitution side effects which are handled
 # by `evalOnceAs`
@@ -190,17 +202,6 @@ block: # keepIf test
   keepIf(floats, proc(x: float): bool = x > 10)
   doAssert floats == @[13.0, 12.5, 10.1]
 
-block: # delete tests
-  let outcome = @[1, 1, 1, 1, 1, 1, 1, 1]
-  var dest = @[1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
-  dest.delete(3, 8)
-  doAssert outcome == dest, """\
-  Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1]
-  is [1,1,1,1,1,1,1,1]"""
-  var x = @[1, 2, 3]
-  x.delete(100, 100)
-  doAssert x == @[1, 2, 3]
-
 block: # insert tests
   var dest = @[1, 1, 1, 1, 1, 1, 1, 1]
   let
@@ -298,43 +299,45 @@ block: # toSeq test
     doAssert myIter.toSeq == @[1, 2]
     doAssert toSeq(myIter) == @[1, 2]
 
-  block:
-    iterator myIter(): int {.closure.} =
-      yield 1
-      yield 2
-
-    doAssert myIter.toSeq == @[1, 2]
-    doAssert toSeq(myIter) == @[1, 2]
+  when not defined(js):
+    # pending #4695
+    block:
+        iterator myIter(): int {.closure.} =
+          yield 1
+          yield 2
 
-  block:
-    proc myIter(): auto =
-      iterator ret(): int {.closure.} =
-        yield 1
-        yield 2
-      result = ret
+        doAssert myIter.toSeq == @[1, 2]
+        doAssert toSeq(myIter) == @[1, 2]
 
-    doAssert myIter().toSeq == @[1, 2]
-    doAssert toSeq(myIter()) == @[1, 2]
+    block:
+      proc myIter(): auto =
+        iterator ret(): int {.closure.} =
+          yield 1
+          yield 2
+        result = ret
 
-  block:
-    proc myIter(n: int): auto =
-      var counter = 0
-      iterator ret(): int {.closure.} =
-        while counter < n:
-          yield counter
-          counter.inc
-      result = ret
+      doAssert myIter().toSeq == @[1, 2]
+      doAssert toSeq(myIter()) == @[1, 2]
 
     block:
-      let myIter3 = myIter(3)
-      doAssert myIter3.toSeq == @[0, 1, 2]
-    block:
-      let myIter3 = myIter(3)
-      doAssert toSeq(myIter3) == @[0, 1, 2]
-    block:
-      # makes sure this does not hang forever
-      doAssert myIter(3).toSeq == @[0, 1, 2]
-      doAssert toSeq(myIter(3)) == @[0, 1, 2]
+      proc myIter(n: int): auto =
+        var counter = 0
+        iterator ret(): int {.closure.} =
+          while counter < n:
+            yield counter
+            counter.inc
+        result = ret
+
+      block:
+        let myIter3 = myIter(3)
+        doAssert myIter3.toSeq == @[0, 1, 2]
+      block:
+        let myIter3 = myIter(3)
+        doAssert toSeq(myIter3) == @[0, 1, 2]
+      block:
+        # makes sure this does not hang forever
+        doAssert myIter(3).toSeq == @[0, 1, 2]
+        doAssert toSeq(myIter(3)) == @[0, 1, 2]
 
 block:
   # tests https://github.com/nim-lang/Nim/issues/7187
@@ -386,6 +389,11 @@ block: # newSeqWith tests
   seq2D[0][1] = true
   doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
 
+block: # bug #21538
+  var x: seq[int] = @[2, 4]
+  var y = newSeqWith(x.pop(), true)
+  doAssert y == @[true, true, true, true]
+
 block: # mapLiterals tests
   let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
   doAssert x is array[4, int]
@@ -452,4 +460,88 @@ block:
       for i in 0..<len:
         yield i
 
-  doAssert: iter(3).mapIt(2*it).foldl(a + b) == 6
+  # xxx: obscure CT error: basic_types.nim(16, 16) Error: internal error: symbol has no generated name: true
+  when not defined(js):
+    doAssert: iter(3).mapIt(2*it).foldl(a + b) == 6
+
+block: # strictFuncs tests with ref object
+  type Foo = ref object
+
+  let foo1 = Foo()
+  let foo2 = Foo()
+  let foos = @[foo1, foo2]
+
+  # Procedures that are `func`
+  discard concat(foos, foos)
+  discard count(foos, foo1)
+  discard cycle(foos, 3)
+  discard deduplicate(foos)
+  discard minIndex(foos)
+  discard maxIndex(foos)
+  discard distribute(foos, 2)
+  var mutableFoos = foos
+  mutableFoos.delete(0..1)
+  mutableFoos.insert(foos)
+
+  # Some procedures that are `proc`, but were reverted from `func`
+  discard repeat(foo1, 3)
+  discard zip(foos, foos)
+  let fooTuples = @[(foo1, 1), (foo2, 2)]
+  discard unzip(fooTuples)
+
+template main =
+  # xxx move all tests here
+  block: # delete tests
+    let outcome = @[1, 1, 1, 1, 1, 1, 1, 1]
+    var dest = @[1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
+    dest.delete(3, 8)
+    doAssert outcome == dest, """\
+    Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1]
+    is [1,1,1,1,1,1,1,1]"""
+    var x = @[1, 2, 3]
+    x.delete(100, 100)
+    doAssert x == @[1, 2, 3]
+
+  block: # delete tests
+    var a = @[10, 11, 12, 13, 14]
+    doAssertRaises(IndexDefect): a.delete(4..5)
+    doAssertRaises(IndexDefect): a.delete(4..<6)
+    doAssertRaises(IndexDefect): a.delete(-1..1)
+    doAssertRaises(IndexDefect): a.delete(-1 .. -1)
+    doAssertRaises(IndexDefect): a.delete(5..5)
+    doAssertRaises(IndexDefect): a.delete(5..3)
+    doAssertRaises(IndexDefect): a.delete(5..<5) # edge case
+    doAssert a == @[10, 11, 12, 13, 14]
+    a.delete(4..4)
+    doAssert a == @[10, 11, 12, 13]
+    a.delete(1..2)
+    doAssert a == @[10, 13]
+    a.delete(1..<1) # empty slice
+    doAssert a == @[10, 13]
+    a.delete(0..<0)
+    doAssert a == @[10, 13]
+    a.delete(0..0)
+    doAssert a == @[13]
+    a.delete(0..0)
+    doAssert a == @[]
+    doAssertRaises(IndexDefect): a.delete(0..0)
+    doAssertRaises(IndexDefect): a.delete(0..<0) # edge case
+    block:
+      type A = object
+        a0: int
+      var a = @[A(a0: 10), A(a0: 11), A(a0: 12)]
+      a.delete(0..1)
+      doAssert a == @[A(a0: 12)]
+    block:
+      type A = ref object
+      let a0 = A()
+      let a1 = A()
+      let a2 = A()
+      var a = @[a0, a1, a2]
+      a.delete(0..1)
+      doAssert a == @[a2]
+
+static: main()
+main()
+
+{.pop.}
diff --git a/tests/stdlib/tsetutils.nim b/tests/stdlib/tsetutils.nim
index f2fb81e6a..c8498f23e 100644
--- a/tests/stdlib/tsetutils.nim
+++ b/tests/stdlib/tsetutils.nim
@@ -1,8 +1,10 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
 import std/setutils
+import std/assertions
 
 type 
   Colors = enum
diff --git a/tests/stdlib/tsha1.nim b/tests/stdlib/tsha1.nim
deleted file mode 100644
index 7e67ccaf6..000000000
--- a/tests/stdlib/tsha1.nim
+++ /dev/null
@@ -1,13 +0,0 @@
-import std/sha1
-
-let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]")
-doAssert hash1 == hash1
-doAssert parseSecureHash($hash1) == hash1
-
-template checkVector(s, exp: string) =
-  doAssert secureHash(s) == parseSecureHash(exp)
-
-checkVector("", "da39a3ee5e6b4b0d3255bfef95601890afd80709")
-checkVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d")
-checkVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-            "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
diff --git a/tests/stdlib/tsharedlist.nim b/tests/stdlib/tsharedlist.nim
index a795be0f3..b91302d19 100644
--- a/tests/stdlib/tsharedlist.nim
+++ b/tests/stdlib/tsharedlist.nim
@@ -1,17 +1,49 @@
-import sharedlist
+discard """
+  matrix: "--mm:orc; --mm:refc"
+"""
 
-var
-  list: SharedList[int]
-  count: int
+import std/sharedlist
+import std/assertions
 
-init(list)
+block:
+  var
+    list: SharedList[int]
+    count: int
 
-for i in 1 .. 250:
-  list.add i
+  init(list)
 
-for i in list:
-  inc count
+  for i in 1 .. 250:
+    list.add i
 
-doAssert count == 250
+  for i in list:
+    inc count
 
-deinitSharedList(list)
+  doAssert count == 250
+
+  deinitSharedList(list)
+
+
+block: # bug #17696
+  var keysList = SharedList[string]()
+  init(keysList)
+
+  keysList.add("a")
+  keysList.add("b")
+  keysList.add("c")
+  keysList.add("d")
+  keysList.add("e")
+  keysList.add("f")
+
+
+  # Remove element "b" and "d" from the list. 
+  keysList.iterAndMutate(proc (key: string): bool =
+    if key == "b" or key == "d": # remove only "b" and "d"
+      return true
+    return false
+  )
+
+  var results: seq[string]
+  for key in keysList.items:
+    results.add key
+
+  doAssert results == @["a", "f", "c", "e"]
diff --git a/tests/stdlib/tsharedtable.nim b/tests/stdlib/tsharedtable.nim
index 0a8f7bcc0..10ad5f658 100644
--- a/tests/stdlib/tsharedtable.nim
+++ b/tests/stdlib/tsharedtable.nim
@@ -1,10 +1,11 @@
 discard """
-cmd: "nim $target --threads:on $options $file"
+matrix: "--mm:refc; --mm:orc"
 output: '''
 '''
 """
 
 import sharedtables
+import std/assertions
 
 block:
   var table: SharedTable[int, int]
diff --git a/tests/stdlib/tsince.nim b/tests/stdlib/tsince.nim
index 14dd09c15..a0a4229cb 100644
--- a/tests/stdlib/tsince.nim
+++ b/tests/stdlib/tsince.nim
@@ -1,4 +1,5 @@
 import std/private/since
+import std/assertions
 
 proc fun1(): int {.since: (1, 3).} = 12
 proc fun1Bad(): int {.since: (99, 3).} = 12
@@ -26,7 +27,6 @@ doAssert ok
 since (99, 3):
   doAssert false
 
-when false:
-  # pending https://github.com/timotheecour/Nim/issues/129
-  # Error: cannot attach a custom pragma to 'fun3'
-  template fun3(): int {.since: (1, 3).} = 12
+template fun3(): int {.since: (1, 3).} = 12
+
+doAssert declared(fun3)
diff --git a/tests/stdlib/tsocketstreams.nim b/tests/stdlib/tsocketstreams.nim
index 0cf952810..a37e7c34c 100644
--- a/tests/stdlib/tsocketstreams.nim
+++ b/tests/stdlib/tsocketstreams.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: '''
 OM
 NIM
diff --git a/tests/stdlib/tsortcall.nim b/tests/stdlib/tsortcall.nim
index 242e3fe4c..32e004921 100644
--- a/tests/stdlib/tsortcall.nim
+++ b/tests/stdlib/tsortcall.nim
@@ -1,5 +1,5 @@
 discard """
-outputsub: ""
+  matrix: "--mm:refc; --mm:orc"
 """
 
 import algorithm
diff --git a/tests/stdlib/tsqlitebindatas.nim b/tests/stdlib/tsqlitebindatas.nim
index 643f1e2e6..e69de29bb 100644
--- a/tests/stdlib/tsqlitebindatas.nim
+++ b/tests/stdlib/tsqlitebindatas.nim
@@ -1,50 +0,0 @@
-discard """
-  action: "run"
-  exitcode: 0
-"""
-import db_sqlite
-import random
-import os
-from stdtest/specialpaths import buildDir
-
-block tsqlitebindatas: ## db_sqlite binary data
-  const dbName = buildDir / "tsqlitebindatas.db"
-
-  let origName = "Bobby"
-  var orig = newSeq[float64](150)
-  randomize()
-  for x in orig.mitems:
-    x = rand(1.0)/10.0
-
-  discard tryRemoveFile(dbName)
-  let db = open(dbName, "", "", "")
-  let createTableStr = sql"""CREATE TABLE test(
-    id INTEGER NOT NULL PRIMARY KEY,
-    name TEXT,
-    data BLOB
-  )
-  """
-  db.exec(createTableStr)
-
-  var dbuf = newSeq[byte](orig.len*sizeof(float64))
-  copyMem(unsafeAddr(dbuf[0]), unsafeAddr(orig[0]), dbuf.len)
-
-  var insertStmt = db.prepare("INSERT INTO test (id, name, data) VALUES (?, ?, ?)")
-  insertStmt.bindParams(1, origName, dbuf)
-  let bres = db.tryExec(insertStmt)
-  doAssert(bres)
-
-  finalize(insertStmt)
-
-  var nameTest = db.getValue(sql"SELECT name FROM test WHERE id = ?", 1)
-  doAssert nameTest == origName
-
-  var dataTest = db.getValue(sql"SELECT data FROM test WHERE id = ?", 1)
-  let seqSize = int(dataTest.len*sizeof(byte)/sizeof(float64))
-  var res: seq[float64] = newSeq[float64](seqSize)
-  copyMem(unsafeAddr(res[0]), addr(dataTest[0]), dataTest.len)
-  doAssert res.len == orig.len
-  doAssert res == orig
-
-  db.close()
-  doAssert tryRemoveFile(dbName)
diff --git a/tests/stdlib/tsqlparser.nim b/tests/stdlib/tsqlparser.nim
index 11ee22e2b..6f123f21d 100644
--- a/tests/stdlib/tsqlparser.nim
+++ b/tests/stdlib/tsqlparser.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: '''true'''
 """
 
diff --git a/tests/stdlib/tssl.nim b/tests/stdlib/tssl.nim
index 7625f3694..1628b9326 100644
--- a/tests/stdlib/tssl.nim
+++ b/tests/stdlib/tssl.nim
@@ -1,10 +1,12 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   joinable: false
-  disabled: "freebsd"
-  disabled: "openbsd"
+  disabled: "freebsd" # see #15713
+  disabled: "openbsd" # see #15713
+  disabled: "netbsd" # see #15713
 """
-# disabled: pending bug #15713
-import net, nativesockets
+
+import std/[net, nativesockets, assertions, typedthreads]
 
 when defined(posix): import os, posix
 else:
@@ -37,8 +39,8 @@ proc notifiedShutdown(port: Port) {.thread.} =
 proc main() =
   when defined(posix):
     var
-      ignoreAction = SigAction(sa_handler: SIG_IGN)
-      oldSigPipeHandler: SigAction
+      ignoreAction = Sigaction(sa_handler: SIG_IGN)
+      oldSigPipeHandler: Sigaction
     if sigemptyset(ignoreAction.sa_mask) == -1:
       raiseOSError(osLastError(), "Couldn't create an empty signal set")
     if sigaction(SIGPIPE, ignoreAction, oldSigPipeHandler) == -1:
diff --git a/tests/stdlib/tstackframes.nim b/tests/stdlib/tstackframes.nim
index 618ff7b92..b0f05d51d 100644
--- a/tests/stdlib/tstackframes.nim
+++ b/tests/stdlib/tstackframes.nim
@@ -1,4 +1,4 @@
-import std/[strformat,os,osproc]
+import std/[strformat,os,osproc,assertions]
 import stdtest/unittest_light
 
 proc main(opt: string, expected: string) =
diff --git a/tests/stdlib/tstaticos.nim b/tests/stdlib/tstaticos.nim
new file mode 100644
index 000000000..41ab995dd
--- /dev/null
+++ b/tests/stdlib/tstaticos.nim
@@ -0,0 +1,8 @@
+import std/[assertions, staticos, os]
+
+block:
+  static:
+    doAssert staticDirExists("MISSINGFILE") == false
+    doAssert staticFileExists("MISSINGDIR") == false
+    doAssert staticDirExists(currentSourcePath().parentDir)
+    doAssert staticFileExists(currentSourcePath())
diff --git a/tests/stdlib/tstats.nim b/tests/stdlib/tstats.nim
index 37240c884..728d93d09 100644
--- a/tests/stdlib/tstats.nim
+++ b/tests/stdlib/tstats.nim
@@ -1,46 +1,61 @@
-include stats
-
-proc clean(x: float): float =
-  result = round(1.0e8*x).float * 1.0e-8
-
-var rs: RunningStat
-rs.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0])
-doAssert(rs.n == 8)
-doAssert(clean(rs.mean) == 2.0)
-doAssert(clean(rs.variance()) == 1.5)
-doAssert(clean(rs.varianceS()) == 1.71428571)
-doAssert(clean(rs.skewness()) == 0.81649658)
-doAssert(clean(rs.skewnessS()) == 1.01835015)
-doAssert(clean(rs.kurtosis()) == -1.0)
-doAssert(clean(rs.kurtosisS()) == -0.7000000000000001)
-
-var rs1, rs2: RunningStat
-rs1.push(@[1.0, 2.0, 1.0, 4.0])
-rs2.push(@[1.0, 4.0, 1.0, 2.0])
-let rs3 = rs1 + rs2
-doAssert(clean(rs3.mom2) == clean(rs.mom2))
-doAssert(clean(rs3.mom3) == clean(rs.mom3))
-doAssert(clean(rs3.mom4) == clean(rs.mom4))
-rs1 += rs2
-doAssert(clean(rs1.mom2) == clean(rs.mom2))
-doAssert(clean(rs1.mom3) == clean(rs.mom3))
-doAssert(clean(rs1.mom4) == clean(rs.mom4))
-rs1.clear()
-rs1.push(@[1.0, 2.2, 1.4, 4.9])
-doAssert(rs1.sum == 9.5)
-doAssert(rs1.mean() == 2.375)
-
-when not defined(cpu32):
-  # XXX For some reason on 32bit CPUs these results differ
-  var rr: RunningRegress
-  rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0])
-  doAssert(rr.slope() == 0.9695585996955861)
-  doAssert(rr.intercept() == -0.03424657534246611)
-  doAssert(rr.correlation() == 0.9905100362239381)
-  var rr1, rr2: RunningRegress
-  rr1.push(@[0.0, 1.0], @[0.0, 1.0])
-  rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0])
-  let rr3 = rr1 + rr2
-  doAssert(rr3.correlation() == rr.correlation())
-  doAssert(clean(rr3.slope()) == clean(rr.slope()))
-  doAssert(clean(rr3.intercept()) == clean(rr.intercept()))
\ No newline at end of file
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/[stats, assertions]
+import std/math
+
+
+func `~=`(x, y: float32): bool =
+  math.almostEqual(x, y)
+
+template main() =
+  var rs: RunningStat
+  rs.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0])
+  doAssert(rs.n == 8)
+  doAssert rs.mean ~= 2.0
+  doAssert rs.variance() ~= 1.5
+  doAssert rs.varianceS() ~= 1.71428571
+  doAssert rs.skewness() ~= 0.81649658
+  doAssert rs.skewnessS() ~= 1.01835015
+  doAssert rs.kurtosis() ~= -1.0
+  doAssert rs.kurtosisS() ~= -0.7000000000000001
+
+  var rs1, rs2: RunningStat
+  rs1.push(@[1.0, 2.0, 1.0, 4.0])
+  rs2.push(@[1.0, 4.0, 1.0, 2.0])
+  let rs3 = rs1 + rs2
+  doAssert rs3.variance ~= rs.variance
+  doAssert rs3.skewness ~= rs.skewness
+  doAssert rs3.kurtosis ~= rs.kurtosis
+  rs1 += rs2
+  doAssert rs1.variance ~= rs.variance
+  doAssert rs1.skewness ~= rs.skewness
+  doAssert rs1.kurtosis ~= rs.kurtosis
+  rs1.clear()
+  rs1.push(@[1.0, 2.2, 1.4, 4.9])
+  doAssert rs1.sum ~= 9.5
+  doAssert rs1.mean() ~= 2.375
+
+  when not defined(cpu32):
+    # XXX For some reason on 32bit CPUs these results differ
+    var rr: RunningRegress
+    rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0])
+    doAssert rr.slope() ~= 0.9695585996955861
+    doAssert rr.intercept() ~= -0.03424657534246611
+    doAssert rr.correlation() ~= 0.9905100362239381
+    var rr1, rr2: RunningRegress
+    rr1.push(@[0.0, 1.0], @[0.0, 1.0])
+    rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0])
+    let rr3 = rr1 + rr2
+    doAssert rr3.correlation() ~= rr.correlation()
+    doAssert rr3.slope() ~= rr.slope()
+    doAssert rr3.intercept() ~= rr.intercept()
+
+  block: # bug #18718
+    var rs: RunningStat
+    rs.push(-1.0)
+    doAssert rs.max == -1.0
+
+static: main()
+main()
diff --git a/tests/stdlib/tstdlib_issues.nim b/tests/stdlib/tstdlib_issues.nim
index 323bf09c6..b7b806db8 100644
--- a/tests/stdlib/tstdlib_issues.nim
+++ b/tests/stdlib/tstdlib_issues.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 output: '''
 02
 1
@@ -17,7 +18,7 @@ Second readLine raised an exception
 '''
 """
 
-import terminal, colors, re, encodings, strutils, os
+import std/[terminal, colors, re, encodings, strutils, os, assertions, syncio]
 
 
 block t9394:
@@ -77,7 +78,7 @@ block t5349:
   const fn = "file9char.txt"
   writeFile(fn, "123456789")
 
-  var f = system.open(fn)
+  var f = syncio.open(fn)
   echo getFileSize(f)
 
   var line = newString(10)
diff --git a/tests/stdlib/tstdlib_various.nim b/tests/stdlib/tstdlib_various.nim
index b153fd2ba..bac5018fa 100644
--- a/tests/stdlib/tstdlib_various.nim
+++ b/tests/stdlib/tstdlib_various.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc"
 output: '''
 abc
 def
@@ -20,27 +21,20 @@ Hi Andreas! How do you feel, Rumpf?
 @[0, 2, 1]
 @[0, 1, 2]
 055this should be the casehugh@["(", "+", " 1", " 2", ")"]
-caught a crash!
-caught a crash!
-caught a crash!
-caught a crash!
-caught a crash!
-caught a crash!
 [5]
 [4, 5]
 [3, 4, 5]
 [2, 3, 4, 5]
 [2, 3, 4, 5, 6]
 [1, 2, 3, 4, 5, 6]
-true
 <h1><a href="http://force7.de/nim">Nim</a></h1>
 '''
 """
 
 import
-  critbits, sets, strutils, tables, random, algorithm, re, ropes,
-  segfaults, lists, parsesql, streams, os, htmlgen, xmltree, strtabs
-
+  std/[critbits, sets, strutils, tables, random, algorithm, re, ropes,
+  segfaults, lists, parsesql, streams, os, htmlgen, xmltree, strtabs]
+import std/[syncio, assertions]
 
 block tcritbits:
   var r: CritBitTree[void]
@@ -161,18 +155,21 @@ block tropes:
 
 
 block tsegfaults:
-  proc main =
-    try:
-      var x: ptr int
-      echo x[]
+  when not defined(arm64):
+    var crashes = 0
+    proc main =
       try:
-        raise newException(ValueError, "not a crash")
-      except ValueError:
-        discard
-    except NilAccessDefect:
-      echo "caught a crash!"
-  for i in 0..5:
-    main()
+        var x: ptr int
+        echo x[]
+        try:
+          raise newException(ValueError, "not a crash")
+        except ValueError:
+          discard
+      except NilAccessDefect:
+        inc crashes
+    for i in 0..5:
+      main()
+    assert crashes == 6
 
 
 
@@ -209,11 +206,7 @@ block tsplit2:
     s.add("#")
     s.add(w)
 
-  try:
-    discard "hello".split("")
-    echo "false"
-  except AssertionDefect:
-    echo "true"
+  doAssert "true".split("") == @["true"]
 
 
 
diff --git a/tests/stdlib/tstrbasics.nim b/tests/stdlib/tstrbasics.nim
index b340ad509..a965ff15f 100644
--- a/tests/stdlib/tstrbasics.nim
+++ b/tests/stdlib/tstrbasics.nim
@@ -1,9 +1,9 @@
 discard """
   targets: "c cpp js"
-  matrix: "--gc:refc; --gc:arc"
+  matrix: "--mm:refc; --mm:orc"
 """
 
-import std/[strbasics, sugar]
+import std/[strbasics, sugar, assertions]
 
 template strip2(input: string, args: varargs[untyped]): untyped =
   var a = input
@@ -73,7 +73,7 @@ proc main() =
 
   block: # setSlice
     var a = "Hello, Nim!"
-    doassert a.dup(setSlice(7 .. 9)) == "Nim"
+    doAssert a.dup(setSlice(7 .. 9)) == "Nim"
     doAssert a.dup(setSlice(0 .. 0)) == "H"
     doAssert a.dup(setSlice(0 .. 1)) == "He"
     doAssert a.dup(setSlice(0 .. 10)) == a
diff --git a/tests/stdlib/tstreams.nim b/tests/stdlib/tstreams.nim
index c2ceed624..60c63b450 100644
--- a/tests/stdlib/tstreams.nim
+++ b/tests/stdlib/tstreams.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   input: "Arne"
   output: '''
 Hello! What is your name?
@@ -15,7 +16,7 @@ GROOT
 """
 
 
-import streams
+import std/[syncio, streams, assertions]
 
 
 block tstreams:
@@ -40,7 +41,7 @@ block tstreams2:
 block tstreams3:
   try:
     var fs = openFileStream("shouldneverexist.txt")
-  except IoError:
+  except IOError:
     echo "threw exception"
 
   static:
@@ -49,6 +50,12 @@ block tstreams3:
       echo line
     s.close
 
+
+block:
+  let fs = newFileStream("amissingfile.txt")
+  defer: fs.close()
+  doAssert isNil(fs)
+
 # bug #12410
 
 var a = newStringStream "hehohihahuhyh"
@@ -74,3 +81,27 @@ block:
   doAssert(ss.peekLine(str))
   doAssert(str == "uick brown fox jumped over the lazy dog.")
   doAssert(ss.getPosition == 5) # haven't moved
+  # bug #19707 - Ensure we dont error with writing over literals on arc/orc
+  ss.setPosition(0)
+  ss.write("hello")
+  ss.setPosition(0)
+  doAssert(ss.peekStr(5) == "hello")
+
+# bug #19716
+static: # Ensure streams it doesnt break with nimscript on arc/orc #19716
+  let s = newStringStream("a")
+  doAssert s.data == "a"
+
+static: # issue #24054, readStr
+  var s = newStringStream("foo bar baz")
+  doAssert s.readStr(3) == "foo"
+
+template main =
+  var strm = newStringStream("abcde")
+  var buffer = "12345"
+  doAssert strm.readDataStr(buffer, 0..3) == 4
+  doAssert buffer == "abcd5"
+  strm.close()
+
+static: main()
+main()
diff --git a/tests/stdlib/tstrformat.nim b/tests/stdlib/tstrformat.nim
index 86100e421..ff406f898 100644
--- a/tests/stdlib/tstrformat.nim
+++ b/tests/stdlib/tstrformat.nim
@@ -1,7 +1,12 @@
-# xxx: test js target
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
 
 import genericstrformat
-import std/[strformat, strutils, times]
+import std/[strformat, strutils, times, tables, json]
+
+import std/[assertions, formatfloat]
+import std/objectdollar
 
 proc main() =
   block: # issue #7632
@@ -284,6 +289,20 @@ proc main() =
     doAssert fmt"{123.456=:>13e}" == "123.456= 1.234560e+02"
     doAssert fmt"{123.456=:13e}" == "123.456= 1.234560e+02"
 
+    let x = 3.14
+    doAssert fmt"{(if x!=0: 1.0/x else: 0):.5}" == "0.31847"
+    doAssert fmt"""{(block:
+      var res: string
+      for i in 1..15:
+        res.add (if i mod 15 == 0: "FizzBuzz"
+          elif i mod 5 == 0: "Buzz"
+          elif i mod 3 == 0: "Fizz"
+          else: $i) & " "
+      res)}""" == "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz "
+
+    doAssert fmt"""{ "\{(" & msg & ")\}" }""" == "{(hello)}"
+    doAssert fmt"""{{({ msg })}}""" == "{(hello)}"
+    doAssert fmt"""{ $(\{msg:1,"world":2\}) }""" == """[("hello", 1), ("world", 2)]"""
   block: # tests for debug format string
     var name = "hello"
     let age = 21
@@ -458,15 +477,17 @@ proc main() =
 
     # Note: times.format adheres to the format protocol. Test that this
     # works:
+    when nimvm:
+      discard
+    else:
+      var dt = dateTime(2000, mJan, 01, 00, 00, 00)
+      check &"{dt:yyyy-MM-dd}", "2000-01-01"
 
-    var dt = initDateTime(01, mJan, 2000, 00, 00, 00)
-    check &"{dt:yyyy-MM-dd}", "2000-01-01"
-
-    var tm = fromUnix(0)
-    discard &"{tm}"
+      var tm = fromUnix(0)
+      discard &"{tm}"
 
-    var noww = now()
-    check &"{noww}", $noww
+      var noww = now()
+      check &"{noww}", $noww
 
     # Unicode string tests
     check &"""{"αβγ"}""", "αβγ"
@@ -496,6 +517,74 @@ proc main() =
 
   block: # test low(int64)
     doAssert &"{low(int64):-}" == "-9223372036854775808"
+  block: #expressions plus formatting
+    doAssert fmt"{if true\: 123.456 else\: 0=:>9.3f}" == "if true: 123.456 else: 0=  123.456"
+    doAssert fmt"{(if true: 123.456 else: 0)=}" == "(if true: 123.456 else: 0)=123.456"
+    doAssert fmt"{if true\: 123.456 else\: 0=:9.3f}" == "if true: 123.456 else: 0=  123.456"
+    doAssert fmt"{(if true: 123.456 else: 0)=:9.4f}" == "(if true: 123.456 else: 0)= 123.4560"
+    doAssert fmt"{(if true: 123.456 else: 0)=:>9.0f}" == "(if true: 123.456 else: 0)=     123."
+    doAssert fmt"{if true\: 123.456 else\: 0=:<9.4f}" == "if true: 123.456 else: 0=123.4560 "
+
+    doAssert fmt"""{(case true
+      of false: 0.0
+      of true: 123.456)=:e}""" == """(case true
+      of false: 0.0
+      of true: 123.456)=1.234560e+02"""
+
+    doAssert fmt"""{block\:
+      var res = 0.000123456
+      for _ in 0..5\:
+        res *= 10
+      res=:>13e}""" == """block:
+      var res = 0.000123456
+      for _ in 0..5:
+        res *= 10
+      res= 1.234560e+02"""
+    #side effects
+    var x = 5
+    doAssert fmt"{(x=7;123.456)=:13e}" == "(x=7;123.456)= 1.234560e+02"
+    doAssert x==7
+  block: #curly bracket expressions and tuples
+    proc formatValue(result: var string; value:Table|bool|JsonNode; specifier:string) = result.add $value
+
+    doAssert fmt"""{\{"a"\:1,"b"\:2\}.toTable() = }""" == """{"a":1,"b":2}.toTable() = {"a": 1, "b": 2}"""
+    doAssert fmt"""{(\{3: (1,"hi",0.9),4: (4,"lo",1.1)\}).toTable()}""" == """{3: (1, "hi", 0.9), 4: (4, "lo", 1.1)}"""
+    doAssert fmt"""{ (%* \{"name": "Isaac", "books": ["Robot Dreams"]\}) }""" == """{"name":"Isaac","books":["Robot Dreams"]}"""
+    doAssert """%( \%\* {"name": "Isaac"})*""".fmt('%','*') == """{"name":"Isaac"}"""
+  block: #parens in quotes that fool my syntax highlighter
+    doAssert fmt"{(if true: ')' else: '(')}" == ")"
+    doAssert fmt"{(if true: ']' else: ')')}" == "]"
+    doAssert fmt"""{(if true: "\")\"" else: "\"(")}""" == """")""""
+    doAssert &"""{(if true: "\")" else: "")}""" == "\")"
+    doAssert &"{(if true: \"\\\")\" else: \"\")}" == "\")"
+    doAssert fmt"""{(if true: "')" else: "")}""" == "')"
+    doAssert fmt"""{(if true: "'" & "'" & ')' else: "")}""" == "'')"
+    doAssert &"""{(if true: "'" & "'" & ')' else: "")}""" == "'')"
+    doAssert &"{(if true: \"\'\" & \"'\" & ')' else: \"\")}" == "'')"
+    doAssert fmt"""{(if true: "'" & ')' else: "")}""" == "')"
+
+  block: # issue #20381
+    var ss: seq[string]
+    template myTemplate(s: string) =
+      ss.add s
+      ss.add s
+    proc foo() =
+      myTemplate fmt"hello"
+    foo()
+    doAssert ss == @["hello", "hello"]
+
+  block:
+    proc noraises() {.raises: [].} =
+      const
+        flt = 0.0
+        str = "str"
+
+      doAssert fmt"{flt} {str}" == "0.0 str"
+
+    noraises()
+
+  block:
+    doAssert not compiles(fmt"{formatting errors detected at compile time")
 
-# xxx static: main()
+static: main()
 main()
diff --git a/tests/stdlib/tstrformatlineinfo.nim b/tests/stdlib/tstrformatlineinfo.nim
new file mode 100644
index 000000000..3a7bf0d33
--- /dev/null
+++ b/tests/stdlib/tstrformatlineinfo.nim
@@ -0,0 +1,8 @@
+# issue #21759
+
+{.hint[ConvFromXToItselfNotNeeded]: on.}
+
+import std/strformat
+
+echo fmt"{string ""abc""}" #[tt.Hint
+        ^ conversion from string to itself is pointless]#
diff --git a/tests/stdlib/tstrimpl.nim b/tests/stdlib/tstrimpl.nim
new file mode 100644
index 000000000..a8933e53f
--- /dev/null
+++ b/tests/stdlib/tstrimpl.nim
@@ -0,0 +1,12 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/private/strimpl
+
+import std/assertions
+
+doAssert find(cstring"Hello Nim", cstring"Nim") == 6
+doAssert find(cstring"Hello Nim", cstring"N") == 6
+doAssert find(cstring"Hello Nim", cstring"I") == -1
+doAssert find(cstring"Hello Nim", cstring"O") == -1
diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim
index 3e2ccb251..b9b3c78a3 100644
--- a/tests/stdlib/tstring.nim
+++ b/tests/stdlib/tstring.nim
@@ -1,9 +1,11 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c cpp js"
 """
 
 from std/sequtils import toSeq, map
 from std/sugar import `=>`
+import std/assertions
 
 proc tester[T](x: T) =
   let test = toSeq(0..4).map(i => newSeq[int]())
diff --git a/tests/stdlib/tstrmiscs.nim b/tests/stdlib/tstrmiscs.nim
index 2e9131ff8..b42f2e1fe 100644
--- a/tests/stdlib/tstrmiscs.nim
+++ b/tests/stdlib/tstrmiscs.nim
@@ -1,4 +1,9 @@
-import strmisc
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/strmisc
+import std/assertions
 
 
 doAssert expandTabs("\t", 4) == "    "
diff --git a/tests/stdlib/tstrscans.nim b/tests/stdlib/tstrscans.nim
index d443c5dda..ae7fd98ca 100644
--- a/tests/stdlib/tstrscans.nim
+++ b/tests/stdlib/tstrscans.nim
@@ -1,8 +1,8 @@
 discard """
-  output: ""
+  matrix: "--mm:refc; --mm:orc"
 """
 
-import strscans, strutils
+import std/[strscans, strutils, assertions]
 
 block ParsePasswd:
   proc parsePasswd(content: string): seq[string] =
@@ -15,7 +15,7 @@ block ParsePasswd:
       else:
         break
 
-  const etc_passwd = """root:x:0:0:root:/root:/bin/bash
+  const etcPasswd = """root:x:0:0:root:/root:/bin/bash
 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
 bin:x:2:2:bin:/bin:/bin/sh
 sys:x:3:3:sys:/dev:/bin/sh
@@ -23,7 +23,7 @@ nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
 messagebus:x:103:107::/var/run/dbus:/bin/false
 """
 
-  const parsed_etc_passwd = @[
+  const parsedEtcPasswd = @[
     "root:x:0:0:root:/root:/bin/bash",
     "daemon:x:1:1:daemon:/usr/sbin:/bin/sh",
     "bin:x:2:2:bin:/bin:/bin/sh",
@@ -31,7 +31,7 @@ messagebus:x:103:107::/var/run/dbus:/bin/false
     "nobody:x:65534:65534:nobody:/nonexistent:/bin/sh",
     "messagebus:x:103:107::/var/run/dbus:/bin/false",
     ]
-  doAssert etc_passwd.parsePasswd == parsed_etc_passwd
+  doAssert etcPasswd.parsePasswd == parsedEtcPasswd
 
 block LastNot:
   var idx : int
@@ -139,27 +139,27 @@ block:
         break
 
   var key, val: string
-  var intval: int
-  var floatval: float
-  doAssert scanf("abc:: xyz 89  33.25", "$w$s::$s$w$s$i  $f", key, val, intval, floatVal)
+  var intVal: int
+  var floatVal: float
+  doAssert scanf("abc:: xyz 89  33.25", "$w$s::$s$w$s$i  $f", key, val, intVal, floatVal)
   doAssert key == "abc"
   doAssert val == "xyz"
-  doAssert intval == 89
+  doAssert intVal == 89
   doAssert floatVal == 33.25
 
-  var binval: int
-  var octval: int
-  var hexval: int
-  doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval)
-  doAssert binval == 0b0101
-  doAssert octval == 0o1234
-  doAssert hexval == 0xabcd
+  var binVal: int
+  var octVal: int
+  var hexVal: int
+  doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binVal, octVal, hexVal)
+  doAssert binVal == 0b0101
+  doAssert octVal == 0o1234
+  doAssert hexVal == 0xabcd
 
-  let xx = scanf("$abc", "$$$i", intval)
+  let xx = scanf("$abc", "$$$i", intVal)
   doAssert xx == false
 
 
-  let xx2 = scanf("$1234", "$$$i", intval)
+  let xx2 = scanf("$1234", "$$$i", intVal)
   doAssert xx2
 
   let yy = scanf(";.--Breakpoint00 [output]",
@@ -246,24 +246,32 @@ block:
     result = 0
     while start+result < input.len and input[start+result] in seps: inc result
 
+  type
+    ScanRetType = tuple
+      success: bool
+      lo: int
+      hi: int
+      ch: char
+      word: string
+
   var res = 0
   for line in input.splitLines:
-    let (success, lo, hi, c ,w) = scanTuple(line, "$i-$i $c: $w")
-    if success:
+    let ret: ScanRetType = scanTuple(line, "$i-$i $c: $w")
+    if ret.success:
       inc res
   doAssert res == 4
 
-  let (_, key, val, intval, floatVal) = scanTuple("abc:: xyz 89  33.25", "$w$s::$s$w$s$i  $f")
+  let (_, key, val, intVal, floatVal) = scanTuple("abc:: xyz 89  33.25", "$w$s::$s$w$s$i  $f")
   doAssert key == "abc"
   doAssert val == "xyz"
-  doAssert intval == 89
+  doAssert intVal == 89
   doAssert floatVal == 33.25
 
 
-  let (_, binVal, octVal, hexVal) = scanTuple("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval)
-  doAssert binval == 0b0101
-  doAssert octval == 0o1234
-  doAssert hexval == 0xabcd
+  let (_, binVal, octVal, hexVal) = scanTuple("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binVal, octVal, hexVal)
+  doAssert binVal == 0b0101
+  doAssert octVal == 0o1234
+  doAssert hexVal == 0xabcd
 
   var (xx,_) = scanTuple("$abc", "$$$i")
   doAssert xx == false
@@ -272,9 +280,9 @@ block:
   let (xx2, _) = block: scanTuple("$1234", "$$$i")
   doAssert xx2
 
-  var (yy, intval2, key2) = scanTuple(";.--Breakpoint00 [output]",
+  var (yy, intVal2, key2) = scanTuple(";.--Breakpoint00 [output]",
       "$[someSep]Breakpoint${twoDigits}$[someSep({';','.','-'})] [$+]$.",
       int)
   doAssert yy
   doAssert key2 == "output"
-  doAssert intVal2 == 13
\ No newline at end of file
+  doAssert intVal2 == 13
diff --git a/tests/stdlib/tstrset.nim b/tests/stdlib/tstrset.nim
index 1b253f862..bbb6c2677 100644
--- a/tests/stdlib/tstrset.nim
+++ b/tests/stdlib/tstrset.nim
@@ -1,12 +1,16 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 # test a simple yet highly efficient set of strings
 
 type
   TRadixNodeKind = enum rnLinear, rnFull, rnLeaf
   PRadixNode = ref TRadixNode
-  TRadixNode = object {.inheritable.}
+  TRadixNode {.inheritable.} = object
     kind: TRadixNodeKind
   TRadixNodeLinear = object of TRadixNode
-    len: int8
+    len: uint8
     keys: array[0..31, char]
     vals: array[0..31, PRadixNode]
   TRadixNodeFull = object of TRadixNode
@@ -24,7 +28,7 @@ proc search(r: PRadixNode, s: string): PRadixNode =
     case r.kind
     of rnLinear:
       var x = PRadixNodeLinear(r)
-      for j in 0..ze(x.len)-1:
+      for j in 0..int(x.len)-1:
         if x.keys[j] == s[i]:
           if s[i] == '\0': return r
           r = x.vals[j]
@@ -50,7 +54,7 @@ proc search(r: PRadixNode, s: string): PRadixNode =
 proc contains*(r: PRadixNode, s: string): bool =
   return search(r, s) != nil
 
-proc testOrincl*(r: var PRadixNode, s: string): bool =
+proc testOrIncl*(r: var PRadixNode, s: string): bool =
   nil
 
 proc incl*(r: var PRadixNode, s: string) = discard testOrIncl(r, s)
@@ -63,9 +67,9 @@ proc excl*(r: var PRadixNode, s: string) =
   of rnFull: PRadixNodeFull(x).b['\0'] = nil
   of rnLinear:
     var x = PRadixNodeLinear(x)
-    for i in 0..ze(x.len)-1:
+    for i in 0..int(x.len)-1:
       if x.keys[i] == '\0':
-        swap(x.keys[i], x.keys[ze(x.len)-1])
+        swap(x.keys[i], x.keys[int(x.len)-1])
         dec(x.len)
         break
 
diff --git a/tests/stdlib/tstrtabs.nim b/tests/stdlib/tstrtabs.nim
index f629c183c..d261abe76 100644
--- a/tests/stdlib/tstrtabs.nim
+++ b/tests/stdlib/tstrtabs.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc; --mm:orc"
 sortoutput: true
 output: '''
 key1: value1
@@ -88,7 +89,7 @@ value1 = value2
 '''
 """
 
-import strtabs
+import std/[strtabs, assertions, syncio]
 
 var tab = newStringTable({"key1": "val1", "key2": "val2"},
                          modeStyleInsensitive)
diff --git a/tests/stdlib/tstrtabs.nims b/tests/stdlib/tstrtabs.nims
index c8ed4ac40..3563ad0ad 100644
--- a/tests/stdlib/tstrtabs.nims
+++ b/tests/stdlib/tstrtabs.nims
@@ -1,4 +1,4 @@
-import strtabs
+import std/[strtabs, assertions]
 
 static:
   let t = {"name": "John", "city": "Monaco"}.newStringTable
diff --git a/tests/stdlib/tstrtabs2.nim b/tests/stdlib/tstrtabs2.nim
new file mode 100644
index 000000000..a4030ec77
--- /dev/null
+++ b/tests/stdlib/tstrtabs2.nim
@@ -0,0 +1,32 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+
+import std/strtabs
+import std/assertions
+
+macro m =
+  var t = {"name": "John"}.newStringTable
+  doAssert t["name"] == "John"
+
+block:
+  var t = {"name": "John"}.newStringTable
+  doAssert t["name"] == "John"
+
+m()
+
+proc fun()=
+  let ret = newStringTable(modeCaseSensitive)
+  ret["foo"] = "bar"
+
+  doAssert $ret == "{foo: bar}"
+
+  let b = ret["foo"]
+  doAssert b == "bar"
+
+proc main()=
+  static: fun()
+  fun()
+
+main()
diff --git a/tests/stdlib/tstrutils.nim b/tests/stdlib/tstrutils.nim
index a6248d1e3..35f6bc669 100644
--- a/tests/stdlib/tstrutils.nim
+++ b/tests/stdlib/tstrutils.nim
@@ -1,9 +1,11 @@
 discard """
-  targets: "c cpp js"
+  matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
 """
 
 import std/strutils
-
+from stdtest/testutils import disableVm
+import std/assertions
+import std/private/jsutils
 # xxx each instance of `disableVm` and `when not defined js:` should eventually be fixed
 
 template rejectParse(e) =
@@ -12,10 +14,6 @@ template rejectParse(e) =
     raise newException(AssertionDefect, "This was supposed to fail: $#!" % astToStr(e))
   except ValueError: discard
 
-template disableVm(body) =
-  when nimvm: discard
-  else: body
-
 template main() =
   block: # strip
     doAssert strip("  ha  ") == "ha"
@@ -55,6 +53,15 @@ template main() =
     doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example  "]
     doAssert s.split(' ', maxsplit = 1) == @["", "this is an example  "]
     doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example  "]
+    # Empty string:
+    doAssert "".split() == @[""]
+    doAssert "".split(" ") == @[""]
+    doAssert "".split({' '}) == @[""]
+    # Empty separators:
+    doAssert "".split({}) == @[""]
+    doAssert "".split("") == @[""]
+    doAssert s.split({}) == @[s]
+    doAssert s.split("") == @[s]
 
   block: # splitLines
     let fixture = "a\nb\rc\r\nd"
@@ -65,12 +72,21 @@ template main() =
   block: # rsplit
     doAssert rsplit("foo bar", seps = Whitespace) == @["foo", "bar"]
     doAssert rsplit(" foo bar", seps = Whitespace, maxsplit = 1) == @[" foo", "bar"]
-    doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[
-        " foo bar", ""]
+    doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[" foo bar", ""]
     doAssert rsplit(":foo:bar", sep = ':') == @["", "foo", "bar"]
     doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"]
     doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"]
     doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"]
+    # Empty string:
+    doAssert "".rsplit() == @[""]
+    doAssert "".rsplit(" ") == @[""]
+    doAssert "".rsplit({' '}) == @[""]
+    # Empty separators:
+    let s = " this is an example  "
+    doAssert "".rsplit({}) == @[""]
+    doAssert "".rsplit("") == @[""]
+    doAssert s.rsplit({}) == @[s]
+    doAssert s.rsplit("") == @[s]
 
   block: # splitWhitespace
     let s = " this is an example  "
@@ -202,7 +218,30 @@ template main() =
     s.removePrefix("")
     doAssert s == "\r\n\r\nhello"
 
-  block: # delete
+  block: # delete(slice)
+    var s = "0123456789ABCDEFGH"
+    delete(s, 4 .. 5)
+    doAssert s == "01236789ABCDEFGH"
+    delete(s, s.len-1 .. s.len-1)
+    doAssert s == "01236789ABCDEFG"
+    delete(s, 0..0)
+    doAssert s == "1236789ABCDEFG"
+    s = ""
+    doAssertRaises(IndexDefect): delete(s, 0..0)
+    doAssert s == ""
+    s = "abc"
+    doAssertRaises(IndexDefect): delete(s, -1 .. -2)
+    doAssertRaises(IndexDefect): delete(s, 2..3)
+    doAssertRaises(IndexDefect): delete(s, 3..2)
+    delete(s, 2..2)
+    doAssert s == "ab"
+    delete(s, 1..0)
+    doAssert s == "ab"
+    delete(s, 0..0)
+    doAssert s == "b"
+
+  block: # delete(first, last)
+    {.push warning[deprecated]:off.}
     var s = "0123456789ABCDEFGH"
     delete(s, 4, 5)
     doAssert s == "01236789ABCDEFGH"
@@ -210,20 +249,88 @@ template main() =
     doAssert s == "01236789ABCDEFG"
     delete(s, 0, 0)
     doAssert s == "1236789ABCDEFG"
+    {.pop.}
 
   block: # find
-    doAssert "0123456789ABCDEFGH".find('A') == 10
-    doAssert "0123456789ABCDEFGH".find('A', 5) == 10
-    doAssert "0123456789ABCDEFGH".find('A', 5, 10) == 10
-    doAssert "0123456789ABCDEFGH".find('A', 5, 9) == -1
-    doAssert "0123456789ABCDEFGH".find("A") == 10
-    doAssert "0123456789ABCDEFGH".find("A", 5) == 10
-    doAssert "0123456789ABCDEFGH".find("A", 5, 10) == 10
-    doAssert "0123456789ABCDEFGH".find("A", 5, 9) == -1
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}) == 10
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5) == 10
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 10) == 10
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 9) == -1
+    const haystack: string = "0123456789ABCDEFGH"
+    doAssert haystack.find('A') == 10
+    doAssert haystack.find('A', 5) == 10
+    doAssert haystack.find('A', 5, 10) == 10
+    doAssert haystack.find('A', 5, 9) == -1
+    doAssert haystack.find("A") == 10
+    doAssert haystack.find("A", 5) == 10
+    doAssert haystack.find("A", 5, 10) == 10
+    doAssert haystack.find("A", 5, 9) == -1
+    doAssert haystack.find({'A'..'C'}) == 10
+    doAssert haystack.find({'A'..'C'}, 5) == 10
+    doAssert haystack.find({'A'..'C'}, 5, 10) == 10
+    doAssert haystack.find({'A'..'C'}, 5, 9) == -1
+    doAssert haystack.find('A', 0, 0) == -1 # search limited to the first char
+    doAssert haystack.find('A', 5, 0) == -1 # last < start
+    doAssert haystack.find('A', 5, 4) == -1 # last < start
+
+    block:
+      const haystack: string = "ABCABABABABCAB"
+      doAssert haystack.len == 14
+
+      # only last argument
+      doAssert haystack.find("ABC") == 0
+      doAssert haystack.find("ABC", last=13) == 0 # after the second ABC
+      doAssert haystack.find("ABC", last=5) == 0 # before the second ABC
+
+      # only start argument
+      doAssert haystack.find("ABC", start=0) == 0
+      doAssert haystack.find("ABC", start=1) == 9
+      doAssert haystack.find("ABC", start=9) == 9
+      doAssert haystack.find("ABC", start=10) == -1
+
+      # both start and last arguments
+      doAssert haystack.find("ABC", start=0, last=14) == 0
+      doAssert haystack.find("ABC", start=0, last=13) == 0
+      doAssert haystack.find("ABC", start=0, last=12) == 0
+      doAssert haystack.find("ABC", start=1, last=13) == 9
+      doAssert haystack.find("ABC", start=1, last=12) == 9
+      doAssert haystack.find("ABC", start=1, last=11) == 9
+      doAssert haystack.find("ABC", start=1, last=10) == -1
+
+    doAssert "".find("/") == -1
+    doAssert "/".find("/") == 0
+    doAssert "/".find("//") == -1
+    doAssert "///".find("//", start=3) == -1
+
+    # searching for empty string
+    doAssert "".find("") == 0
+    doAssert "abc".find("") == 0
+    doAssert "abc".find("", start=1) == 1
+    doAssert "abc".find("", start=2) == 2
+    doAssert "abc".find("", start=3) == 3
+    doAssert "abc".find("", start=4) == -1
+    doAssert "abc".find("", start=400) == -1
+    doAssert "abc".find("", start=1, last=3) == 1
+    doAssert "abc".find("", start=1, last=2) == 1
+    doAssert "abc".find("", start=1, last=1) == 1
+    doAssert "abc".find("", start=1, last=0) == 1
+    doAssert "abc".find("", start=1, last = -1) == 1
+
+    # when last <= start, searching for non-empty string
+    block:
+      let last: int = -1 # searching through whole line
+      doAssert "abcd".find("ab", start=0, last=last) == 0
+      doAssert "abcd".find("ab", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=1, last=last) == 1
+      doAssert "abcd".find("bc", start=2, last=last) == -1
+    block:
+      let last: int = 0
+      doAssert "abcd".find("ab", start=0, last=last) == -1
+      doAssert "abcd".find("ab", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=2, last=last) == -1
+    block:
+      let last: int = 1
+      doAssert "abcd".find("ab", start=0, last=last) == 0
+      doAssert "abcd".find("ab", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=2, last=last) == -1
 
   block: # rfind
     doAssert "0123456789ABCDEFGAH".rfind('A') == 17
@@ -247,6 +354,70 @@ template main() =
     doAssert "/1/2/3".rfind('/', last=1) == 0
     doAssert "/1/2/3".rfind('0') == -1
 
+    block:
+      const haystack: string = "ABCABABABABCAB"
+      doAssert haystack.len == 14
+      doAssert haystack.rfind("ABC") == 9
+      doAssert haystack.rfind("ABC", last=13) == 9
+      doAssert haystack.rfind("ABC", last=12) == 9
+      doAssert haystack.rfind("ABC", last=11) == 9
+      doAssert haystack.rfind("ABC", last=10) == 0
+
+      doAssert haystack.rfind("ABC", start=0) == 9
+      doAssert haystack.rfind("ABC", start=1) == 9
+      doAssert haystack.rfind("ABC", start=9) == 9
+      doAssert haystack.rfind("ABC", start=10) == -1
+
+      doAssert haystack.rfind("ABC", start=0, last=13) == 9
+      doAssert haystack.rfind("ABC", start=0, last=12) == 9
+      doAssert haystack.rfind("ABC", start=0, last=11) == 9
+      doAssert haystack.rfind("ABC", start=0, last=10) == 0
+      doAssert haystack.rfind("ABC", start=1, last=10) == -1
+
+    doAssert "".rfind("/") == -1
+    doAssert "/".rfind("/") == 0
+    doAssert "/".rfind("//") == -1
+    doAssert "///".rfind("//", start=3) == -1
+
+    # searching for empty string
+    doAssert "".rfind("") == 0
+    doAssert "abc".rfind("") == 3
+    doAssert "abc".rfind("", start=1) == 3
+    doAssert "abc".rfind("", start=2) == 3
+    doAssert "abc".rfind("", start=3) == 3
+    doAssert "abc".rfind("", start=4) == 4
+    doAssert "abc".rfind("", start=400) == 400
+
+    doAssert "abc".rfind("", start=1, last=3) == 3
+    doAssert "abc".rfind("", start=1, last=2) == 2
+    doAssert "abc".rfind("", start=1, last=1) == 1
+    # This returns the start index instead of the last index
+    # because start > last
+    doAssert "abc".rfind("", start=1, last=0) == 1
+    doAssert "abc".rfind("", start=1, last = -1) == 3
+    
+    doAssert "abc".rfind("", start=0, last=0) == 0
+
+    # when last <= start, searching for non-empty string
+    block:
+      let last: int = -1
+      doAssert "abcd".rfind("ab", start=0, last=last) == 0
+      doAssert "abcd".rfind("ab", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=1, last=last) == 1
+      doAssert "abcd".rfind("bc", start=2, last=last) == -1
+    block:
+      let last: int = 0
+      doAssert "abcd".rfind("ab", start=0, last=last) == -1
+      doAssert "abcd".rfind("ab", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=2, last=last) == -1
+    block:
+      let last: int = 1
+      doAssert "abcd".rfind("ab", start=0, last=last) == 0
+      doAssert "abcd".rfind("ab", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=2, last=last) == -1
+
   block: # trimZeros
     var x = "1200"
     x.trimZeros()
@@ -281,6 +452,9 @@ template main() =
     x = "1e0"
     x.trimZeros()
     doAssert x == "1e0"
+    x = "1.23"
+    x.trimZeros()
+    doAssert x == "1.23"
 
   block: # countLines
     proc assertCountLines(s: string) = doAssert s.countLines == s.splitLines.len
@@ -353,8 +527,9 @@ template main() =
 
   block: # toHex
     doAssert(toHex(100i16, 32) == "00000000000000000000000000000064")
-    doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
-    when not defined js:
+    whenJsNoBigInt64: discard
+    do:
+      doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
       doAssert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
       doAssert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
       doAssert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF")
@@ -375,11 +550,12 @@ template main() =
     doAssert(spaces(0) == "")
 
   block: # toBin, toOct
-    block:# bug #11369
+    whenJsNoBigInt64: # bug #11369
+      discard
+    do:
       var num: int64 = -1
-      when not defined js:
-        doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
-        doAssert num.toOct(24) == "001777777777777777777777"
+      doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
+      doAssert num.toOct(24) == "001777777777777777777777"
 
   block: # replace
     doAssert "oo".replace("", "abc") == "oo"
@@ -440,6 +616,17 @@ template main() =
       let g = parseEnum[Foo]("Bar", A)
       doAssert g == A
 
+    block: # bug #19463
+      const CAMPAIGN_TABLE = "wikientries_campaign"
+      const CHARACTER_TABLE = "wikientries_character"
+
+      type Tables = enum
+        a = CAMPAIGN_TABLE,
+        b = CHARACTER_TABLE,
+
+      let myA = CAMPAIGN_TABLE
+      doAssert $parseEnum[Tables](myA) == "wikientries_campaign"
+
     block: # check enum defined in block
       type
         Bar = enum
@@ -492,11 +679,22 @@ template main() =
       doAssert b == f2
       doAssert c == f3
 
-  block: # parseEnum TODO: merge above
-    type MyEnum = enum enA, enB, enC, enuD, enE
-    doAssert parseEnum[MyEnum]("enu_D") == enuD
-
-    doAssert parseEnum("invalid enum value", enC) == enC
+    block:
+      type MyEnum = enum enA, enB, enC, enuD, enE
+      doAssert parseEnum[MyEnum]("enu_D") == enuD
+
+      doAssert parseEnum("invalid enum value", enC) == enC
+    
+    block: # issue #22726
+      type SomeEnum = enum A, B, C
+
+      proc assignEnum(dest: var enum, s: string) =
+        type ty = typeof(dest)
+        dest = parseEnum[ty](s)
+      
+      var v: SomeEnum
+      v.assignEnum("A")
+      doAssert v == A
 
   block: # indentation
     doAssert 0 == indentation """
@@ -575,7 +773,8 @@ bar
 
   block: # formatSize
     disableVm:
-      when not defined(js):
+      whenJsNoBigInt64: discard
+      do:
         doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
       doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
       doAssert formatSize(4096) == "4KiB"
@@ -698,5 +897,17 @@ bar
     doAssert s.endsWith('a') == false
     doAssert s.endsWith('\0') == false
 
+  block: # nimIdentNormalize
+    doAssert nimIdentNormalize("") == ""
+    doAssert nimIdentNormalize("foo") == "foo"
+    doAssert nimIdentNormalize("foo_bar") == "foobar"
+    doAssert nimIdentNormalize("Foo_bar") == "Foobar"
+    doAssert nimIdentNormalize("_Foo_bar") == "_foobar"
+
+  block: # bug #19500
+    doAssert "abc \0 def".find("def") == 6
+    doAssert "abc \0 def".find('d') == 6
+
+
 static: main()
 main()
diff --git a/tests/stdlib/tstrutils2.nim b/tests/stdlib/tstrutils2.nim
deleted file mode 100644
index 881817f90..000000000
--- a/tests/stdlib/tstrutils2.nim
+++ /dev/null
@@ -1,32 +0,0 @@
-import "$lib/.." / compiler/strutils2
-
-block: # setLen
-  var a = "abc"
-  a.setLen 0
-  a.setLen 3, isInit = false
-  doAssert a[1] == 'b'
-  a.setLen 0
-  a.setLen 3, isInit = true
-  doAssert a[1] == '\0'
-
-block: # forceCopy
-  var a: string
-  a = "foo"
-  shallow(a)
-  var b: string
-  b = a
-  doAssert b[0].addr == a[0].addr
-  var c: string
-  c.forceCopy a
-  doAssert c == a
-  doAssert c[0].addr != a[0].addr
-
-block: # toLowerAscii
-  var a = "fooBAr"
-  a.toLowerAscii
-  doAssert a == "foobar"
-
-block: # dataPointer
-  var a: string
-  discard a.dataPointer
-  # doAssert a.dataPointer == nil # not guaranteed
diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim
index 72abadae7..2ea96cfbb 100644
--- a/tests/stdlib/tsugar.nim
+++ b/tests/stdlib/tsugar.nim
@@ -1,9 +1,33 @@
 discard """
+  targets: "c js"
+  matrix: "--mm:refc; --mm:orc"
   output: '''
 x + y = 30
 '''
 """
-import std/[sugar, algorithm, random, sets, tables, strutils]
+import std/[sugar, algorithm, random, sets, tables, strutils, sequtils]
+import std/[syncio, assertions]
+
+type # for capture test, ref #20679
+  FooCapture = ref object
+    x: int
+
+proc mainProc() =
+  block: # bug #16967
+    var s = newSeq[proc (): int](5)
+    {.push exportc.}
+    proc bar() =
+      for i in 0 ..< s.len:
+        let foo = i + 1
+        capture foo:
+          s[i] = proc(): int = foo
+    {.pop.}
+
+    bar()
+
+    for i, p in s.pairs:
+      let foo = i + 1
+      doAssert p() == foo
 
 template main() =
   block: # `=>`
@@ -79,21 +103,61 @@ template main() =
             closure2 = () => (i, j)
     doAssert closure2() == (5, 3)
 
-    block: # bug #16967
-      var s = newSeq[proc (): int](5)
-      {.push exportc.}
-      proc bar() =
-        for i in 0 ..< s.len:
-          let foo = i + 1
-          capture foo:
-            s[i] = proc(): int = foo
-      {.pop.}
+    block: # issue #20679
+      # this should compile. Previously was broken as `var int` is an `nnkHiddenDeref`
+      # which was not handled correctly
 
-      bar()
+      block:
+        var x = 5
+        var s1 = newSeq[proc (): int](2)
+        proc function(data: var int) =
+          for i in 0 ..< 2:
+            data = (i+1) * data
+            capture data:
+              s1[i] = proc(): int = data
+        function(x)
+        doAssert s1[0]() == 5
+        doAssert s1[1]() == 10
 
-      for i, p in s.pairs:
-        let foo = i + 1
-        doAssert p() == foo
+
+      block:
+        var y = @[5, 10]
+        var s2 = newSeq[proc (): seq[int]](2)
+        proc functionS(data: var seq[int]) =
+          for i in 0 ..< 2:
+            data.add (i+1) * 5
+            capture data:
+              s2[i] = proc(): seq[int] = data
+        functionS(y)
+        doAssert s2[0]() == @[5, 10, 5]
+        doAssert s2[1]() == @[5, 10, 5, 10]
+
+
+      template typeT(typ, val: untyped): untyped =
+        var x = val
+        var s = newSeq[proc (): typ](2)
+
+        proc functionT[T](data: var T) =
+          for i in 0 ..< 2:
+            if i == 1:
+              data = default(T)
+            capture data:
+              s[i] = proc (): T = data
+
+        functionT(x)
+        doAssert s[0]() == val
+        doAssert s[1]() == x # == default
+        doAssert s[1]() == default(typ)
+
+      block:
+        var x = 1.1
+        typeT(float, x)
+      block:
+        var x = "hello"
+        typeT(string, x)
+      block:
+        var f = FooCapture(x: 5)
+        typeT(FooCapture, f)
 
   block: # dup
     block dup_with_field:
@@ -208,17 +272,16 @@ template main() =
         discard collect(newSeq, for i in 1..3: i)
       foo()
 
-proc mainProc() =
   block: # dump
     # symbols in templates are gensym'd
     let
-      x = 10
-      y = 20
+      x {.inject.} = 10
+      y {.inject.} = 20
     dump(x + y) # x + y = 30
 
   block: # dumpToString
     template square(x): untyped = x * x
-    let x = 10
+    let x {.inject.} = 10
     doAssert dumpToString(square(x)) == "square(x): x * x = 100"
     let s = dumpToString(doAssert 1+1 == 2)
     doAssert "failedAssertImpl" in s
@@ -226,8 +289,22 @@ proc mainProc() =
       doAssertRaises(AssertionDefect): doAssert false
     doAssert "except AssertionDefect" in s2
 
-static:
-  main()
+  block: # bug #20704
+    proc test() =
+      var xs, ys: seq[int]
+      for i in 0..5:
+        xs.add(i)
+
+      xs.apply(proc (d: auto) = ys.add(d))
+      # ^ can be turned into d => ys.add(d) when we can infer void return type, #16906
+      doAssert ys == @[0, 1, 2, 3, 4, 5]
+
+    test()
+
   mainProc()
+
+when not defined(js): # TODO fixme JS VM
+  static:
+    main()
+
 main()
-mainProc()
diff --git a/tests/stdlib/tsums.nim b/tests/stdlib/tsums.nim
index 4c29d3e10..cf410cddf 100644
--- a/tests/stdlib/tsums.nim
+++ b/tests/stdlib/tsums.nim
@@ -1,5 +1,10 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/sums
 from math import pow
+import std/assertions
 
 var epsilon = 1.0
 while 1.0 + epsilon != 1.0:
diff --git a/tests/stdlib/tsysrand.nim b/tests/stdlib/tsysrand.nim
index c6d43a8fb..7b7a0fc34 100644
--- a/tests/stdlib/tsysrand.nim
+++ b/tests/stdlib/tsysrand.nim
@@ -1,10 +1,10 @@
 discard """
   targets: "c cpp js"
-  matrix: "--experimental:vmopsDanger"
+  matrix: "--experimental:vmopsDanger; --experimental:vmopsDanger --mm:refc"
 """
 
 import std/sysrand
-
+import std/assertions
 
 template main() =
   block:
diff --git a/tests/stdlib/tsystem.nim b/tests/stdlib/tsystem.nim
new file mode 100644
index 000000000..f634ce0c2
--- /dev/null
+++ b/tests/stdlib/tsystem.nim
@@ -0,0 +1,200 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+
+import stdtest/testutils
+import std/[assertions, formatfloat]
+
+# TODO: in future work move existing `system` tests here, where they belong
+
+
+template main =
+  block: # closure
+    proc outer() =
+      var a = 0
+      proc inner1 = a.inc
+      proc inner2 = discard
+      doAssert inner1 is "closure"
+      doAssert inner2 isnot "closure"
+      doAssert inner1 is (proc)
+      doAssert inner2 is (proc)
+      let inner1b = inner1
+      doAssert inner1b is "closure"
+      doAssert inner1b == inner1
+    outer()
+
+  block: # rawProc, rawProc, bug #17911
+    proc outer() =
+      var a = 0
+      var b = 0
+      proc inner1() = a.inc
+      proc inner2() = a += 2
+      proc inner3() = b.inc
+      let inner1b = inner1
+      doAssert inner2 != inner1
+      doAssert inner3 != inner1
+      whenVMorJs: discard
+      do:
+        doAssert rawProc(inner1b) == rawProc(inner1)
+        doAssert rawProc(inner2) != rawProc(inner1)
+        doAssert rawProc(inner3) != rawProc(inner1)
+
+        doAssert rawEnv(inner1b) == rawEnv(inner1)
+        doAssert rawEnv(inner2) == rawEnv(inner1) # because both use `a`
+        # doAssert rawEnv(inner3) != rawEnv(inner1) # because `a` vs `b` # this doesn't hold
+    outer()
+
+  block: # system.delete
+    block:
+      var s = @[1]
+      s.delete(0)
+      doAssert s == @[]
+
+    block:
+      var s = @["foo", "bar"]
+      s.delete(1)
+      doAssert s == @["foo"]
+
+    when false:
+      var s: seq[string]
+      doAssertRaises(IndexDefect):
+        s.delete(0)
+
+    block:
+      doAssert not compiles(@["foo"].delete(-1))
+
+    block: # bug #6710
+      var s = @["foo"]
+      s.delete(0)
+      doAssert s == @[]
+
+    when false: # bug #16544: deleting out of bounds index should raise
+      var s = @["foo"]
+      doAssertRaises(IndexDefect):
+        s.delete(1)
+
+static: main()
+main()
+
+# bug #19967
+block:
+  type
+    X = object
+      a: string
+      b: set[char]
+      c: int
+      d: float
+      e: int64
+
+
+  var x = X(b: {'a'}, e: 10)
+
+  var y = move x
+
+  doAssert x.a == ""
+  doAssert x.b == {}
+  doAssert x.c == 0
+  doAssert x.d == 0.0
+  doAssert x.e == 0
+
+  reset(y)
+
+  doAssert y.a == ""
+  doAssert y.b == {}
+  doAssert y.c == 0
+  doAssert y.d == 0.0
+  doAssert y.e == 0
+
+block:
+  var x = 2
+  var y = move x
+  doAssert y == 2
+  doAssert x == 0
+  reset y
+  doAssert y == 0
+
+block:
+  type
+    X = object
+      a: string
+      b: float
+
+  var y = X(b: 1314.521)
+
+  reset(y)
+
+  doAssert y.b == 0.0
+
+block:
+  type
+    X = object
+      a: string
+      b: string
+
+  var y = X(b: "1314")
+
+  reset(y)
+
+  doAssert y.b == ""
+
+block:
+  type
+    X = object
+      a: string
+      b: seq[int]
+
+  var y = X(b: @[1, 3])
+
+  reset(y)
+
+  doAssert y.b == @[]
+
+block:
+  type
+    X = object
+      a: string
+      b: tuple[a: int, b: string]
+
+  var y = X(b: (1, "cc"))
+
+  reset(y)
+
+  doAssert y.b == (0, "")
+
+block:
+  type
+    Color = enum
+      Red, Blue, Yellow
+    X = object
+      a: string
+      b: set[Color]
+
+  var y = X(b: {Red, Blue})
+
+  reset(y)
+  doAssert y.b == {}
+
+block: # bug #20516
+  type Foo = object
+    x {.bitsize:4.}: uint
+    y {.bitsize:4.}: uint
+
+  when not defined(js):
+    let a = create(Foo)
+
+block: # bug #6549
+  when not defined(js):
+    block:
+      const v = 18446744073709551615'u64
+
+      doAssert $v == "18446744073709551615"
+      doAssert $float32(v) == "1.8446744e+19", $float32(v)
+      doAssert $float64(v) == "1.8446744073709552e+19", $float64(v)
+
+    block:
+      let v = 18446744073709551615'u64
+
+      doAssert $v == "18446744073709551615"
+      doAssert $float32(v) == "1.8446744e+19"
+      doAssert $float64(v) == "1.8446744073709552e+19"
diff --git a/tests/stdlib/ttables.nim b/tests/stdlib/ttables.nim
index c1ae89b32..c529aff9f 100644
--- a/tests/stdlib/ttables.nim
+++ b/tests/stdlib/ttables.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import tables, hashes
+import std/assertions
 
 type
   Person = object
diff --git a/tests/stdlib/ttasks.nim b/tests/stdlib/ttasks.nim
new file mode 100644
index 000000000..ba65590d9
--- /dev/null
+++ b/tests/stdlib/ttasks.nim
@@ -0,0 +1,561 @@
+discard """
+  targets: "c cpp"
+  matrix: "--gc:orc --threads:off"
+"""
+
+import std/[tasks, strformat]
+import std/assertions
+
+block:
+  var s = ""
+  proc `+`(x: int, y: string) =
+    s.add $x & y
+
+  let literal = "Nim"
+  let t = toTask(521 + literal)
+  t.invoke()
+
+  doAssert s == "521Nim"
+
+block:
+  var s = ""
+  proc `!`(x: int) =
+    s.add $x
+
+  let t = toTask !12
+  t.invoke()
+
+  doAssert s == "12"
+
+
+block:
+  block:
+    var called = 0
+    proc hello(x: static range[1 .. 5]) =
+      called += x
+
+    let b = toTask hello(3)
+    b.invoke()
+    doAssert called == 3
+    b.invoke()
+    doAssert called == 6
+
+  block:
+    var called = 0
+    proc hello(x: range[1 .. 5]) =
+      called += x
+
+    let b = toTask hello(3)
+    b.invoke()
+    doAssert called == 3
+    b.invoke()
+    doAssert called == 6
+
+  block:
+    var called = 0
+    proc hello(x: 1 .. 5) =
+      called += x
+
+    let b = toTask hello(3)
+    b.invoke()
+    doAssert called == 3
+    b.invoke()
+    doAssert called == 6
+
+  block:
+    var temp = ""
+    proc hello(a: int or seq[string]) =
+      when a is seq[string]:
+        for s in a:
+          temp.add s
+      else:
+        temp.addInt a
+
+    let x = @["1", "2", "3", "4"]
+    let b = toTask hello(x)
+    b.invoke()
+    doAssert temp == "1234"
+    b.invoke()
+    doAssert temp == "12341234"
+
+
+  block:
+    var temp = ""
+
+    proc hello(a: int or string) =
+      when a is string:
+        temp.add a
+
+    let x = "!2"
+
+    let b = toTask hello(x)
+    b.invoke()
+    doAssert temp == x
+
+  block:
+    var temp = ""
+    proc hello(a: int or string) =
+      when a is string:
+        temp.add a
+
+    let x = "!2"
+    let b = toTask hello(x)
+    b.invoke()
+    doAssert temp == x
+
+  block:
+    var x = 0
+    proc hello(typ: typedesc) =
+      x += typ(12)
+
+    let b = toTask hello(int)
+    b.invoke()
+    doAssert x == 12
+
+  block:
+    var temp = ""
+    proc hello(a: int or seq[string]) =
+      when a is seq[string]:
+        for s in a:
+          temp.add s
+
+    let x = @["1", "2", "3", "4"]
+    let b = toTask hello(x)
+    b.invoke()
+    doAssert temp == "1234"
+
+  block:
+    var temp = ""
+    proc hello(a: int | string) =
+      when a is string:
+        temp.add a
+
+    let x = "!2"
+    let b = toTask hello(x)
+    b.invoke()
+    doAssert temp == x
+
+  block:
+    var x = 0
+    proc hello(a: int | string) =
+      when a is int:
+        x = a
+
+    let b = toTask hello(12)
+    b.invoke()
+    doAssert x == 12
+
+  block:
+    var a1: seq[int]
+    var a2 = 0
+    proc hello(c: seq[int], a: int) =
+      a1 = c
+      a2 = a
+
+    let x = 12
+    var y = @[1, 3, 1, 4, 5, x, 1]
+    let b = toTask hello(y, 12)
+    b.invoke()
+
+    doAssert a1 == y
+    doAssert a2 == x
+
+  block:
+    var a1: seq[int]
+    var a2 = 0
+    proc hello(c: seq[int], a: int) =
+      a1 = c
+      a2 = a
+    var x = 2
+    let b = toTask hello(@[1, 3, 1, 4, 5, x, 1], 12)
+    b.invoke()
+
+    doAssert a1 == @[1, 3, 1, 4, 5, x, 1]
+    doAssert a2 == 12
+
+  block:
+    var a1: array[7, int]
+    var a2 = 0
+    proc hello(c: array[7, int], a: int) =
+      a1 = c
+      a2 = a
+
+    let b = toTask hello([1, 3, 1, 4, 5, 2, 1], 12)
+    b.invoke()
+
+    doAssert a1 == [1, 3, 1, 4, 5, 2, 1]
+    doAssert a2 == 12
+
+  block:
+    var a1: seq[int]
+    var a2 = 0
+    proc hello(c: seq[int], a: int) =
+      a1 = c
+      a2 = a
+
+    let b = toTask hello(@[1, 3, 1, 4, 5, 2, 1], 12)
+    b.invoke()
+
+    doAssert a1 == @[1, 3, 1, 4, 5, 2, 1]
+    doAssert a2 == 12
+
+  block:
+    var a1: seq[int]
+    var a2 = 0
+    proc hello(a: int, c: seq[int]) =
+      a1 = c
+      a2 = a
+
+    let b = toTask hello(8, @[1, 3, 1, 4, 5, 2, 1])
+    b.invoke()
+
+    doAssert a1 == @[1, 3, 1, 4, 5, 2, 1]
+    doAssert a2 == 8
+
+    let c = toTask 8.hello(@[1, 3, 1, 4, 5, 2, 1])
+    c.invoke()
+
+    doAssert a1 == @[1, 3, 1, 4, 5, 2, 1]
+    doAssert a2 == 8
+
+  block:
+    var a1: seq[seq[int]]
+    var a2: int
+    proc hello(a: int, c: openArray[seq[int]]) =
+      a1 = @c
+      a2 = a
+
+    let b = toTask hello(8, @[@[3], @[4], @[5], @[6], @[12], @[7]])
+    b.invoke()
+
+    doAssert a1 ==  @[@[3], @[4], @[5], @[6], @[12], @[7]]
+    doAssert a2 == 8
+
+  block:
+    var a1: seq[int]
+    var a2: int
+    proc hello(a: int, c: openArray[int]) =
+      a1 = @c
+      a2 = a
+
+    let b = toTask hello(8, @[3, 4, 5, 6, 12, 7])
+    b.invoke()
+
+    doAssert a1 == @[3, 4, 5, 6, 12, 7]
+    doAssert a2 == 8
+
+  block:
+    var a1: seq[int]
+    var a2: int
+    proc hello(a: int, c: static varargs[int]) =
+      a1 = @c
+      a2 = a
+
+    let b = toTask hello(8, @[3, 4, 5, 6, 12, 7])
+    b.invoke()
+
+    doAssert a1 == @[3, 4, 5, 6, 12, 7]
+    doAssert a2 == 8
+
+  block:
+    var a1: seq[int]
+    var a2: int
+    proc hello(a: int, c: static varargs[int]) =
+      a1 = @c
+      a2 = a
+
+    let b = toTask hello(8, [3, 4, 5, 6, 12, 7])
+    b.invoke()
+
+    doAssert a1 == @[3, 4, 5, 6, 12, 7]
+    doAssert a2 == 8
+
+  block:
+    var a1: seq[int]
+    var a2: int
+    proc hello(a: int, c: varargs[int]) =
+      a1 = @c
+      a2 = a
+
+    let x = 12
+    let b = toTask hello(8, 3, 4, 5, 6, x, 7)
+    b.invoke()
+
+    doAssert a1 == @[3, 4, 5, 6, 12, 7]
+    doAssert a2 == 8
+
+  block:
+    var x = 12
+
+    proc hello(x: ptr int) =
+      x[] += 12
+
+    let b = toTask hello(addr x)
+    b.invoke()
+
+    doAssert x == 24
+
+    let c = toTask x.addr.hello
+    invoke(c)
+
+    doAssert x == 36
+  block:
+    type
+      Test = ref object
+        id: int
+
+    var x = 0
+    proc hello(a: int, c: static Test) =
+      x += a
+      x += c.id
+
+    let b = toTask hello(8, Test(id: 12))
+    b.invoke()
+
+    doAssert x == 20
+
+  block:
+    type
+      Test = object
+        id: int
+
+    var x = 0
+    proc hello(a: int, c: static Test) =
+      x += a
+      x += c.id
+
+    let b = toTask hello(8, Test(id: 12))
+    b.invoke()
+    doAssert x == 20
+
+  block:
+    var x = 0
+    proc hello(a: int, c: static seq[int]) =
+      x += a
+      for i in c:
+        x += i
+
+    let b = toTask hello(8, @[3, 4, 5, 6, 12, 7])
+    b.invoke()
+    doAssert x == 45
+
+  block:
+    var x = 0
+    proc hello(a: int, c: static array[5, int]) =
+      x += a
+      for i in c:
+        x += i
+
+    let b = toTask hello(8, [3, 4, 5, 6, 12])
+    b.invoke()
+    doAssert x == 38
+
+  block:
+    var aVal = 0
+    var cVal = ""
+
+    proc hello(a: int, c: static string) =
+      aVal += a
+      cVal.add c
+
+    var x = 1314
+    let b = toTask hello(x, "hello")
+    b.invoke()
+
+    doAssert aVal == x
+    doAssert cVal == "hello"
+
+  block:
+    var aVal = ""
+
+    proc hello(a: static string) =
+      aVal.add a
+    let b = toTask hello("hello")
+    b.invoke()
+
+    doAssert aVal == "hello"
+
+  block:
+    var aVal = 0
+    var cVal = ""
+
+    proc hello(a: static int, c: static string) =
+      aVal += a
+      cVal.add c
+    let b = toTask hello(8, "hello")
+    b.invoke()
+
+    doAssert aVal == 8
+    doAssert cVal == "hello"
+
+  block:
+    var aVal = 0
+    var cVal = 0
+
+    proc hello(a: static int, c: int) =
+      aVal += a
+      cVal += c
+
+    let b = toTask hello(c = 0, a = 8)
+    b.invoke()
+
+    doAssert aVal == 8
+    doAssert cVal == 0
+
+  block:
+    var aVal = 0
+    var cVal = 0
+
+    proc hello(a: int, c: static int) =
+      aVal += a
+      cVal += c
+
+    let b = toTask hello(c = 0, a = 8)
+    b.invoke()
+
+    doAssert aVal == 8
+    doAssert cVal == 0
+
+  block:
+    var aVal = 0
+    var cVal = 0
+
+    proc hello(a: static int, c: static int) =
+      aVal += a
+      cVal += c
+
+    let b = toTask hello(0, 8)
+    b.invoke()
+
+    doAssert aVal == 0
+    doAssert cVal == 8
+
+  block:
+    var temp = ""
+    proc hello(x: int, y: seq[string], d = 134) =
+      temp = fmt"{x=} {y=} {d=}"
+
+
+    proc main() =
+      var x = @["23456"]
+      let t = toTask hello(2233, x)
+      t.invoke()
+
+      doAssert temp == """x=2233 y=@["23456"] d=134"""
+
+    main()
+
+
+  block:
+    var temp = ""
+    proc hello(x: int, y: seq[string], d = 134) =
+      temp.add fmt"{x=} {y=} {d=}"
+
+    proc ok() =
+      temp = "ok"
+
+    proc main() =
+      var x = @["23456"]
+      let t = toTask hello(2233, x)
+      t.invoke()
+      t.invoke()
+
+      doAssert temp == """x=2233 y=@["23456"] d=134x=2233 y=@["23456"] d=134"""
+
+    main()
+
+    var x = @["4"]
+    let m = toTask hello(2233, x, 7)
+    m.invoke()
+
+    doAssert temp == """x=2233 y=@["23456"] d=134x=2233 y=@["23456"] d=134x=2233 y=@["4"] d=7"""
+
+    let n = toTask ok()
+    n.invoke()
+
+    doAssert temp == "ok"
+
+  block:
+    var called = 0
+    block:
+      proc hello() =
+        inc called
+
+      let a = toTask hello()
+      invoke(a)
+
+    doAssert called == 1
+
+    block:
+      proc hello(a: int) =
+        inc called, a
+
+      let b = toTask hello(13)
+      let c = toTask hello(a = 14)
+      b.invoke()
+      c.invoke()
+
+    doAssert called == 28
+
+    block:
+      proc hello(a: int, c: int) =
+        inc called, a
+
+      let b = toTask hello(c = 0, a = 8)
+      b.invoke()
+
+    doAssert called == 36
+
+  block:
+    proc returnsSomething(a, b: int): int = a + b
+
+    proc noArgsButReturnsSomething(): string = "abcdef"
+
+    proc testReturnValues() =
+      let t = toTask returnsSomething(2233, 11)
+      var res: int
+      t.invoke(addr res)
+      doAssert res == 2233+11
+
+      let tb = toTask noArgsButReturnsSomething()
+      var resB: string
+      tb.invoke(addr resB)
+      doAssert resB == "abcdef"
+
+    testReturnValues()
+
+
+block: # bug #23635
+  block:
+    type
+      Store = object
+        run: proc (a: int) {.nimcall, gcsafe.}
+
+    block:
+      var count = 0
+      proc hello(a: int) =
+        inc count, a
+
+      var store = Store()
+      store.run = hello
+
+      let b = toTask store.run(13)
+      b.invoke()
+      doAssert count == 13
+
+  block:
+    type
+      Store = object
+        run: proc () {.nimcall, gcsafe.}
+
+    block:
+      var count = 0
+      proc hello() =
+        inc count, 1
+
+      var store = Store()
+      store.run = hello
+
+      let b = toTask store.run()
+      b.invoke()
+      doAssert count == 1
diff --git a/tests/stdlib/ttempfiles.nim b/tests/stdlib/ttempfiles.nim
new file mode 100644
index 000000000..352788c42
--- /dev/null
+++ b/tests/stdlib/ttempfiles.nim
@@ -0,0 +1,51 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  joinable: false # not strictly necessary
+"""
+
+import std/tempfiles
+import std/[os, nre]
+import std/[assertions, syncio]
+
+const
+  prefix = "D20210502T100442" # safety precaution to only affect files/dirs with this prefix
+  suffix = ".tmp"
+
+block:
+  var t1 = createTempFile(prefix, suffix)
+  var t2 = createTempFile(prefix, suffix)
+  defer:
+    close(t1.cfile)
+    close(t2.cfile)
+    removeFile(t1.path)
+    removeFile(t2.path)
+
+  doAssert t1.path != t2.path
+
+  let s = "1234"
+  write(t1.cfile, s)
+  doAssert readAll(t2.cfile) == ""
+  doAssert readAll(t1.cfile) == ""
+  t1.cfile.setFilePos 0
+  doAssert readAll(t1.cfile) == s
+
+block: # createTempDir
+  doAssertRaises(OSError): discard createTempDir(prefix, suffix, "nonexistent")
+
+  block:
+    let dir1 = createTempDir(prefix, suffix)
+    let dir2 = createTempDir(prefix, suffix)
+    defer:
+      removeDir(dir1)
+      removeDir(dir2)
+    doAssert dir1 != dir2
+
+    doAssert dirExists(dir1)
+    doAssert dir1.lastPathPart.contains(re"^D20210502T100442(\w+).tmp$")
+    doAssert dir1.parentDir == getTempDir().normalizePathEnd()
+
+  block:
+    let dir3 = createTempDir(prefix, "_mytmp", ".")
+    doAssert dir3.lastPathPart.contains(re"^D20210502T100442(\w+)_mytmp$")
+    doAssert dir3.parentDir == "." # not getCurrentDir(): we honor the absolute/relative state of input `dir`
+    removeDir(dir3)
diff --git a/tests/stdlib/tterminal.nim b/tests/stdlib/tterminal.nim
index 364c8d82e..16365e71c 100644
--- a/tests/stdlib/tterminal.nim
+++ b/tests/stdlib/tterminal.nim
@@ -1,7 +1,6 @@
 discard """
   action: compile
 """
-
 import terminal, colors
 
 styledEcho fgColor, colRed, "Test"
diff --git a/tests/stdlib/tterminal_12759.nim b/tests/stdlib/tterminal_12759.nim
index d6034ab57..e9ea3127c 100644
--- a/tests/stdlib/tterminal_12759.nim
+++ b/tests/stdlib/tterminal_12759.nim
@@ -3,6 +3,7 @@ discard """
 """
 
 import terminal
+import std/syncio
 
 proc test() {.raises:[IOError, ValueError].} =
   setBackgroundColor(stdout, bgRed)
diff --git a/tests/stdlib/ttestutils.nim b/tests/stdlib/ttestutils.nim
index 1a50d311b..0f8bf16cf 100644
--- a/tests/stdlib/ttestutils.nim
+++ b/tests/stdlib/ttestutils.nim
@@ -1,6 +1,40 @@
 import stdtest/testutils
+import std/assertions
+
+block: # assertAll
+  assertAll:
+    1+1 == 2
+    var a = 3
+    a == 3
+
+  doAssertRaises(AssertionDefect):
+    assertAll:
+      1+1 == 2
+      var a = 3
+      a == 4
 
 block: # greedyOrderedSubsetLines
-  doAssert greedyOrderedSubsetLines("a1\na3", "a0\na1\na2\na3\na4")
-  doAssert not greedyOrderedSubsetLines("a3\na1", "a0\na1\na2\na3\na4") # out of order
-  doAssert not greedyOrderedSubsetLines("a1\na5", "a0\na1\na2\na3\na4") # a5 not in lhs
+  assertAll:
+    greedyOrderedSubsetLines("a1\na3", "a0\na1\na2\na3\na4")
+    not greedyOrderedSubsetLines("a3\na1", "a0\na1\na2\na3\na4") # out of order
+    not greedyOrderedSubsetLines("a1\na5", "a0\na1\na2\na3\na4") # a5 not in lhs
+
+    not greedyOrderedSubsetLines("a1\na5", "a0\na1\na2\na3\na4\nprefix:a5")
+    not greedyOrderedSubsetLines("a1\na5", "a0\na1\na2\na3\na4\na5:suffix")
+    not greedyOrderedSubsetLines("a5", "a0\na1\na2\na3\na4\nprefix:a5")
+    not greedyOrderedSubsetLines("a5", "a0\na1\na2\na3\na4\na5:suffix")
+
+block: # greedyOrderedSubsetLines with allowPrefixMatch = true
+  template fn(a, b): bool =
+    greedyOrderedSubsetLines(a, b, allowPrefixMatch = true)
+  assertAll:
+    fn("a1\na3", "a0\na1\na2\na3_suffix\na4")
+    not fn("a1\na3", "a0\na1\na2\nprefix_a3\na4")
+    # these are same as above, could be refactored
+    not fn("a3\na1", "a0\na1\na2\na3\na4") # out of order
+    not fn("a1\na5", "a0\na1\na2\na3\na4") # a5 not in lhs
+
+    not fn("a1\na5", "a0\na1\na2\na3\na4\nprefix:a5")
+    fn("a1\na5", "a0\na1\na2\na3\na4\na5:suffix")
+    not fn("a5", "a0\na1\na2\na3\na4\nprefix:a5")
+    fn("a5", "a0\na1\na2\na3\na4\na5:suffix")
diff --git a/tests/stdlib/tthreadpool.nim b/tests/stdlib/tthreadpool.nim
index 897c7d173..1947074be 100644
--- a/tests/stdlib/tthreadpool.nim
+++ b/tests/stdlib/tthreadpool.nim
@@ -1,9 +1,9 @@
 discard """
-  matrix: "--threads:on --gc:arc"
+  matrix: "--mm:arc; --mm:refc"
   disabled: "freebsd"
   output: "42"
 """
-
+import std/assertions
 from std/threadpool import spawn, `^`, sync
 block: # bug #12005
   proc doworkok(i: int) {.thread.} = echo i
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index 66157b91c..0f04168dc 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -1,8 +1,9 @@
 discard """
-  targets: "c js"
+  matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off -d:nimStringHash2"
 """
 
 import times, strutils, unittest
+import std/assertions
 
 when not defined(js):
   import os
@@ -10,17 +11,17 @@ when not defined(js):
 proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} =
   let offset = hours * 3600 + minutes * 60 + seconds
 
-  proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime {.locks: 0.} =
+  proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime =
     result.isDst = false
     result.utcOffset = offset
     result.time = adjTime + initDuration(seconds = offset)
 
-  proc zonedTimeFromTime(time: Time): ZonedTime {.locks: 0.}=
+  proc zonedTimeFromTime(time: Time): ZonedTime =
     result.isDst = false
     result.utcOffset = offset
     result.time = time
 
-  newTimezone("", zonedTimeFromTime, zonedTImeFromAdjTime)
+  newTimezone("", zonedTimeFromTime, zonedTimeFromAdjTime)
 
 template parseTest(s, f, sExpected: string, ydExpected: int) =
   let
@@ -70,7 +71,7 @@ template runTimezoneTests() =
       "2006-01-12T22:04:05Z", 11)
   # RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
   parseTest("2006-01-12T15:04:05.999999999Z-07:00",
-      "yyyy-MM-dd'T'HH:mm:ss'.999999999Z'zzz", "2006-01-12T22:04:05Z", 11)
+      "yyyy-MM-dd'T'HH:mm:ss.'999999999Z'zzz", "2006-01-12T22:04:05Z", 11)
   for tzFormat in ["z", "zz", "zzz"]:
     # formatting timezone as 'Z' for UTC
     parseTest("2001-01-12T22:04:05Z", "yyyy-MM-dd'T'HH:mm:ss" & tzFormat,
@@ -646,3 +647,138 @@ block: # ttimes
     doAssert initDuration(milliseconds = 500).inMilliseconds == 500
     doAssert initDuration(milliseconds = -500).inMilliseconds == -500
     doAssert initDuration(nanoseconds = -999999999).inMilliseconds == -999
+
+  block: # getIsoWeekAndYear
+    doAssert getIsoWeekAndYear(initDateTime(04, mNov, 2019, 00, 00, 00)) == (isoweek: 45.IsoWeekRange, isoyear: 2019.IsoYear)
+    doAssert initDateTime(dMon, 45, 2019.IsoYear, 00, 00, 00) == initDateTime(04, mNov, 2019, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(28, mDec, 2019, 00, 00, 00)) == (isoweek: 52.IsoWeekRange, isoyear: 2019.IsoYear)
+    doAssert initDateTime(dSat, 52, 2019.IsoYear, 00, 00, 00) == initDateTime(28, mDec, 2019, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(29, mDec, 2019, 00, 00, 00)) == (isoweek: 52.IsoWeekRange, isoyear: 2019.IsoYear)
+    doAssert initDateTime(dSun, 52, 2019.IsoYear, 00, 00, 00) == initDateTime(29, mDec, 2019, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(30, mDec, 2019, 00, 00, 00)) == (isoweek: 01.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dMon, 01, 2020.IsoYear, 00, 00, 00) == initDateTime(30, mDec, 2019, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(31, mDec, 2019, 00, 00, 00)) == (isoweek: 01.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dTue, 01, 2020.IsoYear, 00, 00, 00) == initDateTime(31, mDec, 2019, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mJan, 2020, 00, 00, 00)) == (isoweek: 01.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dWed, 01, 2020.IsoYear, 00, 00, 00) == initDateTime(01, mJan, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(02, mJan, 2020, 00, 00, 00)) == (isoweek: 01.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dThu, 01, 2020.IsoYear, 00, 00, 00) == initDateTime(02, mJan, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(05, mApr, 2020, 00, 00, 00)) == (isoweek: 14.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dSun, 14, 2020.IsoYear, 00, 00, 00) == initDateTime(05, mApr, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(06, mApr, 2020, 00, 00, 00)) == (isoweek: 15.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dMon, 15, 2020.IsoYear, 00, 00, 00) == initDateTime(06, mApr, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(10, mApr, 2020, 00, 00, 00)) == (isoweek: 15.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dFri, 15, 2020.IsoYear, 00, 00, 00) == initDateTime(10, mApr, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(12, mApr, 2020, 00, 00, 00)) == (isoweek: 15.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dSun, 15, 2020.IsoYear, 00, 00, 00) == initDateTime(12, mApr, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(13, mApr, 2020, 00, 00, 00)) == (isoweek: 16.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dMon, 16, 2020.IsoYear, 00, 00, 00) == initDateTime(13, mApr, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(15, mApr, 2020, 00, 00, 00)) == (isoweek: 16.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dThu, 16, 2020.IsoYear, 00, 00, 00) == initDateTime(16, mApr, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(17, mJul, 2020, 00, 00, 00)) == (isoweek: 29.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dFri, 29, 2020.IsoYear, 00, 00, 00) == initDateTime(17, mJul, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(19, mJul, 2020, 00, 00, 00)) == (isoweek: 29.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dSun, 29, 2020.IsoYear, 00, 00, 00) == initDateTime(19, mJul, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(20, mJul, 2020, 00, 00, 00)) == (isoweek: 30.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dMon, 30, 2020.IsoYear, 00, 00, 00) == initDateTime(20, mJul, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(23, mJul, 2020, 00, 00, 00)) == (isoweek: 30.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dThu, 30, 2020.IsoYear, 00, 00, 00) == initDateTime(23, mJul, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(31, mDec, 2020, 00, 00, 00)) == (isoweek: 53.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dThu, 53, 2020.IsoYear, 00, 00, 00) == initDateTime(31, mDec, 2020, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mJan, 2021, 00, 00, 00)) == (isoweek: 53.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dFri, 53, 2020.IsoYear, 00, 00, 00) == initDateTime(01, mJan, 2021, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(02, mJan, 2021, 00, 00, 00)) == (isoweek: 53.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dSat, 53, 2020.IsoYear, 00, 00, 00) == initDateTime(02, mJan, 2021, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(03, mJan, 2021, 00, 00, 00)) == (isoweek: 53.IsoWeekRange, isoyear: 2020.IsoYear)
+    doAssert initDateTime(dSun, 53, 2020.IsoYear, 00, 00, 00) == initDateTime(03, mJan, 2021, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(04, mJan, 2021, 00, 00, 00)) == (isoweek: 01.IsoWeekRange, isoyear: 2021.IsoYear)
+    doAssert initDateTime(dMon, 01, 2021.IsoYear, 00, 00, 00) == initDateTime(04, mJan, 2021, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mFeb, 2021, 00, 00, 00)) == (isoweek: 05.IsoWeekRange, isoyear: 2021.IsoYear)
+    doAssert initDateTime(dMon, 05, 2021.IsoYear, 00, 00, 00) == initDateTime(01, mFeb, 2021, 00, 00, 00)
+
+    doAssert getIsoWeekAndYear(initDateTime(01, mFeb, 2021, 01, 02, 03, 400_000_000, staticTz(hours=1))) == (isoweek: 05.IsoWeekRange, isoyear: 2021.IsoYear)
+    doAssert initDateTime(dMon, 05, 2021.IsoYear, 01, 02, 03, 400_000_000, staticTz(hours=1)) == initDateTime(01, mFeb, 2021, 01, 02, 03, 400_000_000, staticTz(hours=1))
+
+    doAssert getIsoWeekAndYear(initDateTime(01, mApr, +0001, 00, 00, 00)) == (isoweek: 13.IsoWeekRange, isoyear: 0001.IsoYear)
+    doAssert initDateTime(dSun, 13, 0001.IsoYear, 00, 00, 00) == initDateTime(01, mApr, 0001, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mApr, +0000, 00, 00, 00)) == (isoweek: 13.IsoWeekRange, isoyear: 0000.IsoYear)
+    doAssert initDateTime(dSat, 13, 0000.IsoYear, 00, 00, 00) == initDateTime(01, mApr, 0000, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mApr, -0001, 00, 00, 00)) == (isoweek: 13.IsoWeekRange, isoyear: (-0001).IsoYear)
+    doAssert initDateTime(dThu, 13, (-0001).IsoYear, 00, 00, 00) == initDateTime(01, mApr, -0001, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mApr, -0002, 00, 00, 00)) == (isoweek: 14.IsoWeekRange, isoyear: (-0002).IsoYear)
+    doAssert initDateTime(dWed, 14, (-0002).IsoYear, 00, 00, 00) == initDateTime(01, mApr, -0002, 00, 00, 00)
+    doAssert getIsoWeekAndYear(initDateTime(01, mApr, -0753, 00, 00, 00)) == (isoweek: 14.IsoWeekRange, isoyear: (-0753).IsoYear)
+    doAssert initDateTime(dMon, 14, (-0753).IsoYear, 00, 00, 00) == initDateTime(01, mApr, -0753, 00, 00, 00)
+
+  block: # getWeeksInIsoYear
+    doAssert getWeeksInIsoYear((-0014).IsoYear) == 52
+    doAssert getWeeksInIsoYear((-0013).IsoYear) == 53
+    doAssert getWeeksInIsoYear((-0012).IsoYear) == 52
+
+    doAssert getWeeksInIsoYear((-0009).IsoYear) == 52
+    doAssert getWeeksInIsoYear((-0008).IsoYear) == 53
+    doAssert getWeeksInIsoYear((-0007).IsoYear) == 52
+
+    doAssert getWeeksInIsoYear((-0003).IsoYear) == 52
+    doAssert getWeeksInIsoYear((-0002).IsoYear) == 53
+    doAssert getWeeksInIsoYear((-0001).IsoYear) == 52
+
+    doAssert getWeeksInIsoYear(0003.IsoYear) == 52
+    doAssert getWeeksInIsoYear(0004.IsoYear) == 53
+    doAssert getWeeksInIsoYear(0005.IsoYear) == 52
+
+    doAssert getWeeksInIsoYear(1653.IsoYear) == 52
+    doAssert getWeeksInIsoYear(1654.IsoYear) == 53
+    doAssert getWeeksInIsoYear(1655.IsoYear) == 52
+
+    doAssert getWeeksInIsoYear(1997.IsoYear) == 52
+    doAssert getWeeksInIsoYear(1998.IsoYear) == 53
+    doAssert getWeeksInIsoYear(1999.IsoYear) == 52
+
+    doAssert getWeeksInIsoYear(2008.IsoYear) == 52
+    doAssert getWeeksInIsoYear(2009.IsoYear) == 53
+    doAssert getWeeksInIsoYear(2010.IsoYear) == 52
+
+    doAssert getWeeksInIsoYear(2014.IsoYear) == 52
+    doAssert getWeeksInIsoYear(2015.IsoYear) == 53
+    doAssert getWeeksInIsoYear(2016.IsoYear) == 52
+
+  block: # parse and generate iso years
+    # short calendar week with text
+    parseTest("KW 23 2023", "'KW' VV GGGG",
+      "2023-06-05T00:00:00Z", 155)
+    parseTest("KW 5 2023", "'KW' V GGGG",
+      "2023-01-30T00:00:00Z", 29)
+    parseTest("KW 05 23 Saturday", "'KW' V GG dddd",
+      "2023-02-04T00:00:00Z", 34)
+    parseTest("KW 53 20 Fri", "'KW' VV GG ddd",
+      "2021-01-01T00:00:00Z", 0)
+
+    parseTestExcp("KW 23", "'KW' VV") # no year
+    parseTestExcp("KW 23", "'KW' V") # no year
+    parseTestExcp("KW 23", "'KW' GG") # no week
+    parseTestExcp("KW 2023", "'KW' GGGG") # no week
+    
+    var dt = initDateTime(5, mJan, 2023, 0, 0, 0, utc())
+    check dt.format("V") == "1"
+    check dt.format("VV") == "01"
+    check dt.format("GG") == "23"
+    check dt.format("GGGG") == "2023"
+    check dt.format("dddd 'KW'V GGGG") == "Thursday KW1 2023"
+
+  block: # Can be used inside gcsafe proc
+    proc test(): DateTime {.gcsafe.} =
+      result = "1970".parse("yyyy")
+    doAssert test().year == 1970
+
+  block: # test FormatLiterals
+    # since #23861
+    block:
+      let dt = dateTime(2024, mJul, 21, 17, 01, 02, 123_321_123, utc())
+      check dt.format("ss.fff") == "02.123"
+      check dt.format("fff.ffffff") == "123.123321"
+    block:
+      let dt = parse("2024.07.21", "yyyy.MM.dd")
+      check dt.year == 2024
+      check dt.month == mJul
+      check dt.monthday == 21
diff --git a/tests/stdlib/ttypeinfo.nim b/tests/stdlib/ttypeinfo.nim
index 61c661a58..9bbc2e92c 100644
--- a/tests/stdlib/ttypeinfo.nim
+++ b/tests/stdlib/ttypeinfo.nim
@@ -1,4 +1,9 @@
-import typeinfo
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/typeinfo
+import std/assertions
 
 type
   TE = enum
@@ -50,7 +55,7 @@ doAssert($x4[].kind() == "akString")
 
 block:
   # gimme a new scope dammit
-  var myarr: array[0..4, array[0..4, string]] = [
+  var myArr: array[0..4, array[0..4, string]] = [
     ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
     ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
     ["test", "1", "2", "3", "4"]]
@@ -69,3 +74,20 @@ block:
 
   doAssert getEnumOrdinal(y, "Hello") == 0
   doAssert getEnumOrdinal(y, "hello") == 1
+
+block: # bug #23556
+  proc test =
+    var
+      t: seq[int]
+      aseq = toAny(t)
+
+    invokeNewSeq(aseq, 0)
+
+    # Got random value only when loop 8 times.
+    for i in 1 .. 8:
+      extendSeq(aseq)
+
+    doAssert t == @[0, 0, 0, 0, 0, 0, 0, 0]
+
+  for i in 1 .. 7:
+    test()
diff --git a/tests/stdlib/ttypeinfo.nims b/tests/stdlib/ttypeinfo.nims
new file mode 100644
index 000000000..d31d0b26f
--- /dev/null
+++ b/tests/stdlib/ttypeinfo.nims
@@ -0,0 +1 @@
+--styleCheck:off
\ No newline at end of file
diff --git a/tests/stdlib/ttypetraits.nim b/tests/stdlib/ttypetraits.nim
new file mode 100644
index 000000000..6851b9220
--- /dev/null
+++ b/tests/stdlib/ttypetraits.nim
@@ -0,0 +1,94 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+
+# xxx merge with tests/metatype/ttypetraits.nim
+
+import std/typetraits
+import std/assertions
+
+macro testClosure(fn: typed, flag: static bool) =
+  if flag:
+    doAssert hasClosure(fn)
+  else:
+    doAssert not hasClosure(fn)
+
+block:
+  proc h1() =
+    echo 1
+
+  testClosure(h1, false)
+
+  proc h2() {.nimcall.} =
+    echo 2
+
+  testClosure(h2, false)
+
+
+block:
+  proc fn(): auto =
+    proc hello() {.nimcall.} =
+      echo 3
+    hello
+
+  let name = fn()
+  testClosure(name, false)
+
+block:
+  proc fn(): auto =
+    proc hello() =
+      echo 3
+    hello
+
+  let name = fn()
+  testClosure(name, false)
+
+block:
+  proc fn(): auto =
+    var x = 0
+    proc hello() =
+      echo 3
+      inc x
+    hello
+
+  let name = fn()
+  testClosure(name, true)
+
+block:
+  proc fn(): auto =
+    var x = 0
+    proc hello() {.closure.} =
+      echo 3
+      inc x
+    hello
+
+  let name = fn()
+  testClosure(name, true)
+
+block:
+  proc fn(): auto =
+    var x = 0
+    proc hello() {.closure.} =
+      echo 3
+      inc x
+    hello
+
+  let name = fn()
+  testClosure(name, true)
+
+  let name2 = name
+  testClosure(name2, true)
+
+block:
+  iterator hello(): int =
+    yield 1
+
+  testClosure(hello, false)
+
+when not defined(js):
+  block:
+    iterator hello(): int {.closure.}=
+      yield 1
+
+    testClosure(hello, true)
diff --git a/tests/stdlib/tunicode.nim b/tests/stdlib/tunicode.nim
index a346106f9..b9e68b15b 100644
--- a/tests/stdlib/tunicode.nim
+++ b/tests/stdlib/tunicode.nim
@@ -1,5 +1,9 @@
-import unicode
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
 
+import std/unicode
+import std/assertions
 
 proc asRune(s: static[string]): Rune =
   ## Compile-time conversion proc for converting string literals to a Rune
@@ -53,6 +57,7 @@ doAssert isAlpha("r")
 doAssert isAlpha("α")
 doAssert isAlpha("ϙ")
 doAssert isAlpha("ஶ")
+doAssert isAlpha("网")
 doAssert(not isAlpha("$"))
 doAssert(not isAlpha(""))
 
@@ -62,6 +67,7 @@ doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽")
 doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει")
 doAssert isAlpha("Јамогујестистаклоитоминештети")
 doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ")
+doAssert isAlpha("编程语言")
 doAssert(not isAlpha("$Foo✓"))
 doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞"))
 
@@ -213,3 +219,10 @@ block differentSizes:
   doAssert swapCase("ⱥbCd") == "ȺBcD"
   doAssert swapCase("XyꟆaB") == "xYᶎAb"
   doAssert swapCase("aᵹcᲈd") == "AꝽCꙊD"
+
+block: # bug #17768
+  let s1 = "abcdef"
+  let s2 = "abcdéf"
+
+  doAssert s1.runeSubStr(0, -1) == "abcde"
+  doAssert s2.runeSubStr(0, -1) == "abcdé"
diff --git a/tests/stdlib/tunidecode.nim b/tests/stdlib/tunidecode.nim
index be8e0523c..653016ea9 100644
--- a/tests/stdlib/tunidecode.nim
+++ b/tests/stdlib/tunidecode.nim
@@ -5,6 +5,7 @@ discard """
 import unidecode
 
 import std/unidecode # #14112
+import std/assertions
 
 loadUnidecodeTable("lib/pure/unidecode/unidecode.dat")
 
diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim
index 97a45e199..0442c7863 100644
--- a/tests/stdlib/tunittest.nim
+++ b/tests/stdlib/tunittest.nim
@@ -19,10 +19,12 @@ discard """
 
 [Suite] test name filtering
 '''
+matrix: "--mm:refc; --mm:orc"
 targets: "c js"
 """
 
-import std/[unittest, sequtils]
+import std/[unittest, sequtils, assertions]
+from std/unittest {.all.} import matchFilter
 
 proc doThings(spuds: var int): int =
   spuds = 24
diff --git a/tests/stdlib/tunittestpass.nim b/tests/stdlib/tunittestpass.nim
index cff37a3b7..d8de277b7 100644
--- a/tests/stdlib/tunittestpass.nim
+++ b/tests/stdlib/tunittestpass.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets: "c js"
 """
 
diff --git a/tests/stdlib/tunittesttemplate.nim b/tests/stdlib/tunittesttemplate.nim
index 2ca50a18b..c29e0de01 100644
--- a/tests/stdlib/tunittesttemplate.nim
+++ b/tests/stdlib/tunittesttemplate.nim
@@ -8,9 +8,9 @@ discard """
 """
 
 
-# bug #6736
 
-import unittest
+# bug #6736
+import std/unittest
 
 type
   A = object
diff --git a/tests/stdlib/tunixsocket.nim b/tests/stdlib/tunixsocket.nim
new file mode 100644
index 000000000..636fd08c6
--- /dev/null
+++ b/tests/stdlib/tunixsocket.nim
@@ -0,0 +1,35 @@
+import std/[assertions, net, os, osproc]
+
+# XXX: Make this test run on Windows too when we add support for Unix sockets on Windows
+when defined(posix) and not defined(nimNetLite):
+  const nim = getCurrentCompilerExe()
+  let
+    dir = currentSourcePath().parentDir()
+    serverPath = dir / "unixsockettest"
+
+  let (_, err) = execCmdEx(nim & " c " & quoteShell(dir / "unixsockettest.nim"))
+  doAssert err == 0
+
+  let svproc = startProcess(serverPath, workingDir = dir)
+  doAssert svproc.running()
+  # Wait for the server to open the socket and listen from it
+  sleep(400)
+
+  block unixSocketSendRecv:
+    let
+      unixSocketPath = dir / "usox"
+      socket = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_NONE)
+
+    socket.connectUnix(unixSocketPath)
+    # for a blocking Unix socket this should never fail
+    socket.send("data sent through the socket\c\l", maxRetries = 0)
+    var resp: string
+    socket.readLine(resp)
+    doAssert resp == "Hello from server"
+
+    socket.send("bye\c\l")
+    socket.readLine(resp)
+    doAssert resp == "bye"
+    socket.close()
+
+  svproc.close()
diff --git a/tests/stdlib/turi.nim b/tests/stdlib/turi.nim
index 1a6f37520..9c717c5b1 100644
--- a/tests/stdlib/turi.nim
+++ b/tests/stdlib/turi.nim
@@ -1,9 +1,12 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   targets:  "c js"
 """
 
 import std/uri
+from std/uri {.all.} as uri2 import removeDotSegments
 from std/sequtils import toSeq
+import std/assertions
 
 template main() =
   block: # encodeUrl, decodeUrl
@@ -14,6 +17,24 @@ template main() =
     doAssert decodeUrl(encodeUrl(test1, false), false) == test1
     doAssert decodeUrl(encodeUrl(test1)) == test1
 
+  block: # removeDotSegments
+    doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz"
+    doAssert removeDotSegments("") == "" # empty test
+    doAssert removeDotSegments(".") == "." # trailing period
+    doAssert removeDotSegments("a1/a2/../a3/a4/a5/./a6/a7/././") == "a1/a3/a4/a5/a6/a7/"
+    doAssert removeDotSegments("https://a1/a2/../a3/a4/a5/./a6/a7/././") == "https://a1/a3/a4/a5/a6/a7/"
+    doAssert removeDotSegments("http://a1/a2") == "http://a1/a2"
+    doAssert removeDotSegments("http://www.ai.") == "http://www.ai."
+    when false: # xxx these cases are buggy
+      # this should work, refs https://webmasters.stackexchange.com/questions/73934/how-can-urls-have-a-dot-at-the-end-e-g-www-bla-de
+      doAssert removeDotSegments("http://www.ai./") == "http://www.ai./" # fails
+      echo removeDotSegments("http://www.ai./")  # http://www.ai/
+      echo removeDotSegments("a/b.../c") # b.c
+      echo removeDotSegments("a/b../c") # bc
+      echo removeDotSegments("a/.../c") # .c
+      echo removeDotSegments("a//../b") # a/b
+      echo removeDotSegments("a/b/c//") # a/b/c//
+
   block: # parseUri
     block:
       let org = "udp://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
@@ -255,7 +276,9 @@ template main() =
     doAssert encodeQuery({"foo": ""}) == "foo"
     doAssert encodeQuery({"foo": ""}, omitEq = false) == "foo="
     doAssert encodeQuery({"a": "1", "b": "", "c": "3"}) == "a=1&b&c=3"
+    doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, sep = ';') == "a=1;b;c=3"
     doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false) == "a=1&b=&c=3"
+    doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false, sep = ';') == "a=1;b=;c=3"
 
   block: # `?`
     block:
@@ -281,7 +304,20 @@ template main() =
 
   block: # decodeQuery
     doAssert toSeq(decodeQuery("a=1&b=0")) == @[("a", "1"), ("b", "0")]
+    doAssert toSeq(decodeQuery("a=1;b=0", sep = ';')) == @[("a", "1"), ("b", "0")]
     doAssert toSeq(decodeQuery("a=1&b=2c=6")) == @[("a", "1"), ("b", "2c=6")]
+    doAssert toSeq(decodeQuery("a=1;b=2c=6", sep = ';')) == @[("a", "1"), ("b", "2c=6")]
+
+  block: # bug #17481
+    let u1 = parseUri("./")
+    let u2 = parseUri("./path")
+    let u3 = parseUri("a/path")
+    doAssert u1.scheme.len == 0
+    doAssert u1.path == "./"
+    doAssert u2.scheme.len == 0
+    doAssert u2.path == "./path"
+    doAssert u3.scheme.len == 0
+    doAssert u3.path == "a/path"
 
 static: main()
 main()
diff --git a/tests/stdlib/tuserlocks.nim b/tests/stdlib/tuserlocks.nim
index f6eafa05d..927077120 100644
--- a/tests/stdlib/tuserlocks.nim
+++ b/tests/stdlib/tuserlocks.nim
@@ -1,8 +1,9 @@
 discard """
-  cmd: "nim $target --threads:on $options $file"
+  matrix: "--mm:refc; --mm:orc"
 """
 
-import rlocks
+import std/rlocks
+import std/assertions
 
 var r: RLock
 r.initRLock()
@@ -10,4 +11,11 @@ doAssert r.tryAcquire()
 doAssert r.tryAcquire()
 r.release()
 r.release()
+
+block:
+  var x = 12
+  withRLock r:
+    inc x
+  doAssert x == 13
+
 r.deinitRLock()
diff --git a/tests/stdlib/tvarargs.nim b/tests/stdlib/tvarargs.nim
index d56be154b..2edc26264 100644
--- a/tests/stdlib/tvarargs.nim
+++ b/tests/stdlib/tvarargs.nim
@@ -1,8 +1,8 @@
 discard """
   targets: "c js"
-  matrix: "--gc:refc; --gc:arc"
+  matrix: "--mm:refc; --mm:orc"
 """
-
+import std/assertions
 
 template main =
   proc hello(x: varargs[string]): seq[string] =
diff --git a/tests/stdlib/tvarints.nim b/tests/stdlib/tvarints.nim
index dcdb756ce..f9624ee5b 100644
--- a/tests/stdlib/tvarints.nim
+++ b/tests/stdlib/tvarints.nim
@@ -1,15 +1,11 @@
 discard """
-  cmd:      "nim c -r --styleCheck:hint --panics:on $options $file"
-  matrix:   "-d:danger; -d:release"
-  targets:  "c cpp"
-  nimout:   ""
-  action:   "run"
-  exitcode: 0
-  timeout:  60.0
+  matrix: "--mm:refc; --mm:orc"
 """
 
 import std/varints
+import std/assertions
 
+# xxx doesn't work with js: tvarints.nim(18, 14) `wrLen == rdLen`  [AssertionDefect]
 
 block:
   var dest: array[50, byte]
@@ -37,48 +33,41 @@ block:
     doAssert cast[float64](got) == test
 
 block:
-  var hugeIntArray: array[50, byte]
+  var hugeIntArray: array[9, byte]
   var readedInt: uint64
-  doAssert writeVu64(hugeIntArray, 0.uint64) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == 0.uint64
-  doAssert writeVu64(hugeIntArray, uint64.high) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == uint64.high
-  doAssert writeVu64(hugeIntArray, uint64(int64.high)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == uint64(int64.high)
-  doAssert writeVu64(hugeIntArray, uint64(int32.high)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == uint64(int32.high)
-  doAssert writeVu64(hugeIntArray, uint64(int16.high)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == uint64(int16.high)
-  doAssert writeVu64(hugeIntArray, uint64(int8.high)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == uint64(int8.high)
-  doAssert writeVu64(hugeIntArray, cast[uint64](0.0)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](0.0)
-  doAssert writeVu64(hugeIntArray, cast[uint64](-0.0)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](-0.0)
-  doAssert writeVu64(hugeIntArray, cast[uint64](0.1)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](0.1)
-  doAssert writeVu64(hugeIntArray, cast[uint64](0.9555555555555555555555501)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](0.9555555555555555555555501)
-  doAssert writeVu64(hugeIntArray, cast[uint64](+Inf)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](+Inf)
-  doAssert writeVu64(hugeIntArray, cast[uint64](NegInf)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](NegInf)
-  doAssert writeVu64(hugeIntArray, cast[uint64](Nan)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](Nan)
-  doAssert writeVu64(hugeIntArray, cast[uint64](3.1415926535897932384626433)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](3.1415926535897932384626433)
-  doAssert writeVu64(hugeIntArray, cast[uint64](2.71828182845904523536028747)) == readVu64(hugeIntArray, readedInt)
-  doAssert readedInt == cast[uint64](2.71828182845904523536028747)
+
+  template chk(a) =
+    let b = cast[uint64](a)
+    doAssert writeVu64(hugeIntArray, b) == readVu64(hugeIntArray, readedInt)
+    doAssert readedInt == b
+
+  chk 0
+  chk uint64.high
+  chk int64.high
+  chk int32.high
+  chk int16.high
+  chk int16.high
+  chk int8.high
+  chk 0.0
+  chk -0.0
+  chk 0.1
+  chk Inf
+  chk NegInf
+  chk NaN
+  chk 3.1415926535897932384626433
 
 block:
-  doAssert encodeZigzag(decodeZigzag(0.uint64)) == 0.uint64
-  doAssert encodeZigzag(decodeZigzag(uint64(uint32.high))) == uint64(uint32.high)
-  doAssert encodeZigzag(decodeZigzag(uint64(int32.high))) == uint64(int32.high)
-  doAssert encodeZigzag(decodeZigzag(uint64(int16.high))) == uint64(int16.high)
-  doAssert encodeZigzag(decodeZigzag(uint64(int8.high))) == uint64(int8.high)
-  doAssert encodeZigzag(decodeZigzag(cast[uint64](0.0))) == cast[uint64](0.0)
-  doAssert encodeZigzag(decodeZigzag(cast[uint64](0.1))) == cast[uint64](0.1)
-  doAssert encodeZigzag(decodeZigzag(cast[uint64](0.9555555555555555555555501))) == cast[uint64](0.9555555555555555555555501)
-  doAssert encodeZigzag(decodeZigzag(cast[uint64](+Inf))) == cast[uint64](+Inf)
-  doAssert encodeZigzag(decodeZigzag(cast[uint64](3.1415926535897932384626433))) == cast[uint64](3.1415926535897932384626433)
-  doAssert encodeZigzag(decodeZigzag(cast[uint64](2.71828182845904523536028747))) == cast[uint64](2.71828182845904523536028747)
+  template chk(a) =
+    let b = cast[uint64](a)
+    doAssert encodeZigzag(decodeZigzag(b)) == b
+  chk 0
+  chk uint32.high
+  chk int32.high
+  chk int16.high
+  chk int8.high
+  chk 0.0
+  chk 0.1
+  chk 0.9555555555555555555555501
+  chk Inf
+  chk 3.1415926535897932384626433
+  chk 2.71828182845904523536028747
diff --git a/tests/stdlib/tvmutils.nim b/tests/stdlib/tvmutils.nim
new file mode 100644
index 000000000..63804c136
--- /dev/null
+++ b/tests/stdlib/tvmutils.nim
@@ -0,0 +1,31 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  joinable: false
+  nimout: '''
+0
+1
+2
+tvmutils.nim(28, 13) [opcLdImmInt]     if i == 4:
+tvmutils.nim(28, 10) [opcEqInt]     if i == 4:
+tvmutils.nim(28, 10) [opcFJmp]     if i == 4:
+tvmutils.nim(28, 13) [opcLdImmInt]     if i == 4:
+tvmutils.nim(28, 10) [opcEqInt]     if i == 4:
+tvmutils.nim(28, 10) [opcFJmp]     if i == 4:
+tvmutils.nim(29, 7) [opcLdConst]       vmTrace(false)
+tvmutils.nim(29, 15) [opcLdImmInt]       vmTrace(false)
+tvmutils.nim(29, 14) [opcIndCall]       vmTrace(false)
+5
+6
+'''
+"""
+# line 20 (only showing a subset of nimout to avoid making the test rigid)
+import std/vmutils
+proc main() =
+  for i in 0..<7:
+    echo i
+    if i == 2:
+      vmTrace(true)
+    if i == 4:
+      vmTrace(false)
+
+static: main()
diff --git a/tests/stdlib/tvolatile.nim b/tests/stdlib/tvolatile.nim
new file mode 100644
index 000000000..c097f9723
--- /dev/null
+++ b/tests/stdlib/tvolatile.nim
@@ -0,0 +1,15 @@
+import std/[volatile, assertions]
+
+var st: int
+var foo: ptr int = addr st
+volatileStore(foo, 12)
+doAssert volatileLoad(foo) == 12
+
+# bug #14623
+proc bar =
+  var st: int
+  var foo: ptr int = addr st
+  volatileStore(foo, 12)
+  doAssert volatileLoad(foo) == 12
+
+bar()
diff --git a/tests/stdlib/twchartoutf8.nim b/tests/stdlib/twchartoutf8.nim
index a6602e3e3..e437177ac 100644
--- a/tests/stdlib/twchartoutf8.nim
+++ b/tests/stdlib/twchartoutf8.nim
@@ -1,13 +1,17 @@
 discard """
+  matrix: "--mm:refc; --mm:orc"
   output: '''OK'''
 """
 
+import std/[syncio, assertions]
+
 #assume WideCharToMultiByte always produce correct result
 #windows only
 
 when not defined(windows):
   echo "OK"
 else:
+  import std/widestrs
   {.push gcsafe.}
 
   const CP_UTF8 = 65001'i32
@@ -66,8 +70,7 @@ else:
 
   #RFC-2781 "UTF-16, an encoding of ISO 10646"
 
-  var wc: WideCString
-  unsafeNew(wc, 1024 * 4 + 2)
+  var wc: WideCString = newWideCString(1024 * 2)
 
   #U+0000 to U+D7FF
   #skip the U+0000
diff --git a/tests/stdlib/twith.nim b/tests/stdlib/twith.nim
index 80382f7c4..ceadbe7bf 100644
--- a/tests/stdlib/twith.nim
+++ b/tests/stdlib/twith.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/with
+import std/[assertions, formatfloat]
 
 type
   Foo = object
@@ -21,3 +26,19 @@ with f:
 doAssert f.col == "(2, 3, 4)"
 doAssert f.pos == "(0.0, 1.0)"
 doAssert f.name == "bar"
+
+type
+  Baz* = object
+    a*, b*: int
+  Bar* = object
+    x*: int
+    baz*: Baz
+
+var bar: Bar
+with bar:
+  x = 1
+  with baz:
+    a = 2
+
+doAssert bar.x == 1
+doAssert bar.baz.a == 2
diff --git a/tests/stdlib/twordwrap.nim b/tests/stdlib/twordwrap.nim
index c90dd9581..5d49477d3 100644
--- a/tests/stdlib/twordwrap.nim
+++ b/tests/stdlib/twordwrap.nim
@@ -1,4 +1,9 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/wordwrap
+import std/assertions
 
 when true:
   let
diff --git a/tests/stdlib/twrapnils.nim b/tests/stdlib/twrapnils.nim
index af0978762..3da230b5e 100644
--- a/tests/stdlib/twrapnils.nim
+++ b/tests/stdlib/twrapnils.nim
@@ -1,4 +1,10 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/wrapnils
+from std/options import get, isSome
+import std/assertions
 
 proc checkNotZero(x: float): float =
   doAssert x != 0
@@ -6,80 +12,213 @@ proc checkNotZero(x: float): float =
 
 proc main() =
   var witness = 0
-  type Bar = object
-    b1: int
-    b2: ptr string
-
-  type Foo = ref object
-    x1: float
-    x2: Foo
-    x3: string
-    x4: Bar
-    x5: seq[int]
-    x6: ptr Bar
-    x7: array[2, string]
-    x8: seq[int]
-    x9: ref Bar
-
-  type Gook = ref object
-    foo: Foo
-
-  proc fun(a: Bar): auto = a.b2
-
-  var a: Foo
-
-  var x6: ptr Bar
-  when nimvm: discard # pending https://github.com/timotheecour/Nim/issues/568
-  else:
-    x6 = create(Bar)
-    x6.b1 = 42
-  var a2 = Foo(x1: 1.0, x5: @[10, 11], x6: x6)
-  var a3 = Foo(x1: 1.2, x3: "abc")
-  a3.x2 = a3
-
-  var gook = Gook(foo: a)
-
-  proc initFoo(x1: float): auto =
-    witness.inc
-    result = Foo(x1: x1)
-
-  doAssert ?.a.x2.x2.x1 == 0.0
-  doAssert ?.a3.x2.x2.x1 == 1.2
-  doAssert ?.a3.x2.x2.x3[1] == 'b'
-
-  doAssert ?.a3.x2.x2.x5.len == 0
-  doAssert a3.x2.x2.x3.len == 3
-
-  doAssert ?.a.x2.x2.x3[1] == default(char)
-  # here we only apply wrapnil around gook.foo, not gook (and assume gook is not nil)
-  doAssert ?.(gook.foo).x2.x2.x1 == 0.0
-
-  when nimvm: discard
-  else:
-    doAssert ?.a2.x6[] == Bar(b1: 42) # deref for ptr Bar
-
-  doAssert ?.a2.x1.checkNotZero == 1.0
-  doAssert a == nil
-  # shows that checkNotZero won't be called if a nil is found earlier in chain
-  doAssert ?.a.x1.checkNotZero == 0.0
-
-  when nimvm: discard
-  else:
-    # checks that a chain without nil but with an empty seq still raises
-    doAssertRaises(IndexDefect): discard ?.a2.x8[3]
-
-  # make sure no double evaluation bug
-  doAssert witness == 0
-  doAssert ?.initFoo(1.3).x1 == 1.3
-  doAssert witness == 1
-
-  # here, it's used twice, to deref `ref Bar` and then `ptr string`
-  doAssert ?.a.x9[].fun[] == ""
-
-  block: # `??.`
-    doAssert (??.a3.x2.x2.x3.len).get == 3
-    doAssert (??.a2.x4).isSome
-    doAssert not (??.a.x4).isSome
+  block:
+    type Bar = object
+      b1: int
+      b2: ptr string
+
+    type Foo = ref object
+      x1: float
+      x2: Foo
+      x3: string
+      x4: Bar
+      x5: seq[int]
+      x6: ptr Bar
+      x7: array[2, string]
+      x8: seq[int]
+      x9: ref Bar
+
+    type Goo = ref object
+      foo: Foo
+
+    proc fun(a: Bar): auto = a.b2
+
+    var a: Foo
+
+    var x6: ptr Bar
+    when nimvm: discard # pending https://github.com/timotheecour/Nim/issues/568
+    else:
+      x6 = create(Bar)
+      x6.b1 = 42
+    var a2 = Foo(x1: 1.0, x5: @[10, 11], x6: x6)
+    var a3 = Foo(x1: 1.2, x3: "abc")
+    a3.x2 = a3
+
+    var goo = Goo(foo: a)
+
+    proc initFoo(x1: float): auto =
+      witness.inc
+      result = Foo(x1: x1)
+
+    doAssert ?.a.x2.x2.x1 == 0.0
+    doAssert ?.a3.x2.x2.x1 == 1.2
+    doAssert ?.a3.x2.x2.x3[1] == 'b'
+
+    doAssert ?.a3.x2.x2.x5.len == 0
+    doAssert a3.x2.x2.x3.len == 3
+
+    doAssert ?.a.x2.x2.x3[1] == default(char)
+    # here we only apply wrapnil around goo.foo, not goo (and assume goo is not nil)
+    doAssert ?.(goo.foo).x2.x2.x1 == 0.0
+
+    when nimvm: discard
+    else:
+      doAssert ?.a2.x6[] == Bar(b1: 42) # deref for ptr Bar
+
+    doAssert ?.a2.x1.checkNotZero == 1.0
+    doAssert a == nil
+    # shows that checkNotZero won't be called if a nil is found earlier in chain
+    doAssert ?.a.x1.checkNotZero == 0.0
+
+    when nimvm: discard
+    else:
+      # checks that a chain without nil but with an empty seq still raises
+      doAssertRaises(IndexDefect): discard ?.a2.x8[3]
+
+    # make sure no double evaluation bug
+    doAssert witness == 0
+    doAssert ?.initFoo(1.3).x1 == 1.3
+    doAssert witness == 1
+
+    # here, it's used twice, to deref `ref Bar` and then `ptr string`
+    doAssert ?.a.x9[].fun[] == ""
+
+    block: # `??.`
+      doAssert (??.a3.x2.x2.x3.len).get == 3
+      doAssert (??.a2.x4).isSome
+      doAssert not (??.a.x4).isSome
+
+  block:
+    type
+      A = object
+        b: B
+      B = object
+        c: C
+      C = object
+        d: D
+      D = ref object
+        e: E
+        e2: array[2, E]
+        e3: seq[E]
+        d3: D
+        i4: int
+      E = object
+        f: int
+        d2: D
+    proc identity[T](a: T): T = a
+    proc identity2[T](a: T, ignore: int): T = a
+    var a: A
+    doAssert ?.a.b.c.d.e.f == 0
+    doAssert ?.a.b.c.d.e.d2.d3[].d3.e.d2.e.f == 0
+    doAssert ?.a.b.c.d.d3[].e.f == 0
+    doAssert ?.a.b.c.d.e2[0].d2.e3[0].f == 0
+    doAssert ?.a == A.default
+    doAssert ?.a.b.c.d.e == E.default
+    doAssert ?.a.b.c.d.e.d2 == nil
+
+    doAssert ?.a.identity.b.c.identity2(12).d.d3.e.f == 0
+    doAssert ?.a.b.c.d.d3.e2[0].f == 0
+    a.b.c.d = D()
+    a.b.c.d.d3 = a.b.c.d
+    a.b.c.d.e2[0].f = 5
+    doAssert ?.a.b.c.d.d3.e2[0].f == 5
+
+    var d: D = nil
+    doAssert ?.d.identity.i4 == 0
+    doAssert ?.d.i4.identity == 0
+
+  block: # case objects
+    type
+      Kind = enum k0, k1, k2
+      V = object
+        case kind: Kind
+        of k0:
+          x0: int
+        of k1:
+          x1: int
+        of k2:
+          x2: int
+      A = object
+        v0: V
+
+    block:
+      var a = V(kind: k0, x0: 3)
+      doAssert ?.a.x0 == 3
+      doAssert ?.a.x1 == 0
+      a = V(kind: k1, x1: 5)
+      doAssert ?.a.x0 == 0
+      doAssert ?.a.x1 == 5
+
+    block:
+      var a = A(v0: V(kind: k0, x0: 10))
+      doAssert ?.a.v0.x0 == 10
+      doAssert ?.a.v0.x1 == 0
+      a.v0 = V(kind: k2, x2: 8)
+      doAssert ?.a.v0.x0 == 0
+      doAssert ?.a.v0.x1 == 0
+      doAssert ?.a.v0.x2 == 8
+
+  block: # `nnkCall`
+    type
+      A = object
+        a0: int
+        d: D
+      D = ref object
+        i4: int
+
+    proc identity[T](a: T): T = a
+    var d: D = nil
+    doAssert ?.d.i4.identity == 0
+    doAssert ?.identity(?.d.i4) == 0
+    doAssert ?.identity(d.i4) == 0
+    doAssert ?.identity(d) == nil
+    doAssert ?.identity(d[]) == default(typeof(d[]))
+    doAssert ?.identity(d[]).i4 == 0
+    var a: A
+    doAssert ?.identity(a) == default(A)
+    doAssert ?.identity(a.a0) == 0
+    doAssert ?.identity(a.d) == nil
+    doAssert ?.identity(a.d.i4) == 0
+
+  block: # lvalue semantic propagation
+    type
+      A = ref object
+        a0: A
+        a1: seq[A]
+        a2: int
+
+      B = object
+        b0: int
+        case cond: bool
+        of false: discard
+        of true:
+          b1: float
+
+    block:
+      var a: A
+      doAssert ?.a.a0.a1[0].a2.addr == nil
+      a = A(a2: 3)
+      doAssert ?.a.a0.a1[0].a2.addr == nil
+      a.a0 = a
+      a.a1 = @[a]
+      let p = ?.a.a0.a1[0].a2.addr
+      doAssert p != nil
+      p[] = 5
+      doAssert a.a2 == 5
+
+    block:
+      var b = B(cond: false, b0: 3)
+      let p = ?.b.b1.addr
+      doAssert p == nil
+      b = B(cond: true, b1: 4.5)
+      let p2 = ?.b.b1.addr
+      doAssert p2 != nil
+      p2[] = 4.6
+      doAssert b.b1 == 4.6
+      # useful pattern, impossible with Options
+      if (let p3 = ?.b.b1.addr; p3 != nil):
+        p3[] = 4.7
+      doAssert b.b1 == 4.7
 
 main()
 static: main()
diff --git a/tests/stdlib/twrongstattype.nim b/tests/stdlib/twrongstattype.nim
new file mode 100644
index 000000000..4a1fc30c6
--- /dev/null
+++ b/tests/stdlib/twrongstattype.nim
@@ -0,0 +1,14 @@
+# issue #24076
+
+when defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd):
+  import std/posix
+  proc uid(x: uint32): Uid = Uid(x)
+  var y: uint32
+  let myUid = geteuid()
+  discard myUid == uid(y)
+  proc dev(x: uint32): Dev = Dev(x)
+  let myDev = 1.Dev
+  discard myDev == dev(y)
+  proc nlink(x: uint32): Nlink = Nlink(x)
+  let myNlink = 1.Nlink
+  discard myNlink == nlink(y)
diff --git a/tests/stdlib/txmltree.nim b/tests/stdlib/txmltree.nim
index d2f713269..add12a3fc 100644
--- a/tests/stdlib/txmltree.nim
+++ b/tests/stdlib/txmltree.nim
@@ -1,4 +1,8 @@
-import xmltree
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
+import std/[xmltree, assertions, xmlparser]
 
 
 block:
@@ -83,3 +87,34 @@ block:
   x.add newElement("sonTag")
   x.add newEntity("my entity")
   doAssert $x == "<myTag>my text<sonTag />&my entity;</myTag>"
+
+block: # bug #21290
+  let x = newXmlTree("foo",[
+    newXmlTree("bar",[
+      newText("Hola"),
+      newXmlTree("qux",[
+        newXmlTree("plugh",[])
+      ])
+    ])
+  ])
+
+  let s = $x
+  doAssert $parseXml(s) == s
+  doAssert s == """<foo>
+  <bar>Hola<qux>    <plugh />  </qux></bar>
+</foo>"""
+
+block: #21541
+  let root = <>root()
+  root.add <>child(newText("hello"))
+  root.add <>more(newVerbatimText("hola"))
+  let s = $root
+  doAssert s == """<root>
+  <child>hello</child>
+  <more>hola</more>
+</root>"""
+
+  let temp = newVerbatimText("Hello!")
+  doAssert temp.text == "Hello!"
+  temp.text = "Hola!"
+  doAssert temp.text == "Hola!"
diff --git a/tests/stdlib/tyield.nim b/tests/stdlib/tyield.nim
new file mode 100644
index 000000000..f385ddd05
--- /dev/null
+++ b/tests/stdlib/tyield.nim
@@ -0,0 +1,258 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c cpp js"
+"""
+
+import std/[sugar, algorithm]
+import std/assertions
+
+block:
+  var x = @[(6.0, 6, '6'),
+            (5.0, 5, '5'),
+            (4.0, 4, '4'),
+            (3.0, 3, '3'),
+            (2.0, 2, '2'),
+            (1.0, 1, '1')]
+
+  let y = x.reversed
+
+  block:
+    let res = collect:
+      for (f, i, c) in x:
+        (f, i, c)
+
+    doAssert res == x
+
+  iterator popAscending[T](q: var seq[T]): T =
+    while q.len > 0: yield q.pop
+
+  block:
+    var res = collect:
+      for f, i, c in popAscending(x):
+        (f, i, c)
+
+    doAssert res == y
+
+    let z = reversed(res)
+    let res2 = collect:
+      for (f, i, c) in popAscending(res):
+        (f, i, c)
+
+    doAssert res2 == z
+
+
+block:
+  var visits = 0
+  block:
+    proc bar(): (int, int) =
+      inc visits
+      (visits, visits)
+
+    iterator foo(): (int, int) =
+      yield bar()
+
+    for a, b in foo():
+      doAssert a == b
+
+    doAssert visits == 1
+
+  block:
+    proc iterAux(a: seq[int], i: var int): (int, string) =
+      result = (a[i], $a[i])
+      inc i
+
+    iterator pairs(a: seq[int]): (int, string) =
+      var i = 0
+      while i < a.len:
+        yield iterAux(a, i)
+
+    var x = newSeq[int](10)
+    for i in 0 ..< x.len:
+      x[i] = i
+
+    let res = collect:
+      for k, v in x:
+        (k, v)
+
+    let expected = collect:
+      for i in 0 ..< x.len:
+        (i, $i)
+
+    doAssert res == expected
+
+  block:
+    proc bar(): (int, int, int) =
+      inc visits
+      (visits, visits, visits)
+
+    iterator foo(): (int, int, int) =
+      yield bar()
+
+    for a, b, c in foo():
+      doAssert a == b
+
+    doAssert visits == 2
+
+
+  block:
+
+    proc bar(): int =
+      inc visits
+      visits
+
+    proc car(): int =
+      inc visits
+      visits
+
+    iterator foo(): (int, int) =
+      yield (bar(), car())
+      yield (bar(), car())
+
+    for a, b in foo():
+      doAssert b == a + 1
+
+    doAssert visits == 6
+
+
+  block:
+    proc bar(): (int, int) =
+      inc visits
+      (visits, visits)
+
+    proc t2(): int = 99
+
+    iterator foo(): (int, int) =
+      yield (12, t2())
+      yield bar()
+
+    let res = collect:
+      for (a, b) in foo():
+        (a, b)
+
+    doAssert res == @[(12, 99), (7, 7)]
+    doAssert visits == 7
+
+  block:
+    proc bar(): (int, int) =
+      inc visits
+      (visits, visits)
+
+    proc t2(): int = 99
+
+    iterator foo(): (int, int) =
+      yield ((12, t2()))
+      yield (bar())
+
+    let res = collect:
+      for (a, b) in foo():
+        (a, b)
+
+    doAssert res == @[(12, 99), (8, 8)]
+    doAssert visits == 8
+
+  block:
+    proc bar(): (int, int) =
+      inc visits
+      (visits, visits)
+
+    proc t1(): int = 99
+    proc t2(): int = 99
+
+    iterator foo(): (int, int) =
+      yield (t1(), t2())
+      yield bar()
+
+    let res = collect:
+      for a, b in foo():
+        (a, b)
+
+    doAssert res == @[(99, 99), (9, 9)]
+    doAssert visits == 9
+
+
+  block:
+    proc bar(): ((int, int), string) =
+      inc visits
+      ((visits, visits), $visits)
+
+    proc t2(): int = 99
+
+    iterator foo(): ((int, int), string) =
+      yield ((1, 2), $t2())
+      yield bar()
+
+    let res = collect:
+      for a, b in foo():
+        (a, b)
+
+    doAssert res == @[((1, 2), "99"), ((10, 10), "10")]
+    doAssert visits == 10
+
+
+  block:
+    proc bar(): (int, int) =
+      inc visits
+      (visits, visits)
+
+    iterator foo(): (int, int) =
+      yield (for i in 0 ..< 10: discard bar(); bar())
+      yield (bar())
+
+    let res = collect:
+      for (a, b) in foo():
+        (a, b)
+
+    doAssert res == @[(21, 21), (22, 22)]
+
+  block:
+    proc bar(): (int, int) =
+      inc visits
+      (visits, visits)
+
+    proc t2(): int = 99
+
+    iterator foo(): (int, int) =
+      yield if true: bar() else: (t2(), t2())
+      yield (bar())
+
+    let res = collect:
+      for a, b in foo():
+        (a, b)
+
+    doAssert res == @[(23, 23), (24, 24)]
+
+
+block:
+  iterator foo(): (int, int, int) =
+    var time = 777
+    yield (1, time, 3)
+
+  let res = collect:
+    for a, b, c in foo():
+      (a, b, c)
+
+  doAssert res == @[(1, 777, 3)]
+
+block:
+  iterator foo(): (int, int, int) =
+    var time = 777
+    yield (1, time, 3)
+
+  let res = collect:
+    for t in foo():
+      (t[0], t[1], t[2])
+
+  doAssert res == @[(1, 777, 3)]
+
+
+block:
+  proc bar(): (int, int, int) =
+    (1, 2, 3)
+  iterator foo(): (int, int, int) =
+    yield bar()
+
+  let res = collect:
+    for a, b, c in foo():
+      (a, b, c)
+
+  doAssert res == @[(1, 2, 3)]
diff --git a/tests/stdlib/unixsockettest.nim b/tests/stdlib/unixsockettest.nim
new file mode 100644
index 000000000..8f95d0808
--- /dev/null
+++ b/tests/stdlib/unixsockettest.nim
@@ -0,0 +1,26 @@
+import std/[assertions, net, os]
+
+let unixSocketPath = getCurrentDir() / "usox"
+
+removeFile(unixSocketPath)
+
+let socket = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_NONE)
+socket.bindUnix(unixSocketPath)
+socket.listen()
+
+var
+  clientSocket: Socket
+  data: string
+
+socket.accept(clientSocket)
+clientSocket.readLine(data)
+doAssert data == "data sent through the socket"
+clientSocket.send("Hello from server\c\l")
+
+clientSocket.readLine(data)
+doAssert data == "bye"
+clientSocket.send("bye\c\l")
+
+clientSocket.close()
+socket.close()
+removeFile(unixSocketPath)
diff --git a/tests/stdlib/uselocks.nim b/tests/stdlib/uselocks.nim
index cde9641b2..f87623b5e 100644
--- a/tests/stdlib/uselocks.nim
+++ b/tests/stdlib/uselocks.nim
@@ -1,4 +1,5 @@
 import locks
+import std/assertions
 
 type MyType* [T] = object
   lock: Lock
@@ -9,3 +10,7 @@ proc createMyType*[T]: MyType[T] =
 proc use* (m: var MyType): int =
   withLock m.lock:
     result = 3
+
+block:
+  var l: Lock
+  doAssert $l == "()"