go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/protocol/xsurveyor/xsurveyor_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 xsurveyor 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/respondent" 27 _ "go.nanomsg.org/mangos/v3/transport/inproc" 28 ) 29 30 func TestXSurveyorIdentity(t *testing.T) { 31 self := GetSocket(t, NewSocket) 32 id := self.Info() 33 MustBeTrue(t, id.Self == mangos.ProtoSurveyor) 34 MustBeTrue(t, id.SelfName == "surveyor") 35 MustBeTrue(t, id.Peer == mangos.ProtoRespondent) 36 MustBeTrue(t, id.PeerName == "respondent") 37 MustSucceed(t, self.Close()) 38 } 39 40 func TestXSurveyorRaw(t *testing.T) { 41 VerifyRaw(t, NewSocket) 42 } 43 44 func TestXSurveyorClosed(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 makeSurveyMsg(id uint32, s string) *mangos.Message { 54 m := mangos.NewMessage(0) 55 m.Header = append(m.Header, make([]byte, 4)...) 56 binary.BigEndian.PutUint32(m.Header, id|0x80000000) 57 m.Body = append(m.Body, []byte(s)...) 58 return m 59 } 60 61 func TestXSurveyorNoHeader(t *testing.T) { 62 self := GetSocket(t, NewSocket) 63 64 m := mangos.NewMessage(0) 65 66 MustSucceed(t, self.SendMsg(m)) 67 MustSucceed(t, self.Close()) 68 } 69 70 // We can send even with no pipes 71 func TestXSurveyorNonBlock1(t *testing.T) { 72 self := GetSocket(t, NewSocket) 73 for i := 0; i < 100; i++ { 74 m := makeSurveyMsg(uint32(i), "ping") 75 MustSucceed(t, self.SendMsg(m)) 76 } 77 time.Sleep(time.Millisecond * 10) 78 MustSucceed(t, self.Close()) 79 } 80 81 // We can send even if we have a pipe that is blocked 82 func TestXSurveyorNonBlock2(t *testing.T) { 83 self := GetSocket(t, NewSocket) 84 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, 1)) 85 _, _ = MockConnect(t, self) 86 87 for i := 0; i < 100; i++ { 88 m := makeSurveyMsg(uint32(i), "ping") 89 MustSucceed(t, self.SendMsg(m)) 90 } 91 time.Sleep(time.Millisecond * 50) 92 MustSucceed(t, self.Close()) 93 } 94 95 func TestXSurveyorRecvTimeout(t *testing.T) { 96 s, err := NewSocket() 97 MustSucceed(t, err) 98 99 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Millisecond)) 100 m, err := s.RecvMsg() 101 MustBeNil(t, m) 102 MustBeError(t, err, protocol.ErrRecvTimeout) 103 MustSucceed(t, s.Close()) 104 } 105 106 // XSurveyor needs a surveyor ID or it will discard. 107 func TestXSurveyorRecvJunk(t *testing.T) { 108 self := GetSocket(t, NewSocket) 109 mock, _ := MockConnect(t, self) 110 111 MockMustSendStr(t, mock, "", time.Second) 112 time.Sleep(time.Millisecond * 10) 113 MustSucceed(t, self.Close()) 114 } 115 116 func TestXSurveyorOptions(t *testing.T) { 117 VerifyInvalidOption(t, NewSocket) 118 VerifyOptionDuration(t, NewSocket, mangos.OptionRecvDeadline) 119 VerifyOptionQLen(t, NewSocket, mangos.OptionReadQLen) 120 VerifyOptionQLen(t, NewSocket, mangos.OptionWriteQLen) 121 } 122 123 func TestXSurveyorRecvQLenResizeDiscard(t *testing.T) { 124 self := GetSocket(t, NewSocket) 125 peer := GetSocket(t, respondent.NewSocket) 126 127 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Second)) 128 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 3)) 129 MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 100)) 130 ConnectPair(t, self, peer) 131 132 // Now do some exchanges, but don't collect the answers -- let our 133 // receive queue fill up. 134 for i := uint32(0); i < 100; i++ { 135 MustSucceed(t, self.SendMsg(makeSurveyMsg(i, ""))) 136 _ = MustRecvMsg(t, peer) 137 MustSendString(t, peer, "reply") 138 } 139 140 time.Sleep(time.Millisecond * 50) 141 // Shrink it 142 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 2)) 143 // This can fail or succeed -- depending on how much back-pressure we 144 // have applied; it usually succeeds. 145 time.Sleep(time.Millisecond * 50) 146 _, _ = self.RecvMsg() 147 time.Sleep(time.Millisecond * 10) 148 MustSucceed(t, peer.Close()) 149 MustSucceed(t, self.Close()) 150 } 151 152 func TestXSurveyorRecvClosePipeDiscard(t *testing.T) { 153 self := GetSocket(t, NewSocket) 154 peer := GetSocket(t, respondent.NewSocket) 155 156 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Second)) 157 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 3)) 158 MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 100)) 159 ConnectPair(t, self, peer) 160 161 // One exchange to get the pipe ID to close 162 MustSucceed(t, self.SendMsg(makeSurveyMsg(0, ""))) 163 _ = MustRecvMsg(t, peer) 164 MustSendString(t, peer, "junk") 165 r, e := self.RecvMsg() 166 MustSucceed(t, e) 167 pipe := r.Pipe 168 169 // Now do some exchanges, but don't collect the answers -- let our 170 // receive queue fill up. 171 for i := uint32(0); i < 100; i++ { 172 MustSucceed(t, self.SendMsg(makeSurveyMsg(i, ""))) 173 _ = MustRecvMsg(t, peer) 174 MustSendString(t, peer, "reply") 175 } 176 177 MustSucceed(t, pipe.Close()) 178 time.Sleep(time.Millisecond * 20) 179 MustSucceed(t, self.Close()) 180 MustSucceed(t, peer.Close()) 181 182 } 183 184 // This ensures that the upper RecvMsg sees the new queue after a resize 185 func TestXSurveyorResizeRecv(t *testing.T) { 186 self := GetSocket(t, NewSocket) 187 peer := GetSocket(t, respondent.NewSocket) 188 MustSucceed(t, peer.SetOption(mangos.OptionWriteQLen, 20)) 189 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 20)) 190 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Minute)) 191 ConnectPair(t, self, peer) 192 193 m := makeSurveyMsg(1, "hello") 194 MustSucceed(t, self.SendMsg(m)) 195 MustRecvString(t, peer, "hello") 196 197 time.AfterFunc(time.Millisecond*20, func() { 198 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 10)) 199 time.Sleep(time.Millisecond) 200 MustSendString(t, peer, "world") 201 }) 202 203 r, e := self.RecvMsg() 204 MustSucceed(t, e) 205 MustBeTrue(t, binary.BigEndian.Uint32(r.Header) == 0x80000001) 206 MustBeTrue(t, string(r.Body) == "world") 207 208 MustSucceed(t, self.Close()) 209 } 210 211 func TestXSurveyorBroadcast(t *testing.T) { 212 s, err := NewSocket() 213 MustSucceed(t, err) 214 MustNotBeNil(t, s) 215 216 s1, err := respondent.NewSocket() 217 MustSucceed(t, err) 218 MustNotBeNil(t, s1) 219 220 s2, err := respondent.NewSocket() 221 MustSucceed(t, err) 222 MustNotBeNil(t, s2) 223 224 a := AddrTestInp() 225 MustSucceed(t, s.Listen(a)) 226 MustSucceed(t, s1.Dial(a)) 227 MustSucceed(t, s2.Dial(a)) 228 229 time.Sleep(time.Millisecond * 50) 230 231 MustSucceed(t, s1.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50)) 232 MustSucceed(t, s2.SetOption(mangos.OptionRecvDeadline, time.Millisecond*50)) 233 234 MustSucceed(t, s.SendMsg(makeSurveyMsg(1, "one"))) 235 MustSucceed(t, s.SendMsg(makeSurveyMsg(2, "two"))) 236 MustSucceed(t, s.SendMsg(makeSurveyMsg(3, "three"))) 237 238 var wg sync.WaitGroup 239 wg.Add(2) 240 pass1 := false 241 pass2 := false 242 243 f := func(s mangos.Socket, pass *bool) { 244 defer wg.Done() 245 v, e := s.Recv() 246 MustSucceed(t, e) 247 MustBeTrue(t, string(v) == "one") 248 249 v, e = s.Recv() 250 MustSucceed(t, e) 251 MustBeTrue(t, string(v) == "two") 252 253 v, e = s.Recv() 254 MustSucceed(t, e) 255 MustBeTrue(t, string(v) == "three") 256 257 v, e = s.Recv() 258 MustBeError(t, e, mangos.ErrRecvTimeout) 259 MustBeNil(t, v) 260 *pass = true 261 } 262 263 go f(s1, &pass1) 264 go f(s2, &pass2) 265 266 wg.Wait() 267 268 MustBeTrue(t, pass1) 269 MustBeTrue(t, pass2) 270 271 MustSucceed(t, s.Close()) 272 MustSucceed(t, s1.Close()) 273 MustSucceed(t, s2.Close()) 274 }