github.com/vipernet-xyz/tm@v0.34.24/privval/socket_listeners_test.go (about)

     1  package privval
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/vipernet-xyz/tm/crypto/ed25519"
    10  )
    11  
    12  //-------------------------------------------
    13  // helper funcs
    14  
    15  func newPrivKey() ed25519.PrivKey {
    16  	return ed25519.GenPrivKey()
    17  }
    18  
    19  //-------------------------------------------
    20  // tests
    21  
    22  type listenerTestCase struct {
    23  	description string // For test reporting purposes.
    24  	listener    net.Listener
    25  	dialer      SocketDialer
    26  }
    27  
    28  // testUnixAddr will attempt to obtain a platform-independent temporary file
    29  // name for a Unix socket
    30  func testUnixAddr() (string, error) {
    31  	f, err := os.CreateTemp("", "tendermint-privval-test-*")
    32  	if err != nil {
    33  		return "", err
    34  	}
    35  	addr := f.Name()
    36  	f.Close()
    37  	os.Remove(addr)
    38  	return addr, nil
    39  }
    40  
    41  func tcpListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Duration) listenerTestCase {
    42  	ln, err := net.Listen("tcp", "127.0.0.1:0")
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  
    47  	tcpLn := NewTCPListener(ln, newPrivKey())
    48  	TCPListenerTimeoutAccept(timeoutAccept)(tcpLn)
    49  	TCPListenerTimeoutReadWrite(timeoutReadWrite)(tcpLn)
    50  	return listenerTestCase{
    51  		description: "TCP",
    52  		listener:    tcpLn,
    53  		dialer:      DialTCPFn(ln.Addr().String(), testTimeoutReadWrite, newPrivKey()),
    54  	}
    55  }
    56  
    57  func unixListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Duration) listenerTestCase {
    58  	addr, err := testUnixAddr()
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  	ln, err := net.Listen("unix", addr)
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  
    67  	unixLn := NewUnixListener(ln)
    68  	UnixListenerTimeoutAccept(timeoutAccept)(unixLn)
    69  	UnixListenerTimeoutReadWrite(timeoutReadWrite)(unixLn)
    70  	return listenerTestCase{
    71  		description: "Unix",
    72  		listener:    unixLn,
    73  		dialer:      DialUnixFn(addr),
    74  	}
    75  }
    76  
    77  func listenerTestCases(t *testing.T, timeoutAccept, timeoutReadWrite time.Duration) []listenerTestCase {
    78  	return []listenerTestCase{
    79  		tcpListenerTestCase(t, timeoutAccept, timeoutReadWrite),
    80  		unixListenerTestCase(t, timeoutAccept, timeoutReadWrite),
    81  	}
    82  }
    83  
    84  func TestListenerTimeoutAccept(t *testing.T) {
    85  	for _, tc := range listenerTestCases(t, time.Millisecond, time.Second) {
    86  		_, err := tc.listener.Accept()
    87  		opErr, ok := err.(*net.OpError)
    88  		if !ok {
    89  			t.Fatalf("for %s listener, have %v, want *net.OpError", tc.description, err)
    90  		}
    91  
    92  		if have, want := opErr.Op, "accept"; have != want {
    93  			t.Errorf("for %s listener,  have %v, want %v", tc.description, have, want)
    94  		}
    95  	}
    96  }
    97  
    98  func TestListenerTimeoutReadWrite(t *testing.T) {
    99  	const (
   100  		// This needs to be long enough s.t. the Accept will definitely succeed:
   101  		timeoutAccept = time.Second
   102  		// This can be really short but in the TCP case, the accept can
   103  		// also trigger a timeoutReadWrite. Hence, we need to give it some time.
   104  		// Note: this controls how long this test actually runs.
   105  		timeoutReadWrite = 10 * time.Millisecond
   106  	)
   107  	for _, tc := range listenerTestCases(t, timeoutAccept, timeoutReadWrite) {
   108  		go func(dialer SocketDialer) {
   109  			_, err := dialer()
   110  			if err != nil {
   111  				panic(err)
   112  			}
   113  		}(tc.dialer)
   114  
   115  		c, err := tc.listener.Accept()
   116  		if err != nil {
   117  			t.Fatal(err)
   118  		}
   119  
   120  		// this will timeout because we don't write anything:
   121  		msg := make([]byte, 200)
   122  		_, err = c.Read(msg)
   123  		opErr, ok := err.(*net.OpError)
   124  		if !ok {
   125  			t.Fatalf("for %s listener, have %v, want *net.OpError", tc.description, err)
   126  		}
   127  
   128  		if have, want := opErr.Op, "read"; have != want {
   129  			t.Errorf("for %s listener, have %v, want %v", tc.description, have, want)
   130  		}
   131  
   132  		if !opErr.Timeout() {
   133  			t.Errorf("for %s listener, got unexpected error: have %v, want Timeout error", tc.description, opErr)
   134  		}
   135  	}
   136  }