github.com/sandwich-go/boost@v1.3.29/xchan/unbounded_chan_test.go (about)

     1  package xchan
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"go.uber.org/goleak"
    11  )
    12  
    13  func TestMakeUnboundedChan(t *testing.T) {
    14  	ctx, cancel := context.WithCancel(context.Background())
    15  	defer cancel()
    16  	ch := NewUnboundedChan[int64](ctx, 100)
    17  
    18  	for i := 1; i < 200; i++ {
    19  		ch.In <- int64(i)
    20  	}
    21  
    22  	var count int64
    23  	var wg sync.WaitGroup
    24  	wg.Add(1)
    25  	go func() {
    26  		defer wg.Done()
    27  
    28  		for v := range ch.Out {
    29  			count += v
    30  		}
    31  	}()
    32  
    33  	for i := 200; i <= 1000; i++ {
    34  		ch.In <- int64(i)
    35  	}
    36  	close(ch.In)
    37  
    38  	wg.Wait()
    39  
    40  	if count != 500500 {
    41  		t.Fatalf("expected 500500 but got %d", count)
    42  	}
    43  }
    44  
    45  func TestMakeUnboundedChanSize(t *testing.T) {
    46  	ctx, cancel := context.WithCancel(context.Background())
    47  	defer cancel()
    48  	ch := NewUnboundedChanSize[int64](ctx, 10, 50, 100)
    49  
    50  	for i := 1; i < 200; i++ {
    51  		ch.In <- int64(i)
    52  	}
    53  
    54  	var count int64
    55  	var wg sync.WaitGroup
    56  	wg.Add(1)
    57  	go func() {
    58  		defer wg.Done()
    59  
    60  		for v := range ch.Out {
    61  			count += v
    62  		}
    63  	}()
    64  
    65  	for i := 200; i <= 1000; i++ {
    66  		ch.In <- int64(i)
    67  	}
    68  	close(ch.In)
    69  
    70  	wg.Wait()
    71  
    72  	if count != 500500 {
    73  		t.Fatalf("expected 500500 but got %d", count)
    74  	}
    75  }
    76  
    77  func TestLen_DataRace(t *testing.T) {
    78  	ctx, cancel := context.WithCancel(context.Background())
    79  	defer cancel()
    80  	ch := NewUnboundedChan[int64](ctx, 1)
    81  	stop := make(chan bool)
    82  	wg := &sync.WaitGroup{}
    83  	for i := 0; i < 100; i++ { // may tweak the number of iterations
    84  		wg.Add(1)
    85  		go func(ctx context.Context) {
    86  			defer wg.Done()
    87  			for {
    88  				select {
    89  				case <-ctx.Done():
    90  					return
    91  				case <-stop:
    92  					return
    93  				default:
    94  					ch.In <- 42
    95  					<-ch.Out
    96  				}
    97  			}
    98  		}(ctx)
    99  	}
   100  
   101  	for i := 0; i < 10000; i++ { // may tweak the number of iterations
   102  		ch.Len()
   103  	}
   104  	close(stop)
   105  	wg.Wait()
   106  }
   107  
   108  func TestLen(t *testing.T) {
   109  	ctx, cancel := context.WithCancel(context.Background())
   110  	defer cancel()
   111  	ch := NewUnboundedChanSize[int64](ctx, 10, 50, 100)
   112  
   113  	for i := 1; i < 200; i++ {
   114  		ch.In <- int64(i)
   115  	}
   116  
   117  	// wait ch processing in normal case
   118  	time.Sleep(time.Second)
   119  	assert.Equal(t, 0, len(ch.In))
   120  	assert.Equal(t, 50, len(ch.Out))
   121  	assert.Equal(t, 199, ch.Len())
   122  	assert.Equal(t, 149, ch.BufLen())
   123  
   124  	for i := 0; i < 50; i++ {
   125  		<-ch.Out
   126  	}
   127  
   128  	time.Sleep(time.Second)
   129  	assert.Equal(t, 0, len(ch.In))
   130  	assert.Equal(t, 50, len(ch.Out))
   131  	assert.Equal(t, 149, ch.Len())
   132  	assert.Equal(t, 99, ch.BufLen())
   133  
   134  	for i := 0; i < 149; i++ {
   135  		<-ch.Out
   136  	}
   137  
   138  	time.Sleep(time.Second)
   139  	assert.Equal(t, 0, len(ch.In))
   140  	assert.Equal(t, 0, len(ch.Out))
   141  	assert.Equal(t, 0, ch.Len())
   142  	assert.Equal(t, 0, ch.BufLen())
   143  }
   144  
   145  func TestGetDataWithGoleak(t *testing.T) {
   146  	defer goleak.VerifyNone(t)
   147  	ctx, cancel := context.WithCancel(context.Background())
   148  	defer cancel()
   149  	ch := NewUnboundedChanSize[int64](ctx, 10, 50, 100)
   150  	for i := 1; i < 200; i++ {
   151  		ch.In <- int64(i)
   152  	}
   153  }