summary refs log tree commit diff stats
path: root/tests/untestable
diff options
context:
space:
mode:
Diffstat (limited to 'tests/untestable')
-rw-r--r--tests/untestable/gdb/gdb_pretty_printer_test.py50
-rw-r--r--tests/untestable/gdb/gdb_pretty_printer_test_output.txt3
-rw-r--r--tests/untestable/gdb/gdb_pretty_printer_test_program.nim68
-rwxr-xr-x[-rw-r--r--]tests/untestable/gdb/gdb_pretty_printer_test_run.sh20
-rw-r--r--tests/untestable/thttpclient_ssl_disabled.nim36
-rw-r--r--tests/untestable/thttpclient_ssl_env_var.nim74
-rw-r--r--tests/untestable/thttpclient_ssl_remotenetwork.nim230
-rw-r--r--tests/untestable/tpostgres.nim327
8 files changed, 440 insertions, 368 deletions
diff --git a/tests/untestable/gdb/gdb_pretty_printer_test.py b/tests/untestable/gdb/gdb_pretty_printer_test.py
index f002941ec..aed0cfeb0 100644
--- a/tests/untestable/gdb/gdb_pretty_printer_test.py
+++ b/tests/untestable/gdb/gdb_pretty_printer_test.py
@@ -1,36 +1,64 @@
 import gdb
+import re
+import sys
 # this test should test the gdb pretty printers of the nim
 # library. But be aware this test is not complete. It only tests the
 # command line version of gdb. It does not test anything for the
 # machine interface of gdb. This means if if this test passes gdb
 # frontends might still be broken.
 
-gdb.execute("source ../../../tools/nim-gdb.py")
-# debug all instances of the generic function `myDebug`, should be 8
+gdb.execute("set python print-stack full")
+gdb.execute("source ../../../tools/debug/nim-gdb.py")
+# debug all instances of the generic function `myDebug`, should be 14
 gdb.execute("rbreak myDebug")
 gdb.execute("run")
 
 outputs = [
   'meTwo',
+  '""',
   '"meTwo"',
   '{meOne, meThree}',
   'MyOtherEnum(1)',
-  '5',
+  '{MyOtherEnum(0), MyOtherEnum(2)}',
   'array = {1, 2, 3, 4, 5}',
+  'seq(0, 0)',
+  'seq(0, 10)',
+  'array = {"one", "two"}',
+  'seq(3, 3) = {1, 2, 3}',
   'seq(3, 3) = {"one", "two", "three"}',
-  'Table(3, 64) = {["two"] = 2, ["three"] = 3, ["one"] = 1}',
+  'Table(3, 64) = {[4] = "four", [5] = "five", [6] = "six"}',
+  'Table(3, 8) = {["two"] = 2, ["three"] = 3, ["one"] = 1}',
+  '{a = 1, b = "some string"}',
+  '("hello", 42)'
 ]
 
-for i, expected in enumerate(outputs):
-  functionSymbol = gdb.selected_frame().block().function
-  assert functionSymbol.line == 21
+argRegex = re.compile("^.* = (?:No suitable Nim \$ operator found for type: \w+\s*)*(.*)$")
+# Remove this error message which can pop up
+noSuitableRegex = re.compile("(No suitable Nim \$ operator found for type: \w+\s*)")
 
-  if i == 5:
+for i, expected in enumerate(outputs):
+  gdb.write(f"\x1b[38;5;105m{i+1}) expecting: {expected}: \x1b[0m", gdb.STDLOG)
+  gdb.flush()
+  currFrame = gdb.selected_frame()
+  functionSymbol = currFrame.block().function
+  assert functionSymbol.line == 24, str(functionSymbol.line)
+  raw = ""
+  if i == 6:
     # myArray is passed as pointer to int to myDebug. I look up myArray up in the stack
     gdb.execute("up")
-    output = str(gdb.parse_and_eval("myArray"))
+    raw = gdb.parse_and_eval("myArray")    
+  elif i == 9:
+    # myOtherArray is passed as pointer to int to myDebug. I look up myOtherArray up in the stack
+    gdb.execute("up")
+    raw = gdb.parse_and_eval("myOtherArray")
   else:
-    output = str(gdb.parse_and_eval("arg"))
+    rawArg = re.sub(noSuitableRegex, "", gdb.execute("info args", to_string = True))
+    raw = rawArg.split("=", 1)[-1].strip()
+  output = str(raw)
 
-  assert output == expected, output + " != " + expected
+  if output != expected:
+    gdb.write(f"\x1b[38;5;196m ({output}) != expected: ({expected})\x1b[0m\n", gdb.STDERR)
+    gdb.execute("quit 1")
+  else:
+    gdb.write("\x1b[38;5;34mpassed\x1b[0m\n", gdb.STDLOG)
   gdb.execute("continue")
