public void TestReconnectAllowedFlags() { Options opts = utils.DefaultTestOptions; opts.Url = "nats://localhost:22222"; opts.MaxReconnect = 2; opts.ReconnectWait = 1000; Object testLock = new Object(); opts.ClosedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; using (NATSServer ns = utils.CreateServerOnPort(22222)) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { lock (testLock) { ns.Shutdown(); Assert.False(Monitor.Wait(testLock, 1000)); } Assert.True(c.State == ConnState.RECONNECTING); c.Opts.ClosedEventHandler = null; } } }
public void TestReconnectDisallowedFlags() { Options opts = utils.DefaultTestOptions; opts.Url = "nats://localhost:22222"; opts.AllowReconnect = false; Object testLock = new Object(); opts.ClosedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; using (NATSServer ns = utils.CreateServerOnPort(22222)) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { lock (testLock) { ns.Shutdown(); Assert.True(Monitor.Wait(testLock, 1000)); } } } }
public void TestBasicReconnectFunctionality() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; Object testLock = new Object(); Object msgLock = new Object(); opts.DisconnectedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; opts.ReconnectedEventHandler = (sender, args) => { // NOOP }; NATSServer ns = NATSServer.Create(Context.Server1.Port); using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { IAsyncSubscription s = c.SubscribeAsync("foo"); s.MessageHandler += (sender, args) => { lock (msgLock) { Monitor.Pulse(msgLock); } }; s.Start(); c.Flush(); lock (testLock) { ns.Shutdown(); Assert.True(Monitor.Wait(testLock, 100000)); } c.Publish("foo", Encoding.UTF8.GetBytes("Hello")); // restart the server. using (ns = NATSServer.Create(Context.Server1.Port)) { lock (msgLock) { c.Flush(50000); Assert.True(Monitor.Wait(msgLock, 10000)); } Assert.True(c.Stats.Reconnects == 1); } } }
public void TestReconnectAllowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; AutoResetEvent Closed = new AutoResetEvent(false); AutoResetEvent Disconnected = new AutoResetEvent(false); opts.DisconnectedEventHandler = (sender, args) => Disconnected.Set(); opts.ClosedEventHandler = (sender, args) => Closed.Set(); using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { ns.Shutdown(); Assert.True(Disconnected.WaitOne(1000)); Assert.False(Closed.WaitOne(1000)); Assert.True(c.State == ConnState.RECONNECTING); c.Opts.ClosedEventHandler = null; } } }
public void TestClose() { Options opts = utils.DefaultTestOptions; opts.Url = "nats://localhost:22222"; opts.AllowReconnect = true; opts.MaxReconnect = 60; using (NATSServer s1 = utils.CreateServerOnPort(22222)) { IConnection c = new ConnectionFactory().CreateConnection(opts); Assert.False(c.IsClosed()); s1.Shutdown(); Thread.Sleep(100); Assert.False(c.IsClosed(), string.Format("Invalid state, expecting not closed, received: {0}", c.State)); using (NATSServer s2 = utils.CreateServerOnPort(22222)) { Thread.Sleep(1000); Assert.False(c.IsClosed()); c.Close(); Assert.True(c.IsClosed()); } } }
public void TestTlsReconnectAuthTimeout() { AutoResetEvent ev = new AutoResetEvent(false); using (NATSServer s1 = NATSServer.CreateWithConfig(Context.Server1.Port, "auth_tls.conf"), s2 = NATSServer.CreateWithConfig(Context.Server2.Port, "auth_tls_timeout.conf"), s3 = NATSServer.CreateWithConfig(Context.Server3.Port, "auth_tls.conf")) { Options opts = Context.GetTestOptions(); opts.Secure = true; opts.NoRandomize = true; opts.TLSRemoteCertificationValidationCallback = verifyServerCert; opts.Servers = new[] { $"nats://*****:*****@localhost:{Context.Server1.Port}", $"nats://*****:*****@localhost:{Context.Server2.Port}", $"nats://*****:*****@localhost:{Context.Server3.Port}" }; opts.ReconnectedEventHandler += (sender, args) => { ev.Set(); }; using (Context.ConnectionFactory.CreateConnection(opts)) { s1.Shutdown(); // This should fail over to S2 where an authorization timeout occurs // then successfully reconnect to S3. Assert.True(ev.WaitOne(20000)); } } }
public void TestClose() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.AllowReconnect = true; opts.MaxReconnect = 60; using (NATSServer s1 = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { Assert.False(c.IsClosed()); s1.Shutdown(); Thread.Sleep(100); Assert.False(c.IsClosed(), string.Format("Invalid state, expecting not closed, received: {0}", c.State)); using (NATSServer s2 = NATSServer.Create(Context.Server1.Port)) { Thread.Sleep(1000); Assert.False(c.IsClosed()); c.Close(); Assert.True(c.IsClosed()); } } } }
public void TestReconnectDisallowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.AllowReconnect = false; Object testLock = new Object(); opts.ClosedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { lock (testLock) { ns.Shutdown(); Assert.True(Monitor.Wait(testLock, 1000)); } } } }
public void TestRespondFailsWithServerClosed() { Msg m; using (NATSServer ns = NATSServer.CreateFastAndVerify(Context.Server1.Port)) { Options options = Context.GetTestOptions(Context.Server1.Port); options.AllowReconnect = false; using (var c = Context.ConnectionFactory.CreateConnection(options)) { using (var s = c.SubscribeSync("foo")) { string replyTo = c.NewInbox(); c.Publish("foo", replyTo, Encoding.UTF8.GetBytes("message")); m = s.NextMessage(1000); Assert.NotNull(m); Assert.Equal(replyTo, m.Reply); ns.Shutdown(); // Give the server time to close Thread.Sleep(2000); byte[] reply = Encoding.UTF8.GetBytes("reply"); Assert.ThrowsAny <NATSConnectionClosedException>(() => m.Respond(reply)); } } } }
public void TestReconnectAuthTimeout() { AutoResetEvent ev = new AutoResetEvent(false); using (NATSServer s1 = util.CreateServerWithConfig("auth_1222.conf"), s2 = util.CreateServerWithConfig("auth_1223_timeout.conf"), s3 = util.CreateServerWithConfig("auth_1224.conf")) { Options opts = util.DefaultTestOptions; opts.Servers = new string[] { "nats://*****:*****@localhost:1222", "nats://*****:*****@localhost:1223", "nats://*****:*****@localhost:1224" }; opts.NoRandomize = true; opts.ReconnectedEventHandler += (sender, args) => { ev.Set(); }; IConnection c = new ConnectionFactory().CreateConnection(opts); s1.Shutdown(); // This should fail over to S2 where an authorization timeout occurs // then successfully reconnect to S3. Assert.True(ev.WaitOne(20000)); } }
public void TestReconnectAllowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; Object testLock = new Object(); opts.ClosedEventHandler = (sender, args) => { lock (testLock) { Monitor.Pulse(testLock); } }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { lock (testLock) { ns.Shutdown(); Assert.False(Monitor.Wait(testLock, 1000)); } Assert.True(c.State == ConnState.RECONNECTING); c.Opts.ClosedEventHandler = null; } } }
public void TestHotSpotReconnect() { int numClients = 10; SimClient[] clients = new SimClient[100]; Options opts = Context.GetTestOptions(); opts.Servers = Context.GetTestServersUrls(); NATSServer s1 = NATSServer.Create(Context.Server1.Port); Task[] waitgroup = new Task[numClients]; for (int i = 0; i < numClients; i++) { clients[i] = new SimClient(); waitgroup[i] = Task.Run(() => { clients[i].Connect(Context.GetTestServersUrls()); clients[i].waitForReconnect(); }); } NATSServer s3 = NATSServer.Create(Context.Server3.Port); NATSServer s5 = NATSServer.Create(Context.Server5.Port); s1.Shutdown(); Task.WaitAll(waitgroup); int s3Count = 0; int s5Count = 0; int unknown = 0; for (int i = 0; i < numClients; i++) { if (Context.Server3.Url.Equals(clients[i].ConnectedUrl)) { s3Count++; } else if (Context.Server5.Url.Equals(clients[i].ConnectedUrl)) { s5Count++; } else { unknown++; } } Assert.True(unknown == 0); int delta = Math.Abs(s3Count - s5Count); int range = numClients / 30; Assert.False(delta > range, string.Format("Connected clients to servers out of range: {0}/{0}", delta, range)); }
// TODO: Create smaller variant [Fact] private void TestHotSpotReconnect() { int numClients = 10; SimClient[] clients = new SimClient[100]; Options opts = utils.DefaultTestOptions; opts.Servers = testServers; NATSServer s1 = utils.CreateServerOnPort(1222); Task[] waitgroup = new Task[numClients]; for (int i = 0; i < numClients; i++) { clients[i] = new SimClient(); waitgroup[i] = Task.Run(() => { clients[i].Connect(testServers); clients[i].waitForReconnect(); }); } NATSServer s2 = utils.CreateServerOnPort(1224); NATSServer s3 = utils.CreateServerOnPort(1226); s1.Shutdown(); Task.WaitAll(waitgroup); int s2Count = 0; int s3Count = 0; int unknown = 0; for (int i = 0; i < numClients; i++) { if (testServers[3].Equals(clients[i].ConnectedUrl)) { s2Count++; } else if (testServers[5].Equals(clients[i].ConnectedUrl)) { s3Count++; } else { unknown++; } } Assert.True(unknown == 0); int delta = Math.Abs(s2Count - s3Count); int range = numClients / 30; Assert.False(delta > range, string.Format("Connected clients to servers out of range: {0}/{0}", delta, range)); }
public void TestQueueSubsOnReconnect() { AutoResetEvent reconnectEvent = new AutoResetEvent(false); Options opts = getReconnectOptions(); opts.MaxReconnect = 32; string subj = "foo.bar"; string qgroup = "workers"; opts.ReconnectedEventHandler += (sender, args) => { reconnectEvent.Set(); }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { EventHandler <MsgHandlerEventArgs> eh = (sender, args) => { int seq = Convert.ToInt32(Encoding.UTF8.GetString(args.Message.Data)); lock (results) { if (results.ContainsKey(seq) == false) { results.Add(seq, true); } } }; // Create Queue Subscribers c.SubscribeAsync(subj, qgroup, eh); c.SubscribeAsync(subj, qgroup, eh); c.Flush(); sendAndCheckMsgs(c, subj, 10); ns.Shutdown(); // give the OS time to shut it down. Thread.Sleep(1000); // start back up using (NATSServer.Create(Context.Server1.Port)) { // wait for reconnect Assert.True(reconnectEvent.WaitOne(6000)); sendAndCheckMsgs(c, subj, 10); } } } }
public void TestProperReconnectDelay() { Object mu = new Object(); Options opts = Context.GetTestOptions(); opts.Servers = Context.GetTestServersUrls(); opts.NoRandomize = true; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { opts.DisconnectedEventHandler = null; disconnectHandlerCalled = true; lock (mu) { disconnectHandlerCalled = true; Monitor.Pulse(mu); } }; bool closedCbCalled = false; opts.ClosedEventHandler = (sender, args) => { closedCbCalled = true; }; using (NATSServer s1 = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { lock (mu) { s1.Shutdown(); // wait for disconnect Assert.True(Monitor.Wait(mu, 10000)); // Wait, want to make sure we don't spin on //reconnect to non-existant servers. Thread.Sleep(1000); Assert.False(closedCbCalled); Assert.True(disconnectHandlerCalled); Assert.True(c.State == ConnState.RECONNECTING); } } } }
private void TestPingReconnect() { /// Work in progress int RECONNECTS = 4; Options opts = utils.DefaultTestOptions; Object mu = new Object(); opts.Servers = testServersShortList; opts.NoRandomize = true; opts.ReconnectWait = 200; opts.PingInterval = 50; opts.MaxPingsOut = -1; opts.Timeout = 1000; Stopwatch disconnectedTimer = new Stopwatch(); opts.DisconnectedEventHandler = (sender, args) => { disconnectedTimer.Reset(); disconnectedTimer.Start(); }; opts.ReconnectedEventHandler = (sender, args) => { lock (mu) { args.Conn.Opts.MaxPingsOut = 500; disconnectedTimer.Stop(); Monitor.Pulse(mu); } }; using (NATSServer s1 = utils.CreateServerOnPort(1222)) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { s1.Shutdown(); for (int i = 0; i < RECONNECTS; i++) { lock (mu) { Assert.True(Monitor.Wait(mu, 100000)); } } } } }
public void TestTlsReconnectAuthTimeoutLateClose() { AutoResetEvent ev = new AutoResetEvent(false); using (NATSServer s1 = NATSServer.CreateWithConfig(Context.Server1.Port, "auth_tls.conf"), s2 = NATSServer.CreateWithConfig(Context.Server2.Port, "auth_tls.conf")) { Options opts = Context.GetTestOptions(); opts.Secure = true; opts.NoRandomize = true; opts.TLSRemoteCertificationValidationCallback = verifyServerCert; opts.Servers = new string[] { $"nats://*****:*****@localhost:{Context.Server1.Port}", $"nats://*****:*****@localhost:{Context.Server2.Port}" }; opts.ReconnectedEventHandler += (sender, args) => { ev.Set(); }; using (var c = Context.ConnectionFactory.CreateConnection(opts)) { // inject an authorization timeout, as if it were processed by an incoming server message. // this is done at the parser level so that parsing is also tested, // therefore it needs reflection since Parser is an internal type. Type parserType = typeof(Connection).Assembly.GetType("NATS.Client.Parser"); Assert.NotNull(parserType); BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; object parser = Activator.CreateInstance(parserType, flags, null, new object[] { c }, null); Assert.NotNull(parser); MethodInfo parseMethod = parserType.GetMethod("parse", flags); Assert.NotNull(parseMethod); byte[] bytes = "-ERR 'Authorization Timeout'\r\n".ToCharArray().Select(ch => (byte)ch).ToArray(); parseMethod.Invoke(parser, new object[] { bytes, bytes.Length }); // sleep to allow the client to process the error, then shutdown the server. Thread.Sleep(250); s1.Shutdown(); // Wait for a reconnect. Assert.True(ev.WaitOne(20000)); } } }
public void TestTlsReconnect() { AutoResetEvent ev = new AutoResetEvent(false); using (NATSServer srv = NATSServer.CreateWithConfig(Context.Server1.Port, "tls.conf"), srv2 = NATSServer.CreateWithConfig(Context.Server2.Port, "tls.conf")) { Thread.Sleep(1000); Options opts = Context.GetTestOptions(); opts.Secure = true; opts.NoRandomize = true; opts.TLSRemoteCertificationValidationCallback = verifyServerCert; opts.Servers = new[] { Context.Server1.Url, Context.Server2.Url }; opts.ReconnectedEventHandler += (sender, obj) => { ev.Set(); }; using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { // send a message to be sure. using (ISyncSubscription s = c.SubscribeSync("foo")) { c.Publish("foo", null); c.Flush(); s.NextMessage(); // shutdown the server srv.Shutdown(); // wait for reconnect Assert.True(ev.WaitOne(30000)); c.Publish("foo", null); c.Flush(); s.NextMessage(); } } } }
public void TestReconnectVerbose() { // an exception stops and fails the test. Object reconnectLock = new Object(); bool reconnected = false; Options opts = Context.GetTestOptions(Context.Server1.Port); opts.Verbose = true; opts.ReconnectedEventHandler += (sender, args) => { lock (reconnectLock) { reconnected = true; Monitor.Pulse(reconnectLock); } }; using (NATSServer s = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { c.Flush(); s.Shutdown(); using (NATSServer.Create(Context.Server1.Port)) { lock (reconnectLock) { if (!reconnected) { Monitor.Wait(reconnectLock, 5000); } } c.Flush(); } } } }
public void TestTlsReconnect() { AutoResetEvent ev = new AutoResetEvent(false); using (NATSServer srv = util.CreateServerWithConfig("tls_1222.conf"), srv2 = util.CreateServerWithConfig("tls_1224.conf")) { Thread.Sleep(1000); Options opts = util.DefaultTestOptions; opts.Secure = true; opts.NoRandomize = true; opts.TLSRemoteCertificationValidationCallback = verifyServerCert; opts.Servers = new string[] { "nats://localhost:1222", "nats://localhost:1224" }; opts.ReconnectedEventHandler += (sender, obj) => { ev.Set(); }; using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { // send a message to be sure. using (ISyncSubscription s = c.SubscribeSync("foo")) { c.Publish("foo", null); c.Flush(); s.NextMessage(); // shutdown the server srv.Shutdown(); // wait for reconnect Assert.True(ev.WaitOne(30000)); c.Publish("foo", null); c.Flush(); s.NextMessage(); } } } }
public void TestReconnectAllowedFlags() { Options opts = Context.GetTestOptions(Context.Server1.Port); opts.MaxReconnect = 2; opts.ReconnectWait = 1000; AutoResetEvent Closed = new AutoResetEvent(false); AutoResetEvent Disconnected = new AutoResetEvent(false); var sw = new Stopwatch(); opts.DisconnectedEventHandler = (sender, args) => { _testOutputHelper.WriteLine($"Disconnected event handler invoked after: {sw.ElapsedMilliseconds}ms"); Disconnected.Set(); }; opts.ClosedEventHandler = (sender, args) => { _testOutputHelper.WriteLine($"Closed event handler invoked after: {sw.ElapsedMilliseconds}ms"); Closed.Set(); }; opts.ReconnectedEventHandler = (_, __) => { _testOutputHelper.WriteLine($"Reconnect event handler invoked after: {sw.ElapsedMilliseconds}ms"); }; using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { sw.Start(); ns.Shutdown(); Assert.True(Disconnected.WaitOne(1000), "Disconnected event did not receive a signal"); Assert.False(Closed.WaitOne(1000), "Closed event did receive a signal"); Assert.True(c.State == ConnState.RECONNECTING, $"Expected {ConnState.RECONNECTING} but got {c.State} after {sw.ElapsedMilliseconds} ms"); c.Opts.ClosedEventHandler = null; } } }
public void TestRespondFailsWithServerClosed() { IConnection c = null; ISyncSubscription s = null; try { Msg m; using (NATSServer ns = new NATSServer()) { Options options = utils.DefaultTestOptions; options.AllowReconnect = false; c = new ConnectionFactory().CreateConnection(options); s = c.SubscribeSync("foo"); string replyTo = c.NewInbox(); c.Publish("foo", replyTo, Encoding.UTF8.GetBytes("message")); m = s.NextMessage(1000); Assert.NotNull(m); Assert.Equal(replyTo, m.Reply); ns.Shutdown(); } // Give the server time to close Thread.Sleep(2000); byte[] reply = Encoding.UTF8.GetBytes("reply"); Assert.ThrowsAny <NATSConnectionClosedException>(() => m.Respond(reply)); } finally { c?.Dispose(); s?.Dispose(); } }
public void TestTimeoutOnNoServers() { Options opts = utils.DefaultTestOptions; Object dmu = new Object(); Object cmu = new Object(); opts.Servers = testServersShortList; opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 100; // millis bool disconnectHandlerCalled = false; bool closedHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = utils.CreateServerOnPort(1222)) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } Stopwatch sw = new Stopwatch(); sw.Start(); lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 60000)); } } sw.Stop(); int expected = opts.MaxReconnect * opts.ReconnectWait; // .NET has long connect times, so revisit this after // a connect timeout has been added. //Assert.IsTrue(sw.ElapsedMilliseconds < (expected + 500)); Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
public void TestBasicClusterReconnect() { string[] plainServers = new string[] { "nats://localhost:1222", "nats://localhost:1224" }; Options opts = utils.DefaultTestOptions; opts.MaxReconnect = 2; opts.ReconnectWait = 1000; opts.NoRandomize = true; opts.Servers = plainServers; Object disconnectLock = new Object(); opts.DisconnectedEventHandler += (sender, args) => { // Suppress any additional calls opts.DisconnectedEventHandler = null; lock (disconnectLock) { Monitor.Pulse(disconnectLock); } }; Object reconnectLock = new Object(); opts.ReconnectedEventHandler = (sender, args) => { // Suppress any additional calls lock (reconnectLock) { Monitor.Pulse(reconnectLock); } }; opts.Timeout = 1000; using (NATSServer s1 = utils.CreateServerOnPort(1222), s2 = utils.CreateServerOnPort(1224)) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { Stopwatch reconnectSw = new Stopwatch(); lock (disconnectLock) { s1.Shutdown(); Assert.True(Monitor.Wait(disconnectLock, 20000)); } reconnectSw.Start(); lock (reconnectLock) { Assert.True(Monitor.Wait(reconnectLock, 20000)); } Assert.Equal(c.ConnectedUrl, testServers[2]); reconnectSw.Stop(); // Make sure we did not wait on reconnect for default time. // Reconnect should be fast since it will be a switch to the // second server and not be dependent on server restart time. // TODO: .NET connect timeout is exceeding long compared to // GO's. Look shortening it, or living with it. //if (reconnectSw.ElapsedMilliseconds > opts.ReconnectWait) //{ // Assert.Fail("Reconnect time took to long: {0} millis.", // reconnectSw.ElapsedMilliseconds); //} } } }
public void TestProperFalloutAfterMaxAttemptsWithAuthMismatch() { Options opts = Context.GetTestOptions(); Object dmu = new Object(); Object cmu = new Object(); opts.Servers = new [] { Context.Server8.Url, Context.Server1.Url }; opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 25; // millis opts.Timeout = 1000; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; bool closedHandlerCalled = false; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = NATSServer.Create(Context.Server8.Port), s2 = NATSServer.CreateWithConfig(Context.Server1.Port, "tls_verify.conf")) { using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 600000)); } } Assert.True(c.Stats.Reconnects != opts.MaxReconnect); Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
public void TestIsReconnectingAndStatus() { bool disconnected = false; object disconnectedLock = new object(); bool reconnected = false; object reconnectedLock = new object(); Options opts = Context.GetTestOptions(Context.Server1.Port); opts.AllowReconnect = true; opts.MaxReconnect = 10000; opts.ReconnectWait = 100; opts.DisconnectedEventHandler += (sender, args) => { lock (disconnectedLock) { disconnected = true; Monitor.Pulse(disconnectedLock); } }; opts.ReconnectedEventHandler += (sender, args) => { lock (reconnectedLock) { reconnected = true; Monitor.Pulse(reconnectedLock); } }; using (NATSServer s = NATSServer.Create(Context.Server1.Port)) { using (var c = Context.ConnectionFactory.CreateConnection(opts)) { Assert.True(c.State == ConnState.CONNECTED); Assert.True(c.IsReconnecting() == false); s.Shutdown(); lock (disconnectedLock) { if (!disconnected) { Assert.True(Monitor.Wait(disconnectedLock, 10000)); } } Assert.True(c.State == ConnState.RECONNECTING); Assert.True(c.IsReconnecting() == true); // restart the server using (NATSServer.Create(Context.Server1.Port)) { lock (reconnectedLock) { // may have reconnected, if not, wait if (!reconnected) { Assert.True(Monitor.Wait(reconnectedLock, 10000)); } } Assert.True(c.IsReconnecting() == false); Assert.True(c.State == ConnState.CONNECTED); c.Close(); } Assert.True(c.IsReconnecting() == false); Assert.True(c.State == ConnState.CLOSED); } } }
public void TestProperFalloutAfterMaxAttempts() { Options opts = utils.DefaultTestOptions; Object dmu = new Object(); Object cmu = new Object(); opts.Servers = this.testServersShortList; opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 25; // millis opts.Timeout = 500; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; bool closedHandlerCalled = false; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = utils.CreateServerOnPort(1222)) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 60000)); } } Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
public void TestProperFalloutAfterMaxAttemptsWithAuthMismatch() { Options opts = utils.DefaultTestOptions; Object dmu = new Object(); Object cmu = new Object(); opts.Servers = new string[] { "nats://localhost:1220", "nats://localhost:1222" }; opts.NoRandomize = true; opts.MaxReconnect = 2; opts.ReconnectWait = 25; // millis opts.Timeout = 1000; bool disconnectHandlerCalled = false; opts.DisconnectedEventHandler = (sender, args) => { lock (dmu) { disconnectHandlerCalled = true; Monitor.Pulse(dmu); } }; bool closedHandlerCalled = false; opts.ClosedEventHandler = (sender, args) => { lock (cmu) { closedHandlerCalled = true; Monitor.Pulse(cmu); } }; using (NATSServer s1 = utils.CreateServerOnPort(1220), s2 = utils.CreateServerWithConfig("tls_1222_verify.conf")) { using (IConnection c = new ConnectionFactory().CreateConnection(opts)) { s1.Shutdown(); lock (dmu) { if (!disconnectHandlerCalled) { Assert.True(Monitor.Wait(dmu, 20000)); } } lock (cmu) { if (!closedHandlerCalled) { Assert.True(Monitor.Wait(cmu, 600000)); } } Assert.True(c.Stats.Reconnects != opts.MaxReconnect); Assert.True(disconnectHandlerCalled); Assert.True(closedHandlerCalled); Assert.True(c.IsClosed()); } } }
// This test works locally, but fails in AppVeyor some of the time // TODO: Work to identify why this happens... public void TestCallbacksOrder() { bool firstDisconnect = true; long orig = DateTime.Now.Ticks; long dtime1 = orig; long dtime2 = orig; long rtime = orig; long atime1 = orig; long atime2 = orig; long ctime = orig; AutoResetEvent reconnected = new AutoResetEvent(false); AutoResetEvent closed = new AutoResetEvent(false); AutoResetEvent asyncErr1 = new AutoResetEvent(false); AutoResetEvent asyncErr2 = new AutoResetEvent(false); AutoResetEvent recvCh = new AutoResetEvent(false); AutoResetEvent recvCh1 = new AutoResetEvent(false); AutoResetEvent recvCh2 = new AutoResetEvent(false); using (NATSServer serverAuth = NATSServer.CreateWithConfig(Context.Server1.Port, "auth.conf"), serverNoAuth = NATSServer.CreateFastAndVerify(Context.Server2.Port)) { Options o = Context.GetTestOptions(Context.Server2.Port); o.DisconnectedEventHandler += (sender, args) => { Thread.Sleep(100); if (firstDisconnect) { firstDisconnect = false; dtime1 = DateTime.Now.Ticks; } else { dtime2 = DateTime.Now.Ticks; } }; o.ReconnectedEventHandler += (sender, args) => { Thread.Sleep(100); rtime = DateTime.Now.Ticks; reconnected.Set(); }; o.AsyncErrorEventHandler += (sender, args) => { Thread.Sleep(100); if (args.Subscription.Subject.Equals("foo")) { atime1 = DateTime.Now.Ticks; asyncErr1.Set(); } else { atime2 = DateTime.Now.Ticks; asyncErr2.Set(); } }; o.ClosedEventHandler += (sender, args) => { ctime = DateTime.Now.Ticks; closed.Set(); }; o.ReconnectWait = 500; o.NoRandomize = true; o.Servers = new [] { Context.Server2.Url, Context.Server1.Url }; o.SubChannelLength = 1; using (IConnection nc = Context.ConnectionFactory.CreateConnection(o), ncp = Context.OpenConnection(Context.Server1.Port)) { // On hosted environments, some threads/tasks can start before others // due to resource constraints. Allow time to start. Thread.Sleep(1000); serverNoAuth.Bounce(1000); Thread.Sleep(1000); Assert.True(reconnected.WaitOne(3000)); object asyncLock = new object(); EventHandler <MsgHandlerEventArgs> eh = (sender, args) => { lock (asyncLock) { recvCh.Set(); if (args.Message.Subject.Equals("foo")) { recvCh1.Set(); } else { recvCh2.Set(); } } }; IAsyncSubscription sub1 = nc.SubscribeAsync("foo", eh); IAsyncSubscription sub2 = nc.SubscribeAsync("bar", eh); nc.Flush(); ncp.Publish("foo", System.Text.Encoding.UTF8.GetBytes("hello")); ncp.Publish("bar", System.Text.Encoding.UTF8.GetBytes("hello")); ncp.Flush(); recvCh.WaitOne(3000); for (int i = 0; i < 3; i++) { ncp.Publish("foo", System.Text.Encoding.UTF8.GetBytes("hello")); ncp.Publish("bar", System.Text.Encoding.UTF8.GetBytes("hello")); } ncp.Flush(); Assert.True(asyncErr1.WaitOne(3000)); Assert.True(asyncErr2.WaitOne(3000)); serverNoAuth.Shutdown(); Thread.Sleep(1000); closed.Reset(); nc.Close(); Assert.True(closed.WaitOne(3000)); } if (dtime1 == orig || dtime2 == orig || rtime == orig || atime1 == orig || atime2 == orig || ctime == orig) { Console.WriteLine("Error = callback didn't fire: {0}\n{1}\n{2}\n{3}\n{4}\n{5}\n", dtime1, dtime2, rtime, atime1, atime2, ctime); throw new Exception("Callback didn't fire."); } if (rtime < dtime1 || dtime2 < rtime || ctime < atime2) { Console.WriteLine("Wrong callback order:\n" + "dtime1: {0}\n" + "rtime: {1}\n" + "atime1: {2}\n" + "atime2: {3}\n" + "dtime2: {4}\n" + "ctime: {5}\n", dtime1, rtime, atime1, atime2, dtime2, ctime); throw new Exception("Invalid callback order."); } } }
public void TestExtendedReconnectFunctionality() { Options opts = getReconnectOptions(); Object msgLock = new Object(); AutoResetEvent disconnectedEvent = new AutoResetEvent(false); AutoResetEvent reconnectedEvent = new AutoResetEvent(false); opts.DisconnectedEventHandler = (sender, args) => { disconnectedEvent.Set(); }; opts.ReconnectedEventHandler = (sender, args) => { reconnectedEvent.Set(); }; byte[] payload = Encoding.UTF8.GetBytes("bar"); NATSServer ns = NATSServer.Create(Context.Server1.Port); using (IConnection c = Context.ConnectionFactory.CreateConnection(opts)) { IAsyncSubscription s1 = c.SubscribeAsync("foo"); IAsyncSubscription s2 = c.SubscribeAsync("foobar"); s1.MessageHandler += incrReceivedMessageHandler; s2.MessageHandler += incrReceivedMessageHandler; s1.Start(); s2.Start(); received = 0; c.Publish("foo", payload); c.Flush(); ns.Shutdown(); // server is stopped here. Assert.True(disconnectedEvent.WaitOne(20000)); // subscribe to bar while connected. IAsyncSubscription s3 = c.SubscribeAsync("bar"); s3.MessageHandler += incrReceivedMessageHandler; s3.Start(); // Unsub foobar while disconnected s2.Unsubscribe(); c.Publish("foo", payload); c.Publish("bar", payload); // server is restarted here... using (NATSServer ts = NATSServer.Create(Context.Server1.Port)) { // wait for reconnect Assert.True(reconnectedEvent.WaitOne(60000)); c.Publish("foobar", payload); c.Publish("foo", payload); using (IAsyncSubscription s4 = c.SubscribeAsync("done")) { AutoResetEvent doneEvent = new AutoResetEvent(false); s4.MessageHandler += (sender, args) => { doneEvent.Set(); }; s4.Start(); c.Publish("done", payload); Assert.True(doneEvent.WaitOne(4000)); } } // NATSServer Assert.Equal(4, received); } }