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

     1  package lscq
     2  
     3  import (
     4  	"sync"
     5  	"testing"
     6  
     7  	"github.com/songzhibin97/go-baseutils/base/bcomparator"
     8  	"github.com/songzhibin97/go-baseutils/structure/sets/skipset"
     9  	"github.com/songzhibin97/go-baseutils/sys/fastrand"
    10  )
    11  
    12  func TestBoundedQueue(t *testing.T) {
    13  	q := newUint64SCQ()
    14  	s := skipset.New[uint64](bcomparator.Uint64Comparator())
    15  
    16  	// Dequeue empty queue.
    17  	val, ok := q.Dequeue()
    18  	if ok {
    19  		t.Fatal(val)
    20  	}
    21  
    22  	// Single goroutine correctness.
    23  	for i := 0; i < scqsize; i++ {
    24  		if !q.Enqueue(uint64(i)) {
    25  			t.Fatal(i)
    26  		}
    27  		s.Add(uint64(i))
    28  	}
    29  
    30  	if q.Enqueue(20) { // queue is full
    31  		t.Fatal()
    32  	}
    33  
    34  	s.Range(func(value uint64) bool {
    35  		if val, ok := q.Dequeue(); !ok || val != value {
    36  			t.Fatal(val, ok, value)
    37  		}
    38  		return true
    39  	})
    40  
    41  	// Dequeue empty queue after previous loop.
    42  	val, ok = q.Dequeue()
    43  	if ok {
    44  		t.Fatal(val)
    45  	}
    46  
    47  	// ---------- MULTIPLE TEST BEGIN ----------.
    48  	for j := 0; j < 10; j++ {
    49  		s = skipset.New[uint64](bcomparator.Uint64Comparator())
    50  
    51  		// Dequeue empty queue.
    52  		val, ok = q.Dequeue()
    53  		if ok {
    54  			t.Fatal(val)
    55  		}
    56  
    57  		// Single goroutine correctness.
    58  		for i := 0; i < scqsize; i++ {
    59  			if !q.Enqueue(uint64(i)) {
    60  				t.Fatal()
    61  			}
    62  			s.Add(uint64(i))
    63  		}
    64  
    65  		if q.Enqueue(20) { // queue is full
    66  			t.Fatal()
    67  		}
    68  
    69  		s.Range(func(value uint64) bool {
    70  			if val, ok := q.Dequeue(); !ok || val != value {
    71  				t.Fatal(val, ok, value)
    72  			}
    73  			return true
    74  		})
    75  
    76  		// Dequeue empty queue after previous loop.
    77  		val, ok = q.Dequeue()
    78  		if ok {
    79  			t.Fatal(val)
    80  		}
    81  	}
    82  	// ---------- MULTIPLE TEST END ----------.
    83  
    84  	// MPMC correctness.
    85  	var wg sync.WaitGroup
    86  	s1 := skipset.New[uint64](bcomparator.Uint64Comparator())
    87  	s2 := skipset.New[uint64](bcomparator.Uint64Comparator())
    88  	for i := 0; i < 100000; i++ {
    89  		wg.Add(1)
    90  		go func() {
    91  			if fastrand.Uint32n(2) == 0 {
    92  				r := fastrand.Uint64()
    93  				if q.Enqueue(r) {
    94  					s1.Add(r)
    95  				}
    96  			} else {
    97  				val, ok := q.Dequeue()
    98  				if ok {
    99  					s2.Add(uint64(val))
   100  				}
   101  			}
   102  			wg.Done()
   103  		}()
   104  	}
   105  	wg.Wait()
   106  
   107  	for {
   108  		val, ok := q.Dequeue()
   109  		if !ok {
   110  			break
   111  		}
   112  		s2.Add(uint64(val))
   113  	}
   114  
   115  	s1.Range(func(value uint64) bool {
   116  		if !s2.Contains(value) {
   117  			t.Fatal(value)
   118  		}
   119  		return true
   120  	})
   121  
   122  	if s1.Len() != s2.Len() {
   123  		t.Fatal("invalid")
   124  	}
   125  }
   126  
   127  func TestUnboundedQueue(t *testing.T) {
   128  	// MPMC correctness.
   129  	q := NewUint64()
   130  	var wg sync.WaitGroup
   131  	s1 := skipset.New[uint64](bcomparator.Uint64Comparator())
   132  	s2 := skipset.New[uint64](bcomparator.Uint64Comparator())
   133  	for i := 0; i < 100000; i++ {
   134  		wg.Add(1)
   135  		go func() {
   136  			if fastrand.Uint32n(2) == 0 {
   137  				r := fastrand.Uint64()
   138  				if !s1.AddB(r) || !q.Enqueue(r) {
   139  					panic("invalid")
   140  				}
   141  			} else {
   142  				val, ok := q.Dequeue()
   143  				if ok {
   144  					s2.Add(uint64(val))
   145  				}
   146  			}
   147  			wg.Done()
   148  		}()
   149  	}
   150  	wg.Wait()
   151  
   152  	for {
   153  		val, ok := q.Dequeue()
   154  		if !ok {
   155  			break
   156  		}
   157  		s2.Add(uint64(val))
   158  	}
   159  
   160  	s1.Range(func(value uint64) bool {
   161  		if !s2.Contains(value) {
   162  			t.Fatal(value)
   163  		}
   164  		return true
   165  	})
   166  
   167  	if s1.Len() != s2.Len() {
   168  		t.Fatal("invalid")
   169  	}
   170  }