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