func TestNilConnection(t *testing.T) { var nc *nats.Conn data := []byte("ok") // Publish if err := nc.Publish("foo", data); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if err := nc.PublishMsg(nil); err == nil || err != nats.ErrInvalidMsg { t.Fatalf("Expected ErrInvalidMsg error, got %v\n", err) } if err := nc.PublishMsg(&nats.Msg{}); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if err := nc.PublishRequest("foo", "reply", data); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } // Subscribe if _, err := nc.Subscribe("foo", nil); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if _, err := nc.SubscribeSync("foo"); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if _, err := nc.QueueSubscribe("foo", "bar", nil); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } ch := make(chan *nats.Msg) if _, err := nc.ChanSubscribe("foo", ch); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if _, err := nc.ChanQueueSubscribe("foo", "bar", ch); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if _, err := nc.QueueSubscribeSyncWithChan("foo", "bar", ch); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } // Flush if err := nc.Flush(); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } if err := nc.FlushTimeout(time.Millisecond); err == nil || err != nats.ErrInvalidConnection { t.Fatalf("Expected ErrInvalidConnection error, got %v\n", err) } // Nil Subscribers var sub *nats.Subscription if sub.Type() != nats.NilSubscription { t.Fatalf("Got wrong type for nil subscription, %v\n", sub.Type()) } if sub.IsValid() { t.Fatalf("Expected IsValid() to return false") } if err := sub.Unsubscribe(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected Unsubscribe to return proper error, got %v\n", err) } if err := sub.AutoUnsubscribe(1); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, err := sub.NextMsg(time.Millisecond); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, err := sub.QueuedMsgs(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, _, err := sub.Pending(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, _, err := sub.MaxPending(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if err := sub.ClearMaxPending(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, _, err := sub.PendingLimits(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if err := sub.SetPendingLimits(1, 1); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, err := sub.Delivered(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } if _, err := sub.Dropped(); err == nil || err != nats.ErrBadSubscription { t.Fatalf("Expected ErrBadSubscription error, got %v\n", err) } }
func TestCallbacksOrder(t *testing.T) { authS, authSOpts := RunServerWithConfig("./configs/tls.conf") defer authS.Shutdown() s := RunDefaultServer() defer s.Shutdown() firstDisconnect := true dtime1 := time.Time{} dtime2 := time.Time{} rtime := time.Time{} atime1 := time.Time{} atime2 := time.Time{} ctime := time.Time{} cbErrors := make(chan error, 20) reconnected := make(chan bool) closed := make(chan bool) asyncErr := make(chan bool, 2) recvCh := make(chan bool, 2) recvCh1 := make(chan bool) recvCh2 := make(chan bool) dch := func(nc *nats.Conn) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err return } time.Sleep(100 * time.Millisecond) if firstDisconnect { firstDisconnect = false dtime1 = time.Now() } else { dtime2 = time.Now() } } rch := func(nc *nats.Conn) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err reconnected <- true return } time.Sleep(50 * time.Millisecond) rtime = time.Now() reconnected <- true } ech := func(nc *nats.Conn, sub *nats.Subscription, err error) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err asyncErr <- true return } if sub.Subject == "foo" { time.Sleep(20 * time.Millisecond) atime1 = time.Now() } else { atime2 = time.Now() } asyncErr <- true } cch := func(nc *nats.Conn) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err closed <- true return } ctime = time.Now() closed <- true } url := net.JoinHostPort(authSOpts.Host, strconv.Itoa(authSOpts.Port)) url = "nats://" + url + "," + nats.DefaultURL nc, err := nats.Connect(url, nats.DisconnectHandler(dch), nats.ReconnectHandler(rch), nats.ClosedHandler(cch), nats.ErrorHandler(ech), nats.ReconnectWait(50*time.Millisecond), nats.DontRandomize()) if err != nil { t.Fatalf("Unable to connect: %v\n", err) } defer nc.Close() ncp, err := nats.Connect(nats.DefaultURL, nats.ReconnectWait(50*time.Millisecond)) if err != nil { t.Fatalf("Unable to connect: %v\n", err) } defer ncp.Close() // Wait to make sure that if we have closed (incorrectly) the // asyncCBDispatcher during the connect process, this is caught here. time.Sleep(time.Second) s.Shutdown() s = RunDefaultServer() defer s.Shutdown() if err := Wait(reconnected); err != nil { t.Fatal("Did not get the reconnected callback") } var sub1 *nats.Subscription var sub2 *nats.Subscription recv := func(m *nats.Msg) { // Signal that one message is received recvCh <- true // We will now block if m.Subject == "foo" { <-recvCh1 } else { <-recvCh2 } m.Sub.Unsubscribe() } sub1, err = nc.Subscribe("foo", recv) if err != nil { t.Fatalf("Unable to create subscription: %v\n", err) } sub1.SetPendingLimits(1, 100000) sub2, err = nc.Subscribe("bar", recv) if err != nil { t.Fatalf("Unable to create subscription: %v\n", err) } sub2.SetPendingLimits(1, 100000) nc.Flush() ncp.Publish("foo", []byte("test")) ncp.Publish("bar", []byte("test")) ncp.Flush() // Wait notification that message were received err = Wait(recvCh) if err == nil { err = Wait(recvCh) } if err != nil { t.Fatal("Did not receive message") } for i := 0; i < 2; i++ { ncp.Publish("foo", []byte("test")) ncp.Publish("bar", []byte("test")) } ncp.Flush() if err := Wait(asyncErr); err != nil { t.Fatal("Did not get the async callback") } if err := Wait(asyncErr); err != nil { t.Fatal("Did not get the async callback") } close(recvCh1) close(recvCh2) nc.Close() if err := Wait(closed); err != nil { t.Fatal("Did not get the close callback") } if len(cbErrors) > 0 { t.Fatalf("%v", <-cbErrors) } if (dtime1 == time.Time{}) || (dtime2 == time.Time{}) || (rtime == time.Time{}) || (atime1 == time.Time{}) || (atime2 == time.Time{}) || (ctime == time.Time{}) { t.Fatalf("Some callbacks did not fire:\n%v\n%v\n%v\n%v\n%v\n%v", dtime1, rtime, atime1, atime2, dtime2, ctime) } if rtime.Before(dtime1) || dtime2.Before(rtime) || atime2.Before(atime1) || ctime.Before(atime2) { t.Fatalf("Wrong callback order:\n%v\n%v\n%v\n%v\n%v\n%v", dtime1, rtime, atime1, atime2, dtime2, ctime) } }
func TestSetPendingLimits(t *testing.T) { s := RunDefaultServer() defer s.Shutdown() nc := NewDefaultConnection(t) defer nc.Close() payload := []byte("hello") payloadLen := len(payload) toSend := 100 var sub *nats.Subscription // Check for invalid values invalid := func() error { if err := sub.SetPendingLimits(0, 1); err == nil { return fmt.Errorf("Setting limit with 0 should fail") } if err := sub.SetPendingLimits(1, 0); err == nil { return fmt.Errorf("Setting limit with 0 should fail") } return nil } // function to send messages send := func(subject string, count int) { for i := 0; i < count; i++ { if err := nc.Publish(subject, payload); err != nil { t.Fatalf("Unexpected error on publish: %v", err) } } nc.Flush() } // Check pending vs expected values var limitCount, limitBytes int var expectedCount, expectedBytes int checkPending := func() error { lc, lb, err := sub.PendingLimits() if err != nil { return err } if lc != limitCount || lb != limitBytes { return fmt.Errorf("Unexpected limits, expected %v msgs %v bytes, got %v msgs %v bytes", limitCount, limitBytes, lc, lb) } msgs, bytes, err := sub.Pending() if err != nil { return fmt.Errorf("Unexpected error getting pending counts: %v", err) } if (msgs != expectedCount && msgs != expectedCount-1) || (bytes != expectedBytes && bytes != expectedBytes-payloadLen) { return fmt.Errorf("Unexpected counts, expected %v msgs %v bytes, got %v msgs %v bytes", expectedCount, expectedBytes, msgs, bytes) } return nil } recv := make(chan bool) block := make(chan bool) cb := func(m *nats.Msg) { recv <- true <-block m.Sub.Unsubscribe() } subj := "foo" sub, err := nc.Subscribe(subj, cb) if err != nil { t.Fatalf("Unexpected error on subscribe: %v", err) } defer sub.Unsubscribe() if err := invalid(); err != nil { t.Fatalf("%v", err) } // Check we apply limit only for size limitCount = -1 limitBytes = (toSend / 2) * payloadLen if err := sub.SetPendingLimits(limitCount, limitBytes); err != nil { t.Fatalf("Unexpected error setting limits: %v", err) } // Send messages send(subj, toSend) // Wait for message to be received if err := Wait(recv); err != nil { t.Fatal("Did not get our message") } expectedBytes = limitBytes expectedCount = limitBytes / payloadLen if err := checkPending(); err != nil { t.Fatalf("%v", err) } // Release callback block <- true subj = "bar" sub, err = nc.Subscribe(subj, cb) if err != nil { t.Fatalf("Unexpected error on subscribe: %v", err) } defer sub.Unsubscribe() // Check we apply limit only for count limitCount = toSend / 4 limitBytes = -1 if err := sub.SetPendingLimits(limitCount, limitBytes); err != nil { t.Fatalf("Unexpected error setting limits: %v", err) } // Send messages send(subj, toSend) // Wait for message to be received if err := Wait(recv); err != nil { t.Fatal("Did not get our message") } expectedCount = limitCount expectedBytes = limitCount * payloadLen if err := checkPending(); err != nil { t.Fatalf("%v", err) } // Release callback block <- true subj = "baz" sub, err = nc.SubscribeSync(subj) if err != nil { t.Fatalf("Unexpected error on subscribe: %v", err) } defer sub.Unsubscribe() if err := invalid(); err != nil { t.Fatalf("%v", err) } // Check we apply limit only for size limitCount = -1 limitBytes = (toSend / 2) * payloadLen if err := sub.SetPendingLimits(limitCount, limitBytes); err != nil { t.Fatalf("Unexpected error setting limits: %v", err) } // Send messages send(subj, toSend) expectedBytes = limitBytes expectedCount = limitBytes / payloadLen if err := checkPending(); err != nil { t.Fatalf("%v", err) } sub.Unsubscribe() nc.Flush() subj = "boz" sub, err = nc.SubscribeSync(subj) if err != nil { t.Fatalf("Unexpected error on subscribe: %v", err) } defer sub.Unsubscribe() // Check we apply limit only for count limitCount = toSend / 4 limitBytes = -1 if err := sub.SetPendingLimits(limitCount, limitBytes); err != nil { t.Fatalf("Unexpected error setting limits: %v", err) } // Send messages send(subj, toSend) expectedCount = limitCount expectedBytes = limitCount * payloadLen if err := checkPending(); err != nil { t.Fatalf("%v", err) } sub.Unsubscribe() nc.Flush() }