github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/link/ld/heap_test.go (about)

     1  // Copyright 2020 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  package ld
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/go-asm/go/cmd/link/loader"
    11  )
    12  
    13  func TestHeap(t *testing.T) {
    14  	tests := [][]loader.Sym{
    15  		{10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
    16  		{100, 90, 80, 70, 60, 50, 40, 30, 20, 10},
    17  		{30, 50, 80, 20, 60, 70, 10, 100, 90, 40},
    18  	}
    19  	for _, s := range tests {
    20  		h := heap{}
    21  		for _, i := range s {
    22  			h.push(i)
    23  			if !verify(&h, 0) {
    24  				t.Errorf("heap invariant violated: %v", h)
    25  			}
    26  		}
    27  		for j := 0; j < len(s); j++ {
    28  			x := h.pop()
    29  			if !verify(&h, 0) {
    30  				t.Errorf("heap invariant violated: %v", h)
    31  			}
    32  			// pop should return elements in ascending order.
    33  			if want := loader.Sym((j + 1) * 10); x != want {
    34  				t.Errorf("pop returns wrong element: want %d, got %d", want, x)
    35  			}
    36  		}
    37  		if !h.empty() {
    38  			t.Errorf("heap is not empty after all pops")
    39  		}
    40  	}
    41  
    42  	// Also check that mixed pushes and pops work correctly.
    43  	for _, s := range tests {
    44  		h := heap{}
    45  		for i := 0; i < len(s)/2; i++ {
    46  			// two pushes, one pop
    47  			h.push(s[2*i])
    48  			if !verify(&h, 0) {
    49  				t.Errorf("heap invariant violated: %v", h)
    50  			}
    51  			h.push(s[2*i+1])
    52  			if !verify(&h, 0) {
    53  				t.Errorf("heap invariant violated: %v", h)
    54  			}
    55  			h.pop()
    56  			if !verify(&h, 0) {
    57  				t.Errorf("heap invariant violated: %v", h)
    58  			}
    59  		}
    60  		for !h.empty() { // pop remaining elements
    61  			h.pop()
    62  			if !verify(&h, 0) {
    63  				t.Errorf("heap invariant violated: %v", h)
    64  			}
    65  		}
    66  	}
    67  }
    68  
    69  // recursively verify heap-ness, starting at element i.
    70  func verify(h *heap, i int) bool {
    71  	n := len(*h)
    72  	c1 := 2*i + 1 // left child
    73  	c2 := 2*i + 2 // right child
    74  	if c1 < n {
    75  		if (*h)[c1] < (*h)[i] {
    76  			return false
    77  		}
    78  		if !verify(h, c1) {
    79  			return false
    80  		}
    81  	}
    82  	if c2 < n {
    83  		if (*h)[c2] < (*h)[i] {
    84  			return false
    85  		}
    86  		if !verify(h, c2) {
    87  			return false
    88  		}
    89  	}
    90  	return true
    91  }