github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/ss2022/slidingwindow_test.go (about)

     1  package ss2022
     2  
     3  import (
     4  	"strconv"
     5  	"testing"
     6  )
     7  
     8  func testIsOkMustAdd(t *testing.T, f *SlidingWindowFilter) {
     9  	f.Reset()
    10  	i := uint64(1)
    11  	n := uint64(len(f.ring)+1) * swfBlockBits
    12  
    13  	// Add 1, 3, 5, ..., n-1.
    14  	for ; i < n; i += 2 {
    15  		if !f.IsOk(i) {
    16  			t.Error(i, "should be ok.")
    17  		}
    18  		f.MustAdd(i)
    19  	}
    20  
    21  	// Check 0, 2, 4, ..., 126.
    22  	for i = 0; i < n-f.size; i += 2 {
    23  		if f.IsOk(i) {
    24  			t.Error(i, "should not be ok.")
    25  		}
    26  	}
    27  
    28  	// Check 128, 130, 132, ..., n-2.
    29  	for ; i < n; i += 2 {
    30  		if !f.IsOk(i) {
    31  			t.Error(i, "should be ok.")
    32  		}
    33  	}
    34  
    35  	// Check 1, 3, 5, ..., n-1.
    36  	for i = 1; i < n; i += 2 {
    37  		if f.IsOk(i) {
    38  			t.Error(i, "should not be ok.")
    39  		}
    40  	}
    41  
    42  	// Roll over the window.
    43  	n <<= 1
    44  	if !f.IsOk(n) {
    45  		t.Error(n, "should be ok.")
    46  	}
    47  	f.MustAdd(n)
    48  
    49  	// Check behind window.
    50  	for i = 0; i < n-f.size+1; i++ {
    51  		if f.IsOk(i) {
    52  			t.Error(i, "should not be ok.")
    53  		}
    54  	}
    55  
    56  	// Check within window.
    57  	for ; i < n; i++ {
    58  		if !f.IsOk(i) {
    59  			t.Error(i, "should be ok.")
    60  		}
    61  	}
    62  
    63  	// Check n.
    64  	if i == n {
    65  		if f.IsOk(i) {
    66  			t.Error(i, "should not be ok.")
    67  		}
    68  		i++
    69  	}
    70  
    71  	// Check after window.
    72  	for ; i < n+f.size; i++ {
    73  		if !f.IsOk(i) {
    74  			t.Error(i, "should be ok.")
    75  		}
    76  	}
    77  }
    78  
    79  func testAdd(t *testing.T, f *SlidingWindowFilter) {
    80  	f.Reset()
    81  	i := uint64(1)
    82  	n := uint64(len(f.ring)+1) * swfBlockBits
    83  
    84  	// Add 1, 3, 5, ..., n-1.
    85  	for ; i < n; i += 2 {
    86  		if !f.Add(i) {
    87  			t.Error(i, "should succeed.")
    88  		}
    89  	}
    90  
    91  	// Check 0, 2, 4, ..., 126.
    92  	for i = 0; i < n-f.size; i += 2 {
    93  		if f.Add(i) {
    94  			t.Error(i, "should fail.")
    95  		}
    96  	}
    97  
    98  	// Check 128, 130, 132, ..., n-2.
    99  	for ; i < n; i += 2 {
   100  		if !f.Add(i) {
   101  			t.Error(i, "should succeed.")
   102  		}
   103  	}
   104  
   105  	// Check 1, 3, 5, ..., n-1.
   106  	for i = 1; i < n; i += 2 {
   107  		if f.Add(i) {
   108  			t.Error(i, "should fail.")
   109  		}
   110  	}
   111  
   112  	// Roll over the window.
   113  	n <<= 1
   114  	if !f.Add(n) {
   115  		t.Error(n, "should succeed.")
   116  	}
   117  
   118  	// Check behind window.
   119  	for i = 0; i < n-f.size+1; i++ {
   120  		if f.Add(i) {
   121  			t.Error(i, "should fail.")
   122  		}
   123  	}
   124  
   125  	// Check within window.
   126  	for ; i < n; i++ {
   127  		if !f.Add(i) {
   128  			t.Error(i, "should succeed.")
   129  		}
   130  	}
   131  
   132  	// Check n.
   133  	if i == n {
   134  		if f.Add(i) {
   135  			t.Error(i, "should fail.")
   136  		}
   137  		i++
   138  	}
   139  
   140  	// Check after window.
   141  	for ; i < n+f.size; i++ {
   142  		if !f.Add(i) {
   143  			t.Error(i, "should succeed.")
   144  		}
   145  	}
   146  }
   147  
   148  func testReset(t *testing.T, f *SlidingWindowFilter) {
   149  	n := f.Size() * 2
   150  
   151  	for i := uint64(0); i < n; i++ {
   152  		f.MustAdd(i)
   153  	}
   154  
   155  	f.Reset()
   156  
   157  	for i := uint64(0); i < n; i++ {
   158  		if !f.IsOk(i) {
   159  			t.Error(i, "should be ok.")
   160  		}
   161  	}
   162  }
   163  
   164  func testSlidingWindowFilter(t *testing.T, f *SlidingWindowFilter) {
   165  	t.Run("IsOkMustAdd", func(t *testing.T) {
   166  		testIsOkMustAdd(t, f)
   167  	})
   168  	t.Run("Add", func(t *testing.T) {
   169  		testAdd(t, f)
   170  	})
   171  	t.Run("Reset", func(t *testing.T) {
   172  		testReset(t, f)
   173  	})
   174  }
   175  
   176  func TestSlidingWindowFilter(t *testing.T) {
   177  	sizes := []uint64{0, 1, 2, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255, 256, 257}
   178  	for _, size := range sizes {
   179  		t.Run(strconv.FormatUint(size, 10), func(t *testing.T) {
   180  			f := NewSlidingWindowFilter(size)
   181  			t.Log("ringBlockIndexMask", f.ringBlockIndexMask)
   182  			testSlidingWindowFilter(t, f)
   183  		})
   184  	}
   185  }