|
| 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