go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/protocol/xpair1/xpair1_test.go (about)

     1  // Copyright 2022 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 xpair1
    16  
    17  import (
    18  	"sync"
    19  	"sync/atomic"
    20  	"testing"
    21  	"time"
    22  
    23  	"go.nanomsg.org/mangos/v3"
    24  	. "go.nanomsg.org/mangos/v3/internal/test"
    25  	_ "go.nanomsg.org/mangos/v3/transport/inproc"
    26  )
    27  
    28  func TestXPair1Identity(t *testing.T) {
    29  	s, err := NewSocket()
    30  	MustSucceed(t, err)
    31  	id := s.Info()
    32  	MustBeTrue(t, id.Self == mangos.ProtoPair1)
    33  	MustBeTrue(t, id.SelfName == "pair1")
    34  	MustBeTrue(t, id.Peer == mangos.ProtoPair1)
    35  	MustBeTrue(t, id.PeerName == "pair1")
    36  	MustSucceed(t, s.Close())
    37  }
    38  
    39  func TestXPair1Raw(t *testing.T) {
    40  	VerifyRaw(t, NewSocket)
    41  }
    42  
    43  func TestXPair1Closed(t *testing.T) {
    44  	VerifyClosedRecv(t, NewSocket)
    45  	//VerifyClosedSend(t, NewSocket)
    46  	VerifyClosedClose(t, NewSocket)
    47  	VerifyClosedDial(t, NewSocket)
    48  	VerifyClosedListen(t, NewSocket)
    49  	VerifyClosedAddPipe(t, NewSocket)
    50  }
    51  
    52  func TestXPair1Options(t *testing.T) {
    53  	VerifyInvalidOption(t, NewSocket)
    54  	VerifyOptionDuration(t, NewSocket, mangos.OptionRecvDeadline)
    55  	VerifyOptionDuration(t, NewSocket, mangos.OptionSendDeadline)
    56  	VerifyOptionInt(t, NewSocket, mangos.OptionReadQLen)
    57  	VerifyOptionInt(t, NewSocket, mangos.OptionWriteQLen)
    58  	VerifyOptionInt(t, NewSocket, mangos.OptionTTL)
    59  	VerifyOptionBool(t, NewSocket, mangos.OptionBestEffort)
    60  }
    61  
    62  func TestXPair1ReceiveDeadline(t *testing.T) {
    63  	self := GetSocket(t, NewSocket)
    64  	MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10))
    65  	MustNotRecv(t, self, mangos.ErrRecvTimeout)
    66  	MustSucceed(t, self.Close())
    67  }
    68  
    69  func TestXPair1SendMissingHeader(t *testing.T) {
    70  	self := GetSocket(t, NewSocket)
    71  	peer := GetSocket(t, NewSocket)
    72  	ConnectPair(t, self, peer)
    73  	MustSucceed(t, peer.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10))
    74  	MustSend(t, self, []byte{}) // empty message (no header)
    75  	MustNotRecv(t, peer, mangos.ErrRecvTimeout)
    76  	MustSucceed(t, self.Close())
    77  	MustSucceed(t, peer.Close())
    78  }
    79  
    80  func TestXPair1SendMalformedHeader(t *testing.T) {
    81  	self := GetSocket(t, NewSocket)
    82  	peer := GetSocket(t, NewSocket)
    83  	ConnectPair(t, self, peer)
    84  	MustSucceed(t, peer.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10))
    85  	m := mangos.NewMessage(0)
    86  	m.Header = append(m.Header, 1, 0, 0, 0)
    87  	MustSendMsg(t, self, m) // malformed header
    88  	MustNotRecv(t, peer, mangos.ErrRecvTimeout)
    89  	MustSucceed(t, self.Close())
    90  	MustSucceed(t, peer.Close())
    91  }
    92  
    93  func TestXPair1SendClosed(t *testing.T) {
    94  	self := GetSocket(t, NewSocket)
    95  	peer := GetSocket(t, NewSocket)
    96  	ConnectPair(t, self, peer)
    97  	MustSucceed(t, peer.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10))
    98  	MustSucceed(t, self.Close())
    99  	m := mangos.NewMessage(0)
   100  	m.Header = append(m.Header, 0, 0, 0, 0)
   101  	err := self.SendMsg(m)
   102  	MustBeError(t, err, mangos.ErrClosed)
   103  	MustNotRecv(t, peer, mangos.ErrRecvTimeout)
   104  	MustSucceed(t, peer.Close())
   105  }
   106  
   107  func TestXPair1SendClosedBestEffort(t *testing.T) {
   108  	self := GetSocket(t, NewSocket)
   109  	peer := GetSocket(t, NewSocket)
   110  	ConnectPair(t, self, peer)
   111  	MustSucceed(t, peer.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10))
   112  	MustSucceed(t, self.SetOption(mangos.OptionBestEffort, true))
   113  	MustSucceed(t, self.Close())
   114  	m := mangos.NewMessage(0)
   115  	m.Header = append(m.Header, 0, 0, 0, 0)
   116  	MustBeError(t, self.SendMsg(m), mangos.ErrClosed)
   117  	MustNotRecv(t, peer, mangos.ErrRecvTimeout)
   118  	MustSucceed(t, peer.Close())
   119  }
   120  
   121  func TestXPair1SendDeadline(t *testing.T) {
   122  	self := GetSocket(t, NewSocket)
   123  	MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 0))
   124  	MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Millisecond*10))
   125  	m := mangos.NewMessage(0)
   126  	m.Header = append(m.Header, 0, 0, 0, 1)
   127  	MustBeError(t, self.SendMsg(m), mangos.ErrSendTimeout)
   128  	MustSucceed(t, self.Close())
   129  }
   130  
   131  func TestXPair1SendBestEffort(t *testing.T) {
   132  	self := GetSocket(t, NewSocket)
   133  	MustSucceed(t, self.SetOption(mangos.OptionBestEffort, true))
   134  	MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 0))
   135  	MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Millisecond*10))
   136  	for i := 0; i < 100; i++ {
   137  		m := mangos.NewMessage(0)
   138  		m.Header = append(m.Header, 0, 0, 0, 1)
   139  		m.Body = append(m.Body, []byte("yep")...)
   140  		MustSendMsg(t, self, m)
   141  	}
   142  	time.Sleep(time.Millisecond * 20)
   143  	MustSucceed(t, self.Close())
   144  }
   145  
   146  func TestXPair1RejectSecondPipe(t *testing.T) {
   147  	self := GetSocket(t, NewSocket)
   148  	peer1 := GetSocket(t, NewSocket)
   149  	peer2 := GetSocket(t, NewSocket)
   150  
   151  	ConnectPair(t, self, peer1)
   152  	a := AddrTestInp()
   153  	MustSucceed(t, self.Listen(a))
   154  
   155  	con := int32(0)
   156  	add := int32(0)
   157  	dis := int32(0)
   158  	peer2.SetPipeEventHook(func(ev mangos.PipeEvent, p mangos.Pipe) {
   159  		switch ev {
   160  		case mangos.PipeEventAttaching:
   161  			atomic.AddInt32(&con, 1)
   162  		case mangos.PipeEventAttached:
   163  			atomic.AddInt32(&add, 1)
   164  		case mangos.PipeEventDetached:
   165  			atomic.AddInt32(&dis, 1)
   166  		}
   167  	})
   168  	MustSucceed(t, peer2.Dial(a))
   169  	time.Sleep(time.Millisecond * 10)
   170  	MustBeTrue(t, atomic.LoadInt32(&con) > 0)
   171  	MustBeTrue(t, atomic.LoadInt32(&add) > 0)
   172  	MustBeTrue(t, atomic.LoadInt32(&dis) > 0)
   173  	MustSucceed(t, peer2.Close())
   174  	MustSucceed(t, peer1.Close())
   175  	MustSucceed(t, self.Close())
   176  }
   177  
   178  func TestXPair1CloseAbort(t *testing.T) {
   179  	self := GetSocket(t, NewSocket)
   180  	MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Minute))
   181  	MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 1))
   182  	pass := false
   183  	time.AfterFunc(time.Millisecond*10, func() {
   184  		MustSucceed(t, self.Close())
   185  	})
   186  	for i := 0; i < 20; i++ {
   187  		m := mangos.NewMessage(0)
   188  		m.Header = append(m.Header, 0, 0, 0, 1)
   189  		if e := self.SendMsg(m); e != nil {
   190  			MustBeError(t, e, mangos.ErrClosed)
   191  			pass = true
   192  			break
   193  		}
   194  	}
   195  	MustBeTrue(t, pass)
   196  }
   197  
   198  func TestXPair1ClosePipe(t *testing.T) {
   199  	s := GetSocket(t, NewSocket)
   200  	p := GetSocket(t, NewSocket)
   201  	MustSucceed(t, p.SetOption(mangos.OptionWriteQLen, 1))
   202  	MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 3))
   203  	MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Minute))
   204  	ConnectPair(t, s, p)
   205  	m := mangos.NewMessage(0)
   206  	m.Header = append(m.Header, 0, 0, 0, 1)
   207  	MustSucceed(t, p.SendMsg(m))
   208  	m, e := s.RecvMsg()
   209  	MustSucceed(t, e)
   210  	MustSucceed(t, p.SetOption(mangos.OptionSendDeadline, time.Millisecond))
   211  
   212  	// Fill the pipe
   213  	for i := 0; i < 20; i++ {
   214  		// These all will work, but the back-pressure will go all the
   215  		// way to the sender.
   216  		m := mangos.NewMessage(0)
   217  		m.Header = append(m.Header, 0, 0, 0, 1)
   218  		if e := p.SendMsg(m); e != nil {
   219  			MustBeError(t, e, mangos.ErrSendTimeout)
   220  			break
   221  		}
   222  	}
   223  
   224  	time.Sleep(time.Millisecond * 10)
   225  	MustSucceed(t, m.Pipe.Close())
   226  
   227  	time.Sleep(time.Millisecond * 10)
   228  	MustSucceed(t, s.Close())
   229  }
   230  
   231  func TestXPair1ResizeReceive(t *testing.T) {
   232  	self := GetSocket(t, NewSocket)
   233  	peer := GetSocket(t, NewSocket)
   234  	MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 1))
   235  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0))
   236  	MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond))
   237  	ConnectPair(t, self, peer)
   238  
   239  	m := mangos.NewMessage(0)
   240  	m.Header = append(m.Header, 0, 0, 0, 1)
   241  	m.Body = append(m.Body, 'o', 'n', 'e')
   242  	MustSendMsg(t, peer, m)
   243  	time.Sleep(time.Millisecond * 10)
   244  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 2))
   245  	MustNotRecv(t, self, mangos.ErrRecvTimeout)
   246  	MustSucceed(t, self.Close())
   247  	MustSucceed(t, peer.Close())
   248  }
   249  
   250  func TestXPair1ResizeReceive1(t *testing.T) {
   251  	self := GetSocket(t, NewSocket)
   252  	peer := GetSocket(t, NewSocket)
   253  	MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 1))
   254  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0))
   255  	MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Second))
   256  	ConnectPair(t, self, peer)
   257  
   258  	time.AfterFunc(time.Millisecond*20, func() {
   259  		MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 2))
   260  		m := mangos.NewMessage(0)
   261  		m.Header = append(m.Header, 0, 0, 0, 1)
   262  		m.Body = append(m.Body, []byte("one")...)
   263  		MustSendMsg(t, peer, m)
   264  	})
   265  	MustRecvString(t, self, "one")
   266  	MustSucceed(t, self.Close())
   267  	MustSucceed(t, peer.Close())
   268  }
   269  
   270  func TestXPair1ResizeReceive2(t *testing.T) {
   271  	self := GetSocket(t, NewSocket)
   272  	peer := GetSocket(t, NewSocket)
   273  	MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 0))
   274  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 20))
   275  	MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond))
   276  	ConnectPair(t, self, peer)
   277  
   278  	// Fill the pipe
   279  	for i := 0; i < 20; i++ {
   280  		m := mangos.NewMessage(0)
   281  		m.Header = append(m.Header, 0, 0, 0, 1)
   282  		MustSendMsg(t, peer, m)
   283  	}
   284  
   285  	time.Sleep(time.Millisecond * 10)
   286  	MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 1))
   287  	// Sleep so the resize filler finishes
   288  	time.Sleep(time.Millisecond * 20)
   289  
   290  	MustNotRecv(t, self, mangos.ErrRecvTimeout)
   291  	MustSucceed(t, self.Close())
   292  	MustSucceed(t, peer.Close())
   293  }
   294  
   295  func TestXPair1ResizeSend(t *testing.T) {
   296  	self := GetSocket(t, NewSocket)
   297  	_, _ = MockConnect(t, self)
   298  	MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 0))
   299  	MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Second))
   300  
   301  	var wg sync.WaitGroup
   302  	wg.Add(1)
   303  	time.AfterFunc(time.Millisecond*50, func() {
   304  		defer wg.Done()
   305  		MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 2))
   306  	})
   307  	m1 := mangos.NewMessage(0)
   308  	m1.Header = append(m1.Header, 0, 0, 0, 1)
   309  	m1.Body = append(m1.Body, '1')
   310  	MustSendMsg(t, self, m1)
   311  
   312  	m2 := mangos.NewMessage(0)
   313  	m2.Header = append(m1.Header, 0, 0, 0, 1)
   314  	m2.Body = append(m1.Body, '2')
   315  	MustSendMsg(t, self, m2)
   316  
   317  	wg.Wait()
   318  	MustSucceed(t, self.Close())
   319  }
   320  
   321  func TestXPair1TTL(t *testing.T) {
   322  	SetTTLZero(t, NewSocket)
   323  	SetTTLNegative(t, NewSocket)
   324  	SetTTLTooBig(t, NewSocket)
   325  	SetTTLNotInt(t, NewSocket)
   326  	SetTTL(t, NewSocket)
   327  }
   328  
   329  func TestXPair1EnforceTTL(t *testing.T) {
   330  	self := GetSocket(t, NewSocket)
   331  	mock, _ := MockConnect(t, self)
   332  
   333  	MustSucceed(t, self.SetOption(mangos.OptionTTL, 4))
   334  	MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50))
   335  
   336  	// First byte is non-zero
   337  	m := mangos.NewMessage(0)
   338  	m.Body = append(m.Body, 0, 0, 0, 1)
   339  	m.Body = append(m.Body, []byte("one")...)
   340  
   341  	MockMustSendMsg(t, mock, m, time.Second)
   342  	MustRecvString(t, self, "one")
   343  
   344  	m = mangos.NewMessage(0)
   345  	m.Body = append(m.Body, 0, 0, 0, 5)
   346  	m.Body = append(m.Body, []byte("drop")...)
   347  
   348  	MockMustSendMsg(t, mock, m, time.Second)
   349  	MustNotRecv(t, self, mangos.ErrRecvTimeout)
   350  
   351  	m = mangos.NewMessage(0)
   352  	m.Body = append(m.Body, 0, 0, 0, 2)
   353  	m.Body = append(m.Body, []byte("two")...)
   354  
   355  	MockMustSendMsg(t, mock, m, time.Second)
   356  	m = MustRecvMsg(t, self)
   357  
   358  	MustBeTrue(t, string(m.Body) == "two")
   359  	MustBeTrue(t, len(m.Header) == 4)
   360  	MustBeTrue(t, m.Header[0] == 0)
   361  	MustBeTrue(t, m.Header[0] == 0)
   362  	MustBeTrue(t, m.Header[0] == 0)
   363  	MustBeTrue(t, m.Header[3] == 3) // incremented on receive
   364  
   365  	MustClose(t, self)
   366  }
   367  
   368  func TestXPair1DropMissingTTL(t *testing.T) {
   369  	self := GetSocket(t, NewSocket)
   370  	mock, _ := MockConnect(t, self)
   371  
   372  	MustSucceed(t, self.SetOption(mangos.OptionTTL, 4))
   373  	MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50))
   374  
   375  	// First byte is non-zero
   376  	m := mangos.NewMessage(0)
   377  	m.Body = append(m.Body, 0, 0, 0)
   378  
   379  	MockMustSendMsg(t, mock, m, time.Second)
   380  	MustNotRecv(t, self, mangos.ErrRecvTimeout)
   381  
   382  	MustClose(t, self)
   383  }