go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/internal/test/transport.go (about)

     1  // Copyright 2019 The Mangos Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use file except in compliance with the License.
     5  // You may obtain a copy of the license at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package test
    16  
    17  import (
    18  	"crypto/tls"
    19  	"fmt"
    20  	"io"
    21  	"net"
    22  	"strings"
    23  	"sync"
    24  	"testing"
    25  	"time"
    26  
    27  	"go.nanomsg.org/mangos/v3"
    28  	"go.nanomsg.org/mangos/v3/transport"
    29  )
    30  
    31  type tranOption interface {
    32  	SetOption(string, interface{}) error
    33  	GetOption(string) (interface{}, error)
    34  }
    35  
    36  func getTranPair(t *testing.T, tran transport.Transport) (mangos.Dialer, mangos.Listener, mangos.Socket, mangos.Socket) {
    37  	addr := getScratchAddr(tran)
    38  	s1 := GetMockSocket()
    39  	s2 := GetMockSocket()
    40  	d, e := s1.NewDialer(addr, nil)
    41  	MustSucceed(t, e)
    42  	MustNotBeNil(t, d)
    43  	l, e := s2.NewListener(addr, nil)
    44  	MustSucceed(t, e)
    45  	MustNotBeNil(t, l)
    46  	return d, l, s1, s2
    47  }
    48  
    49  func getScratchAddr(tran transport.Transport) string {
    50  	switch tran.Scheme() {
    51  	case "mock":
    52  		return "mock://mock"
    53  	case "inproc":
    54  		return AddrTestInp()
    55  	case "tcp":
    56  		return AddrTestTCP()
    57  	case "ipc":
    58  		return AddrTestIPC()
    59  	case "tls+tcp":
    60  		return AddrTestTLS()
    61  	case "ws":
    62  		return AddrTestWS()
    63  	case "wss":
    64  		return AddrTestWSS()
    65  	}
    66  	return "unknown://"
    67  }
    68  
    69  // TranVerifyBoolOption verifies that a bool option behaves properly.
    70  func TranVerifyBoolOption(t *testing.T, tran transport.Transport, name string) {
    71  	d, l, s1, s2 := getTranPair(t, tran)
    72  	defer MustClose(t, s1)
    73  	defer MustClose(t, s2)
    74  
    75  	for _, o := range []tranOption{d, l} {
    76  		MustBeError(t, o.SetOption(name, "nope"), mangos.ErrBadValue)
    77  		MustSucceed(t, o.SetOption(name, true))
    78  		MustSucceed(t, o.SetOption(name, false))
    79  		v, e := o.GetOption(name)
    80  		MustSucceed(t, e)
    81  		_, ok := v.(bool)
    82  		MustBeTrue(t, ok)
    83  	}
    84  }
    85  
    86  // TranVerifyIntOption verifies that an int option behaves properly.
    87  func TranVerifyIntOption(t *testing.T, tran transport.Transport, name string) {
    88  	d, l, s1, s2 := getTranPair(t, tran)
    89  	defer MustClose(t, s1)
    90  	defer MustClose(t, s2)
    91  
    92  	for _, o := range []tranOption{d, l} {
    93  
    94  		MustBeError(t, o.SetOption(name, "nope"), mangos.ErrBadValue)
    95  		MustBeError(t, o.SetOption(name, false), mangos.ErrBadValue)
    96  		MustSucceed(t, o.SetOption(name, 2))
    97  		MustSucceed(t, o.SetOption(name, 42))
    98  		v, e := o.GetOption(name)
    99  		MustSucceed(t, e)
   100  		_, ok := v.(int)
   101  		MustBeTrue(t, ok)
   102  	}
   103  }
   104  
   105  // TranVerifyDurationOption verifies that a time.Duration option behaves properly.
   106  func TranVerifyDurationOption(t *testing.T, tran transport.Transport, name string) {
   107  	d, l, s1, s2 := getTranPair(t, tran)
   108  	defer MustClose(t, s1)
   109  	defer MustClose(t, s2)
   110  
   111  	MustBeError(t, d.SetOption(name, "nope"), mangos.ErrBadValue)
   112  	MustSucceed(t, d.SetOption(name, time.Second))
   113  	v, e := d.GetOption(name)
   114  	MustSucceed(t, e)
   115  	_, ok := v.(time.Duration)
   116  	MustBeTrue(t, ok)
   117  
   118  	MustBeError(t, l.SetOption(name, false), mangos.ErrBadValue)
   119  	MustSucceed(t, l.SetOption(name, time.Hour))
   120  	v, e = l.GetOption(name)
   121  	MustSucceed(t, e)
   122  	_, ok = v.(time.Duration)
   123  	MustBeTrue(t, ok)
   124  }
   125  
   126  // TranVerifyNoDelayOption verifies that NoDelay is always true.
   127  func TranVerifyNoDelayOption(t *testing.T, tran transport.Transport) {
   128  	d, l, s1, s2 := getTranPair(t, tran)
   129  	defer MustClose(t, s1)
   130  	defer MustClose(t, s2)
   131  
   132  	name := mangos.OptionNoDelay
   133  	for _, o := range []tranOption{d, l} {
   134  		MustBeError(t, o.SetOption(name, "nope"), mangos.ErrBadValue)
   135  		MustSucceed(t, o.SetOption(name, true))
   136  		MustSucceed(t, o.SetOption(name, false)) // But it must not work
   137  		v, e := o.GetOption(name)
   138  		MustSucceed(t, e)
   139  		b, ok := v.(bool)
   140  		MustBeTrue(t, ok)
   141  		MustBeTrue(t, b)
   142  	}
   143  }
   144  
   145  // TranVerifyKeepAliveOption verifies that keep alive options work.
   146  func TranVerifyKeepAliveOption(t *testing.T, tran transport.Transport) {
   147  	d, l, s1, s2 := getTranPair(t, tran)
   148  	defer MustClose(t, s1)
   149  	defer MustClose(t, s2)
   150  
   151  	// First verify that the base types work
   152  	TranVerifyBoolOption(t, tran, mangos.OptionKeepAlive)
   153  	TranVerifyDurationOption(t, tran, mangos.OptionKeepAliveTime)
   154  
   155  	// Now try setting various things.
   156  	for _, o := range []tranOption{d, l} {
   157  
   158  		// Setting the legacy option to true
   159  		MustSucceed(t, o.SetOption(mangos.OptionKeepAlive, true))
   160  		b, e := o.GetOption(mangos.OptionKeepAlive)
   161  		MustSucceed(t, e)
   162  		MustBeTrue(t, b.(bool))
   163  		x, e := o.GetOption(mangos.OptionKeepAliveTime)
   164  		MustSucceed(t, e)
   165  		MustBeTrue(t, x.(time.Duration) >= 0)
   166  
   167  		// Setting the legacy option to false
   168  		MustSucceed(t, o.SetOption(mangos.OptionKeepAlive, false))
   169  		b, e = o.GetOption(mangos.OptionKeepAlive)
   170  		MustSucceed(t, e)
   171  		MustBeFalse(t, b.(bool))
   172  		x, e = o.GetOption(mangos.OptionKeepAliveTime)
   173  		MustSucceed(t, e)
   174  		MustBeTrue(t, x.(time.Duration) < 0)
   175  
   176  		// Setting the duration to zero (on)
   177  		MustSucceed(t, o.SetOption(mangos.OptionKeepAliveTime, time.Duration(0)))
   178  		b, e = o.GetOption(mangos.OptionKeepAlive)
   179  		MustSucceed(t, e)
   180  		MustBeTrue(t, b.(bool))
   181  
   182  		MustSucceed(t, o.SetOption(mangos.OptionKeepAliveTime, time.Duration(-1)))
   183  		b, e = o.GetOption(mangos.OptionKeepAlive)
   184  		MustSucceed(t, e)
   185  		MustBeFalse(t, b.(bool))
   186  
   187  		MustSucceed(t, o.SetOption(mangos.OptionKeepAliveTime, time.Second))
   188  		b, e = o.GetOption(mangos.OptionKeepAlive)
   189  		MustSucceed(t, e)
   190  		MustBeTrue(t, b.(bool))
   191  	}
   192  
   193  }
   194  
   195  // TranVerifyTLSConfigOption verifies that OptionTLSConfig works properly.
   196  func TranVerifyTLSConfigOption(t *testing.T, tran transport.Transport) {
   197  	d, l, s1, s2 := getTranPair(t, tran)
   198  	defer MustClose(t, s1)
   199  	defer MustClose(t, s2)
   200  
   201  	name := mangos.OptionTLSConfig
   202  
   203  	MustBeError(t, d.SetOption(name, "nope"), mangos.ErrBadValue)
   204  	MustSucceed(t, d.SetOption(name, GetTLSConfig(t, false)))
   205  	v, e := d.GetOption(name)
   206  	MustSucceed(t, e)
   207  	_, ok := v.(*tls.Config)
   208  	MustBeTrue(t, ok)
   209  
   210  	MustBeError(t, l.SetOption(name, false), mangos.ErrBadValue)
   211  	MustSucceed(t, l.SetOption(name, GetTLSConfig(t, true)))
   212  	v, e = l.GetOption(name)
   213  	MustSucceed(t, e)
   214  	_, ok = v.(*tls.Config)
   215  	MustBeTrue(t, ok)
   216  }
   217  
   218  // TranVerifyInvalidOption verifies that an invalid option behaves properly.
   219  func TranVerifyInvalidOption(t *testing.T, tran transport.Transport) {
   220  	d, l, s1, s2 := getTranPair(t, tran)
   221  	defer MustClose(t, s1)
   222  	defer MustClose(t, s2)
   223  
   224  	// Dialer first.
   225  	MustBeError(t, d.SetOption("NoSuchOption", 0), mangos.ErrBadOption)
   226  	_, e := d.GetOption("NoSuchOption")
   227  	MustBeError(t, e, mangos.ErrBadOption)
   228  
   229  	MustBeError(t, l.SetOption("NoSuchOption", 0), mangos.ErrBadOption)
   230  	_, e = l.GetOption("NoSuchOption")
   231  	MustBeError(t, e, mangos.ErrBadOption)
   232  }
   233  
   234  // TranVerifyScheme verifies that we get the right scheme.  It also tries
   235  // an invalid scheme.
   236  func TranVerifyScheme(t *testing.T, tran transport.Transport) {
   237  	sock := GetMockSocket()
   238  	defer MustClose(t, sock)
   239  	d, e := tran.NewDialer("wrong://", sock)
   240  	MustBeError(t, e, mangos.ErrBadTran)
   241  	MustBeTrue(t, d == nil)
   242  	l, e := tran.NewListener("wrong://", sock)
   243  	MustBeError(t, e, mangos.ErrBadTran)
   244  	MustBeTrue(t, l == nil)
   245  
   246  	addr := getScratchAddr(tran)
   247  	d, e = tran.NewDialer(addr, sock)
   248  	MustSucceed(t, e)
   249  	MustNotBeNil(t, d)
   250  
   251  	l, e = tran.NewListener(addr, sock)
   252  	MustSucceed(t, e)
   253  	MustNotBeNil(t, l)
   254  	addr2 := l.Address()
   255  	MustBeTrue(t, strings.HasPrefix(addr2, tran.Scheme()+"://"))
   256  }
   257  
   258  // TranVerifyConnectionRefused verifies that connection is refused if no listener.
   259  func TranVerifyConnectionRefused(t *testing.T, tran transport.Transport, opts map[string]interface{}) {
   260  	sock := GetMockSocket()
   261  	defer MustClose(t, sock)
   262  	d, _ := sock.NewDialer(getScratchAddr(tran), opts)
   263  	MustFail(t, d.Dial()) // Windows won't let us validate properly
   264  }
   265  
   266  // TranVerifyDuplicateListen verifies that we can't bind to the same address twice.
   267  func TranVerifyDuplicateListen(t *testing.T, tran transport.Transport, opts map[string]interface{}) {
   268  	sock1 := GetMockSocket()
   269  	defer MustClose(t, sock1)
   270  	sock2 := GetMockSocket()
   271  	defer MustClose(t, sock2)
   272  	addr := getScratchAddr(tran)
   273  	l1, _ := sock1.NewListener(addr, opts)
   274  	l2, _ := sock2.NewListener(addr, opts)
   275  	MustSucceed(t, l1.Listen())
   276  	MustFail(t, l2.Listen()) // Cannot validate ErrAddrInUse because Windows
   277  }
   278  
   279  // TranVerifyListenAndAccept verifies that we can establish the connection.
   280  func TranVerifyListenAndAccept(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   281  	s1 := GetMockSocket()
   282  	s2 := GetMockSocket()
   283  	defer MustClose(t, s1)
   284  	defer MustClose(t, s2)
   285  	addr := getScratchAddr(tran)
   286  	d, e := s1.NewDialer(addr, dOpts)
   287  	MustSucceed(t, e)
   288  	l, e := s2.NewListener(addr, lOpts)
   289  	MustSucceed(t, e)
   290  	MustSucceed(t, l.Listen())
   291  
   292  	var wg sync.WaitGroup
   293  	wg.Add(1)
   294  	pass := false
   295  	go func() {
   296  		defer wg.Done()
   297  		MustSucceed(t, d.Dial())
   298  		pass = true
   299  	}()
   300  
   301  	wg.Wait()
   302  	MustBeTrue(t, pass)
   303  }
   304  
   305  // TranVerifyAcceptWithoutListen verifies that we can't call accept if we
   306  // did not first call listen.
   307  func TranVerifyAcceptWithoutListen(t *testing.T, tran transport.Transport) {
   308  	sock := GetMockSocket()
   309  	defer MustClose(t, sock)
   310  	l, e := tran.NewListener(getScratchAddr(tran), sock)
   311  	MustSucceed(t, e)
   312  	_, e = l.Accept()
   313  	MustBeError(t, e, mangos.ErrClosed)
   314  }
   315  
   316  // TranVerifyMaxRecvSize verifies the transport handles maximum receive size properly.
   317  func TranVerifyMaxRecvSize(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   318  	VerifyOptionMaxRecvSize(t, NewMockSocket)
   319  
   320  	addr := getScratchAddr(tran)
   321  	tx := GetMockSocket()
   322  	rx := GetMockSocket()
   323  	defer MustClose(t, tx)
   324  	defer MustClose(t, rx)
   325  	maxRx := 100
   326  
   327  	// Now try setting the option
   328  	MustSucceed(t, rx.SetOption(mangos.OptionMaxRecvSize, maxRx))
   329  	// At this point, we can issue requests on rq, and read them from rp.
   330  	MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50))
   331  	MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second))
   332  
   333  	ConnectPairVia(t, addr, rx, tx, lOpts, dOpts)
   334  
   335  	for i := maxRx - 2; i < maxRx+2; i++ {
   336  		m := mangos.NewMessage(i)
   337  		m.Body = append(m.Body, make([]byte, i)...)
   338  		MustSendMsg(t, tx, m)
   339  		if i <= maxRx {
   340  			m = MustRecvMsg(t, rx)
   341  			m.Free()
   342  		} else {
   343  			MustNotRecv(t, rx, mangos.ErrRecvTimeout)
   344  		}
   345  	}
   346  }
   347  
   348  // TranVerifyHandshakeFail verifies that we fail if the protocols mismatch.
   349  func TranVerifyHandshakeFail(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   350  	s1 := GetMockSocketEx(1, "mock1")
   351  	s2 := GetMockSocketEx(2, "mock2")
   352  	defer MustClose(t, s1)
   353  	defer MustClose(t, s2)
   354  	addr := getScratchAddr(tran)
   355  	d, e := s1.NewDialer(addr, dOpts)
   356  	MustSucceed(t, e)
   357  	l, e := s2.NewListener(addr, lOpts)
   358  	MustSucceed(t, e)
   359  	MustSucceed(t, l.Listen())
   360  
   361  	var wg sync.WaitGroup
   362  	wg.Add(1)
   363  	pass := false
   364  	go func() {
   365  		defer wg.Done()
   366  		e = d.Dial()
   367  		MustBeError(t, e, mangos.ErrBadProto)
   368  		pass = true
   369  	}()
   370  
   371  	wg.Wait()
   372  	MustBeTrue(t, pass)
   373  }
   374  
   375  // TranVerifySendRecv just verifies basic send and receive.
   376  func TranVerifySendRecv(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   377  	tx := GetMockSocket()
   378  	rx := GetMockSocket()
   379  	defer MustClose(t, tx)
   380  	defer MustClose(t, rx)
   381  
   382  	MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Second))
   383  	MustSucceed(t, tx.SetOption(mangos.OptionRecvDeadline, time.Second))
   384  	MustSucceed(t, rx.SetOption(mangos.OptionSendDeadline, time.Second))
   385  	MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second))
   386  
   387  	addr := getScratchAddr(tran)
   388  	d, e := tx.NewDialer(addr, dOpts)
   389  	MustSucceed(t, e)
   390  	l, e := rx.NewListener(addr, lOpts)
   391  	MustSucceed(t, e)
   392  
   393  	MustSucceed(t, l.Listen())
   394  	MustSucceed(t, d.Dial())
   395  
   396  	for i := 0; i < 10; i++ {
   397  		send := fmt.Sprintf("SEND%d", i)
   398  		repl := fmt.Sprintf("REPL%d", i)
   399  		MustSendString(t, tx, send)
   400  		MustRecvString(t, rx, send)
   401  		MustSendString(t, rx, repl)
   402  		MustRecvString(t, tx, repl)
   403  	}
   404  }
   405  
   406  // TranVerifyAnonymousPort is used by TCP based transports to verify that using
   407  // a wild card port address works. The addr is an address using a wild card
   408  // port (usually port 0).
   409  func TranVerifyAnonymousPort(t *testing.T, addr string, dOpts, lOpts map[string]interface{}) {
   410  	tx := GetMockSocket()
   411  	rx := GetMockSocket()
   412  	defer MustClose(t, tx)
   413  	defer MustClose(t, rx)
   414  
   415  	MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Second))
   416  	MustSucceed(t, tx.SetOption(mangos.OptionRecvDeadline, time.Second))
   417  	MustSucceed(t, rx.SetOption(mangos.OptionSendDeadline, time.Second))
   418  	MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second))
   419  
   420  	// First get the listener.
   421  	l, e := rx.NewListener(addr, lOpts)
   422  	MustSucceed(t, e)
   423  	MustBeTrue(t, l.Address() == addr)
   424  	MustSucceed(t, l.Listen())
   425  	MustBeTrue(t, l.Address() != addr)
   426  
   427  	d, e := tx.NewDialer(l.Address(), dOpts)
   428  	MustSucceed(t, e)
   429  	MustSucceed(t, d.Dial())
   430  
   431  	MustSendString(t, tx, "hello")
   432  	MustRecvString(t, rx, "hello")
   433  
   434  	// Impossible to dial to a wildcard address
   435  	d2, e := tx.NewDialer(addr, dOpts)
   436  	if e == nil {
   437  		MustFail(t, d2.Dial())
   438  	}
   439  }
   440  
   441  // TranVerifyPipeOptions verifies that the LocalAddr, RemoteAddr and invalid
   442  // options all behave as we expect.
   443  func TranVerifyPipeOptions(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   444  	tx := GetMockSocket()
   445  	rx := GetMockSocket()
   446  	defer MustClose(t, tx)
   447  	defer MustClose(t, rx)
   448  
   449  	addr := getScratchAddr(tran)
   450  	MustSucceed(t, rx.SetOption(mangos.OptionRecvDeadline, time.Second))
   451  	MustSucceed(t, tx.SetOption(mangos.OptionRecvDeadline, time.Second))
   452  	MustSucceed(t, rx.SetOption(mangos.OptionSendDeadline, time.Second))
   453  	MustSucceed(t, tx.SetOption(mangos.OptionSendDeadline, time.Second))
   454  
   455  	MustSucceed(t, rx.ListenOptions(addr, lOpts))
   456  	MustSucceed(t, tx.DialOptions(addr, dOpts))
   457  
   458  	MustSendString(t, tx, "hello")
   459  	m := MustRecvMsg(t, rx)
   460  	p1 := m.Pipe
   461  
   462  	MustSendString(t, rx, "there")
   463  	m = MustRecvMsg(t, tx)
   464  	p2 := m.Pipe
   465  
   466  	remaddr := []net.Addr{}
   467  	locaddr := []net.Addr{}
   468  
   469  	for _, p := range []mangos.Pipe{p1, p2} {
   470  		a, e := p.GetOption(mangos.OptionLocalAddr)
   471  		addr1 := a.(net.Addr)
   472  		MustSucceed(t, e)
   473  		MustBeTrue(t, len(addr1.Network()) > 0)
   474  		MustBeTrue(t, len(addr1.String()) > 0)
   475  
   476  		a, e = p.GetOption(mangos.OptionRemoteAddr)
   477  		addr2 := a.(net.Addr)
   478  		MustSucceed(t, e)
   479  		MustBeTrue(t, len(addr2.Network()) > 0)
   480  		MustBeTrue(t, len(addr2.String()) > 0)
   481  
   482  		MustBeTrue(t, addr2.Network() == addr1.Network())
   483  
   484  		locaddr = append(locaddr, addr1)
   485  		remaddr = append(remaddr, addr2)
   486  
   487  		_, e = p.GetOption("NO-SUCH-OPTION")
   488  		MustFail(t, e)
   489  	}
   490  	MustBeTrue(t, remaddr[0].String() == locaddr[1].String())
   491  	MustBeTrue(t, remaddr[1].String() == locaddr[0].String())
   492  
   493  }
   494  
   495  // TranVerifyBadLocalAddress is used to verify that a given address cannot be
   496  // listened to.  This could be for an address that we cannot resolve a name
   497  // for, or an address that we do not have an IP address for.  The failure can
   498  // occur at either listener allocation time, or when trying to bind.
   499  func TranVerifyBadLocalAddress(t *testing.T, addr string, opts map[string]interface{}) {
   500  	sock := GetMockSocket()
   501  	defer MustClose(t, sock)
   502  
   503  	if l, e := sock.NewListener(addr, opts); e == nil {
   504  		MustFail(t, l.Listen())
   505  	}
   506  }
   507  
   508  // TranVerifyBadRemoteAddress is used to verify that a given address cannot be
   509  // dialed to.  This could be for an address that we cannot resolve a name
   510  // for, or an address is known to be otherwise impossible or invalid.
   511  func TranVerifyBadRemoteAddress(t *testing.T, addr string, opts map[string]interface{}) {
   512  	sock := GetMockSocket()
   513  	defer MustClose(t, sock)
   514  
   515  	if d, e := sock.NewDialer(addr, opts); e == nil {
   516  		MustFail(t, d.Dial())
   517  	}
   518  }
   519  
   520  // TranVerifyBadAddress is used to verify that certain addresses are invalid
   521  // and cannot be used for dialing or listening.  This is useful, for example,
   522  // when checking that DNS failures are handled properly.
   523  func TranVerifyBadAddress(t *testing.T, addr string, dOpts, lOpts map[string]interface{}) {
   524  	TranVerifyBadLocalAddress(t, addr, lOpts)
   525  	TranVerifyBadRemoteAddress(t, addr, dOpts)
   526  }
   527  
   528  // TranVerifyListenerClosed verifies that the listener behaves after closed.
   529  func TranVerifyListenerClosed(t *testing.T, tran transport.Transport, opts map[string]interface{}) {
   530  	sock := GetMockSocket()
   531  	defer MustClose(t, sock)
   532  
   533  	l, e := tran.NewListener(getScratchAddr(tran), sock)
   534  	MustSucceed(t, e)
   535  	for key, val := range opts {
   536  		MustSucceed(t, l.SetOption(key, val))
   537  	}
   538  	MustSucceed(t, l.Close())
   539  	MustBeError(t, l.Listen(), mangos.ErrClosed)
   540  	_, e = l.Accept()
   541  	MustBeError(t, e, mangos.ErrClosed)
   542  	_ = l.Close() // this might succeed or fail, we don't care.
   543  
   544  	l, e = tran.NewListener(getScratchAddr(tran), sock)
   545  	MustSucceed(t, e)
   546  	for key, val := range opts {
   547  		MustSucceed(t, l.SetOption(key, val))
   548  	}
   549  	MustSucceed(t, l.Listen())
   550  	MustSucceed(t, l.Close())
   551  	_, e = l.Accept()
   552  	MustBeError(t, e, mangos.ErrClosed)
   553  
   554  	// Now async
   555  	l, e = tran.NewListener(getScratchAddr(tran), sock)
   556  	MustSucceed(t, e)
   557  	for key, val := range opts {
   558  		MustSucceed(t, l.SetOption(key, val))
   559  	}
   560  	MustSucceed(t, l.Listen())
   561  	time.AfterFunc(time.Millisecond*50, func() {
   562  		MustSucceed(t, l.Close())
   563  	})
   564  	_, e = l.Accept()
   565  	MustBeError(t, e, mangos.ErrClosed)
   566  }
   567  
   568  // TranVerifyDialNoCert verifies that we fail to dial if we lack a Server cert.
   569  func TranVerifyDialNoCert(t *testing.T, tran transport.Transport) {
   570  	sock := GetMockSocket()
   571  	defer MustClose(t, sock)
   572  
   573  	addr := getScratchAddr(tran)
   574  	opts := make(map[string]interface{})
   575  	opts[mangos.OptionTLSConfig] = GetTLSConfig(t, true)
   576  	MustSucceed(t, sock.ListenOptions(addr, opts))
   577  
   578  	// Unfortunately the tls package doesn't allow us to distinguish
   579  	// the various errors.
   580  	MustFail(t, sock.Dial(addr))
   581  }
   582  
   583  // TranVerifyDialInsecure verifies InsecureSkipVerify.
   584  func TranVerifyDialInsecure(t *testing.T, tran transport.Transport) {
   585  	sock := GetMockSocket()
   586  	defer MustClose(t, sock)
   587  
   588  	addr := getScratchAddr(tran)
   589  	opts := make(map[string]interface{})
   590  	opts[mangos.OptionTLSConfig] = GetTLSConfig(t, true)
   591  	MustSucceed(t, sock.ListenOptions(addr, opts))
   592  
   593  	opts = make(map[string]interface{})
   594  	opts[mangos.OptionTLSConfig] = &tls.Config{}
   595  	MustFail(t, sock.DialOptions(addr, opts))
   596  
   597  	opts[mangos.OptionTLSConfig] = &tls.Config{
   598  		InsecureSkipVerify: true,
   599  	}
   600  	MustSucceed(t, sock.DialOptions(addr, opts))
   601  }
   602  
   603  // TranVerifyMessageSizes verifies we can transport a variety of message sizes
   604  func TranVerifyMessageSizes(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   605  	sock1 := GetMockSocket()
   606  	sock2 := GetMockSocket()
   607  	addr := getScratchAddr(tran)
   608  	defer MustClose(t, sock1)
   609  	defer MustClose(t, sock2)
   610  
   611  	MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second))
   612  	MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second))
   613  	MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second))
   614  	MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second))
   615  	MustSucceed(t, sock1.ListenOptions(addr, lOpts))
   616  	MustSucceed(t, sock2.DialOptions(addr, dOpts))
   617  
   618  	for i := 0; i < 20; i++ {
   619  		sz := 1 << i
   620  		m := mangos.NewMessage(sz)
   621  		for j := 0; j < sz; j++ {
   622  			m.Body = append(m.Body, byte(i))
   623  		}
   624  		MustSendMsg(t, sock1, m)
   625  		m = MustRecvMsg(t, sock2)
   626  		MustBeTrue(t, len(m.Body) == sz)
   627  		for j := 0; j < sz; j++ {
   628  			MustBeTrue(t, m.Body[j] == byte(i))
   629  		}
   630  		m.Free()
   631  	}
   632  	// And back down:
   633  	for i := 20; i >= 0; i-- {
   634  		sz := 1 << i
   635  		m := mangos.NewMessage(sz)
   636  		for j := 0; j < sz; j++ {
   637  			m.Body = append(m.Body, byte(i))
   638  		}
   639  		MustSendMsg(t, sock1, m)
   640  		m = MustRecvMsg(t, sock2)
   641  		MustBeTrue(t, len(m.Body) == sz)
   642  		for j := 0; j < sz; j++ {
   643  			MustBeTrue(t, m.Body[j] == byte(i))
   644  		}
   645  		m.Free()
   646  	}
   647  }
   648  
   649  // TranVerifyMessageHeader verifies that message headers are transmitted.
   650  func TranVerifyMessageHeader(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   651  	sock1 := GetMockSocket()
   652  	sock2 := GetMockSocket()
   653  	addr := getScratchAddr(tran)
   654  	defer MustClose(t, sock1)
   655  	defer MustClose(t, sock2)
   656  
   657  	MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second))
   658  	MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second))
   659  	MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second))
   660  	MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second))
   661  	MustSucceed(t, sock1.ListenOptions(addr, lOpts))
   662  	MustSucceed(t, sock2.DialOptions(addr, dOpts))
   663  
   664  	m := mangos.NewMessage(0)
   665  	m.Header = append(m.Header, 'h', 'e', 'l', 'l', 'o', ',', ' ')
   666  	m.Body = append(m.Body, 'w', 'o', 'r', 'l', 'd')
   667  	MustSendMsg(t, sock1, m)
   668  	MustRecvString(t, sock2, "hello, world")
   669  }
   670  
   671  // TranVerifyPipeAddresses performs basic validation of pipe address options.
   672  func TranVerifyPipeAddresses(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   673  	sock1 := GetMockSocket()
   674  	sock2 := GetMockSocket()
   675  	addr := getScratchAddr(tran)
   676  	defer MustClose(t, sock1)
   677  	defer MustClose(t, sock2)
   678  
   679  	MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second))
   680  	MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second))
   681  	MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second))
   682  	MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second))
   683  	MustSucceed(t, sock1.ListenOptions(addr, lOpts))
   684  	MustSucceed(t, sock2.DialOptions(addr, dOpts))
   685  
   686  	m := mangos.NewMessage(0)
   687  	MustSendMsg(t, sock1, m)
   688  	m = MustRecvMsg(t, sock2)
   689  	p1 := m.Pipe
   690  
   691  	// Now Send it back the other way.
   692  	MustSendMsg(t, sock2, m)
   693  	m = MustRecvMsg(t, sock1)
   694  	p2 := m.Pipe
   695  
   696  	v, e := m.Pipe.GetOption("JUNK")
   697  	MustBeError(t, e, mangos.ErrBadProperty)
   698  	MustBeTrue(t, v == nil)
   699  
   700  	v, e = p1.GetOption(mangos.OptionLocalAddr)
   701  	MustSucceed(t, e)
   702  	la1, ok := v.(net.Addr)
   703  	MustBeTrue(t, ok)
   704  	v, e = p1.GetOption(mangos.OptionRemoteAddr)
   705  	MustSucceed(t, e)
   706  	ra1, ok := v.(net.Addr)
   707  	MustBeTrue(t, ok)
   708  
   709  	v, e = p2.GetOption(mangos.OptionLocalAddr)
   710  	MustSucceed(t, e)
   711  	la2, ok := v.(net.Addr)
   712  	MustBeTrue(t, ok)
   713  	v, e = p2.GetOption(mangos.OptionRemoteAddr)
   714  	MustSucceed(t, e)
   715  	ra2, ok := v.(net.Addr)
   716  	MustBeTrue(t, ok)
   717  
   718  	MustBeTrue(t, la1.Network() == la2.Network())
   719  	MustBeTrue(t, ra1.Network() == ra2.Network())
   720  	MustBeTrue(t, ra2.Network() == ra1.Network())
   721  
   722  	MustBeTrue(t, la1.String() == ra2.String())
   723  	MustBeTrue(t, la2.String() == ra1.String())
   724  
   725  }
   726  
   727  // TranVerifyPipeOptions2 verifies standard pipe Options.
   728  func TranVerifyPipeOptions2(t *testing.T, tran transport.Transport, dOpts, lOpts map[string]interface{}) {
   729  	sock1 := GetMockSocket()
   730  	sock2 := GetMockSocket()
   731  	addr := getScratchAddr(tran)
   732  	defer MustClose(t, sock1)
   733  	defer MustClose(t, sock2)
   734  
   735  	MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second))
   736  	MustSucceed(t, sock1.SetOption(mangos.OptionSendDeadline, time.Second))
   737  	MustSucceed(t, sock2.SetOption(mangos.OptionRecvDeadline, time.Second))
   738  	MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second))
   739  	MustSucceed(t, sock1.ListenOptions(addr, lOpts))
   740  	MustSucceed(t, sock2.DialOptions(addr, dOpts))
   741  
   742  	m := mangos.NewMessage(0)
   743  	MustSendMsg(t, sock1, m)
   744  	m = MustRecvMsg(t, sock2)
   745  	v, e := m.Pipe.GetOption("JUNK")
   746  	MustBeError(t, e, mangos.ErrBadProperty)
   747  	MustBeTrue(t, v == nil)
   748  
   749  	v, e = m.Pipe.GetOption(mangos.OptionMaxRecvSize)
   750  	MustSucceed(t, e)
   751  	_, ok := v.(int)
   752  	MustBeTrue(t, ok)
   753  }
   754  
   755  // type connHeader struct {
   756  // 	Zero     byte // must be zero
   757  // 	S        byte // 'S'
   758  // 	P        byte // 'P'
   759  // 	Version  byte // only zero at present
   760  // 	Proto    uint16
   761  // 	Reserved uint16 // always zero at present
   762  // }
   763  
   764  // TranSendConnBadHandshakes just sends garbage handshakes.
   765  func TranSendConnBadHandshakes(t *testing.T, dial func() (net.Conn, error)) {
   766  
   767  	tries := [][]byte{
   768  		{},
   769  		{0},
   770  		{0, 'S'},
   771  		{0, 'S', 'P'},
   772  		{0, 'S', 'P', 0},
   773  		{0, 'S', 'P', 0, 0},
   774  		{0, 'S', 'P', 0, 0, 0},
   775  		{0, 'S', 'P', 0, 0, 1, 0},
   776  		{0, 'S', 'P', 0, 0, 1, 0, 0},
   777  		{1, 'S', 'P', 0, 0, 0, 0, 0},
   778  		{0, 'x', 'P', 0, 0, 0, 0, 0},
   779  		{0, 'S', 'x', 0, 0, 0, 0, 0},
   780  		{0, 'S', 'P', 2, 0, 0, 0, 0},
   781  		{0, 'S', 'P', 0, 0, 0, 0, 1},
   782  	}
   783  
   784  	for _, b := range tries {
   785  		c, e := dial()
   786  		MustSucceed(t, e)
   787  		_, e = c.Write(b)
   788  		MustSucceed(t, e)
   789  		time.Sleep(time.Millisecond * 10)
   790  		MustSucceed(t, c.Close())
   791  	}
   792  }
   793  
   794  // TranConnHandshake just performs the handshake, the conn should be connected.
   795  func TranConnHandshake(t *testing.T, c net.Conn, proto uint16) {
   796  	hs := []byte{
   797  		0,                 // Zero
   798  		'S',               // S
   799  		'P',               // P
   800  		0,                 // Version
   801  		byte(proto / 256), // Proto Hi byte
   802  		byte(proto % 256), // Proto Lo byte
   803  		0,                 // Reserved Hi
   804  		0,                 // Reserved Lo
   805  	}
   806  	peer := make([]byte, 8)
   807  	_, e := c.Write(hs)
   808  	MustSucceed(t, e)
   809  	_, e = io.ReadFull(c, peer)
   810  	MustSucceed(t, e)
   811  }
   812  
   813  // TranSendBadMessages opens new connections and sends garbage to them.
   814  func TranSendBadMessages(t *testing.T, proto uint16, isipc bool, dial func() (net.Conn, error)) {
   815  
   816  	bad := [][]byte{
   817  		{},
   818  		{0x80},
   819  		{0, 0, 0, 1},
   820  		{0, 0, 0, 0, 0, 0, 0, 10, 1, 2},
   821  		{0x80, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6},
   822  	}
   823  	for _, b := range bad {
   824  		c, e := dial()
   825  		MustSucceed(t, e)
   826  		TranConnHandshake(t, c, proto)
   827  		var x []byte
   828  		if isipc {
   829  			x = append([]byte{1}, b...)
   830  		} else {
   831  			x = b
   832  		}
   833  		_, e = c.Write(x)
   834  		MustSucceed(t, e)
   835  		time.Sleep(time.Millisecond * 10)
   836  		MustSucceed(t, c.Close())
   837  	}
   838  }