gitee.com/quant1x/gox@v1.7.6/pool/channel_rpc_test.go (about) 1 package pool 2 3 import ( 4 "math/rand" 5 "net" 6 "net/http" 7 "net/rpc" 8 "sync" 9 "testing" 10 "time" 11 ) 12 13 var ( 14 InitialCap = 5 15 MaxIdleCap = 10 16 MaximumCap = 100 17 network = "tcp" 18 address = "127.0.0.1:7777" 19 //factory = func() (interface{}, error) { return net.Dial(network, address) } 20 factory = func() (interface{}, error) { 21 return rpc.DialHTTP("tcp", address) 22 } 23 closeFac = func(v interface{}) error { 24 nc := v.(*rpc.Client) 25 return nc.Close() 26 } 27 ) 28 29 func init() { 30 // used for factory function 31 go rpcServer() 32 time.Sleep(time.Millisecond * 300) // wait until tcp server has been settled 33 34 rand.Seed(time.Now().UTC().UnixNano()) 35 } 36 37 func TestNew(t *testing.T) { 38 p, err := newChannelPool() 39 defer p.Release() 40 if err != nil { 41 t.Errorf("New error: %s", err) 42 } 43 } 44 func TestPool_Get_Impl(t *testing.T) { 45 p, _ := newChannelPool() 46 defer p.Release() 47 48 conn, err := p.Get() 49 if err != nil { 50 t.Errorf("Get error: %s", err) 51 } 52 _, ok := conn.(*rpc.Client) 53 if !ok { 54 t.Errorf("Conn is not of type poolConn") 55 } 56 p.Put(conn) 57 } 58 59 func TestPool_Get(t *testing.T) { 60 p, _ := newChannelPool() 61 defer p.Release() 62 63 _, err := p.Get() 64 if err != nil { 65 t.Errorf("Get error: %s", err) 66 } 67 68 // after one get, current capacity should be lowered by one. 69 if p.Len() != (InitialCap - 1) { 70 t.Errorf("Get error. Expecting %d, got %d", 71 (InitialCap - 1), p.Len()) 72 } 73 74 // get them all 75 var wg sync.WaitGroup 76 for i := 0; i < (MaximumCap - 1); i++ { 77 wg.Add(1) 78 go func() { 79 defer wg.Done() 80 _, err := p.Get() 81 if err != nil { 82 t.Errorf("Get error: %s", err) 83 } 84 }() 85 } 86 wg.Wait() 87 88 if p.Len() != 0 { 89 t.Errorf("Get error. Expecting %d, got %d", 90 (InitialCap - 1), p.Len()) 91 } 92 93 _, err = p.Get() 94 if err != ErrMaxActiveConnReached { 95 t.Errorf("Get error: %s", err) 96 } 97 98 } 99 100 func TestPool_Put(t *testing.T) { 101 pconf := Config{InitialCap: InitialCap, MaxCap: MaximumCap, Factory: factory, Close: closeFac, IdleTimeout: time.Second * 20, 102 MaxIdle:MaxIdleCap} 103 p, err := NewChannelPool(&pconf) 104 if err != nil { 105 t.Fatal(err) 106 } 107 defer p.Release() 108 109 // get/create from the pool 110 conns := make([]interface{}, MaximumCap) 111 for i := 0; i < MaximumCap; i++ { 112 conn, _ := p.Get() 113 conns[i] = conn 114 } 115 116 // now put them all back 117 for _, conn := range conns { 118 p.Put(conn) 119 } 120 121 if p.Len() != MaxIdleCap { 122 t.Errorf("Put error len. Expecting %d, got %d", 123 1, p.Len()) 124 } 125 126 p.Release() // close pool 127 128 } 129 130 func TestPool_UsedCapacity(t *testing.T) { 131 p, _ := newChannelPool() 132 defer p.Release() 133 134 if p.Len() != InitialCap { 135 t.Errorf("InitialCap error. Expecting %d, got %d", 136 InitialCap, p.Len()) 137 } 138 } 139 140 func TestPool_Close(t *testing.T) { 141 p, _ := newChannelPool() 142 143 // now close it and test all cases we are expecting. 144 p.Release() 145 146 c := p.(*channelPool) 147 148 if c.conns != nil { 149 t.Errorf("Close error, conns channel should be nil") 150 } 151 152 if c.factory != nil { 153 t.Errorf("Close error, factory should be nil") 154 } 155 156 _, err := p.Get() 157 if err == nil { 158 t.Errorf("Close error, get conn should return an error") 159 } 160 161 if p.Len() != 0 { 162 t.Errorf("Close error used capacity. Expecting 0, got %d", p.Len()) 163 } 164 } 165 166 func TestPoolConcurrent(t *testing.T) { 167 p, _ := newChannelPool() 168 pipe := make(chan interface{}, 0) 169 170 go func() { 171 p.Release() 172 }() 173 174 for i := 0; i < MaximumCap; i++ { 175 go func() { 176 conn, _ := p.Get() 177 178 pipe <- conn 179 }() 180 181 go func() { 182 conn := <-pipe 183 if conn == nil { 184 return 185 } 186 p.Put(conn) 187 }() 188 } 189 } 190 191 func TestPoolWriteRead(t *testing.T) { 192 //p, _ := NewChannelPool(0, 30, factory) 193 p, _ := newChannelPool() 194 conn, _ := p.Get() 195 cli := conn.(*rpc.Client) 196 var resp int 197 err := cli.Call("Arith.Multiply", Args{1, 2}, &resp) 198 if err != nil { 199 t.Error(err) 200 } 201 if resp != 2 { 202 t.Error("rpc.err") 203 } 204 } 205 206 func TestPoolConcurrent2(t *testing.T) { 207 //p, _ := NewChannelPool(0, 30, factory) 208 p, _ := newChannelPool() 209 210 var wg sync.WaitGroup 211 212 go func() { 213 for i := 0; i < 10; i++ { 214 wg.Add(1) 215 go func(i int) { 216 conn, _ := p.Get() 217 time.Sleep(time.Millisecond * time.Duration(rand.Intn(100))) 218 p.Close(conn) 219 wg.Done() 220 }(i) 221 } 222 }() 223 224 for i := 0; i < 10; i++ { 225 wg.Add(1) 226 go func(i int) { 227 conn, _ := p.Get() 228 time.Sleep(time.Millisecond * time.Duration(rand.Intn(100))) 229 p.Close(conn) 230 wg.Done() 231 }(i) 232 } 233 234 wg.Wait() 235 } 236 237 // 238 //func TestPoolConcurrent3(t *testing.T) { 239 // p, _ := NewChannelPool(0, 1, factory) 240 // 241 // var wg sync.WaitGroup 242 // 243 // wg.Add(1) 244 // go func() { 245 // p.Close() 246 // wg.Done() 247 // }() 248 // 249 // if conn, err := p.Get(); err == nil { 250 // conn.Close() 251 // } 252 // 253 // wg.Wait() 254 //} 255 256 func newChannelPool() (Pool, error) { 257 pconf := Config{InitialCap: InitialCap, MaxCap: MaximumCap, Factory: factory, Close: closeFac, IdleTimeout: time.Second * 20, 258 MaxIdle:MaxIdleCap} 259 return NewChannelPool(&pconf) 260 } 261 262 func rpcServer() { 263 arith := new(Arith) 264 rpc.Register(arith) 265 rpc.HandleHTTP() 266 267 l, e := net.Listen("tcp", address) 268 if e != nil { 269 panic(e) 270 } 271 go http.Serve(l, nil) 272 } 273 274 type Args struct { 275 A, B int 276 } 277 278 type Arith int 279 280 func (t *Arith) Multiply(args *Args, reply *int) error { 281 *reply = args.A * args.B 282 return nil 283 }