go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/protocol/xpair/xpair_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 xpair 16 17 import ( 18 "sync/atomic" 19 "testing" 20 "time" 21 22 "go.nanomsg.org/mangos/v3" 23 . "go.nanomsg.org/mangos/v3/internal/test" 24 _ "go.nanomsg.org/mangos/v3/transport/inproc" 25 ) 26 27 func TestXBusIdentity(t *testing.T) { 28 s, err := NewSocket() 29 MustSucceed(t, err) 30 id := s.Info() 31 MustBeTrue(t, id.Self == mangos.ProtoPair) 32 MustBeTrue(t, id.SelfName == "pair") 33 MustBeTrue(t, id.Peer == mangos.ProtoPair) 34 MustBeTrue(t, id.PeerName == "pair") 35 MustSucceed(t, s.Close()) 36 } 37 38 func TestXPairRaw(t *testing.T) { 39 VerifyRaw(t, NewSocket) 40 } 41 42 func TestXPairClosed(t *testing.T) { 43 VerifyClosedRecv(t, NewSocket) 44 VerifyClosedSend(t, NewSocket) 45 VerifyClosedClose(t, NewSocket) 46 VerifyClosedDial(t, NewSocket) 47 VerifyClosedListen(t, NewSocket) 48 VerifyClosedAddPipe(t, NewSocket) 49 } 50 51 func TestXPairOptions(t *testing.T) { 52 VerifyInvalidOption(t, NewSocket) 53 VerifyOptionDuration(t, NewSocket, mangos.OptionRecvDeadline) 54 VerifyOptionDuration(t, NewSocket, mangos.OptionSendDeadline) 55 VerifyOptionInt(t, NewSocket, mangos.OptionReadQLen) 56 VerifyOptionInt(t, NewSocket, mangos.OptionWriteQLen) 57 VerifyOptionBool(t, NewSocket, mangos.OptionBestEffort) 58 } 59 60 func TestXPairRecvDeadline(t *testing.T) { 61 self := GetSocket(t, NewSocket) 62 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10)) 63 MustNotRecv(t, self, mangos.ErrRecvTimeout) 64 MustSucceed(t, self.Close()) 65 } 66 67 func TestXPairSendDeadline(t *testing.T) { 68 self := GetSocket(t, NewSocket) 69 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 0)) 70 MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Millisecond*10)) 71 MustBeError(t, self.Send([]byte{}), mangos.ErrSendTimeout) 72 MustSucceed(t, self.Close()) 73 } 74 75 func TestXPairSendBestEffort(t *testing.T) { 76 self := GetSocket(t, NewSocket) 77 MustSucceed(t, self.SetOption(mangos.OptionBestEffort, true)) 78 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 0)) 79 MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Millisecond*10)) 80 for i := 0; i < 100; i++ { 81 MustSendString(t, self, "yep") 82 } 83 MustSucceed(t, self.Close()) 84 } 85 86 func TestXPairRejectSecondPipe(t *testing.T) { 87 self := GetSocket(t, NewSocket) 88 peer1 := GetSocket(t, NewSocket) 89 peer2 := GetSocket(t, NewSocket) 90 91 ConnectPair(t, self, peer1) 92 a := AddrTestInp() 93 MustSucceed(t, self.Listen(a)) 94 95 con := int32(0) 96 add := int32(0) 97 dis := int32(0) 98 peer2.SetPipeEventHook(func(ev mangos.PipeEvent, p mangos.Pipe) { 99 switch ev { 100 case mangos.PipeEventAttaching: 101 atomic.AddInt32(&con, 1) 102 case mangos.PipeEventAttached: 103 atomic.AddInt32(&add, 1) 104 case mangos.PipeEventDetached: 105 atomic.AddInt32(&dis, 1) 106 } 107 }) 108 MustSucceed(t, peer2.Dial(a)) 109 time.Sleep(time.Millisecond * 10) 110 MustBeTrue(t, atomic.LoadInt32(&con) > 0) 111 MustBeTrue(t, atomic.LoadInt32(&add) > 0) 112 MustBeTrue(t, atomic.LoadInt32(&dis) > 0) 113 MustSucceed(t, peer2.Close()) 114 MustSucceed(t, peer1.Close()) 115 MustSucceed(t, self.Close()) 116 } 117 118 func TestXPairCloseAbort(t *testing.T) { 119 self := GetSocket(t, NewSocket) 120 MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Minute)) 121 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 1)) 122 pass := false 123 time.AfterFunc(time.Millisecond*10, func() { 124 MustSucceed(t, self.Close()) 125 }) 126 for i := 0; i < 20; i++ { 127 if e := self.Send([]byte{}); e != nil { 128 MustBeError(t, e, mangos.ErrClosed) 129 pass = true 130 break 131 } 132 } 133 MustBeTrue(t, pass) 134 } 135 136 func TestXPairClosePipe(t *testing.T) { 137 s := GetSocket(t, NewSocket) 138 p := GetSocket(t, NewSocket) 139 MustSucceed(t, p.SetOption(mangos.OptionWriteQLen, 1)) 140 MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 3)) 141 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Minute)) 142 ConnectPair(t, s, p) 143 MustSucceed(t, p.Send([]byte{})) 144 m, e := s.RecvMsg() 145 MustSucceed(t, e) 146 MustSucceed(t, p.SetOption(mangos.OptionSendDeadline, time.Millisecond)) 147 148 // Fill the pipe 149 for i := 0; i < 20; i++ { 150 // These all will work, but the back-pressure will go all the 151 // way to the sender. 152 if e := p.Send([]byte{byte(i)}); e != nil { 153 MustBeError(t, e, mangos.ErrSendTimeout) 154 break 155 } 156 } 157 158 time.Sleep(time.Millisecond * 10) 159 MustSucceed(t, m.Pipe.Close()) 160 161 time.Sleep(time.Millisecond * 10) 162 MustSucceed(t, s.Close()) 163 } 164 165 func TestXPairResizeRecv(t *testing.T) { 166 self := GetSocket(t, NewSocket) 167 peer := GetSocket(t, NewSocket) 168 MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 1)) 169 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0)) 170 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond)) 171 ConnectPair(t, self, peer) 172 173 MustSendString(t, peer, "one") 174 time.Sleep(time.Millisecond * 10) 175 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 2)) 176 MustNotRecv(t, self, mangos.ErrRecvTimeout) 177 MustSucceed(t, self.Close()) 178 MustSucceed(t, peer.Close()) 179 } 180 181 func TestXPairResizeRecv1(t *testing.T) { 182 self := GetSocket(t, NewSocket) 183 peer := GetSocket(t, NewSocket) 184 MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 1)) 185 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0)) 186 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Second)) 187 ConnectPair(t, self, peer) 188 189 time.AfterFunc(time.Millisecond*20, func() { 190 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 2)) 191 MustSendString(t, peer, "one") 192 }) 193 MustRecvString(t, self, "one") 194 MustSucceed(t, self.Close()) 195 MustSucceed(t, peer.Close()) 196 } 197 198 func TestXPairResizeRecv2(t *testing.T) { 199 self := GetSocket(t, NewSocket) 200 peer := GetSocket(t, NewSocket) 201 MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 0)) 202 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 20)) 203 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond)) 204 ConnectPair(t, self, peer) 205 206 // Fill the pipe 207 for i := 0; i < 20; i++ { 208 MustSucceed(t, peer.Send([]byte{byte(i)})) 209 } 210 211 time.Sleep(time.Millisecond * 10) 212 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 1)) 213 // Sleep so the resize filler finishes 214 time.Sleep(time.Millisecond * 20) 215 216 MustNotRecv(t, self, mangos.ErrRecvTimeout) 217 MustSucceed(t, self.Close()) 218 MustSucceed(t, peer.Close()) 219 } 220 221 func TestXPairResizeSend(t *testing.T) { 222 self := GetSocket(t, NewSocket) 223 _, _ = MockConnect(t, self) 224 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 0)) 225 MustSucceed(t, self.SetOption(mangos.OptionSendDeadline, time.Second)) 226 227 cq := make(chan struct{}) 228 time.AfterFunc(time.Millisecond*50, func() { 229 defer func() { close(cq) }() 230 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 2)) 231 }) 232 MustSendString(t, self, "one") 233 MustSendString(t, self, "two") 234 <-cq 235 MustSucceed(t, self.Close()) 236 }