bucket_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2018 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. package stack
  5. import (
  6. "bytes"
  7. "io/ioutil"
  8. "reflect"
  9. "strings"
  10. "testing"
  11. )
  12. func TestAggregateNotAggressive(t *testing.T) {
  13. // 2 goroutines with similar but not exact same signature.
  14. data := []string{
  15. "panic: runtime error: index out of range",
  16. "",
  17. "goroutine 6 [chan receive]:",
  18. "main.func·001(0x11000000, 2)",
  19. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  20. "",
  21. "goroutine 7 [chan receive]:",
  22. "main.func·001(0x21000000, 2)",
  23. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  24. "",
  25. }
  26. c, err := ParseDump(bytes.NewBufferString(strings.Join(data, "\n")), ioutil.Discard, false)
  27. if err != nil {
  28. t.Fatal(err)
  29. }
  30. actual := Aggregate(c.Goroutines, ExactLines)
  31. expected := []*Bucket{
  32. {
  33. Signature: Signature{
  34. State: "chan receive",
  35. Stack: Stack{
  36. Calls: []Call{
  37. {
  38. SrcPath: "/gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go",
  39. Line: 72,
  40. Func: Func{Raw: "main.func·001"},
  41. Args: Args{Values: []Arg{{Value: 0x11000000, Name: ""}, {Value: 2}}},
  42. },
  43. },
  44. },
  45. },
  46. IDs: []int{6},
  47. First: true,
  48. },
  49. {
  50. Signature: Signature{
  51. State: "chan receive",
  52. Stack: Stack{
  53. Calls: []Call{
  54. {
  55. SrcPath: "/gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go",
  56. Line: 72,
  57. Func: Func{Raw: "main.func·001"},
  58. Args: Args{Values: []Arg{{Value: 0x21000000, Name: "#1"}, {Value: 2}}},
  59. },
  60. },
  61. },
  62. },
  63. IDs: []int{7},
  64. },
  65. }
  66. compareBuckets(t, expected, actual)
  67. }
  68. func TestAggregateExactMatching(t *testing.T) {
  69. // 2 goroutines with the exact same signature.
  70. data := []string{
  71. "panic: runtime error: index out of range",
  72. "",
  73. "goroutine 6 [chan receive]:",
  74. "main.func·001()",
  75. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  76. "created by main.mainImpl",
  77. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:74 +0xeb",
  78. "",
  79. "goroutine 7 [chan receive]:",
  80. "main.func·001()",
  81. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  82. "created by main.mainImpl",
  83. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:74 +0xeb",
  84. "",
  85. }
  86. c, err := ParseDump(bytes.NewBufferString(strings.Join(data, "\n")), &bytes.Buffer{}, false)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. actual := Aggregate(c.Goroutines, ExactLines)
  91. expected := []*Bucket{
  92. {
  93. Signature: Signature{
  94. State: "chan receive",
  95. Stack: Stack{
  96. Calls: []Call{
  97. {
  98. SrcPath: "/gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go",
  99. Line: 72,
  100. Func: Func{Raw: "main.func·001"},
  101. },
  102. },
  103. },
  104. CreatedBy: Call{
  105. SrcPath: "/gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go",
  106. Line: 74,
  107. Func: Func{Raw: "main.mainImpl"},
  108. },
  109. },
  110. IDs: []int{6, 7},
  111. First: true,
  112. },
  113. }
  114. compareBuckets(t, expected, actual)
  115. }
  116. func TestAggregateAggressive(t *testing.T) {
  117. // 3 goroutines with similar signatures.
  118. data := []string{
  119. "panic: runtime error: index out of range",
  120. "",
  121. "goroutine 6 [chan receive, 10 minutes]:",
  122. "main.func·001(0x11000000, 2)",
  123. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  124. "",
  125. "goroutine 7 [chan receive, 50 minutes]:",
  126. "main.func·001(0x21000000, 2)",
  127. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  128. "",
  129. "goroutine 8 [chan receive, 100 minutes]:",
  130. "main.func·001(0x21000000, 2)",
  131. " /gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go:72 +0x49",
  132. "",
  133. }
  134. c, err := ParseDump(bytes.NewBufferString(strings.Join(data, "\n")), ioutil.Discard, false)
  135. if err != nil {
  136. t.Fatal(err)
  137. }
  138. actual := Aggregate(c.Goroutines, AnyPointer)
  139. expected := []*Bucket{
  140. {
  141. Signature: Signature{
  142. State: "chan receive",
  143. SleepMin: 10,
  144. SleepMax: 100,
  145. Stack: Stack{
  146. Calls: []Call{
  147. {
  148. SrcPath: "/gopath/src/notabug.org/themusicgod1/panicparse/stack/stack.go",
  149. Line: 72,
  150. Func: Func{Raw: "main.func·001"},
  151. Args: Args{Values: []Arg{{Value: 0x11000000, Name: "*"}, {Value: 2}}},
  152. },
  153. },
  154. },
  155. },
  156. IDs: []int{6, 7, 8},
  157. First: true,
  158. },
  159. }
  160. compareBuckets(t, expected, actual)
  161. }
  162. func compareBuckets(t *testing.T, expected, actual []*Bucket) {
  163. if len(expected) != len(actual) {
  164. t.Fatalf("Different []Bucket length:\n- %v\n- %v", expected, actual)
  165. }
  166. for i := range expected {
  167. if !reflect.DeepEqual(expected[i], actual[i]) {
  168. t.Fatalf("Different Bucket:\n- %#v\n- %#v", expected[i], actual[i])
  169. }
  170. }
  171. }