// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT.

//go:build go1.21

package trace

import (
	"fmt"
	"strings"
	"testing"

	"slices"
)

func TestHeap(t *testing.T) {
	var heap []*batchCursor

	// Insert a bunch of values into the heap.
	checkHeap(t, heap)
	heap = heapInsert(heap, makeBatchCursor(5))
	checkHeap(t, heap)
	for i := int64(-20); i < 20; i++ {
		heap = heapInsert(heap, makeBatchCursor(i))
		checkHeap(t, heap)
	}

	// Update an element in the middle to be the new minimum.
	for i := range heap {
		if heap[i].ev.time == 5 {
			heap[i].ev.time = -21
			heapUpdate(heap, i)
			break
		}
	}
	checkHeap(t, heap)
	if heap[0].ev.time != -21 {
		t.Fatalf("heap update failed, expected %d as heap min: %s", -21, heapDebugString(heap))
	}

	// Update the minimum element to be smaller. There should be no change.
	heap[0].ev.time = -22
	heapUpdate(heap, 0)
	checkHeap(t, heap)
	if heap[0].ev.time != -22 {
		t.Fatalf("heap update failed, expected %d as heap min: %s", -22, heapDebugString(heap))
	}

	// Update the last element to be larger. There should be no change.
	heap[len(heap)-1].ev.time = 21
	heapUpdate(heap, len(heap)-1)
	checkHeap(t, heap)
	if heap[len(heap)-1].ev.time != 21 {
		t.Fatalf("heap update failed, expected %d as heap min: %s", 21, heapDebugString(heap))
	}

	// Update the last element to be smaller.
	heap[len(heap)-1].ev.time = 7
	heapUpdate(heap, len(heap)-1)
	checkHeap(t, heap)
	if heap[len(heap)-1].ev.time == 21 {
		t.Fatalf("heap update failed, unexpected %d as heap min: %s", 21, heapDebugString(heap))
	}

	// Remove an element in the middle.
	for i := range heap {
		if heap[i].ev.time == 5 {
			heap = heapRemove(heap, i)
			break
		}
	}
	checkHeap(t, heap)
	for i := range heap {
		if heap[i].ev.time == 5 {
			t.Fatalf("failed to remove heap elem with time %d: %s", 5, heapDebugString(heap))
		}
	}

	// Remove tail.
	heap = heapRemove(heap, len(heap)-1)
	checkHeap(t, heap)

	// Remove from the head, and make sure the result is sorted.
	l := len(heap)
	var removed []*batchCursor
	for i := 0; i < l; i++ {
		removed = append(removed, heap[0])
		heap = heapRemove(heap, 0)
		checkHeap(t, heap)
	}
	if !slices.IsSortedFunc(removed, (*batchCursor).compare) {
		t.Fatalf("heap elements not removed in sorted order, got: %s", heapDebugString(removed))
	}
}

func makeBatchCursor(v int64) *batchCursor {
	return &batchCursor{ev: baseEvent{time: Time(v)}}
}

func heapDebugString(heap []*batchCursor) string {
	var sb strings.Builder
	fmt.Fprintf(&sb, "[")
	for i := range heap {
		if i != 0 {
			fmt.Fprintf(&sb, ", ")
		}
		fmt.Fprintf(&sb, "%d", heap[i].ev.time)
	}
	fmt.Fprintf(&sb, "]")
	return sb.String()
}

func checkHeap(t *testing.T, heap []*batchCursor) {
	t.Helper()

	for i := range heap {
		if i == 0 {
			continue
		}
		if heap[(i-1)/2].compare(heap[i]) > 0 {
			t.Errorf("heap invariant not maintained between index %d and parent %d: %s", i, i/2, heapDebugString(heap))
		}
	}
	if t.Failed() {
		t.FailNow()
	}
}