diff --git a/tests/untestable/gdb/gdb_pretty_printer_test_output.txt b/tests/untestable/gdb/gdb_pretty_printer_test_output.txt
deleted file mode 100644
index 73d26016f..000000000
--- a/tests/untestable/gdb/gdb_pretty_printer_test_output.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Loading Nim Runtime support.
-NimEnumPrinter: lookup global symbol 'NTI__z9cu80OJCfNgw9bUdzn5ZEzw_ failed for tyEnum_MyOtherEnum__z9cu80OJCfNgw9bUdzn5ZEzw.
-8
diff --git a/tests/untestable/gdb/gdb_pretty_printer_test_program.nim b/tests/untestable/gdb/gdb_pretty_printer_test_program.nim
index 458435c1a..163c99860 100644
--- a/tests/untestable/gdb/gdb_pretty_printer_test_program.nim
+++ b/tests/untestable/gdb/gdb_pretty_printer_test_program.nim
@@ -14,7 +14,10 @@ type
     moTwo,
     moThree,
     moFoure,
-
+  
+  MyObj = object
+    a*: int
+    b*: string
 
 var counter = 0
 
@@ -23,31 +26,64 @@ proc myDebug[T](arg: T): void =
 
 proc testProc(): void =
   var myEnum = meTwo
-  myDebug(myEnum)
+  myDebug(myEnum) #1
+  
+  # create a string, but don't allocate it
+  var myString: string
+  myDebug(myString) #2
+
   # create a string object but also make the NTI for MyEnum is generated
-  var myString = $myEnum
-  myDebug(myString)
+  myString = $myEnum
+  myDebug(myString) #3
+  
   var mySet = {meOne,meThree}
-  myDebug(mySet)
+  myDebug(mySet) #4
 
   # for MyOtherEnum there is no NTI. This tests the fallback for the pretty printer.
   var moEnum = moTwo
-  myDebug(moEnum)
+  myDebug(moEnum) #5
+
   var moSet = {moOne,moThree}
-  myDebug(moSet)
+  myDebug(moSet) #6
 
   let myArray = [1,2,3,4,5]
-  myDebug(myArray)
-  let mySeq   = @["one","two","three"]
-  myDebug(mySeq)
+  myDebug(myArray) #7
+
+  # implicitly initialized seq test
+  var mySeq: seq[string]
+  myDebug(mySeq) #8
+
+  # len not equal to capacity
+  let myOtherSeq = newSeqOfCap[string](10)
+  myDebug(myOtherSeq) #9
+
+  let myOtherArray = ["one","two"]
+  myDebug(myOtherArray) #10
+
+  # numeric sec
+  var mySeq3 = @[1,2,3]
+  myDebug(mySeq3) #11
+
+  # seq had to grow
+  var mySeq4 = @["one","two","three"]
+  myDebug(mySeq4) #12
+
+  var myTable = initTable[int, string]()
+  myTable[4] = "four"
+  myTable[5] = "five"
+  myTable[6] = "six"
+  myDebug(myTable) #13
+
+  var myOtherTable = {"one": 1, "two": 2, "three": 3}.toTable
+  myDebug(myOtherTable) #14
+
+  var obj = MyObj(a: 1, b: "some string")
+  myDebug(obj) #15
 
-  var myTable = initTable[string, int]()
-  myTable["one"] = 1
-  myTable["two"] = 2
-  myTable["three"] = 3
-  myDebug(myTable)
+  var tup = ("hello", 42)
+  myDebug(tup) # 16
 
-  echo(counter)
+  assert counter == 16
 
 
 testProc()
diff --git a/tests/untestable/gdb/gdb_pretty_printer_test_run.sh b/tests/untestable/gdb/gdb_pretty_printer_test_run.sh
index 525f54705..411c68435 100644..100755
--- a/tests/untestable/gdb/gdb_pretty_printer_test_run.sh
+++ b/tests/untestable/gdb/gdb_pretty_printer_test_run.sh
@@ -1,15 +1,13 @@
 #!/usr/bin/env bash
-# Exit if anything fails
 set -e
-#!/usr/bin/env bash
 # Compile the test project with fresh debug information.
-nim c --debugger:native gdb_pretty_printer_test_program.nim &> /dev/null
+nim c --debugger:native --mm:orc --out:gdbNew gdb_pretty_printer_test_program.nim
+echo "Running new runtime tests..."
 # 2>&1 redirects stderr to stdout (all output in stdout)
