github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/xlist/list_test.go (about) 1 package xlist 2 3 import "testing" 4 5 func checkListLen[T comparable](t *testing.T, l List[T], expectedLen int) bool { 6 if n := l.Len(); n != expectedLen { 7 t.Errorf("l.Len() = %d, want %d", n, expectedLen) 8 9 return false 10 } 11 12 return true 13 } 14 15 func checkListPointers[T comparable](t *testing.T, l List[T], es []*Element[T]) { 16 root := &l.(*list[T]).root 17 18 if !checkListLen(t, l, len(es)) { 19 return 20 } 21 22 // zero length lists must be the zero value or properly initialized (sentinel circle) 23 if len(es) == 0 { 24 if l.(*list[T]).root.next != nil && l.(*list[T]).root.next != root || 25 l.(*list[T]).root.prev != nil && l.(*list[T]).root.prev != root { 26 t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", 27 l.(*list[T]).root.next, l.(*list[T]).root.prev, root) 28 } 29 30 return 31 } 32 // len(es) > 0 33 34 // check internal and external prev/next connections 35 for i, e := range es { 36 prev := root 37 Prev := (*Element[T])(nil) 38 if i > 0 { 39 prev = es[i-1] 40 Prev = prev 41 } 42 if p := e.prev; p != prev { 43 t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev) 44 } 45 if p := e.Prev(); p != Prev { 46 t.Errorf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev) 47 } 48 49 next := root 50 Next := (*Element[T])(nil) 51 if i < len(es)-1 { 52 next = es[i+1] 53 Next = next 54 } 55 if n := e.next; n != next { 56 t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next) 57 } 58 if n := e.Next(); n != Next { 59 t.Errorf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next) 60 } 61 } 62 } 63 64 func TestList(t *testing.T) { 65 t.Run("SingleElementList", func(t *testing.T) { 66 l := New[string]() 67 checkListPointers(t, l, []*Element[string]{}) 68 69 e := l.PushFront("a") 70 checkListPointers(t, l, []*Element[string]{e}) 71 l.MoveToFront(e) 72 checkListPointers(t, l, []*Element[string]{e}) 73 l.MoveToBack(e) 74 checkListPointers(t, l, []*Element[string]{e}) 75 l.Remove(e) 76 checkListPointers(t, l, []*Element[string]{}) 77 }) 78 79 t.Run("BiggerList", func(t *testing.T) { 80 l := New[int]() 81 checkListPointers(t, l, []*Element[int]{}) 82 83 e2 := l.PushFront(2) 84 e1 := l.PushFront(1) 85 e3 := l.PushBack(3) 86 e4 := l.PushBack(4) 87 checkListPointers(t, l, []*Element[int]{e1, e2, e3, e4}) 88 89 l.Remove(e2) 90 checkListPointers(t, l, []*Element[int]{e1, e3, e4}) 91 92 l.MoveToFront(e3) // move from middle 93 checkListPointers(t, l, []*Element[int]{e3, e1, e4}) 94 95 l.MoveToFront(e1) 96 l.MoveToBack(e3) // move from middle 97 checkListPointers(t, l, []*Element[int]{e1, e4, e3}) 98 99 l.MoveToFront(e3) // move from back 100 checkListPointers(t, l, []*Element[int]{e3, e1, e4}) 101 l.MoveToFront(e3) // should be no-op 102 checkListPointers(t, l, []*Element[int]{e3, e1, e4}) 103 104 l.MoveToBack(e3) // move from front 105 checkListPointers(t, l, []*Element[int]{e1, e4, e3}) 106 l.MoveToBack(e3) // should be no-op 107 checkListPointers(t, l, []*Element[int]{e1, e4, e3}) 108 109 e2 = l.InsertBefore(2, e1) // insert before front 110 checkListPointers(t, l, []*Element[int]{e2, e1, e4, e3}) 111 l.Remove(e2) 112 e2 = l.InsertBefore(2, e4) // insert before middle 113 checkListPointers(t, l, []*Element[int]{e1, e2, e4, e3}) 114 l.Remove(e2) 115 e2 = l.InsertBefore(2, e3) // insert before back 116 checkListPointers(t, l, []*Element[int]{e1, e4, e2, e3}) 117 l.Remove(e2) 118 119 e2 = l.InsertAfter(2, e1) // insert after front 120 checkListPointers(t, l, []*Element[int]{e1, e2, e4, e3}) 121 l.Remove(e2) 122 e2 = l.InsertAfter(2, e4) // insert after middle 123 checkListPointers(t, l, []*Element[int]{e1, e4, e2, e3}) 124 l.Remove(e2) 125 e2 = l.InsertAfter(2, e3) // insert after back 126 checkListPointers(t, l, []*Element[int]{e1, e4, e3, e2}) 127 l.Remove(e2) 128 129 t.Run("CheckStandardIteration", func(t *testing.T) { 130 sum := 0 131 for e := l.Front(); e != nil; e = e.Next() { 132 sum += e.Value 133 } 134 if sum != 8 { 135 t.Errorf("sum over l = %d, want 8", sum) 136 } 137 }) 138 139 t.Run("ClearAllElementsByIterating", func(t *testing.T) { 140 var next *Element[int] 141 for e := l.Front(); e != nil; e = next { 142 next = e.Next() 143 l.Remove(e) 144 } 145 checkListPointers(t, l, []*Element[int]{}) 146 }) 147 }) 148 } 149 150 func checkList[T comparable](t *testing.T, l List[T], es []any) { 151 if !checkListLen(t, l, len(es)) { 152 return 153 } 154 155 i := 0 156 for e := l.Front(); e != nil; e = e.Next() { 157 le := e.Value 158 if le != es[i] { 159 t.Errorf("elt[%d].Value = %v, want %v", i, le, es[i]) 160 } 161 i++ 162 } 163 } 164 165 func TestExtending(t *testing.T) { 166 l1 := New[int]() 167 l2 := New[int]() 168 169 l1.PushBack(1) 170 l1.PushBack(2) 171 l1.PushBack(3) 172 173 l2.PushBack(4) 174 l2.PushBack(5) 175 176 l3 := New[int]() 177 l3.PushBackList(l1) 178 checkList(t, l3, []any{1, 2, 3}) 179 l3.PushBackList(l2) 180 checkList(t, l3, []any{1, 2, 3, 4, 5}) 181 182 l3 = New[int]() 183 l3.PushFrontList(l2) 184 checkList(t, l3, []any{4, 5}) 185 l3.PushFrontList(l1) 186 checkList(t, l3, []any{1, 2, 3, 4, 5}) 187 188 checkList(t, l1, []any{1, 2, 3}) 189 checkList(t, l2, []any{4, 5}) 190 191 l3 = New[int]() 192 l3.PushBackList(l1) 193 checkList(t, l3, []any{1, 2, 3}) 194 l3.PushBackList(l3) 195 checkList(t, l3, []any{1, 2, 3, 1, 2, 3}) 196 197 l3 = New[int]() 198 l3.PushFrontList(l1) 199 checkList(t, l3, []any{1, 2, 3}) 200 l3.PushFrontList(l3) 201 checkList(t, l3, []any{1, 2, 3, 1, 2, 3}) 202 203 l3 = New[int]() 204 l1.PushBackList(l3) 205 checkList(t, l1, []any{1, 2, 3}) 206 l1.PushFrontList(l3) 207 checkList(t, l1, []any{1, 2, 3}) 208 } 209 210 func TestRemove(t *testing.T) { 211 l := New[int]() 212 e1 := l.PushBack(1) 213 e2 := l.PushBack(2) 214 checkListPointers(t, l, []*Element[int]{e1, e2}) 215 e := l.Front() 216 l.Remove(e) 217 checkListPointers(t, l, []*Element[int]{e2}) 218 l.Remove(e) 219 checkListPointers(t, l, []*Element[int]{e2}) 220 } 221 222 func TestIssue4103(t *testing.T) { 223 l1 := New[int]() 224 l1.PushBack(1) 225 l1.PushBack(2) 226 227 l2 := New[int]() 228 l2.PushBack(3) 229 l2.PushBack(4) 230 231 e := l1.Front() 232 l2.Remove(e) // l2 should not change because e is not an element of l2 233 if n := l2.Len(); n != 2 { 234 t.Errorf("l2.Len() = %d, want 2", n) 235 } 236 237 l1.InsertBefore(8, e) 238 if n := l1.Len(); n != 3 { 239 t.Errorf("l1.Len() = %d, want 3", n) 240 } 241 } 242 243 func TestIssue6349(t *testing.T) { 244 l := New[int]() 245 l.PushBack(1) 246 l.PushBack(2) 247 248 e := l.Front() 249 l.Remove(e) 250 if e.Value != 1 { 251 t.Errorf("e.value = %d, want 1", e.Value) 252 } 253 if e.Next() != nil { 254 t.Errorf("e.Next() != nil") 255 } 256 if e.Prev() != nil { 257 t.Errorf("e.Prev() != nil") 258 } 259 } 260 261 func TestMove(t *testing.T) { 262 l := New[int]() 263 e1 := l.PushBack(1) 264 e2 := l.PushBack(2) 265 e3 := l.PushBack(3) 266 e4 := l.PushBack(4) 267 268 l.MoveAfter(e3, e3) 269 checkListPointers(t, l, []*Element[int]{e1, e2, e3, e4}) 270 l.MoveBefore(e2, e2) 271 checkListPointers(t, l, []*Element[int]{e1, e2, e3, e4}) 272 273 l.MoveAfter(e3, e2) 274 checkListPointers(t, l, []*Element[int]{e1, e2, e3, e4}) 275 l.MoveBefore(e2, e3) 276 checkListPointers(t, l, []*Element[int]{e1, e2, e3, e4}) 277 278 l.MoveBefore(e2, e4) 279 checkListPointers(t, l, []*Element[int]{e1, e3, e2, e4}) 280 e2, e3 = e3, e2 281 282 l.MoveBefore(e4, e1) 283 checkListPointers(t, l, []*Element[int]{e4, e1, e2, e3}) 284 e1, e2, e3, e4 = e4, e1, e2, e3 285 286 l.MoveAfter(e4, e1) 287 checkListPointers(t, l, []*Element[int]{e1, e4, e2, e3}) 288 e2, e3, e4 = e4, e2, e3 289 290 l.MoveAfter(e2, e3) 291 checkListPointers(t, l, []*Element[int]{e1, e3, e2, e4}) 292 } 293 294 // Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l. 295 func TestInsertBeforeUnknownMark(t *testing.T) { 296 l := New[int]() 297 l.PushBack(1) 298 l.PushBack(2) 299 l.PushBack(3) 300 l.InsertBefore(1, new(Element[int])) 301 checkList(t, l, []any{1, 2, 3}) 302 } 303 304 // Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l. 305 func TestInsertAfterUnknownMark(t *testing.T) { 306 l := New[int]() 307 l.PushBack(1) 308 l.PushBack(2) 309 l.PushBack(3) 310 l.InsertAfter(1, new(Element[int])) 311 checkList(t, l, []any{1, 2, 3}) 312 } 313 314 // Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l. 315 func TestMoveUnknownMark(t *testing.T) { 316 l1 := New[int]() 317 e1 := l1.PushBack(1) 318 319 l2 := New[int]() 320 e2 := l2.PushBack(2) 321 322 l1.MoveAfter(e1, e2) 323 checkList(t, l1, []any{1}) 324 checkList(t, l2, []any{2}) 325 326 l1.MoveBefore(e1, e2) 327 checkList(t, l1, []any{1}) 328 checkList(t, l2, []any{2}) 329 }