github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/net_test.go (about) 1 package net 2 3 import ( 4 "bufio" 5 "encoding/binary" 6 "fmt" 7 "io" 8 "log" 9 "math/rand" 10 nt "net" 11 "os" 12 "runtime" 13 "sync/atomic" 14 "testing" 15 "time" 16 17 "github.com/angenalZZZ/gofunc/net/pool/bytebuffer" 18 "github.com/angenalZZZ/gofunc/net/pool/goroutine" 19 "github.com/valyala/bytebufferpool" 20 ) 21 22 func TestCodecServe(t *testing.T) { 23 // start a server 24 // connect 10 clients 25 // each client will pipe random data for 1-3 seconds. 26 // the writes to the server will be random sizes. 0KB - 1MB. 27 // the server will echo back the data. 28 // waits for graceful connection closing. 29 t.Run("poll", func(t *testing.T) { 30 t.Run("tcp", func(t *testing.T) { 31 t.Run("1-loop-LineBasedFrameCodec", func(t *testing.T) { 32 testCodecServe("tcp", ":9991", false, false, 10, false, new(LineBasedFrameCodec)) 33 }) 34 t.Run("1-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 35 testCodecServe("tcp", ":9992", false, false, 10, false, NewDelimiterBasedFrameCodec('|')) 36 }) 37 t.Run("1-loop-FixedLengthFrameCodec", func(t *testing.T) { 38 testCodecServe("tcp", ":9993", false, false, 10, false, NewFixedLengthFrameCodec(64)) 39 }) 40 t.Run("1-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 41 testCodecServe("tcp", ":9994", false, false, 10, false, nil) 42 }) 43 t.Run("N-loop-LineBasedFrameCodec", func(t *testing.T) { 44 testCodecServe("tcp", ":9995", true, false, 10, false, new(LineBasedFrameCodec)) 45 }) 46 t.Run("N-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 47 testCodecServe("tcp", ":9996", true, false, 10, false, NewDelimiterBasedFrameCodec('|')) 48 }) 49 t.Run("N-loop-FixedLengthFrameCodec", func(t *testing.T) { 50 testCodecServe("tcp", ":9997", true, false, 10, false, NewFixedLengthFrameCodec(64)) 51 }) 52 t.Run("N-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 53 testCodecServe("tcp", ":9998", true, false, 10, false, nil) 54 }) 55 }) 56 t.Run("tcp-async", func(t *testing.T) { 57 t.Run("1-loop-LineBasedFrameCodec", func(t *testing.T) { 58 testCodecServe("tcp", ":9991", false, true, 10, false, new(LineBasedFrameCodec)) 59 }) 60 t.Run("1-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 61 testCodecServe("tcp", ":9992", false, true, 10, false, NewDelimiterBasedFrameCodec('|')) 62 }) 63 t.Run("1-loop-FixedLengthFrameCodec", func(t *testing.T) { 64 testCodecServe("tcp", ":9993", false, true, 10, false, NewFixedLengthFrameCodec(64)) 65 }) 66 t.Run("1-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 67 testCodecServe("tcp", ":9994", false, true, 10, false, nil) 68 }) 69 t.Run("N-loop-LineBasedFrameCodec", func(t *testing.T) { 70 testCodecServe("tcp", ":9995", true, true, 10, false, new(LineBasedFrameCodec)) 71 }) 72 t.Run("N-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 73 testCodecServe("tcp", ":9996", true, true, 10, false, NewDelimiterBasedFrameCodec('|')) 74 }) 75 t.Run("N-loop-FixedLengthFrameCodec", func(t *testing.T) { 76 testCodecServe("tcp", ":9997", true, true, 10, false, NewFixedLengthFrameCodec(64)) 77 }) 78 t.Run("N-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 79 testCodecServe("tcp", ":9998", true, true, 10, false, nil) 80 }) 81 }) 82 }) 83 t.Run("poll-reuseport", func(t *testing.T) { 84 t.Run("tcp", func(t *testing.T) { 85 t.Run("1-loop-LineBasedFrameCodec", func(t *testing.T) { 86 testCodecServe("tcp", ":9991", false, false, 10, true, new(LineBasedFrameCodec)) 87 }) 88 t.Run("1-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 89 testCodecServe("tcp", ":9992", false, false, 10, true, NewDelimiterBasedFrameCodec('|')) 90 }) 91 t.Run("1-loop-FixedLengthFrameCodec", func(t *testing.T) { 92 testCodecServe("tcp", ":9993", false, false, 10, true, NewFixedLengthFrameCodec(64)) 93 }) 94 t.Run("1-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 95 testCodecServe("tcp", ":9994", false, false, 10, true, nil) 96 }) 97 t.Run("N-loop-LineBasedFrameCodec", func(t *testing.T) { 98 testCodecServe("tcp", ":9995", true, false, 10, true, new(LineBasedFrameCodec)) 99 }) 100 t.Run("N-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 101 testCodecServe("tcp", ":9996", true, false, 10, true, NewDelimiterBasedFrameCodec('|')) 102 }) 103 t.Run("N-loop-FixedLengthFrameCodec", func(t *testing.T) { 104 testCodecServe("tcp", ":9997", true, false, 10, true, NewFixedLengthFrameCodec(64)) 105 }) 106 t.Run("N-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 107 testCodecServe("tcp", ":9998", true, false, 10, true, nil) 108 }) 109 }) 110 t.Run("tcp-async", func(t *testing.T) { 111 t.Run("1-loop-LineBasedFrameCodec", func(t *testing.T) { 112 testCodecServe("tcp", ":9991", false, true, 10, true, new(LineBasedFrameCodec)) 113 }) 114 t.Run("1-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 115 testCodecServe("tcp", ":9992", false, true, 10, true, NewDelimiterBasedFrameCodec('|')) 116 }) 117 t.Run("1-loop-FixedLengthFrameCodec", func(t *testing.T) { 118 testCodecServe("tcp", ":9993", false, true, 10, true, NewFixedLengthFrameCodec(64)) 119 }) 120 t.Run("1-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 121 testCodecServe("tcp", ":9994", false, true, 10, true, nil) 122 }) 123 t.Run("N-loop-LineBasedFrameCodec", func(t *testing.T) { 124 testCodecServe("tcp", ":9995", true, true, 10, true, new(LineBasedFrameCodec)) 125 }) 126 t.Run("N-loop-DelimiterBasedFrameCodec", func(t *testing.T) { 127 testCodecServe("tcp", ":9996", true, true, 10, true, NewDelimiterBasedFrameCodec('|')) 128 }) 129 t.Run("N-loop-FixedLengthFrameCodec", func(t *testing.T) { 130 testCodecServe("tcp", ":9997", true, true, 10, true, NewFixedLengthFrameCodec(64)) 131 }) 132 t.Run("N-loop-LengthFieldBasedFrameCodec", func(t *testing.T) { 133 testCodecServe("tcp", ":9998", true, true, 10, true, nil) 134 }) 135 }) 136 }) 137 } 138 139 type testCodecServer struct { 140 *EventServer 141 network string 142 addr string 143 multicore bool 144 async bool 145 nclients int 146 started int32 147 connected int32 148 disconnected int32 149 codec ICodec 150 workerPool *goroutine.Pool 151 } 152 153 func (s *testCodecServer) OnOpened(c Conn) (out []byte, action Action) { 154 c.SetContext(c) 155 atomic.AddInt32(&s.connected, 1) 156 out = []byte("sweetness\r\n") 157 if c.LocalAddr() == nil { 158 panic("nil local addr") 159 } 160 if c.RemoteAddr() == nil { 161 panic("nil local addr") 162 } 163 return 164 } 165 func (s *testCodecServer) OnClosed(c Conn, err error) (action Action) { 166 if c.Context() != c { 167 panic("invalid context") 168 } 169 170 atomic.AddInt32(&s.disconnected, 1) 171 if atomic.LoadInt32(&s.connected) == atomic.LoadInt32(&s.disconnected) && 172 atomic.LoadInt32(&s.disconnected) == int32(s.nclients) { 173 action = Shutdown 174 } 175 176 return 177 } 178 func (s *testCodecServer) React(frame []byte, c Conn) (out []byte, action Action) { 179 if s.async { 180 if frame != nil { 181 data := append([]byte{}, frame...) 182 _ = s.workerPool.Submit(func() { 183 _ = c.AsyncWrite(data) 184 }) 185 } 186 return 187 } 188 out = frame 189 return 190 } 191 func (s *testCodecServer) Tick() (delay time.Duration, action Action) { 192 if atomic.LoadInt32(&s.started) == 0 { 193 for i := 0; i < s.nclients; i++ { 194 go func() { 195 startCodecClient(s.network, s.addr, s.multicore, s.async, s.codec) 196 }() 197 } 198 atomic.StoreInt32(&s.started, 1) 199 } 200 delay = time.Second / 5 201 return 202 } 203 204 var ( 205 n = 0 206 fieldLengths = []int{1, 2, 3, 4, 8} 207 ) 208 209 func testCodecServe(network, addr string, multicore, async bool, nclients int, reuseport bool, codec ICodec) { 210 var err error 211 fieldLength := fieldLengths[n] 212 if codec == nil { 213 encoderConfig := EncoderConfig{ 214 ByteOrder: binary.BigEndian, 215 LengthFieldLength: fieldLength, 216 LengthAdjustment: 0, 217 LengthIncludesLengthFieldLength: false, 218 } 219 decoderConfig := DecoderConfig{ 220 ByteOrder: binary.BigEndian, 221 LengthFieldOffset: 0, 222 LengthFieldLength: fieldLength, 223 LengthAdjustment: 0, 224 InitialBytesToStrip: fieldLength, 225 } 226 codec = NewLengthFieldBasedFrameCodec(encoderConfig, decoderConfig) 227 } 228 n++ 229 if n > 4 { 230 n = 0 231 } 232 ts := &testCodecServer{network: network, addr: addr, multicore: multicore, async: async, nclients: nclients, 233 codec: codec, workerPool: goroutine.Default()} 234 if reuseport { 235 err = Serve(ts, network+"://"+addr, WithMulticore(multicore), WithTicker(true), 236 WithTCPKeepAlive(time.Minute*5), WithCodec(codec), WithReusePort(true)) 237 } else { 238 err = Serve(ts, network+"://"+addr, WithMulticore(multicore), WithTicker(true), 239 WithTCPKeepAlive(time.Minute*5), WithCodec(codec)) 240 } 241 if err != nil { 242 panic(err) 243 } 244 } 245 246 func startCodecClient(network, addr string, multicore, async bool, codec ICodec) { 247 rand.Seed(time.Now().UnixNano()) 248 c, err := nt.Dial(network, addr) 249 if err != nil { 250 panic(err) 251 } 252 defer c.Close() 253 rd := bufio.NewReader(c) 254 msg, err := rd.ReadBytes('\n') 255 if err != nil { 256 panic(err) 257 } 258 if string(msg) != "sweetness\r\n" { 259 panic("bad header") 260 } 261 duration := time.Duration((rand.Float64()*2+1)*float64(time.Second)) / 8 262 start := time.Now() 263 for time.Since(start) < duration { 264 //data := []byte("Hello, World") 265 data := make([]byte, 1024) 266 rand.Read(data) 267 encodedData, _ := codec.Encode(nil, data) 268 if _, err := c.Write(encodedData); err != nil { 269 panic(err) 270 } 271 data2 := make([]byte, len(encodedData)) 272 if _, err := io.ReadFull(rd, data2); err != nil { 273 panic(err) 274 } 275 if string(encodedData) != string(data2) && !async { 276 //panic(fmt.Sprintf("mismatch %s/multi-core:%t: %d vs %d bytes, %s:%s", network, multicore, 277 // len(encodedData), len(data2), string(encodedData), string(data2))) 278 panic(fmt.Sprintf("mismatch %s/multi-core:%t: %d vs %d bytes", network, multicore, len(encodedData), len(data2))) 279 } 280 } 281 } 282 283 func TestServe(t *testing.T) { 284 // start a server 285 // connect 10 clients 286 // each client will pipe random data for 1-3 seconds. 287 // the writes to the server will be random sizes. 0KB - 1MB. 288 // the server will echo back the data. 289 // waits for graceful connection closing. 290 t.Run("poll", func(t *testing.T) { 291 t.Run("tcp", func(t *testing.T) { 292 t.Run("1-loop", func(t *testing.T) { 293 testServe("tcp", ":9991", false, false, false, 10, RoundRobin) 294 }) 295 t.Run("N-loop", func(t *testing.T) { 296 testServe("tcp", ":9992", false, true, false, 10, LeastConnections) 297 }) 298 }) 299 t.Run("tcp-async", func(t *testing.T) { 300 t.Run("1-loop", func(t *testing.T) { 301 testServe("tcp", ":9991", false, false, true, 10, RoundRobin) 302 }) 303 t.Run("N-loop", func(t *testing.T) { 304 testServe("tcp", ":9992", false, true, true, 10, LeastConnections) 305 }) 306 }) 307 t.Run("udp", func(t *testing.T) { 308 t.Run("1-loop", func(t *testing.T) { 309 testServe("udp", ":9991", false, false, false, 10, RoundRobin) 310 }) 311 t.Run("N-loop", func(t *testing.T) { 312 testServe("udp", ":9992", false, true, false, 10, LeastConnections) 313 }) 314 }) 315 t.Run("udp-async", func(t *testing.T) { 316 t.Run("1-loop", func(t *testing.T) { 317 testServe("udp", ":9991", false, false, true, 10, RoundRobin) 318 }) 319 t.Run("N-loop", func(t *testing.T) { 320 testServe("udp", ":9992", false, true, true, 10, LeastConnections) 321 }) 322 }) 323 t.Run("unix", func(t *testing.T) { 324 t.Run("1-loop", func(t *testing.T) { 325 testServe("unix", "gnet1.sock", false, false, false, 10, RoundRobin) 326 }) 327 t.Run("N-loop", func(t *testing.T) { 328 testServe("unix", "gnet2.sock", false, true, false, 10, SourceAddrHash) 329 }) 330 }) 331 t.Run("unix-async", func(t *testing.T) { 332 t.Run("1-loop", func(t *testing.T) { 333 testServe("unix", "gnet1.sock", false, false, true, 10, RoundRobin) 334 }) 335 t.Run("N-loop", func(t *testing.T) { 336 testServe("unix", "gnet2.sock", false, true, true, 10, SourceAddrHash) 337 }) 338 }) 339 }) 340 341 t.Run("poll-reuseport", func(t *testing.T) { 342 t.Run("tcp", func(t *testing.T) { 343 t.Run("1-loop", func(t *testing.T) { 344 testServe("tcp", ":9991", true, false, false, 10, RoundRobin) 345 }) 346 t.Run("N-loop", func(t *testing.T) { 347 testServe("tcp", ":9992", true, true, false, 10, LeastConnections) 348 }) 349 }) 350 t.Run("tcp-async", func(t *testing.T) { 351 t.Run("1-loop", func(t *testing.T) { 352 testServe("tcp", ":9991", true, false, true, 10, RoundRobin) 353 }) 354 t.Run("N-loop", func(t *testing.T) { 355 testServe("tcp", ":9992", true, true, false, 10, LeastConnections) 356 }) 357 }) 358 t.Run("udp", func(t *testing.T) { 359 t.Run("1-loop", func(t *testing.T) { 360 testServe("udp", ":9991", true, false, false, 10, RoundRobin) 361 }) 362 t.Run("N-loop", func(t *testing.T) { 363 testServe("udp", ":9992", true, true, false, 10, LeastConnections) 364 }) 365 }) 366 t.Run("udp-async", func(t *testing.T) { 367 t.Run("1-loop", func(t *testing.T) { 368 testServe("udp", ":9991", true, false, false, 10, RoundRobin) 369 }) 370 t.Run("N-loop", func(t *testing.T) { 371 testServe("udp", ":9992", true, true, true, 10, LeastConnections) 372 }) 373 }) 374 t.Run("unix", func(t *testing.T) { 375 t.Run("1-loop", func(t *testing.T) { 376 testServe("unix", "gnet1.sock", true, false, false, 10, RoundRobin) 377 }) 378 t.Run("N-loop", func(t *testing.T) { 379 testServe("unix", "gnet2.sock", true, true, false, 10, LeastConnections) 380 }) 381 }) 382 t.Run("unix-async", func(t *testing.T) { 383 t.Run("1-loop", func(t *testing.T) { 384 testServe("unix", "gnet1.sock", true, false, true, 10, RoundRobin) 385 }) 386 t.Run("N-loop", func(t *testing.T) { 387 testServe("unix", "gnet2.sock", true, true, true, 10, LeastConnections) 388 }) 389 }) 390 }) 391 } 392 393 type testServer struct { 394 *EventServer 395 svr Server 396 network string 397 addr string 398 multicore bool 399 async bool 400 nclients int 401 started int32 402 connected int32 403 clientActive int32 404 disconnected int32 405 workerPool *goroutine.Pool 406 bytesList []*bytebufferpool.ByteBuffer 407 } 408 409 func (s *testServer) OnInitComplete(svr Server) (action Action) { 410 s.svr = svr 411 return 412 } 413 414 func (s *testServer) OnOpened(c Conn) (out []byte, action Action) { 415 c.SetContext(c) 416 atomic.AddInt32(&s.connected, 1) 417 out = []byte("sweetness\r\n") 418 if c.LocalAddr() == nil { 419 panic("nil local addr") 420 } 421 if c.RemoteAddr() == nil { 422 panic("nil local addr") 423 } 424 return 425 } 426 func (s *testServer) OnClosed(c Conn, err error) (action Action) { 427 if err != nil { 428 fmt.Printf("error occurred on closed, %v\n", err) 429 } 430 if c.Context() != c { 431 panic("invalid context") 432 } 433 434 atomic.AddInt32(&s.disconnected, 1) 435 if atomic.LoadInt32(&s.connected) == atomic.LoadInt32(&s.disconnected) && 436 atomic.LoadInt32(&s.disconnected) == int32(s.nclients) { 437 action = Shutdown 438 for i := range s.bytesList { 439 bytebuffer.Put(s.bytesList[i]) 440 } 441 s.workerPool.Release() 442 } 443 444 return 445 } 446 func (s *testServer) React(frame []byte, c Conn) (out []byte, action Action) { 447 if s.async { 448 if s.network == "tcp" || s.network == "unix" { 449 _ = c.BufferLength() 450 buf := bytebuffer.Get() 451 _, _ = buf.Write(frame) 452 s.bytesList = append(s.bytesList, buf) 453 // just for test 454 c.ShiftN(1) 455 _ = s.workerPool.Submit( 456 func() { 457 _ = c.AsyncWrite(buf.Bytes()) 458 }) 459 return 460 } 461 if s.network == "udp" { 462 _ = s.workerPool.Submit( 463 func() { 464 _ = c.SendTo(frame) 465 }) 466 return 467 } 468 return 469 } 470 out = frame 471 return 472 } 473 func (s *testServer) Tick() (delay time.Duration, action Action) { 474 if atomic.LoadInt32(&s.started) == 0 { 475 for i := 0; i < s.nclients; i++ { 476 atomic.AddInt32(&s.clientActive, 1) 477 go func() { 478 startClient(s.network, s.addr, s.multicore, s.async) 479 atomic.AddInt32(&s.clientActive, -1) 480 }() 481 } 482 atomic.StoreInt32(&s.started, 1) 483 } 484 fmt.Printf("active connections: %d\n", s.svr.CountConnections()) 485 if s.network == "udp" && atomic.LoadInt32(&s.clientActive) == 0 { 486 action = Shutdown 487 return 488 } 489 delay = time.Second / 5 490 return 491 } 492 493 func testServe(network, addr string, reuseport, multicore, async bool, nclients int, lb LoadBalancing) { 494 ts := &testServer{ 495 network: network, 496 addr: addr, 497 multicore: multicore, 498 async: async, 499 nclients: nclients, 500 workerPool: goroutine.Default()} 501 must(Serve(ts, network+"://"+addr, WithMulticore(multicore), WithReusePort(reuseport), WithTicker(true), 502 WithTCPKeepAlive(time.Minute*1), WithLoadBalancing(lb))) 503 } 504 505 func startClient(network, addr string, multicore, async bool) { 506 rand.Seed(time.Now().UnixNano()) 507 c, err := nt.Dial(network, addr) 508 if err != nil { 509 panic(err) 510 } 511 defer c.Close() 512 rd := bufio.NewReader(c) 513 if network != "udp" { 514 msg, err := rd.ReadBytes('\n') 515 if err != nil { 516 panic(err) 517 } 518 if string(msg) != "sweetness\r\n" { 519 panic("bad header") 520 } 521 } 522 duration := time.Duration((rand.Float64()*2+1)*float64(time.Second)) / 8 523 start := time.Now() 524 for time.Since(start) < duration { 525 //sz := rand.Intn(10) * (1024 * 1024) 526 sz := 1024 * 1024 527 data := make([]byte, sz) 528 if network == "udp" || network == "unix" { 529 n := 1024 530 data = data[:n] 531 } 532 if _, err := rand.Read(data); err != nil { 533 panic(err) 534 } 535 if _, err := c.Write(data); err != nil { 536 panic(err) 537 } 538 data2 := make([]byte, len(data)) 539 if _, err := io.ReadFull(rd, data2); err != nil { 540 panic(err) 541 } 542 if string(data) != string(data2) && !async { 543 panic(fmt.Sprintf("mismatch %s/multi-core:%t: %d vs %d bytes\n", network, multicore, len(data), len(data2))) 544 } 545 } 546 } 547 548 func must(err error) { 549 if err != nil && err != ErrUnsupportedProtocol { 550 panic(err) 551 } 552 } 553 554 func TestDefaultGnetServer(t *testing.T) { 555 svr := EventServer{} 556 svr.OnInitComplete(Server{}) 557 svr.OnOpened(nil) 558 svr.OnClosed(nil, nil) 559 svr.PreWrite() 560 svr.React(nil, nil) 561 svr.Tick() 562 } 563 564 func TestTick(t *testing.T) { 565 testTick("tcp4", ":9991", t) 566 } 567 568 type testTickServer struct { 569 *EventServer 570 count int 571 } 572 573 func (t *testTickServer) Tick() (delay time.Duration, action Action) { 574 if t.count == 25 { 575 action = Shutdown 576 return 577 } 578 t.count++ 579 delay = time.Millisecond * 10 580 return 581 } 582 583 func testTick(network, addr string, t *testing.T) { 584 events := &testTickServer{} 585 start := time.Now() 586 opts := Options{Ticker: true} 587 must(Serve(events, network+"://"+addr, WithOptions(opts))) 588 dur := time.Since(start) 589 if dur < 250&time.Millisecond || dur > time.Second { 590 t.Logf("bad ticker timing: %d", dur) 591 } 592 } 593 594 func TestWakeConn(t *testing.T) { 595 testWakeConn("tcp", ":9000") 596 } 597 598 type testWakeConnServer struct { 599 *EventServer 600 network string 601 addr string 602 conn Conn 603 wake bool 604 } 605 606 func (t *testWakeConnServer) OnOpened(c Conn) (out []byte, action Action) { 607 t.conn = c 608 return 609 } 610 func (t *testWakeConnServer) OnClosed(c Conn, err error) (action Action) { 611 action = Shutdown 612 return 613 } 614 func (t *testWakeConnServer) React(frame []byte, c Conn) (out []byte, action Action) { 615 out = []byte("Waking up.") 616 action = -1 617 return 618 } 619 func (t *testWakeConnServer) Tick() (delay time.Duration, action Action) { 620 if !t.wake { 621 t.wake = true 622 delay = time.Millisecond * 100 623 go func() { 624 conn, err := nt.Dial(t.network, t.addr) 625 must(err) 626 defer conn.Close() 627 r := make([]byte, 10) 628 _, err = conn.Read(r) 629 if err != nil { 630 panic(err) 631 } 632 fmt.Println(string(r)) 633 }() 634 return 635 } 636 _ = t.conn.Wake() 637 delay = time.Millisecond * 100 638 return 639 } 640 641 func testWakeConn(network, addr string) { 642 svr := &testWakeConnServer{network: network, addr: addr} 643 must(Serve(svr, network+"://"+addr, WithTicker(true), WithNumEventLoop(2*runtime.NumCPU()), 644 WithLogger(log.New(os.Stderr, "", log.LstdFlags)))) 645 } 646 647 func TestShutdown(t *testing.T) { 648 testShutdown("tcp", ":9991") 649 } 650 651 type testShutdownServer struct { 652 *EventServer 653 network string 654 addr string 655 count int 656 clients int64 657 N int 658 } 659 660 func (t *testShutdownServer) OnOpened(c Conn) (out []byte, action Action) { 661 atomic.AddInt64(&t.clients, 1) 662 return 663 } 664 func (t *testShutdownServer) OnClosed(c Conn, err error) (action Action) { 665 atomic.AddInt64(&t.clients, -1) 666 return 667 } 668 func (t *testShutdownServer) Tick() (delay time.Duration, action Action) { 669 if t.count == 0 { 670 // start clients 671 for i := 0; i < t.N; i++ { 672 go func() { 673 conn, err := nt.Dial(t.network, t.addr) 674 must(err) 675 defer conn.Close() 676 _, err = conn.Read([]byte{0}) 677 if err == nil { 678 panic("expected error") 679 } 680 }() 681 } 682 } else { 683 if int(atomic.LoadInt64(&t.clients)) == t.N { 684 action = Shutdown 685 } 686 } 687 t.count++ 688 delay = time.Second / 20 689 return 690 } 691 692 func testShutdown(network, addr string) { 693 events := &testShutdownServer{network: network, addr: addr, N: 10} 694 must(Serve(events, network+"://"+addr, WithTicker(true))) 695 if events.clients != 0 { 696 panic("did not call close on all clients") 697 } 698 } 699 700 type testBadAddrServer struct { 701 *EventServer 702 } 703 704 func (t *testBadAddrServer) OnInitComplete(srv Server) (action Action) { 705 return Shutdown 706 } 707 708 func TestBadAddresses(t *testing.T) { 709 events := new(testBadAddrServer) 710 if err := Serve(events, "tulip://howdy"); err == nil { 711 t.Fatalf("expected error") 712 } 713 if err := Serve(events, "howdy"); err == nil { 714 t.Fatalf("expected error") 715 } 716 if err := Serve(events, "tcp://"); err != nil { 717 t.Fatalf("expected nil, got '%v'", err) 718 } 719 } 720 721 func TestCloseActionError(t *testing.T) { 722 testCloseActionError("tcp", ":9991") 723 } 724 725 type testCloseActionErrorServer struct { 726 *EventServer 727 network, addr string 728 action bool 729 } 730 731 func (t *testCloseActionErrorServer) OnClosed(c Conn, err error) (action Action) { 732 action = Shutdown 733 return 734 } 735 func (t *testCloseActionErrorServer) React(frame []byte, c Conn) (out []byte, action Action) { 736 out = frame 737 action = Close 738 return 739 } 740 func (t *testCloseActionErrorServer) Tick() (delay time.Duration, action Action) { 741 if !t.action { 742 t.action = true 743 delay = time.Millisecond * 100 744 go func() { 745 conn, err := nt.Dial(t.network, t.addr) 746 must(err) 747 defer conn.Close() 748 data := []byte("Hello World!") 749 _, _ = conn.Write(data) 750 _, err = conn.Read(data) 751 if err != nil { 752 panic(err) 753 } 754 fmt.Println(string(data)) 755 }() 756 return 757 } 758 delay = time.Millisecond * 100 759 return 760 } 761 762 func testCloseActionError(network, addr string) { 763 events := &testCloseActionErrorServer{network: network, addr: addr} 764 must(Serve(events, network+"://"+addr, WithTicker(true))) 765 } 766 767 func TestShutdownActionError(t *testing.T) { 768 testShutdownActionError("tcp", ":9991") 769 } 770 771 type testShutdownActionErrorServer struct { 772 *EventServer 773 network, addr string 774 action bool 775 } 776 777 func (t *testShutdownActionErrorServer) React(frame []byte, c Conn) (out []byte, action Action) { 778 c.ReadN(-1) // just for test 779 out = frame 780 action = Shutdown 781 return 782 } 783 func (t *testShutdownActionErrorServer) Tick() (delay time.Duration, action Action) { 784 if !t.action { 785 t.action = true 786 delay = time.Millisecond * 100 787 go func() { 788 conn, err := nt.Dial(t.network, t.addr) 789 must(err) 790 defer conn.Close() 791 data := []byte("Hello World!") 792 _, _ = conn.Write(data) 793 _, err = conn.Read(data) 794 if err != nil { 795 panic(err) 796 } 797 fmt.Println(string(data)) 798 }() 799 return 800 } 801 delay = time.Millisecond * 100 802 return 803 } 804 805 func testShutdownActionError(network, addr string) { 806 events := &testShutdownActionErrorServer{network: network, addr: addr} 807 must(Serve(events, network+"://"+addr, WithTicker(true))) 808 } 809 810 func TestCloseActionOnOpen(t *testing.T) { 811 testCloseActionOnOpen("tcp", ":9991") 812 } 813 814 type testCloseActionOnOpenServer struct { 815 *EventServer 816 network, addr string 817 action bool 818 } 819 820 func (t *testCloseActionOnOpenServer) OnOpened(c Conn) (out []byte, action Action) { 821 action = Close 822 return 823 } 824 func (t *testCloseActionOnOpenServer) OnClosed(c Conn, err error) (action Action) { 825 action = Shutdown 826 return 827 } 828 func (t *testCloseActionOnOpenServer) Tick() (delay time.Duration, action Action) { 829 if !t.action { 830 t.action = true 831 delay = time.Millisecond * 100 832 go func() { 833 conn, err := nt.Dial(t.network, t.addr) 834 must(err) 835 defer conn.Close() 836 }() 837 return 838 } 839 delay = time.Millisecond * 100 840 return 841 } 842 843 func testCloseActionOnOpen(network, addr string) { 844 events := &testCloseActionOnOpenServer{network: network, addr: addr} 845 must(Serve(events, network+"://"+addr, WithTicker(true))) 846 } 847 848 func TestShutdownActionOnOpen(t *testing.T) { 849 testShutdownActionOnOpen("tcp", ":9991") 850 } 851 852 type testShutdownActionOnOpenServer struct { 853 *EventServer 854 network, addr string 855 action bool 856 } 857 858 func (t *testShutdownActionOnOpenServer) OnOpened(c Conn) (out []byte, action Action) { 859 action = Shutdown 860 return 861 } 862 func (t *testShutdownActionOnOpenServer) Tick() (delay time.Duration, action Action) { 863 if !t.action { 864 t.action = true 865 delay = time.Millisecond * 100 866 go func() { 867 conn, err := nt.Dial(t.network, t.addr) 868 must(err) 869 defer conn.Close() 870 }() 871 return 872 } 873 delay = time.Millisecond * 100 874 return 875 } 876 877 func testShutdownActionOnOpen(network, addr string) { 878 events := &testShutdownActionOnOpenServer{network: network, addr: addr} 879 must(Serve(events, network+"://"+addr, WithTicker(true))) 880 } 881 882 func TestUDPShutdown(t *testing.T) { 883 testUDPShutdown("udp4", ":9000") 884 } 885 886 type testUDPShutdownServer struct { 887 *EventServer 888 network string 889 addr string 890 tick bool 891 } 892 893 func (t *testUDPShutdownServer) React(frame []byte, c Conn) (out []byte, action Action) { 894 out = frame 895 action = Shutdown 896 return 897 } 898 func (t *testUDPShutdownServer) Tick() (delay time.Duration, action Action) { 899 if !t.tick { 900 t.tick = true 901 delay = time.Millisecond * 100 902 go func() { 903 conn, err := nt.Dial(t.network, t.addr) 904 must(err) 905 defer conn.Close() 906 data := []byte("Hello World!") 907 if _, err = conn.Write(data); err != nil { 908 panic(err) 909 } 910 if _, err = conn.Read(data); err != nil { 911 panic(err) 912 } 913 fmt.Println(string(data)) 914 }() 915 return 916 } 917 delay = time.Millisecond * 100 918 return 919 } 920 921 func testUDPShutdown(network, addr string) { 922 svr := &testUDPShutdownServer{network: network, addr: addr} 923 must(Serve(svr, network+"://"+addr, WithTicker(true))) 924 } 925 926 func TestCloseConnection(t *testing.T) { 927 testCloseConnection("tcp", ":9991") 928 } 929 930 type testCloseConnectionServer struct { 931 *EventServer 932 network, addr string 933 action bool 934 } 935 936 func (t *testCloseConnectionServer) OnClosed(c Conn, err error) (action Action) { 937 action = Shutdown 938 return 939 } 940 func (t *testCloseConnectionServer) React(frame []byte, c Conn) (out []byte, action Action) { 941 out = frame 942 go func() { 943 time.Sleep(time.Second) 944 _ = c.Close() 945 }() 946 return 947 } 948 func (t *testCloseConnectionServer) Tick() (delay time.Duration, action Action) { 949 if !t.action { 950 t.action = true 951 delay = time.Millisecond * 100 952 go func() { 953 conn, err := nt.Dial(t.network, t.addr) 954 must(err) 955 defer conn.Close() 956 data := []byte("Hello World!") 957 _, _ = conn.Write(data) 958 _, err = conn.Read(data) 959 if err != nil { 960 panic(err) 961 } 962 fmt.Println(string(data)) 963 // waiting the server shutdown. 964 _, err = conn.Read(data) 965 if err == nil { 966 panic(err) 967 } 968 }() 969 return 970 } 971 delay = time.Millisecond * 100 972 return 973 } 974 975 func testCloseConnection(network, addr string) { 976 events := &testCloseConnectionServer{network: network, addr: addr} 977 must(Serve(events, network+"://"+addr, WithTicker(true))) 978 }