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.py64
-rw-r--r--tests/untestable/gdb/gdb_pretty_printer_test_program.nim89
-rwxr-xr-xtests/untestable/gdb/gdb_pretty_printer_test_run.sh13
-rw-r--r--tests/untestable/network/README.md8
-rw-r--r--tests/untestable/network/stdlib/tnet.nim16
-rw-r--r--tests/untestable/readme.markdown9
-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.nim1
-rw-r--r--tests/untestable/tssl.nim36
11 files changed, 576 insertions, 0 deletions
diff --git a/tests/untestable/gdb/gdb_pretty_printer_test.py b/tests/untestable/gdb/gdb_pretty_printer_test.py
new file mode 100644
index 000000000..aed0cfeb0
--- /dev/null
+++ b/tests/untestable/gdb/gdb_pretty_printer_test.py
@@ -0,0 +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("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)',
+  '{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) = {[4] = "four", [5] = "five", [6] = "six"}',
+  'Table(3, 8) = {["two"] = 2, ["three"] = 3, ["one"] = 1}',
+  '{a = 1, b = "some string"}',
+  '("hello", 42)'
+]
+
+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*)")
+
+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")
+    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:
+    rawArg = re.sub(noSuitableRegex, "", gdb.execute("info args", to_string = True))
+    raw = rawArg.split("=", 1)[-1].strip()
+  output = str(raw)
+
+  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_program.nim b/tests/untestable/gdb/gdb_pretty_printer_test_program.nim
new file mode 100644
index 000000000..163c99860
--- /dev/null
+++ b/tests/untestable/gdb/gdb_pretty_printer_test_program.nim
@@ -0,0 +1,89 @@
+
+
+import tables
+
+type
+  MyEnum = enum
+    meOne,
+    meTwo,
+    meThree,
+    meFour,
+
+  MyOtherEnum = enum
+    moOne,
+    moTwo,
+    moThree,
+    moFoure,
+  
+  MyObj = object
+    a*: int
+    b*: string
+
+var counter = 0
+
+proc myDebug[T](arg: T): void =
+  counter += 1
+
+proc testProc(): void =
+  var myEnum = meTwo
+  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
+  myString = $myEnum
+  myDebug(myString) #3
+  
+  var mySet = {meOne,meThree}
+  myDebug(mySet) #4
+
+  # for MyOtherEnum there is no NTI. This tests the fallback for the pretty printer.
+  var moEnum = moTwo
+  myDebug(moEnum) #5
+
+  var moSet = {moOne,moThree}
+  myDebug(moSet) #6
+
+  let myArray = [1,2,3,4,5]
+  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 tup = ("hello", 42)
+  myDebug(tup) # 16
+
+  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
new file mode 100755
index 000000000..411c68435
--- /dev/null
+++ b/tests/untestable/gdb/gdb_pretty_printer_test_run.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -e
+# Compile the test project with fresh debug information.
+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)
+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/network/README.md b/tests/untestable/network/README.md
new file mode 100644
index 000000000..173cf105f
--- /dev/null
+++ b/tests/untestable/network/README.md
@@ -0,0 +1,8 @@
+This directory contains tests that require networking and cannot be run in CI.
+
+The tests can be run manually during development using:
+```nim
+./koch tests cat untestable/network/stdlib
+```
+
+The directory structure mimics tests/
diff --git a/tests/untestable/network/stdlib/tnet.nim b/tests/untestable/network/stdlib/tnet.nim
new file mode 100644
index 000000000..cb0f38944
--- /dev/null
+++ b/tests/untestable/network/stdlib/tnet.nim
@@ -0,0 +1,16 @@
+discard """
+outputsub: ""
+"""
+
+import net, nativesockets
+import unittest
+
+suite "getPrimaryIPAddr":
+  test "localhost v4":
+    check getPrimaryIPAddr(parseIpAddress("127.0.0.1")) == parseIpAddress("127.0.0.1")
+
+  test "localhost v6":
+    check getPrimaryIPAddr(parseIpAddress("::1")) == parseIpAddress("::1")
+
+  test "v4":
+    check getPrimaryIPAddr() != parseIpAddress("127.0.0.1")
diff --git a/tests/untestable/readme.markdown b/tests/untestable/readme.markdown
new file mode 100644
index 000000000..de1ba9459
--- /dev/null
+++ b/tests/untestable/readme.markdown
@@ -0,0 +1,9 @@
+This directory contains integration tests which are not automatically executed
+for various reasons:
+- dependency on external services
+- dependency on files / configuration / state of the local host
+- tests that are extremely slow or require large amounts of memory or storage
+- tests that spawn local daemons
+
+Integration tests can become stale very quickly. Automated ./koch tests are
+strongly recommended.
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
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/tests/untestable/tpostgres.nim
@@ -0,0 +1 @@
+
diff --git a/tests/untestable/tssl.nim b/tests/untestable/tssl.nim
new file mode 100644
index 000000000..fca6385f8
--- /dev/null
+++ b/tests/untestable/tssl.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.
+#
+## Warning: this test performs external networking.
+##
+## Test with:
+## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
+## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim
+## The compilation is expected to succeed with any new/old version of OpenSSL,
+## both with dynamic and static linking.
+## The "howsmyssl" test is known to fail with OpenSSL < 1.1 due to insecure
+## cypher suites being used.
+
+import httpclient, os
+from strutils import contains, toHex
+
+from openssl import getOpenSSLVersion
+
+when true:
+  echo "version: 0x" & $getOpenSSLVersion().toHex()
+
+  let client = newHttpClient()
+  # hacky SSL check
+  const url = "https://www.howsmyssl.com"
+  let report = client.getContent(url)
+  if not report.contains(">Probably Okay</span>"):
+    let fn = getTempDir() / "sslreport.html"
+    echo "SSL CHECK ERROR, see " & fn
+    writeFile(fn, report)
+    quit(1)
+
+  echo "done"