github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/runtime/traceback_test.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime_test 6 7 import ( 8 "bytes" 9 "runtime" 10 "testing" 11 ) 12 13 var testTracebackArgsBuf [1000]byte 14 15 func TestTracebackArgs(t *testing.T) { 16 tests := []struct { 17 fn func() int 18 expect string 19 }{ 20 // simple ints 21 { 22 func() int { return testTracebackArgs1(1, 2, 3, 4, 5) }, 23 "testTracebackArgs1(0x1, 0x2, 0x3, 0x4, 0x5)", 24 }, 25 // some aggregates 26 { 27 func() int { 28 return testTracebackArgs2(false, struct { 29 a, b, c int 30 x [2]int 31 }{1, 2, 3, [2]int{4, 5}}, [0]int{}, [3]byte{6, 7, 8}) 32 }, 33 "testTracebackArgs2(0x0, {0x1, 0x2, 0x3, {0x4, 0x5}}, {}, {0x6, 0x7, 0x8})", 34 }, 35 { 36 func() int { return testTracebackArgs3([3]byte{1, 2, 3}, 4, 5, 6, [3]byte{7, 8, 9}) }, 37 "testTracebackArgs3({0x1, 0x2, 0x3}, 0x4, 0x5, 0x6, {0x7, 0x8, 0x9})", 38 }, 39 // too deeply nested type 40 { 41 func() int { return testTracebackArgs4(false, [1][1][1][1][1][1][1][1][1][1]int{}) }, 42 "testTracebackArgs4(0x0, {{{{{...}}}}})", 43 }, 44 // a lot of zero-sized type 45 { 46 func() int { 47 z := [0]int{} 48 return testTracebackArgs5(false, struct { 49 x int 50 y [0]int 51 z [2][0]int 52 }{1, z, [2][0]int{}}, z, z, z, z, z, z, z, z, z, z, z, z) 53 }, 54 "testTracebackArgs5(0x0, {0x1, {}, {{}, {}}}, {}, {}, {}, {}, {}, ...)", 55 }, 56 57 // edge cases for ... 58 // no ... for 10 args 59 { 60 func() int { return testTracebackArgs6a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) }, 61 "testTracebackArgs6a(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa)", 62 }, 63 // has ... for 11 args 64 { 65 func() int { return testTracebackArgs6b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) }, 66 "testTracebackArgs6b(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...)", 67 }, 68 // no ... for aggregates with 10 words 69 { 70 func() int { return testTracebackArgs7a([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) }, 71 "testTracebackArgs7a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa})", 72 }, 73 // has ... for aggregates with 11 words 74 { 75 func() int { return testTracebackArgs7b([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) }, 76 "testTracebackArgs7b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...})", 77 }, 78 // no ... for aggregates, but with more args 79 { 80 func() int { return testTracebackArgs7c([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11) }, 81 "testTracebackArgs7c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}, ...)", 82 }, 83 // has ... for aggregates and also for more args 84 { 85 func() int { return testTracebackArgs7d([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 12) }, 86 "testTracebackArgs7d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...}, ...)", 87 }, 88 // nested aggregates, no ... 89 { 90 func() int { return testTracebackArgs8a(testArgsType8a{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}}) }, 91 "testTracebackArgs8a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}})", 92 }, 93 // nested aggregates, ... in inner but not outer 94 { 95 func() int { return testTracebackArgs8b(testArgsType8b{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}}) }, 96 "testTracebackArgs8b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}})", 97 }, 98 // nested aggregates, ... in outer but not inner 99 { 100 func() int { return testTracebackArgs8c(testArgsType8c{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}, 11}) }, 101 "testTracebackArgs8c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}, ...})", 102 }, 103 // nested aggregates, ... in both inner and outer 104 { 105 func() int { return testTracebackArgs8d(testArgsType8d{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}, 12}) }, 106 "testTracebackArgs8d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}, ...})", 107 }, 108 } 109 for _, test := range tests { 110 n := test.fn() 111 got := testTracebackArgsBuf[:n] 112 if !bytes.Contains(got, []byte(test.expect)) { 113 t.Errorf("traceback does not contain expected string: want %q, got\n%s", test.expect, got) 114 } 115 } 116 } 117 118 //go:noinline 119 func testTracebackArgs1(a, b, c, d, e int) int { 120 n := runtime.Stack(testTracebackArgsBuf[:], false) 121 if a < 0 { 122 // use in-reg args to keep them alive 123 return a + b + c + d + e 124 } 125 return n 126 } 127 128 //go:noinline 129 func testTracebackArgs2(a bool, b struct { 130 a, b, c int 131 x [2]int 132 }, _ [0]int, d [3]byte) int { 133 n := runtime.Stack(testTracebackArgsBuf[:], false) 134 if a { 135 // use in-reg args to keep them alive 136 return b.a + b.b + b.c + b.x[0] + b.x[1] + int(d[0]) + int(d[1]) + int(d[2]) 137 } 138 return n 139 140 } 141 142 //go:noinline 143 //go:registerparams 144 func testTracebackArgs3(x [3]byte, a, b, c int, y [3]byte) int { 145 n := runtime.Stack(testTracebackArgsBuf[:], false) 146 if a < 0 { 147 // use in-reg args to keep them alive 148 return int(x[0]) + int(x[1]) + int(x[2]) + a + b + c + int(y[0]) + int(y[1]) + int(y[2]) 149 } 150 return n 151 } 152 153 //go:noinline 154 func testTracebackArgs4(a bool, x [1][1][1][1][1][1][1][1][1][1]int) int { 155 n := runtime.Stack(testTracebackArgsBuf[:], false) 156 if a { 157 panic(x) // use args to keep them alive 158 } 159 return n 160 } 161 162 //go:noinline 163 func testTracebackArgs5(a bool, x struct { 164 x int 165 y [0]int 166 z [2][0]int 167 }, _, _, _, _, _, _, _, _, _, _, _, _ [0]int) int { 168 n := runtime.Stack(testTracebackArgsBuf[:], false) 169 if a { 170 panic(x) // use args to keep them alive 171 } 172 return n 173 } 174 175 //go:noinline 176 func testTracebackArgs6a(a, b, c, d, e, f, g, h, i, j int) int { 177 n := runtime.Stack(testTracebackArgsBuf[:], false) 178 if a < 0 { 179 // use in-reg args to keep them alive 180 return a + b + c + d + e + f + g + h + i + j 181 } 182 return n 183 } 184 185 //go:noinline 186 func testTracebackArgs6b(a, b, c, d, e, f, g, h, i, j, k int) int { 187 n := runtime.Stack(testTracebackArgsBuf[:], false) 188 if a < 0 { 189 // use in-reg args to keep them alive 190 return a + b + c + d + e + f + g + h + i + j + k 191 } 192 return n 193 } 194 195 //go:noinline 196 func testTracebackArgs7a(a [10]int) int { 197 n := runtime.Stack(testTracebackArgsBuf[:], false) 198 if a[0] < 0 { 199 // use in-reg args to keep them alive 200 return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] 201 } 202 return n 203 } 204 205 //go:noinline 206 func testTracebackArgs7b(a [11]int) int { 207 n := runtime.Stack(testTracebackArgsBuf[:], false) 208 if a[0] < 0 { 209 // use in-reg args to keep them alive 210 return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] 211 } 212 return n 213 } 214 215 //go:noinline 216 func testTracebackArgs7c(a [10]int, b int) int { 217 n := runtime.Stack(testTracebackArgsBuf[:], false) 218 if a[0] < 0 { 219 // use in-reg args to keep them alive 220 return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + b 221 } 222 return n 223 } 224 225 //go:noinline 226 func testTracebackArgs7d(a [11]int, b int) int { 227 n := runtime.Stack(testTracebackArgsBuf[:], false) 228 if a[0] < 0 { 229 // use in-reg args to keep them alive 230 return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + b 231 } 232 return n 233 } 234 235 type testArgsType8a struct { 236 a, b, c, d, e, f, g, h int 237 i [2]int 238 } 239 type testArgsType8b struct { 240 a, b, c, d, e, f, g, h int 241 i [3]int 242 } 243 type testArgsType8c struct { 244 a, b, c, d, e, f, g, h int 245 i [2]int 246 j int 247 } 248 type testArgsType8d struct { 249 a, b, c, d, e, f, g, h int 250 i [3]int 251 j int 252 } 253 254 //go:noinline 255 func testTracebackArgs8a(a testArgsType8a) int { 256 n := runtime.Stack(testTracebackArgsBuf[:], false) 257 if a.a < 0 { 258 // use in-reg args to keep them alive 259 return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] 260 } 261 return n 262 } 263 264 //go:noinline 265 func testTracebackArgs8b(a testArgsType8b) int { 266 n := runtime.Stack(testTracebackArgsBuf[:], false) 267 if a.a < 0 { 268 // use in-reg args to keep them alive 269 return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2] 270 } 271 return n 272 } 273 274 //go:noinline 275 func testTracebackArgs8c(a testArgsType8c) int { 276 n := runtime.Stack(testTracebackArgsBuf[:], false) 277 if a.a < 0 { 278 // use in-reg args to keep them alive 279 return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.j 280 } 281 return n 282 } 283 284 //go:noinline 285 func testTracebackArgs8d(a testArgsType8d) int { 286 n := runtime.Stack(testTracebackArgsBuf[:], false) 287 if a.a < 0 { 288 // use in-reg args to keep them alive 289 return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2] + a.j 290 } 291 return n 292 }