github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/queues/circularbuffer/circularbuffer_test.go (about)

     1  package circularbuffer
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  )
     9  
    10  func TestQueueEnqueue(t *testing.T) {
    11  	queue := New[int](3)
    12  	if actualValue := queue.Empty(); actualValue != true {
    13  		t.Errorf("Got %v expected %v", actualValue, true)
    14  	}
    15  	queue.Enqueue(1)
    16  	queue.Enqueue(2)
    17  	queue.Enqueue(3)
    18  
    19  	if actualValue := queue.Values(); actualValue[0] != 1 || actualValue[1] != 2 || actualValue[2] != 3 {
    20  		t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
    21  	}
    22  	if actualValue := queue.Empty(); actualValue != false {
    23  		t.Errorf("Got %v expected %v", actualValue, false)
    24  	}
    25  	if actualValue := queue.Size(); actualValue != 3 {
    26  		t.Errorf("Got %v expected %v", actualValue, 3)
    27  	}
    28  	if actualValue, ok := queue.Peek(); actualValue != 1 || !ok {
    29  		t.Errorf("Got %v expected %v", actualValue, 1)
    30  	}
    31  }
    32  
    33  func TestQueuePeek(t *testing.T) {
    34  	queue := New[int](3)
    35  	if actualValue, ok := queue.Peek(); actualValue != 0 || ok {
    36  		t.Errorf("Got %v expected %v", actualValue, nil)
    37  	}
    38  	queue.Enqueue(1)
    39  	queue.Enqueue(2)
    40  	queue.Enqueue(3)
    41  	if actualValue, ok := queue.Peek(); actualValue != 1 || !ok {
    42  		t.Errorf("Got %v expected %v", actualValue, 1)
    43  	}
    44  }
    45  
    46  func TestQueueDequeue(t *testing.T) {
    47  	assert := func(actualValue interface{}, expectedValue interface{}) {
    48  		if actualValue != expectedValue {
    49  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
    50  		}
    51  	}
    52  
    53  	queue := New[int](3)
    54  	assert(queue.Empty(), true)
    55  	assert(queue.Empty(), true)
    56  	assert(queue.Full(), false)
    57  	assert(queue.Size(), 0)
    58  	queue.Enqueue(1)
    59  	assert(queue.Size(), 1)
    60  	queue.Enqueue(2)
    61  	assert(queue.Size(), 2)
    62  
    63  	queue.Enqueue(3)
    64  	assert(queue.Size(), 3)
    65  	assert(queue.Empty(), false)
    66  	assert(queue.Full(), true)
    67  
    68  	queue.Dequeue()
    69  	assert(queue.Size(), 2)
    70  
    71  	if actualValue, ok := queue.Peek(); actualValue != 2 || !ok {
    72  		t.Errorf("Got %v expected %v", actualValue, 2)
    73  	}
    74  	assert(queue.Size(), 2)
    75  
    76  	if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok {
    77  		t.Errorf("Got %v expected %v", actualValue, 2)
    78  	}
    79  	assert(queue.Size(), 1)
    80  
    81  	if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
    82  		t.Errorf("Got %v expected %v", actualValue, 3)
    83  	}
    84  	assert(queue.Size(), 0)
    85  	assert(queue.Empty(), true)
    86  	assert(queue.Full(), false)
    87  
    88  	if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
    89  		t.Errorf("Got %v expected %v", actualValue, nil)
    90  	}
    91  	assert(queue.Size(), 0)
    92  
    93  	assert(queue.Empty(), true)
    94  	assert(queue.Full(), false)
    95  	assert(len(queue.Values()), 0)
    96  }
    97  
    98  func TestQueueDequeueFull(t *testing.T) {
    99  	assert := func(actualValue interface{}, expectedValue interface{}) {
   100  		if actualValue != expectedValue {
   101  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   102  		}
   103  	}
   104  
   105  	queue := New[int](2)
   106  	assert(queue.Empty(), true)
   107  	assert(queue.Full(), false)
   108  	assert(queue.Size(), 0)
   109  
   110  	queue.Enqueue(1)
   111  	assert(queue.Size(), 1)
   112  
   113  	queue.Enqueue(2)
   114  	assert(queue.Size(), 2)
   115  	assert(queue.Full(), true)
   116  	if actualValue, ok := queue.Peek(); actualValue != 1 || !ok {
   117  		t.Errorf("Got %v expected %v", actualValue, 2)
   118  	}
   119  	queue.Enqueue(3) // overwrites 1
   120  	assert(queue.Size(), 2)
   121  
   122  	if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok {
   123  		t.Errorf("Got %v expected %v", actualValue, 2)
   124  	}
   125  	if actualValue, expectedValue := queue.Size(), 1; actualValue != expectedValue {
   126  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   127  	}
   128  
   129  	if actualValue, ok := queue.Peek(); actualValue != 3 || !ok {
   130  		t.Errorf("Got %v expected %v", actualValue, 3)
   131  	}
   132  	if actualValue, expectedValue := queue.Size(), 1; actualValue != expectedValue {
   133  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   134  	}
   135  
   136  	if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
   137  		t.Errorf("Got %v expected %v", actualValue, 3)
   138  	}
   139  	assert(queue.Size(), 0)
   140  
   141  	if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
   142  		t.Errorf("Got %v expected %v", actualValue, nil)
   143  	}
   144  	assert(queue.Empty(), true)
   145  	assert(queue.Full(), false)
   146  	assert(len(queue.Values()), 0)
   147  }
   148  
   149  func TestQueueIteratorOnEmpty(t *testing.T) {
   150  	queue := New[int](3)
   151  	it := queue.Iterator()
   152  	for it.Next() {
   153  		t.Errorf("Shouldn't iterate on empty queue")
   154  	}
   155  }
   156  
   157  func TestQueueIteratorNext(t *testing.T) {
   158  	queue := New[string](3)
   159  	queue.Enqueue("a")
   160  	queue.Enqueue("b")
   161  	queue.Enqueue("c")
   162  
   163  	it := queue.Iterator()
   164  	count := 0
   165  	for it.Next() {
   166  		count++
   167  		index := it.Index()
   168  		value := it.Value()
   169  		switch index {
   170  		case 0:
   171  			if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
   172  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   173  			}
   174  		case 1:
   175  			if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
   176  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   177  			}
   178  		case 2:
   179  			if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
   180  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   181  			}
   182  		default:
   183  			t.Errorf("Too many")
   184  		}
   185  		if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
   186  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   187  		}
   188  	}
   189  	if actualValue, expectedValue := count, 3; actualValue != expectedValue {
   190  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   191  	}
   192  
   193  	queue.Clear()
   194  	it = queue.Iterator()
   195  	for it.Next() {
   196  		t.Errorf("Shouldn't iterate on empty queue")
   197  	}
   198  }
   199  
   200  func TestQueueIteratorPrev(t *testing.T) {
   201  	queue := New[string](3)
   202  	queue.Enqueue("a")
   203  	queue.Enqueue("b")
   204  	queue.Enqueue("c")
   205  
   206  	it := queue.Iterator()
   207  	for it.Next() {
   208  	}
   209  	count := 0
   210  	for it.Prev() {
   211  		count++
   212  		index := it.Index()
   213  		value := it.Value()
   214  		switch index {
   215  		case 0:
   216  			if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
   217  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   218  			}
   219  		case 1:
   220  			if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
   221  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   222  			}
   223  		case 2:
   224  			if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
   225  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   226  			}
   227  		default:
   228  			t.Errorf("Too many")
   229  		}
   230  		if actualValue, expectedValue := index, 3-count; actualValue != expectedValue {
   231  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   232  		}
   233  	}
   234  	if actualValue, expectedValue := count, 3; actualValue != expectedValue {
   235  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   236  	}
   237  }
   238  
   239  func TestQueueIteratorBegin(t *testing.T) {
   240  	queue := New[string](3)
   241  	it := queue.Iterator()
   242  	it.Begin()
   243  	queue.Enqueue("a")
   244  	queue.Enqueue("b")
   245  	queue.Enqueue("c")
   246  	for it.Next() {
   247  	}
   248  	it.Begin()
   249  	it.Next()
   250  	if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
   251  		t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
   252  	}
   253  }
   254  
   255  func TestQueueIteratorEnd(t *testing.T) {
   256  	queue := New[string](3)
   257  	it := queue.Iterator()
   258  
   259  	if index := it.Index(); index != -1 {
   260  		t.Errorf("Got %v expected %v", index, -1)
   261  	}
   262  
   263  	it.End()
   264  	if index := it.Index(); index != 0 {
   265  		t.Errorf("Got %v expected %v", index, 0)
   266  	}
   267  
   268  	queue.Enqueue("a")
   269  	queue.Enqueue("b")
   270  	queue.Enqueue("c")
   271  	it.End()
   272  	if index := it.Index(); index != queue.Size() {
   273  		t.Errorf("Got %v expected %v", index, queue.Size())
   274  	}
   275  
   276  	it.Prev()
   277  	if index, value := it.Index(), it.Value(); index != queue.Size()-1 || value != "c" {
   278  		t.Errorf("Got %v,%v expected %v,%v", index, value, queue.Size()-1, "c")
   279  	}
   280  }
   281  
   282  func TestQueueIteratorFirst(t *testing.T) {
   283  	queue := New[string](3)
   284  	it := queue.Iterator()
   285  	if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
   286  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   287  	}
   288  	queue.Enqueue("a")
   289  	queue.Enqueue("b")
   290  	queue.Enqueue("c")
   291  	if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
   292  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   293  	}
   294  	if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
   295  		t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
   296  	}
   297  }
   298  
   299  func TestQueueIteratorLast(t *testing.T) {
   300  	queue := New[string](3)
   301  	it := queue.Iterator()
   302  	if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
   303  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   304  	}
   305  	queue.Enqueue("a")
   306  	queue.Enqueue("b")
   307  	queue.Enqueue("c")
   308  	if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
   309  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   310  	}
   311  	if index, value := it.Index(), it.Value(); index != 2 || value != "c" {
   312  		t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "c")
   313  	}
   314  }
   315  
   316  func TestQueueIteratorNextTo(t *testing.T) {
   317  	// Sample seek function, i.e. string starting with "b"
   318  	seek := func(index int, value string) bool {
   319  		return strings.HasSuffix(value, "b")
   320  	}
   321  
   322  	// NextTo (empty)
   323  	{
   324  		queue := New[string](3)
   325  		it := queue.Iterator()
   326  		for it.NextTo(seek) {
   327  			t.Errorf("Shouldn't iterate on empty queue")
   328  		}
   329  	}
   330  
   331  	// NextTo (not found)
   332  	{
   333  		queue := New[string](3)
   334  		queue.Enqueue("xx")
   335  		queue.Enqueue("yy")
   336  		it := queue.Iterator()
   337  		for it.NextTo(seek) {
   338  			t.Errorf("Shouldn't iterate on empty queue")
   339  		}
   340  	}
   341  
   342  	// NextTo (found)
   343  	{
   344  		queue := New[string](3)
   345  		queue.Enqueue("aa")
   346  		queue.Enqueue("bb")
   347  		queue.Enqueue("cc")
   348  		it := queue.Iterator()
   349  		it.Begin()
   350  		if !it.NextTo(seek) {
   351  			t.Errorf("Shouldn't iterate on empty queue")
   352  		}
   353  		if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
   354  			t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
   355  		}
   356  		if !it.Next() {
   357  			t.Errorf("Should go to first element")
   358  		}
   359  		if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
   360  			t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
   361  		}
   362  		if it.Next() {
   363  			t.Errorf("Should not go past last element")
   364  		}
   365  	}
   366  }
   367  
   368  func TestQueueIteratorPrevTo(t *testing.T) {
   369  	// Sample seek function, i.e. string starting with "b"
   370  	seek := func(index int, value string) bool {
   371  		return strings.HasSuffix(value, "b")
   372  	}
   373  
   374  	// PrevTo (empty)
   375  	{
   376  		queue := New[string](3)
   377  		it := queue.Iterator()
   378  		it.End()
   379  		for it.PrevTo(seek) {
   380  			t.Errorf("Shouldn't iterate on empty queue")
   381  		}
   382  	}
   383  
   384  	// PrevTo (not found)
   385  	{
   386  		queue := New[string](3)
   387  		queue.Enqueue("xx")
   388  		queue.Enqueue("yy")
   389  		it := queue.Iterator()
   390  		it.End()
   391  		for it.PrevTo(seek) {
   392  			t.Errorf("Shouldn't iterate on empty queue")
   393  		}
   394  	}
   395  
   396  	// PrevTo (found)
   397  	{
   398  		queue := New[string](3)
   399  		queue.Enqueue("aa")
   400  		queue.Enqueue("bb")
   401  		queue.Enqueue("cc")
   402  		it := queue.Iterator()
   403  		it.End()
   404  		if !it.PrevTo(seek) {
   405  			t.Errorf("Shouldn't iterate on empty queue")
   406  		}
   407  		if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
   408  			t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
   409  		}
   410  		if !it.Prev() {
   411  			t.Errorf("Should go to first element")
   412  		}
   413  		if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
   414  			t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
   415  		}
   416  		if it.Prev() {
   417  			t.Errorf("Should not go before first element")
   418  		}
   419  	}
   420  }
   421  
   422  func TestQueueIterator(t *testing.T) {
   423  	assert := func(actualValue interface{}, expectedValue interface{}) {
   424  		if actualValue != expectedValue {
   425  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   426  		}
   427  	}
   428  
   429  	queue := New[string](2)
   430  
   431  	queue.Enqueue("a")
   432  	queue.Enqueue("b")
   433  	queue.Enqueue("c") // overwrites "a"
   434  
   435  	it := queue.Iterator()
   436  
   437  	if actualIndex, expectedIndex := it.Index(), -1; actualIndex != expectedIndex {
   438  		t.Errorf("Got %v expected %v", actualIndex, expectedIndex)
   439  	}
   440  
   441  	assert(it.Next(), true)
   442  
   443  	if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "b", 0; actualValue != expectedValue || actualIndex != expectedIndex {
   444  		t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
   445  	}
   446  
   447  	assert(it.Next(), true)
   448  
   449  	if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "c", 1; actualValue != expectedValue || actualIndex != expectedIndex {
   450  		t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
   451  	}
   452  
   453  	assert(it.Next(), false)
   454  
   455  	if actualIndex, expectedIndex := it.Index(), 2; actualIndex != expectedIndex {
   456  		t.Errorf("Got %v expected %v", actualIndex, expectedIndex)
   457  	}
   458  
   459  	assert(it.Next(), false)
   460  
   461  	assert(it.Prev(), true)
   462  
   463  	if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "c", 1; actualValue != expectedValue || actualIndex != expectedIndex {
   464  		t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
   465  	}
   466  
   467  	assert(it.Prev(), true)
   468  
   469  	if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "b", 0; actualValue != expectedValue || actualIndex != expectedIndex {
   470  		t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
   471  	}
   472  
   473  	assert(it.Prev(), false)
   474  
   475  	if actualIndex, expectedIndex := it.Index(), -1; actualIndex != expectedIndex {
   476  		t.Errorf("Got %v expected %v", actualIndex, expectedIndex)
   477  	}
   478  }
   479  
   480  func TestQueueSerialization(t *testing.T) {
   481  	queue := New[string](3)
   482  	queue.Enqueue("a")
   483  	queue.Enqueue("b")
   484  	queue.Enqueue("c")
   485  
   486  	var err error
   487  	assert := func() {
   488  		if actualValue, expectedValue := queue.Values(), []string{"a", "b", "c"}; !reflect.DeepEqual(actualValue, expectedValue) {
   489  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   490  		}
   491  		if actualValue, expectedValue := queue.Size(), 3; actualValue != expectedValue {
   492  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   493  		}
   494  		if err != nil {
   495  			t.Errorf("Got error %v", err)
   496  		}
   497  	}
   498  
   499  	assert()
   500  
   501  	bytes, err := queue.MarshalJSON()
   502  	assert()
   503  
   504  	err = queue.UnmarshalJSON(bytes)
   505  	assert()
   506  
   507  	bytes, err = json.Marshal([]interface{}{"a", "b", "c", queue})
   508  	if err != nil {
   509  		t.Errorf("Got error %v", err)
   510  	}
   511  
   512  	err = json.Unmarshal([]byte(`["1","2","3"]`), &queue)
   513  	if err != nil {
   514  		t.Errorf("Got error %v", err)
   515  	}
   516  }
   517  
   518  func TestQueueString(t *testing.T) {
   519  	c := New[int](3)
   520  	c.Enqueue(1)
   521  	if !strings.HasPrefix(c.String(), "CircularBuffer") {
   522  		t.Errorf("String should start with container name")
   523  	}
   524  }
   525  
   526  func benchmarkEnqueue[E int](b *testing.B, queue *Queue[E], size int) {
   527  	for i := 0; i < b.N; i++ {
   528  		for n := 0; n < size; n++ {
   529  			queue.Enqueue(E(n))
   530  		}
   531  	}
   532  }
   533  
   534  func benchmarkDequeue[E int](b *testing.B, queue *Queue[E], size int) {
   535  	for i := 0; i < b.N; i++ {
   536  		for n := 0; n < size; n++ {
   537  			queue.Dequeue()
   538  		}
   539  	}
   540  }
   541  
   542  func BenchmarkArrayQueueDequeue100(b *testing.B) {
   543  	b.StopTimer()
   544  	size := 100
   545  	queue := New[int](3)
   546  	for n := 0; n < size; n++ {
   547  		queue.Enqueue(n)
   548  	}
   549  	b.StartTimer()
   550  	benchmarkDequeue(b, queue, size)
   551  }
   552  
   553  func BenchmarkArrayQueueDequeue1000(b *testing.B) {
   554  	b.StopTimer()
   555  	size := 1000
   556  	queue := New[int](3)
   557  	for n := 0; n < size; n++ {
   558  		queue.Enqueue(n)
   559  	}
   560  	b.StartTimer()
   561  	benchmarkDequeue(b, queue, size)
   562  }
   563  
   564  func BenchmarkArrayQueueDequeue10000(b *testing.B) {
   565  	b.StopTimer()
   566  	size := 10000
   567  	queue := New[int](3)
   568  	for n := 0; n < size; n++ {
   569  		queue.Enqueue(n)
   570  	}
   571  	b.StartTimer()
   572  	benchmarkDequeue(b, queue, size)
   573  }
   574  
   575  func BenchmarkArrayQueueDequeue100000(b *testing.B) {
   576  	b.StopTimer()
   577  	size := 100000
   578  	queue := New[int](3)
   579  	for n := 0; n < size; n++ {
   580  		queue.Enqueue(n)
   581  	}
   582  	b.StartTimer()
   583  	benchmarkDequeue(b, queue, size)
   584  }
   585  
   586  func BenchmarkArrayQueueEnqueue100(b *testing.B) {
   587  	b.StopTimer()
   588  	size := 100
   589  	queue := New[int](3)
   590  	b.StartTimer()
   591  	benchmarkEnqueue(b, queue, size)
   592  }
   593  
   594  func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
   595  	b.StopTimer()
   596  	size := 1000
   597  	queue := New[int](3)
   598  	for n := 0; n < size; n++ {
   599  		queue.Enqueue(n)
   600  	}
   601  	b.StartTimer()
   602  	benchmarkEnqueue(b, queue, size)
   603  }
   604  
   605  func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
   606  	b.StopTimer()
   607  	size := 10000
   608  	queue := New[int](3)
   609  	for n := 0; n < size; n++ {
   610  		queue.Enqueue(n)
   611  	}
   612  	b.StartTimer()
   613  	benchmarkEnqueue(b, queue, size)
   614  }
   615  
   616  func BenchmarkArrayQueueEnqueue100000(b *testing.B) {
   617  	b.StopTimer()
   618  	size := 100000
   619  	queue := New[int](3)
   620  	for n := 0; n < size; n++ {
   621  		queue.Enqueue(n)
   622  	}
   623  	b.StartTimer()
   624  	benchmarkEnqueue(b, queue, size)
   625  }