View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Exoffice Technologies. For written permission, 18 * please contact tma@netspace.net.au. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Exoffice Technologies. Exolab is a registered 23 * trademark of Exoffice Technologies. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: ReceiverTest.java,v 1.11 2004/02/03 07:32:07 tanderson Exp $ 44 */ 45 package org.exolab.jmscts.test.connection; 46 47 import java.util.List; 48 49 import javax.jms.Connection; 50 import javax.jms.Session; 51 52 import org.apache.log4j.Category; 53 54 import junit.framework.Test; 55 56 import org.exolab.jmscts.core.AbstractSendReceiveTestCase; 57 import org.exolab.jmscts.core.CompletionListener; 58 import org.exolab.jmscts.core.ConnectionHelper; 59 import org.exolab.jmscts.core.DelayedAction; 60 import org.exolab.jmscts.core.MessageReceiver; 61 import org.exolab.jmscts.core.TestContext; 62 import org.exolab.jmscts.core.TestCreator; 63 import org.exolab.jmscts.core.ThreadedActions; 64 import org.exolab.jmscts.core.ThreadedReceiver; 65 66 67 /*** 68 * This class tests the behaviour of stopping and closing a connection 69 * while a receiver is active. 70 * 71 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> 72 * @version $Revision: 1.11 $ 73 * @see AbstractSendReceiveTestCase 74 * @see org.exolab.jmscts.core.SendReceiveTestRunner 75 * @jmscts.session all 76 * @jmscts.message TextMessage 77 * @jmscts.delivery synchronous 78 */ 79 public class ReceiverTest extends AbstractSendReceiveTestCase { 80 81 /*** 82 * The destination used by this test case 83 */ 84 private static final String DESTINATION = "ReceiverTest"; 85 86 /*** 87 * The logger 88 */ 89 private static final Category log = 90 Category.getInstance(ReceiverTest.class); 91 92 93 /*** 94 * Construct a new <code>ReceiverTest</code> 95 * 96 * @param name the name of test case 97 */ 98 public ReceiverTest(String name) { 99 super(name); 100 } 101 102 /*** 103 * Sets up the test suite 104 * 105 * @return an instance of this class that may be run by 106 * {@link org.exolab.jmscts.core.JMSTestRunner} 107 */ 108 public static Test suite() { 109 return TestCreator.createSendReceiveTest(ReceiverTest.class); 110 } 111 112 /*** 113 * Returns if this test can share resources with other test cases. 114 * This implementation always returns <code>false</code>, to 115 * ensure that a new connection is created for each test. 116 * 117 * @return <code>false</code> 118 */ 119 public boolean share() { 120 return false; 121 } 122 123 /*** 124 * Returns if the connection should be started prior to running the test. 125 * This implementation always returns <code>false</code> to avoid 126 * conflicts with test cases 127 * 128 * @return <code>false</code> 129 */ 130 public boolean startConnection() { 131 return false; 132 } 133 134 /*** 135 * Returns the list of destination names used by this test case. These 136 * are used to pre-create destinations prior to running the test case. 137 * 138 * @return the list of destinations used by this test case 139 */ 140 public String[] getDestinations() { 141 return new String[]{DESTINATION}; 142 } 143 144 /*** 145 * Verifies that the receive timers for a stopped connection continue to 146 * advance, so receives may time out and return a null message while the 147 * connection is stopped. 148 * 149 * @jmscts.requirement connection.stop.receivers 150 * @throws Exception for any error 151 */ 152 public void testConnectionStop() throws Exception { 153 final int delayTime = 500; // 500 ms 154 final int receiptTime = 5000; // 5 secs 155 TestContext context = getContext(); 156 final Connection connection = context.getConnection(); 157 MessageReceiver receiver = createReceiver(DESTINATION); 158 159 DelayedAction action = new DelayedAction(delayTime) { 160 public void runProtected() throws Exception { 161 connection.stop(); 162 } 163 }; 164 165 try { 166 // start the connection 167 connection.start(); 168 169 // stop the connection in a separate thread to allow the receiver 170 // to invoke receive() 171 action.start(); 172 173 try { 174 // wait for a non-existent message 175 List result = receiver.receive(0, receiptTime); 176 } catch (Exception exception) { 177 fail("Expected synchronous consumer to time out and return " 178 + "null when connection stopped, but threw exception=" 179 + exception.getClass().getName() + ", message=" 180 + exception.getMessage()); 181 } 182 183 // receiver returned null. Verify that the connection was stopped 184 Exception exception = action.getException(); 185 if (exception != null) { 186 fail("Failed to stop connection, exception=" 187 + exception.getClass().getName() + ", message=" 188 + exception.getMessage()); 189 } 190 } finally { 191 try { 192 receiver.remove(); 193 } catch (Exception exception) { 194 fail("Attempting to invoke close() for a consumer on a " 195 + "stopped connection threw exception=" 196 + exception.getClass().getName() + ", message=" 197 + exception.getMessage()); 198 } 199 } 200 } 201 202 /*** 203 * Verifies that the receive timers for a closed connection continue to 204 * advance, so receives may time out and return a null message as the 205 * connection is closed. 206 * 207 * @jmscts.requirement connection.close.receivers 208 * @throws Exception for any error 209 */ 210 public void testConnectionClose() throws Exception { 211 final int delayTime = 1000; // 1 sec 212 final int completionTime = 30000; // 30 secs 213 TestContext context = getContext(); 214 final Connection connection = context.getConnection(); 215 final MessageReceiver receiver = createReceiver(DESTINATION); 216 CompletionListener listener = new CompletionListener(2); 217 218 DelayedAction receive = new DelayedAction(0, listener) { 219 public void runProtected() throws Exception { 220 try { 221 log.debug("Receiver starting"); 222 receiver.receive(0, 0); 223 } finally { 224 log.debug("Receiver terminating"); 225 } 226 } 227 }; 228 229 DelayedAction close = new DelayedAction(delayTime, listener) { 230 public void runProtected() throws Exception { 231 try { 232 log.debug("Connection closing"); 233 connection.close(); 234 } finally { 235 log.debug("Connection closed"); 236 } 237 } 238 }; 239 240 // start the connection 241 connection.start(); 242 243 // invoke the receive in a separate thread 244 receive.start(); 245 246 // close the connection in a separate thread to allow the receiver 247 // to invoke receive() 248 close.start(); 249 250 // wait for up to 30 seconds for the two threads to complete 251 listener.waitForCompletion(completionTime); 252 253 if (listener.getCompleted() != 2) { 254 // one or both of the threads didn't complete. Invalidate the 255 // connection so that the test runner doesn't attempt to close it, 256 // which could result in the suite to hang. 257 context.invalidate(); 258 fail("Connection.close() didn't force consumer's receive() " 259 + "to be terminated and return null. Appears to have " 260 + "blocked"); 261 } 262 263 if (receive.getException() != null) { 264 context.invalidate(); 265 Exception exception = receive.getException(); 266 fail("Expected synchronous consumer's receive() to be " 267 + "terminated and return null when connection closed, " 268 + "but threw exception=" + exception.getClass().getName() 269 + ", message=" + exception.getMessage()); 270 } 271 if (close.getException() != null) { 272 context.invalidate(); 273 Exception exception = close.getException(); 274 fail("Closing connection while a synchronous receive() in " 275 + "progress threw exception=" + exception.getClass().getName() 276 + ", message=" + exception.getMessage()); 277 } 278 279 try { 280 // Closing a consumer for a closed connection should be ignored 281 receiver.close(); 282 } catch (Exception exception) { 283 fail("Attempting to invoke close() for a consumer on a " 284 + "closed connection threw exception=" 285 + exception.getClass().getName() + ", message=" 286 + exception.getMessage()); 287 } 288 } 289 290 /*** 291 * Verifies that the receive timers for a stopped connection continue to 292 * advance, so that when the connection is stopped, a waiting receiver can 293 * subsequently receive a message when the connection is started again 294 * 295 * @jmscts.requirement connection.stop.receivers 296 * @throws Exception for any error 297 */ 298 public void testConnectionRestart() throws Exception { 299 final int delayTime = 1000; // 1 sec 300 final int completionTime = 30000; // 30 secs 301 final TestContext context = getContext(); 302 final Connection connection = context.getConnection(); 303 final MessageReceiver receiver = createReceiver(DESTINATION); 304 305 // receiver which waits indefinitely to receive 1 message 306 ThreadedReceiver receive = new ThreadedReceiver(receiver, 1, 0); 307 308 // action which restarts the connection and sends a message, 309 // to be received by the receive thread 310 DelayedAction restart = new DelayedAction(delayTime) { 311 public void runProtected() throws Exception { 312 connection.stop(); 313 connection.start(); 314 // create a context with a new session to avoid synchronization 315 // issues 316 Session session = ConnectionHelper.createSession(context); 317 TestContext tmp = new TestContext(context, session, 318 context.getAckType()); 319 TestContext local = new TestContext( 320 tmp, context.getMessage(), 321 context.getMessagingBehaviour()); 322 send(local, DESTINATION, 1); 323 } 324 }; 325 326 ThreadedActions actions = new ThreadedActions(); 327 actions.addAction(receive); 328 actions.addAction(restart); 329 330 // start the connection 331 connection.start(); 332 333 // start the two actions, and wait for them to complete 334 actions.start(); 335 boolean completed = actions.waitForCompletion(completionTime); 336 337 if (!completed) { 338 // one or both of the actions didn't complete. Invalidate the 339 // connection so that the test runner doesn't attempt to close it, 340 // which could result in the suite to hang. 341 context.invalidate(); 342 fail("Receiver didn't return a message after connection restart. " 343 + "Appears to have blocked"); 344 } 345 346 // make sure both actions completed successfully 347 if (receive.getException() != null) { 348 context.invalidate(); 349 Exception exception = receive.getException(); 350 fail("Expected synchronous consumer to return a message " 351 + "after connection was restarted, but threw exception=" 352 + exception.getClass().getName() + ", message=" 353 + exception.getMessage()); 354 } 355 356 if (restart.getException() != null) { 357 context.invalidate(); 358 Exception exception = receive.getException(); 359 fail("Failure in restarting connection, exception=" 360 + exception.getClass().getName() + ", message=" 361 + exception.getMessage()); 362 } 363 364 List messages = receive.getMessages(); 365 if (messages == null) { 366 // No message was received. Verify that the connection was 367 // restarted successfully 368 fail("Failed to receive any messages from the " 369 + "destination after the connection was restarted"); 370 } 371 372 receiver.remove(); 373 } 374 375 }

This page was automatically generated by Maven