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 2003-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: ExpirationTest.java,v 1.3 2004/02/03 07:33:32 tanderson Exp $
44 */
45 package org.exolab.jmscts.test.producer.ttl;
46
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.List;
50
51 import javax.jms.Message;
52 import javax.jms.Session;
53
54 import org.apache.log4j.Category;
55
56 import junit.framework.Test;
57
58 import org.exolab.jmscts.core.AbstractSendReceiveTestCase;
59 import org.exolab.jmscts.core.MessageReceiver;
60 import org.exolab.jmscts.core.MessageSender;
61 import org.exolab.jmscts.core.MessagingBehaviour;
62 import org.exolab.jmscts.core.TestContext;
63 import org.exolab.jmscts.core.TestContextHelper;
64 import org.exolab.jmscts.core.TestCreator;
65 import org.exolab.jmscts.core.TestProperties;
66
67
68 /***
69 * This class tests message expiration
70 *
71 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
72 * @version $Revision: 1.3 $
73 */
74 public class ExpirationTest extends AbstractSendReceiveTestCase {
75
76 /***
77 * The default destination
78 */
79 private static final String DESTINATION = "ExpirationTest";
80
81 /***
82 * The logger
83 */
84 private static final Category log = Category.getInstance(
85 ExpirationTest.class);
86
87 /***
88 * The time in milliseconds to wait for the JMS provider to collect expired
89 * This can be set for providers which collect expired messages
90 * periodically, rather than at the moment they expire, and is a
91 * workaround for section 3.9 of the specification which states:
92 * "Clients should not receive messages which have expired, however JMS
93 * does not guarantee that this will not happen."
94 */
95 private static final long EXPIRATION_INTERVAL =
96 TestProperties.getLong(ExpirationTest.class, "expirationInterval", 0);
97
98
99 /***
100 * Construct a new <code>ExpirationTest</code>
101 *
102 * @param name the name of test case
103 */
104 public ExpirationTest(String name) {
105 super(name);
106 }
107
108 /***
109 * Sets up the test suite
110 *
111 * @return an instance of this class that may be run by
112 * {@link org.exolab.jmscts.core.JMSTestRunner}
113 */
114 public static Test suite() {
115 return TestCreator.createSendReceiveTest(ExpirationTest.class);
116 }
117
118 /***
119 * Returns the list of destination names used by this test case. These
120 * are used to pre-administer destinations prior to running the test case.
121 *
122 * @return the list of destinations used by this test case
123 */
124 public String[] getDestinations() {
125 return new String[] {DESTINATION};
126 }
127
128 /***
129 * Verifies that messages expire.
130 * <p/>
131 * It sends two groups of messages - one group which expires after
132 * 1 second, and another which don't expire, and verifies that after
133 * the first group should have expired, only the non-expiring group
134 * can be received.
135 * <p/>
136 * If the JMS provider doesn't support immediate expiration of messages,
137 * the
138 * <em>
139 * org.exolab.jmscts.test.producer.ttl.ExpirationTest.expirationInterval
140 * </em>
141 * property should be configured in <em>jmscts.properties</em> to delay
142 * the test until the expired messages are collected.
143 *
144 * @jmscts.requirement message.expiration.zero
145 * @jmscts.requirement message.expiration.expired
146 * @jmscts.message TextMessage
147 * @throws Exception for any error
148 */
149 public void testExpiration() throws Exception {
150 final long timeToLive = 1000; // i.e, 1 second
151 final int messages = 10; // no. of messages to send
152 final int receivers = 1; // no. of receivers.
153 checkExpiration(timeToLive, messages, receivers);
154 }
155
156 /***
157 * Verifies that a single message expires.
158 * <p/>
159 * It sends two messages - one which expires after 1 second, and another
160 * which doesn't expire, and verifies that after the first should have
161 * expired, only the non-expiring message can be received.
162 * <p/>
163 * If the JMS provider doesn't support immediate expiration of messages,
164 * the
165 * <em>
166 * org.exolab.jmscts.test.producer.ttl.ExpirationTest.expirationInterval
167 * </em>
168 * property should be configured in <em>jmscts.properties</em> to delay
169 * the test until the expired messages are collected.
170 *
171 * @jmscts.requirement message.expiration.zero
172 * @jmscts.requirement message.expiration.expired
173 * @jmscts.message TextMessage
174 * @throws Exception for any error
175 */
176 public void testSingleMessageExpiration() throws Exception {
177 final long timeToLive = 1000; // i.e, 1 second
178 final int messages = 1; // no. of messages to send
179 final int receivers = 1; // no. of receivers.
180 checkExpiration(timeToLive, messages, receivers);
181 }
182
183 /***
184 * Verifies that messages to topics expire, when there is more than
185 * one subscriber.
186 * <p/>
187 * It sends two groups of messages - one group which expires after
188 * 1 second, and another which don't expire, and verifies that after
189 * the first group should have expired, only the non-expiring group
190 * can be received.
191 * <p/>
192 * If the JMS provider doesn't support immediate expiration of messages,
193 * the
194 * <em>
195 * org.exolab.jmscts.test.producer.ttl.ExpirationTest.expirationInterval
196 * </em>
197 * property should be configured in <em>jmscts.properties</em> to delay
198 * the test until the expired messages are collected.
199 *
200 * @jmscts.requirement message.expiration.zero
201 * @jmscts.requirement message.expiration.expired
202 * @jmscts.factory TopicConnectionFactory
203 * @jmscts.factory XATopicConnectionFactory
204 * @jmscts.message ObjectMessage
205 * @throws Exception for any error
206 */
207 public void testExpiration2Subscribers() throws Exception {
208 final long timeToLive = 1000; // i.e, 1 second
209 final int messages = 10; // no. of messages to send
210 final int subscribers = 2; // no. of subscribers.
211 checkExpiration(timeToLive, messages, subscribers);
212 }
213
214 /***
215 * Verifies that messages to topics expire, when one subscriber is
216 * durable, and the other non-durable.
217 * <p/>
218 * It sends two groups of messages - one group which expires after
219 * 1 second, and another which don't expire, and verifies that after
220 * the first group should have expired, only the non-expiring group
221 * can be received.
222 * <p/>
223 * If the JMS provider doesn't support immediate expiration of messages,
224 * the
225 * <em>
226 * org.exolab.jmscts.test.producer.ttl.ExpirationTest.expirationInterval
227 * </em>
228 * property should be configured in <em>jmscts.properties</em> to delay
229 * the test until the expired messages are collected.
230 *
231 * @jmscts.requirement message.expiration.zero
232 * @jmscts.requirement message.expiration.expired
233 * @jmscts.factory TopicConnectionFactory
234 * @jmscts.factory XATopicConnectionFactory
235 * @jmscts.delivery administered-consumer
236 * @jmscts.durableonly true
237 * @jmscts.message MapMessage
238 * @throws Exception for any error
239 */
240 public void testExpiration2DiffSubscribers() throws Exception {
241 final long timeToLive = 1000; // i.e, 1 second
242 final int messages = 10; // no. of messages to send
243
244 TestContext context = getContext();
245 MessageReceiver[] subscribers = new MessageReceiver[2];
246
247 // create a context for the non-durable subscriber
248 MessagingBehaviour behaviour = new MessagingBehaviour(
249 context.getMessagingBehaviour());
250 behaviour.setDurable(false);
251 TestContext nondurable = TestContextHelper.createSendReceiveContext(
252 context, false, behaviour);
253
254 try {
255 subscribers[0] = createReceiver(DESTINATION); // durable subscriber
256 subscribers[1] = createReceiver(nondurable, DESTINATION);
257 checkExpiration(timeToLive, messages, subscribers);
258 } finally {
259 close(subscribers);
260 nondurable.close();
261 }
262 }
263
264 /***
265 * Sends <code>messageCount</code> messages with time-to-live
266 * <code>timeToLive</code>, and <code>messageCount</code> messages which
267 * don't expire, and verifies that after sleeping
268 * <code>timeToLive + EXPIRATION_INTERVAL</code> milliseconds, only the
269 * non-expiring messages may be received
270 *
271 * @param timeToLive the time-to-live for the expiring messages
272 * @param messageCount the no. of messages to send
273 * @param receiverCount the no. of receivers. For queues, should be 1.
274 * @throws Exception for any error
275 */
276 private void checkExpiration(long timeToLive, int messageCount,
277 int receiverCount) throws Exception {
278 MessageReceiver[] receivers = new MessageReceiver[receiverCount];
279
280 try {
281 for (int i = 0; i < receivers.length; ++i) {
282 receivers[i] = createReceiver(DESTINATION);
283 }
284 checkExpiration(timeToLive, messageCount, receivers);
285 } finally {
286 close(receivers);
287 }
288 }
289
290 /***
291 * Sends <code>messageCount</code> messages with time-to-live
292 * <code>timeToLive</code>, and <code>messageCount</code> messages which
293 * don't expire, and verifies that after sleeping
294 * <code>timeToLive + EXPIRATION_INTERVAL</code> milliseconds, only the
295 * non-expiring messages may be received
296 *
297 * @param timeToLive the time-to-live for the expiring messages
298 * @param messageCount the no. of messages to send
299 * @param receivers the receivers to use.
300 * @throws Exception for any error
301 */
302 private void checkExpiration(long timeToLive, int messageCount,
303 MessageReceiver[] receivers)
304 throws Exception {
305 TestContext context = getContext();
306 Session session = context.getSession();
307 Message message = context.getMessage();
308 HashSet expiringIds = new HashSet();
309 HashSet nonExpiringIds = new HashSet();
310
311 MessageSender sender = null;
312
313 try {
314 sender = createSender(DESTINATION);
315
316 // send messages that expire
317 for (int i = 0; i < messageCount; ++i) {
318 sender.send(message, 1, timeToLive);
319 expiringIds.add(message.getJMSMessageID());
320 }
321
322 // send messages that don't expire
323 for (int i = 0; i < messageCount; ++i) {
324 sender.send(message, 1, Message.DEFAULT_TIME_TO_LIVE);
325 nonExpiringIds.add(message.getJMSMessageID());
326 }
327
328 if (session.getTransacted()) {
329 session.commit();
330 }
331
332 assertEquals("Duplicate JMSMessageID allocated", messageCount,
333 expiringIds.size());
334
335 assertEquals("Duplicate JMSMessageID allocated", messageCount,
336 nonExpiringIds.size());
337
338 // now wait to allow the messages to expire. All of the non
339 // expiring messages should be received, and none of the expiring
340 // messages
341 long sleepTime = EXPIRATION_INTERVAL + timeToLive;
342 try {
343 log.debug("Sleeping for " + sleepTime
344 + "ms to allow messages to expire");
345 Thread.currentThread().sleep(sleepTime);
346 } catch (InterruptedException ignore) {
347 // no-op
348 }
349
350 for (int i = 0; i < receivers.length; ++i) {
351 List messages = receive(receivers[i], messageCount);
352 Iterator iterator = messages.iterator();
353 while (iterator.hasNext()) {
354 Message received = (Message) iterator.next();
355 String id = received.getJMSMessageID();
356 if (!nonExpiringIds.contains(id)) {
357 if (expiringIds.contains(id)) {
358 fail("Received a message which should have "
359 + "expired: " + id);
360 } else {
361 fail("Received a message which wasn't sent by this"
362 + " test: " + id);
363 }
364 }
365 }
366 }
367 } finally {
368 close(sender);
369 }
370 }
371
372 }
This page was automatically generated by Maven