-# <(...) is a bash feature that makes the output of a command into a
-# file handle.
-# diff compares the two files, the expected output, and the file
-# handle that is created by the execution of gdb.
-diff ./gdb_pretty_printer_test_output.txt <(gdb -x gdb_pretty_printer_test.py --batch-silent --args gdb_pretty_printer_test_program 2>&1)
-# The exit code of diff is forwarded as the exit code of this
-# script. So when the comparison fails, the exit code of this script
-# won't be 0. So this script should be embeddable in a test suite.
+gdb -x gdb_pretty_printer_test.py --batch-silent --args gdbNew 2>&1
+
+
+# Do it all again, but with old runtime
+nim c --debugger:native --mm:refc --out:gdbOld gdb_pretty_printer_test_program.nim &> /dev/null
+echo "Running old runtime tests"
+gdb -x gdb_pretty_printer_test.py --batch-silent --args gdbOld 2>&1
diff --git a/tests/untestable/thttpclient_ssl_disabled.nim b/tests/untestable/thttpclient_ssl_disabled.nim
new file mode 100644
index 000000000..b95dad2c6
--- /dev/null
+++ b/tests/untestable/thttpclient_ssl_disabled.nim
@@ -0,0 +1,36 @@
+#
+#            Nim - SSL integration tests
+#        (c) Copyright 2017 Nim contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+## Compile and run with:
+## nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:nimDisableCertificateValidation -d:ssl -p:. tests/untestable/thttpclient_ssl_disabled.nim
+
+from stdtest/testutils import enableRemoteNetworking
+when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(openbsd)):
+  import httpclient, net, unittest
+
+  const expired = "https://expired.badssl.com/"
+
+  doAssert defined(nimDisableCertificateValidation)
+
+  suite "SSL certificate check - disabled":
+
+    test "httpclient in insecure mode":
+      var ctx = newContext(verifyMode = CVerifyPeer)
+      var client = newHttpClient(sslContext = ctx)
+      let a = $client.getContent(expired)
+
+    test "httpclient in insecure mode":
+      var ctx = newContext(verifyMode = CVerifyPeerUseEnvVars)
+      var client = newHttpClient(sslContext = ctx)
+      let a = $client.getContent(expired)
+
+    test "net socket in insecure mode":
+      var sock = newSocket()
+      var ctx = newContext(verifyMode = CVerifyPeerUseEnvVars)
+      ctx.wrapSocket(sock)
+      sock.connect("expired.badssl.com", 443.Port)
+      sock.close
diff --git a/tests/untestable/thttpclient_ssl_env_var.nim b/tests/untestable/thttpclient_ssl_env_var.nim
new file mode 100644
index 000000000..3f25a6ff4
--- /dev/null
+++ b/tests/untestable/thttpclient_ssl_env_var.nim
@@ -0,0 +1,74 @@
+#
+#            Nim - SSL integration tests
+#        (c) Copyright 2017 Nim contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+## Warning: this test performs external networking.
+## Compile with:
+## ./bin/nim c -d:ssl -p:. tests/untestable/thttpclient_ssl_env_var.nim
+##
+## Test with:
+##  SSL_CERT_FILE=BogusInexistentFileName tests/untestable/thttpclient_ssl_env_var
+##  SSL_CERT_DIR=BogusInexistentDirName tests/untestable/thttpclient_ssl_env_var
+
+import httpclient, unittest, os
+from net import newSocket, newContext, wrapSocket, connect, close, Port,
+  CVerifyPeerUseEnvVars
+from strutils import contains
+
+const
+  expired = "https://expired.badssl.com/"
+  good = "https://google.com/"
+
+
+suite "SSL certificate check":
+
+  test "httpclient with inexistent file":
+    if existsEnv("SSL_CERT_FILE"):
+      var ctx = newContext(verifyMode=CVerifyPeerUseEnvVars)
+      var client = newHttpClient(sslContext=ctx)
+      checkpoint("Client created")
+      check client.getContent("https://google.com").contains("doctype")
+      checkpoint("Google ok")
+      try:
+        let a = $client.getContent(good)
+        echo "Connection should have failed"
+        fail()
+      except:
+        echo getCurrentExceptionMsg()
+        check getCurrentExceptionMsg().contains("certificate verify failed")
+
+    elif existsEnv("SSL_CERT_DIR"):
+      try:
+        var ctx = newContext(verifyMode=CVerifyPeerUseEnvVars)
+        var client = newHttpClient(sslContext=ctx)
+        echo "Should have raised 'No SSL/TLS CA certificates found.'"
+        fail()
+      except:
+        check getCurrentExceptionMsg() ==
+          "No SSL/TLS CA certificates found."
+
+  test "net socket with inexistent file":
+    if existsEnv("SSL_CERT_FILE"):
+      var sock = newSocket()
+      var ctx = newContext(verifyMode=CVerifyPeerUseEnvVars)
+      ctx.wrapSocket(sock)
+      checkpoint("Socket created")
+      try:
+        sock.connect("expired.badssl.com", 443.Port)
+        fail()
+      except:
+        sock.close
+        check getCurrentExceptionMsg().contains("certificate verify failed")
+
+    elif existsEnv("SSL_CERT_DIR"):
+      var sock = newSocket()
+      checkpoint("Socket created")
+      try:
+        var ctx = newContext(verifyMode=CVerifyPeerUseEnvVars) # raises here
+        fail()
+      except:
+        check getCurrentExceptionMsg() ==
+          "No SSL/TLS CA certificates found."
diff --git a/tests/untestable/thttpclient_ssl_remotenetwork.nim b/tests/untestable/thttpclient_ssl_remotenetwork.nim
new file mode 100644
index 000000000..3cb759516
--- /dev/null
+++ b/tests/untestable/thttpclient_ssl_remotenetwork.nim
@@ -0,0 +1,230 @@
+#
+#
+#            Nim - SSL integration tests
+#        (c) Copyright 2017 Nim contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+## Test with:
+## nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:ssl -p:. --threads:on tests/untestable/thttpclient_ssl_remotenetwork.nim
+##
+## See https://github.com/FedericoCeratto/ssl-comparison/blob/master/README.md
+## for a comparison with other clients.
+
+from stdtest/testutils import enableRemoteNetworking
+when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(windows) and not defined(openbsd)):
+  # Not supported on Windows due to old openssl version
+  import
+    httpclient,
+    net,
+    strutils,
+    threadpool,
+    unittest
+
+
+  type
+    # bad and dubious tests should not pass SSL validation
+    # "_broken" mark the test as skipped. Some tests have different
+    # behavior depending on OS and SSL version!
+    # TODO: chase and fix the broken tests
+    Category = enum
+      good, bad, dubious, good_broken, bad_broken, dubious_broken
+    CertTest = tuple[url:string, category:Category, desc: string]
+
+  # badssl certs sometimes expire, set to false when that happens
+  when true:
+    const certificate_tests: array[0..54, CertTest] = [
+      ("https://wrong.host.badssl.com/", bad, "wrong.host"),
+      ("https://captive-portal.badssl.com/", bad, "captive-portal"),
+      ("https://expired.badssl.com/", bad, "expired"),
+      ("https://google.com/", good, "good"),
+      ("https://self-signed.badssl.com/", bad, "self-signed"),
+      ("https://untrusted-root.badssl.com/", bad, "untrusted-root"),
+      ("https://revoked.badssl.com/", bad_broken, "revoked"),
+      ("https://pinning-test.badssl.com/", bad_broken, "pinning-test"),
+      ("https://no-common-name.badssl.com/", bad, "no-common-name"),
+      ("https://no-subject.badssl.com/", bad, "no-subject"),
+      ("https://sha1-intermediate.badssl.com/", bad, "sha1-intermediate"),
+      ("https://sha256.badssl.com/", good, "sha256"),
+      ("https://sha384.badssl.com/", bad, "sha384"),
+      ("https://sha512.badssl.com/", bad, "sha512"),
+      ("https://1000-sans.badssl.com/", bad, "1000-sans"),
+      ("https://10000-sans.badssl.com/", good_broken, "10000-sans"),
+      ("https://ecc256.badssl.com/", good_broken, "ecc256"),
+      ("https://ecc384.badssl.com/", good_broken, "ecc384"),
+      ("https://rsa2048.badssl.com/", good, "rsa2048"),
+      ("https://rsa8192.badssl.com/", dubious_broken, "rsa8192"),
+      ("http://http.badssl.com/", good, "regular http"),
+      ("https://http.badssl.com/", bad_broken, "http on https URL"),  # FIXME
+      ("https://cbc.badssl.com/", dubious, "cbc"),
+      ("https://rc4-md5.badssl.com/", bad, "rc4-md5"),
+      ("https://rc4.badssl.com/", bad, "rc4"),
+      ("https://3des.badssl.com/", bad, "3des"),
+      ("https://null.badssl.com/", bad, "null"),
+      ("https://mozilla-old.badssl.com/", bad_broken, "mozilla-old"),
+      ("https://mozilla-intermediate.badssl.com/", dubious_broken, "mozilla-intermediate"),
+      ("https://mozilla-modern.badssl.com/", good, "mozilla-modern"),
+      ("https://dh480.badssl.com/", bad, "dh480"),
+      ("https://dh512.badssl.com/", bad, "dh512"),
+      ("https://dh1024.badssl.com/", dubious_broken, "dh1024"),
+      ("https://dh2048.badssl.com/", good, "dh2048"),
+      ("https://dh-small-subgroup.badssl.com/", bad_broken, "dh-small-subgroup"),
+      ("https://dh-composite.badssl.com/", bad_broken, "dh-composite"),
+      ("https://static-rsa.badssl.com/", dubious, "static-rsa"),
+      ("https://tls-v1-0.badssl.com:1010/", dubious, "tls-v1-0"),
+      ("https://tls-v1-1.badssl.com:1011/", dubious, "tls-v1-1"),
+      ("https://invalid-expected-sct.badssl.com/", bad, "invalid-expected-sct"),
+      ("https://hsts.badssl.com/", good, "hsts"),
+      ("https://upgrade.badssl.com/", good, "upgrade"),
+      ("https://preloaded-hsts.badssl.com/", good, "preloaded-hsts"),
+      ("https://subdomain.preloaded-hsts.badssl.com/", bad, "subdomain.preloaded-hsts"),
+      ("https://https-everywhere.badssl.com/", good, "https-everywhere"),
+      ("https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/", good,
+        "long-extended-subdomain-name-containing-many-letters-and-dashes"),
+      ("https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/", good,
+        "longextendedsubdomainnamewithoutdashesinordertotestwordwrapping"),
+      ("https://superfish.badssl.com/", bad, "(Lenovo) Superfish"),
+      ("https://edellroot.badssl.com/", bad, "(Dell) eDellRoot"),
+      ("https://dsdtestprovider.badssl.com/", bad, "(Dell) DSD Test Provider"),
+      ("https://preact-cli.badssl.com/", bad, "preact-cli"),
+      ("https://webpack-dev-server.badssl.com/", bad, "webpack-dev-server"),
+      ("https://mitm-software.badssl.com/", bad, "mitm-software"),
+      ("https://sha1-2016.badssl.com/", dubious, "sha1-2016"),
+      ("https://sha1-2017.badssl.com/", bad, "sha1-2017"),
+    ]
+  else:
+    const certificate_tests: array[0..0, CertTest] = [
+      ("https://google.com/", good, "good")
+    ]
+
+
+  template evaluate(exception_msg: string, category: Category, desc: string) =
+    # Evaluate test outcome. Tests flagged as `_broken` are evaluated and skipped
+    let raised = (exception_msg.len > 0)
+    let should_not_raise = category in {good, dubious_broken, bad_broken}
+    if should_not_raise xor raised:
+      # we are seeing a known behavior
+      if category in {good_broken, dubious_broken, bad_broken}:
+        skip()
+      if raised:
+        # check exception_msg == "No SSL certificate found." or
+        doAssert exception_msg == "No SSL certificate found." or
+          exception_msg == "SSL Certificate check failed." or
+          exception_msg.contains("certificate verify failed") or
+          exception_msg.contains("key too small") or
+          exception_msg.contains("alert handshake failure") or
+          exception_msg.contains("bad dh p length") or
+          # TODO: This one should only triggers for 10000-sans
+          exception_msg.contains("excessive message size"), exception_msg
+
+    else:
+      # this is unexpected
+      var fatal = true
+      var msg = ""
+      if raised:
+        msg = "         $# ($#) raised: $#" % [desc, $category, exception_msg]
+        if "500 Internal Server Error" in exception_msg:
+          # refs https://github.com/nim-lang/Nim/issues/16338#issuecomment-804300278
+          # we got: `good (good) raised: 500 Internal Server Error`
+          fatal = false
+          msg.add " (http 500 => assuming this is not our problem)"
+      else:
+        msg = "         $# ($#) did not raise" % [desc, $category]
+
+      if category in {good, dubious, bad} and fatal:
+        echo "D20210322T121353: error: " & msg
+        fail()
+      else:
+        echo "D20210322T121353: warning: " & msg
+
+
+  suite "SSL certificate check - httpclient":
+
+    for i, ct in certificate_tests:
+
+      test ct.desc:
+        var ctx = newContext(verifyMode=CVerifyPeer)
+        var client = newHttpClient(sslContext=ctx)
+        let exception_msg =
+          try:
+            let a = $client.getContent(ct.url)
+            ""
+          except:
+            getCurrentExceptionMsg()
+
+        evaluate(exception_msg, ct.category, ct.desc)
+
+
+
+  # threaded tests
+
+
+  type
+    TTOutcome = ref object
+      desc, exception_msg: string
+      category: Category
+
+  proc run_t_test(ct: CertTest): TTOutcome {.thread.} =
+    ## Run test in a {.thread.} - return by ref
+    result = TTOutcome(desc:ct.desc, exception_msg:"", category: ct.category)
+    try:
+      var ctx = newContext(verifyMode=CVerifyPeer)
+      var client = newHttpClient(sslContext=ctx)
+      let a = $client.getContent(ct.url)
+    except:
+      result.exception_msg = getCurrentExceptionMsg()
+
+
+  suite "SSL certificate check - httpclient - threaded":
+    when defined(nimTestsEnableFlaky) or not defined(linux): # xxx pending bug #16338
+      # Spawn threads before the "test" blocks
+      var outcomes = newSeq[FlowVar[TTOutcome]](certificate_tests.len)
+      for i, ct in certificate_tests:
+        let t = spawn run_t_test(ct)
+        outcomes[i] = t
+
+      # create "test" blocks and handle thread outputs
+      for t in outcomes:
+        let outcome = ^t  # wait for a thread to terminate
+        test outcome.desc:
+          evaluate(outcome.exception_msg, outcome.category, outcome.desc)
+    else:
+      echo "skipped test"
+
+  # net tests
+
+
+  type NetSocketTest = tuple[hostname: string, port: Port, category:Category, desc: string]
+  # badssl certs sometimes expire, set to false when that happens
+  when true:
+    const net_tests:array[0..3, NetSocketTest] = [
+      ("imap.gmail.com", 993.Port, good, "IMAP"),
+      ("wrong.host.badssl.com", 443.Port, bad, "wrong.host"),
+      ("captive-portal.badssl.com", 443.Port, bad, "captive-portal"),
+      ("expired.badssl.com", 443.Port, bad, "expired"),
+    ]
+  else:
+    const net_tests: array[0..0, NetSocketTest] = [
+      ("imap.gmail.com", 993.Port, good, "IMAP")
+    ]
+  # TODO: ("null.badssl.com", 443.Port, bad_broken, "null"),
+
+
+  suite "SSL certificate check - sockets":
+
+    for ct in net_tests:
+
+      test ct.desc:
+
+        var sock = newSocket()
+        var ctx = newContext()
+        ctx.wrapSocket(sock)
+        let exception_msg =
+          try:
+            sock.connect(ct.hostname, ct.port)
+            ""
+          except:
+            getCurrentExceptionMsg()
+
+        evaluate(exception_msg, ct.category, ct.desc)
diff --git a/tests/untestable/tpostgres.nim b/tests/untestable/tpostgres.nim
index d3397e53a..8b1378917 100644
--- a/tests/untestable/tpostgres.nim
+++ b/tests/untestable/tpostgres.nim
@@ -1,328 +1 @@
-import db_postgres, strutils
-
-
-let db = open("localhost", "dom", "", "test")
-db.exec(sql"DROP TABLE IF EXISTS myTable")
-db.exec(sql("""CREATE TABLE myTable (
-                  id integer PRIMARY KEY,
-                  name varchar(50) not null)"""))
-let name = "Dom"
-db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
-        name)
-doAssert db.getValue(sql"SELECT name FROM myTable") == name
-# Check issue #3513
-doAssert db.getValue(sql"SELECT name FROM myTable") == name
-
-
-# issue #3560
-proc addToDb(conn: DbConn, fileId: int, fileName: string): int64 =
-  result = conn.insertId(sql("INSERT into files (id, filename) VALUES (?, ?)"), fileId, fileName)
-
-db.exec(sql"DROP TABLE IF EXISTS files")
-db.exec(sql"DROP TABLE IF EXISTS fileobjects")
-db.exec(sql("""CREATE TABLE FILEOBJECTS(
-               ID             SERIAL PRIMARY KEY,
-               FILE_SIZE      INT,
-               MD5            CHAR(32)  NOT NULL UNIQUE
-            );"""))
-
-db.exec(sql("""CREATE TABLE FILES(
-               ID                  SERIAL PRIMARY KEY,
-               OBJECT_ID           INT,
-               FILENAME            TEXT NOT NULL,
-               URI                 TEXT,
-               SCHEME              CHAR(10),
-               PUBLIC              BOOLEAN DEFAULT FALSE,
-               CONSTRAINT fk1_fileobjs FOREIGN KEY (object_id)
-               REFERENCES fileobjects (id) MATCH SIMPLE
-               ON DELETE CASCADE
-            );"""))
-
-let f1 = db.addToDb(1, "hello.tmp")
-doAssert f1 == 1
-let f2 = db.addToDb(2, "hello2.tmp")
-doAssert f2 == 2
-
-# PreparedStmt vs. normal query
-try:
-  echo db.getValue(sql("select * from files where id = $1"), 1)
-  doAssert false, "Exception expected"
-except DbError:
-  let msg = getCurrentExceptionMsg().normalize
-  doAssert "expects" in msg
-  doAssert "?" in msg
-  doAssert "parameter substitution" in msg
-
-doAssert db.getValue(sql("select filename from files where id = ?"), 1) == "hello.tmp"
-
-var first = prepare(db, "one", sql"select filename from files where id = $1", 1)
-doAssert db.getValue(first, 1) == "hello.tmp"
-
-try:
-  var second = prepare(db, "two", sql"select filename from files where id = ?", 1)
-  doAssert false, "Exception expected"
-except:
-  let msg = getCurrentExceptionMsg().normalize
-  doAssert "expects" in msg
-  doAssert "$1" in msg
-  doAssert "parameter substitution" in msg
-
-# issue #3569
-db.exec(SqlQuery("DROP TABLE IF EXISTS tags"))
-db.exec(SqlQuery("CREATE TABLE tags(id serial UNIQUE, name varchar(255))"))
-
-for i in 1..10:
-  var name = "t" & $i
-  echo(name)
-  discard db.getRow(
-    SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name]))
-    
-# get column details
-db.exec(SqlQuery("DROP TABLE IF EXISTS dbtypes;"))
-db.exec(SqlQuery("DROP TYPE IF EXISTS custom_enum;"))
-db.exec(SqlQuery("CREATE TYPE custom_enum AS ENUM ('1', '2', '3');"))
-db.exec(SqlQuery("DROP TYPE IF EXISTS custom_composite;"))
-db.exec(SqlQuery("CREATE TYPE custom_composite AS (r double precision, i double precision);"))
-db.exec(SqlQuery("""CREATE TABLE dbtypes(
-                    id serial UNIQUE,
-                    bytea_col bytea,
-                    smallint_col smallint,
-                    integer_col integer,
-                    bigint_col bigint,
-                    decimal_col decimal,
-                    numeric_col numeric,
-                    real_col real,
-                    double_precision_col double precision,
-                    smallserial_col smallserial,
-                    serial_col serial,
-                    bigserial_col bigserial,
-                    money_col money,
-                    varchar_col varchar(10),
-                    character_col character(1),
-                    text_col text,
-                    timestamp_col timestamp,
-                    date_col date,
-                    time_col time,
-                    interval_col interval,
-                    bool_col boolean,
-                    custom_enum_col custom_enum,
-                    point_col point,
-                    line_col line,
-                    lseg_col lseg,
-                    box_col box,
-                    path_col path,
-                    polygon_col polygon,
-                    circle_col circle,
-                    cidr_col cidr,
-                    inet_col inet,
-                    macaddr_col macaddr,
-                    bit_col bit,
-                    varbit_col bit(3),
-                    tsvector_col tsvector,
-                    tsquery_col tsquery,
-                    uuid_col uuid,
-                    xml_col xml,
-                    json_col json,
-                    array_col integer[],
-                    custom_composite_col custom_composite,
-                    range_col int4range
-                    );"""))
-db.exec(SqlQuery("INSERT INTO dbtypes (id) VALUES(0);"))
-
-var dbCols : DbColumns = @[]
-for row in db.instantRows(dbCols, sql"SELECT * FROM dbtypes"):
-  doAssert len(dbCols) == 42
-
-doAssert dbCols[0].name == "id"
-doAssert dbCols[0].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[0].typ.name == "int4"
-doAssert dbCols[0].typ.size == 4
-
-doAssert dbCols[1].name == "bytea_col"
-doAssert dbCols[1].typ.kind == DbTypeKind.dbBlob
-doAssert dbCols[1].typ.name == "bytea"
-
-doAssert dbCols[2].name == "smallint_col"
-doAssert dbCols[2].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[2].typ.name == "int2"
-doAssert dbCols[2].typ.size == 2
-
-doAssert dbCols[3].name == "integer_col"
-doAssert dbCols[3].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[3].typ.name == "int4"
-doAssert dbCols[3].typ.size == 4
-
-doAssert dbCols[4].name == "bigint_col"
-doAssert dbCols[4].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[4].typ.name == "int8"
-doAssert dbCols[4].typ.size == 8
-
-doAssert dbCols[5].name == "decimal_col"
-doAssert dbCols[5].typ.kind == DbTypeKind.dbDecimal
-doAssert dbCols[5].typ.name == "numeric"
-
-doAssert dbCols[6].name == "numeric_col"
-doAssert dbCols[6].typ.kind == DbTypeKind.dbDecimal
-doAssert dbCols[6].typ.name == "numeric"
-
-doAssert dbCols[7].name == "real_col"
-doAssert dbCols[7].typ.kind == DbTypeKind.dbFloat
-doAssert dbCols[7].typ.name == "float4"
-
-doAssert dbCols[8].name == "double_precision_col"
-doAssert dbCols[8].typ.kind == DbTypeKind.dbFloat
-doAssert dbCols[8].typ.name == "float8"
-
-doAssert dbCols[9].name == "smallserial_col"
-doAssert dbCols[9].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[9].typ.name == "int2"
-
-doAssert dbCols[10].name == "serial_col"
-doAssert dbCols[10].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[10].typ.name == "int4"
-
-doAssert dbCols[11].name == "bigserial_col"
-doAssert dbCols[11].typ.kind == DbTypeKind.dbInt
-doAssert dbCols[11].typ.name == "int8"
-
-doAssert dbCols[12].name == "money_col"
-doAssert dbCols[12].typ.kind == DbTypeKind.dbDecimal
-doAssert dbCols[12].typ.name == "money"    
-    
-doAssert dbCols[13].name == "varchar_col"
-doAssert dbCols[13].typ.kind == DbTypeKind.dbVarchar
-doAssert dbCols[13].typ.name == "varchar"
-
-doAssert dbCols[14].name == "character_col"
-doAssert dbCols[14].typ.kind == DbTypeKind.dbFixedChar
-doAssert dbCols[14].typ.name == "bpchar"
-
-doAssert dbCols[15].name == "text_col"
-doAssert dbCols[15].typ.kind == DbTypeKind.dbVarchar
-doAssert dbCols[15].typ.name == "text"
-
-doAssert dbCols[16].name == "timestamp_col"
-doAssert dbCols[16].typ.kind == DbTypeKind.dbTimestamp
-doAssert dbCols[16].typ.name == "timestamp"
-
-doAssert dbCols[17].name == "date_col"
-doAssert dbCols[17].typ.kind == DbTypeKind.dbDate
-doAssert dbCols[17].typ.name == "date"
-
-doAssert dbCols[18].name == "time_col"
-doAssert dbCols[18].typ.kind == DbTypeKind.dbTime
-doAssert dbCols[18].typ.name == "time"
-
-doAssert dbCols[19].name == "interval_col"
-doAssert dbCols[19].typ.kind == DbTypeKind.dbTimeInterval
-doAssert dbCols[19].typ.name == "interval"
-
-doAssert dbCols[20].name == "bool_col"
-doAssert dbCols[20].typ.kind == DbTypeKind.dbBool
-doAssert dbCols[20].typ.name == "bool"
-
-doAssert dbCols[21].name == "custom_enum_col"
-doAssert dbCols[21].typ.kind == DbTypeKind.dbUnknown
-doAssert parseInt(dbCols[21].typ.name) > 0
-    
-doAssert dbCols[22].name == "point_col"
-doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint
-doAssert dbCols[22].typ.name == "point"    
-
-doAssert dbCols[23].name == "line_col"
-doAssert dbCols[23].typ.kind == DbTypeKind.dbLine
-doAssert dbCols[23].typ.name == "line"    
-
-doAssert dbCols[24].name == "lseg_col"
-doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg
-doAssert dbCols[24].typ.name == "lseg"    
-
-doAssert dbCols[25].name == "box_col"
-doAssert dbCols[25].typ.kind == DbTypeKind.dbBox
-doAssert dbCols[25].typ.name == "box"    
-
-doAssert dbCols[26].name == "path_col"
-doAssert dbCols[26].typ.kind == DbTypeKind.dbPath
-doAssert dbCols[26].typ.name == "path"    
-
-doAssert dbCols[27].name == "polygon_col"
-doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon
-doAssert dbCols[27].typ.name == "polygon"
-
-doAssert dbCols[28].name == "circle_col"
-doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle
-doAssert dbCols[28].typ.name == "circle"
-
-doAssert dbCols[29].name == "cidr_col"
-doAssert dbCols[29].typ.kind == DbTypeKind.dbInet
-doAssert dbCols[29].typ.name == "cidr"
-
-doAssert dbCols[30].name == "inet_col"
-doAssert dbCols[30].typ.kind == DbTypeKind.dbInet
-doAssert dbCols[30].typ.name == "inet"
-
-doAssert dbCols[31].name == "macaddr_col"
-doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress
-doAssert dbCols[31].typ.name == "macaddr"
-
-doAssert dbCols[32].name == "bit_col"
-doAssert dbCols[32].typ.kind == DbTypeKind.dbBit
-doAssert dbCols[32].typ.name == "bit"
-
-doAssert dbCols[33].name == "varbit_col"
-doAssert dbCols[33].typ.kind == DbTypeKind.dbBit
-doAssert dbCols[33].typ.name == "bit"
-
-doAssert dbCols[34].name == "tsvector_col"
-doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar
-doAssert dbCols[34].typ.name == "tsvector"
-
-doAssert dbCols[35].name == "tsquery_col"
-doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar
-doAssert dbCols[35].typ.name == "tsquery"
-
-doAssert dbCols[36].name == "uuid_col"
-doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar
-doAssert dbCols[36].typ.name == "uuid"
-
-doAssert dbCols[37].name == "xml_col"
-doAssert dbCols[37].typ.kind == DbTypeKind.dbXml
-doAssert dbCols[37].typ.name == "xml"
-
-doAssert dbCols[38].name == "json_col"
-doAssert dbCols[38].typ.kind == DbTypeKind.dbJson
-doAssert dbCols[38].typ.name == "json"
-
-doAssert dbCols[39].name == "array_col"
-doAssert dbCols[39].typ.kind == DbTypeKind.dbArray
-doAssert dbCols[39].typ.name == "int4[]"
-
-doAssert dbCols[40].name == "custom_composite_col"
-doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown
-doAssert parseInt(dbCols[40].typ.name) > 0
-
-doAssert dbCols[41].name == "range_col"
-doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite
-doAssert dbCols[41].typ.name == "int4range"
-
-# issue 6571
-db.exec(sql"DROP TABLE IF EXISTS DICTIONARY")
-db.exec(sql("""CREATE TABLE DICTIONARY(
-               id             SERIAL PRIMARY KEY,
-               entry      VARCHAR(1000) NOT NULL,
-               definition VARCHAR(4000) NOT NULL
-            );"""))
-var entry = "あっそ"
-var definition = "(int) (See ああそうそう) oh, really (uninterested)/oh yeah?/hmmmmm"
-discard db.getRow(
-  SqlQuery("INSERT INTO DICTIONARY(entry, definition) VALUES(\'$1\', \'$2\') RETURNING id" % [entry, definition]))
-doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition
-entry = "Format string entry"
-definition = "Format string definition"
-db.exec(sql"INSERT INTO DICTIONARY(entry, definition) VALUES (?, ?)", entry, definition)
-doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition
-
-echo("All tests succeeded!")
-
-db.close()