github.com/gdamore/mangos@v1.4.0/transport/tcp/tcp_test.go (about)

     1  // Copyright 2018 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 tcp
    16  
    17  import (
    18  	"bytes"
    19  	"testing"
    20  	"time"
    21  
    22  	"nanomsg.org/go-mangos"
    23  	"nanomsg.org/go-mangos/protocol/rep"
    24  	"nanomsg.org/go-mangos/protocol/req"
    25  )
    26  
    27  var tran = NewTransport()
    28  var sockRep, _ = rep.NewSocket()
    29  var sockReq, _ = req.NewSocket()
    30  
    31  func TestTCPListenAndAccept(t *testing.T) {
    32  	addr := "tcp://127.0.0.1:3333"
    33  	t.Logf("Establishing accepter")
    34  	l, err := tran.NewListener(addr, sockRep)
    35  	if err != nil {
    36  		t.Errorf("NewListener failed: %v", err)
    37  		return
    38  	}
    39  	defer l.Close()
    40  	if err = l.Listen(); err != nil {
    41  		t.Errorf("Listen failed: %v", err)
    42  		return
    43  	}
    44  
    45  	go func() {
    46  		d, err := tran.NewDialer(addr, sockReq)
    47  		if err != nil {
    48  			t.Errorf("NewDialier failed: %v", err)
    49  			return
    50  		}
    51  		t.Logf("Connecting")
    52  		client, err := d.Dial()
    53  		if err != nil {
    54  			t.Errorf("Dial failed: %v", err)
    55  			return
    56  		}
    57  		t.Logf("Connected client: %d (server %d)",
    58  			client.LocalProtocol(), client.RemoteProtocol())
    59  		t.Logf("Client open: %t", client.IsOpen())
    60  		if !client.IsOpen() {
    61  			t.Error("Client is closed")
    62  			return
    63  		}
    64  	}()
    65  
    66  	server, err := l.Accept()
    67  	if err != nil {
    68  		t.Errorf("Accept failed: %v", err)
    69  		return
    70  	}
    71  	defer server.Close()
    72  
    73  	t.Logf("Connected server: %d (client %d)",
    74  		server.LocalProtocol(), server.RemoteProtocol())
    75  	t.Logf("Server open: %t", server.IsOpen())
    76  	if !server.IsOpen() {
    77  		t.Error("Server is closed")
    78  		return
    79  	}
    80  }
    81  
    82  func TestTCPAnonymousPort(t *testing.T) {
    83  	addr := "tcp://127.0.0.1:0"
    84  	t.Logf("Establishing accepter")
    85  	l, err := tran.NewListener(addr, sockRep)
    86  	if err != nil {
    87  		t.Errorf("NewListener failed: %v", err)
    88  		return
    89  	}
    90  	defer l.Close()
    91  	if err = l.Listen(); err != nil {
    92  		t.Errorf("Listen failed: %v", err)
    93  		return
    94  	}
    95  	baddr := l.Address()
    96  	t.Logf("Bound to %s", baddr)
    97  
    98  	go func() {
    99  		d, err := tran.NewDialer(baddr, sockReq)
   100  		if err != nil {
   101  			t.Errorf("NewDialier failed: %v", err)
   102  			return
   103  		}
   104  		t.Logf("Connecting")
   105  		client, err := d.Dial()
   106  		if err != nil {
   107  			t.Errorf("Dial failed: %v", err)
   108  			return
   109  		}
   110  		t.Logf("Connected client: %d (server %d)",
   111  			client.LocalProtocol(), client.RemoteProtocol())
   112  		t.Logf("Client open: %t", client.IsOpen())
   113  		if !client.IsOpen() {
   114  			t.Error("Client is closed")
   115  			return
   116  		}
   117  	}()
   118  
   119  	server, err := l.Accept()
   120  	if err != nil {
   121  		t.Errorf("Accept failed: %v", err)
   122  		return
   123  	}
   124  	defer server.Close()
   125  
   126  	t.Logf("Connected server: %d (client %d)",
   127  		server.LocalProtocol(), server.RemoteProtocol())
   128  	t.Logf("Server open: %t", server.IsOpen())
   129  	if !server.IsOpen() {
   130  		t.Error("Server is closed")
   131  		return
   132  	}
   133  }
   134  
   135  func TestTCPDuplicateListen(t *testing.T) {
   136  	addr := "tcp://127.0.0.1:3333"
   137  	var err error
   138  	l1, err := tran.NewListener(addr, sockRep)
   139  	if err != nil {
   140  		t.Errorf("NewListener failed: %v", err)
   141  		return
   142  	}
   143  	defer l1.Close()
   144  	if err = l1.Listen(); err != nil {
   145  		t.Errorf("Listen failed: %v", err)
   146  		return
   147  	}
   148  
   149  	l2, err := tran.NewListener(addr, sockReq)
   150  	if err != nil {
   151  		t.Errorf("NewListener failed: %v", err)
   152  		return
   153  	}
   154  	defer l2.Close()
   155  	if err = l2.Listen(); err == nil {
   156  		t.Errorf("Duplicate listen should not be permitted!")
   157  		return
   158  	}
   159  	t.Logf("Got expected error: %v", err)
   160  }
   161  
   162  func TestTCPConnRefused(t *testing.T) {
   163  	addr := "tcp://127.0.0.1:19" // Port 19 is chargen, rarely in use
   164  	var err error
   165  	d, err := tran.NewDialer(addr, sockReq)
   166  	if err != nil || d == nil {
   167  		t.Errorf("New Dialer failed: %v", err)
   168  		return
   169  	}
   170  	c, err := d.Dial()
   171  	if err == nil || c != nil {
   172  		t.Errorf("Connection not refused (%s)!", addr)
   173  		return
   174  	}
   175  	t.Logf("Got expected error: %v", err)
   176  }
   177  
   178  func TestTCPSendRecv(t *testing.T) {
   179  	addr := "tcp://127.0.0.1:3333"
   180  	ping := []byte("REQUEST_MESSAGE")
   181  	ack := []byte("RESPONSE_MESSAGE")
   182  
   183  	ch := make(chan *mangos.Message)
   184  
   185  	t.Logf("Establishing listener")
   186  	l, err := tran.NewListener(addr, sockRep)
   187  	if err != nil {
   188  		t.Errorf("NewListener failed: %v", err)
   189  		return
   190  	}
   191  	defer l.Close()
   192  	if err = l.Listen(); err != nil {
   193  		t.Errorf("Listen failed: %v", err)
   194  		return
   195  	}
   196  
   197  	go func() {
   198  		defer close(ch)
   199  
   200  		// Client side
   201  		t.Logf("Connecting")
   202  		d, err := tran.NewDialer(addr, sockReq)
   203  
   204  		client, err := d.Dial()
   205  		if err != nil {
   206  			t.Errorf("Dial failed: %v", err)
   207  			return
   208  		}
   209  		t.Logf("Connected client: %t", client.IsOpen())
   210  		defer client.Close()
   211  
   212  		req := mangos.NewMessage(len(ping))
   213  		req.Body = append(req.Body, ping...)
   214  
   215  		// Now try to send data
   216  		t.Logf("Sending %d bytes", len(req.Body))
   217  
   218  		err = client.Send(req)
   219  		if err != nil {
   220  			t.Errorf("Client send error: %v", err)
   221  			return
   222  		}
   223  		t.Logf("Client sent")
   224  
   225  		rep, err := client.Recv()
   226  		if err != nil {
   227  			t.Errorf("Client receive error: %v", err)
   228  			return
   229  		}
   230  
   231  		if !bytes.Equal(rep.Body, ack) {
   232  			t.Errorf("Reply mismatch: %v, %v", rep.Body, ack)
   233  			return
   234  		}
   235  		if len(rep.Header) != 0 {
   236  			t.Errorf("Client reply non-empty header: %v",
   237  				rep.Header)
   238  			return
   239  		}
   240  		select {
   241  		case ch <- rep:
   242  			t.Log("Client reply forwarded")
   243  		case <-time.After(5 * time.Second): // 5 secs should be plenty
   244  			t.Error("Client timeout forwarding reply")
   245  			return
   246  		}
   247  	}()
   248  
   249  	server, err := l.Accept()
   250  	if err != nil {
   251  		t.Errorf("Accept failed: %v", err)
   252  		return
   253  	}
   254  	t.Logf("Connected server: %t", server.IsOpen())
   255  	defer server.Close()
   256  
   257  	// Now we can try to send and receive
   258  	req, err := server.Recv()
   259  	if err != nil {
   260  		t.Errorf("Server receive error: %v", err)
   261  		return
   262  	}
   263  	t.Logf("Server received %d bytes", len(req.Body))
   264  	if !bytes.Equal(req.Body, ping) {
   265  		t.Errorf("Request mismatch: %v, %v", req.Body, ping)
   266  		return
   267  	}
   268  
   269  	if len(req.Header) != 0 {
   270  		t.Errorf("Server request non-empty header: %v", req.Header)
   271  		return
   272  	}
   273  
   274  	// Now reply
   275  	rep := mangos.NewMessage(len(ack))
   276  	rep.Body = append(rep.Body, ack...)
   277  
   278  	t.Logf("Server sending %d bytes", len(rep.Body))
   279  
   280  	err = server.Send(rep)
   281  	if err != nil {
   282  		t.Errorf("Server send error: %v", err)
   283  		return
   284  	}
   285  	t.Log("Server reply sent")
   286  
   287  	// Wait for client to ack reply over back channel.
   288  	select {
   289  	case nrep := <-ch:
   290  		if !bytes.Equal(nrep.Body, ack) {
   291  			t.Errorf("Client forward mismatch: %v, %v", ack, rep)
   292  			return
   293  		}
   294  	case <-time.After(5 * time.Second):
   295  		t.Error("Client timeout?")
   296  		return
   297  	}
   298  }
   299  
   300  func TestTCPOptions(t *testing.T) {
   301  	addr := "tcp://127.0.0.1:19" // Port 19 is chargen, rarely in use
   302  	var err error
   303  	d, err := tran.NewDialer(addr, sockReq)
   304  	if err != nil || d == nil {
   305  		t.Errorf("New Dialer failed: %v", err)
   306  		return
   307  	}
   308  
   309  	t.Logf("Options are %v", interface{}(d).(*dialer).opts)
   310  
   311  	// Valid Boolean Options
   312  	for _, n := range []string{mangos.OptionNoDelay, mangos.OptionKeepAlive} {
   313  		t.Logf("Checking option %s", n)
   314  
   315  		if err := d.SetOption(n, true); err != nil {
   316  			t.Errorf("Set option %s failed: %v", n, err)
   317  			return
   318  		}
   319  
   320  		val, err := d.GetOption(n)
   321  		if err != nil {
   322  			t.Errorf("Get option %s failed: %v", n, err)
   323  			return
   324  		}
   325  		switch v := val.(type) {
   326  		case bool:
   327  			if !v {
   328  				t.Errorf("Option %s value not true", n)
   329  				return
   330  			}
   331  		default:
   332  			t.Errorf("Option %s wrong type!", n)
   333  			return
   334  		}
   335  
   336  		if err = d.SetOption(n, 1234); err != mangos.ErrBadValue {
   337  			t.Errorf("Expected ErrBadValue, but did not get it")
   338  			return
   339  		}
   340  	}
   341  
   342  	// Negative test: try a bad option
   343  	if err = d.SetOption("NO-SUCH-OPTION", 0); err != mangos.ErrBadOption {
   344  		t.Errorf("Expected ErrBadOption, but did not get it")
   345  		return
   346  	}
   347  }