001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.server.failover;
022
023 import junit.framework.TestCase;
024 import org.apache.qpid.AMQDisconnectedException;
025 import org.apache.qpid.AMQException;
026 import org.apache.qpid.client.AMQConnection;
027 import org.apache.qpid.client.AMQConnectionURL;
028 import org.apache.qpid.client.transport.TransportConnection;
029 import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
030 import org.apache.qpid.url.URLSyntaxException;
031 import org.slf4j.Logger;
032 import org.slf4j.LoggerFactory;
033
034 import javax.jms.ExceptionListener;
035 import javax.jms.JMSException;
036 import java.util.concurrent.CountDownLatch;
037
038 public class FailoverMethodTest extends TestCase implements ExceptionListener
039 {
040 private CountDownLatch _failoverComplete = new CountDownLatch(1);
041
042 public void setUp() throws AMQVMBrokerCreationException
043 {
044 TransportConnection.createVMBroker(1);
045 }
046
047 public void tearDown() throws AMQVMBrokerCreationException
048 {
049 TransportConnection.killAllVMBrokers();
050 }
051
052 /**
053 * Test that the round robin method has the correct delays.
054 * The first connection to vm://:1 will work but the localhost connection should fail but the duration it takes
055 * to report the failure is what is being tested.
056 *
057 * @throws URLSyntaxException
058 * @throws InterruptedException
059 * @throws JMSException
060 */
061 public void testFailoverRoundRobinDelay() throws URLSyntaxException, InterruptedException, JMSException
062 {
063 //note: The VM broker has no connect delay and the default 1 retry
064 // while the tcp:localhost broker has 3 retries with a 2s connect delay
065 String connectionString = "amqp://guest:guest@/test?brokerlist=" +
066 "'vm://:1;tcp://localhost:5670?connectdelay='2000',retries='3''";
067
068 AMQConnectionURL url = new AMQConnectionURL(connectionString);
069
070 try
071 {
072 long start = System.currentTimeMillis();
073 AMQConnection connection = new AMQConnection(url, null);
074
075 connection.setExceptionListener(this);
076
077 TransportConnection.killAllVMBrokers();
078
079 _failoverComplete.await();
080
081 long end = System.currentTimeMillis();
082
083 long duration = (end - start);
084
085 //Failover should take more that 6 seconds.
086 // 3 Retires
087 // so VM Broker NoDelay 0 (Connect) NoDelay 0
088 // then TCP NoDelay 0 Delay 1 Delay 2 Delay 3
089 // so 3 delays of 2s in total for connection
090 // as this is a tcp connection it will take 1second per connection to fail
091 // so max time is 6seconds of delay plus 4 seconds of TCP Delay + 1 second of runtime. == 11 seconds
092
093 // Ensure we actually had the delay
094 assertTrue("Failover took less than 6 seconds", duration > 6000);
095
096 // Ensure we don't have delays before initial connection and reconnection.
097 // We allow 1 second for initial connection and failover logic on top of 6s of sleep.
098 assertTrue("Failover took more than 11 seconds:(" + duration + ")", duration < 11000);
099 }
100 catch (AMQException e)
101 {
102 fail(e.getMessage());
103 }
104 }
105
106 public void testFailoverSingleDelay() throws URLSyntaxException, AMQVMBrokerCreationException,
107 InterruptedException, JMSException
108 {
109 String connectionString = "amqp://guest:guest@/test?brokerlist='vm://:1?connectdelay='2000',retries='3''";
110
111 AMQConnectionURL url = new AMQConnectionURL(connectionString);
112
113 try
114 {
115 long start = System.currentTimeMillis();
116 AMQConnection connection = new AMQConnection(url, null);
117
118 connection.setExceptionListener(this);
119
120 TransportConnection.killAllVMBrokers();
121
122 _failoverComplete.await();
123
124 long end = System.currentTimeMillis();
125
126 long duration = (end - start);
127
128 //Failover should take more that 6 seconds.
129 // 3 Retires
130 // so NoDelay 0 (Connect) NoDelay 0 Delay 1 Delay 2 Delay 3
131 // so 3 delays of 2s in total for connection
132 // so max time is 6 seconds of delay + 1 second of runtime. == 7 seconds
133
134 // Ensure we actually had the delay
135 assertTrue("Failover took less than 6 seconds", duration > 6000);
136
137 // Ensure we don't have delays before initial connection and reconnection.
138 // We allow 1 second for initial connection and failover logic on top of 6s of sleep.
139 assertTrue("Failover took more than 7 seconds:(" + duration + ")", duration < 7000);
140 }
141 catch (AMQException e)
142 {
143 fail(e.getMessage());
144 }
145 }
146
147 public void onException(JMSException e)
148 {
149 if (e.getLinkedException() instanceof AMQDisconnectedException)
150 {
151 _failoverComplete.countDown();
152 }
153 }
154 }
|