nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/protocol/xsub/xsub_test.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 xsub
    16  
    17  import (
    18  	"nanomsg.org/go/mangos/v2"
    19  	"nanomsg.org/go/mangos/v2/protocol/pub"
    20  	"sync"
    21  	"testing"
    22  	"time"
    23  
    24  	. "nanomsg.org/go/mangos/v2/internal/test"
    25  	_ "nanomsg.org/go/mangos/v2/transport/inproc"
    26  )
    27  
    28  func TestXSubIdentity(t *testing.T) {
    29  	s := GetSocket(t, NewSocket)
    30  	id := s.Info()
    31  	MustBeTrue(t, id.Self == mangos.ProtoSub)
    32  	MustBeTrue(t, id.SelfName == "sub")
    33  	MustBeTrue(t, id.Peer == mangos.ProtoPub)
    34  	MustBeTrue(t, id.PeerName == "pub")
    35  	MustSucceed(t, s.Close())
    36  }
    37  
    38  func TestXSubRaw(t *testing.T) {
    39  	VerifyRaw(t, NewSocket)
    40  }
    41  
    42  func TestXSubClosed(t *testing.T) {
    43  	VerifyClosedRecv(t, NewSocket)
    44  	VerifyClosedClose(t, NewSocket)
    45  	VerifyClosedDial(t, NewSocket)
    46  	VerifyClosedListen(t, NewSocket)
    47  	VerifyClosedAddPipe(t, NewSocket)
    48  }
    49  
    50  func TestXSubCannotSend(t *testing.T) {
    51  	CannotSend(t, NewSocket)
    52  }
    53  
    54  func TestXSubCannotSubscribe(t *testing.T) {
    55  	// Raw sockets cannot subscribe or unsubscribe.
    56  	s, e := NewSocket()
    57  	MustSucceed(t, e)
    58  	e = s.SetOption(mangos.OptionSubscribe, []byte("topic"))
    59  	MustFail(t, e)
    60  	MustBeTrue(t, e == mangos.ErrBadOption)
    61  	_ = s.Close()
    62  }
    63  
    64  func TestXSubCannotUnsubscribe(t *testing.T) {
    65  	// Raw sockets cannot subscribe or unsubscribe.
    66  	s, e := NewSocket()
    67  	MustSucceed(t, e)
    68  	e = s.SetOption(mangos.OptionUnsubscribe, []byte("topic"))
    69  	MustFail(t, e)
    70  	MustBeTrue(t, e == mangos.ErrBadOption)
    71  	_ = s.Close()
    72  }
    73  
    74  func TestXSubRecvDeadline(t *testing.T) {
    75  	s, e := NewSocket()
    76  	MustSucceed(t, e)
    77  	e = s.SetOption(mangos.OptionRecvDeadline, time.Millisecond)
    78  	MustSucceed(t, e)
    79  	m, e := s.RecvMsg()
    80  	MustFail(t, e)
    81  	MustBeTrue(t, e == mangos.ErrRecvTimeout)
    82  	MustBeNil(t, m)
    83  	_ = s.Close()
    84  }
    85  
    86  func TestXSubRecvClean(t *testing.T) {
    87  	s, e := NewSocket()
    88  	MustSucceed(t, e)
    89  	p, e := pub.NewSocket()
    90  	MustSucceed(t, e)
    91  	addr := AddrTestInp()
    92  	MustSucceed(t, s.Listen(addr))
    93  	MustSucceed(t, p.Dial(addr))
    94  	MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Second))
    95  	m := mangos.NewMessage(0)
    96  	m.Body = append(m.Body, []byte("Hello world")...)
    97  	e = p.SendMsg(m)
    98  	MustSucceed(t, e)
    99  	m, e = s.RecvMsg()
   100  	MustSucceed(t, e)
   101  	MustNotBeNil(t, m)
   102  	MustBeTrue(t, string(m.Body) == "Hello world")
   103  	_ = p.Close()
   104  	_ = s.Close()
   105  }
   106  
   107  func TestXSubRecvQLen(t *testing.T) {
   108  	s, e := NewSocket()
   109  	MustSucceed(t, e)
   110  	p, e := pub.NewSocket()
   111  	MustSucceed(t, e)
   112  	addr := AddrTestInp()
   113  	MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10))
   114  	MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 2))
   115  	MustSucceed(t, s.Listen(addr))
   116  	MustSucceed(t, p.Dial(addr))
   117  	time.Sleep(time.Millisecond * 50)
   118  
   119  	MustSucceed(t, p.Send([]byte("one")))
   120  	MustSucceed(t, p.Send([]byte("two")))
   121  	MustSucceed(t, p.Send([]byte("three")))
   122  	time.Sleep(time.Millisecond * 50)
   123  
   124  	MustSucceed(t, e)
   125  	m, e := s.RecvMsg()
   126  	MustSucceed(t, e)
   127  	MustNotBeNil(t, m)
   128  	m, e = s.RecvMsg()
   129  	MustSucceed(t, e)
   130  	MustNotBeNil(t, m)
   131  	MustNotRecv(t, s, mangos.ErrRecvTimeout)
   132  	MustClose(t, p)
   133  	MustClose(t, s)
   134  }
   135  
   136  func TestXSubRecvQLenResize(t *testing.T) {
   137  	s := GetSocket(t, NewSocket)
   138  	p := GetSocket(t, pub.NewSocket)
   139  
   140  	MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Millisecond*20))
   141  	MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 4))
   142  	MustSucceed(t, p.SetOption(mangos.OptionWriteQLen, 10))
   143  	ConnectPair(t, s, p)
   144  	time.Sleep(time.Millisecond * 50)
   145  	MustSendString(t, p, "one")
   146  	MustSendString(t, p, "two")
   147  	MustSendString(t, p, "three")
   148  	time.Sleep(time.Millisecond * 100)
   149  	MustRecvString(t, s, "one")
   150  	// Shrink it
   151  	MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 20))
   152  	MustNotRecv(t, s, mangos.ErrRecvTimeout)
   153  
   154  	MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Second))
   155  
   156  	// Now make sure it still works
   157  	MustSendString(t, p, "four")
   158  	MustRecvString(t, s, "four")
   159  
   160  	// Now try a posted recv and asynchronous resize.
   161  	var wg sync.WaitGroup
   162  	wg.Add(1)
   163  	pass := false
   164  	go func() {
   165  		defer wg.Done()
   166  		time.Sleep(time.Millisecond * 20)
   167  		MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 5))
   168  		MustSendString(t, p, "five")
   169  		pass = true
   170  	}()
   171  
   172  	MustRecvString(t, s, "five")
   173  	wg.Wait()
   174  	MustSucceed(t, p.Close())
   175  	MustSucceed(t, s.Close())
   176  	MustBeTrue(t, pass)
   177  }
   178  
   179  func TestXSubOptions(t *testing.T) {
   180  	VerifyInvalidOption(t, NewSocket)
   181  	VerifyOptionDuration(t, NewSocket, mangos.OptionRecvDeadline)
   182  	VerifyOptionInt(t, NewSocket, mangos.OptionReadQLen)
   183  }
   184  
   185  func TestXSubPoundPipes(t *testing.T) {
   186  	self := GetSocket(t, NewSocket)
   187  	var peers []mangos.Socket
   188  	nPeers := 20
   189  	repeat := 100
   190  	var wg sync.WaitGroup
   191  	wg.Add(nPeers)
   192  
   193  	startQ := make(chan struct{})
   194  	for i := 0; i < nPeers; i++ {
   195  		peer := GetSocket(t, pub.NewSocket)
   196  		peers = append(peers, peer)
   197  		ConnectPair(t, self, peer)
   198  
   199  		go func(s mangos.Socket) {
   200  			defer wg.Done()
   201  			<-startQ
   202  			for j := 0; j < repeat; j++ {
   203  				MustSendString(t, s, "yes")
   204  			}
   205  			time.Sleep(time.Millisecond * 10)
   206  		}(peer)
   207  	}
   208  	close(startQ)
   209  	wg.Wait()
   210  	for _, peer := range peers {
   211  		MustSucceed(t, peer.Close())
   212  	}
   213  	MustSucceed(t, self.Close())
   214  }
   215  
   216  func TestXSubPoundClose(t *testing.T) {
   217  	self := GetSocket(t, NewSocket)
   218  	var peers []mangos.Socket
   219  	nPeers := 20
   220  	var wg sync.WaitGroup
   221  	wg.Add(nPeers)
   222  
   223  	startQ := make(chan struct{})
   224  	for i := 0; i < nPeers; i++ {
   225  		peer := GetSocket(t, pub.NewSocket)
   226  		peers = append(peers, peer)
   227  		ConnectPair(t, self, peer)
   228  
   229  		go func(s mangos.Socket) {
   230  			defer wg.Done()
   231  			<-startQ
   232  			for {
   233  				e := s.Send([]byte("yes"))
   234  				if e != nil {
   235  					MustBeError(t, e, mangos.ErrClosed)
   236  					break
   237  				}
   238  			}
   239  			time.Sleep(time.Millisecond * 10)
   240  		}(peer)
   241  	}
   242  	close(startQ)
   243  	time.Sleep(time.Millisecond * 10)
   244  	MustSucceed(t, self.Close())
   245  	time.Sleep(time.Millisecond * 100)
   246  	for _, peer := range peers {
   247  		MustSucceed(t, peer.Close())
   248  	}
   249  	wg.Wait()
   250  
   251  }
   252  
   253  func TestXSubPoundRecv(t *testing.T) {
   254  	self := GetSocket(t, NewSocket)
   255  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0))
   256  	var peers []mangos.Socket
   257  	nPeers := 20
   258  	nReaders := 20
   259  	var wg1 sync.WaitGroup
   260  	var wg2 sync.WaitGroup
   261  	wg1.Add(nPeers)
   262  	wg2.Add(nReaders)
   263  
   264  	for i := 0; i < nReaders; i++ {
   265  		go func() {
   266  			defer wg2.Done()
   267  			for {
   268  				_, e := self.RecvMsg()
   269  				if e != nil {
   270  					break
   271  				}
   272  			}
   273  		}()
   274  	}
   275  
   276  	for i := 0; i < nPeers; i++ {
   277  		peer := GetSocket(t, pub.NewSocket)
   278  		peers = append(peers, peer)
   279  		ConnectPair(t, self, peer)
   280  
   281  		go func(s mangos.Socket) {
   282  			defer wg1.Done()
   283  			for {
   284  				e := s.Send([]byte("yes"))
   285  				if e != nil {
   286  					break
   287  				}
   288  			}
   289  			time.Sleep(time.Millisecond * 10)
   290  		}(peer)
   291  
   292  		// ramp up slowly
   293  		time.Sleep(time.Millisecond)
   294  	}
   295  	time.Sleep(time.Millisecond * 10)
   296  
   297  	for _, peer := range peers {
   298  		MustSucceed(t, peer.Close())
   299  	}
   300  	MustSucceed(t, self.Close())
   301  	wg1.Wait()
   302  	wg2.Wait()
   303  }
   304  
   305  func TestXSubRecvNoQ(t *testing.T) {
   306  	self := GetSocket(t, NewSocket)
   307  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0))
   308  	var peers []mangos.Socket
   309  	nPeers := 20
   310  	var wg1 sync.WaitGroup
   311  	wg1.Add(nPeers)
   312  
   313  	for i := 0; i < nPeers; i++ {
   314  		peer := GetSocket(t, pub.NewSocket)
   315  		peers = append(peers, peer)
   316  		ConnectPair(t, self, peer)
   317  
   318  		go func(s mangos.Socket) {
   319  			defer wg1.Done()
   320  			for {
   321  				e := s.Send([]byte("yes"))
   322  				if e != nil {
   323  					break
   324  				}
   325  			}
   326  			time.Sleep(time.Millisecond * 10)
   327  		}(peer)
   328  
   329  		// ramp up slowly
   330  		time.Sleep(time.Millisecond)
   331  	}
   332  	time.Sleep(time.Millisecond * 10)
   333  
   334  	for _, peer := range peers {
   335  		MustSucceed(t, peer.Close())
   336  	}
   337  	MustSucceed(t, self.Close())
   338  	wg1.Wait()
   339  }