stack_test.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright (c) 2023 Uber Technologies, Inc.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. package stacktrace
  21. import (
  22. "bytes"
  23. "strings"
  24. "testing"
  25. "github.com/stretchr/testify/assert"
  26. "github.com/stretchr/testify/require"
  27. )
  28. func TestTake(t *testing.T) {
  29. trace := Take(0)
  30. lines := strings.Split(trace, "\n")
  31. require.NotEmpty(t, lines, "Expected stacktrace to have at least one frame.")
  32. assert.Contains(
  33. t,
  34. lines[0],
  35. "go.uber.org/zap/internal/stacktrace.TestTake",
  36. "Expected stacktrace to start with the test.",
  37. )
  38. }
  39. func TestTakeWithSkip(t *testing.T) {
  40. trace := Take(1)
  41. lines := strings.Split(trace, "\n")
  42. require.NotEmpty(t, lines, "Expected stacktrace to have at least one frame.")
  43. assert.Contains(
  44. t,
  45. lines[0],
  46. "testing.",
  47. "Expected stacktrace to start with the test runner (skipping our own frame).",
  48. )
  49. }
  50. func TestTakeWithSkipInnerFunc(t *testing.T) {
  51. var trace string
  52. func() {
  53. trace = Take(2)
  54. }()
  55. lines := strings.Split(trace, "\n")
  56. require.NotEmpty(t, lines, "Expected stacktrace to have at least one frame.")
  57. assert.Contains(
  58. t,
  59. lines[0],
  60. "testing.",
  61. "Expected stacktrace to start with the test function (skipping the test function).",
  62. )
  63. }
  64. func TestTakeDeepStack(t *testing.T) {
  65. const (
  66. N = 500
  67. withStackDepthName = "go.uber.org/zap/internal/stacktrace.withStackDepth"
  68. )
  69. withStackDepth(N, func() {
  70. trace := Take(0)
  71. for found := 0; found < N; found++ {
  72. i := strings.Index(trace, withStackDepthName)
  73. if i < 0 {
  74. t.Fatalf(`expected %v occurrences of %q, found %d`,
  75. N, withStackDepthName, found)
  76. }
  77. trace = trace[i+len(withStackDepthName):]
  78. }
  79. })
  80. }
  81. func BenchmarkTake(b *testing.B) {
  82. for i := 0; i < b.N; i++ {
  83. Take(0)
  84. }
  85. }
  86. func withStackDepth(depth int, f func()) {
  87. var recurse func(rune) rune
  88. recurse = func(r rune) rune {
  89. if r > 0 {
  90. bytes.Map(recurse, []byte(string([]rune{r - 1})))
  91. } else {
  92. f()
  93. }
  94. return 0
  95. }
  96. recurse(rune(depth))
  97. }