github.com/randomizedcoder/goTrackRTP@v0.0.2/trackRTP_test.go (about)

     1  package goTrackRTP
     2  
     3  // https://github.com/randomizedcoder/goTrackRTP/
     4  
     5  // See also: https://dave.cheney.net/2019/05/07/prefer-table-driven-tests
     6  
     7  import (
     8  	"math"
     9  	"os"
    10  	"reflect"
    11  	"testing"
    12  	_ "unsafe"
    13  )
    14  
    15  // unsafe for fastrand
    16  
    17  const (
    18  	debugLevelCst        = 11
    19  	WindowSizeTestingCst = 100
    20  )
    21  
    22  // unsafe for the FastRand()
    23  //_ "unsafe"
    24  // //go:linkname FastRand runtime.fastrand
    25  // func FastRand() uint32
    26  
    27  // // https://cs.opensource.google/go/go/+/master:src/runtime/stubs.go;l=151?q=FastRandN&ss=go%2Fgo
    28  // // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
    29  
    30  // //go:linkname FastRandN runtime.fastrandn
    31  // func FastRandN(n uint32) uint32
    32  
    33  func TestTrackerInit(t *testing.T) {
    34  
    35  	type test struct {
    36  		aw     uint16
    37  		bw     uint16
    38  		ab     uint16
    39  		bb     uint16
    40  		err    error
    41  		Window uint16
    42  		Len    int
    43  	}
    44  
    45  	tests := []test{
    46  		// basic
    47  		{10, 10, 10, 10, nil, 10 + 10, 0},
    48  		{100, 100, 100, 100, nil, 200, 0},
    49  		{1500, 1500, 1500, 1500, nil, 1500 + 1500, 0},
    50  		{10, 20, 10, 10, nil, 10 + 20, 0},
    51  
    52  		// errors
    53  		{1, 10, 10, 10, ErrWindowAWMin, 0, 0},
    54  		{1501, 10, 10, 10, ErrWindowAWMax, 0, 0},
    55  		{10, 1, 10, 10, ErrWindowBWMin, 0, 0},
    56  		{10, 1501, 10, 10, ErrWindowBWMax, 0, 0},
    57  		{10, 10, 1, 10, ErrWindowABMin, 0, 0},
    58  		{10, 10, 1501, 10, ErrWindowABMax, 0, 0},
    59  		{10, 10, 10, 1, ErrWindowBBMin, 0, 0},
    60  		{10, 10, 10, 1501, ErrWindowBBMax, 0, 0},
    61  
    62  		// window too small
    63  		{0, 0, 0, 0, ErrWindowAWMin, 0, 0},
    64  		{1, 1, 1, 1, ErrWindowAWMin, 0, 0},
    65  		{3, 3, 3, 3, ErrWindowAWMin, 0, 0},
    66  		{1501, 1501, 1501, 1501, ErrWindowAWMax, 0, 0},
    67  		{1501, 1501, 1501, 1501, ErrWindowAWMax, 0, 0},
    68  	}
    69  
    70  	for i, tc := range tests {
    71  
    72  		t.Logf("%s i:%d, tc: %v\n", t.Name(), i, tc)
    73  
    74  		tr, err := New(tc.aw, tc.bw, tc.ab, tc.bb, debugLevelCst)
    75  
    76  		if err != tc.err {
    77  			t.Fatalf("%s, err:%v != tc.err:%v", t.Name(), err, tc.err)
    78  		}
    79  
    80  		if err == nil {
    81  			if tr.Window != tc.Window {
    82  				t.Fatalf("%s, tr.Window:%d != tc.Window:%d", t.Name(), tr.Window, tc.Window)
    83  			}
    84  
    85  			if tr.Len() != tc.Len {
    86  				t.Fatalf("%s, etr.Len():%d != tc.Len:%d", t.Name(), tr.Len(), tc.Len)
    87  			}
    88  		}
    89  	}
    90  }
    91  
    92  func TestTrackerWindow(t *testing.T) {
    93  
    94  	type test struct {
    95  		aw          uint16
    96  		bw          uint16
    97  		ab          uint16
    98  		bb          uint16
    99  		m           uint16
   100  		seq         uint16
   101  		err         error
   102  		Window      uint16
   103  		Len         int
   104  		Max         uint16
   105  		Jump        uint16
   106  		Position    int
   107  		Category    int
   108  		SubCategory int
   109  	}
   110  
   111  	tests := []test{
   112  		// position duplicate
   113  		{10, 10, 10, 10, 0, 0, nil, 10 + 10, 1, 0, 0, PositionDuplicate, CategoryUnknown, SubCategoryUnknown},
   114  		{10, 10, 10, 10, 1, 1, nil, 10 + 10, 1, 1, 0, PositionDuplicate, CategoryUnknown, SubCategoryUnknown},
   115  		{10, 10, 10, 10, maxUint16, maxUint16, nil, 10 + 10, 1, maxUint16, 0, PositionDuplicate, CategoryUnknown, SubCategoryUnknown},
   116  		{10, 10, 10, 10, maxUint16 - 1, maxUint16 - 1, nil, 10 + 10, 1, maxUint16 - 1, 0, PositionDuplicate, CategoryUnknown, SubCategoryUnknown},
   117  		{100, 100, 100, 100, 0, 0, nil, 100 + 100, 1, 0, 0, PositionDuplicate, CategoryUnknown, SubCategoryUnknown},
   118  		// position ahead - window
   119  		{10, 10, 10, 10, 0, 1, nil, 10 + 10, 2, 1, 1, PositionAhead, CategoryWindow, SubCategoryNext}, // failing here!  max not updating
   120  		{10, 10, 10, 10, 0, 10, nil, 10 + 10, 2, 10, 10, PositionAhead, CategoryWindow, SubCategoryJump},
   121  		{100, 100, 100, 100, 0, 1, nil, 100 + 100, 2, 1, 1, PositionAhead, CategoryWindow, SubCategoryNext},
   122  		{100, 100, 100, 100, 0, 10, nil, 100 + 100, 2, 10, 10, PositionAhead, CategoryWindow, SubCategoryJump},
   123  		{100, 100, 100, 100, 0, 100, nil, 100 + 100, 2, 100, 100, PositionAhead, CategoryWindow, SubCategoryJump},
   124  		// position ahead - buffer
   125  		{10, 10, 10, 10, 0, 11, nil, 10 + 10, 1, 0, 0, PositionAhead, CategoryBuffer, SubCategoryUnknown},
   126  		{10, 10, 10, 10, 0, 15, nil, 10 + 10, 1, 0, 0, PositionAhead, CategoryBuffer, SubCategoryUnknown},
   127  		{10, 10, 10, 10, 0, 19, nil, 10 + 10, 1, 0, 0, PositionAhead, CategoryBuffer, SubCategoryUnknown},
   128  		{10, 10, 10, 10, 0, 20, nil, 10 + 10, 1, 0, 0, PositionAhead, CategoryBuffer, SubCategoryUnknown},
   129  		{100, 100, 100, 100, 0, 101, nil, 100 + 100, 1, 0, 0, PositionAhead, CategoryBuffer, SubCategoryUnknown},
   130  		{100, 100, 100, 100, 0, 200, nil, 100 + 100, 1, 0, 0, PositionAhead, CategoryBuffer, SubCategoryUnknown},
   131  		// position ahead - restart
   132  		{10, 10, 10, 10, 0, 21, nil, 10 + 10, 1, 21, 0, PositionAhead, CategoryRestart, SubCategoryUnknown},
   133  		{10, 10, 10, 10, 0, 100, nil, 10 + 10, 1, 100, 0, PositionAhead, CategoryRestart, SubCategoryUnknown},
   134  		{10, 10, 10, 10, 0, 1000, nil, 10 + 10, 1, 1000, 0, PositionAhead, CategoryRestart, SubCategoryUnknown},
   135  		{100, 100, 100, 100, 0, 201, nil, 100 + 100, 1, 201, 0, PositionAhead, CategoryRestart, SubCategoryUnknown},
   136  		{100, 100, 100, 100, 0, 1000, nil, 100 + 100, 1, 1000, 0, PositionAhead, CategoryRestart, SubCategoryUnknown},
   137  		// position ahead - window
   138  
   139  		// - note because we only insert x2 in this test, we can't test PositionAhead + SubCategoryDuplicate
   140  		// position behind - window
   141  		{10, 10, 10, 10, 0, maxUint16, nil, 10 + 10, 2, 0, 1, PositionBehind, CategoryWindow, SubCategoryUnknown},
   142  		{10, 10, 10, 10, 0, maxUint16 - 5, nil, 10 + 10, 2, 0, 6, PositionBehind, CategoryWindow, SubCategoryUnknown},
   143  		{10, 10, 10, 10, 0, maxUint16 - 9, nil, 10 + 10, 2, 0, 10, PositionBehind, CategoryWindow, SubCategoryUnknown},
   144  		{100, 100, 100, 100, 0, maxUint16, nil, 100 + 100, 2, 0, 1, PositionBehind, CategoryWindow, SubCategoryUnknown},
   145  		// position behind - buffer
   146  		{10, 10, 10, 10, 0, maxUint16 - 10, nil, 10 + 10, 1, 0, 0, PositionBehind, CategoryBuffer, SubCategoryUnknown},
   147  		{10, 10, 10, 10, 0, maxUint16 - 11, nil, 10 + 10, 1, 0, 0, PositionBehind, CategoryBuffer, SubCategoryUnknown},
   148  		{10, 10, 10, 10, 0, maxUint16 - 19, nil, 10 + 10, 1, 0, 0, PositionBehind, CategoryBuffer, SubCategoryUnknown},
   149  		{100, 100, 100, 100, 0, maxUint16 - 100, nil, 100 + 100, 1, 0, 0, PositionBehind, CategoryBuffer, SubCategoryUnknown},
   150  		{100, 100, 100, 100, 0, maxUint16 - 199, nil, 100 + 100, 1, 0, 0, PositionBehind, CategoryBuffer, SubCategoryUnknown},
   151  		// position behind - restart
   152  		{10, 10, 10, 10, 0, maxUint16 - 20, nil, 10 + 10, 1, maxUint16 - 20, 0, PositionBehind, CategoryRestart, SubCategoryUnknown},
   153  		{10, 10, 10, 10, 0, maxUint16 - 100, nil, 10 + 10, 1, maxUint16 - 100, 0, PositionBehind, CategoryRestart, SubCategoryUnknown},
   154  		{10, 10, 10, 10, 0, maxUint16 - 1000, nil, 10 + 10, 1, maxUint16 - 1000, 0, PositionBehind, CategoryRestart, SubCategoryUnknown},
   155  		{100, 100, 100, 100, 0, maxUint16 - 200, nil, 100 + 100, 1, maxUint16 - 200, 0, PositionBehind, CategoryRestart, SubCategoryUnknown},
   156  	}
   157  
   158  	for i, tc := range tests {
   159  
   160  		t.Logf("%s i:%d, tc: %v\n", t.Name(), i, tc)
   161  
   162  		tr, err := New(tc.aw, tc.bw, tc.ab, tc.bb, debugLevelCst)
   163  		if err != tc.err {
   164  			t.Fatalf("%s, err:%v != tc.err:%v", t.Name(), err, tc.err)
   165  		}
   166  
   167  		_, e := tr.PacketArrival(tc.m)
   168  		if e != nil {
   169  			t.Fatalf("%s, err != nil:%v", t.Name(), e)
   170  		}
   171  
   172  		tax, et := tr.PacketArrival(tc.seq)
   173  		if et != nil {
   174  			t.Fatalf("%s, err != nil:%v", t.Name(), et)
   175  		}
   176  
   177  		if !reflect.DeepEqual(tr.Window, tc.Window) {
   178  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tr.Window:%v, tc.Window:%v)", t.Name(), i, tr.Window, tc.Window)
   179  		}
   180  
   181  		if !reflect.DeepEqual(tax.Len, tc.Len) {
   182  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Len:%v, tc.Len:%v)", t.Name(), i, tax.Len, tc.Len)
   183  		}
   184  
   185  		if !reflect.DeepEqual(tr.Max(), tc.Max) {
   186  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tr.Max():%v, tc.Max:%v)", t.Name(), i, tr.Max(), tc.Max)
   187  		}
   188  
   189  		if !reflect.DeepEqual(tax.Jump, tc.Jump) {
   190  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Jump:%v, tc.Jump:%v)", t.Name(), i, tax.Jump, tc.Jump)
   191  		}
   192  
   193  		if !reflect.DeepEqual(tax.Position, tc.Position) {
   194  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Position:%v, tc.Position:%v)", t.Name(), i, tax.Position, tc.Position)
   195  		}
   196  		if !reflect.DeepEqual(tax.Categroy, tc.Category) {
   197  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Categroy:%v, tc.Category:%v)", t.Name(), i, tax.Categroy, tc.Category)
   198  		}
   199  		if !reflect.DeepEqual(tax.SubCategory, tc.SubCategory) {
   200  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.SubCategory:%v, tc.SubCategory:%v)", t.Name(), i, tax.SubCategory, tc.SubCategory)
   201  		}
   202  	}
   203  }
   204  
   205  func TestLongRunningWindow(t *testing.T) {
   206  
   207  	type test struct {
   208  		aw    uint16
   209  		bw    uint16
   210  		ab    uint16
   211  		bb    uint16
   212  		dl    int
   213  		start uint16
   214  		err   error
   215  		loops int64
   216  		Len   int
   217  	}
   218  
   219  	tests := []test{
   220  		{10, 10, 10, 10, 11, 0, nil, 21, 20},
   221  		{10, 10, 10, 10, 11, 0, nil, 41, 20},
   222  		{10, 10, 10, 10, 11, maxUint16 - 10, nil, 41, 20},
   223  		{100, 100, 100, 100, 11, 0, nil, 201, 200},
   224  		{100, 100, 100, 100, 11, 0, nil, 401, 200},
   225  		{100, 100, 100, 100, 11, maxUint16 - 100, nil, 401, 200},
   226  		{1000, 1000, 1000, 1000, 11, 0, nil, 2001, 2000},
   227  		{1000, 1000, 1000, 1000, 11, 0, nil, 4001, 2000},
   228  		{1000, 1000, 1000, 1000, 11, maxUint16 - 1000, nil, 4001, 2000},
   229  		// long
   230  		{10, 10, 10, 10, 0, 0, nil, (math.MaxInt32 * 2) + 21, 20},
   231  		{100, 100, 100, 100, 0, 0, nil, (math.MaxInt32 * 2) + 201, 200},
   232  		{100, 100, 100, 100, 11, 0, nil, (math.MaxInt32 * 2) + 201, 200},
   233  	}
   234  
   235  	if os.Getenv("LONG") != "true" {
   236  		t.Skip("Skipping long test.  Set 'LONG=true' env var to run this")
   237  	}
   238  
   239  	for i, tc := range tests {
   240  
   241  		t.Logf("%s i:%d, tc: %v\n", t.Name(), i, tc)
   242  
   243  		tr, err := New(tc.aw, tc.bw, tc.ab, tc.bb, tc.dl)
   244  		if err != tc.err {
   245  			t.Fatalf("%s, err:%v != tc.err:%v", t.Name(), err, tc.err)
   246  		}
   247  
   248  		var tax *Taxonomy
   249  		var e error
   250  		var loops int64
   251  		var j uint16 = tc.start
   252  		for {
   253  			if tc.dl > 10 {
   254  				t.Logf("%s i:%d, tc: %v, j:%d, loops:%d\n", t.Name(), i, tc, j, loops)
   255  			}
   256  			tax, e = tr.PacketArrival(j)
   257  			if e != nil {
   258  				t.Fatalf("%s, e != nil:%v", t.Name(), e)
   259  			}
   260  			j++
   261  			loops++
   262  			if loops > tc.loops {
   263  				t.Logf("loops:%d > tc.Loops:%d, tr.Max():%d, tax.Len:%d, tr.Min():%d", loops, tc.loops, tr.Max(), tax.Len, tr.Min())
   264  				if tc.dl > 110 {
   265  					t.Logf("items:%v", tr.itemsDescending())
   266  				}
   267  				break
   268  			}
   269  		}
   270  		if !reflect.DeepEqual(tax.Len, tc.Len) {
   271  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Len:%v, tc.Len:%v)", t.Name(), i, tax.Len, tc.Len)
   272  		}
   273  	}
   274  }
   275  
   276  func TestLongRunningBackwardDuplicates(t *testing.T) {
   277  
   278  	type test struct {
   279  		aw          uint16
   280  		bw          uint16
   281  		ab          uint16
   282  		bb          uint16
   283  		dl          int
   284  		start       uint16
   285  		err         error
   286  		loops       int64
   287  		MaxRandJump uint32
   288  		Len         int
   289  	}
   290  
   291  	debugL := 0
   292  
   293  	tests := []test{
   294  		{10, 10, 10, 10, debugL, 0, nil, 21, 10, 20},
   295  		{10, 10, 10, 10, debugL, 0, nil, 41, 10, 20},
   296  		{10, 10, 10, 10, debugL, maxUint16 - 10, nil, 41, 10, 20},
   297  		{100, 100, 100, 100, debugL, 0, nil, 201, 100, 200},
   298  		{100, 100, 100, 100, debugL, 0, nil, 401, 100, 200},
   299  		{100, 100, 100, 100, debugL, maxUint16 - 100, nil, 401, 100, 200},
   300  		{1000, 1000, 1000, 1000, debugL, 0, nil, 2001, 1000, 2000},
   301  		{1000, 1000, 1000, 1000, debugL, 0, nil, 4001, 1000, 2000},
   302  		{1000, 1000, 1000, 1000, debugL, maxUint16 - 1000, nil, 4001, 1000, 2000},
   303  		// long
   304  		{10, 10, 10, 10, 0, 0, nil, (int64(maxUint16) * 3) + 21, 10, 20},
   305  		{100, 100, 100, 100, 0, 0, nil, (int64(maxUint16) * 3) + 201, 100, 200},
   306  		{100, 100, 100, 100, 0, 0, nil, (int64(maxUint16) * 3) + 201, 100, 200},
   307  	}
   308  
   309  	if os.Getenv("LONG") != "true" {
   310  		t.Skip("Skipping long test.  Set 'LONG=true' env var to run this")
   311  	}
   312  
   313  	for i, tc := range tests {
   314  
   315  		t.Logf("%s i:%d, tc: %v\n", t.Name(), i, tc)
   316  
   317  		tr, err := New(tc.aw, tc.bw, tc.ab, tc.bb, tc.dl)
   318  		if err != tc.err {
   319  			t.Fatalf("%s, err:%v != tc.err:%v", t.Name(), err, tc.err)
   320  		}
   321  
   322  		var tax *Taxonomy
   323  		var e error
   324  		var loops int64
   325  		var j uint16 = tc.start
   326  		var dupSent int
   327  		var dup int
   328  		for {
   329  			if tc.dl > 10 {
   330  				t.Logf("%s i:%d, tc: %v, j:%d, loops:%d", t.Name(), i, tc, j, loops)
   331  			}
   332  			tax, e = tr.PacketArrival(j)
   333  			if e != nil {
   334  				t.Fatalf("%s, e != nil:%v", t.Name(), e)
   335  			}
   336  			if loops > int64(tc.MaxRandJump) {
   337  				if tax.SubCategory != SubCategoryNext {
   338  					t.Fatalf("%s, test:%d tax.SubCategory:%v != SubCategoryNext:%v", t.Name(), i, tax.SubCategory, SubCategoryNext)
   339  				}
   340  
   341  				// send a duplicate in the behind window
   342  				r := uint16(FastRandN(tc.MaxRandJump-1) + 1) // FastRandN can return zero (0)
   343  				if tc.dl > 10 {
   344  					t.Logf("%s i:%d, r:%d, j - r:%d", t.Name(), i, r, j-r)
   345  				}
   346  				tax, e = tr.PacketArrival(j - r)
   347  				if e != nil {
   348  					t.Fatalf("%s, e != nil:%v", t.Name(), e)
   349  				}
   350  				dupSent++
   351  				if tax.SubCategory == SubCategoryDuplicate {
   352  					dup++
   353  				} else {
   354  					t.Fatalf("%s, test:%d tax.SubCategory != SubCategoryDuplicate", t.Name(), i)
   355  				}
   356  			}
   357  
   358  			j++
   359  			loops++
   360  			if loops > tc.loops {
   361  				t.Logf("loops:%d > tc.Loops:%d, tr.Max():%d, tax.Len:%d, tr.Min():%d", loops, tc.loops, tr.Max(), tax.Len, tr.Min())
   362  				if tc.dl > 110 {
   363  					t.Logf("items:%v", tr.itemsDescending())
   364  				}
   365  				break
   366  			}
   367  
   368  			if tc.dl > 10 {
   369  				if loops%int64(maxUint16) == 0 {
   370  					t.Logf("loops:%d > tc.Loops:%d, tr.Max():%d, tax.Len:%d, tr.Min():%d", loops, tc.loops, tr.Max(), tax.Len, tr.Min())
   371  				}
   372  			}
   373  		}
   374  		// if !reflect.DeepEqual(tax.Len, tc.Len) {
   375  		// 	t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Len:%v, tc.Len:%v)", t.Name(), i, tax.Len, tc.Len)
   376  		// }
   377  		if dupSent != dup {
   378  			t.Fatalf("%s, test:%d dupSent:%d != dup:%d", t.Name(), i, dupSent, dup)
   379  		} else {
   380  			t.Logf("%s i:%d, tc: %v, j:%d, loops:%d, duplicate test succeeded! dup:%d", t.Name(), i, tc, j, loops, dup)
   381  		}
   382  	}
   383  }
   384  
   385  func TestLongRunningSkipSend(t *testing.T) {
   386  
   387  	type test struct {
   388  		aw      uint16
   389  		bw      uint16
   390  		ab      uint16
   391  		bb      uint16
   392  		dl      int
   393  		start   uint16
   394  		err     error
   395  		loops   int64
   396  		SkipMod int
   397  		MaxSkip int
   398  		Len     int
   399  	}
   400  
   401  	debugL := 11
   402  
   403  	tests := []test{
   404  		{10, 10, 10, 10, debugL, 0, nil, 10, 2, 3, 10},
   405  		{10, 10, 10, 10, debugL, 0, nil, 10, 3, 3, 10},
   406  		{10, 10, 10, 10, debugL, maxUint16 - 10, nil, 10, 5, 3, 10},
   407  		{100, 100, 100, 100, debugL, 0, nil, 100, 2, 3, 100},
   408  		{100, 100, 100, 100, debugL, 0, nil, 100, 3, 3, 100},
   409  		{100, 100, 100, 100, debugL, maxUint16 - 100, nil, 100, 5, 3, 100},
   410  		{1000, 1000, 1000, 1000, debugL, 0, nil, 1000, 10, 2, 1000},
   411  		{1000, 1000, 1000, 1000, debugL, 0, nil, 1000, 20, 3, 1000},
   412  		{1000, 1000, 1000, 1000, debugL, maxUint16 - 1000, nil, 1000, 50, 10, 1000},
   413  	}
   414  
   415  	if os.Getenv("LONG") != "true" {
   416  		t.Skip("Skipping long test.  Set 'LONG=true' env var to run this")
   417  	}
   418  
   419  	for i, tc := range tests {
   420  
   421  		t.Logf("%s i:%d, tc: %v\n", t.Name(), i, tc)
   422  
   423  		tr, err := New(tc.aw, tc.bw, tc.ab, tc.bb, tc.dl)
   424  		if err != tc.err {
   425  			t.Fatalf("%s, err:%v != tc.err:%v", t.Name(), err, tc.err)
   426  		}
   427  
   428  		var tax *Taxonomy
   429  		var e error
   430  		var loops int64
   431  		var j uint16 = tc.start
   432  		var skip int
   433  		for {
   434  			if tc.dl > 10 {
   435  				t.Logf("%s i:%d, tc: %v, j:%d, loops:%d", t.Name(), i, tc, j, loops)
   436  			}
   437  			if loops%int64(tc.SkipMod) == 0 && skip < tc.MaxSkip {
   438  				t.Logf("%s i:%d, loops:%d, j:%d, skip:%d", t.Name(), i, loops, j, skip)
   439  				skip++
   440  			} else {
   441  				tax, e = tr.PacketArrival(j)
   442  				if e != nil {
   443  					t.Fatalf("%s, e != nil:%v", t.Name(), e)
   444  				}
   445  			}
   446  
   447  			j++
   448  			loops++
   449  			if loops > tc.loops {
   450  				t.Logf("loops:%d > tc.Loops:%d, tr.Max():%d, tax.Len:%d, tr.Min():%d", loops, tc.loops, tr.Max(), tax.Len, tr.Min())
   451  				if tc.dl > 110 {
   452  					t.Logf("items:%v", tr.itemsDescending())
   453  				}
   454  				break
   455  			}
   456  
   457  			if tc.dl > 10 {
   458  				if loops%int64(maxUint16) == 0 {
   459  					t.Logf("loops:%d > tc.Loops:%d, tr.Max():%d, tax.Len:%d, tr.Min():%d", loops, tc.loops, tr.Max(), tax.Len, tr.Min())
   460  				}
   461  			}
   462  		}
   463  		if !reflect.DeepEqual(tax.Len-1, tc.Len-skip) {
   464  			t.Fatalf("%s, test:%d !reflect.DeepEqual(tax.Len-1:%v, tc.Len:%v), skip:%d", t.Name(), i, tax.Len-1, tc.Len-skip, skip)
   465  		}
   466  	}
   467  }
   468  
   469  //go:linkname FastRand runtime.fastrand
   470  func FastRand() uint32
   471  
   472  // https://cs.opensource.google/go/go/+/master:src/runtime/stubs.go;l=151?q=FastRandN&ss=go%2Fgo
   473  // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
   474  
   475  //go:linkname FastRandN runtime.fastrandn
   476  func FastRandN(n uint32) uint32