Source file
src/internal/trace/batchcursor_test.go
1
2
3
4
5 package trace
6
7 import (
8 "fmt"
9 "strings"
10 "testing"
11
12 "slices"
13 )
14
15 func TestHeap(t *testing.T) {
16 var heap []*batchCursor
17
18
19 checkHeap(t, heap)
20 heap = heapInsert(heap, makeBatchCursor(5))
21 checkHeap(t, heap)
22 for i := int64(-20); i < 20; i++ {
23 heap = heapInsert(heap, makeBatchCursor(i))
24 checkHeap(t, heap)
25 }
26
27
28 for i := range heap {
29 if heap[i].ev.time == 5 {
30 heap[i].ev.time = -21
31 heapUpdate(heap, i)
32 break
33 }
34 }
35 checkHeap(t, heap)
36 if heap[0].ev.time != -21 {
37 t.Fatalf("heap update failed, expected %d as heap min: %s", -21, heapDebugString(heap))
38 }
39
40
41 heap[0].ev.time = -22
42 heapUpdate(heap, 0)
43 checkHeap(t, heap)
44 if heap[0].ev.time != -22 {
45 t.Fatalf("heap update failed, expected %d as heap min: %s", -22, heapDebugString(heap))
46 }
47
48
49 heap[len(heap)-1].ev.time = 21
50 heapUpdate(heap, len(heap)-1)
51 checkHeap(t, heap)
52 if heap[len(heap)-1].ev.time != 21 {
53 t.Fatalf("heap update failed, expected %d as heap min: %s", 21, heapDebugString(heap))
54 }
55
56
57 heap[len(heap)-1].ev.time = 7
58 heapUpdate(heap, len(heap)-1)
59 checkHeap(t, heap)
60 if heap[len(heap)-1].ev.time == 21 {
61 t.Fatalf("heap update failed, unexpected %d as heap min: %s", 21, heapDebugString(heap))
62 }
63
64
65 for i := range heap {
66 if heap[i].ev.time == 5 {
67 heap = heapRemove(heap, i)
68 break
69 }
70 }
71 checkHeap(t, heap)
72 for i := range heap {
73 if heap[i].ev.time == 5 {
74 t.Fatalf("failed to remove heap elem with time %d: %s", 5, heapDebugString(heap))
75 }
76 }
77
78
79 heap = heapRemove(heap, len(heap)-1)
80 checkHeap(t, heap)
81
82
83 l := len(heap)
84 var removed []*batchCursor
85 for i := 0; i < l; i++ {
86 removed = append(removed, heap[0])
87 heap = heapRemove(heap, 0)
88 checkHeap(t, heap)
89 }
90 if !slices.IsSortedFunc(removed, (*batchCursor).compare) {
91 t.Fatalf("heap elements not removed in sorted order, got: %s", heapDebugString(removed))
92 }
93 }
94
95 func makeBatchCursor(v int64) *batchCursor {
96 return &batchCursor{ev: baseEvent{time: Time(v)}}
97 }
98
99 func heapDebugString(heap []*batchCursor) string {
100 var sb strings.Builder
101 fmt.Fprintf(&sb, "[")
102 for i := range heap {
103 if i != 0 {
104 fmt.Fprintf(&sb, ", ")
105 }
106 fmt.Fprintf(&sb, "%d", heap[i].ev.time)
107 }
108 fmt.Fprintf(&sb, "]")
109 return sb.String()
110 }
111
112 func checkHeap(t *testing.T, heap []*batchCursor) {
113 t.Helper()
114
115 for i := range heap {
116 if i == 0 {
117 continue
118 }
119 if heap[(i-1)/2].compare(heap[i]) > 0 {
120 t.Errorf("heap invariant not maintained between index %d and parent %d: %s", i, i/2, heapDebugString(heap))
121 }
122 }
123 if t.Failed() {
124 t.FailNow()
125 }
126 }
127
View as plain text