View Javadoc

1   /*
2    * $Id: ServiceInFlightMessagesTestCase.java 22431 2011-07-18 07:40:35Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.test.integration.service;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleException;
15  import org.mule.api.service.Service;
16  import org.mule.config.DefaultMuleConfiguration;
17  import org.mule.context.DefaultMuleContextBuilder;
18  import org.mule.tck.junit4.FunctionalTestCase;
19  import org.mule.util.store.QueuePersistenceObjectStore;
20  
21  import java.io.File;
22  
23  import org.apache.commons.io.FileUtils;
24  import org.junit.Test;
25  
26  import static org.junit.Assert.assertEquals;
27  import static org.junit.Assert.assertTrue;
28  
29  public class ServiceInFlightMessagesTestCase extends FunctionalTestCase
30  {
31  
32      protected static final int WAIT_TIME_MILLIS = 500;
33      protected static final int NUM_MESSAGES = 500;
34  
35      @Override
36      protected String getConfigResources()
37      {
38          return "org/mule/test/integration/service/service-inflight-messages.xml";
39      }
40  
41      @Override
42      protected MuleContext createMuleContext() throws Exception
43      {
44          // Use a graceful shutdown but not the full 5s default
45          MuleContext context = super.createMuleContext();
46          ((DefaultMuleConfiguration) context.getConfiguration()).setShutdownTimeout(WAIT_TIME_MILLIS);
47          return context;
48      }
49  
50      @Override
51      protected void doTearDown() throws Exception
52      {
53          FileUtils.deleteDirectory(new File(muleContext.getConfiguration().getWorkingDirectory()));
54          super.doTearDown();
55      }
56  
57      @Test
58      public void testInFlightMessagesWhenServiceStopped() throws Exception
59      {
60          Service service = muleContext.getRegistry().lookupService("TestService");
61          populateSedaQueue(service, NUM_MESSAGES);
62  
63          stopService(service);
64  
65          assertNoLostMessages(NUM_MESSAGES, service);
66          // Seda queue is empty because queue is not persistent and therefore is
67          // emptied when service is stopped
68          assertSedaQueueEmpty(service);
69      }
70  
71      @Test
72      public void testInFlightMessagesPausedServiceWhenServiceStopped() throws Exception
73      {
74          Service service = muleContext.getRegistry().lookupService("PausedTestService");
75          populateSedaQueue(service, NUM_MESSAGES);
76  
77          stopService(service);
78  
79          // The service is paused so no message get processed. Because the service is
80          // stopped messages aren't lost. If Mule was disposed then messages would be
81          // lost
82          assertNoLostMessages(NUM_MESSAGES, service);
83  
84          assertOutboundEmpty();
85      }
86  
87      @Test
88      public void testInFlightMessagesPersistentQueueServiceWhenServiceStopped() throws Exception
89      {
90          Service service = muleContext.getRegistry().lookupService("TestPersistentQueueService");
91  
92          populateSedaQueue(service, NUM_MESSAGES);
93  
94          stopService(service);
95  
96          assertNoLostMessages(NUM_MESSAGES, service);
97  
98          // Start, process some messages, stop and make sure no messages get lost.
99          startService(service);
100         Thread.sleep(WAIT_TIME_MILLIS * 2);
101         stopService(service);
102 
103         assertNoLostMessages(NUM_MESSAGES, service);
104 
105         // Let mule finish up with the rest of the messages until seda queue is empty
106         startService(service);
107         Thread.sleep(WAIT_TIME_MILLIS * 10);
108         stopService(service);
109 
110         assertNoLostMessages(NUM_MESSAGES, service);
111         assertSedaQueueEmpty(service);
112     }
113 
114     @Test
115     public void testInFlightMessagesPausedPersistentQueueServiceWhenServiceStopped() throws Exception
116     {
117         Service service = muleContext.getRegistry().lookupService("PausedTestPersistentQueueService");
118         populateSedaQueue(service, NUM_MESSAGES);
119 
120         stopService(service);
121 
122         // Paused service does not process messages before or during stop().
123         assertOutboundEmpty();
124         assertNoLostMessages(NUM_MESSAGES, service);
125 
126         // Start, process some messages, stop and make sure no messages get lost.
127         startService(service);
128         service.resume();
129         Thread.sleep(WAIT_TIME_MILLIS * 2);
130         stopService(service);
131 
132         assertNoLostMessages(NUM_MESSAGES, service);
133 
134         // Let mule finish up with the rest of the messages until seda queue is empty
135         startService(service);
136         service.resume();
137         Thread.sleep(WAIT_TIME_MILLIS * 20);
138         stopService(service);
139 
140         assertNoLostMessages(NUM_MESSAGES, service);
141         assertSedaQueueEmpty(service);
142     }
143 
144     @Test
145     public void testInFlightMessagesPersistentQueueServiceWhenMuleDisposed() throws Exception
146     {
147         Service service = muleContext.getRegistry().lookupService("TestPersistentQueueService");
148         populateSedaQueue(service, NUM_MESSAGES);
149 
150         muleContext.dispose();
151 
152         assertNoLostMessages(NUM_MESSAGES, service);
153 
154         recreateAndStartMuleContext();
155         Thread.sleep(WAIT_TIME_MILLIS);
156         muleContext.dispose();
157 
158         assertNoLostMessages(NUM_MESSAGES, service);
159 
160         // Let mule finish up with the rest of the messages until seda queue is empty
161         recreateAndStartMuleContext();
162         Thread.sleep(WAIT_TIME_MILLIS * 10);
163         muleContext.dispose();
164 
165         assertNoLostMessages(NUM_MESSAGES, service);
166         assertSedaQueueEmpty(service);
167     }
168 
169     protected void recreateAndStartMuleContext() throws Exception, MuleException
170     {
171         muleContext = createMuleContext();
172         muleContext.start();
173     }
174 
175     protected void populateSedaQueue(Service service, int numMessages) throws MuleException, Exception
176     {
177         for (int i = 0; i < numMessages; i++)
178         {
179             service.dispatchEvent(getTestEvent("test", service, muleContext.getEndpointFactory()
180                 .getInboundEndpoint("test://test")));
181         }
182     }
183 
184     /**
185      * After each run the following should total 500 events: 1) Event still in SEDA
186      * queue 2) Events dispatched to outbound vm endpooint 3) Events that were unable
187      * to be sent to stopped service and raised exceptions
188      *
189      * @throws Exception
190      */
191     protected synchronized void assertNoLostMessages(int numMessages, Service service) throws Exception
192     {
193         logger.info("SEDA Queue: " + getSedaQueueSize(service) + ", Outbound endpoint: "
194                     + getOutSize());
195         assertEquals(numMessages, getOutSize() + getSedaQueueSize(service));
196     }
197 
198     protected synchronized void assertSedaQueueEmpty(Service service) throws MuleException
199     {
200         assertEquals(0, getSedaQueueSize(service));
201     }
202 
203     protected synchronized void assertSedaQueueNotEmpty(Service service) throws MuleException
204     {
205         assertTrue(String.format("Seda queue for service '%s' is empty", service.getName()),
206             getSedaQueueSize(service) > 0);
207     }
208 
209     protected synchronized void assertOutboundEmpty() throws Exception
210     {
211         assertEquals(0, getOutSize());
212     }
213 
214     protected synchronized void assertOutboundNotEmpty() throws Exception
215     {
216         assertTrue("VM Out queue is empty", getOutSize() > 0);
217     }
218 
219     protected int getSedaQueueSize(Service service) throws MuleException
220     {
221         return getQueueSize(getSedaQueueName(service));
222     }
223 
224     protected String getSedaQueueName(Service service)
225     {
226         return "seda.queue(" + service.getName() + ")";
227     }
228 
229     protected int getOutSize() throws Exception
230     {
231         return getQueueSize("out");
232     }
233 
234     protected int getQueueSize(String name) throws MuleException
235     {
236         if (muleContext != null && muleContext.isStarted())
237         {
238             return muleContext.getQueueManager().getQueueSession().getQueue(name).size();
239         }
240         else
241         {
242             // Don;t fool around trying to use objects that weren't started fully, just go to the disk
243             MuleContext localMuleContext = new DefaultMuleContextBuilder().buildMuleContext();
244             String workingDirectory = localMuleContext.getConfiguration().getWorkingDirectory();
245             String path = workingDirectory + File.separator + QueuePersistenceObjectStore.DEFAULT_QUEUE_STORE + File.separator + name;
246 
247             File[] filesInQueue = new File(path).listFiles();
248             return filesInQueue.length;
249         }
250     }
251 
252     protected void stopService(Service service) throws Exception
253     {
254         service.stop();
255         muleContext.getRegistry().lookupConnector("outPersistentConnector").stop();
256     }
257 
258     protected void startService(Service service) throws Exception
259     {
260         muleContext.getRegistry().lookupConnector("outPersistentConnector").start();
261         service.start();
262     }
263 
264 }