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

     1  package linkedliststack
     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 TestStackIterator(t *testing.T) {
    73  	stack := New[string]()
    74  	stack.Push("a")
    75  	stack.Push("b")
    76  	stack.Push("c")
    77  
    78  	// Iterator
    79  	it := stack.Iterator()
    80  	count := 0
    81  	for it.Next() {
    82  		count++
    83  		index := it.Index()
    84  		value := it.Value()
    85  		switch index {
    86  		case 0:
    87  			if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
    88  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
    89  			}
    90  		case 1:
    91  			if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
    92  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
    93  			}
    94  		case 2:
    95  			if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
    96  				t.Errorf("Got %v expected %v", actualValue, expectedValue)
    97  			}
    98  		default:
    99  			t.Errorf("Too many")
   100  		}
   101  		if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
   102  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   103  		}
   104  	}
   105  	if actualValue, expectedValue := count, 3; actualValue != expectedValue {
   106  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   107  	}
   108  
   109  	stack.Clear()
   110  	it = stack.Iterator()
   111  	for it.Next() {
   112  		t.Errorf("Shouldn't iterate on empty stack")
   113  	}
   114  }
   115  
   116  func TestStackIteratorBegin(t *testing.T) {
   117  	stack := New[string]()
   118  	it := stack.Iterator()
   119  	it.Begin()
   120  	stack.Push("a")
   121  	stack.Push("b")
   122  	stack.Push("c")
   123  	for it.Next() {
   124  	}
   125  	it.Begin()
   126  	it.Next()
   127  	if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
   128  		t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
   129  	}
   130  }
   131  
   132  func TestStackIteratorFirst(t *testing.T) {
   133  	stack := New[string]()
   134  	it := stack.Iterator()
   135  	if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
   136  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   137  	}
   138  	stack.Push("a")
   139  	stack.Push("b")
   140  	stack.Push("c")
   141  	if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
   142  		t.Errorf("Got %v expected %v", actualValue, expectedValue)
   143  	}
   144  	if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
   145  		t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
   146  	}
   147  }
   148  
   149  func TestStackIteratorNextTo(t *testing.T) {
   150  	// Sample seek function, i.e. string starting with "b"
   151  	seek := func(index int, value string) bool {
   152  		return strings.HasSuffix(value, "b")
   153  	}
   154  
   155  	// NextTo (empty)
   156  	{
   157  		stack := New[string]()
   158  		it := stack.Iterator()
   159  		for it.NextTo(seek) {
   160  			t.Errorf("Shouldn't iterate on empty stack")
   161  		}
   162  	}
   163  
   164  	// NextTo (not found)
   165  	{
   166  		stack := New[string]()
   167  		stack.Push("xx")
   168  		stack.Push("yy")
   169  		it := stack.Iterator()
   170  		for it.NextTo(seek) {
   171  			t.Errorf("Shouldn't iterate on empty stack")
   172  		}
   173  	}
   174  
   175  	// NextTo (found)
   176  	{
   177  		stack := New[string]()
   178  		stack.Push("aa")
   179  		stack.Push("bb")
   180  		stack.Push("cc")
   181  		it := stack.Iterator()
   182  		it.Begin()
   183  		if !it.NextTo(seek) {
   184  			t.Errorf("Shouldn't iterate on empty stack")
   185  		}
   186  		if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
   187  			t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
   188  		}
   189  		if !it.Next() {
   190  			t.Errorf("Should go to first element")
   191  		}
   192  		if index, value := it.Index(), it.Value(); index != 2 || value != "aa" {
   193  			t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "aa")
   194  		}
   195  		if it.Next() {
   196  			t.Errorf("Should not go past last element")
   197  		}
   198  	}
   199  }
   200  
   201  func TestStackSerialization(t *testing.T) {
   202  	stack := New[string]()
   203  	stack.Push("a")
   204  	stack.Push("b")
   205  	stack.Push("c")
   206  
   207  	var err error
   208  	assert := func() {
   209  		if actualValue, expectedValue := stack.Values(), []string{"c", "b", "a"}; !reflect.DeepEqual(actualValue, expectedValue) {
   210  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   211  		}
   212  		if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue {
   213  			t.Errorf("Got %v expected %v", actualValue, expectedValue)
   214  		}
   215  		if err != nil {
   216  			t.Errorf("Got error %v", err)
   217  		}
   218  	}
   219  
   220  	assert()
   221  
   222  	bytes, err := stack.MarshalJSON()
   223  	assert()
   224  
   225  	err = stack.UnmarshalJSON(bytes)
   226  	assert()
   227  
   228  	bytes, err = json.Marshal([]interface{}{"a", "b", "c", stack})
   229  	if err != nil {
   230  		t.Errorf("Got error %v", err)
   231  	}
   232  
   233  	err = json.Unmarshal([]byte(`["1","2","3"]`), &stack)
   234  	if err != nil {
   235  		t.Errorf("Got error %v", err)
   236  	}
   237  }
   238  
   239  func TestStackString(t *testing.T) {
   240  	c := New[int]()
   241  	c.Push(1)
   242  	if !strings.HasPrefix(c.String(), "LinkedListStack") {
   243  		t.Errorf("String should start with container name")
   244  	}
   245  }
   246  
   247  func benchmarkPush[E int](b *testing.B, stack *Stack[E], size int) {
   248  	for i := 0; i < b.N; i++ {
   249  		for n := 0; n < size; n++ {
   250  			stack.Push(E(n))
   251  		}
   252  	}
   253  }
   254  
   255  func benchmarkPop[E int](b *testing.B, stack *Stack[E], size int) {
   256  	for i := 0; i < b.N; i++ {
   257  		for n := 0; n < size; n++ {
   258  			stack.Pop()
   259  		}
   260  	}
   261  }
   262  
   263  func BenchmarkLinkedListStackPop100(b *testing.B) {
   264  	b.StopTimer()
   265  	size := 100
   266  	stack := New[int]()
   267  	for n := 0; n < size; n++ {
   268  		stack.Push(n)
   269  	}
   270  	b.StartTimer()
   271  	benchmarkPop(b, stack, size)
   272  }
   273  
   274  func BenchmarkLinkedListStackPop1000(b *testing.B) {
   275  	b.StopTimer()
   276  	size := 1000
   277  	stack := New[int]()
   278  	for n := 0; n < size; n++ {
   279  		stack.Push(n)
   280  	}
   281  	b.StartTimer()
   282  	benchmarkPop(b, stack, size)
   283  }
   284  
   285  func BenchmarkLinkedListStackPop10000(b *testing.B) {
   286  	b.StopTimer()
   287  	size := 10000
   288  	stack := New[int]()
   289  	for n := 0; n < size; n++ {
   290  		stack.Push(n)
   291  	}
   292  	b.StartTimer()
   293  	benchmarkPop(b, stack, size)
   294  }
   295  
   296  func BenchmarkLinkedListStackPop100000(b *testing.B) {
   297  	b.StopTimer()
   298  	size := 100000
   299  	stack := New[int]()
   300  	for n := 0; n < size; n++ {
   301  		stack.Push(n)
   302  	}
   303  	b.StartTimer()
   304  	benchmarkPop(b, stack, size)
   305  }
   306  
   307  func BenchmarkLinkedListStackPush100(b *testing.B) {
   308  	b.StopTimer()
   309  	size := 100
   310  	stack := New[int]()
   311  	b.StartTimer()
   312  	benchmarkPush(b, stack, size)
   313  }
   314  
   315  func BenchmarkLinkedListStackPush1000(b *testing.B) {
   316  	b.StopTimer()
   317  	size := 1000
   318  	stack := New[int]()
   319  	for n := 0; n < size; n++ {
   320  		stack.Push(n)
   321  	}
   322  	b.StartTimer()
   323  	benchmarkPush(b, stack, size)
   324  }
   325  
   326  func BenchmarkLinkedListStackPush10000(b *testing.B) {
   327  	b.StopTimer()
   328  	size := 10000
   329  	stack := New[int]()
   330  	for n := 0; n < size; n++ {
   331  		stack.Push(n)
   332  	}
   333  	b.StartTimer()
   334  	benchmarkPush(b, stack, size)
   335  }
   336  
   337  func BenchmarkLinkedListStackPush100000(b *testing.B) {
   338  	b.StopTimer()
   339  	size := 100000
   340  	stack := New[int]()
   341  	for n := 0; n < size; n++ {
   342  		stack.Push(n)
   343  	}
   344  	b.StartTimer()
   345  	benchmarkPush(b, stack, size)
   346  }