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  }