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 }