github.com/dubbogo/gost@v1.14.0/container/chan/unbounded_chan_test.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package gxchan
    19  
    20  import (
    21  	"sync"
    22  	"testing"
    23  	"time"
    24  )
    25  
    26  import (
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  func TestUnboundedChan(t *testing.T) {
    31  	ch := NewUnboundedChan(300)
    32  
    33  	var count int
    34  
    35  	for i := 1; i < 200; i++ {
    36  		ch.In() <- i
    37  	}
    38  
    39  	for i := 1; i < 60; i++ {
    40  		v, _ := <-ch.Out()
    41  		count += v.(int)
    42  	}
    43  
    44  	assert.Equal(t, 100, ch.queue.Cap())
    45  
    46  	for i := 200; i <= 1200; i++ {
    47  		ch.In() <- i
    48  	}
    49  	assert.Equal(t, 1600, ch.queue.Cap())
    50  
    51  	wg := sync.WaitGroup{}
    52  	wg.Add(1)
    53  	go func() {
    54  		defer wg.Done()
    55  		var icount int
    56  		for v := range ch.Out() {
    57  			count += v.(int)
    58  			icount++
    59  			if icount == 900 {
    60  				break
    61  			}
    62  		}
    63  	}()
    64  
    65  	wg.Wait()
    66  
    67  	close(ch.In())
    68  
    69  	// buffer should be empty
    70  	wg.Add(1)
    71  	go func() {
    72  		defer wg.Done()
    73  		for v := range ch.Out() {
    74  			count += v.(int)
    75  		}
    76  	}()
    77  
    78  	wg.Wait()
    79  
    80  	assert.Equal(t, 720600, count)
    81  
    82  }
    83  
    84  func TestUnboundedChan_Quota(t *testing.T) {
    85  	t.Run("testQuota1", testQuota1)
    86  	t.Run("testQuota2", testQuota2)
    87  }
    88  
    89  func testQuota1(t *testing.T) {
    90  	ch := NewUnboundedChanWithQuota(10, 15)
    91  	assert.Equal(t, 2, cap(ch.in))
    92  	assert.Equal(t, 3, cap(ch.out))
    93  	assert.Equal(t, 4, ch.queue.Cap())
    94  	assert.Equal(t, 0, ch.Len())
    95  	assert.Equal(t, 10, ch.Cap())
    96  
    97  	var count int
    98  
    99  	for i := 0; i < 10; i++ {
   100  		ch.In() <- i
   101  	}
   102  
   103  	assert.True(t, 14 >= ch.Cap())
   104  	assert.True(t, 10 >= ch.Len())
   105  
   106  	for i := 0; i < 10; i++ {
   107  		v, ok := <-ch.Out()
   108  		assert.True(t, ok)
   109  		count += v.(int)
   110  	}
   111  
   112  	assert.Equal(t, 45, count)
   113  
   114  	for i := 0; i < 15; i++ {
   115  		ch.In() <- i
   116  	}
   117  
   118  	wg := sync.WaitGroup{}
   119  	wg.Add(1)
   120  	go func() {
   121  		defer wg.Done()
   122  		ch.In() <- 15
   123  	}()
   124  
   125  	for i := 0; i < 16; i++ {
   126  		v, ok := <-ch.Out()
   127  		assert.True(t, ok)
   128  		count += v.(int)
   129  	}
   130  
   131  	wg.Wait()
   132  
   133  	assert.Equal(t, 165, count)
   134  }
   135  
   136  // testQuota2 tests `ch.in` has no space
   137  func testQuota2(t *testing.T) {
   138  	ch := NewUnboundedChanWithQuota(1, 1)
   139  
   140  	for i := 0; i < 1; i++ {
   141  		ch.In() <- i
   142  	}
   143  
   144  	time.Sleep(10 * time.Millisecond)
   145  
   146  	select {
   147  	case ch.In() <- 1:
   148  	default:
   149  		assert.Fail(t, "the chan shouldn't be blocked")
   150  	}
   151  
   152  	time.Sleep(10 * time.Millisecond)
   153  
   154  	select {
   155  	case ch.In() <- 2:
   156  		assert.Fail(t, "the chan should be blocked")
   157  	default:
   158  	}
   159  
   160  	ch = NewUnboundedChanWithQuota(1, 0)
   161  
   162  	for i := 0; i < 2; i++ {
   163  		ch.In() <- i
   164  	}
   165  
   166  	time.Sleep(10 * time.Millisecond)
   167  
   168  	select {
   169  	case ch.In() <- 2:
   170  		assert.True(t, ch.Len() <= 3)
   171  	default:
   172  		assert.Fail(t, "the chan shouldn't be blocked")
   173  	}
   174  
   175  	ch = NewUnboundedChanWithQuota(1, 2)
   176  
   177  	for i := 0; i < 1; i++ {
   178  		ch.In() <- i
   179  	}
   180  
   181  	time.Sleep(10 * time.Millisecond)
   182  
   183  	select {
   184  	case ch.In() <- 1:
   185  	default:
   186  		assert.Fail(t, "the chan shouldn't be blocked")
   187  	}
   188  
   189  	time.Sleep(10 * time.Millisecond)
   190  
   191  	select {
   192  	case ch.In() <- 1:
   193  		assert.Fail(t, "the chan should be blocked")
   194  	default:
   195  	}
   196  
   197  	ch = NewUnboundedChanWithQuota(1, 3)
   198  
   199  	for i := 0; i < 2; i++ {
   200  		ch.In() <- i
   201  	}
   202  
   203  	time.Sleep(10 * time.Millisecond)
   204  
   205  	select {
   206  	case ch.In() <- 2:
   207  	default:
   208  		assert.Fail(t, "the chan shouldn't be blocked")
   209  	}
   210  
   211  	time.Sleep(10 * time.Millisecond)
   212  
   213  	select {
   214  	case ch.In() <- 2:
   215  		assert.Fail(t, "the chan should be blocked")
   216  	default:
   217  	}
   218  }
   219  
   220  func BenchmarkUnboundedChan_Fixed(b *testing.B) {
   221  	ch := NewUnboundedChanWithQuota(1000, 1000)
   222  
   223  	b.RunParallel(func(pb *testing.PB) {
   224  		for pb.Next() {
   225  			select {
   226  			case ch.In() <- 1:
   227  			}
   228  
   229  			<-ch.Out()
   230  		}
   231  	})
   232  
   233  	close(ch.In())
   234  }
   235  
   236  func BenchmarkUnboundedChan_Extension(b *testing.B) {
   237  	ch := NewUnboundedChanWithQuota(1000, 100000)
   238  
   239  	b.RunParallel(func(pb *testing.PB) {
   240  		for pb.Next() {
   241  			select {
   242  			case ch.In() <- 1:
   243  			}
   244  
   245  			<-ch.Out()
   246  		}
   247  	})
   248  
   249  	close(ch.In())
   250  }
   251  
   252  func BenchmarkUnboundedChan_ExtensionUnlimited(b *testing.B) {
   253  	ch := NewUnboundedChanWithQuota(1000, 0)
   254  
   255  	b.RunParallel(func(pb *testing.PB) {
   256  		for pb.Next() {
   257  			select {
   258  			case ch.In() <- 1:
   259  			}
   260  
   261  			<-ch.Out()
   262  		}
   263  	})
   264  
   265  	close(ch.In())
   266  }