summary refs log tree commit diff stats
path: root/tests/async/tasync_traceback.nim
blob: 9f787929b33a07b4095f0ca0779db7d4cff8f89c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
discard """
  exitcode: 0
  disabled: "windows"
  output: "Matched"
"""
import asyncdispatch, strutils

# Tests to ensure our exception trace backs are friendly.

# --- Simple test. ---
#
# What does this look like when it's synchronous?
#
# tasync_traceback.nim(23) tasync_traceback
# tasync_traceback.nim(21) a
# tasync_traceback.nim(18) b
# Error: unhandled exception: b failure [OSError]
#
# Good (not quite ideal, but gotta work within constraints) traceback,
# when exception is unhandled:
#
# <traceback for the unhandled exception>
# <very much a bunch of noise>
# <would be ideal to customise this>
# <(the code responsible is in excpt:raiseExceptionAux)>
# Error: unhandled exception: b failure
# ===============
# Async traceback
# ===============
#
# tasync_traceback.nim(23) tasync_traceback
#
# tasync_traceback.nim(21) a
# tasync_traceback.nim(18) b

var result = ""

proc b(): Future[int] {.async.} =
  if true:
    raise newException(OSError, "b failure")

proc a(): Future[int] {.async.} =
  return await b()

let aFut = a()
try:
  discard waitFor aFut
except Exception as exc:
  result.add(exc.msg & "\n")
result.add("\n")

# From #6803
proc bar(): Future[string] {.async.} =
  await sleepAsync(100)
  if true:
    raise newException(OSError, "bar failure")

proc foo(): Future[string] {.async.} = return await bar()

try:
  result.add(waitFor(foo()) & "\n")
except Exception as exc:
  result.add(exc.msg & "\n")
result.add("\n")

# Use re to parse the result
import re
const expected = """
b failure
Async traceback:
  tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
  asyncmacro\.nim\(\d+?\)\s+?a
  asyncmacro\.nim\(\d+?\)\s+?aNimAsyncContinue
    ## Resumes an async procedure
  tasync_traceback\.nim\(\d+?\)\s+?aIter
  asyncmacro\.nim\(\d+?\)\s+?b
  asyncmacro\.nim\(\d+?\)\s+?bNimAsyncContinue
    ## Resumes an async procedure
  tasync_traceback\.nim\(\d+?\)\s+?bIter
  #\[
    tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
    asyncmacro\.nim\(\d+?\)\s+?a
    asyncmacro\.nim\(\d+?\)\s+?aNimAsyncContinue
      ## Resumes an async procedure
    asyncmacro\.nim\(\d+?\)\s+?aIter
    asyncfutures\.nim\(\d+?\)\s+?read
  \]#
Exception message: b failure
Exception type:

bar failure
Async traceback:
  tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
  asyncdispatch\.nim\(\d+?\)\s+?waitFor
  asyncdispatch\.nim\(\d+?\)\s+?poll
    ## Processes asynchronous completion events
  asyncdispatch\.nim\(\d+?\)\s+?runOnce
  asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks
    ## Executes pending callbacks
  asyncmacro\.nim\(\d+?\)\s+?barNimAsyncContinue
    ## Resumes an async procedure
  tasync_traceback\.nim\(\d+?\)\s+?barIter
  #\[
    tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
    asyncdispatch\.nim\(\d+?\)\s+?waitFor
    asyncdispatch\.nim\(\d+?\)\s+?poll
      ## Processes asynchronous completion events
    asyncdispatch\.nim\(\d+?\)\s+?runOnce
    asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks
      ## Executes pending callbacks
    asyncmacro\.nim\(\d+?\)\s+?fooNimAsyncContinue
      ## Resumes an async procedure
    asyncmacro\.nim\(\d+?\)\s+?fooIter
    asyncfutures\.nim\(\d+?\)\s+?read
  \]#
Exception message: bar failure
Exception type:
"""

# TODO: is asyncmacro good enough location for fooIter traceback/debugging? just put the callsite info for all?

let resLines = splitLines(result.strip)
let expLines = splitLines(expected.strip)

if resLines.len != expLines.len:
  echo("Not matched! Wrong number of lines!")
  echo expLines.len
  echo resLines.len
  echo("Expected: -----------")
  echo expected
  echo("Gotten: -------------")
  echo result
  echo("---------------------")
  quit(QuitFailure)

var ok = true
for i in 0 ..< resLines.len:
  if not resLines[i].match(re(expLines[i])):
    echo "Not matched! Line ", i + 1
    echo "Expected:"
    echo expLines[i]
    echo "Actual:"
    echo resLines[i]
    ok = false

if ok:
  echo("Matched")
else:
  quit(QuitFailure)