github.com/gdamore/mangos@v1.4.0/test/star_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 test
    16  
    17  import (
    18  	"math/rand"
    19  	"testing"
    20  	"time"
    21  
    22  	"nanomsg.org/go-mangos"
    23  	"nanomsg.org/go-mangos/protocol/star"
    24  	"nanomsg.org/go-mangos/transport/tcp"
    25  )
    26  
    27  type starTester struct {
    28  	id     int
    29  	sock   mangos.Socket
    30  	rdoneq chan bool
    31  	sdoneq chan bool
    32  }
    33  
    34  func starTestSender(t *testing.T, bt *starTester, cnt int) {
    35  	defer close(bt.sdoneq)
    36  	for i := 0; i < cnt; i++ {
    37  		// Inject a small delay to give receivers a chance to catch up
    38  		// Maximum is 10 msec.
    39  		d := time.Duration(rand.Uint32() % 10000)
    40  		time.Sleep(d * time.Microsecond)
    41  		t.Logf("Peer %d: Sending %d", bt.id, i)
    42  		msg := mangos.NewMessage(2)
    43  		msg.Body = append(msg.Body, byte(bt.id), byte(i))
    44  		if err := bt.sock.SendMsg(msg); err != nil {
    45  			t.Errorf("Peer %d send %d fail: %v", bt.id, i, err)
    46  			return
    47  		}
    48  	}
    49  }
    50  
    51  func starTestReceiver(t *testing.T, bt *starTester, cnt int, numID int) {
    52  	var rcpt = make([]int, numID)
    53  	defer close(bt.rdoneq)
    54  
    55  	for tot := 0; tot < (numID-1)*cnt; {
    56  		msg, err := bt.sock.RecvMsg()
    57  		if err != nil {
    58  			t.Errorf("Peer %d: Recv fail: %v", bt.id, err)
    59  			return
    60  		}
    61  
    62  		if len(msg.Body) != 2 {
    63  			t.Errorf("Peer %d: Received wrong length", bt.id)
    64  			return
    65  		}
    66  		peer := int(msg.Body[0])
    67  		if peer == bt.id {
    68  			t.Errorf("Peer %d: Got its own message!", bt.id)
    69  			return
    70  		}
    71  		if int(msg.Body[1]) != rcpt[peer] {
    72  			t.Errorf("Peer %d: Bad message from peer %d: %d s/b %d",
    73  				bt.id, peer, msg.Body[1], rcpt[peer])
    74  			return
    75  		}
    76  		if int(msg.Body[1]) >= cnt {
    77  			t.Errorf("Peer %d: Too many from peer %d", bt.id,
    78  				peer)
    79  			return
    80  		}
    81  		t.Logf("Peer %d: Good rcv from peer %d (%d)", bt.id, peer,
    82  			rcpt[peer])
    83  		rcpt[peer]++
    84  		tot++
    85  		msg.Free()
    86  	}
    87  	t.Logf("Peer %d: Finish", bt.id)
    88  }
    89  
    90  func starTestNewServer(t *testing.T, addr string, id int) *starTester {
    91  	var err error
    92  	bt := &starTester{id: id, rdoneq: make(chan bool), sdoneq: make(chan bool)}
    93  
    94  	if bt.sock, err = star.NewSocket(); err != nil {
    95  		t.Errorf("Failed getting server %d socket: %v", id, err)
    96  		return nil
    97  	}
    98  	bt.sock.AddTransport(tcp.NewTransport())
    99  
   100  	if err = bt.sock.Listen(addr); err != nil {
   101  		t.Errorf("Failed server %d listening: %v", id, err)
   102  		bt.sock.Close()
   103  		return nil
   104  	}
   105  	return bt
   106  }
   107  
   108  func starTestNewClient(t *testing.T, addr string, id int) *starTester {
   109  	var err error
   110  	bt := &starTester{id: id, rdoneq: make(chan bool), sdoneq: make(chan bool)}
   111  
   112  	if bt.sock, err = star.NewSocket(); err != nil {
   113  		t.Errorf("Failed getting client %d socket: %v", id, err)
   114  		return nil
   115  	}
   116  	bt.sock.AddTransport(tcp.NewTransport())
   117  	if err = bt.sock.Dial(addr); err != nil {
   118  		t.Errorf("Failed client %d dialing: %v", id, err)
   119  		bt.sock.Close()
   120  		return nil
   121  	}
   122  	return bt
   123  }
   124  
   125  func starTestCleanup(t *testing.T, bts []*starTester) {
   126  	for id := 0; id < len(bts); id++ {
   127  		t.Logf("Cleanup %d", id)
   128  		if bts[id].sock != nil {
   129  			bts[id].sock.Close()
   130  		}
   131  	}
   132  }
   133  
   134  func TestStar(t *testing.T) {
   135  	addr := "tcp://127.0.0.1:3538"
   136  
   137  	num := 5
   138  	pkts := 7
   139  	bts := make([]*starTester, num)
   140  	defer starTestCleanup(t, bts)
   141  
   142  	t.Logf("Creating star network")
   143  	for id := 0; id < num; id++ {
   144  		if id == 0 {
   145  			bts[id] = starTestNewServer(t, addr, id)
   146  		} else {
   147  			bts[id] = starTestNewClient(t, addr, id)
   148  		}
   149  		if bts[id] == nil {
   150  			t.Errorf("Failed creating %d", id)
   151  			return
   152  		}
   153  	}
   154  
   155  	// wait a little bit for connections to establish
   156  	time.Sleep(time.Microsecond * 500)
   157  
   158  	// start receivers first... avoids first missed dropped packet
   159  	t.Logf("Starting recv")
   160  	for id := 0; id < num; id++ {
   161  		go starTestReceiver(t, bts[id], pkts, num)
   162  	}
   163  
   164  	// wait a little just to be sure go routines are all running
   165  	time.Sleep(time.Millisecond * 10)
   166  
   167  	// then start senders
   168  	t.Logf("Starting send")
   169  	for id := 0; id < num; id++ {
   170  		go starTestSender(t, bts[id], pkts)
   171  	}
   172  
   173  	tmout := time.After(5 * time.Second)
   174  
   175  	for id := 0; id < num; id++ {
   176  		select {
   177  		case <-bts[id].sdoneq:
   178  			continue
   179  		case <-tmout:
   180  			t.Errorf("Timeout waiting for sender id %d", id)
   181  			return
   182  		}
   183  	}
   184  
   185  	for id := 0; id < num; id++ {
   186  		select {
   187  		case <-bts[id].rdoneq:
   188  			continue
   189  		case <-tmout:
   190  			t.Errorf("Timeout waiting for receiver id %d", id)
   191  			return
   192  		}
   193  	}
   194  	t.Logf("All pass")
   195  }
   196  
   197  func TestStarTTLZero(t *testing.T) {
   198  	SetTTLZero(t, star.NewSocket)
   199  }
   200  
   201  func TestStarTTLNegative(t *testing.T) {
   202  	SetTTLNegative(t, star.NewSocket)
   203  }
   204  
   205  func TestStarTTLTooBig(t *testing.T) {
   206  	SetTTLTooBig(t, star.NewSocket)
   207  }
   208  
   209  func TestStarTTLNotInt(t *testing.T) {
   210  	SetTTLNotInt(t, star.NewSocket)
   211  }
   212  
   213  func TestStarTTLSet(t *testing.T) {
   214  	SetTTL(t, star.NewSocket)
   215  }
   216  
   217  func TestStarTTLDrop(t *testing.T) {
   218  	TTLDropTest(t, star.NewSocket, star.NewSocket)
   219  }