github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/collection/listx/list_test.go (about)

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