github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/stacks/arraystack/arraystack_test.go (about)

     1  package arraystack
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  )
     9  
    10  func TestStackPush(t *testing.T) {
    11  	stack := New[int]()
    12  	if actualValue := stack.Empty(); actualValue != true {
    13  		t.Errorf("Got %v expected %v", actualValue, true)
    14  	}
    15  	stack.Push(1)
    16  	stack.Push(2)
    17  	stack.Push(3)
    18  
    19  	if actualValue := stack.Values(); actualValue[0] != 3 || actualValue[1] != 2 || actualValue[2] != 1 {
    20  		t.Errorf("Got %v expected %v", actualValue, "[3,2,1]")
    21  	}
    22  	if actualValue := stack.Empty(); actualValue != false {
    23  		t.Errorf("Got %v expected %v", actualValue, false)
    24  	}
    25  	if actualValue := stack.Size(); actualValue != 3 {
    26  		t.Errorf("Got %v expected %v", actualValue, 3)
    27  	}
    28  	if actualValue, ok := stack.Peek(); actualValue != 3 || !ok {
    29  		t.Errorf("Got %v expected %v", actualValue, 3)
    30  	}
    31  }
    32  
    33  func TestStackPeek(t *testing.T) {
    34  	stack := New[int]()
    35  	if actualValue, ok := stack.Peek(); actualValue != 0 || ok {
    36  		t.Errorf("Got %v expected %v", actualValue, nil)
    37  	}
    38  	stack.Push(1)
    39  	stack.Push(2)
    40  	stack.Push(3)
    41  	if actualValue, ok := stack.Peek(); actualValue != 3 || !ok {
    42  		t.Errorf("Got %v expected %v", actualValue, 3)
    43  	}
    44  }
    45  
    46  func TestStackPop(t *testing.T) {
    47  	stack := New[int]()
    48  	stack.Push(1)
    49  	stack.Push(2)
    50  	stack.Push(3)
    51  	stack.Pop()
    52  	if actualValue, ok := stack.Peek(); actualValue != 2 || !ok {
    53  		t.Errorf("Got %v expected %v", actualValue, 2)
    54  	}
    55  	if actualValue, ok := stack.Pop(); actualValue != 2 || !ok {
    56  		t.Errorf("Got %v expected %v", actualValue, 2)
    57  	}
    58  	if actualValue, ok := stack.Pop(); actualValue != 1 || !ok {
    59  		t.Errorf("Got %v expected %v", actualValue, 1)
    60  	}
    61  	if actualValue, ok := stack.Pop(); actualValue != 0 || ok {
    62  		t.Errorf("Got %v expected %v", actualValue, nil)
    63  	}
    64  	if actualValue := stack.Empty(); actualValue != true {
    65  		t.Errorf("Got %v expected %v", actualValue, true)
    66  	}
    67  	if actualValue := stack.Values(); len(actualValue) != 0 {
    68  		t.Errorf("Got %v expected %v", actualValue, "[]")
    69  	}
    70  }
    71  
    72  func TestStackIteratorOnEmpty(t *testing.T) {
    73  	stack := New[int]()
    74  	it := stack.Iterator()
    75  	for it.Next() {
    76  		t.Errorf("Shouldn't iterate on empty stack")
    77  	}
    78  }
    79  
    80  func TestStackIteratorNext(t *testing.T) {
    81  	stack := New[string]()
    82  	stack.Push("a")
    83  	stack.Push("b")
    84  	stack.Push("c")
    85  
    86  	it := stack.Iterator()
    87  	count := 0
    88  	for it.Next() {
    89  		count++
    90  		index := it.Index()
    91  		value := it.Value()
    92  		switch index {
    93  		case 0:
    94  			if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
    95  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
    96  			}
    97  		case 1:
    98  			if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
    99  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   100  			}
   101  		case 2:
   102  			if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
   103  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   104  			}
   105  		default:
   106  			t.Errorf("Too many")
   107  		}
   108  		if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
   109  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   110  		}
   111  	}
   112  	if actualValue, expectedValue := count, 3; actualValue != expectedValue {
   113  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   114  	}
   115  
   116  	stack.Clear()
   117  	it = stack.Iterator()
   118  	for it.Next() {
   119  		t.Errorf("Shouldn't iterate on empty stack")
   120  	}
   121  }
   122  
   123  func TestStackIteratorPrev(t *testing.T) {
   124  	stack := New[string]()
   125  	stack.Push("a")
   126  	stack.Push("b")
   127  	stack.Push("c")
   128  
   129  	it := stack.Iterator()
   130  	for it.Next() {
   131  	}
   132  	count := 0
   133  	for it.Prev() {
   134  		count++
   135  		index := it.Index()
   136  		value := it.Value()
   137  		switch index {
   138  		case 0:
   139  			if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
   140  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   141  			}
   142  		case 1:
   143  			if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
   144  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   145  			}
   146  		case 2:
   147  			if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
   148  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
   149  			}
   150  		default:
   151  			t.Errorf("Too many")
   152  		}
   153  		if actualValue, expectedValue := index, 3-count; actualValue != expectedValue {
   154  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   155  		}
   156  	}
   157  	if actualValue, expectedValue := count, 3; actualValue != expectedValue {
   158  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   159  	}
   160  }
   161  
   162  func TestStackIteratorBegin(t *testing.T) {
   163  	stack := New[string]()
   164  	it := stack.Iterator()
   165  	it.Begin()
   166  	stack.Push("a")
   167  	stack.Push("b")
   168  	stack.Push("c")
   169  	for it.Next() {
   170  	}
   171  	it.Begin()
   172  	it.Next()
   173  	if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
   174  		t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
   175  	}
   176  }
   177  
   178  func TestStackIteratorEnd(t *testing.T) {
   179  	stack := New[string]()
   180  	it := stack.Iterator()
   181  
   182  	if index := it.Index(); index != -1 {
   183  		t.Errorf("Got %v expected %v", index, -1)
   184  	}
   185  
   186  	it.End()
   187  	if index := it.Index(); index != 0 {
   188  		t.Errorf("Got %v expected %v", index, 0)
   189  	}
   190  
   191  	stack.Push("a")
   192  	stack.Push("b")
   193  	stack.Push("c")
   194  	it.End()
   195  	if index := it.Index(); index != stack.Size() {
   196  		t.Errorf("Got %v expected %v", index, stack.Size())
   197  	}
   198  
   199  	it.Prev()
   200  	if index, value := it.Index(), it.Value(); index != stack.Size()-1 || value != "a" {
   201  		t.Errorf("Got %v,%v expected %v,%v", index, value, stack.Size()-1, "a")
   202  	}
   203  }
   204  
   205  func TestStackIteratorFirst(t *testing.T) {
   206  	stack := New[string]()
   207  	it := stack.Iterator()
   208  	if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
   209  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   210  	}
   211  	stack.Push("a")
   212  	stack.Push("b")
   213  	stack.Push("c")
   214  	if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
   215  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   216  	}
   217  	if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
   218  		t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
   219  	}
   220  }
   221  
   222  func TestStackIteratorLast(t *testing.T) {
   223  	stack := New[string]()
   224  	it := stack.Iterator()
   225  	if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
   226  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   227  	}
   228  	stack.Push("a")
   229  	stack.Push("b")
   230  	stack.Push("c")
   231  	if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
   232  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   233  	}
   234  	if index, value := it.Index(), it.Value(); index != 2 || value != "a" {
   235  		t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "a")
   236  	}
   237  }
   238  
   239  func TestStackIteratorNextTo(t *testing.T) {
   240  	// Sample seek function, i.e. string starting with "b"
   241  	seek := func(index int, value string) bool {
   242  		return strings.HasSuffix(value, "b")
   243  	}
   244  
   245  	// NextTo (empty)
   246  	{
   247  		stack := New[string]()
   248  		it := stack.Iterator()
   249  		for it.NextTo(seek) {
   250  			t.Errorf("Shouldn't iterate on empty stack")
   251  		}
   252  	}
   253  
   254  	// NextTo (not found)
   255  	{
   256  		stack := New[string]()
   257  		stack.Push("xx")
   258  		stack.Push("yy")
   259  		it := stack.Iterator()
   260  		for it.NextTo(seek) {
   261  			t.Errorf("Shouldn't iterate on empty stack")
   262  		}
   263  	}
   264  
   265  	// NextTo (found)
   266  	{
   267  		stack := New[string]()
   268  		stack.Push("aa")
   269  		stack.Push("bb")
   270  		stack.Push("cc")
   271  		it := stack.Iterator()
   272  		it.Begin()
   273  		if !it.NextTo(seek) {
   274  			t.Errorf("Shouldn't iterate on empty stack")
   275  		}
   276  		if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
   277  			t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
   278  		}
   279  		if !it.Next() {
   280  			t.Errorf("Should go to first element")
   281  		}
   282  		if index, value := it.Index(), it.Value(); index != 2 || value != "aa" {
   283  			t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "aa")
   284  		}
   285  		if it.Next() {
   286  			t.Errorf("Should not go past last element")
   287  		}
   288  	}
   289  }
   290  
   291  func TestStackIteratorPrevTo(t *testing.T) {
   292  	// Sample seek function, i.e. string starting with "b"
   293  	seek := func(index int, value string) bool {
   294  		return strings.HasSuffix(value, "b")
   295  	}
   296  
   297  	// PrevTo (empty)
   298  	{
   299  		stack := New[string]()
   300  		it := stack.Iterator()
   301  		it.End()
   302  		for it.PrevTo(seek) {
   303  			t.Errorf("Shouldn't iterate on empty stack")
   304  		}
   305  	}
   306  
   307  	// PrevTo (not found)
   308  	{
   309  		stack := New[string]()
   310  		stack.Push("xx")
   311  		stack.Push("yy")
   312  		it := stack.Iterator()
   313  		it.End()
   314  		for it.PrevTo(seek) {
   315  			t.Errorf("Shouldn't iterate on empty stack")
   316  		}
   317  	}
   318  
   319  	// PrevTo (found)
   320  	{
   321  		stack := New[string]()
   322  		stack.Push("aa")
   323  		stack.Push("bb")
   324  		stack.Push("cc")
   325  		it := stack.Iterator()
   326  		it.End()
   327  		if !it.PrevTo(seek) {
   328  			t.Errorf("Shouldn't iterate on empty stack")
   329  		}
   330  		if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
   331  			t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
   332  		}
   333  		if !it.Prev() {
   334  			t.Errorf("Should go to first element")
   335  		}
   336  		if index, value := it.Index(), it.Value(); index != 0 || value != "cc" {
   337  			t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "cc")
   338  		}
   339  		if it.Prev() {
   340  			t.Errorf("Should not go before first element")
   341  		}
   342  	}
   343  }
   344  
   345  func TestStackSerialization(t *testing.T) {
   346  	stack := New[string]()
   347  	stack.Push("a")
   348  	stack.Push("b")
   349  	stack.Push("c")
   350  
   351  	var err error
   352  	assert := func() {
   353  		if actualValue, expectedValue := stack.Values(), []string{"c", "b", "a"}; !reflect.DeepEqual(actualValue, expectedValue) {
   354  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   355  		}
   356  		if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue {
   357  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   358  		}
   359  		if err != nil {
   360  			t.Errorf("Got error %v", err)
   361  		}
   362  	}
   363  
   364  	assert()
   365  
   366  	bytes, err := stack.MarshalJSON()
   367  	assert()
   368  
   369  	err = stack.UnmarshalJSON(bytes)
   370  	assert()
   371  
   372  	bytes, err = json.Marshal([]interface{}{"a", "b", "c", stack})
   373  	if err != nil {
   374  		t.Errorf("Got error %v", err)
   375  	}
   376  
   377  	err = json.Unmarshal([]byte(`["1","2","3"]`), &stack)
   378  	if err != nil {
   379  		t.Errorf("Got error %v", err)
   380  	}
   381  }
   382  
   383  func TestStackString(t *testing.T) {
   384  	c := New[int]()
   385  	c.Push(1)
   386  	if !strings.HasPrefix(c.String(), "ArrayStack") {
   387  		t.Errorf("String should start with container name")
   388  	}
   389  }
   390  
   391  func benchmarkPush[E int](b *testing.B, stack *Stack[E], size int) {
   392  	for i := 0; i < b.N; i++ {
   393  		for n := 0; n < size; n++ {
   394  			stack.Push(E(n))
   395  		}
   396  	}
   397  }
   398  
   399  func benchmarkPop[E int](b *testing.B, stack *Stack[E], size int) {
   400  	for i := 0; i < b.N; i++ {
   401  		for n := 0; n < size; n++ {
   402  			stack.Pop()
   403  		}
   404  	}
   405  }
   406  
   407  func BenchmarkArrayStackPop100(b *testing.B) {
   408  	b.StopTimer()
   409  	size := 100
   410  	stack := New[int]()
   411  	for n := 0; n < size; n++ {
   412  		stack.Push(n)
   413  	}
   414  	b.StartTimer()
   415  	benchmarkPop(b, stack, size)
   416  }
   417  
   418  func BenchmarkArrayStackPop1000(b *testing.B) {
   419  	b.StopTimer()
   420  	size := 1000
   421  	stack := New[int]()
   422  	for n := 0; n < size; n++ {
   423  		stack.Push(n)
   424  	}
   425  	b.StartTimer()
   426  	benchmarkPop(b, stack, size)
   427  }
   428  
   429  func BenchmarkArrayStackPop10000(b *testing.B) {
   430  	b.StopTimer()
   431  	size := 10000
   432  	stack := New[int]()
   433  	for n := 0; n < size; n++ {
   434  		stack.Push(n)
   435  	}
   436  	b.StartTimer()
   437  	benchmarkPop(b, stack, size)
   438  }
   439  
   440  func BenchmarkArrayStackPop100000(b *testing.B) {
   441  	b.StopTimer()
   442  	size := 100000
   443  	stack := New[int]()
   444  	for n := 0; n < size; n++ {
   445  		stack.Push(n)
   446  	}
   447  	b.StartTimer()
   448  	benchmarkPop(b, stack, size)
   449  }
   450  
   451  func BenchmarkArrayStackPush100(b *testing.B) {
   452  	b.StopTimer()
   453  	size := 100
   454  	stack := New[int]()
   455  	b.StartTimer()
   456  	benchmarkPush(b, stack, size)
   457  }
   458  
   459  func BenchmarkArrayStackPush1000(b *testing.B) {
   460  	b.StopTimer()
   461  	size := 1000
   462  	stack := New[int]()
   463  	for n := 0; n < size; n++ {
   464  		stack.Push(n)
   465  	}
   466  	b.StartTimer()
   467  	benchmarkPush(b, stack, size)
   468  }
   469  
   470  func BenchmarkArrayStackPush10000(b *testing.B) {
   471  	b.StopTimer()
   472  	size := 10000
   473  	stack := New[int]()
   474  	for n := 0; n < size; n++ {
   475  		stack.Push(n)
   476  	}
   477  	b.StartTimer()
   478  	benchmarkPush(b, stack, size)
   479  }
   480  
   481  func BenchmarkArrayStackPush100000(b *testing.B) {
   482  	b.StopTimer()
   483  	size := 100000
   484  	stack := New[int]()
   485  	for n := 0; n < size; n++ {
   486  		stack.Push(n)
   487  	}
   488  	b.StartTimer()
   489  	benchmarkPush(b, stack, size)
   490  }