@@ -350,29 +350,67 @@ func TestLargeBufferWrite(t *testing.T) {
350350 trigger <- 1
351351}
352352
353- func TestWriteTimeout (t * testing.T ) {
354- address := getTestAddress ()
355- ln , err := createTestListener ("tcp" , address )
353+ func TestConnectionTimeout (t * testing.T ) {
354+ ln , err := net .Listen ("tcp" , "127.0.0.1:0" )
356355 MustNil (t , err )
356+ defer ln .Close ()
357+
358+ const (
359+ bufsz = 1 << 20
360+ interval = 10 * time .Millisecond
361+ )
362+
363+ calcRate := func (n int32 ) int32 {
364+ v := n / int32 (time .Second / interval )
365+ if v > bufsz {
366+ panic (v )
367+ }
368+ if v < 1 {
369+ return 1
370+ }
371+ return v
372+ }
373+
374+ wn := int32 (1 ) // for each Read, must <= bufsz
375+ setServerWriteRate := func (n int32 ) {
376+ atomic .StoreInt32 (& wn , calcRate (n ))
377+ }
378+
379+ rn := int32 (1 ) // for each Write, must <= bufsz
380+ setServerReadRate := func (n int32 ) {
381+ atomic .StoreInt32 (& rn , calcRate (n ))
382+ }
357383
358- interval := time .Millisecond * 100
359384 go func () {
360385 for {
361386 conn , err := ln .Accept ()
362- if conn == nil && err == nil {
363- continue
364- }
365387 if err != nil {
366388 return
367389 }
390+ // set small SO_SNDBUF/SO_RCVBUF buffer for better control timeout test
391+ tcpconn := conn .(* net.TCPConn )
392+ tcpconn .SetReadBuffer (512 )
393+ tcpconn .SetWriteBuffer (512 )
368394 go func () {
369- buf := make ([]byte , 1024 )
370- // slow read
395+ buf := make ([]byte , bufsz )
371396 for {
372- _ , err := conn .Read (buf )
397+ n := atomic .LoadInt32 (& rn )
398+ _ , err := conn .Read (buf [:int (n )])
373399 if err != nil {
374- err = conn .Close ()
375- MustNil (t , err )
400+ conn .Close ()
401+ return
402+ }
403+ time .Sleep (interval )
404+ }
405+ }()
406+
407+ go func () {
408+ buf := make ([]byte , bufsz )
409+ for {
410+ n := atomic .LoadInt32 (& wn )
411+ _ , err := conn .Write (buf [:int (n )])
412+ if err != nil {
413+ conn .Close ()
376414 return
377415 }
378416 time .Sleep (interval )
@@ -381,26 +419,103 @@ func TestWriteTimeout(t *testing.T) {
381419 }
382420 }()
383421
384- conn , err := DialConnection ("tcp" , address , time .Second )
385- MustNil (t , err )
422+ newConn := func () Connection {
423+ conn , err := DialConnection ("tcp" , ln .Addr ().String (), time .Second )
424+ MustNil (t , err )
425+ fd := conn .(Conn ).Fd ()
426+ // set small SO_SNDBUF/SO_RCVBUF buffer for better control timeout test
427+ err = syscall .SetsockoptInt (fd , syscall .SOL_SOCKET , syscall .SO_SNDBUF , 512 )
428+ MustNil (t , err )
429+ err = syscall .SetsockoptInt (fd , syscall .SOL_SOCKET , syscall .SO_RCVBUF , 512 )
430+ MustNil (t , err )
431+ return conn
432+ }
386433
387- _ , err = conn .Writer ().Malloc (1024 )
388- MustNil (t , err )
389- err = conn .Writer ().Flush ()
390- MustNil (t , err )
434+ mallocAndFlush := func (conn Connection , sz int ) error {
435+ _ , err = conn .Writer ().Malloc (sz )
436+ MustNil (t , err )
437+ return conn .Writer ().Flush ()
438+ }
391439
392- _ = conn .SetWriteTimeout (time .Millisecond * 10 )
393- _ , err = conn .Writer ().Malloc (1024 * 1024 * 512 )
394- MustNil (t , err )
395- err = conn .Writer ().Flush ()
396- MustTrue (t , errors .Is (err , ErrWriteTimeout ))
440+ t .Run ("TestWriteTimeout" , func (t * testing.T ) {
441+ setServerReadRate (10 << 10 ) // 10KB/s
397442
398- // close success
399- err = conn .Close ()
400- MustNil (t , err )
443+ conn := newConn ()
444+ defer conn .Close ()
401445
402- err = ln .Close ()
403- MustNil (t , err )
446+ // write 1KB without timeout
447+ err = mallocAndFlush (conn , 1 << 10 ) // ~100ms
448+ MustNil (t , err )
449+
450+ // write 50ms timeout
451+ _ = conn .SetWriteTimeout (50 * time .Millisecond )
452+ err = mallocAndFlush (conn , 1 << 20 )
453+ MustTrue (t , errors .Is (err , ErrWriteTimeout ))
454+ })
455+
456+ t .Run ("TestReadTimeout" , func (t * testing.T ) {
457+ setServerWriteRate (10 << 10 ) // 10KB/s
458+
459+ conn := newConn ()
460+ defer conn .Close ()
461+
462+ // read 1KB without timeout
463+ _ , err = conn .Reader ().Next (1 << 10 ) // ~100ms
464+ MustNil (t , err )
465+
466+ // read 20KB ~ 2s, 50ms timeout
467+ _ = conn .SetReadTimeout (50 * time .Millisecond )
468+ _ , err = conn .Reader ().Next (20 << 10 )
469+ MustTrue (t , errors .Is (err , ErrReadTimeout ))
470+ })
471+
472+ t .Run ("TestWriteDeadline" , func (t * testing.T ) {
473+ setServerReadRate (10 << 10 ) // 10KB/s
474+
475+ conn := newConn ()
476+ defer conn .Close ()
477+
478+ // write 1KB without deadline
479+ err = conn .SetWriteDeadline (time .Now ())
480+ err = conn .SetDeadline (time.Time {})
481+ MustNil (t , err )
482+ err = mallocAndFlush (conn , 1 << 10 ) // ~100ms
483+ MustNil (t , err )
484+
485+ // write with deadline
486+ err = conn .SetWriteDeadline (time .Now ().Add (50 * time .Millisecond ))
487+ MustNil (t , err )
488+ err = mallocAndFlush (conn , 1 << 20 )
489+ MustTrue (t , errors .Is (err , ErrWriteTimeout ))
490+
491+ // write deadline exceeded
492+ err = mallocAndFlush (conn , 10 << 10 )
493+ MustTrue (t , errors .Is (err , ErrWriteTimeout ))
494+ })
495+
496+ t .Run ("TestReadDeadline" , func (t * testing.T ) {
497+ setServerWriteRate (20 << 10 ) // 20KB/s
498+
499+ conn := newConn ()
500+ defer conn .Close ()
501+
502+ // read 1KB without deadline
503+ err = conn .SetReadDeadline (time .Now ())
504+ err = conn .SetDeadline (time.Time {})
505+ MustNil (t , err )
506+ _ , err = conn .Reader ().Next (1 << 10 )
507+ MustNil (t , err )
508+
509+ // read 100KB with deadline
510+ err = conn .SetReadDeadline (time .Now ().Add (50 * time .Millisecond ))
511+ MustNil (t , err )
512+ _ , err = conn .Reader ().Next (100 << 10 )
513+ MustTrue (t , errors .Is (err , ErrReadTimeout ))
514+
515+ // read 10KB, deadline exceeded
516+ _ , err = conn .Reader ().Next (10 << 10 )
517+ MustTrue (t , errors .Is (err , ErrReadTimeout ))
518+ })
404519}
405520
406521// TestConnectionLargeMemory is used to verify the memory usage in the large package scenario.
@@ -656,7 +771,7 @@ func TestConnectionServerClose(t *testing.T) {
656771 var wg sync.WaitGroup
657772 el , err := NewEventLoop (
658773 func (ctx context.Context , connection Connection ) error {
659- // t.Logf("server.OnRequest: addr=%s", connection.RemoteAddr())
774+ t .Logf ("server.OnRequest: addr=%s" , connection .RemoteAddr ())
660775 defer wg .Done ()
661776 buf , err := connection .Reader ().Next (len (PONG )) // pong
662777 Equal (t , string (buf ), PONG )
@@ -679,14 +794,14 @@ func TestConnectionServerClose(t *testing.T) {
679794 err = connection .Writer ().Flush ()
680795 MustNil (t , err )
681796 connection .AddCloseCallback (func (connection Connection ) error {
682- // t.Logf("server.CloseCallback: addr=%s", connection.RemoteAddr())
797+ t .Logf ("server.CloseCallback: addr=%s" , connection .RemoteAddr ())
683798 wg .Done ()
684799 return nil
685800 })
686801 return ctx
687802 }),
688803 WithOnPrepare (func (connection Connection ) context.Context {
689- // t.Logf("server.OnPrepare: addr=%s", connection.RemoteAddr())
804+ t .Logf ("server.OnPrepare: addr=%s" , connection .RemoteAddr ())
690805 defer wg .Done ()
691806 //nolint:staticcheck // SA1029 no built-in type string as key
692807 return context .WithValue (context .Background (), "prepare" , "true" )
@@ -719,7 +834,7 @@ func TestConnectionServerClose(t *testing.T) {
719834
720835 return connection .Close ()
721836 }
722- conns := 100
837+ conns := 10
723838 // server: OnPrepare, OnConnect, OnRequest, CloseCallback
724839 // client: OnRequest, CloseCallback
725840 wg .Add (conns * 6 )
@@ -730,7 +845,7 @@ func TestConnectionServerClose(t *testing.T) {
730845 err = conn .SetOnRequest (clientOnRequest )
731846 MustNil (t , err )
732847 conn .AddCloseCallback (func (connection Connection ) error {
733- // t.Logf("client.CloseCallback: addr=%s", connection.LocalAddr())
848+ t .Logf ("client.CloseCallback: addr=%s" , connection .LocalAddr ())
734849 defer wg .Done ()
735850 return nil
736851 })
0 commit comments