github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/linked_list_test.go (about)

     1  package list
     2  
     3  import (
     4  	"container/list"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func TestLinkedList_AppendValue(t *testing.T) {
    13  	dlist := NewLinkedList[int]()
    14  	elements := dlist.AppendValue(1, 2, 3, 4, 5)
    15  	assert.Equal(t, len(elements), 5)
    16  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
    17  		t.Logf("index: %d, e: %v", idx, e)
    18  		assert.Equal(t, elements[idx], e)
    19  		t.Logf("addr: %p, return addr: %p", elements[idx], e)
    20  		return nil
    21  	})
    22  	require.NoError(t, err)
    23  
    24  	dlist2 := list.New()
    25  	dlist2.PushBack(1)
    26  	dlist2.PushBack(2)
    27  	dlist2.PushBack(3)
    28  	dlist2.PushBack(4)
    29  	dlist2.PushBack(5)
    30  
    31  	assert.Equal(t, dlist.Len(), int64(dlist2.Len()))
    32  
    33  	dlistItr := dlist.Front()
    34  	dlist2Itr := dlist2.Front()
    35  	for dlist2Itr != nil {
    36  		assert.Equal(t, dlistItr.Value, dlist2Itr.Value)
    37  		dlist2Itr = dlist2Itr.Next()
    38  		dlistItr = dlistItr.Next()
    39  	}
    40  }
    41  
    42  func TestDoublyLinkedList_InsertBefore(t *testing.T) {
    43  	dlist := NewLinkedList[int]()
    44  	elements := dlist.AppendValue(1)
    45  	_2n := dlist.InsertBefore(2, elements[0])
    46  	_3n := dlist.InsertBefore(3, _2n)
    47  	_4n := dlist.InsertBefore(4, _3n)
    48  	dlist.InsertBefore(5, _4n)
    49  	assert.Equal(t, int64(5), dlist.Len())
    50  
    51  	dlist2 := list.New()
    52  	_1n_2 := dlist2.PushBack(1)
    53  	_2n_2 := dlist2.InsertBefore(2, _1n_2)
    54  	_3n_2 := dlist2.InsertBefore(3, _2n_2)
    55  	_4n_2 := dlist2.InsertBefore(4, _3n_2)
    56  	dlist2.InsertBefore(5, _4n_2)
    57  
    58  	assert.Equal(t, dlist.Len(), int64(dlist2.Len()))
    59  
    60  	dlistItr := dlist.Front()
    61  	dlist2Itr := dlist2.Front()
    62  	for dlist2Itr != nil {
    63  		assert.Equal(t, dlistItr.Value, dlist2Itr.Value)
    64  		dlist2Itr = dlist2Itr.Next()
    65  		dlistItr = dlistItr.Next()
    66  	}
    67  }
    68  
    69  func TestDoublyLinkedList_InsertAfter(t *testing.T) {
    70  	dlist := NewLinkedList[int]()
    71  	elements := dlist.AppendValue(1)
    72  	_2n := dlist.InsertAfter(2, elements[0])
    73  	_3n := dlist.InsertAfter(3, _2n)
    74  	_4n := dlist.InsertAfter(4, _3n)
    75  	dlist.InsertAfter(5, _4n)
    76  	assert.Equal(t, int64(5), dlist.Len())
    77  
    78  	dlist2 := list.New()
    79  	_1n_2 := dlist2.PushBack(1)
    80  	_2n_2 := dlist2.InsertAfter(2, _1n_2)
    81  	_3n_2 := dlist2.InsertAfter(3, _2n_2)
    82  	_4n_2 := dlist2.InsertAfter(4, _3n_2)
    83  	dlist2.InsertAfter(5, _4n_2)
    84  
    85  	assert.Equal(t, dlist.Len(), int64(dlist2.Len()))
    86  
    87  	dlistItr := dlist.Front()
    88  	dlist2Itr := dlist2.Front()
    89  	for dlist2Itr != nil {
    90  		assert.Equal(t, dlistItr.Value, dlist2Itr.Value)
    91  		dlist2Itr = dlist2Itr.Next()
    92  		dlistItr = dlistItr.Next()
    93  	}
    94  }
    95  
    96  func TestLinkedList_AppendValueThenRemove(t *testing.T) {
    97  	t.Log("test linked list append value")
    98  	dlist := NewLinkedList[int]()
    99  	dlist2 := list.New()
   100  	checkItems := func() {
   101  		dlistItr := dlist.Front()
   102  		dlist2Itr := dlist2.Front()
   103  		for dlist2Itr != nil {
   104  			require.Equal(t, dlistItr.Value, dlist2Itr.Value)
   105  			dlist2Itr = dlist2Itr.Next()
   106  			dlistItr = dlistItr.Next()
   107  		}
   108  	}
   109  
   110  	elements := dlist.AppendValue(1, 2, 3, 4, 5)
   111  	require.Equal(t, len(elements), 5)
   112  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   113  		require.Equal(t, elements[idx], e)
   114  		addr1, addr2 := fmt.Sprintf("%p", elements[idx]), fmt.Sprintf("%p", e)
   115  		require.Equal(t, addr1, addr2)
   116  		return nil
   117  	})
   118  	require.NoError(t, err)
   119  
   120  	dlist2.PushBack(1)
   121  	dlist2.PushBack(2)
   122  	_3n := dlist2.PushBack(3)
   123  	dlist2.PushBack(4)
   124  	dlist2.PushBack(5)
   125  	assert.Equal(t, dlist.Len(), int64(dlist2.Len()))
   126  	checkItems()
   127  
   128  	t.Log("test linked list remove middle")
   129  	dlist.Remove(elements[2])
   130  	dlist2.Remove(_3n)
   131  	checkItems()
   132  
   133  	t.Log("test linked list remove head")
   134  	dlist.Remove(dlist.Front())
   135  	dlist2.Remove(dlist2.Front())
   136  	checkItems()
   137  
   138  	t.Log("test linked list remove tail")
   139  	dlist.Remove(dlist.Back())
   140  	dlist2.Remove(dlist2.Back())
   141  	checkItems()
   142  
   143  	t.Log("test linked list remove nil")
   144  	dlist.Remove(nil)
   145  	// dlist2.Remove(nil) // nil panic
   146  	checkItems()
   147  
   148  	t.Log("check released elements")
   149  	require.Equal(t, int64(dlist2.Len()), dlist.Len())
   150  	expected := []int{2, 4}
   151  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   152  		require.Equal(t, expected[idx], e.Value)
   153  		return nil
   154  	})
   155  	require.NoError(t, err)
   156  
   157  	require.Nil(t, elements[0].prev)
   158  	require.Nil(t, elements[0].next)
   159  	require.Nil(t, elements[0].listRef)
   160  
   161  	require.Nil(t, elements[2].prev)
   162  	require.Nil(t, elements[2].next)
   163  	require.Nil(t, elements[2].listRef)
   164  
   165  	require.Nil(t, elements[4].prev)
   166  	require.Nil(t, elements[4].next)
   167  	require.Nil(t, elements[4].listRef)
   168  }
   169  
   170  func BenchmarkNewLinkedList_AppendValue(b *testing.B) {
   171  	dlist := NewLinkedList[int]()
   172  	b.ResetTimer()
   173  	for i := 0; i < b.N; i++ {
   174  		dlist.AppendValue(i)
   175  	}
   176  	b.ReportAllocs()
   177  }
   178  
   179  func BenchmarkSDKLinkedList_PushBack(b *testing.B) {
   180  	dlist := list.New()
   181  	b.ResetTimer()
   182  	for i := 0; i < b.N; i++ {
   183  		dlist.PushBack(i)
   184  	}
   185  	b.ReportAllocs()
   186  }
   187  
   188  func TestLinkedList_PushBack(t *testing.T) {
   189  	dlist := NewLinkedList[int]()
   190  	element := dlist.PushBack(1)
   191  	require.Equal(t, int64(1), dlist.Len())
   192  	require.Equal(t, element.Value, 1)
   193  
   194  	element = dlist.PushBack(2)
   195  	require.Equal(t, int64(2), dlist.Len())
   196  	require.Equal(t, element.Value, 2)
   197  
   198  	expected := []int{1, 2}
   199  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   200  		require.Equal(t, expected[idx], e.Value)
   201  		return nil
   202  	})
   203  	require.NoError(t, err)
   204  
   205  	reverseExpected := []int{2, 1}
   206  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   207  		require.Equal(t, reverseExpected[idx], e.Value)
   208  	})
   209  }
   210  
   211  func TestLinkedList_PushFront(t *testing.T) {
   212  	dlist := NewLinkedList[int]()
   213  	element := dlist.PushFront(1)
   214  	require.Equal(t, int64(1), dlist.Len())
   215  	require.Equal(t, element.Value, 1)
   216  
   217  	element = dlist.PushFront(2)
   218  	require.Equal(t, int64(2), dlist.Len())
   219  	require.Equal(t, element.Value, 2)
   220  
   221  	expected := []int{2, 1}
   222  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   223  		require.Equal(t, expected[idx], e.Value)
   224  		return nil
   225  	})
   226  	require.NoError(t, err)
   227  
   228  	reverseExpected := []int{1, 2}
   229  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   230  		require.Equal(t, reverseExpected[idx], e.Value)
   231  	})
   232  }
   233  
   234  func BenchmarkDoublyLinkedList_PushBack(b *testing.B) {
   235  	dlist := NewLinkedList[int]()
   236  	b.ResetTimer()
   237  	for i := 0; i < b.N; i++ {
   238  		dlist.PushBack(i)
   239  	}
   240  	b.ReportAllocs()
   241  }
   242  
   243  func BenchmarkDoublyLinkedList_Append(b *testing.B) {
   244  	dlist := NewLinkedList[int]()
   245  	elements := make([]*NodeElement[int], 0, b.N)
   246  	for i := 0; i < b.N; i++ {
   247  		elements = append(elements, newNodeElement[int](i, dlist.(*doublyLinkedList[int])))
   248  	}
   249  	b.ResetTimer()
   250  	for i := 0; i < b.N; i++ {
   251  		dlist.Append(elements[i])
   252  	}
   253  	b.StopTimer()
   254  	b.ReportAllocs()
   255  	require.Equal(b, int64(b.N), dlist.Len())
   256  }
   257  
   258  func TestDoublyLinkedList_InsertBefore2(t *testing.T) {
   259  	dlist := NewLinkedList[int]()
   260  	_2n := dlist.InsertBefore(2, dlist.Front())
   261  	require.Equal(t, int64(1), dlist.Len())
   262  	require.Equal(t, _2n.Value, 2)
   263  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   264  		t.Logf("index: %d, addr: %p, e: %v", idx, e, e)
   265  		return nil
   266  	})
   267  	require.NoError(t, err)
   268  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   269  		t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e)
   270  	})
   271  }
   272  
   273  func TestLinkedList_InsertAfterAndMove(t *testing.T) {
   274  	dlist := NewLinkedList[int]()
   275  	dlist2 := list.New()
   276  	checkItems := func() {
   277  		dlistItr := dlist.Front()
   278  		dlist2Itr := dlist2.Front()
   279  		require.NotNil(t, dlistItr)
   280  		require.NotNil(t, dlist2Itr)
   281  		require.Equal(t, int64(dlist2.Len()), dlist.Len())
   282  		for dlist2Itr != nil {
   283  			require.Equal(t, dlist2Itr.Value, dlistItr.Value)
   284  			dlist2Itr = dlist2Itr.Next()
   285  			dlistItr = dlistItr.Next()
   286  		}
   287  	}
   288  
   289  	elements := dlist.AppendValue(1, 2, 3, 4, 5)
   290  	_6n := dlist.InsertAfter(6, elements[len(elements)-1])
   291  	_7n := dlist.InsertBefore(7, elements[0])
   292  	require.Equal(t, int64(7), dlist.Len())
   293  	expected := []int{7, 1, 2, 3, 4, 5, 6}
   294  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   295  		require.Equal(t, expected[idx], e.Value)
   296  		return nil
   297  	})
   298  	require.NoError(t, err)
   299  	reverseExpected := []int{6, 5, 4, 3, 2, 1, 7}
   300  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   301  		require.Equal(t, reverseExpected[idx], e.Value)
   302  	})
   303  
   304  	dlist2.PushBack(1)
   305  	dlist2.PushBack(2)
   306  	dlist2.PushBack(3)
   307  	dlist2.PushBack(4)
   308  	dlist2.PushBack(5)
   309  	_6n_2 := dlist2.InsertAfter(6, dlist2.Back())
   310  	_7n_2 := dlist2.InsertBefore(7, dlist2.Front())
   311  	require.Equal(t, int64(dlist2.Len()), dlist.Len())
   312  	checkItems()
   313  
   314  	t.Log("test move after")
   315  	dlist.MoveToBack(_7n)
   316  	dlist2.MoveToBack(_7n_2)
   317  	checkItems()
   318  	expected = []int{1, 2, 3, 4, 5, 6, 7}
   319  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   320  		require.Equal(t, expected[idx], e.Value)
   321  		return nil
   322  	})
   323  	require.NoError(t, err)
   324  	reverseExpected = []int{7, 6, 5, 4, 3, 2, 1}
   325  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   326  		require.Equal(t, reverseExpected[idx], e.Value)
   327  	})
   328  
   329  	t.Log("test move to front")
   330  	dlist.MoveToFront(_6n)
   331  	dlist2.MoveToFront(_6n_2)
   332  	checkItems()
   333  	expected = []int{6, 1, 2, 3, 4, 5, 7}
   334  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   335  		require.Equal(t, expected[idx], e.Value)
   336  		return nil
   337  	})
   338  	require.NoError(t, err)
   339  	reverseExpected = []int{7, 5, 4, 3, 2, 1, 6}
   340  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   341  		require.Equal(t, reverseExpected[idx], e.Value)
   342  	})
   343  
   344  	t.Log("test move before")
   345  	dlist.MoveBefore(_6n, _7n)
   346  	dlist2.MoveBefore(_6n_2, _7n_2)
   347  	checkItems()
   348  	expected = []int{1, 2, 3, 4, 5, 6, 7}
   349  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   350  		require.Equal(t, expected[idx], e.Value)
   351  		return nil
   352  	})
   353  	require.NoError(t, err)
   354  	reverseExpected = []int{7, 6, 5, 4, 3, 2, 1}
   355  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   356  		require.Equal(t, reverseExpected[idx], e.Value)
   357  	})
   358  
   359  	t.Log("test move after")
   360  	dlist.MoveAfter(_7n, dlist.Front())
   361  	dlist2.MoveAfter(_7n_2, dlist2.Front())
   362  	checkItems()
   363  	expected = []int{1, 7, 2, 3, 4, 5, 6}
   364  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   365  		require.Equal(t, expected[idx], e.Value)
   366  		return nil
   367  	})
   368  	require.NoError(t, err)
   369  	reverseExpected = []int{6, 5, 4, 3, 2, 7, 1}
   370  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   371  		require.Equal(t, reverseExpected[idx], e.Value)
   372  	})
   373  
   374  	t.Log("test push front list")
   375  	dlist_1 := NewLinkedList[int]()
   376  	dlist_1.AppendValue(8, 9, 10)
   377  	dlist2_1 := list.New()
   378  	dlist2_1.PushBack(8)
   379  	dlist2_1.PushBack(9)
   380  	dlist2_1.PushBack(10)
   381  
   382  	dlist.PushFrontList(dlist_1)
   383  	dlist2.PushFrontList(dlist2_1)
   384  	checkItems()
   385  	expected = []int{8, 9, 10, 1, 7, 2, 3, 4, 5, 6}
   386  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   387  		require.Equal(t, expected[idx], e.Value)
   388  		return nil
   389  	})
   390  	require.NoError(t, err)
   391  	reverseExpected = []int{6, 5, 4, 3, 2, 7, 1, 10, 9, 8}
   392  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   393  		require.Equal(t, reverseExpected[idx], e.Value)
   394  	})
   395  
   396  	t.Log("test push back list")
   397  	dlist_2 := NewLinkedList[int]()
   398  	dlist_2.AppendValue(11, 12, 13)
   399  	dlist2_2 := list.New()
   400  	dlist2_2.PushBack(11)
   401  	dlist2_2.PushBack(12)
   402  	dlist2_2.PushBack(13)
   403  
   404  	dlist.PushBackList(dlist_2)
   405  	dlist2.PushBackList(dlist2_2)
   406  	checkItems()
   407  	expected = []int{8, 9, 10, 1, 7, 2, 3, 4, 5, 6, 11, 12, 13}
   408  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   409  		require.Equal(t, expected[idx], e.Value)
   410  		return nil
   411  	})
   412  	require.NoError(t, err)
   413  	reverseExpected = []int{13, 12, 11, 6, 5, 4, 3, 2, 7, 1, 10, 9, 8}
   414  	dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) {
   415  		require.Equal(t, reverseExpected[idx], e.Value)
   416  	})
   417  }
   418  
   419  func TestDoublyLinkedList_APIsCoverage(t *testing.T) {
   420  	dlist := NewLinkedList[int]()
   421  	dlist2 := list.New()
   422  	checkItems := func() {
   423  		dlistItr := dlist.Front()
   424  		dlist2Itr := dlist2.Front()
   425  		require.NotNil(t, dlistItr)
   426  		require.NotNil(t, dlist2Itr)
   427  		require.Equal(t, int64(dlist2.Len()), dlist.Len())
   428  		for dlist2Itr != nil {
   429  			require.Equal(t, dlist2Itr.Value, dlistItr.Value)
   430  			dlist2Itr = dlist2Itr.Next()
   431  			dlistItr = dlistItr.Next()
   432  		}
   433  	}
   434  
   435  	e1 := dlist.PushFront(1)
   436  	e2 := dlist.PushBack(2)
   437  	dlist.MoveBefore(e2, e1)
   438  
   439  	e1_1 := dlist2.PushFront(1)
   440  	e2_1 := dlist2.PushBack(2)
   441  	dlist2.MoveBefore(e2_1, e1_1)
   442  
   443  	checkItems()
   444  
   445  	e3 := dlist.InsertAfter(3, e1)
   446  	e3_1 := dlist2.InsertAfter(3, e1_1)
   447  	checkItems()
   448  
   449  	expected := []int{2, 1, 3}
   450  	err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   451  		require.Equal(t, expected[idx], e.Value)
   452  		return nil
   453  	})
   454  	require.NoError(t, err)
   455  
   456  	dlist.MoveBefore(e3, e1)
   457  	dlist2.MoveBefore(e3_1, e1_1)
   458  	checkItems()
   459  
   460  	expected = []int{2, 3, 1}
   461  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   462  		require.Equal(t, expected[idx], e.Value)
   463  		return nil
   464  	})
   465  	require.NoError(t, err)
   466  
   467  	dlist.MoveBefore(e2, e3)
   468  	dlist2.MoveBefore(e2_1, e3_1)
   469  	checkItems()
   470  	expected = []int{2, 3, 1}
   471  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   472  		require.Equal(t, expected[idx], e.Value)
   473  		return nil
   474  	})
   475  	require.NoError(t, err)
   476  
   477  	dlist.MoveBefore(e2, e1)
   478  	dlist2.MoveBefore(e2_1, e1_1)
   479  	checkItems()
   480  	expected = []int{3, 2, 1}
   481  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   482  		require.Equal(t, expected[idx], e.Value)
   483  		return nil
   484  	})
   485  	require.NoError(t, err)
   486  
   487  	dlist.MoveBefore(e2, e3)
   488  	dlist2.MoveBefore(e2_1, e3_1)
   489  	checkItems()
   490  	expected = []int{2, 3, 1}
   491  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   492  		require.Equal(t, expected[idx], e.Value)
   493  		return nil
   494  	})
   495  	require.NoError(t, err)
   496  
   497  	dlist.MoveAfter(e2, e3)
   498  	dlist2.MoveAfter(e2_1, e3_1)
   499  	checkItems()
   500  	expected = []int{3, 2, 1}
   501  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   502  		require.Equal(t, expected[idx], e.Value)
   503  		return nil
   504  	})
   505  	require.NoError(t, err)
   506  
   507  	dlist.MoveAfter(e1, e2)
   508  	dlist2.MoveAfter(e1_1, e2_1)
   509  	checkItems()
   510  	expected = []int{3, 2, 1}
   511  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   512  		require.Equal(t, expected[idx], e.Value)
   513  		return nil
   514  	})
   515  	require.NoError(t, err)
   516  
   517  	dlist.MoveAfter(e2, e1)
   518  	dlist2.MoveAfter(e2_1, e1_1)
   519  	checkItems()
   520  	expected = []int{3, 1, 2}
   521  	err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error {
   522  		require.Equal(t, expected[idx], e.Value)
   523  		return nil
   524  	})
   525  	require.NoError(t, err)
   526  
   527  	moved := dlist.MoveAfter(e2, e2)
   528  	require.False(t, moved)
   529  	checkItems()
   530  
   531  	moved = dlist.MoveBefore(e1, e1)
   532  	require.False(t, moved)
   533  	checkItems()
   534  
   535  	moved = dlist.MoveBefore(nil, e1)
   536  	require.False(t, moved)
   537  	checkItems()
   538  
   539  	moved = dlist.MoveBefore(e1, nil)
   540  	require.False(t, moved)
   541  	checkItems()
   542  
   543  	moved = dlist.MoveAfter(nil, e1)
   544  	require.False(t, moved)
   545  	checkItems()
   546  
   547  	moved = dlist.MoveAfter(e1, nil)
   548  	require.False(t, moved)
   549  	checkItems()
   550  
   551  	moved = dlist.MoveToBack(nil)
   552  	require.False(t, moved)
   553  	checkItems()
   554  
   555  	moved = dlist.MoveToFront(nil)
   556  	require.False(t, moved)
   557  	checkItems()
   558  
   559  	var nilE *NodeElement[int] = nil
   560  	require.Nil(t, nilE.Prev())
   561  	require.Nil(t, nilE.Next())
   562  	require.False(t, nilE.HasNext())
   563  	require.False(t, nilE.HasPrev())
   564  }