github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/deadlineconn/deadlineconn_test.go (about)

     1  // Copyright (c) 2015-2022 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package deadlineconn
    19  
    20  import (
    21  	"bufio"
    22  	"io"
    23  	"net"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  )
    28  
    29  // Test deadlineconn handles read timeout properly by reading two messages beyond deadline.
    30  func TestBuffConnReadTimeout(t *testing.T) {
    31  	l, err := net.Listen("tcp", "localhost:0")
    32  	if err != nil {
    33  		t.Fatalf("unable to create listener. %v", err)
    34  	}
    35  	defer l.Close()
    36  	serverAddr := l.Addr().String()
    37  
    38  	tcpListener, ok := l.(*net.TCPListener)
    39  	if !ok {
    40  		t.Fatalf("failed to assert to net.TCPListener")
    41  	}
    42  
    43  	var wg sync.WaitGroup
    44  	wg.Add(1)
    45  	go func() {
    46  		defer wg.Done()
    47  
    48  		tcpConn, terr := tcpListener.AcceptTCP()
    49  		if terr != nil {
    50  			t.Errorf("failed to accept new connection. %v", terr)
    51  			return
    52  		}
    53  		deadlineconn := New(tcpConn)
    54  		deadlineconn.WithReadDeadline(time.Second)
    55  		deadlineconn.WithWriteDeadline(time.Second)
    56  		defer deadlineconn.Close()
    57  
    58  		// Read a line
    59  		b := make([]byte, 12)
    60  		_, terr = deadlineconn.Read(b)
    61  		if terr != nil {
    62  			t.Errorf("failed to read from client. %v", terr)
    63  			return
    64  		}
    65  		received := string(b)
    66  		if received != "message one\n" {
    67  			t.Errorf(`server: expected: "message one\n", got: %v`, received)
    68  			return
    69  		}
    70  
    71  		// Wait for more than read timeout to simulate processing.
    72  		time.Sleep(3 * time.Second)
    73  
    74  		_, terr = deadlineconn.Read(b)
    75  		if terr != nil {
    76  			t.Errorf("failed to read from client. %v", terr)
    77  			return
    78  		}
    79  		received = string(b)
    80  		if received != "message two\n" {
    81  			t.Errorf(`server: expected: "message two\n", got: %v`, received)
    82  			return
    83  		}
    84  
    85  		// Send a response.
    86  		_, terr = io.WriteString(deadlineconn, "messages received\n")
    87  		if terr != nil {
    88  			t.Errorf("failed to write to client. %v", terr)
    89  			return
    90  		}
    91  	}()
    92  
    93  	c, err := net.Dial("tcp", serverAddr)
    94  	if err != nil {
    95  		t.Fatalf("unable to connect to server. %v", err)
    96  	}
    97  	defer c.Close()
    98  
    99  	_, err = io.WriteString(c, "message one\n")
   100  	if err != nil {
   101  		t.Fatalf("failed to write to server. %v", err)
   102  	}
   103  	_, err = io.WriteString(c, "message two\n")
   104  	if err != nil {
   105  		t.Fatalf("failed to write to server. %v", err)
   106  	}
   107  
   108  	received, err := bufio.NewReader(c).ReadString('\n')
   109  	if err != nil {
   110  		t.Fatalf("failed to read from server. %v", err)
   111  	}
   112  	if received != "messages received\n" {
   113  		t.Fatalf(`client: expected: "messages received\n", got: %v`, received)
   114  	}
   115  
   116  	wg.Wait()
   117  }