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  }