nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/internal/test/dialer_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 test 16 17 import ( 18 "nanomsg.org/go/mangos/v2" 19 "nanomsg.org/go/mangos/v2/protocol/pair" 20 _ "nanomsg.org/go/mangos/v2/transport/inproc" 21 "reflect" 22 "sync" 23 "testing" 24 "time" 25 ) 26 27 func TestDialerBadScheme(t *testing.T) { 28 self := GetMockSocket() 29 defer MustClose(t, self) 30 31 d, e := self.NewDialer("bad://nothere", nil) 32 MustBeError(t, e, mangos.ErrBadTran) 33 MustBeTrue(t, d == nil) 34 35 // Malformed, needs :// bit 36 d, e = self.NewDialer("inproc:nothere", nil) 37 MustBeError(t, e, mangos.ErrBadTran) 38 MustBeTrue(t, d == nil) 39 } 40 41 func TestDialerAddress(t *testing.T) { 42 AddMockTransport() 43 self := GetMockSocket() 44 defer MustClose(t, self) 45 46 d, e := self.NewDialer(AddrMock(), nil) 47 MustSucceed(t, e) 48 MustBeTrue(t, d.Address() == AddrMock()) 49 } 50 51 func TestDialerSocketOptions(t *testing.T) { 52 AddMockTransport() 53 54 VerifyOptionDuration(t, NewMockSocket, mangos.OptionReconnectTime) 55 VerifyOptionDuration(t, NewMockSocket, mangos.OptionMaxReconnectTime) 56 VerifyOptionBool(t, NewMockSocket, mangos.OptionDialAsynch) 57 VerifyOptionInt(t, NewMockSocket, mangos.OptionMaxRecvSize) 58 } 59 60 func TestDialerOptions(t *testing.T) { 61 AddMockTransport() 62 sock := GetMockSocket() 63 defer MustClose(t, sock) 64 65 d, e := sock.NewDialer(AddrMock(), nil) 66 MustSucceed(t, e) 67 MustBeTrue(t, d != nil) 68 69 MustBeError(t, d.SetOption("bogus", nil), mangos.ErrBadOption) 70 _, e = d.GetOption("bogus") 71 MustBeError(t, e, mangos.ErrBadOption) 72 73 val, e := d.GetOption(mangos.OptionReconnectTime) 74 MustSucceed(t, e) 75 MustBeTrue(t, reflect.TypeOf(val) == reflect.TypeOf(time.Duration(0))) 76 77 val, e = d.GetOption(mangos.OptionMaxReconnectTime) 78 MustSucceed(t, e) 79 MustBeTrue(t, reflect.TypeOf(val) == reflect.TypeOf(time.Duration(0))) 80 81 val, e = d.GetOption(mangos.OptionDialAsynch) 82 MustSucceed(t, e) 83 MustBeTrue(t, reflect.TypeOf(val) == reflect.TypeOf(true)) 84 85 val, e = d.GetOption("mockError") 86 MustBeError(t, e, mangos.ErrProtoState) 87 MustBeTrue(t, val == nil) 88 89 MustBeError(t, d.SetOption(mangos.OptionDialAsynch, 1), mangos.ErrBadValue) 90 MustBeError(t, d.SetOption(mangos.OptionReconnectTime, 1), mangos.ErrBadValue) 91 MustBeError(t, d.SetOption(mangos.OptionReconnectTime, -time.Second), mangos.ErrBadValue) 92 MustBeError(t, d.SetOption(mangos.OptionMaxReconnectTime, 1), mangos.ErrBadValue) 93 MustBeError(t, d.SetOption(mangos.OptionMaxReconnectTime, -time.Second), mangos.ErrBadValue) 94 MustBeError(t, d.SetOption(mangos.OptionMaxRecvSize, -100), mangos.ErrBadValue) 95 MustBeError(t, d.SetOption(mangos.OptionMaxRecvSize, "a"), mangos.ErrBadValue) 96 MustBeError(t, d.SetOption("mockError", mangos.ErrCanceled), mangos.ErrCanceled) 97 98 MustSucceed(t, d.SetOption(mangos.OptionDialAsynch, false)) 99 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Duration(0))) 100 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Second)) 101 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, time.Duration(0))) 102 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, 5*time.Second)) 103 MustSucceed(t, d.SetOption(mangos.OptionMaxRecvSize, 1024)) 104 105 MustSucceed(t, d.SetOption(mangos.OptionMaxRecvSize, 1024)) 106 val, e = d.GetOption(mangos.OptionMaxRecvSize) 107 MustSucceed(t, e) 108 sz, ok := val.(int) 109 MustBeTrue(t, ok) 110 MustBeTrue(t, sz == 1024) 111 } 112 113 func TestDialerOptionsMap(t *testing.T) { 114 AddMockTransport() 115 sock := GetMockSocket() 116 defer MustClose(t, sock) 117 addr := AddrMock() 118 119 opts := make(map[string]interface{}) 120 opts[mangos.OptionMaxRecvSize] = "garbage" 121 d, e := sock.NewDialer(addr, opts) 122 MustBeError(t, e, mangos.ErrBadValue) 123 MustBeTrue(t, d == nil) 124 125 opts = make(map[string]interface{}) 126 opts[mangos.OptionMaxRecvSize] = -1 127 d, e = sock.NewDialer(addr, opts) 128 MustBeError(t, e, mangos.ErrBadValue) 129 MustBeTrue(t, d == nil) 130 131 opts = make(map[string]interface{}) 132 opts[mangos.OptionMaxRecvSize] = 1001 133 d, e = sock.NewDialer(addr, opts) 134 MustBeError(t, e, mangos.ErrBadValue) 135 MustBeTrue(t, d == nil) 136 137 opts = make(map[string]interface{}) 138 opts[mangos.OptionMaxRecvSize] = 1002 139 d, e = sock.NewDialer(addr, opts) 140 MustBeError(t, e, mangos.ErrBadOption) 141 MustBeTrue(t, d == nil) 142 143 opts = make(map[string]interface{}) 144 opts[mangos.OptionDialAsynch] = -1 145 d, e = sock.NewDialer(addr, opts) 146 MustBeError(t, e, mangos.ErrBadValue) 147 MustBeTrue(t, d == nil) 148 149 opts = make(map[string]interface{}) 150 opts["JUNKOPT"] = "yes" 151 d, e = sock.NewDialer(addr, opts) 152 MustBeError(t, e, mangos.ErrBadOption) 153 MustBeTrue(t, d == nil) 154 155 opts = make(map[string]interface{}) 156 opts["mockError"] = mangos.ErrCanceled 157 d, e = sock.NewDialer(addr, opts) 158 MustBeError(t, e, mangos.ErrCanceled) 159 MustBeTrue(t, d == nil) 160 161 // Now good options 162 opts = make(map[string]interface{}) 163 opts[mangos.OptionMaxRecvSize] = 3172 164 opts[mangos.OptionReconnectTime] = time.Second 165 opts[mangos.OptionMaxReconnectTime] = time.Second * 2 166 opts[mangos.OptionDialAsynch] = false 167 d, e = sock.NewDialer(addr, opts) 168 MustSucceed(t, e) 169 MustBeTrue(t, d != nil) 170 v, e := d.GetOption(mangos.OptionMaxRecvSize) 171 MustSucceed(t, e) 172 sz, ok := v.(int) 173 MustBeTrue(t, ok) 174 MustBeTrue(t, sz == 3172) 175 176 } 177 178 func TestDialerOptionsInherit(t *testing.T) { 179 AddMockTransport() 180 sock := GetMockSocket() 181 defer MustClose(t, sock) 182 addr := AddrMock() 183 184 // This should force listener not to alloc (bad option value) 185 MustSucceed(t, sock.SetOption(mangos.OptionMaxRecvSize, 1001)) 186 d, e := sock.NewDialer(addr, nil) 187 MustBeError(t, e, mangos.ErrBadValue) 188 MustBeTrue(t, d == nil) 189 MustSucceed(t, sock.SetOption(mangos.OptionMaxRecvSize, 1002)) 190 d, e = sock.NewDialer(addr, nil) 191 MustSucceed(t, e) 192 MustBeTrue(t, d != nil) 193 194 MustSucceed(t, sock.SetOption(mangos.OptionMaxRecvSize, 500)) 195 v, e := d.GetOption(mangos.OptionMaxRecvSize) 196 MustSucceed(t, e) 197 MustBeTrue(t, v.(int) == 500) 198 199 } 200 201 func TestDialerPipe(t *testing.T) { 202 sock1 := GetMockSocket() 203 defer MustClose(t, sock1) 204 sock2 := GetMockSocket() 205 defer MustClose(t, sock2) 206 addr := AddrTestInp() 207 208 MustSucceed(t, sock1.SetOption(mangos.OptionRecvDeadline, time.Second)) 209 MustSucceed(t, sock2.SetOption(mangos.OptionSendDeadline, time.Second)) 210 211 d, e := sock1.NewDialer(addr, nil) 212 MustSucceed(t, e) 213 MustSucceed(t, sock2.Listen(addr)) 214 MustSucceed(t, d.Dial()) 215 216 MustSendString(t, sock2, "junk") 217 m := MustRecvMsg(t, sock1) 218 219 MustBeTrue(t, m.Pipe.Dialer() == d) 220 MustBeTrue(t, m.Pipe.Listener() == nil) 221 MustBeTrue(t, m.Pipe.Address() == addr) 222 m.Free() 223 } 224 225 func TestDialerClosed(t *testing.T) { 226 AddMockTransport() 227 sock := GetMockSocket() 228 defer MustClose(t, sock) 229 230 d, e := sock.NewDialer(AddrMock(), nil) 231 MustSucceed(t, e) 232 MustBeTrue(t, d != nil) 233 234 MustSucceed(t, d.Close()) 235 236 MustBeError(t, d.Dial(), mangos.ErrClosed) 237 MustBeError(t, d.Close(), mangos.ErrClosed) 238 } 239 240 func TestDialerCloseAbort(t *testing.T) { 241 addr := AddrTestInp() 242 sock := GetMockSocket() 243 defer MustClose(t, sock) 244 245 d, e := sock.NewDialer(addr, nil) 246 MustSucceed(t, e) 247 MustBeTrue(t, d != nil) 248 MustSucceed(t, d.SetOption(mangos.OptionDialAsynch, true)) 249 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Millisecond)) 250 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, time.Millisecond)) 251 252 MustSucceed(t, d.Dial()) 253 time.Sleep(time.Millisecond * 50) 254 MustSucceed(t, d.Close()) 255 } 256 257 func TestDialerCloseAbort2(t *testing.T) { 258 sock := GetMockSocket() 259 defer MustClose(t, sock) 260 261 d, mc := GetMockDialer(t, sock) 262 MustSucceed(t, d.SetOption(mangos.OptionDialAsynch, true)) 263 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Millisecond)) 264 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, time.Millisecond)) 265 266 var wg sync.WaitGroup 267 wg.Add(1) 268 269 pass := false 270 go func() { 271 defer wg.Done() 272 time.Sleep(time.Millisecond * 20) 273 MustSucceed(t, mc.Close()) 274 pass = true 275 }() 276 277 // We're async, so this is guaranteed to succeed. 278 MustSucceed(t, d.Dial()) 279 time.Sleep(time.Millisecond * 50) 280 wg.Wait() 281 MustBeTrue(t, pass) 282 } 283 284 func TestDialerReuse(t *testing.T) { 285 AddMockTransport() 286 sock := GetMockSocket() 287 defer MustClose(t, sock) 288 289 d, e := sock.NewDialer(AddrMock(), nil) 290 MustSucceed(t, e) 291 MustBeTrue(t, d != nil) 292 MustSucceed(t, d.SetOption(mangos.OptionDialAsynch, true)) 293 294 MustSucceed(t, d.Dial()) 295 MustBeError(t, d.Dial(), mangos.ErrAddrInUse) 296 297 MustSucceed(t, d.Close()) 298 } 299 300 func TestDialerReconnect(t *testing.T) { 301 // We have to use real protocol and transport for this. 302 addr := AddrTestInp() 303 sock := GetSocket(t, pair.NewSocket) 304 defer MustClose(t, sock) 305 peer1 := GetSocket(t, pair.NewSocket) 306 peer2 := GetSocket(t, pair.NewSocket) 307 defer MustClose(t, peer2) 308 309 MustSucceed(t, sock.SetOption(mangos.OptionRecvDeadline, time.Second)) 310 MustSucceed(t, sock.SetOption(mangos.OptionSendDeadline, time.Second)) 311 MustSucceed(t, peer1.SetOption(mangos.OptionRecvDeadline, time.Second)) 312 MustSucceed(t, peer1.SetOption(mangos.OptionSendDeadline, time.Second)) 313 MustSucceed(t, peer2.SetOption(mangos.OptionRecvDeadline, time.Second)) 314 MustSucceed(t, peer2.SetOption(mangos.OptionSendDeadline, time.Second)) 315 316 d, e := sock.NewDialer(addr, nil) 317 MustSucceed(t, e) 318 MustBeTrue(t, d != nil) 319 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Millisecond)) 320 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, time.Millisecond)) 321 322 MustSucceed(t, peer1.Listen(addr)) 323 MustSucceed(t, d.Dial()) 324 time.Sleep(time.Millisecond * 20) 325 MustClose(t, peer1) 326 MustSucceed(t, peer2.Listen(addr)) 327 time.Sleep(time.Millisecond * 20) 328 MustSendString(t, sock, "test") 329 MustRecvString(t, peer2, "test") 330 331 MustSucceed(t, d.Close()) 332 } 333 334 func TestDialerConnectLate(t *testing.T) { 335 // We have to use real protocol and transport for this. 336 addr := AddrTestInp() 337 sock := GetSocket(t, pair.NewSocket) 338 defer MustClose(t, sock) 339 peer := GetSocket(t, pair.NewSocket) 340 defer MustClose(t, peer) 341 342 d, e := sock.NewDialer(addr, nil) 343 MustSucceed(t, e) 344 MustBeTrue(t, d != nil) 345 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Millisecond)) 346 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, time.Millisecond)) 347 MustSucceed(t, d.SetOption(mangos.OptionDialAsynch, true)) 348 349 lock := &sync.Mutex{} 350 cond := sync.NewCond(lock) 351 done := false 352 353 hook := func(ev mangos.PipeEvent, p mangos.Pipe) { 354 if ev == mangos.PipeEventAttached { 355 lock.Lock() 356 done = true 357 cond.Broadcast() 358 lock.Unlock() 359 } 360 } 361 _ = sock.SetPipeEventHook(hook) 362 363 var wg sync.WaitGroup 364 wg.Add(1) 365 366 go func() { 367 defer wg.Done() 368 time.Sleep(time.Millisecond * 50) 369 MustSucceed(t, peer.Listen(addr)) 370 }() 371 372 MustSucceed(t, d.Dial()) 373 374 wg.Wait() 375 lock.Lock() 376 cond.Wait() 377 lock.Unlock() 378 379 MustBeTrue(t, done) 380 } 381 382 func TestDialerConnectRefused(t *testing.T) { 383 // We have to use real protocol and transport for this. 384 addr := AddrTestInp() 385 sock := GetSocket(t, pair.NewSocket) 386 defer MustClose(t, sock) 387 peer := GetSocket(t, pair.NewSocket) 388 defer MustClose(t, peer) 389 390 d, e := sock.NewDialer(addr, nil) 391 MustSucceed(t, e) 392 MustBeTrue(t, d != nil) 393 MustSucceed(t, d.SetOption(mangos.OptionReconnectTime, time.Millisecond)) 394 MustSucceed(t, d.SetOption(mangos.OptionMaxReconnectTime, time.Millisecond)) 395 396 MustBeError(t, d.Dial(), mangos.ErrConnRefused) 397 398 }