golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/trace/batchcursor_test.go (about) 1 // Copyright 2023 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 // Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. 6 7 //go:build go1.21 8 9 package trace 10 11 import ( 12 "fmt" 13 "strings" 14 "testing" 15 16 "slices" 17 ) 18 19 func TestHeap(t *testing.T) { 20 var heap []*batchCursor 21 22 // Insert a bunch of values into the heap. 23 checkHeap(t, heap) 24 heap = heapInsert(heap, makeBatchCursor(5)) 25 checkHeap(t, heap) 26 for i := int64(-20); i < 20; i++ { 27 heap = heapInsert(heap, makeBatchCursor(i)) 28 checkHeap(t, heap) 29 } 30 31 // Update an element in the middle to be the new minimum. 32 for i := range heap { 33 if heap[i].ev.time == 5 { 34 heap[i].ev.time = -21 35 heapUpdate(heap, i) 36 break 37 } 38 } 39 checkHeap(t, heap) 40 if heap[0].ev.time != -21 { 41 t.Fatalf("heap update failed, expected %d as heap min: %s", -21, heapDebugString(heap)) 42 } 43 44 // Update the minimum element to be smaller. There should be no change. 45 heap[0].ev.time = -22 46 heapUpdate(heap, 0) 47 checkHeap(t, heap) 48 if heap[0].ev.time != -22 { 49 t.Fatalf("heap update failed, expected %d as heap min: %s", -22, heapDebugString(heap)) 50 } 51 52 // Update the last element to be larger. There should be no change. 53 heap[len(heap)-1].ev.time = 21 54 heapUpdate(heap, len(heap)-1) 55 checkHeap(t, heap) 56 if heap[len(heap)-1].ev.time != 21 { 57 t.Fatalf("heap update failed, expected %d as heap min: %s", 21, heapDebugString(heap)) 58 } 59 60 // Update the last element to be smaller. 61 heap[len(heap)-1].ev.time = 7 62 heapUpdate(heap, len(heap)-1) 63 checkHeap(t, heap) 64 if heap[len(heap)-1].ev.time == 21 { 65 t.Fatalf("heap update failed, unexpected %d as heap min: %s", 21, heapDebugString(heap)) 66 } 67 68 // Remove an element in the middle. 69 for i := range heap { 70 if heap[i].ev.time == 5 { 71 heap = heapRemove(heap, i) 72 break 73 } 74 } 75 checkHeap(t, heap) 76 for i := range heap { 77 if heap[i].ev.time == 5 { 78 t.Fatalf("failed to remove heap elem with time %d: %s", 5, heapDebugString(heap)) 79 } 80 } 81 82 // Remove tail. 83 heap = heapRemove(heap, len(heap)-1) 84 checkHeap(t, heap) 85 86 // Remove from the head, and make sure the result is sorted. 87 l := len(heap) 88 var removed []*batchCursor 89 for i := 0; i < l; i++ { 90 removed = append(removed, heap[0]) 91 heap = heapRemove(heap, 0) 92 checkHeap(t, heap) 93 } 94 if !slices.IsSortedFunc(removed, (*batchCursor).compare) { 95 t.Fatalf("heap elements not removed in sorted order, got: %s", heapDebugString(removed)) 96 } 97 } 98 99 func makeBatchCursor(v int64) *batchCursor { 100 return &batchCursor{ev: baseEvent{time: Time(v)}} 101 } 102 103 func heapDebugString(heap []*batchCursor) string { 104 var sb strings.Builder 105 fmt.Fprintf(&sb, "[") 106 for i := range heap { 107 if i != 0 { 108 fmt.Fprintf(&sb, ", ") 109 } 110 fmt.Fprintf(&sb, "%d", heap[i].ev.time) 111 } 112 fmt.Fprintf(&sb, "]") 113 return sb.String() 114 } 115 116 func checkHeap(t *testing.T, heap []*batchCursor) { 117 t.Helper() 118 119 for i := range heap { 120 if i == 0 { 121 continue 122 } 123 if heap[(i-1)/2].compare(heap[i]) > 0 { 124 t.Errorf("heap invariant not maintained between index %d and parent %d: %s", i, i/2, heapDebugString(heap)) 125 } 126 } 127 if t.Failed() { 128 t.FailNow() 129 } 130 }