Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/traceback_test.go

Documentation: runtime

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

View as plain text