github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/runtime/treap_test.go (about)

     1  // Copyright 2019 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 runtime_test
     6  
     7  import (
     8  	"runtime"
     9  	"testing"
    10  )
    11  
    12  var spanDesc = map[uintptr]uintptr{
    13  	0xc0000000: 2,
    14  	0xc0006000: 1,
    15  	0xc0010000: 8,
    16  	0xc0022000: 7,
    17  	0xc0034000: 4,
    18  	0xc0040000: 5,
    19  	0xc0050000: 5,
    20  	0xc0060000: 5000,
    21  }
    22  
    23  // Wrap the Treap one more time because go:notinheap doesn't
    24  // actually follow a structure across package boundaries.
    25  //
    26  //go:notinheap
    27  type treap struct {
    28  	runtime.Treap
    29  }
    30  
    31  // This test ensures that the treap implementation in the runtime
    32  // maintains all stated invariants after different sequences of
    33  // insert, removeSpan, find, and erase. Invariants specific to the
    34  // treap data structure are checked implicitly: after each mutating
    35  // operation, treap-related invariants are checked for the entire
    36  // treap.
    37  func TestTreap(t *testing.T) {
    38  	// Set up a bunch of spans allocated into mheap_.
    39  	spans := make([]runtime.Span, 0, len(spanDesc))
    40  	for base, pages := range spanDesc {
    41  		s := runtime.AllocSpan(base, pages)
    42  		defer s.Free()
    43  		spans = append(spans, s)
    44  	}
    45  	t.Run("Insert", func(t *testing.T) {
    46  		tr := treap{}
    47  		// Test just a very basic insert/remove for sanity.
    48  		tr.Insert(spans[0])
    49  		tr.RemoveSpan(spans[0])
    50  	})
    51  	t.Run("FindTrivial", func(t *testing.T) {
    52  		tr := treap{}
    53  		// Test just a very basic find operation for sanity.
    54  		tr.Insert(spans[0])
    55  		i := tr.Find(1)
    56  		if i.Span() != spans[0] {
    57  			t.Fatal("found unknown span in treap")
    58  		}
    59  		tr.RemoveSpan(spans[0])
    60  	})
    61  	t.Run("FindBestFit", func(t *testing.T) {
    62  		// Run this 10 times, recreating the treap each time.
    63  		// Because of the non-deterministic structure of a treap,
    64  		// we'll be able to test different structures this way.
    65  		for i := 0; i < 10; i++ {
    66  			tr := treap{}
    67  			for _, s := range spans {
    68  				tr.Insert(s)
    69  			}
    70  			i := tr.Find(5)
    71  			if i.Span().Pages() != 5 {
    72  				t.Fatalf("expected span of size 5, got span of size %d", i.Span().Pages())
    73  			} else if i.Span().Base() != 0xc0040000 {
    74  				t.Fatalf("expected span to have the lowest base address, instead got base %x", i.Span().Base())
    75  			}
    76  			for _, s := range spans {
    77  				tr.RemoveSpan(s)
    78  			}
    79  		}
    80  	})
    81  	t.Run("Iterate", func(t *testing.T) {
    82  		t.Run("StartToEnd", func(t *testing.T) {
    83  			// Ensure progressing an iterator actually goes over the whole treap
    84  			// from the start and that it iterates over the elements in order.
    85  			// Also ensures that Start returns a valid iterator.
    86  			tr := treap{}
    87  			for _, s := range spans {
    88  				tr.Insert(s)
    89  			}
    90  			nspans := 0
    91  			lastSize := uintptr(0)
    92  			for i := tr.Start(); i.Valid(); i = i.Next() {
    93  				nspans++
    94  				if lastSize > i.Span().Pages() {
    95  					t.Fatalf("not iterating in correct order: encountered size %d before %d", lastSize, i.Span().Pages())
    96  				}
    97  				lastSize = i.Span().Pages()
    98  			}
    99  			if nspans != len(spans) {
   100  				t.Fatal("failed to iterate forwards over full treap")
   101  			}
   102  			for _, s := range spans {
   103  				tr.RemoveSpan(s)
   104  			}
   105  		})
   106  		t.Run("EndToStart", func(t *testing.T) {
   107  			// Ensure progressing an iterator actually goes over the whole treap
   108  			// from the end and that it iterates over the elements in reverse
   109  			// order. Also ensures that End returns a valid iterator.
   110  			tr := treap{}
   111  			for _, s := range spans {
   112  				tr.Insert(s)
   113  			}
   114  			nspans := 0
   115  			lastSize := ^uintptr(0)
   116  			for i := tr.End(); i.Valid(); i = i.Prev() {
   117  				nspans++
   118  				if lastSize < i.Span().Pages() {
   119  					t.Fatalf("not iterating in correct order: encountered size %d before %d", lastSize, i.Span().Pages())
   120  				}
   121  				lastSize = i.Span().Pages()
   122  			}
   123  			if nspans != len(spans) {
   124  				t.Fatal("failed to iterate backwards over full treap")
   125  			}
   126  			for _, s := range spans {
   127  				tr.RemoveSpan(s)
   128  			}
   129  		})
   130  		t.Run("Prev", func(t *testing.T) {
   131  			// Test the iterator invariant that i.prev().next() == i.
   132  			tr := treap{}
   133  			for _, s := range spans {
   134  				tr.Insert(s)
   135  			}
   136  			i := tr.Start().Next().Next()
   137  			p := i.Prev()
   138  			if !p.Valid() {
   139  				t.Fatal("i.prev() is invalid")
   140  			}
   141  			if p.Next().Span() != i.Span() {
   142  				t.Fatal("i.prev().next() != i")
   143  			}
   144  			for _, s := range spans {
   145  				tr.RemoveSpan(s)
   146  			}
   147  		})
   148  		t.Run("Next", func(t *testing.T) {
   149  			// Test the iterator invariant that i.next().prev() == i.
   150  			tr := treap{}
   151  			for _, s := range spans {
   152  				tr.Insert(s)
   153  			}
   154  			i := tr.Start().Next().Next()
   155  			n := i.Next()
   156  			if !n.Valid() {
   157  				t.Fatal("i.next() is invalid")
   158  			}
   159  			if n.Prev().Span() != i.Span() {
   160  				t.Fatal("i.next().prev() != i")
   161  			}
   162  			for _, s := range spans {
   163  				tr.RemoveSpan(s)
   164  			}
   165  		})
   166  	})
   167  	t.Run("EraseOne", func(t *testing.T) {
   168  		// Test that erasing one iterator correctly retains
   169  		// all relationships between elements.
   170  		tr := treap{}
   171  		for _, s := range spans {
   172  			tr.Insert(s)
   173  		}
   174  		i := tr.Start().Next().Next().Next()
   175  		s := i.Span()
   176  		n := i.Next()
   177  		p := i.Prev()
   178  		tr.Erase(i)
   179  		if n.Prev().Span() != p.Span() {
   180  			t.Fatal("p, n := i.Prev(), i.Next(); n.prev() != p after i was erased")
   181  		}
   182  		if p.Next().Span() != n.Span() {
   183  			t.Fatal("p, n := i.Prev(), i.Next(); p.next() != n after i was erased")
   184  		}
   185  		tr.Insert(s)
   186  		for _, s := range spans {
   187  			tr.RemoveSpan(s)
   188  		}
   189  	})
   190  	t.Run("EraseAll", func(t *testing.T) {
   191  		// Test that erasing iterators actually removes nodes from the treap.
   192  		tr := treap{}
   193  		for _, s := range spans {
   194  			tr.Insert(s)
   195  		}
   196  		for i := tr.Start(); i.Valid(); {
   197  			n := i.Next()
   198  			tr.Erase(i)
   199  			i = n
   200  		}
   201  		if size := tr.Size(); size != 0 {
   202  			t.Fatalf("should have emptied out treap, %d spans left", size)
   203  		}
   204  	})
   205  }