summary refs log tree commit diff stats
path: root/tests/exception
diff options
context:
space:
mode:
Diffstat (limited to 'tests/exception')
-rw-r--r--tests/exception/m21261.nim1
-rw-r--r--tests/exception/m22469.nim4
-rw-r--r--tests/exception/t13115.nim31
-rw-r--r--tests/exception/t18620.nim17
-rw-r--r--tests/exception/t20613.nim8
-rw-r--r--tests/exception/t21261.nim9
-rw-r--r--tests/exception/t22008.nim8
-rw-r--r--tests/exception/t22469.nim16
-rw-r--r--tests/exception/t9657.nim12
-rw-r--r--tests/exception/tcontinuexc.nim26
-rw-r--r--tests/exception/tcpp_imported_exc.nim136
-rw-r--r--tests/exception/tcpp_imported_exc2.nim10
-rw-r--r--tests/exception/tdefer1.nim35
-rw-r--r--tests/exception/tdont_overwrite_typename.nim30
-rw-r--r--tests/exception/testindexerroroutput.nims23
-rw-r--r--tests/exception/texcas.nim43
-rw-r--r--tests/exception/texception_inference.nim32
-rw-r--r--tests/exception/texceptionbreak.nim44
-rw-r--r--tests/exception/texceptions.nim130
-rw-r--r--tests/exception/texceptions2.nim130
-rw-r--r--tests/exception/texcpt1.nim45
-rw-r--r--tests/exception/texcsub.nim13
-rw-r--r--tests/exception/tfinally.nim62
-rw-r--r--tests/exception/tfinally2.nim28
-rw-r--r--tests/exception/tfinally3.nim27
-rw-r--r--tests/exception/tfinally4.nim73
-rw-r--r--tests/exception/tnestedreturn.nim40
-rw-r--r--tests/exception/tnestedreturn2.nim19
-rw-r--r--tests/exception/treraise.nim20
-rw-r--r--tests/exception/tsetexceptions.nim11
-rw-r--r--tests/exception/tshow_real_exception_name.nim28
-rw-r--r--tests/exception/tunhandledexc.nim23
-rw-r--r--tests/exception/twrongexc.nim8
33 files changed, 1142 insertions, 0 deletions
diff --git a/tests/exception/m21261.nim b/tests/exception/m21261.nim
new file mode 100644
index 000000000..11b12fb5b
--- /dev/null
+++ b/tests/exception/m21261.nim
@@ -0,0 +1 @@
+raise (ref Exception)(msg: "something")
\ No newline at end of file
diff --git a/tests/exception/m22469.nim b/tests/exception/m22469.nim
new file mode 100644
index 000000000..201698701
--- /dev/null
+++ b/tests/exception/m22469.nim
@@ -0,0 +1,4 @@
+# ModuleB
+echo "First top-level statement of ModuleB"
+echo high(int) + 1
+echo "ModuleB last statement"
\ No newline at end of file
diff --git a/tests/exception/t13115.nim b/tests/exception/t13115.nim
new file mode 100644
index 000000000..5db8f9107
--- /dev/null
+++ b/tests/exception/t13115.nim
@@ -0,0 +1,31 @@
+const msg = "This char is `" & '\0' & "` and works fine!"
+
+when defined nim_t13115:
+  # bug #13115
+  template fn =
+    raise newException(Exception, msg)
+  when defined nim_t13115_static:
+    static: fn()
+  fn()
+else:
+  import std/[osproc,strformat,os,strutils]
+  proc main =
+    const nim = getCurrentCompilerExe()
+    const file = currentSourcePath
+    for b in "c js cpp".split:
+      # save CI time by avoiding mostly redundant combinations as far as this bug is concerned
+      var opts = case b
+        of "c": @["", "-d:nim_t13115_static", "-d:danger", "-d:debug"]
+        of "js": @["", "-d:nim_t13115_static"]
+        else: @[""]
+
+      for opt in opts:
+        let cmd = fmt"{nim} r -b:{b} -d:nim_t13115 {opt} --hints:off {file}"
+        let (outp, exitCode) = execCmdEx(cmd)
+        when defined windows:
+          # `\0` not preserved on windows
+          doAssert "` and works fine!" in outp, cmd & "\n" & msg
+        else:
+          doAssert msg in outp, cmd & "\n" & msg
+        doAssert exitCode == 1
+  main()
diff --git a/tests/exception/t18620.nim b/tests/exception/t18620.nim
new file mode 100644
index 000000000..ee23f8bac
--- /dev/null
+++ b/tests/exception/t18620.nim
@@ -0,0 +1,17 @@
+discard """
+  matrix: "--gc:arc; --gc:refc"
+"""
+
+proc hello() =
+  raise newException(ValueError, "You are wrong")
+
+var flag = false
+
+try:
+  hello()
+except ValueError as e:
+  flag = true
+  doAssert len(getStackTraceEntries(e)) > 0
+  doAssert len(getStackTraceEntries(e)) > 0
+
+doAssert flag
diff --git a/tests/exception/t20613.nim b/tests/exception/t20613.nim
new file mode 100644
index 000000000..6edb69415
--- /dev/null
+++ b/tests/exception/t20613.nim
@@ -0,0 +1,8 @@
+discard """
+  matrix: "; --panics:on"
+"""
+
+func test =
+  if 0 > 10:
+    raiseAssert "hey"
+test()
diff --git a/tests/exception/t21261.nim b/tests/exception/t21261.nim
new file mode 100644
index 000000000..84817d854
--- /dev/null
+++ b/tests/exception/t21261.nim
@@ -0,0 +1,9 @@
+discard """
+  exitcode: 1
+  outputsub: '''
+m21261.nim(1)            m21261
+Error: unhandled exception: something [Exception]
+'''
+"""
+
+import m21261
\ No newline at end of file
diff --git a/tests/exception/t22008.nim b/tests/exception/t22008.nim
new file mode 100644
index 000000000..c0758e7b4
--- /dev/null
+++ b/tests/exception/t22008.nim
@@ -0,0 +1,8 @@
+template detect(v: untyped) =
+  doAssert typeof(v) is int
+
+detect:
+  try:
+    raise (ref ValueError)()
+  except ValueError:
+    42
\ No newline at end of file
diff --git a/tests/exception/t22469.nim b/tests/exception/t22469.nim
new file mode 100644
index 000000000..a76c74967
--- /dev/null
+++ b/tests/exception/t22469.nim
@@ -0,0 +1,16 @@
+discard """
+  exitcode: 1
+  output: '''
+First top-level statement of ModuleB
+m22469.nim(3)            m22469
+fatal.nim(53)            sysFatal
+Error: unhandled exception: over- or underflow [OverflowDefect]
+'''
+"""
+
+# bug #22469
+
+# ModuleA
+import m22469
+echo "ModuleA about to have exception"
+echo high(int) + 1
diff --git a/tests/exception/t9657.nim b/tests/exception/t9657.nim
new file mode 100644
index 000000000..6ac525a70
--- /dev/null
+++ b/tests/exception/t9657.nim
@@ -0,0 +1,12 @@
+discard """
+  action: run
+  exitcode: 1
+  targets: "c cpp"
+  disabled: "openbsd"
+  disabled: "netbsd"
+"""
+
+close stdmsg
+const m = "exception!"
+# see #10343 for details on this test
+discard writeBuffer(stdmsg, cstring(m), m.len)
diff --git a/tests/exception/tcontinuexc.nim b/tests/exception/tcontinuexc.nim
new file mode 100644
index 000000000..b7560a605
--- /dev/null
+++ b/tests/exception/tcontinuexc.nim
@@ -0,0 +1,26 @@
+discard """
+  outputsub: "ECcaught"
+  exitcode: "1"
+"""
+type
+  ESomething = object of Exception
+  ESomeOtherErr = object of Exception
+
+proc genErrors(s: string) =
+  if s == "error!":
+    raise newException(ESomething, "Test")
+  else:
+    raise newException(EsomeotherErr, "bla")
+
+try:
+  for i in 0..3:
+    try:
+      genErrors("error!")
+    except ESomething:
+      stdout.write("E")
+    stdout.write("C")
+    raise newException(EsomeotherErr, "bla")
+finally:
+  echo "caught"
+
+#OUT ECcaught
diff --git a/tests/exception/tcpp_imported_exc.nim b/tests/exception/tcpp_imported_exc.nim
new file mode 100644
index 000000000..55a58440f
--- /dev/null
+++ b/tests/exception/tcpp_imported_exc.nim
@@ -0,0 +1,136 @@
+discard """
+matrix: "--mm:refc"
+targets: "cpp"
+output: '''
+caught as std::exception
+expected
+finally1
+finally2
+finally2
+2
+expected
+finally 1
+finally 2
+expected
+cpp exception caught
+'''
+disabled: "windows" # pending bug #18011
+"""
+
+type
+  std_exception* {.importcpp: "std::exception", header: "<exception>".} = object
+  std_runtime_error* {.importcpp: "std::runtime_error", header: "<stdexcept>".} = object
+  std_string* {.importcpp: "std::string", header: "<string>".} = object
+
+proc constructStdString(s: cstring): std_string {.importcpp: "std::string(@)", constructor, header: "<string>".}
+
+proc constructRuntimeError(s: stdstring): std_runtime_error {.importcpp: "std::runtime_error(@)", constructor.}
+
+proc what(ex: std_runtime_error): cstring {.importcpp: "((char *)#.what())".}
+
+proc myexception =
+  raise constructRuntimeError(constructStdString("cpp_exception"))
+
+try:
+  myexception() # raise std::runtime_error
+except std_exception:
+  echo "caught as std::exception"
+  try:
+    raise constructStdString("x")
+  except std_exception:
+    echo "should not happen"
+  except:
+    echo "expected"
+
+doAssert(getCurrentException() == nil)
+
+proc earlyReturn =
+  try:
+    try:
+      myexception()
+    finally:
+      echo "finally1"
+  except:
+    return
+  finally:
+    echo "finally2"
+
+earlyReturn()
+doAssert(getCurrentException() == nil)
+
+
+try:
+  block blk1:
+    try:
+      raise newException(ValueError, "mmm")
+    except:
+      break blk1
+except:
+  echo "should not happen"
+finally:
+  echo "finally2"
+
+doAssert(getCurrentException() == nil)
+
+#--------------------------------------
+
+# raise by pointer and also generic type
+
+type
+  std_vector[T] {.importcpp"std::vector", header"<vector>".} = object
+
+proc newVector[T](len: int): ptr std_vector[T] {.importcpp: "new std::vector<'1>(@)".}
+proc deleteVector[T](v: ptr std_vector[T]) {.importcpp: "delete @; @ = NIM_NIL;".}
+proc len[T](v: std_vector[T]): uint {.importcpp: "size".}
+
+var v = newVector[int](2)
+try:
+  try:
+    try:
+      raise v
+    except ptr std_vector[int] as ex:
+      echo len(ex[])
+      raise newException(ValueError, "msg5")
+    except:
+      echo "should not happen"
+  finally:
+    deleteVector(v)
+except:
+  echo "expected"
+
+doAssert(v == nil)
+doAssert(getCurrentException() == nil)
+
+#--------------------------------------
+
+# mix of Nim and imported exceptions
+try:
+  try:
+    try:
+      raise newException(KeyError, "msg1")
+    except KeyError:
+      raise newException(ValueError, "msg2")
+    except:
+      echo "should not happen"
+    finally:
+      echo "finally 1"
+  except:
+    doAssert(getCurrentExceptionMsg() == "msg2")
+    raise constructStdString("std::string")
+  finally:
+    echo "finally 2"
+except:
+  echo "expected"
+
+doAssert(getCurrentException() == nil)
+
+try:
+  try:
+    myexception()
+  except std_runtime_error as ex:
+    echo "cpp exception caught"
+    raise newException(ValueError, "rewritten " & $ex.what())
+except:
+  doAssert(getCurrentExceptionMsg() == "rewritten cpp_exception")
+
+doAssert(getCurrentException() == nil)
diff --git a/tests/exception/tcpp_imported_exc2.nim b/tests/exception/tcpp_imported_exc2.nim
new file mode 100644
index 000000000..ff299ea3d
--- /dev/null
+++ b/tests/exception/tcpp_imported_exc2.nim
@@ -0,0 +1,10 @@
+discard """
+targets: "cpp"
+output: ""
+"""
+#issue #14369 case 2
+type RuntimeError {.requiresInit, importcpp: "std::runtime_error", header: "<stdexcept>".} = object
+
+proc initRuntimeError(a: cstring): RuntimeError {.importcpp: "std::runtime_error(@)", constructor.}
+try: raise initRuntimeError("foo2")
+except: discard
diff --git a/tests/exception/tdefer1.nim b/tests/exception/tdefer1.nim
new file mode 100644
index 000000000..db46bad27
--- /dev/null
+++ b/tests/exception/tdefer1.nim
@@ -0,0 +1,35 @@
+discard """
+  output: '''hi
+1
+hi
+2
+B
+A'''
+"""
+
+# bug #1742
+
+import strutils
+let x = try: parseInt("133a")
+        except: -1
+        finally: echo "hi"
+
+
+template atFuncEnd =
+  defer:
+    echo "A"
+  defer:
+    echo "B"
+
+template testB(): untyped =
+    let a = 0
+    defer: echo "hi"
+    a
+
+proc main =
+  atFuncEnd()
+  echo 1
+  let i = testB()
+  echo 2
+
+main()
diff --git a/tests/exception/tdont_overwrite_typename.nim b/tests/exception/tdont_overwrite_typename.nim
new file mode 100644
index 000000000..d6dca0990
--- /dev/null
+++ b/tests/exception/tdont_overwrite_typename.nim
@@ -0,0 +1,30 @@
+discard """
+  targets: "c cpp"
+  output: '''Check passed
+Check passed'''
+"""
+
+# bug #5628
+
+proc checkException(ex: ref Exception) =
+  doAssert(ex.name == cstring"ValueError")
+  doAssert(ex.msg == "SecondException")
+  doAssert(ex.parent != nil)
+  doAssert(ex.parent.name == cstring"KeyError")
+  doAssert(ex.parent.msg == "FirstException")
+  echo "Check passed"
+
+var e: ref Exception
+try:
+  try:
+    raise newException(KeyError, "FirstException")
+  except:
+    raise newException(ValueError, "SecondException", getCurrentException())
+except:
+  e = getCurrentException()
+
+try:
+  checkException(e) # passes here
+  raise e
+except ValueError:
+  checkException(getCurrentException()) # fails here
diff --git a/tests/exception/testindexerroroutput.nims b/tests/exception/testindexerroroutput.nims
new file mode 100644
index 000000000..e282f14b4
--- /dev/null
+++ b/tests/exception/testindexerroroutput.nims
@@ -0,0 +1,23 @@
+mode = ScriptMode.Verbose
+
+case paramStr(3):
+  of "test1":
+    #543
+    block:
+      let s = "abc"
+      discard s[len(s)]
+  of "test2":
+    #537
+    block:
+      var s = "abc"
+      s[len(s)] = 'd'
+  of "test3":
+    #588
+    block:
+      let arr = ['a', 'b', 'c']
+      discard arr[len(arr)]
+  of "test4":
+    #588
+    block:
+      var arr = ['a', 'b', 'c']
+      arr[len(arr)] = 'd'
diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim
new file mode 100644
index 000000000..ad6819f11
--- /dev/null
+++ b/tests/exception/texcas.nim
@@ -0,0 +1,43 @@
+discard """
+  targets: "c cpp"
+  output: '''
+Hello
+Hello
+'''
+"""
+proc test[T]() =
+  try:
+    raise newException(T, "Hello")
+  except T as foobar:
+    echo(foobar.msg)
+  doAssert(not declared(foobar))
+
+template testTemplate(excType: typedesc) =
+  try:
+    raise newException(excType, "Hello")
+  except excType as foobar:
+    echo(foobar.msg)
+  doAssert(not declared(foobar))
+
+proc test2() =
+  testTemplate(Exception)
+  doAssert(not declared(foobar))
+
+
+proc testTryAsExpr(i: int) =
+  let x = try: i    
+  except ValueError as ex:
+    echo(ex.msg)
+    -1
+
+test[Exception]()
+test2()
+testTryAsExpr(5)
+
+# see bug #7115
+doAssert(not compiles(
+  try: 
+    echo 1
+  except [KeyError as ex1, ValueError as ex2]:
+    echo 2
+))
diff --git a/tests/exception/texception_inference.nim b/tests/exception/texception_inference.nim
new file mode 100644
index 000000000..7dd01cca1
--- /dev/null
+++ b/tests/exception/texception_inference.nim
@@ -0,0 +1,32 @@
+discard """

+  output: '''good'''

+  cmd: "nim c --gc:orc -d:release $file"

+"""

