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

     1  package list
     2  
     3  import (
     4  	"cmp"
     5  	"runtime"
     6  	"sort"
     7  	"strconv"
     8  	"sync"
     9  	"sync/atomic"
    10  	"testing"
    11  	"time"
    12  	"unsafe"
    13  
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/benz9527/xboot/lib/id"
    17  	"github.com/benz9527/xboot/lib/infra"
    18  )
    19  
    20  // Auxiliary: records the traverse predecessors and successors info.
    21  type xConcSklAux[K infra.OrderedKey, V any] []*xConcSklNode[K, V]
    22  
    23  // Left part.
    24  func (aux xConcSklAux[K, V]) loadPred(i int32) *xConcSklNode[K, V] {
    25  	return aux[i]
    26  }
    27  
    28  func (aux xConcSklAux[K, V]) storePred(i int32, pred *xConcSklNode[K, V]) {
    29  	aux[i] = pred
    30  }
    31  
    32  func (aux xConcSklAux[K, V]) foreachPred(fn func(list ...*xConcSklNode[K, V])) {
    33  	fn(aux[0:sklMaxLevel]...)
    34  }
    35  
    36  // Right part.
    37  func (aux xConcSklAux[K, V]) loadSucc(i int32) *xConcSklNode[K, V] {
    38  	return aux[sklMaxLevel+i]
    39  }
    40  
    41  func (aux xConcSklAux[K, V]) storeSucc(i int32, succ *xConcSklNode[K, V]) {
    42  	aux[sklMaxLevel+i] = succ
    43  }
    44  
    45  func (aux xConcSklAux[K, V]) foreachSucc(fn func(list ...*xConcSklNode[K, V])) {
    46  	fn(aux[sklMaxLevel:]...)
    47  }
    48  
    49  type xConcSklIndex[K infra.OrderedKey, V any] struct {
    50  	forward *xConcSklNode[K, V]
    51  }
    52  
    53  type xConcSklIndices[W infra.OrderedKey, O any] []*xConcSklIndex[W, O]
    54  
    55  func TestXConcSkl_Indexes(t *testing.T) {
    56  	idx := make(xConcSklIndices[uint8, *xSklObject], 2)
    57  	idx[0] = &xConcSklIndex[uint8, *xSklObject]{
    58  		forward: nil,
    59  	}
    60  	idx[0].forward = &xConcSklNode[uint8, *xSklObject]{}
    61  	idx[0] = &xConcSklIndex[uint8, *xSklObject]{
    62  		forward: nil,
    63  	}
    64  	ptr := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&idx[0].forward)))
    65  	t.Logf("%v\n", ptr)
    66  }
    67  
    68  func TestDecreaseIndexSize(t *testing.T) {
    69  	idxSize := uint64(100)
    70  	atomic.AddUint64(&idxSize, ^uint64(50-1))
    71  	require.Equal(t, uint64(50), idxSize)
    72  }
    73  
    74  func TestXConcSklNodeSize(t *testing.T) {
    75  	node := new(xConcSklNode[int64, []byte])
    76  	size := unsafe.Sizeof(*node)
    77  	t.Log(size)
    78  }
    79  
    80  type vNode[W SkipListWeight, O HashObject] struct {
    81  	weight *atomic.Pointer[W]
    82  	object *atomic.Pointer[O]
    83  	next   *atomic.Pointer[vNode[W, O]]
    84  }
    85  
    86  func TestAtomicPointerCAS(t *testing.T) {
    87  	a := &vNode[uint8, *xSklObject]{
    88  		weight: &atomic.Pointer[uint8]{},
    89  		object: &atomic.Pointer[*xSklObject]{},
    90  		next:   nil,
    91  	}
    92  	w1 := uint8(1)
    93  	o1 := &xSklObject{
    94  		id: "1",
    95  	}
    96  	a.weight.Store(&w1)
    97  	a.object.Store(&o1)
    98  
    99  	b := a
   100  
   101  	w2 := uint8(2)
   102  	o2 := &xSklObject{
   103  		id: "2",
   104  	}
   105  	c := &vNode[uint8, *xSklObject]{
   106  		weight: &atomic.Pointer[uint8]{},
   107  		object: &atomic.Pointer[*xSklObject]{},
   108  		next:   nil,
   109  	}
   110  	c.weight.Store(&w2)
   111  	c.object.Store(&o2)
   112  
   113  	ptr := atomic.Pointer[vNode[uint8, *xSklObject]]{}
   114  	ptr.Store(a)
   115  	res := ptr.CompareAndSwap(b, c)
   116  	require.True(t, res)
   117  	require.Equal(t, c, ptr.Load())
   118  }
   119  
   120  func TestUnsafePointerCAS(t *testing.T) {
   121  	type obj struct {
   122  		id int
   123  	}
   124  	a := &obj{
   125  		id: 1,
   126  	}
   127  	b := a
   128  	c := &obj{
   129  		id: 2,
   130  	}
   131  
   132  	res := atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&a)), unsafe.Pointer(b), unsafe.Pointer(c))
   133  	require.True(t, res)
   134  	require.Equal(t, c, a)
   135  }
   136  
   137  func TestUnsafePointerCAS_ConcurrentMemVisibility(t *testing.T) {
   138  	runtime.GOMAXPROCS(4)
   139  	type obj struct {
   140  		id string
   141  	}
   142  	a := &obj{
   143  		id: "1",
   144  	}
   145  	b := a
   146  	c := &obj{
   147  		id: "2",
   148  	}
   149  
   150  	logC := make(chan string, 1000)
   151  
   152  	var wg sync.WaitGroup
   153  	wg.Add(4)
   154  	go func() {
   155  		for i := 0; i < 200; i++ {
   156  			val := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&a)))
   157  			log := "cas load a vptr, obj: " + (*obj)(val).id + ", id: 1"
   158  			runtime.Gosched()
   159  			logC <- log
   160  		}
   161  		wg.Done()
   162  	}()
   163  	go func() {
   164  		for i := 0; i < 200; i++ {
   165  			val := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&a)))
   166  			log := "cas load a vptr, obj: " + (*obj)(val).id + ", id: 2"
   167  			runtime.Gosched()
   168  			logC <- log
   169  		}
   170  		wg.Done()
   171  	}()
   172  	go func() {
   173  		swapped := false
   174  		for i := 0; i < 50; i++ {
   175  			ms := cryptoRandUint32() % 11
   176  			if ms == 5 && !swapped {
   177  				log := "starting to cas obj to c, id: 1, loop: " + strconv.Itoa(i)
   178  				logC <- log
   179  				swapped = atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&a)), unsafe.Pointer(b), unsafe.Pointer(c))
   180  				if swapped != true {
   181  					log = "cas result is false, id: 1"
   182  					logC <- log
   183  				} else {
   184  					log = "cas result is ok, id: 1"
   185  					logC <- log
   186  				}
   187  			}
   188  		}
   189  		wg.Done()
   190  	}()
   191  	go func() {
   192  		swapped := false
   193  		for i := 0; i < 50; i++ {
   194  			ms := cryptoRandUint32() % 11
   195  			if ms == 6 && !swapped {
   196  				log := "starting to cas obj to c, id: 2, loop: " + strconv.Itoa(i)
   197  				logC <- log
   198  				swapped = atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&a)), unsafe.Pointer(b), unsafe.Pointer(c))
   199  				if swapped != true {
   200  					log = "cas result is false, id: 2"
   201  					logC <- log
   202  				} else {
   203  					log = "cas result is ok, id: 2"
   204  					logC <- log
   205  				}
   206  			}
   207  		}
   208  		wg.Done()
   209  	}()
   210  	go func() {
   211  		for log := range logC {
   212  			t.Log(log)
   213  		}
   214  	}()
   215  	wg.Wait()
   216  	time.Sleep(1 * time.Second)
   217  }
   218  
   219  func TestAuxIndexes(t *testing.T) {
   220  	aux := make(xConcSklAux[uint8, *xSklObject], 2*sklMaxLevel)
   221  	for i := uint8(0); i < 2*sklMaxLevel; i++ {
   222  		aux[i] = &xConcSklNode[uint8, *xSklObject]{
   223  			key: i,
   224  		}
   225  	}
   226  
   227  	for i := uint8(0); i < sklMaxLevel; i++ {
   228  		require.Equal(t, i, aux.loadPred(int32(i)).key)
   229  		require.Equal(t, sklMaxLevel+i, aux.loadSucc(int32(i)).key)
   230  	}
   231  
   232  	aux.foreachPred(func(predList ...*xConcSklNode[uint8, *xSklObject]) {
   233  		for i := uint8(0); i < sklMaxLevel; i++ {
   234  			require.Equal(t, i, predList[i].key)
   235  		}
   236  	})
   237  	aux.foreachSucc(func(succList ...*xConcSklNode[uint8, *xSklObject]) {
   238  		for i := uint8(0); i < sklMaxLevel; i++ {
   239  			require.Equal(t, sklMaxLevel+i, succList[i].key)
   240  		}
   241  	})
   242  }
   243  
   244  // test remove by pred references:
   245  // https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
   246  // https://github.com/minghu6/rust-minghu6/blob/master/coll_st/src/bst/rb.rs
   247  
   248  func TestRbtreeLeftAndRightRotate(t *testing.T) {
   249  	type checkData struct {
   250  		color color
   251  		val   uint64
   252  	}
   253  
   254  	vcmp := func(i, j uint64) int64 {
   255  		if i == j {
   256  			return 0
   257  		} else if i > j {
   258  			return 1
   259  		}
   260  		return -1
   261  	}
   262  
   263  	node := &xConcSklNode[uint64, uint64]{}
   264  	node.rbInsert(52, vcmp)
   265  	expected := []checkData{
   266  		{black, 52},
   267  	}
   268  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   269  		require.Equal(t, expected[idx].color, color)
   270  		require.Equal(t, expected[idx].val, val)
   271  		return true
   272  	})
   273  	require.NoError(t, node.rbRedViolationValidate())
   274  	require.NoError(t, node.rbBlackViolationValidate())
   275  
   276  	node.rbInsert(47, vcmp)
   277  	expected = []checkData{
   278  		{red, 47}, {black, 52},
   279  	}
   280  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   281  		require.Equal(t, expected[idx].color, color)
   282  		require.Equal(t, expected[idx].val, val)
   283  		return true
   284  	})
   285  	require.NoError(t, node.rbRedViolationValidate())
   286  
   287  	node.rbInsert(3, vcmp)
   288  	expected = []checkData{
   289  		{red, 3}, {black, 47}, {red, 52},
   290  	}
   291  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   292  		require.Equal(t, expected[idx].color, color)
   293  		require.Equal(t, expected[idx].val, val)
   294  		return true
   295  	})
   296  	require.NoError(t, node.rbRedViolationValidate())
   297  	require.NoError(t, node.rbBlackViolationValidate())
   298  
   299  	node.rbInsert(35, vcmp)
   300  	expected = []checkData{
   301  		{black, 3},
   302  		{red, 35},
   303  		{black, 47},
   304  		{black, 52},
   305  	}
   306  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   307  		require.Equal(t, expected[idx].color, color)
   308  		require.Equal(t, expected[idx].val, val)
   309  		return true
   310  	})
   311  	require.NoError(t, node.rbRedViolationValidate())
   312  	require.NoError(t, node.rbBlackViolationValidate())
   313  
   314  	node.rbInsert(24, vcmp)
   315  	expected = []checkData{
   316  		{red, 3},
   317  		{black, 24},
   318  		{red, 35},
   319  		{black, 47},
   320  		{black, 52},
   321  	}
   322  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   323  		require.Equal(t, expected[idx].color, color)
   324  		require.Equal(t, expected[idx].val, val)
   325  		return true
   326  	})
   327  	require.NoError(t, node.rbRedViolationValidate())
   328  	require.NoError(t, node.rbBlackViolationValidate())
   329  
   330  	// remove
   331  
   332  	x, err := node.rbRemove(24, vcmp)
   333  	require.NoError(t, err)
   334  	require.Equal(t, uint64(24), *x.vptr)
   335  	expected = []checkData{
   336  		{black, 3},
   337  		{red, 35},
   338  		{black, 47},
   339  		{black, 52},
   340  	}
   341  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   342  		require.Equal(t, expected[idx].color, color)
   343  		require.Equal(t, expected[idx].val, val)
   344  		return true
   345  	})
   346  	require.NoError(t, node.rbRedViolationValidate())
   347  	require.NoError(t, node.rbBlackViolationValidate())
   348  
   349  	x, err = node.rbRemove(47, vcmp)
   350  	require.NoError(t, err)
   351  	require.Equal(t, uint64(47), *x.vptr)
   352  	expected = []checkData{
   353  		{black, 3},
   354  		{black, 35},
   355  		{black, 52},
   356  	}
   357  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   358  		require.Equal(t, expected[idx].color, color)
   359  		require.Equal(t, expected[idx].val, val)
   360  		return true
   361  	})
   362  	require.NoError(t, node.rbRedViolationValidate())
   363  	require.NoError(t, node.rbBlackViolationValidate())
   364  
   365  	x, err = node.rbRemove(52, vcmp)
   366  	require.NoError(t, err)
   367  	require.Equal(t, uint64(52), *x.vptr)
   368  	expected = []checkData{
   369  		{red, 3}, {black, 35},
   370  	}
   371  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   372  		require.Equal(t, expected[idx].color, color)
   373  		require.Equal(t, expected[idx].val, val)
   374  		return true
   375  	})
   376  	require.NoError(t, node.rbRedViolationValidate())
   377  	require.NoError(t, node.rbBlackViolationValidate())
   378  
   379  	x, err = node.rbRemove(3, vcmp)
   380  	require.NoError(t, err)
   381  	require.Equal(t, uint64(3), *x.vptr)
   382  	expected = []checkData{
   383  		{black, 35},
   384  	}
   385  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   386  		require.Equal(t, expected[idx].color, color)
   387  		require.Equal(t, expected[idx].val, val)
   388  		return true
   389  	})
   390  	require.NoError(t, node.rbRedViolationValidate())
   391  	require.NoError(t, node.rbBlackViolationValidate())
   392  
   393  	x, err = node.rbRemove(35, vcmp)
   394  	require.NoError(t, err)
   395  	require.Equal(t, uint64(35), *x.vptr)
   396  	require.Equal(t, int64(0), atomic.LoadInt64(&node.count))
   397  }
   398  
   399  func TestRbtree_RemoveMin(t *testing.T) {
   400  	type checkData struct {
   401  		color color
   402  		val   uint64
   403  	}
   404  
   405  	vcmp := func(i, j uint64) int64 {
   406  		if i == j {
   407  			return 0
   408  		} else if i > j {
   409  			return 1
   410  		}
   411  		return -1
   412  	}
   413  
   414  	node := &xConcSklNode[uint64, uint64]{}
   415  	node.rbInsert(52, vcmp)
   416  	node.rbInsert(47, vcmp)
   417  	node.rbInsert(3, vcmp)
   418  	node.rbInsert(35, vcmp)
   419  	node.rbInsert(24, vcmp)
   420  	expected := []checkData{
   421  		{red, 3},
   422  		{black, 24},
   423  		{red, 35},
   424  		{black, 47},
   425  		{black, 52},
   426  	}
   427  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   428  		require.Equal(t, expected[idx].color, color)
   429  		require.Equal(t, expected[idx].val, val)
   430  		return true
   431  	})
   432  
   433  	// remove min
   434  
   435  	x, err := node.rbRemoveMin()
   436  	require.NoError(t, err)
   437  	require.Equal(t, uint64(3), *x.vptr)
   438  	expected = []checkData{
   439  		{black, 24},
   440  		{red, 35},
   441  		{black, 47},
   442  		{black, 52},
   443  	}
   444  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   445  		require.Equal(t, expected[idx].color, color)
   446  		require.Equal(t, expected[idx].val, val)
   447  		return true
   448  	})
   449  	require.NoError(t, node.rbRedViolationValidate())
   450  	require.NoError(t, node.rbBlackViolationValidate())
   451  
   452  	x, err = node.rbRemoveMin()
   453  	require.NoError(t, err)
   454  	require.Equal(t, uint64(24), *x.vptr)
   455  	expected = []checkData{
   456  		{black, 35},
   457  		{black, 47},
   458  		{black, 52},
   459  	}
   460  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   461  		require.Equal(t, expected[idx].color, color)
   462  		require.Equal(t, expected[idx].val, val)
   463  		return true
   464  	})
   465  	require.NoError(t, node.rbRedViolationValidate())
   466  	require.NoError(t, node.rbBlackViolationValidate())
   467  
   468  	x, err = node.rbRemoveMin()
   469  	require.NoError(t, err)
   470  	require.Equal(t, uint64(35), *x.vptr)
   471  	expected = []checkData{
   472  		{black, 47}, {red, 52},
   473  	}
   474  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   475  		require.Equal(t, expected[idx].color, color)
   476  		require.Equal(t, expected[idx].val, val)
   477  		return true
   478  	})
   479  	require.NoError(t, node.rbRedViolationValidate())
   480  	require.NoError(t, node.rbBlackViolationValidate())
   481  
   482  	x, err = node.rbRemoveMin()
   483  	require.NoError(t, err)
   484  	require.Equal(t, uint64(47), *x.vptr)
   485  	expected = []checkData{
   486  		{black, 52},
   487  	}
   488  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   489  		require.Equal(t, expected[idx].color, color)
   490  		require.Equal(t, expected[idx].val, val)
   491  		return true
   492  	})
   493  	require.NoError(t, node.rbRedViolationValidate())
   494  	require.NoError(t, node.rbBlackViolationValidate())
   495  
   496  	x, err = node.rbRemoveMin()
   497  	require.NoError(t, err)
   498  	require.Equal(t, uint64(52), *x.vptr)
   499  	require.Equal(t, int64(0), atomic.LoadInt64(&node.count))
   500  }
   501  
   502  func xConcSklNodeRandomInsertAndRemoveRbtreeSequentialNumberRunCore(t *testing.T, rbRmBySucc bool) {
   503  	total := uint64(1000)
   504  	insertTotal := uint64(float64(total) * 0.8)
   505  	removeTotal := uint64(float64(total) * 0.2)
   506  
   507  	vcmp := func(i, j uint64) int64 {
   508  		if i == j {
   509  			return 0
   510  		} else if i > j {
   511  			return 1
   512  		}
   513  		return -1
   514  	}
   515  
   516  	node := &xConcSklNode[uint64, uint64]{}
   517  	if rbRmBySucc {
   518  		node.flags = set(node.flags, nodeRbRmBorrowFlagBit)
   519  	}
   520  
   521  	for i := uint64(0); i < insertTotal; i++ {
   522  		node.rbInsert(i, vcmp)
   523  		require.NoError(t, node.rbRedViolationValidate())
   524  		require.NoError(t, node.rbBlackViolationValidate())
   525  	}
   526  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   527  		require.Equal(t, uint64(idx), val)
   528  		return true
   529  	})
   530  
   531  	for i := insertTotal; i < removeTotal+insertTotal; i++ {
   532  		node.rbInsert(i, vcmp)
   533  		require.NoError(t, node.rbRedViolationValidate())
   534  		require.NoError(t, node.rbBlackViolationValidate())
   535  	}
   536  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   537  		require.Equal(t, uint64(idx), val)
   538  		return true
   539  	})
   540  
   541  	for i := insertTotal; i < removeTotal+insertTotal; i++ {
   542  		if i == 92 {
   543  			x := node.rbSearch(node.root, func(x *xNode[uint64]) int64 {
   544  				return vcmp(i, *x.vptr)
   545  			})
   546  			require.Equal(t, uint64(92), *x.vptr)
   547  		}
   548  		x, err := node.rbRemove(i, vcmp)
   549  		require.NoError(t, err)
   550  		require.Equal(t, i, *x.vptr)
   551  		require.NoError(t, node.rbRedViolationValidate())
   552  		require.NoError(t, node.rbBlackViolationValidate())
   553  	}
   554  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   555  		require.Equal(t, uint64(idx), val)
   556  		return true
   557  	})
   558  }
   559  
   560  func TestRandomInsertAndRemoveRbtree_SequentialNumber(t *testing.T) {
   561  	type testcase struct {
   562  		name       string
   563  		rbRmBySucc bool
   564  	}
   565  	testcases := []testcase{
   566  		{
   567  			name: "rm by pred",
   568  		},
   569  		{
   570  			name:       "rm by succ",
   571  			rbRmBySucc: true,
   572  		},
   573  	}
   574  	for _, tc := range testcases {
   575  		t.Run(tc.name, func(tt *testing.T) {
   576  			xConcSklNodeRandomInsertAndRemoveRbtreeSequentialNumberRunCore(tt, tc.rbRmBySucc)
   577  		})
   578  	}
   579  }
   580  
   581  func TestRandomInsertAndRemoveRbtree_SequentialNumber_Release(t *testing.T) {
   582  	insertTotal := uint64(100000)
   583  
   584  	vcmp := func(i, j uint64) int64 {
   585  		if i == j {
   586  			return 0
   587  		} else if i > j {
   588  			return 1
   589  		}
   590  		return -1
   591  	}
   592  
   593  	node := &xConcSklNode[uint64, uint64]{}
   594  
   595  	rand := uint64(cryptoRandUint32() % 1000)
   596  	for i := uint64(0); i < insertTotal; i++ {
   597  		node.rbInsert(i, vcmp)
   598  		if i%1000 == rand {
   599  			require.NoError(t, node.rbRedViolationValidate())
   600  			require.NoError(t, node.rbBlackViolationValidate())
   601  		}
   602  	}
   603  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   604  		require.Equal(t, uint64(idx), val)
   605  		return true
   606  	})
   607  	node.rbRelease()
   608  	require.Equal(t, int64(0), node.count)
   609  	require.Nil(t, node.root)
   610  }
   611  
   612  func TestRandomInsertAndRemoveRbtree_ReverseSequentialNumber(t *testing.T) {
   613  	total := int64(10000)
   614  	insertTotal := int64(float64(total) * 0.8)
   615  	removeTotal := int64(float64(total) * 0.2)
   616  
   617  	vcmp := func(i, j int64) int64 {
   618  		if i == j {
   619  			return 0
   620  		} else if i > j {
   621  			return 1
   622  		}
   623  		return -1
   624  	}
   625  
   626  	node := &xConcSklNode[uint64, int64]{}
   627  
   628  	rand := int64(cryptoRandUint32() % 1000)
   629  	for i := insertTotal - 1; i >= 0; i-- {
   630  		node.rbInsert(i, vcmp)
   631  		if i%1000 == rand {
   632  			require.NoError(t, node.rbRedViolationValidate())
   633  			require.NoError(t, node.rbBlackViolationValidate())
   634  		}
   635  	}
   636  	node.rbDFS(func(idx int64, color color, val int64) bool {
   637  		require.Equal(t, int64(idx), val)
   638  		return true
   639  	})
   640  
   641  	for i := removeTotal + insertTotal - 1; i >= insertTotal; i-- {
   642  		node.rbInsert(i, vcmp)
   643  	}
   644  	node.rbDFS(func(idx int64, color color, val int64) bool {
   645  		require.Equal(t, int64(idx), val)
   646  		return true
   647  	})
   648  
   649  	for i := insertTotal; i < removeTotal+insertTotal; i++ {
   650  		if i == 92 {
   651  			x := node.rbSearch(node.root, func(x *xNode[int64]) int64 {
   652  				return vcmp(i, *x.vptr)
   653  			})
   654  			require.Equal(t, int64(92), *x.vptr)
   655  		}
   656  		x, err := node.rbRemove(i, vcmp)
   657  		require.NoError(t, err)
   658  		require.Equal(t, i, *x.vptr)
   659  	}
   660  	node.rbDFS(func(idx int64, color color, val int64) bool {
   661  		require.Equal(t, int64(idx), val)
   662  		return true
   663  	})
   664  }
   665  
   666  func xConcSklNodeRandomInsertAndRemoveRbtreeRandomMonoNumberRunCore(t *testing.T, total uint64, rbRmBySucc bool, violationCheck bool) {
   667  	insertTotal := uint64(float64(total) * 0.8)
   668  	removeTotal := uint64(float64(total) * 0.2)
   669  
   670  	idGen, _ := id.MonotonicNonZeroID()
   671  	insertElements := make([]uint64, 0, insertTotal)
   672  	removeElements := make([]uint64, 0, removeTotal)
   673  
   674  	ignore := uint32(0)
   675  	for {
   676  		num := idGen.Number()
   677  		if ignore > 0 {
   678  			ignore--
   679  			continue
   680  		}
   681  		ignore = cryptoRandUint32() % 100
   682  		if ignore&0x1 == 0 && uint64(len(insertElements)) < insertTotal {
   683  			insertElements = append(insertElements, num)
   684  		} else if ignore&0x1 == 1 && uint64(len(removeElements)) < removeTotal {
   685  			removeElements = append(removeElements, num)
   686  		}
   687  		if uint64(len(insertElements)) == insertTotal && uint64(len(removeElements)) == removeTotal {
   688  			break
   689  		}
   690  	}
   691  
   692  	shuffle := func(arr []uint64) {
   693  		count := uint32(len(arr) >> 2)
   694  		for i := uint32(0); i < count; i++ {
   695  			j := cryptoRandUint32() % (i + 1)
   696  			arr[i], arr[j] = arr[j], arr[i]
   697  		}
   698  	}
   699  
   700  	shuffle(insertElements)
   701  	shuffle(removeElements)
   702  
   703  	vcmp := func(i, j uint64) int64 {
   704  		if i == j {
   705  			return 0
   706  		} else if i > j {
   707  			return 1
   708  		}
   709  		return -1
   710  	}
   711  
   712  	node := &xConcSklNode[uint64, uint64]{}
   713  	if rbRmBySucc {
   714  		set(node.flags, nodeRbRmBorrowFlagBit)
   715  	}
   716  
   717  	for i := uint64(0); i < insertTotal; i++ {
   718  		node.rbInsert(insertElements[i], vcmp)
   719  		if violationCheck {
   720  			require.NoError(t, node.rbRedViolationValidate())
   721  			require.NoError(t, node.rbBlackViolationValidate())
   722  		}
   723  	}
   724  	sort.Slice(insertElements, func(i, j int) bool {
   725  		return insertElements[i] < insertElements[j]
   726  	})
   727  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   728  		require.Equal(t, insertElements[idx], val)
   729  		return true
   730  	})
   731  
   732  	for i := uint64(0); i < removeTotal; i++ {
   733  		node.rbInsert(removeElements[i], vcmp)
   734  		if violationCheck {
   735  			require.NoError(t, node.rbRedViolationValidate())
   736  			require.NoError(t, node.rbBlackViolationValidate())
   737  		}
   738  	}
   739  	require.NoError(t, node.rbRedViolationValidate())
   740  	require.NoError(t, node.rbBlackViolationValidate())
   741  
   742  	for i := uint64(0); i < removeTotal; i++ {
   743  		x, err := node.rbRemove(removeElements[i], vcmp)
   744  		require.NoError(t, err)
   745  		require.Equalf(t, removeElements[i], *x.vptr, "value exp: %d, real: %d\n", removeElements[i], *x.vptr)
   746  		if violationCheck {
   747  			require.NoError(t, node.rbRedViolationValidate())
   748  			require.NoError(t, node.rbBlackViolationValidate())
   749  		}
   750  	}
   751  	node.rbDFS(func(idx int64, color color, val uint64) bool {
   752  		require.Equal(t, insertElements[idx], val)
   753  		return true
   754  	})
   755  }
   756  
   757  func TestRandomInsertAndRemoveRbtree_RandomMonotonicNumber(t *testing.T) {
   758  	type testcase struct {
   759  		name           string
   760  		rbRmBySucc     bool
   761  		total          uint64
   762  		violationCheck bool
   763  	}
   764  	testcases := []testcase{
   765  		{
   766  			name:  "rm by pred 1000000",
   767  			total: 1000000,
   768  		},
   769  		{
   770  			name:       "rm by succ 1000000",
   771  			rbRmBySucc: true,
   772  			total:      1000000,
   773  		},
   774  		{
   775  			name:           "violation check rm by pred 10000",
   776  			total:          10000,
   777  			violationCheck: true,
   778  		},
   779  		{
   780  			name:           "violation check rm by succ 10000",
   781  			rbRmBySucc:     true,
   782  			total:          10000,
   783  			violationCheck: true,
   784  		},
   785  		{
   786  			name:           "violation check rm by pred 20000",
   787  			total:          20000,
   788  			violationCheck: true,
   789  		},
   790  		{
   791  			name:           "violation check rm by succ 20000",
   792  			rbRmBySucc:     true,
   793  			total:          20000,
   794  			violationCheck: true,
   795  		},
   796  	}
   797  	t.Parallel()
   798  	for _, tc := range testcases {
   799  		t.Run(tc.name, func(tt *testing.T) {
   800  			xConcSklNodeRandomInsertAndRemoveRbtreeRandomMonoNumberRunCore(tt, tc.total, tc.rbRmBySucc, tc.violationCheck)
   801  		})
   802  	}
   803  }
   804  
   805  func TestXConcSklNodeGen(t *testing.T) {
   806  	for lvl := int32(1); lvl <= sklMaxLevel; lvl++ {
   807  		genXConcSklUniqueNode[string, int]("123", 1, lvl)
   808  	}
   809  	require.Panics(t, func() {
   810  		genXConcSklUniqueNode[string, int]("123", 1, 0)
   811  	})
   812  
   813  	for lvl := int32(1); lvl <= sklMaxLevel; lvl++ {
   814  		genXConcSklLinkedListNode[string, int]("123", 1, lvl)
   815  	}
   816  	require.Panics(t, func() {
   817  		genXConcSklLinkedListNode[string, int]("123", 1, 0)
   818  	})
   819  
   820  	vcmp := func(i, j int) int64 {
   821  		return int64(cmp.Compare[int](i, j))
   822  	}
   823  	for lvl := int32(1); lvl <= sklMaxLevel; lvl++ {
   824  		genXConcSklRbtreeNode[string, int]("123", 1, vcmp, lvl)
   825  	}
   826  	require.Panics(t, func() {
   827  		genXConcSklRbtreeNode[string, int]("123", 1, vcmp, 0)
   828  	})
   829  }