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 }