+

+type

+  Raising[T, E] = object

+

+proc foo[T, Errors](x: proc (x: Raising[T, Errors])) {.raises: Errors.} =

+  discard

+

+proc callback(x: Raising[int, ValueError]) =

+  echo "callback"

+

+proc xy() {.raises: [ValueError].} =

+  foo callback

+

+proc x[E]() {.raises: [E, IOError].} =

+  raise newException(E, "text here")

+

+try:

+  x[ValueError]()

+except ValueError:

+  echo "good"

+

+proc callback2(x: Raising[int, IOError]) =

+  discard

+

+proc foo2[T, OtherErrors](x: proc(x: Raising[T, OtherErrors])) {.raises: [ValueError, OtherErrors].} =

+  discard

+

+foo2 callback2

diff --git a/tests/exception/texceptionbreak.nim b/tests/exception/texceptionbreak.nim
new file mode 100644
index 000000000..b8ce7eead
--- /dev/null
+++ b/tests/exception/texceptionbreak.nim
@@ -0,0 +1,44 @@
+discard """
+  output: "1\n2\n3\n4"
+"""
+
+# First variety
+try:
+  raise newException(OSError, "Problem")
+except OSError:
+  for y in [1, 2, 3]:
+    discard
+  try:
+    discard
+  except OSError:
+    discard
+echo "1"
+
+# Second Variety
+try:
+  raise newException(OSError, "Problem")
+except OSError:
+  for y in [1, 2, 3]:
+    discard
+  for y in [1, 2, 3]:
+    discard
+
+echo "2"
+
+# Third Variety
+try:
+  raise newException(OSError, "Problem")
+except OSError:
+  block label:
+    break label
+
+echo "3"
+
+# Fourth Variety
+block label:
+  try:
+    raise newException(OSError, "Problem")
+  except OSError:
+    break label
+
+echo "4"
diff --git a/tests/exception/texceptions.nim b/tests/exception/texceptions.nim
new file mode 100644
index 000000000..62d24c934
--- /dev/null
+++ b/tests/exception/texceptions.nim
@@ -0,0 +1,130 @@
+discard """
+  disabled: "windows" # no sigsetjmp() there
+  matrix: "-d:nimStdSetjmp; -d:nimSigSetjmp; -d:nimRawSetjmp; -d:nimBuiltinSetjmp"
+  output: '''
+
+BEFORE
+FINALLY
+
+BEFORE
+EXCEPT
+FINALLY
+RECOVER
+
+BEFORE
+EXCEPT: IOError: hi
+FINALLY
+'''
+"""
+
+echo ""
+
+proc no_exception =
+  try:
+    echo "BEFORE"
+
+  except:
+    echo "EXCEPT"
+    raise
+
+  finally:
+    echo "FINALLY"
+
+try: no_exception()
+except: echo "RECOVER"
+
+echo ""
+
+proc reraise_in_except =
+  try:
+    echo "BEFORE"
+    raise newException(IOError, "")
+
+  except IOError:
+    echo "EXCEPT"
+    raise
+
+  finally:
+    echo "FINALLY"
+
+try: reraise_in_except()
+except: echo "RECOVER"
+
+echo ""
+
+proc return_in_except =
+  try:
+    echo "BEFORE"
+    raise newException(IOError, "hi")
+
+  except:
+    echo "EXCEPT: ", getCurrentException().name, ": ", getCurrentExceptionMsg()
+    return
+
+  finally:
+    echo "FINALLY"
+
+try: return_in_except()
+except: echo "RECOVER"
+
+block: #10417
+  proc moo() {.noreturn.} = discard
+
+  let bar =
+    try:
+      1
+    except:
+      moo()
+
+  doAssert(bar == 1)
+
+# Make sure the VM handles the exceptions correctly
+block:
+  proc fun1(): seq[int] =
+    try:
+      try:
+        raise newException(ValueError, "xx")
+      except:
+        doAssert("xx" == getCurrentExceptionMsg())
+        raise newException(KeyError, "yy")
+    except:
+      doAssert("yy" == getCurrentExceptionMsg())
+      result.add(1212)
+    try:
+      try:
+        raise newException(AssertionDefect, "a")
+      finally:
+        result.add(42)
+    except AssertionDefect:
+      result.add(99)
+    finally:
+      result.add(10)
+    result.add(4)
+    result.add(0)
+    try:
+      result.add(1)
+    except KeyError:
+      result.add(-1)
+    except ValueError:
+      result.add(-1)
+    except IndexDefect:
+      result.add(2)
+    except:
+      result.add(3)
+
+    try:
+      try:
+        result.add(1)
+        return
+      except:
+        result.add(-1)
+      finally:
+        result.add(2)
+    except KeyError:
+      doAssert(false)
+    finally:
+      result.add(3)
+
+  let x1 = fun1()
+  const x2 = fun1()
+  doAssert(x1 == x2)
diff --git a/tests/exception/texceptions2.nim b/tests/exception/texceptions2.nim
new file mode 100644
index 000000000..97fd856a0
--- /dev/null
+++ b/tests/exception/texceptions2.nim
@@ -0,0 +1,130 @@
+discard """
+  disabled: "posix" # already covered by texceptions.nim
+  matrix: "-d:nimStdSetjmp; -d:nimRawSetjmp; -d:nimBuiltinSetjmp"
+  output: '''
+
+BEFORE
+FINALLY
+
+BEFORE
+EXCEPT
+FINALLY
+RECOVER
+
+BEFORE
+EXCEPT: IOError: hi
+FINALLY
+'''
+"""
+
+echo ""
+
+proc no_exception =
+  try:
+    echo "BEFORE"
+
+  except:
+    echo "EXCEPT"
+    raise
+
+  finally:
+    echo "FINALLY"
+
+try: no_exception()
+except: echo "RECOVER"
+
+echo ""
+
+proc reraise_in_except =
+  try:
+    echo "BEFORE"
+    raise newException(IOError, "")
+
+  except IOError:
+    echo "EXCEPT"
+    raise
+
+  finally:
+    echo "FINALLY"
+
+try: reraise_in_except()
+except: echo "RECOVER"
+
+echo ""
+
+proc return_in_except =
+  try:
+    echo "BEFORE"
+    raise newException(IOError, "hi")
+
+  except:
+    echo "EXCEPT: ", getCurrentException().name, ": ", getCurrentExceptionMsg()
+    return
+
+  finally:
+    echo "FINALLY"
+
+try: return_in_except()
+except: echo "RECOVER"
+
+block: #10417
+  proc moo() {.noreturn.} = discard
+
+  let bar =
+    try:
+      1
+    except:
+      moo()
+
+  doAssert(bar == 1)
+
+# Make sure the VM handles the exceptions correctly
+block:
+  proc fun1(): seq[int] =
+    try:
+      try:
+        raise newException(ValueError, "xx")
+      except:
+        doAssert("xx" == getCurrentExceptionMsg())
+        raise newException(KeyError, "yy")
+    except:
+      doAssert("yy" == getCurrentExceptionMsg())
+      result.add(1212)
+    try:
+      try:
+        raise newException(AssertionDefect, "a")
+      finally:
+        result.add(42)
+    except AssertionDefect:
+      result.add(99)
+    finally:
+      result.add(10)
+    result.add(4)
+    result.add(0)
+    try:
+      result.add(1)
+    except KeyError:
+      result.add(-1)
+    except ValueError:
+      result.add(-1)
+    except IndexDefect:
+      result.add(2)
+    except:
+      result.add(3)
+
+    try:
+      try:
+        result.add(1)
+        return
+      except:
+        result.add(-1)
+      finally:
+        result.add(2)
+    except KeyError:
+      doAssert(false)
+    finally:
+      result.add(3)
+
+  let x1 = fun1()
+  const x2 = fun1()
+  doAssert(x1 == x2)
diff --git a/tests/exception/texcpt1.nim b/tests/exception/texcpt1.nim
new file mode 100644
index 000000000..835f3610a
--- /dev/null
+++ b/tests/exception/texcpt1.nim
@@ -0,0 +1,45 @@
+discard """
+  outputsub: "-6"
+"""
+type
+  ESomething = object of Exception
+  ESomeOtherErr = object of Exception
+  ESomethingGen[T] = object of Exception
+  ESomethingGenRef[T] = ref object of Exception
+
+proc genErrors(s: string) =
+  if s == "error!":
+    raise newException(ESomething, "Test")
+  else:
+    raise newException(EsomeotherErr, "bla")
+
+proc raiseBla(): int =
+  try:
+    genErrors("errssor!")
+  except ESomething:
+    echo("Error happened")
+  except:
+    raise
+
+proc blah(): int =
+  try:
+    result = raiseBla()
+  except ESomeOtherErr:
+    result = -6
+
+echo blah()
+
+# Issue #7845, raise generic exception
+var x: ref ESomethingGen[int]
+new(x)
+try:
+  raise x
+except ESomethingGen[int] as e:
+  discard
+
+try:
+  raise new(ESomethingGenRef[int])
+except ESomethingGenRef[int] as e:
+  discard
+except:
+  discard
\ No newline at end of file
diff --git a/tests/exception/texcsub.nim b/tests/exception/texcsub.nim
new file mode 100644
index 000000000..463e95613
--- /dev/null
+++ b/tests/exception/texcsub.nim
@@ -0,0 +1,13 @@
+discard """
+  output: "caught!"
+"""
+# Test inheritance for exception matching:
+
+try:
+  raise newException(OSError, "dummy message")
+except Exception:
+  echo "caught!"
+except:
+  echo "wtf!?"
+
+#OUT caught!
diff --git a/tests/exception/tfinally.nim b/tests/exception/tfinally.nim
new file mode 100644
index 000000000..c5b1dd841
--- /dev/null
+++ b/tests/exception/tfinally.nim
@@ -0,0 +1,62 @@
+discard """
+  output: '''
+came
+here
+3
+msg1
+msg2
+finally2
+finally1
+-----------
+except1
+finally1
+except2
+finally2
+'''
+"""
+# Test return in try statement:
+
+proc main: int =
+  try:
+    try:
+      return 1
+    finally:
+      echo("came")
+      return 2
+  finally:
+    echo("here")
+    return 3
+
+echo main() #OUT came here 3
+
+#bug 7204
+proc nested_finally =
+  try:
+    raise newException(KeyError, "msg1")
+  except KeyError as ex:
+    echo ex.msg
+    try:
+      raise newException(ValueError, "msg2")
+    except:
+      echo getCurrentExceptionMsg()
+    finally:
+      echo "finally2"
+  finally:
+    echo "finally1"
+
+nested_finally()
+
+echo "-----------"
+#bug 7414
+try:
+  try:
+    raise newException(Exception, "Hello")
+  except:
+    echo "except1"
+    raise
+  finally:
+    echo "finally1"
+except:
+  echo "except2"
+finally:
+  echo "finally2"
diff --git a/tests/exception/tfinally2.nim b/tests/exception/tfinally2.nim
new file mode 100644
index 000000000..dae1a468a
--- /dev/null
+++ b/tests/exception/tfinally2.nim
@@ -0,0 +1,28 @@
+discard """
+output: '''
+A
+B
+C
+D
+'''
+"""
+# Test break in try statement:
+
+proc main: int =
+  try:
+    block AB:
+      try:
+        try:
+          break AB
+        finally:
+          echo("A")
+        echo("skipped")
+      finally:
+        block B:
+          echo("B")
+      echo("skipped")
+    echo("C")
+  finally:
+    echo("D")
+
+discard main()
diff --git a/tests/exception/tfinally3.nim b/tests/exception/tfinally3.nim
new file mode 100644
index 000000000..9053d397d
--- /dev/null
+++ b/tests/exception/tfinally3.nim
@@ -0,0 +1,27 @@
+discard """
+  outputsub: '''
+false
+Within finally->try
+'''
+  exitCode: 1
+"""
+# Test break in try statement:
+
+proc main: bool =
+  while true:
+    try:
+      return true
+    finally:
+      break
+  return false
+
+echo main() #OUT false
+
+# bug #5871
+try:
+  raise newException(Exception, "First")
+finally:
+  try:
+    raise newException(Exception, "Within finally->try")
+  except:
+    echo getCurrentExceptionMsg()
diff --git a/tests/exception/tfinally4.nim b/tests/exception/tfinally4.nim
new file mode 100644
index 000000000..a7dbbffef
--- /dev/null
+++ b/tests/exception/tfinally4.nim
@@ -0,0 +1,73 @@
+discard """
+  output: '''
+B1
+A1
+1
+B1
+B2
+catch
+A1
+1
+B1
+A1
+A2
+2
+B1
+B2
+catch
+A1
+A2
+0
+B1
+A1
+1
+B1
+B2
+A1
+1
+B1
+A1
+A2
+2
+B1
+B2
+A1
+A2
+3'''
+"""
+
+# More thorough test of return-in-finaly
+
+var raiseEx = true
+var returnA = true
+var returnB = false
+
+proc main: int =
+  try: #A
+    try: #B
+      if raiseEx:
+        raise newException(OSError, "")
+      return 3
+    finally: #B
+      echo "B1"
+      if returnB:
+        return 2
+      echo "B2"
+  except OSError: #A
+    echo "catch"
+  finally: #A
+    echo "A1"
+    if returnA:
+      return 1
+    echo "A2"
+
+for x in [true, false]:
+  for y in [true, false]:
+    for z in [true, false]:
+      # echo "raiseEx: " & $x
+      # echo "returnA: " & $y
+      # echo "returnB: " & $z
+      raiseEx = x
+      returnA = y
+      returnB = z
+      echo main()
diff --git a/tests/exception/tnestedreturn.nim b/tests/exception/tnestedreturn.nim
new file mode 100644
index 000000000..acb83d2c8
--- /dev/null
+++ b/tests/exception/tnestedreturn.nim
@@ -0,0 +1,40 @@
+discard """
+  targets: "c cpp"
+  output: "A\nB\nC\n"
+"""
+
+# Various tests of return nested in double try/except statements
+
+proc test1() =
+
+  defer: echo "A"
+
+  try:
+    raise newException(OSError, "Problem")
+  except OSError:
+    return
+
+test1()
+
+
+proc test2() =
+
+  defer: echo "B"
+
+  try:
+    return
+  except OSError:
+    discard
+
+test2()
+
+proc test3() =
+  try:
+    try:
+      raise newException(OSError, "Problem")
+    except OSError:
+      return
+  finally:
+    echo "C"
+
+test3()
diff --git a/tests/exception/tnestedreturn2.nim b/tests/exception/tnestedreturn2.nim
new file mode 100644
index 000000000..167d09b96
--- /dev/null
+++ b/tests/exception/tnestedreturn2.nim
@@ -0,0 +1,19 @@
+discard """
+  outputsub: "Error: unhandled exception: Problem [OSError]"
+  exitcode: "1"
+"""
+
+proc test4() =
+  try:
+    try:
+      raise newException(OSError, "Problem")
+    except OSError:
+      return
+  finally:
+    discard
+
+# Should cause unhandled exception error,
+# but could cause segmentation fault if
+# exceptions are not handled properly.
+test4()
+raise newException(OSError, "Problem")
diff --git a/tests/exception/treraise.nim b/tests/exception/treraise.nim
new file mode 100644
index 000000000..17a38aa53
--- /dev/null
+++ b/tests/exception/treraise.nim
@@ -0,0 +1,20 @@
+discard """
+  outputsub: "Error: unhandled exception: bla [ESomeOtherErr]"
+  exitcode: "1"
+"""
+type
+  ESomething = object of Exception
+  ESomeOtherErr = object of Exception
+
+proc genErrors(s: string) =
+  if s == "error!":
+    raise newException(ESomething, "Test")
+  else:
+    raise newException(EsomeotherErr, "bla")
+
+try:
+  genErrors("errssor!")
+except ESomething:
+  echo("Error happened")
+except:
+  raise
diff --git a/tests/exception/tsetexceptions.nim b/tests/exception/tsetexceptions.nim
new file mode 100644
index 000000000..0e353f43e
--- /dev/null
+++ b/tests/exception/tsetexceptions.nim
@@ -0,0 +1,11 @@
+discard """
+  targets: "c cpp js"
+  joinable: false
+"""
+
+# refs https://github.com/nim-lang/Nim/pull/18247#issuecomment-860877161
+
+let ex = newException(CatchableError, "test")
+setCurrentException(ex)
+doAssert getCurrentException().msg == ex.msg
+doAssert getCurrentExceptionMsg() == ex.msg
diff --git a/tests/exception/tshow_real_exception_name.nim b/tests/exception/tshow_real_exception_name.nim
new file mode 100644
index 000000000..1a708dbd6
--- /dev/null
+++ b/tests/exception/tshow_real_exception_name.nim
@@ -0,0 +1,28 @@
+discard """
+  outputsub: "CustomChildError"
+  exitcode: 1
+"""
+
+type
+  CustomError* = object of Exception
+  CustomChildError* = object of CustomError
+
+  FutureBase* = ref object of RootObj
+    error*: ref Exception
+
+  Future*[T] = ref object of FutureBase
+    v: T
+
+proc fail[T](future: Future[T], error: ref Exception) =
+  future.error = error
+
+proc w1(): Future[int] =
+  result = Future[int]()
+  result.fail(newException(CustomChildError, "abc"))
+
+proc main =
+  var fut = w1()
+  if true:
+    raise fut.error
+
+main()
diff --git a/tests/exception/tunhandledexc.nim b/tests/exception/tunhandledexc.nim
new file mode 100644
index 000000000..6ca311d38
--- /dev/null
+++ b/tests/exception/tunhandledexc.nim
@@ -0,0 +1,23 @@
+discard """
+  cmd: "nim $target -d:release $options $file"
+  outputsub: '''tunhandledexc.nim(15)    genErrors
+Error: unhandled exception: bla [ESomeOtherErr]'''
+  exitcode: "1"
+"""
+type
+  ESomething = object of Exception
+  ESomeOtherErr = object of Exception
+
+proc genErrors(s: string) =
+  if s == "error!":
+    raise newException(ESomething, "Test")
+  else:
+    raise newException(EsomeotherErr, "bla")
+
+when true:
+  try: discard except: discard
+
+  try:
+    genErrors("errssor!")
+  except ESomething:
+    echo("Error happened")
diff --git a/tests/exception/twrongexc.nim b/tests/exception/twrongexc.nim
new file mode 100644
index 000000000..d229c5749
--- /dev/null
+++ b/tests/exception/twrongexc.nim
@@ -0,0 +1,8 @@
+discard """
+  outputsub: "Error: unhandled exception:  [ValueError]"
+  exitcode: "1"
+"""
+try:
+  raise newException(ValueError, "")
+except OverflowDefect:
+  echo("Error caught")