nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/protocol/xsub/xsub_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 xsub 16 17 import ( 18 "nanomsg.org/go/mangos/v2" 19 "nanomsg.org/go/mangos/v2/protocol/pub" 20 "sync" 21 "testing" 22 "time" 23 24 . "nanomsg.org/go/mangos/v2/internal/test" 25 _ "nanomsg.org/go/mangos/v2/transport/inproc" 26 ) 27 28 func TestXSubIdentity(t *testing.T) { 29 s := GetSocket(t, NewSocket) 30 id := s.Info() 31 MustBeTrue(t, id.Self == mangos.ProtoSub) 32 MustBeTrue(t, id.SelfName == "sub") 33 MustBeTrue(t, id.Peer == mangos.ProtoPub) 34 MustBeTrue(t, id.PeerName == "pub") 35 MustSucceed(t, s.Close()) 36 } 37 38 func TestXSubRaw(t *testing.T) { 39 VerifyRaw(t, NewSocket) 40 } 41 42 func TestXSubClosed(t *testing.T) { 43 VerifyClosedRecv(t, NewSocket) 44 VerifyClosedClose(t, NewSocket) 45 VerifyClosedDial(t, NewSocket) 46 VerifyClosedListen(t, NewSocket) 47 VerifyClosedAddPipe(t, NewSocket) 48 } 49 50 func TestXSubCannotSend(t *testing.T) { 51 CannotSend(t, NewSocket) 52 } 53 54 func TestXSubCannotSubscribe(t *testing.T) { 55 // Raw sockets cannot subscribe or unsubscribe. 56 s, e := NewSocket() 57 MustSucceed(t, e) 58 e = s.SetOption(mangos.OptionSubscribe, []byte("topic")) 59 MustFail(t, e) 60 MustBeTrue(t, e == mangos.ErrBadOption) 61 _ = s.Close() 62 } 63 64 func TestXSubCannotUnsubscribe(t *testing.T) { 65 // Raw sockets cannot subscribe or unsubscribe. 66 s, e := NewSocket() 67 MustSucceed(t, e) 68 e = s.SetOption(mangos.OptionUnsubscribe, []byte("topic")) 69 MustFail(t, e) 70 MustBeTrue(t, e == mangos.ErrBadOption) 71 _ = s.Close() 72 } 73 74 func TestXSubRecvDeadline(t *testing.T) { 75 s, e := NewSocket() 76 MustSucceed(t, e) 77 e = s.SetOption(mangos.OptionRecvDeadline, time.Millisecond) 78 MustSucceed(t, e) 79 m, e := s.RecvMsg() 80 MustFail(t, e) 81 MustBeTrue(t, e == mangos.ErrRecvTimeout) 82 MustBeNil(t, m) 83 _ = s.Close() 84 } 85 86 func TestXSubRecvClean(t *testing.T) { 87 s, e := NewSocket() 88 MustSucceed(t, e) 89 p, e := pub.NewSocket() 90 MustSucceed(t, e) 91 addr := AddrTestInp() 92 MustSucceed(t, s.Listen(addr)) 93 MustSucceed(t, p.Dial(addr)) 94 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Second)) 95 m := mangos.NewMessage(0) 96 m.Body = append(m.Body, []byte("Hello world")...) 97 e = p.SendMsg(m) 98 MustSucceed(t, e) 99 m, e = s.RecvMsg() 100 MustSucceed(t, e) 101 MustNotBeNil(t, m) 102 MustBeTrue(t, string(m.Body) == "Hello world") 103 _ = p.Close() 104 _ = s.Close() 105 } 106 107 func TestXSubRecvQLen(t *testing.T) { 108 s, e := NewSocket() 109 MustSucceed(t, e) 110 p, e := pub.NewSocket() 111 MustSucceed(t, e) 112 addr := AddrTestInp() 113 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Millisecond*10)) 114 MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 2)) 115 MustSucceed(t, s.Listen(addr)) 116 MustSucceed(t, p.Dial(addr)) 117 time.Sleep(time.Millisecond * 50) 118 119 MustSucceed(t, p.Send([]byte("one"))) 120 MustSucceed(t, p.Send([]byte("two"))) 121 MustSucceed(t, p.Send([]byte("three"))) 122 time.Sleep(time.Millisecond * 50) 123 124 MustSucceed(t, e) 125 m, e := s.RecvMsg() 126 MustSucceed(t, e) 127 MustNotBeNil(t, m) 128 m, e = s.RecvMsg() 129 MustSucceed(t, e) 130 MustNotBeNil(t, m) 131 MustNotRecv(t, s, mangos.ErrRecvTimeout) 132 MustClose(t, p) 133 MustClose(t, s) 134 } 135 136 func TestXSubRecvQLenResize(t *testing.T) { 137 s := GetSocket(t, NewSocket) 138 p := GetSocket(t, pub.NewSocket) 139 140 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Millisecond*20)) 141 MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 4)) 142 MustSucceed(t, p.SetOption(mangos.OptionWriteQLen, 10)) 143 ConnectPair(t, s, p) 144 time.Sleep(time.Millisecond * 50) 145 MustSendString(t, p, "one") 146 MustSendString(t, p, "two") 147 MustSendString(t, p, "three") 148 time.Sleep(time.Millisecond * 100) 149 MustRecvString(t, s, "one") 150 // Shrink it 151 MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 20)) 152 MustNotRecv(t, s, mangos.ErrRecvTimeout) 153 154 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, time.Second)) 155 156 // Now make sure it still works 157 MustSendString(t, p, "four") 158 MustRecvString(t, s, "four") 159 160 // Now try a posted recv and asynchronous resize. 161 var wg sync.WaitGroup 162 wg.Add(1) 163 pass := false 164 go func() { 165 defer wg.Done() 166 time.Sleep(time.Millisecond * 20) 167 MustSucceed(t, s.SetOption(mangos.OptionReadQLen, 5)) 168 MustSendString(t, p, "five") 169 pass = true 170 }() 171 172 MustRecvString(t, s, "five") 173 wg.Wait() 174 MustSucceed(t, p.Close()) 175 MustSucceed(t, s.Close()) 176 MustBeTrue(t, pass) 177 } 178 179 func TestXSubOptions(t *testing.T) { 180 VerifyInvalidOption(t, NewSocket) 181 VerifyOptionDuration(t, NewSocket, mangos.OptionRecvDeadline) 182 VerifyOptionInt(t, NewSocket, mangos.OptionReadQLen) 183 } 184 185 func TestXSubPoundPipes(t *testing.T) { 186 self := GetSocket(t, NewSocket) 187 var peers []mangos.Socket 188 nPeers := 20 189 repeat := 100 190 var wg sync.WaitGroup 191 wg.Add(nPeers) 192 193 startQ := make(chan struct{}) 194 for i := 0; i < nPeers; i++ { 195 peer := GetSocket(t, pub.NewSocket) 196 peers = append(peers, peer) 197 ConnectPair(t, self, peer) 198 199 go func(s mangos.Socket) { 200 defer wg.Done() 201 <-startQ 202 for j := 0; j < repeat; j++ { 203 MustSendString(t, s, "yes") 204 } 205 time.Sleep(time.Millisecond * 10) 206 }(peer) 207 } 208 close(startQ) 209 wg.Wait() 210 for _, peer := range peers { 211 MustSucceed(t, peer.Close()) 212 } 213 MustSucceed(t, self.Close()) 214 } 215 216 func TestXSubPoundClose(t *testing.T) { 217 self := GetSocket(t, NewSocket) 218 var peers []mangos.Socket 219 nPeers := 20 220 var wg sync.WaitGroup 221 wg.Add(nPeers) 222 223 startQ := make(chan struct{}) 224 for i := 0; i < nPeers; i++ { 225 peer := GetSocket(t, pub.NewSocket) 226 peers = append(peers, peer) 227 ConnectPair(t, self, peer) 228 229 go func(s mangos.Socket) { 230 defer wg.Done() 231 <-startQ 232 for { 233 e := s.Send([]byte("yes")) 234 if e != nil { 235 MustBeError(t, e, mangos.ErrClosed) 236 break 237 } 238 } 239 time.Sleep(time.Millisecond * 10) 240 }(peer) 241 } 242 close(startQ) 243 time.Sleep(time.Millisecond * 10) 244 MustSucceed(t, self.Close()) 245 time.Sleep(time.Millisecond * 100) 246 for _, peer := range peers { 247 MustSucceed(t, peer.Close()) 248 } 249 wg.Wait() 250 251 } 252 253 func TestXSubPoundRecv(t *testing.T) { 254 self := GetSocket(t, NewSocket) 255 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0)) 256 var peers []mangos.Socket 257 nPeers := 20 258 nReaders := 20 259 var wg1 sync.WaitGroup 260 var wg2 sync.WaitGroup 261 wg1.Add(nPeers) 262 wg2.Add(nReaders) 263 264 for i := 0; i < nReaders; i++ { 265 go func() { 266 defer wg2.Done() 267 for { 268 _, e := self.RecvMsg() 269 if e != nil { 270 break 271 } 272 } 273 }() 274 } 275 276 for i := 0; i < nPeers; i++ { 277 peer := GetSocket(t, pub.NewSocket) 278 peers = append(peers, peer) 279 ConnectPair(t, self, peer) 280 281 go func(s mangos.Socket) { 282 defer wg1.Done() 283 for { 284 e := s.Send([]byte("yes")) 285 if e != nil { 286 break 287 } 288 } 289 time.Sleep(time.Millisecond * 10) 290 }(peer) 291 292 // ramp up slowly 293 time.Sleep(time.Millisecond) 294 } 295 time.Sleep(time.Millisecond * 10) 296 297 for _, peer := range peers { 298 MustSucceed(t, peer.Close()) 299 } 300 MustSucceed(t, self.Close()) 301 wg1.Wait() 302 wg2.Wait() 303 } 304 305 func TestXSubRecvNoQ(t *testing.T) { 306 self := GetSocket(t, NewSocket) 307 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, 0)) 308 var peers []mangos.Socket 309 nPeers := 20 310 var wg1 sync.WaitGroup 311 wg1.Add(nPeers) 312 313 for i := 0; i < nPeers; i++ { 314 peer := GetSocket(t, pub.NewSocket) 315 peers = append(peers, peer) 316 ConnectPair(t, self, peer) 317 318 go func(s mangos.Socket) { 319 defer wg1.Done() 320 for { 321 e := s.Send([]byte("yes")) 322 if e != nil { 323 break 324 } 325 } 326 time.Sleep(time.Millisecond * 10) 327 }(peer) 328 329 // ramp up slowly 330 time.Sleep(time.Millisecond) 331 } 332 time.Sleep(time.Millisecond * 10) 333 334 for _, peer := range peers { 335 MustSucceed(t, peer.Close()) 336 } 337 MustSucceed(t, self.Close()) 338 wg1.Wait() 339 }