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

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