Skip to content

Commit 3964879

Browse files
committed
[Test][Backtracing] Added tests for JSON backtrace output.
Check that we generate valid JSON crash reports. rdar://121430255
1 parent b4d4a27 commit 3964879

File tree

3 files changed

+419
-19
lines changed

3 files changed

+419
-19
lines changed

stdlib/public/libexec/swift-backtrace/JSON.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ extension SwiftBacktrace {
6161
"description": "\(escapeJSON(description))", \
6262
"faultAddress": "\(hex(target.faultAddress))", \
6363
"platform": "\(escapeJSON(target.images.platform))", \
64-
"architecture": "\(escapeJSON(architecture))",
64+
"architecture": "\(escapeJSON(architecture))"
6565
""")
6666

6767
var mentionedImages = Set<Int>()
@@ -233,7 +233,7 @@ extension SwiftBacktrace {
233233
"column": \(sourceLocation.column)
234234
""")
235235

236-
write(" } ")
236+
write(" }")
237237
}
238238
}
239239
write(" }")
@@ -267,7 +267,13 @@ extension SwiftBacktrace {
267267

268268
if args.threads! {
269269
write(#", "threads": [ "#)
270+
var first = true
270271
for (ndx, thread) in target.threads.enumerated() {
272+
if first {
273+
first = false
274+
} else {
275+
write(", ")
276+
}
271277
outputJSONThread(ndx: ndx, thread: thread)
272278
}
273279
write("]")

test/Backtracing/JSON.swift

Lines changed: 191 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/JSON
3-
// RUN: %target-codesign %t/JSON
4-
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no %target-run %t/JSON 2>&1 || true) | %FileCheck %s
2+
// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/Crash
3+
// RUN: %target-codesign %t/Crash
4+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash.json %target-run %t/Crash 2>&1 || true
5+
// RUN: %validate-json %t/crash.json | %FileCheck %s
6+
7+
8+
// Also check that we generate valid JSON with various different options set.
9+
10+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash2.json,threads=crashed %target-run %t/Crash 2>&1 || true
11+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash3.json,registers=all %target-run %t/Crash 2>&1 || true
12+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash4.json,sanitize=yes %target-run %t/Crash 2>&1 || true
13+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash5.json,images=none %target-run %t/Crash 2>&1 || true
14+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash6.json,images=all %target-run %t/Crash 2>&1 || true
15+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash7.json,symbolicate=off %target-run %t/Crash 2>&1 || true
16+
// RUN: env SWIFT_BACKTRACE=enable=yes,cache=no,format=json,output-to=%t/crash8.json,demangle=no %target-run %t/Crash 2>&1 || true
17+
// RUN: %validate-json %t/crash2.json
18+
// RUN: %validate-json %t/crash3.json
19+
// RUN: %validate-json %t/crash4.json
20+
// RUN: %validate-json %t/crash5.json
21+
// RUN: %validate-json %t/crash6.json
22+
// RUN: %validate-json %t/crash7.json
23+
// RUN: %validate-json %t/crash8.json
24+
525

626
// UNSUPPORTED: use_os_stdlib
727
// UNSUPPORTED: back_deployment_runtime
@@ -33,27 +53,181 @@ func level5() {
3353
}
3454

3555
@main
36-
struct JSON {
56+
struct Crash {
3757
static func main() {
3858
level1()
3959
}
4060
}
4161

42-
// CHECK: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 ***
62+
// CHECK: {
63+
64+
// JSON logs start with an ISO timestamp
65+
66+
// CHECK-NEXT: "timestamp": "{{[0-9]{4,}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{6}Z}}",
67+
68+
69+
// Then a tag identifying this as a crash report
70+
71+
// CHECK-NEXT: "kind": "crashReport",
72+
73+
74+
// This is followed by a description and the fault address
75+
76+
// CHECK-NEXT: "description": "Bad pointer dereference",
77+
// CHECK-NEXT: "faultAddress": "0x{{0+}}4",
78+
79+
80+
// And then by the platform and architecture
81+
// CHECK-NEXT: "platform": "{{.*}}",
82+
// CHECK-NEXT: "architecture": "{{.*}}",
83+
84+
85+
// And then a list of threads
86+
87+
// CHECK-NEXT: "threads": [
88+
// CHECK-NEXT: {
89+
// CHECK-NEXT: "crashed": true,
90+
// CHECK-NEXT: "frames": [
91+
// CHECK-NEXT: {
92+
// CHECK-NEXT: "kind": "programCounter",
93+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
94+
// CHECK-NEXT: "symbol": "{{_?}}$s5Crash6level5yyF",
95+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
96+
// CHECK-NEXT: "description": "level5() + [[OFFSET]]",
97+
// CHECK-NEXT: "image": "Crash",
98+
// CHECK-NEXT: "sourceLocation": {
99+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
100+
// CHECK-NEXT: "line": 52,
101+
// CHECK-NEXT: "column": 15
102+
// CHECK-NEXT: }
103+
// CHECK-NEXT: },
104+
// CHECK-NEXT: {
105+
// CHECK-NEXT: "kind": "returnAddress",
106+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
107+
// CHECK-NEXT: "symbol": "{{_?}}$s5Crash6level4yyF",
108+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
109+
// CHECK-NEXT: "description": "level4() + [[OFFSET]]",
110+
// CHECK-NEXT: "image": "Crash",
111+
// CHECK-NEXT: "sourceLocation": {
112+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
113+
// CHECK-NEXT: "line": 46,
114+
// CHECK-NEXT: "column": 3
115+
// CHECK-NEXT: }
116+
// CHECK-NEXT: },
117+
// CHECK-NEXT: {
118+
// CHECK-NEXT: "kind": "returnAddress",
119+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
120+
// CHECK-NEXT: "symbol": "{{_?}}$s5Crash6level3yyF",
121+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
122+
// CHECK-NEXT: "description": "level3() + [[OFFSET]]",
123+
// CHECK-NEXT: "image": "Crash",
124+
// CHECK-NEXT: "sourceLocation": {
125+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
126+
// CHECK-NEXT: "line": 42,
127+
// CHECK-NEXT: "column": 3
128+
// CHECK-NEXT: }
129+
// CHECK-NEXT: },
130+
// CHECK-NEXT: {
131+
// CHECK-NEXT: "kind": "returnAddress",
132+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
133+
// CHECK-NEXT: "symbol": "{{_?}}$s5Crash6level2yyF",
134+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
135+
// CHECK-NEXT: "description": "level2() + [[OFFSET]]",
136+
// CHECK-NEXT: "image": "Crash",
137+
// CHECK-NEXT: "sourceLocation": {
138+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
139+
// CHECK-NEXT: "line": 38,
140+
// CHECK-NEXT: "column": 3
141+
// CHECK-NEXT: }
142+
// CHECK-NEXT: },
143+
// CHECK-NEXT: {
144+
// CHECK-NEXT: "kind": "returnAddress",
145+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
146+
// CHECK-NEXT: "symbol": "{{_?}}$s5Crash6level1yyF",
147+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
148+
// CHECK-NEXT: "description": "level1() + [[OFFSET]]",
149+
// CHECK-NEXT: "image": "Crash",
150+
// CHECK-NEXT: "sourceLocation": {
151+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
152+
// CHECK-NEXT: "line": 34,
153+
// CHECK-NEXT: "column": 3
154+
// CHECK-NEXT: }
155+
// CHECK-NEXT: },
156+
// CHECK-NEXT: {
157+
// CHECK-NEXT: "kind": "returnAddress",
158+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
159+
// CHECK-NEXT: "symbol": "{{_?}}$s5CrashAAV4mainyyFZ",
160+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
161+
// CHECK-NEXT: "description": "static Crash.main() + [[OFFSET]]",
162+
// CHECK-NEXT: "image": "Crash",
163+
// CHECK-NEXT: "sourceLocation": {
164+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
165+
// CHECK-NEXT: "line": 58,
166+
// CHECK-NEXT: "column": 5
167+
// CHECK-NEXT: }
168+
// CHECK-NEXT: },
169+
// CHECK-NEXT: {
170+
// CHECK-NEXT: "kind": "returnAddress",
171+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
172+
// CHECK-NEXT: "system": true,
173+
// CHECK-NEXT: "symbol": "{{_?}}$s5CrashAAV5$mainyyFZ",
174+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
175+
// CHECK-NEXT: "description": "static Crash.$main() + [[OFFSET]]",
176+
// CHECK-NEXT: "image": "Crash",
177+
// CHECK-NEXT: "sourceLocation": {
178+
// CHECK-NEXT: "file": "{{/?}}<compiler-generated>",
179+
// CHECK-NEXT: "line": 0,
180+
// CHECK-NEXT: "column": 0
181+
// CHECK-NEXT: }
182+
// CHECK-NEXT: },
183+
// CHECK-NEXT: {
184+
// CHECK-NEXT: "kind": "returnAddress",
185+
// CHECK-NEXT: "address": "0x{{[0-9a-f]+}}",
186+
// CHECK-NEXT: "system": true,
187+
// CHECK-NEXT: "symbol": "{{_?main}}",
188+
// CHECK-NEXT: "offset": [[OFFSET:[0-9]+]],
189+
// CHECK-NEXT: "description": "main + [[OFFSET]]",
190+
// CHECK-NEXT: "image": "Crash",
191+
// CHECK-NEXT: "sourceLocation": {
192+
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
193+
// CHECK-NEXT: "line": 0,
194+
// CHECK-NEXT: "column": 0
195+
// CHECK-NEXT: }
196+
// CHECK-NEXT: },
197+
198+
// More frames here, but they're system specific
199+
200+
// CHECK: ]
201+
// CHECK: }
202+
// CHECK-NEXT: ],
203+
// CHECK-NEXT: "registers": {
204+
// CHECK-NEXT: "{{.*}}": "0x{{[0-9a-f]+}}",
205+
206+
// More registers here, again, system specific
207+
208+
// CHECK: },
209+
// CHECK-NEXT: "capturedMemory": {
210+
// CHECK-NEXT: "0x{{[[0-9a-f]+}}": "{{([0-9a-f][0-9a-f])+}}",
211+
212+
// More captures here, but system specific
213+
214+
// CHECK: },
215+
// CHECK-NEXT: "omittedImages": {{[0-9]+}},
216+
// CHECK-NEXT: "images": [
217+
// CHECK-NEXT: {
43218

44-
// CHECK: Thread 0 {{(".*" )?}}crashed:
219+
// Maybe multiple images before this one
45220

46-
// CHECK: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in JSON at {{.*}}/JSON.swift:42:15
47-
// CHECK-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in JSON at {{.*}}/JSON.swift:36:3
48-
// CHECK-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in JSON at {{.*}}/JSON.swift:32:3
49-
// CHECK-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in JSON at {{.*}}/JSON.swift:28:3
50-
// CHECK-NEXT: 4 [ra] 0x{{[0-9a-f]+}} level1() + {{[0-9]+}} in JSON at {{.*}}/JSON.swift:24:3
51-
// CHECK-NEXT: 5 [ra] 0x{{[0-9a-f]+}} static JSON.main() + {{[0-9]+}} in JSON at {{.*}}/JSON.swift:48:5
52-
// CHECK-NEXT: 6 [ra] [system] 0x{{[0-9a-f]+}} static JSON.$main() + {{[0-9]+}} in JSON at {{.*}}/<compiler-generated>
53-
// CHECK-NEXT: 7 [ra] [system] 0x{{[0-9a-f]+}} main + {{[0-9]+}} in JSON at {{.*}}/JSON.swift
221+
// CHECK: "name": "Crash",
222+
// CHECK-NEXT: "buildId": "{{([0-9a-f][0-9a-f])+}}",
223+
// CHECK-NEXT: "path": "{{.*}}/Crash",
224+
// CHECK-NEXT: "baseAddress": "0x{{[0-9a-f]+}}",
225+
// CHECK-NEXT: "endOfText": "0x{{[0-9a-f]+}}"
226+
// CHECK-NEXT: }
54227

55-
// CHECK: Registers:
228+
// Maybe multiple images after this one
56229

57-
// CHECK: Images ({{[0-9]+}} omitted):
230+
// CHECK: ],
231+
// CHECK-NEXT: "backtraceTime": {{[0-9]+(\.[0-9]+)?}}
58232

59-
// CHECK: {{0x[0-9a-f]+}}–{{0x[0-9a-f]+}}{{ +}}{{([0-9a-f]+|<no build ID>)}}{{ +}}JSON{{ +}}{{.*}}/JSON
233+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)