Skip to content

Commit 766956a

Browse files
committed
internal/panic: add tool to generate panics
The source code is designed to scale to a large number of panic styles. Eventually testing should be transformed to smoke tests that run this tool, this way this will test the whole toolchain behavior.
1 parent 7492cd3 commit 766956a

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed

internal/panic/main.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright 2017 Marc-Antoine Ruel. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
// Panic crashes in various ways.
6+
//
7+
// It is a tool to help test panicparse.
8+
package main
9+
10+
// To install, run:
11+
// go install github.com/maruel/panicparse/internal/panic
12+
// panic -help
13+
//
14+
// You can also run directly:
15+
// go run ./internal/panic/main.go str |& pp
16+
//
17+
// To add a new panic stack signature, add it to types type below, keeping the
18+
// list ordered by name. If you need utility functions, add it in the section
19+
// below. That's it!
20+
21+
import (
22+
"fmt"
23+
"io"
24+
"os"
25+
"sort"
26+
"sync"
27+
"time"
28+
)
29+
30+
// Utility functions.
31+
32+
func panicint(i int) {
33+
panic(i)
34+
}
35+
36+
func panicstr(a string) {
37+
panic(a)
38+
}
39+
40+
func panicslicestr(a []string) {
41+
panic(a)
42+
}
43+
44+
//
45+
46+
// types is all the supported types of panics.
47+
//
48+
// Keep the list sorted.
49+
var types = map[string]struct {
50+
desc string
51+
f func()
52+
}{
53+
"goroutine_1": {
54+
"panic in one goroutine",
55+
func() {
56+
go func() {
57+
panicint(42)
58+
}()
59+
time.Sleep(time.Minute)
60+
},
61+
},
62+
63+
"goroutine_100": {
64+
"start 100 goroutines before panicking",
65+
func() {
66+
var wg sync.WaitGroup
67+
for i := 0; i < 100; i++ {
68+
wg.Add(1)
69+
go func() {
70+
wg.Done()
71+
time.Sleep(time.Minute)
72+
}()
73+
}
74+
wg.Wait()
75+
panicint(42)
76+
},
77+
},
78+
79+
"int": {
80+
"panic(42)",
81+
func() {
82+
panicint(42)
83+
},
84+
},
85+
86+
"simple": {
87+
// This is not used for real, here for documentation.
88+
"skip the map for a shorter stack trace",
89+
func() {},
90+
},
91+
92+
"slice_str": {
93+
"panic([]string{\"allo\"}) with cap=2",
94+
func() {
95+
a := make([]string, 1, 2)
96+
a[0] = "allo"
97+
panicslicestr(a)
98+
},
99+
},
100+
101+
"str": {
102+
"panic(\"allo\")",
103+
func() {
104+
panicstr("allo")
105+
},
106+
},
107+
}
108+
109+
//
110+
111+
func main() {
112+
fmt.Printf("GOTRACEBACK=%s\n", os.Getenv("GOTRACEBACK"))
113+
if len(os.Args) == 2 {
114+
n := os.Args[1]
115+
if n == "simple" {
116+
// Since the map lookup creates another call stack entry, add a one-off
117+
// "simple" to test the very minimal case.
118+
panic("simple")
119+
}
120+
if f, ok := types[n]; ok {
121+
f.f()
122+
}
123+
}
124+
usage()
125+
}
126+
127+
func usage() {
128+
t := `usage: panic <way>
129+
130+
This tool is meant to be used with panicparse to test different parsing
131+
scenarios and ensure output on different version of the Go toolchain can be
132+
successfully parsed.
133+
134+
Set GOTRACEBACK before running this tool to see how it affects the panic output.
135+
136+
Select the way to panic:
137+
`
138+
io.WriteString(os.Stderr, t)
139+
names := make([]string, 0, len(types))
140+
m := 0
141+
for n := range types {
142+
names = append(names, n)
143+
if i := len(n); i > m {
144+
m = i
145+
}
146+
}
147+
sort.Strings(names)
148+
for _, n := range names {
149+
fmt.Fprintf(os.Stderr, "- %-*s %s\n", m, n, types[n].desc)
150+
}
151+
os.Exit(2)
152+
}

0 commit comments

Comments
 (0)