github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/x/generics/list/list_test.go (about) 1 // Copyright (c) 2019 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 // This implementation is a modification from Go's container/list source code. 22 // Here is its license: 23 24 // Copyright (c) 2009 The Go Authors. All rights reserved. 25 26 // Redistribution and use in source and binary forms, with or without 27 // modification, are permitted provided that the following conditions are 28 // met: 29 30 // * Redistributions of source code must retain the above copyright 31 // notice, this list of conditions and the following disclaimer. 32 // * Redistributions in binary form must reproduce the above 33 // copyright notice, this list of conditions and the following disclaimer 34 // in the documentation and/or other materials provided with the 35 // distribution. 36 // * Neither the name of Google Inc. nor the names of its 37 // contributors may be used to endorse or promote products derived from 38 // this software without specific prior written permission. 39 40 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 package list 52 53 import ( 54 "testing" 55 ) 56 57 func checkListLen(t *testing.T, l *List, len int) bool { 58 if n := l.Len(); n != len { 59 t.Errorf("l.Len() = %d, want %d", n, len) 60 return false 61 } 62 return true 63 } 64 65 func checkListPointers(t *testing.T, l *List, es []*Element) { 66 root := &l.root 67 68 if !checkListLen(t, l, len(es)) { 69 return 70 } 71 72 // zero length lists must be the zero value or properly initialized (sentinel circle) 73 if len(es) == 0 { 74 if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root { 75 t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root) 76 } 77 return 78 } 79 // len(es) > 0 80 81 // check internal and external prev/next connections 82 for i, e := range es { 83 prev := root 84 Prev := (*Element)(nil) 85 if i > 0 { 86 prev = es[i-1] 87 Prev = prev 88 } 89 if p := e.prev; p != prev { 90 t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev) 91 } 92 if p := e.Prev(); p != Prev { 93 t.Errorf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev) 94 } 95 96 next := root 97 Next := (*Element)(nil) 98 if i < len(es)-1 { 99 next = es[i+1] 100 Next = next 101 } 102 if n := e.next; n != next { 103 t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next) 104 } 105 if n := e.Next(); n != Next { 106 t.Errorf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next) 107 } 108 } 109 } 110 111 func TestList(t *testing.T) { 112 l := newList(nil) 113 checkListPointers(t, l, []*Element{}) 114 115 // Single element list 116 e := l.PushFront("a") 117 checkListPointers(t, l, []*Element{e}) 118 l.MoveToFront(e) 119 checkListPointers(t, l, []*Element{e}) 120 l.MoveToBack(e) 121 checkListPointers(t, l, []*Element{e}) 122 l.Remove(e) 123 checkListPointers(t, l, []*Element{}) 124 125 // Bigger list 126 e2 := l.PushFront(2) 127 e1 := l.PushFront(1) 128 e3 := l.PushBack(3) 129 e4 := l.PushBack("banana") 130 checkListPointers(t, l, []*Element{e1, e2, e3, e4}) 131 132 l.Remove(e2) 133 checkListPointers(t, l, []*Element{e1, e3, e4}) 134 135 l.MoveToFront(e3) // move from middle 136 checkListPointers(t, l, []*Element{e3, e1, e4}) 137 138 l.MoveToFront(e1) 139 l.MoveToBack(e3) // move from middle 140 checkListPointers(t, l, []*Element{e1, e4, e3}) 141 142 l.MoveToFront(e3) // move from back 143 checkListPointers(t, l, []*Element{e3, e1, e4}) 144 l.MoveToFront(e3) // should be no-op 145 checkListPointers(t, l, []*Element{e3, e1, e4}) 146 147 l.MoveToBack(e3) // move from front 148 checkListPointers(t, l, []*Element{e1, e4, e3}) 149 l.MoveToBack(e3) // should be no-op 150 checkListPointers(t, l, []*Element{e1, e4, e3}) 151 152 e2 = l.InsertBefore(2, e1) // insert before front 153 checkListPointers(t, l, []*Element{e2, e1, e4, e3}) 154 l.Remove(e2) 155 e2 = l.InsertBefore(2, e4) // insert before middle 156 checkListPointers(t, l, []*Element{e1, e2, e4, e3}) 157 l.Remove(e2) 158 e2 = l.InsertBefore(2, e3) // insert before back 159 checkListPointers(t, l, []*Element{e1, e4, e2, e3}) 160 l.Remove(e2) 161 162 e2 = l.InsertAfter(2, e1) // insert after front 163 checkListPointers(t, l, []*Element{e1, e2, e4, e3}) 164 l.Remove(e2) 165 e2 = l.InsertAfter(2, e4) // insert after middle 166 checkListPointers(t, l, []*Element{e1, e4, e2, e3}) 167 l.Remove(e2) 168 e2 = l.InsertAfter(2, e3) // insert after back 169 checkListPointers(t, l, []*Element{e1, e4, e3, e2}) 170 l.Remove(e2) 171 172 // Check standard iteration. 173 sum := 0 174 for e := l.Front(); e != nil; e = e.Next() { 175 if i, ok := e.Value.(int); ok { 176 sum += i 177 } 178 } 179 if sum != 4 { 180 t.Errorf("sum over l = %d, want 4", sum) 181 } 182 183 // Clear all elements by iterating 184 var next *Element 185 for e := l.Front(); e != nil; e = next { 186 next = e.Next() 187 l.Remove(e) 188 } 189 checkListPointers(t, l, []*Element{}) 190 } 191 192 func checkList(t *testing.T, l *List, es []interface{}) { 193 if !checkListLen(t, l, len(es)) { 194 return 195 } 196 197 i := 0 198 for e := l.Front(); e != nil; e = e.Next() { 199 le := e.Value.(int) 200 if le != es[i] { 201 t.Errorf("elt[%d].Value = %v, want %v", i, le, es[i]) 202 } 203 i++ 204 } 205 } 206 207 func TestExtending(t *testing.T) { 208 l1 := newList(nil) 209 l2 := newList(nil) 210 211 l1.PushBack(1) 212 l1.PushBack(2) 213 l1.PushBack(3) 214 215 l2.PushBack(4) 216 l2.PushBack(5) 217 218 l3 := newList(nil) 219 l3.PushBackList(l1) 220 checkList(t, l3, []interface{}{1, 2, 3}) 221 l3.PushBackList(l2) 222 checkList(t, l3, []interface{}{1, 2, 3, 4, 5}) 223 224 l3 = newList(nil) 225 l3.PushFrontList(l2) 226 checkList(t, l3, []interface{}{4, 5}) 227 l3.PushFrontList(l1) 228 checkList(t, l3, []interface{}{1, 2, 3, 4, 5}) 229 230 checkList(t, l1, []interface{}{1, 2, 3}) 231 checkList(t, l2, []interface{}{4, 5}) 232 233 l3 = newList(nil) 234 l3.PushBackList(l1) 235 checkList(t, l3, []interface{}{1, 2, 3}) 236 l3.PushBackList(l3) 237 checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3}) 238 239 l3 = newList(nil) 240 l3.PushFrontList(l1) 241 checkList(t, l3, []interface{}{1, 2, 3}) 242 l3.PushFrontList(l3) 243 checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3}) 244 245 l3 = newList(nil) 246 l1.PushBackList(l3) 247 checkList(t, l1, []interface{}{1, 2, 3}) 248 l1.PushFrontList(l3) 249 checkList(t, l1, []interface{}{1, 2, 3}) 250 } 251 252 func TestRemove(t *testing.T) { 253 l := newList(nil) 254 e1 := l.PushBack(1) 255 e2 := l.PushBack(2) 256 checkListPointers(t, l, []*Element{e1, e2}) 257 e := l.Front() 258 l.Remove(e) 259 checkListPointers(t, l, []*Element{e2}) 260 l.Remove(e) 261 checkListPointers(t, l, []*Element{e2}) 262 } 263 264 func TestIssue4103(t *testing.T) { 265 l1 := newList(nil) 266 l1.PushBack(1) 267 l1.PushBack(2) 268 269 l2 := newList(nil) 270 l2.PushBack(3) 271 l2.PushBack(4) 272 273 e := l1.Front() 274 l2.Remove(e) // l2 should not change because e is not an element of l2 275 if n := l2.Len(); n != 2 { 276 t.Errorf("l2.Len() = %d, want 2", n) 277 } 278 279 l1.InsertBefore(8, e) 280 if n := l1.Len(); n != 3 { 281 t.Errorf("l1.Len() = %d, want 3", n) 282 } 283 } 284 285 func TestIssue6349(t *testing.T) { 286 l := newList(nil) 287 l.PushBack(1) 288 l.PushBack(2) 289 290 e := l.Front() 291 l.Remove(e) 292 if e.Value != 1 { 293 t.Errorf("e.value = %d, want 1", e.Value) 294 } 295 if e.Next() != nil { 296 t.Errorf("e.Next() != nil") 297 } 298 if e.Prev() != nil { 299 t.Errorf("e.Prev() != nil") 300 } 301 } 302 303 func TestMove(t *testing.T) { 304 l := newList(nil) 305 e1 := l.PushBack(1) 306 e2 := l.PushBack(2) 307 e3 := l.PushBack(3) 308 e4 := l.PushBack(4) 309 310 l.MoveAfter(e3, e3) 311 checkListPointers(t, l, []*Element{e1, e2, e3, e4}) 312 l.MoveBefore(e2, e2) 313 checkListPointers(t, l, []*Element{e1, e2, e3, e4}) 314 315 l.MoveAfter(e3, e2) 316 checkListPointers(t, l, []*Element{e1, e2, e3, e4}) 317 l.MoveBefore(e2, e3) 318 checkListPointers(t, l, []*Element{e1, e2, e3, e4}) 319 320 l.MoveBefore(e2, e4) 321 checkListPointers(t, l, []*Element{e1, e3, e2, e4}) 322 e2, e3 = e3, e2 323 324 l.MoveBefore(e4, e1) 325 checkListPointers(t, l, []*Element{e4, e1, e2, e3}) 326 e1, e2, e3, e4 = e4, e1, e2, e3 327 328 l.MoveAfter(e4, e1) 329 checkListPointers(t, l, []*Element{e1, e4, e2, e3}) 330 e2, e3, e4 = e4, e2, e3 331 332 l.MoveAfter(e2, e3) 333 checkListPointers(t, l, []*Element{e1, e3, e2, e4}) 334 e2, e3 = e3, e2 335 } 336 337 // Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List 338 func TestZeroList(t *testing.T) { 339 var l1 = new(List) 340 l1.PushFront(1) 341 checkList(t, l1, []interface{}{1}) 342 343 var l2 = new(List) 344 l2.PushBack(1) 345 checkList(t, l2, []interface{}{1}) 346 347 var l3 = new(List) 348 l3.PushFrontList(l1) 349 checkList(t, l3, []interface{}{1}) 350 351 var l4 = new(List) 352 l4.PushBackList(l2) 353 checkList(t, l4, []interface{}{1}) 354 } 355 356 // Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l. 357 func TestInsertBeforeUnknownMark(t *testing.T) { 358 var l List 359 l.PushBack(1) 360 l.PushBack(2) 361 l.PushBack(3) 362 l.InsertBefore(1, new(Element)) 363 checkList(t, &l, []interface{}{1, 2, 3}) 364 } 365 366 // Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l. 367 func TestInsertAfterUnknownMark(t *testing.T) { 368 var l List 369 l.PushBack(1) 370 l.PushBack(2) 371 l.PushBack(3) 372 l.InsertAfter(1, new(Element)) 373 checkList(t, &l, []interface{}{1, 2, 3}) 374 } 375 376 // Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l. 377 func TestMoveUnknownMark(t *testing.T) { 378 var l1 List 379 e1 := l1.PushBack(1) 380 381 var l2 List 382 e2 := l2.PushBack(2) 383 384 l1.MoveAfter(e1, e2) 385 checkList(t, &l1, []interface{}{1}) 386 checkList(t, &l2, []interface{}{2}) 387 388 l1.MoveBefore(e1, e2) 389 checkList(t, &l1, []interface{}{1}) 390 checkList(t, &l2, []interface{}{2}) 391 } 392 393 func TestReset(t *testing.T) { 394 var l1 List 395 l1.Reset() 396 checkList(t, &l1, []interface{}{}) 397 398 l1.PushBack(1) 399 checkList(t, &l1, []interface{}{1}) 400 l1.Reset() 401 checkList(t, &l1, []interface{}{}) 402 403 l1.PushBack(2) 404 l1.PushBack(3) 405 l1.PushBack(4) 406 l1.PushBack(5) 407 checkList(t, &l1, []interface{}{2, 3, 4, 5}) 408 l1.Reset() 409 checkList(t, &l1, []interface{}{}) 410 }