View Javadoc

1   /*
2    * $Id: ConnectorLifecycleTestCase.java 19327 2010-09-03 13:09:47Z tcarlson $
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.transport;
12  
13  
14  import org.mule.api.MuleException;
15  import org.mule.api.endpoint.InboundEndpoint;
16  import org.mule.api.endpoint.OutboundEndpoint;
17  import org.mule.api.lifecycle.LifecycleException;
18  import org.mule.api.service.Service;
19  import org.mule.api.source.CompositeMessageSource;
20  import org.mule.api.transport.MessageDispatcher;
21  import org.mule.api.transport.MessageRequester;
22  import org.mule.tck.AbstractMuleTestCase;
23  import org.mule.tck.testmodels.mule.TestConnector;
24  
25  import javax.resource.spi.work.Work;
26  import javax.resource.spi.work.WorkException;
27  
28  import junit.framework.Assert;
29  
30  /**
31   * Tests that lifecycle methods on a connector are not processed more than once. (@see MULE-3062)
32   * Also test lifecycle of a connector dispatchers, receivers, workManagers and scheduler.
33   */
34  public class ConnectorLifecycleTestCase extends AbstractMuleTestCase
35  {
36      private TestConnector connector;
37  
38      @Override
39      public void doSetUp() throws Exception
40      {
41          connector = new TestConnector(muleContext);
42          connector.initialise();
43      }
44  
45      @Override
46      public void doTearDown() throws Exception
47      {
48          if(!connector.isDisposed()) connector.dispose();
49          connector = null;
50      }
51  
52      /**
53       * This test ensures that the connector is only initialised once even on a
54       * direct initialisation (not through Mule).
55       *
56       * @throws Exception if things go pear-shaped
57       */
58      public void testDoubleInitialiseConnector() throws Exception
59      {
60          // Note: the connector was already initialized once during doSetUp()
61  
62          // Initialising the connector should leave it disconnected.
63          assertEquals(1, connector.getInitialiseCount());
64          assertEquals(0, connector.getConnectCount());
65          assertEquals(0, connector.getStartCount());
66          assertEquals(0, connector.getStopCount());
67          assertEquals(0, connector.getDisconnectCount());
68          assertEquals(0, connector.getDisposeCount());
69  
70          // Initialising the connector again should not throw an exception.
71          try
72          {
73              connector.initialise();
74              Assert.fail("Expected IllegalStateException not thrown.");
75          }
76          catch (IllegalStateException ex)
77          {
78              // ignore since expected
79          }
80      }
81  
82      /**
83       * This test ensures that the connector is only started once even on a
84       * direct restart (not through Mule).
85       *
86       * @throws Exception if things go pear-shaped
87       */
88      public void testDoubleStartConnector() throws Exception
89      {
90          // Starting the connector should leave it uninitialised,
91          // but connected and started.
92          connector.start();
93          assertEquals(1, connector.getInitialiseCount());
94          assertEquals(1, connector.getConnectCount());
95          assertEquals(1, connector.getStartCount());
96          assertEquals(0, connector.getStopCount());
97          assertEquals(0, connector.getDisconnectCount());
98          assertEquals(0, connector.getDisposeCount());
99  
100         // Starting the connector again
101         try
102         {
103             connector.start();
104             fail("cannot start the connector twice");
105         }
106         catch (IllegalStateException e)
107         {
108             //expected
109         }
110         assertEquals(1, connector.getInitialiseCount());
111         assertEquals(1, connector.getConnectCount());
112         assertEquals(1, connector.getStartCount());
113         assertEquals(0, connector.getStopCount());
114         assertEquals(0, connector.getDisconnectCount());
115         assertEquals(0, connector.getDisposeCount());
116     }
117 
118     /**
119      * This test ensures that the connector is only stopped once even on a
120      * direct restop (not through Mule).
121      *
122      * @throws Exception if things go pear-shaped
123      */
124     public void testDoubleStopConnector() throws Exception
125     {
126         // Starting the connector should leave it uninitialised,
127         // but connected and started.
128         connector.start();
129         assertEquals(1, connector.getInitialiseCount());
130         assertEquals(1, connector.getConnectCount());
131         assertEquals(1, connector.getStartCount());
132         assertEquals(0, connector.getStopCount());
133         assertEquals(0, connector.getDisconnectCount());
134         assertEquals(0, connector.getDisposeCount());
135 
136         assertTrue(connector.isStarted());
137 
138         // Stopping the connector should stop and disconnect it.
139         connector.stop();
140         assertEquals(1, connector.getInitialiseCount());
141         assertEquals(1, connector.getConnectCount());
142         assertEquals(1, connector.getStartCount());
143         assertEquals(1, connector.getStopCount());
144         assertEquals(1, connector.getDisconnectCount());
145         assertEquals(0, connector.getDisposeCount());
146 
147 
148         try
149         {
150             connector.stop();
151             fail("cannot stop the connector twice");
152         }
153         catch (IllegalStateException e)
154         {
155             //expected
156         }
157         assertEquals(1, connector.getInitialiseCount());
158         assertEquals(1, connector.getConnectCount());
159         assertEquals(1, connector.getStartCount());
160         assertEquals(1, connector.getStopCount());
161         assertEquals(1, connector.getDisconnectCount());
162         assertEquals(0, connector.getDisposeCount());
163     }
164 
165     /**
166      * This test ensures that the connector is only disposed once even on a
167      * direct disposal (not through Mule).
168      *
169      * @throws Exception if things go pear-shaped
170      */
171     public void testDoubleDisposeConnectorStartStop() throws Exception
172     {
173         connector.start();
174         assertTrue(connector.isStarted());
175 
176         connector.stop();
177         assertFalse(connector.isStarted());
178 
179         // Disposing the connector should leave it uninitialised.
180         connector.dispose();
181         assertEquals(1, connector.getInitialiseCount());
182         assertEquals(1, connector.getConnectCount());
183         assertEquals(1, connector.getStartCount());
184         assertEquals(1, connector.getStopCount());
185         assertEquals(1, connector.getDisconnectCount());
186         assertEquals(1, connector.getDisposeCount());
187 
188         try
189         {
190             connector.dispose();
191             fail("cannot dispose the connector twice");
192         }
193         catch (IllegalStateException e)
194         {
195             //expected
196         }
197         assertEquals(1, connector.getInitialiseCount());
198         assertEquals(1, connector.getConnectCount());
199         assertEquals(1, connector.getStartCount());
200         assertEquals(1, connector.getStopCount());
201         assertEquals(1, connector.getDisconnectCount());
202         assertEquals(1, connector.getDisposeCount());
203     }
204 
205     /**
206      * This test ensures that the connector is only disposed once even on a
207      * direct disposal (not through Mule).
208      *
209      * @throws Exception if things go pear-shaped
210      */
211     public void testDoubleDisposeConnectorStartOnly() throws Exception
212     {
213         connector.start();
214         assertTrue(connector.isStarted());
215 
216         // Disposing the connector should leave it uninitialised.
217         connector.dispose();
218         assertEquals(1, connector.getInitialiseCount());
219         assertEquals(1, connector.getConnectCount());
220         assertEquals(1, connector.getStartCount());
221         // dispose() implicitly calls stop()
222         assertEquals(1, connector.getStopCount());
223         assertEquals(1, connector.getDisconnectCount());
224         assertEquals(1, connector.getDisposeCount());
225 
226         try
227         {
228             connector.dispose();
229             fail("cannot dispose the connector twice");
230         }
231         catch (IllegalStateException e)
232         {
233             //expected
234         }
235         assertEquals(1, connector.getInitialiseCount());
236         assertEquals(1, connector.getConnectCount());
237         assertEquals(1, connector.getStartCount());
238         // dispose() implicitly calls stop()
239         assertEquals(1, connector.getStopCount());
240         assertEquals(1, connector.getDisconnectCount());
241         assertEquals(1, connector.getDisposeCount());
242     }
243 
244     /**
245      * This test ensures that the connector is only disposed once even on a
246      * direct disposal (not through Mule).
247      *
248      * @throws Exception if things go pear-shaped
249      */
250     public void testDoubleDisposeConnector() throws Exception
251     {
252         // Disposing the connector should leave it uninitialised.
253         connector.dispose();
254         assertEquals(1, connector.getInitialiseCount());
255         assertEquals(0, connector.getConnectCount());
256         assertEquals(0, connector.getStartCount());
257         assertEquals(0, connector.getStopCount());
258         assertEquals(0, connector.getDisconnectCount());
259         assertEquals(1, connector.getDisposeCount());
260 
261         try
262         {
263             connector.dispose();
264             fail("cannot dispose the connector twice");
265         }
266         catch (IllegalStateException e)
267         {
268             //expected
269         }
270         assertEquals(1, connector.getInitialiseCount());
271         assertEquals(0, connector.getConnectCount());
272         assertEquals(0, connector.getStartCount());
273         assertEquals(0, connector.getStopCount());
274         assertEquals(0, connector.getDisconnectCount());
275         assertEquals(1, connector.getDisposeCount());
276     }
277 
278     public void testReceiversLifecycle() throws Exception
279     {
280         Service service=getTestService();
281         service.start();
282         connector.registerListener(getTestInboundEndpoint("in", "test://in"), getSensingNullMessageProcessor(), service);
283 
284         assertEquals(1, connector.receivers.size());
285         assertFalse(( connector.receivers.get("in")).isConnected());
286         assertFalse(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
287 
288         connector.start();
289         assertTrue(( connector.receivers.get("in")).isConnected());
290         assertTrue(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
291 
292         connector.registerListener(getTestInboundEndpoint("in2", "test://in2"), getSensingNullMessageProcessor(), service);
293 
294         assertEquals(2, connector.receivers.size());
295         assertTrue(( connector.receivers.get("in")).isConnected());
296         assertTrue(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
297 
298         assertTrue((connector.receivers.get("in2")).isConnected());
299         assertTrue(((AbstractMessageReceiver)connector.receivers.get("in2")).isStarted());
300 
301         connector.stop();
302         assertEquals(2, connector.receivers.size());
303         assertFalse(( connector.receivers.get("in")).isConnected());
304         assertFalse(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
305         assertFalse(( connector.receivers.get("in2")).isConnected());
306         assertFalse(((AbstractMessageReceiver) connector.receivers.get("in2")).isStarted());
307 
308         connector.start();
309         assertEquals(2, connector.receivers.size());
310         assertTrue((connector.receivers.get("in")).isConnected());
311         assertTrue(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
312         assertTrue((connector.receivers.get("in2")).isConnected());
313         assertTrue(((AbstractMessageReceiver) connector.receivers.get("in2")).isStarted());
314 
315         connector.dispose();
316         assertEquals(0, connector.receivers.size());
317 
318     }
319 
320     public void testReceiversServiceLifecycle() throws Exception
321     {
322         Service service = getTestService();
323         InboundEndpoint endpoint = getTestInboundEndpoint("in", "test://in");
324         ((CompositeMessageSource) service.getMessageSource()).addSource(endpoint);
325         connector = (TestConnector) endpoint.getConnector();
326 
327         assertEquals(0, connector.receivers.size());
328 
329         connector.start();
330         assertEquals(0, connector.receivers.size());
331 
332         service.start();
333         assertEquals(1, connector.receivers.size());
334         assertTrue(( connector.receivers.get("in")).isConnected());
335         assertTrue(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
336 
337         connector.stop();
338         assertEquals(1, connector.receivers.size());
339         assertFalse(( connector.receivers.get("in")).isConnected());
340         assertFalse(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
341 
342         connector.start();
343         assertEquals(1, connector.receivers.size());
344         assertTrue(( connector.receivers.get("in")).isConnected());
345         assertTrue(((AbstractMessageReceiver) connector.receivers.get("in")).isStarted());
346 
347         service.stop();
348         assertEquals(0, connector.receivers.size());
349 
350         connector.stop();
351         assertEquals(0, connector.receivers.size());
352     }
353 
354     public void testDispatchersLifecycle() throws Exception
355     {
356         //using sync endpoint so that any calls to 'process()' will be blocking and avoid timing issues
357         OutboundEndpoint out = getTestOutboundEndpoint("out", 
358             "test://out?exchangePattern=request-response", null, null, null, connector);
359 
360         // attempts to send/dispatch/request are made on a stopped/stopping connector
361         // This should fail because the connector is not started!
362         try
363         {
364             out.process(getTestEvent("data"));
365             fail("cannot send on a connector that is not started");
366         }
367         catch (LifecycleException e)
368         {
369             // expected
370         }
371 
372         assertEquals(0, connector.dispatchers.getNumIdle());
373 
374         // Dispatcher is not started or connected
375         assertDispatcherStartedConnected(out, false, false);
376 
377         connector.start();
378         //This causes the first instance out dispatcher to be created
379         assertDispatcherStartedConnected(out, true, true);
380 
381         OutboundEndpoint out2 = getTestOutboundEndpoint("out2", 
382             "test://out2?exchangePattern=request-response", null, null, null, connector);
383         //This causes the first instance out2 dispatcher to be created
384         out2.process(getTestEvent("data", out2));
385 
386         //At this point there should be two idle, but the build server reports one, I suspect its a timing issues
387         assertEquals(2, connector.dispatchers.getNumIdle());
388         assertDispatcherStartedConnected(out, true, true);
389         assertDispatcherStartedConnected(out2, true, true);
390 
391         connector.stop();
392 
393         // Pool is cleared because of implementation of workaround for MULE-4553
394         assertEquals(0, connector.dispatchers.getNumActive() + connector.dispatchers.getNumIdle());
395         assertDispatcherStartedConnected(out, false, false);
396         assertDispatcherStartedConnected(out2, false, false);
397 
398         connector.start();
399 
400         assertEquals(2, connector.dispatchers.getNumActive() + connector.dispatchers.getNumIdle());
401         assertDispatcherStartedConnected(out, true, true);
402         assertDispatcherStartedConnected(out2, true, true);
403 
404         out.process(getTestEvent("data", out));
405         assertEquals(2, connector.dispatchers.getNumIdle());
406         assertDispatcherStartedConnected(out, true, true);
407 
408         connector.dispose();
409         assertEquals(0, connector.dispatchers.getNumActive() + connector.dispatchers.getNumIdle());
410 
411     }
412 
413     public void testDispatcherFullLifecycle() throws Exception
414     {
415         OutboundEndpoint out = getTestOutboundEndpoint("out", "test://out", null, null, null, connector);
416 
417         MessageDispatcher dispatcher = connector.getDispatcherFactory().create(out);
418         dispatcher.initialise();
419         
420         assertTrue(dispatcher.getLifecycleState().isInitialised());
421         dispatcher.connect();
422         assertTrue(dispatcher.isConnected());
423 
424         dispatcher.start();
425         assertTrue(dispatcher.getLifecycleState().isStarted());
426 
427         dispatcher.stop();
428         assertTrue(dispatcher.getLifecycleState().isStopped());
429 
430         dispatcher.disconnect();
431         assertFalse(dispatcher.isConnected());
432 
433         dispatcher.dispose();
434         assertTrue(dispatcher.getLifecycleState().isDisposed());
435 
436     }
437 
438     public void testRequestersLifecycle() throws Exception
439     {
440         InboundEndpoint in = getTestInboundEndpoint("in", "test://in", null, null, null, connector);
441 
442         // attempts to send/dispatch/request are made on a stopped/stopping connector
443         // This should fail because the connector is not started!
444         try
445         {
446             in.request(1000L);
447             fail("cannot sent on a connector that is not started");
448         }
449         catch (LifecycleException e)
450         {
451             //Expected
452         }
453 
454 
455         assertEquals(0, connector.requesters.getNumIdle());
456 
457         // Dispatcher is not started or connected
458         assertRequesterStartedConnected(in, false, false);
459 
460         connector.start();
461         assertRequesterStartedConnected(in, true, true);
462 
463         assertEquals(1, connector.requesters.getNumIdle());
464 
465         InboundEndpoint in2 = getTestInboundEndpoint("in2", "test://in2", null, null, null, connector);
466         in2.request(1000L);
467 
468 
469         assertEquals(2, connector.requesters.getNumIdle());
470         assertRequesterStartedConnected(in, true, true);
471         assertRequesterStartedConnected(in2, true, true);
472 
473         connector.stop();
474 
475         // Pool is cleared because of implementation of workaround for MULE-4553
476         assertEquals(0, connector.requesters.getNumActive() + connector.requesters.getNumIdle());
477         assertRequesterStartedConnected(in, false, false);
478         assertRequesterStartedConnected(in2, false, false);
479 
480         connector.start();
481         //Between Stop and start the requester pool maintains existing pooled objects
482         assertEquals(2, connector.requesters.getNumActive() + connector.requesters.getNumIdle());
483         assertRequesterStartedConnected(in, true, true);
484         assertRequesterStartedConnected(in2, true, true);
485 
486         in.request(1000L);
487         assertEquals(2, connector.requesters.getNumIdle());
488         assertRequesterStartedConnected(in, true, true);
489 
490         connector.dispose();
491         assertEquals(0, connector.requesters.getNumActive() + connector.requesters.getNumIdle());
492 
493     }
494 
495     public void testRequesterFullLifecycle() throws Exception
496     {
497         InboundEndpoint in = getTestInboundEndpoint("out", "test://out", null, null, null, connector);
498 
499         MessageRequester requester = connector.getRequesterFactory().create(in);
500 
501         requester.initialise();
502         assertTrue(requester.getLifecycleState().isInitialised());
503 
504         requester.connect();
505         assertTrue(requester.isConnected());
506 
507         requester.start();
508         assertTrue(requester.getLifecycleState().isStarted());
509 
510         requester.stop();
511         assertTrue(requester.getLifecycleState().isStopped());
512 
513         requester.disconnect();
514         assertFalse(requester.isConnected());
515 
516         requester.dispose();
517         assertTrue(requester.getLifecycleState().isDisposed());
518 
519     }
520 
521     public void testWorkManagerLifecycle() throws MuleException, WorkException
522     {
523         //ConnectorLifecycleTestCase These are now created in the "initialize" phase
524         //   assertNull(connector.getReceiverWorkManager());
525         //   assertNull(connector.getDispatcherWorkManager());
526         //   assertNull(connector.getRequesterWorkManager());
527 
528         connector.start();
529         assertNotNull(connector.getReceiverWorkManager());
530         assertNotNull(connector.getDispatcherWorkManager());
531         assertNotNull(connector.getRequesterWorkManager());
532         connector.getReceiverWorkManager().doWork(createSomeWork());
533         connector.getDispatcherWorkManager().doWork(createSomeWork());
534         connector.getRequesterWorkManager().doWork(createSomeWork());
535 
536         connector.stop();
537         assertNull(connector.getReceiverWorkManager());
538         assertNull(connector.getDispatcherWorkManager());
539         assertNull(connector.getRequesterWorkManager());
540 
541         connector.start();
542         assertNotNull(connector.getReceiverWorkManager());
543         assertNotNull(connector.getDispatcherWorkManager());
544         assertNotNull(connector.getRequesterWorkManager());
545         connector.getReceiverWorkManager().doWork(createSomeWork());
546         connector.getDispatcherWorkManager().doWork(createSomeWork());
547         connector.getRequesterWorkManager().doWork(createSomeWork());
548 
549         connector.dispose();
550         assertNull(connector.getReceiverWorkManager());
551         assertNull(connector.getDispatcherWorkManager());
552         assertNull(connector.getRequesterWorkManager());
553     }
554 
555     public void testSchedulerLifecycle() throws MuleException, WorkException
556     {
557         assertNull(connector.getScheduler());
558 
559         connector.start();
560         assertFalse(connector.getScheduler().isShutdown());
561         assertFalse(connector.getScheduler().isTerminated());
562 
563         connector.stop();
564         assertNull(connector.getScheduler());
565 
566         connector.start();
567         assertFalse(connector.getScheduler().isShutdown());
568         assertFalse(connector.getScheduler().isTerminated());
569 
570         connector.dispose();
571         assertNull(connector.getScheduler());
572     }
573 
574     protected Work createSomeWork()
575     {
576         return new Work()
577         {
578             public void run()
579             {
580                 System.out.println("I'm doing some work");
581             }
582 
583             public void release()
584             {
585                 // nothing to do
586             }
587         };
588     }
589 
590     private void assertDispatcherStartedConnected(OutboundEndpoint out, boolean started, boolean connected)
591             throws Exception
592     {
593         AbstractMessageDispatcher dispatcher = (AbstractMessageDispatcher) connector.dispatchers.borrowObject(out);
594         assertEquals("Dispatcher started", started, dispatcher.isStarted());
595         assertEquals("Dispatcher connected", connected, dispatcher.isConnected());
596         connector.dispatchers.returnObject(out, dispatcher);
597     }
598 
599     private void assertRequesterStartedConnected(InboundEndpoint in, boolean started, boolean connected)
600             throws Exception
601     {
602         AbstractMessageRequester requester = (AbstractMessageRequester) connector.requesters.borrowObject(in);
603         assertEquals("Requester started", started, requester.isStarted());
604         assertEquals("requester connected", connected, requester.isConnected());
605         connector.requesters.returnObject(in, requester);
606     }
607 }