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 }