github.com/kaydxh/golang@v0.0.131/go/container/heap/heap_test.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package heap_test 23 24 import ( 25 "sync" 26 "testing" 27 28 heap_ "github.com/kaydxh/golang/go/container/heap" 29 ) 30 31 func testHeapObjectKeyFunc(obj interface{}) string { 32 return obj.(testHeapObject).name 33 } 34 35 type testHeapObject struct { 36 name string 37 val interface{} 38 } 39 40 func mkHeapObj(name string, val interface{}) testHeapObject { 41 return testHeapObject{name: name, val: val} 42 } 43 44 //minheap 45 func compareInts(val1 interface{}, val2 interface{}) bool { 46 first := val1.(testHeapObject).val.(int) 47 second := val2.(testHeapObject).val.(int) 48 return first < second 49 } 50 51 // TestHeapBasic tests Heap invariant and synchronization. 52 func TestHeapBasic(t *testing.T) { 53 h := heap_.NewHeap(testHeapObjectKeyFunc, compareInts) 54 var wg sync.WaitGroup 55 wg.Add(2) 56 const amount = 10 57 var i, u int 58 // Insert items in the heap in opposite orders in two go routines. 59 go func() { 60 for i = amount; i > 0; i-- { 61 h.Add(mkHeapObj(string([]rune{'a', rune(i)}), i)) 62 } 63 wg.Done() 64 }() 65 go func() { 66 for u = 0; u < amount; u++ { 67 h.Add(mkHeapObj(string([]rune{'b', rune(u)}), u+1)) 68 } 69 wg.Done() 70 }() 71 // Wait for the two go routines to finish. 72 wg.Wait() 73 74 t.Logf("heap: %+v", h.List()) 75 // Make sure that the numbers are popped in ascending order. 76 prevNum := 0 77 for i := 0; i < amount*2; i++ { 78 obj, err := h.Pop() 79 num := obj.(testHeapObject).val.(int) 80 // All the items must be sorted. 81 if err != nil || prevNum > num { 82 t.Errorf("got %v out of order, last was %v", obj, prevNum) 83 } 84 t.Logf("get %v", num) 85 prevNum = num 86 } 87 88 } 89 90 // TestHeap_Get tests Heap.Get. 91 func TestHeap_Get(t *testing.T) { 92 h := heap_.NewHeap(testHeapObjectKeyFunc, compareInts) 93 h.Add(mkHeapObj("foo", 10)) 94 h.Add(mkHeapObj("bar", 1)) 95 h.Add(mkHeapObj("bal", 31)) 96 h.Add(mkHeapObj("baz", 11)) 97 98 // Get works with the key. 99 obj, exists := h.Get(mkHeapObj("baz", 0)) 100 if !exists || obj.(testHeapObject).val != 11 { 101 t.Fatalf("unexpected error in getting element") 102 } 103 // Get non-existing object. 104 _, exists = h.Get(mkHeapObj("non-existing", 0)) 105 if exists { 106 t.Fatalf("didn't expect to get any object") 107 } 108 } 109 110 // TestHeap_GetByKey tests Heap.GetByKey and is very similar to TestHeap_Get. 111 func TestHeap_GetByKey(t *testing.T) { 112 h := heap_.NewHeap(testHeapObjectKeyFunc, compareInts) 113 h.Add(mkHeapObj("foo", 10)) 114 h.Add(mkHeapObj("bar", 1)) 115 h.Add(mkHeapObj("bal", 31)) 116 h.Add(mkHeapObj("baz", 11)) 117 118 obj, exists := h.GetByKey("baz") 119 if exists == false || obj.(testHeapObject).val != 11 { 120 t.Fatalf("unexpected error in getting element") 121 } 122 // Get non-existing object. 123 _, exists = h.GetByKey("non-existing") 124 if exists { 125 t.Fatalf("didn't expect to get any object") 126 } 127 } 128 129 type Student struct { 130 Id string 131 Name string 132 Score float32 133 } 134 135 func testStudentObjectKeyFunc(obj interface{}) string { 136 return obj.(*Student).Id 137 } 138 139 //maxheap 140 func compareStudentScore(val1 interface{}, val2 interface{}) bool { 141 first := val1.(*Student).Score 142 second := val2.(*Student).Score 143 return first > second 144 } 145 146 func TestMaxHeap(t *testing.T) { 147 h := heap_.NewHeap(testStudentObjectKeyFunc, compareStudentScore) 148 h.AddIfHeapOrder(&Student{ 149 Id: "id_1", 150 Name: "name_1", 151 Score: 89.2, 152 }) 153 h.AddIfHeapOrder(&Student{ 154 Id: "id_2", 155 Name: "name_2", 156 Score: 87.2, 157 }) 158 h.AddIfHeapOrder(&Student{ 159 Id: "id_3", 160 Name: "name_3", 161 Score: 97.2, 162 }) 163 h.AddIfHeapOrder(&Student{ 164 Id: "id_1", 165 Name: "name_3", 166 Score: 88.2, 167 }) 168 t.Logf("list key: %v", h.ListKeys()) 169 170 sz := len(h.ListKeys()) 171 for i := 0; i < sz; i++ { 172 obj, err := h.Pop() 173 if err != nil { 174 t.Fatalf("failed to pop, err: %v", err) 175 } 176 t.Logf("get obj: %v", obj.(*Student)) 177 } 178 }