go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/protocol/xrespondent/xrespondent_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 xrespondent 16 17 import ( 18 "encoding/binary" 19 "sync" 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/protocol" 26 "go.nanomsg.org/mangos/v3/protocol/surveyor" 27 "go.nanomsg.org/mangos/v3/protocol/xsurveyor" 28 _ "go.nanomsg.org/mangos/v3/transport/inproc" 29 ) 30 31 func TestXRespondentIdentity(t *testing.T) { 32 id := MustGetInfo(t, NewSocket) 33 MustBeTrue(t, id.Peer == protocol.ProtoSurveyor) 34 MustBeTrue(t, id.PeerName == "surveyor") 35 MustBeTrue(t, id.Self == protocol.ProtoRespondent) 36 MustBeTrue(t, id.SelfName == "respondent") 37 } 38 39 func TestXRespondentRaw(t *testing.T) { 40 VerifyRaw(t, NewSocket) 41 } 42 43 func TestXRespondentClosed(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 TestXRespondentNoHeader(t *testing.T) { 53 s := GetSocket(t, NewSocket) 54 defer MustClose(t, s) 55 m := mangos.NewMessage(0) 56 57 MustSucceed(t, s.SendMsg(m)) 58 } 59 60 func TestXRespondentMismatchHeader(t *testing.T) { 61 s, err := NewSocket() 62 MustSucceed(t, err) 63 64 m := mangos.NewMessage(0) 65 m.Header = append(m.Header, []byte{1, 1, 1, 1}...) 66 67 MustSucceed(t, s.SendMsg(m)) 68 MustSucceed(t, s.Close()) 69 } 70 71 func TestXRespondentRecvTimeout(t *testing.T) { 72 s, err := NewSocket() 73 MustSucceed(t, err) 74 75 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Millisecond)) 76 m, err := s.RecvMsg() 77 MustBeNil(t, m) 78 MustFail(t, err) 79 MustBeTrue(t, err == protocol.ErrRecvTimeout) 80 MustSucceed(t, s.Close()) 81 } 82 83 func TestXRespondentTTLZero(t *testing.T) { 84 SetTTLZero(t, NewSocket) 85 } 86 87 func TestXRespondentTTLNegative(t *testing.T) { 88 SetTTLNegative(t, NewSocket) 89 } 90 91 func TestXRespondentTTLTooBig(t *testing.T) { 92 SetTTLTooBig(t, NewSocket) 93 } 94 95 func TestXRespondentTTLNotInt(t *testing.T) { 96 SetTTLNotInt(t, NewSocket) 97 } 98 99 func TestXRespondentTTLSet(t *testing.T) { 100 SetTTL(t, NewSocket) 101 } 102 103 func TestXRespondentTTLDrop(t *testing.T) { 104 TTLDropTest(t, surveyor.NewSocket, NewSocket, xsurveyor.NewSocket, NewSocket) 105 } 106 107 func TestXRespondentOptions(t *testing.T) { 108 VerifyInvalidOption(t, NewSocket) 109 VerifyOptionDuration(t, NewSocket, mangos.OptionRecvDeadline) 110 VerifyOptionDuration(t, NewSocket, mangos.OptionSendDeadline) 111 VerifyOptionQLen(t, NewSocket, mangos.OptionReadQLen) 112 VerifyOptionQLen(t, NewSocket, mangos.OptionWriteQLen) 113 VerifyOptionInt(t, NewSocket, mangos.OptionTTL) 114 VerifyOptionBool(t, NewSocket, mangos.OptionBestEffort) 115 } 116 117 func TestXRespondentSendTimeout(t *testing.T) { 118 timeout := time.Millisecond * 10 119 120 s, err := NewSocket() 121 MustSucceed(t, err) 122 MustNotBeNil(t, s) 123 124 r, err := xsurveyor.NewSocket() 125 MustSucceed(t, err) 126 MustNotBeNil(t, r) 127 128 MustSucceed(t, s.SetOption(mangos.OptionWriteQLen, 1)) 129 MustSucceed(t, r.SetOption(mangos.OptionReadQLen, 0)) 130 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, timeout)) 131 MustSucceed(t, s.SetOption(mangos.OptionSendDeadline, timeout)) 132 MustSucceed(t, r.SetOption(mangos.OptionRecvDeadline, timeout)) 133 134 // We need to setup a connection so that we can get a meaningful 135 // pipe ID. We get this by receiving a message. 136 a := AddrTestInp() 137 MustSucceed(t, s.Listen(a)) 138 MustSucceed(t, r.Dial(a)) 139 140 time.Sleep(time.Millisecond * 20) 141 MustSucceed(t, r.Send([]byte{0x80, 0, 0, 1})) // Request ID #1 142 m, e := s.RecvMsg() 143 MustSucceed(t, e) 144 MustBeTrue(t, len(m.Header) >= 8) // request ID and pipe ID 145 146 // Because of vagaries in the queuing, we slam messages until we 147 // hit a timeout. We expect to do so after only a modest number 148 // of messages, as we have no reader on the other side. 149 for i := 0; i < 100; i++ { 150 e = s.SendMsg(m.Dup()) 151 if e != nil { 152 break 153 } 154 } 155 MustBeError(t, s.SendMsg(m.Dup()), mangos.ErrSendTimeout) 156 MustSucceed(t, s.Close()) 157 MustSucceed(t, r.Close()) 158 } 159 160 func TestXRespondentBestEffort(t *testing.T) { 161 timeout := time.Millisecond * 10 162 163 s, err := NewSocket() 164 MustSucceed(t, err) 165 MustNotBeNil(t, s) 166 167 r, err := xsurveyor.NewSocket() 168 MustSucceed(t, err) 169 MustNotBeNil(t, r) 170 171 MustSucceed(t, s.SetOption(mangos.OptionWriteQLen, 1)) 172 MustSucceed(t, r.SetOption(mangos.OptionReadQLen, 0)) 173 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, timeout)) 174 MustSucceed(t, s.SetOption(mangos.OptionSendDeadline, timeout)) 175 MustSucceed(t, r.SetOption(mangos.OptionRecvDeadline, timeout)) 176 177 // We need to setup a connection so that we can get a meaningful 178 // pipe ID. We get this by receiving a message. 179 a := AddrTestInp() 180 MustSucceed(t, s.Listen(a)) 181 MustSucceed(t, r.Dial(a)) 182 183 time.Sleep(time.Millisecond * 20) 184 MustSucceed(t, r.Send([]byte{0x80, 0, 0, 1})) // Request ID #1 185 m, e := s.RecvMsg() 186 MustSucceed(t, e) 187 MustBeTrue(t, len(m.Header) >= 8) // request ID and pipe ID 188 MustSucceed(t, s.SetOption(mangos.OptionBestEffort, true)) 189 190 // Because of vagaries in the queuing, we slam messages until we 191 // hit a timeout. We expect to do so after only a modest number 192 // of messages, as we have no reader on the other side. 193 for i := 0; i < 100; i++ { 194 e = s.SendMsg(m.Dup()) 195 if e != nil { 196 break 197 } 198 } 199 MustSucceed(t, e) 200 MustSucceed(t, s.Close()) 201 MustSucceed(t, r.Close()) 202 } 203 204 func TestXRespondentRecvNoHeader(t *testing.T) { 205 self := GetSocket(t, NewSocket) 206 mock, _ := MockConnect(t, self) 207 208 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 2)) 209 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50)) 210 MockMustSend(t, mock, []byte{}, time.Millisecond*5) 211 MustNotRecv(t, self, mangos.ErrRecvTimeout) 212 MustSucceed(t, self.Close()) 213 } 214 215 func TestXRespondentRecvJunk(t *testing.T) { 216 self := GetSocket(t, NewSocket) 217 MustSucceed(t, self.SetOption(protocol.OptionReadQLen, 20)) 218 MustSucceed(t, self.SetOption(protocol.OptionRecvDeadline, time.Millisecond*10)) 219 220 mp, _ := MockConnect(t, self) 221 MockMustSend(t, mp, []byte{}, time.Second) 222 MockMustSend(t, mp, []byte{0, 1}, time.Second) 223 MockMustSend(t, mp, []byte{0, 1, 2, 3}, time.Second) 224 MockMustSend(t, mp, []byte{0, 1, 2, 3, 0x80}, time.Second) 225 226 MustNotRecv(t, self, protocol.ErrRecvTimeout) 227 MustClose(t, self) 228 } 229 230 func newRequest(id uint32, content string) *mangos.Message { 231 m := mangos.NewMessage(len(content) + 8) 232 b := make([]byte, 4) 233 binary.BigEndian.PutUint32(b[:4], id|0x80000000) 234 // Requests (coming in) will be entirely on the body. 235 m.Body = append(m.Body, b...) 236 m.Body = append(m.Body, []byte(content)...) 237 return m 238 } 239 240 func newReply(id uint32, p mangos.Pipe, content string) *mangos.Message { 241 m := mangos.NewMessage(len(content)) 242 b := make([]byte, 8) 243 binary.BigEndian.PutUint32(b, p.ID()) // outgoing pipe ID 244 binary.BigEndian.PutUint32(b[4:], id|0x80000000) // request ID 245 m.Header = append(m.Header, b...) 246 m.Body = append(m.Body, []byte(content)...) 247 return m 248 } 249 250 func TestXRespondentPipeCloseSendAbort(t *testing.T) { 251 self := GetSocket(t, NewSocket) 252 defer MustClose(t, self) 253 254 MustSucceed(t, self.SetOption(protocol.OptionWriteQLen, 0)) 255 MustSucceed(t, self.SetOption(protocol.OptionSendDeadline, time.Second)) 256 257 _, p := MockConnect(t, self) 258 var wg sync.WaitGroup 259 wg.Add(1) 260 pass := false 261 finishQ := make(chan struct{}) 262 go func() { 263 defer wg.Done() 264 i := uint32(0) 265 for { 266 i++ 267 m := newReply(i, p, "") 268 MustSendMsg(t, self, m) 269 select { 270 case <-finishQ: 271 pass = true 272 return 273 default: 274 } 275 } 276 }() 277 time.Sleep(time.Millisecond * 50) 278 _ = p.Close() 279 time.Sleep(time.Millisecond * 50) 280 close(finishQ) 281 wg.Wait() 282 MustBeTrue(t, pass) 283 284 } 285 286 func TestXRespondentPipeCloseRecvAbort(t *testing.T) { 287 self := GetSocket(t, NewSocket) 288 defer MustClose(t, self) 289 290 MustSucceed(t, self.SetOption(protocol.OptionReadQLen, 1)) 291 MustSucceed(t, self.SetOption(protocol.OptionSendDeadline, time.Second)) 292 293 mock, p := MockConnect(t, self) 294 var wg sync.WaitGroup 295 wg.Add(1) 296 pass := false 297 go func() { 298 defer wg.Done() 299 i := uint32(0) 300 for { 301 i++ 302 m := newRequest(i, "") 303 e := mock.MockSendMsg(m, time.Second) 304 if e != nil { 305 MustBeError(t, e, protocol.ErrClosed) 306 pass = true 307 return 308 } 309 MustSucceed(t, e) 310 } 311 }() 312 time.Sleep(time.Millisecond * 50) 313 _ = p.Close() 314 time.Sleep(time.Millisecond * 50) 315 _ = mock.Close() 316 317 wg.Wait() 318 MustBeTrue(t, pass) 319 320 } 321 322 func TestXRespondentRecv1(t *testing.T) { 323 self := GetSocket(t, NewSocket) 324 mp, _ := MockConnect(t, self) 325 MustSucceed(t, self.SetOption(protocol.OptionReadQLen, 0)) 326 MustSucceed(t, self.SetOption(protocol.OptionRecvDeadline, time.Millisecond)) 327 MockMustSendMsg(t, mp, newRequest(1, "hello"), time.Second) 328 329 time.Sleep(time.Millisecond * 50) 330 MustSucceed(t, self.SetOption(protocol.OptionReadQLen, 2)) 331 MustNotRecv(t, self, protocol.ErrRecvTimeout) 332 MustClose(t, self) 333 } 334 335 func TestXRespondentResizeRecv2(t *testing.T) { 336 self := GetSocket(t, NewSocket) 337 mp, _ := MockConnect(t, self) 338 MustSucceed(t, self.SetOption(protocol.OptionReadQLen, 1)) 339 MustSucceed(t, self.SetOption(protocol.OptionRecvDeadline, time.Second)) 340 341 time.AfterFunc(time.Millisecond*50, func() { 342 MustSucceed(t, self.SetOption(protocol.OptionReadQLen, 2)) 343 time.Sleep(time.Millisecond * 50) 344 MockMustSendMsg(t, mp, newRequest(1, "hello"), time.Second) 345 }) 346 MustRecvString(t, self, "hello") 347 MustClose(t, self) 348 }