View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.tck;
8   
9   import org.mule.MessageExchangePattern;
10  import org.mule.RequestContext;
11  import org.mule.api.MuleContext;
12  import org.mule.api.MuleEvent;
13  import org.mule.api.MuleEventContext;
14  import org.mule.api.MuleSession;
15  import org.mule.api.config.ConfigurationBuilder;
16  import org.mule.api.context.MuleContextBuilder;
17  import org.mule.api.context.MuleContextFactory;
18  import org.mule.api.context.notification.MuleContextNotificationListener;
19  import org.mule.api.endpoint.ImmutableEndpoint;
20  import org.mule.api.endpoint.InboundEndpoint;
21  import org.mule.api.endpoint.OutboundEndpoint;
22  import org.mule.api.processor.MessageProcessor;
23  import org.mule.api.registry.RegistrationException;
24  import org.mule.api.routing.filter.Filter;
25  import org.mule.api.service.Service;
26  import org.mule.api.transformer.Transformer;
27  import org.mule.api.transport.Connector;
28  import org.mule.config.DefaultMuleConfiguration;
29  import org.mule.config.builders.DefaultsConfigurationBuilder;
30  import org.mule.config.builders.SimpleConfigurationBuilder;
31  import org.mule.context.DefaultMuleContextBuilder;
32  import org.mule.context.DefaultMuleContextFactory;
33  import org.mule.context.notification.MuleContextNotification;
34  import org.mule.tck.testmodels.mule.TestConnector;
35  import org.mule.util.ClassUtils;
36  import org.mule.util.FileUtils;
37  import org.mule.util.IOUtils;
38  import org.mule.util.MuleUrlStreamHandlerFactory;
39  import org.mule.util.StringMessageUtils;
40  import org.mule.util.StringUtils;
41  import org.mule.util.SystemUtils;
42  import org.mule.util.concurrent.Latch;
43  
44  import java.io.IOException;
45  import java.io.InputStream;
46  import java.net.URL;
47  import java.net.URLClassLoader;
48  import java.util.ArrayList;
49  import java.util.Collections;
50  import java.util.HashMap;
51  import java.util.HashSet;
52  import java.util.Iterator;
53  import java.util.List;
54  import java.util.Map;
55  import java.util.Properties;
56  import java.util.Set;
57  import java.util.concurrent.atomic.AtomicReference;
58  
59  import junit.framework.TestCase;
60  import junit.framework.TestResult;
61  
62  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
63  
64  import org.apache.commons.collections.IteratorUtils;
65  import org.apache.commons.collections.Predicate;
66  import org.apache.commons.logging.Log;
67  import org.apache.commons.logging.LogFactory;
68  
69  /**
70   * <code>AbstractMuleTestCase</code> is a base class for Mule testcases. This
71   * implementation provides services to test code for creating mock and test objects.
72   * @Deprecated Use {@link org.mule.tck.junit4.AbstractMuleTestCase}
73   */
74  @Deprecated
75  public abstract class AbstractMuleTestCase extends TestCase implements TestCaseWatchdogTimeoutHandler
76  {
77  
78      /**
79       * Top-level directories under <code>.mule</code> which are not deleted on each
80       * test case recycle. This is required, e.g. to play nice with transaction manager
81       * recovery service object store.
82       */
83      public static final String[] IGNORED_DOT_MULE_DIRS = new String[]{"transaction-log"};
84  
85      /**
86       * Name of a property to override the default test watchdog timeout.
87       *
88       * @see #DEFAULT_MULE_TEST_TIMEOUT_SECS
89       */
90      public static final String PROPERTY_MULE_TEST_TIMEOUT = "mule.test.timeoutSecs";
91  
92      /**
93       * Default test watchdog timeout in seconds.
94       */
95      public static final int DEFAULT_MULE_TEST_TIMEOUT_SECS = 60;
96  
97      /**
98       * If the annotations module is on the classpath, also enable annotations config builder
99       */
100     public static final String CLASSNAME_ANNOTATIONS_CONFIG_BUILDER = "org.mule.config.AnnotationsConfigurationBuilder";
101 
102 
103     protected static MuleContext muleContext;
104 
105     /**
106      * This flag controls whether the text boxes will be logged when starting each test case.
107      */
108     private static final boolean verbose;
109 
110     // A Map of test case extension objects. JUnit creates a new TestCase instance for
111     // every method, so we need to record metainfo outside the test.
112     private static final Map<String, TestInfo> testInfos = Collections.synchronizedMap(new HashMap<String, TestInfo>());
113 
114     // A logger that should be suitable for most test cases.
115     protected final transient Log logger = LogFactory.getLog(this.getClass());
116 
117     /**
118      * Start the muleContext once it's configured (defaults to false for AbstractMuleTestCase, true for FunctionalTestCase).
119      */
120     private boolean startContext = false;
121 
122     // Should be set to a string message describing any prerequisites not met.
123     private boolean offline = "true".equalsIgnoreCase(System.getProperty("org.mule.offline"));
124 
125     // Barks if the test exceeds its time limit
126     private TestCaseWatchdog watchdog;
127 
128     protected int numPorts = 0;
129     
130     public List<Integer> ports = null;   
131     
132     static
133     {
134         String muleOpts = SystemUtils.getenv("MULE_TEST_OPTS");
135         if (StringUtils.isNotBlank(muleOpts))
136         {
137             Map<String, String> parsedOpts = SystemUtils.parsePropertyDefinitions(muleOpts);
138             String optVerbose = parsedOpts.get("mule.verbose");
139             verbose = Boolean.valueOf(optVerbose);
140         }
141         else
142         {
143             // per default, revert to the old behaviour
144             verbose = true;
145         }
146 
147         // register the custom UrlStreamHandlerFactory.
148         MuleUrlStreamHandlerFactory.installUrlStreamHandlerFactory();
149     }
150 
151     /**
152      * Convenient test message for unit testing.
153      */
154     public static final String TEST_MESSAGE = "Test Message";
155 
156     /**
157      * Default timeout for multithreaded tests (using CountDownLatch, WaitableBoolean, etc.),
158      * in milliseconds.  The higher this value, the more reliable the test will be, so it
159      * should be set high for Continuous Integration.  However, this can waste time during
160      * day-to-day development cycles, so you may want to temporarily lower it while debugging.
161      */
162     public static final long LOCK_TIMEOUT = 30000;
163 
164     /**
165      * Default timeout for waiting for responses
166      */
167     public static final int RECEIVE_TIMEOUT = 5000;
168 
169     /**
170      * Use this as a semaphore to the unit test to indicate when a callback has successfully been called.
171      */
172     protected Latch callbackCalled;
173 
174     /**
175      * Timeout used for the test watchdog
176      */
177     protected int testTimeoutSecs = DEFAULT_MULE_TEST_TIMEOUT_SECS;
178 
179     /**
180      * When a test case depends on a 3rd-party resource such as a public web service,
181      * it may be desirable to not fail the test upon timeout but rather to simply log
182      * a warning.
183      */
184     private boolean failOnTimeout = true;
185 
186     /**
187      * This is just a reference to the main thread running the current thread. It is
188      * set in the {@link #setUp()} method.
189      */
190     private volatile Thread currentTestRunningThread;
191 
192     public AbstractMuleTestCase()
193     {
194         super();
195 
196         TestInfo info = getTestInfo();
197         if (info == null)
198         {
199             info = this.createTestInfo();
200             testInfos.put(getClass().getName(), info);
201         }
202         registerTestMethod();
203         initTestTimeoutSecs();
204     }
205 
206     protected void registerTestMethod()
207     {
208         if (this.getName() != null)
209         {
210             this.getTestInfo().incTestCount(getName());
211         }
212     }
213 
214     protected void initTestTimeoutSecs()
215     {
216         String timeoutString = System.getProperty(PROPERTY_MULE_TEST_TIMEOUT, null);
217         if (timeoutString == null)
218         {
219             // unix style: MULE_TEST_TIMEOUTSECS
220             String variableName = PROPERTY_MULE_TEST_TIMEOUT.toUpperCase().replace(".", "_");
221             timeoutString = System.getenv(variableName);
222         }
223 
224         if (timeoutString != null)
225         {
226             try
227             {
228                 testTimeoutSecs = Integer.parseInt(timeoutString);
229             }
230             catch (NumberFormatException nfe)
231             {
232                 // the default still applies
233             }
234         }
235     }
236 
237     @Override
238     public void setName(String name)
239     {
240         super.setName(name);
241         registerTestMethod();
242     }
243 
244     protected TestInfo createTestInfo()
245     {
246         return new TestInfo(this);
247     }
248 
249     protected TestInfo getTestInfo()
250     {
251         return testInfos.get(this.getClass().getName());
252     }
253 
254     private void clearInfo()
255     {
256         testInfos.remove(this.getClass().getName());
257     }
258 
259     @Override
260     public void run(TestResult result)
261     {
262         if (this.isExcluded())
263         {
264             if (verbose)
265             {
266                 logger.info(this.getClass().getName() + " excluded");
267             }
268             return;
269         }
270 
271         if (this.isDisabledInThisEnvironment())
272         {
273             if (verbose)
274             {
275                 logger.info(this.getClass().getName() + " disabled");
276             }
277             return;
278         }
279 
280         super.run(result);
281     }
282 
283     /**
284      * Shamelessly copy from Spring's ConditionalTestCase so in MULE-2.0 we can extend
285      * this class from ConditionalTestCase.
286      * <p/>
287      * Subclasses can override <code>isDisabledInThisEnvironment</code> to skip a single test.
288      */
289     @Override
290     public void runBare() throws Throwable
291     {
292         // getName will return the name of the method being run. Use the real JUnit implementation,
293         // this class has a different implementation
294         if (this.isDisabledInThisEnvironment(super.getName()))
295         {
296             logger.warn(this.getClass().getName() + "." + super.getName() + " disabled in this environment");
297             return;
298         }
299 
300         // Let JUnit handle execution
301         super.runBare();
302     }
303 
304     /**
305      * Subclasses can override this method to skip the execution of the entire test class.
306      *
307      * @return <code>true</code> if the test class should not be run.
308      */
309     protected boolean isDisabledInThisEnvironment()
310     {
311         return false;
312     }
313 
314     /**
315      * Indicates whether this test has been explicitly disabled through the configuration
316      * file loaded by TestInfo.
317      *
318      * @return whether the test has been explicitly disabled
319      */
320     protected boolean isExcluded()
321     {
322         return getTestInfo().isExcluded();
323     }
324 
325     /**
326      * Should this test run?
327      *
328      * @param testMethodName name of the test method
329      * @return whether the test should execute in the current envionment
330      */
331     protected boolean isDisabledInThisEnvironment(String testMethodName)
332     {
333         return false;
334     }
335 
336     public boolean isOffline(String method)
337     {
338         if (offline)
339         {
340             logger.warn(StringMessageUtils.getBoilerPlate(
341                     "Working offline cannot run test: " + method, '=', 80));
342         }
343         return offline;
344     }
345 
346     protected boolean isDisposeManagerPerSuite()
347     {
348         return getTestInfo().isDisposeManagerPerSuite();
349     }
350 
351     protected void setDisposeManagerPerSuite(boolean val)
352     {
353         getTestInfo().setDisposeManagerPerSuite(val);
354     }
355 
356     public int getTestTimeoutSecs()
357     {
358         return testTimeoutSecs;
359     }
360 
361     protected TestCaseWatchdog createWatchdog()
362     {
363         return new TestCaseWatchdog(testTimeoutSecs, TimeUnit.SECONDS, this);
364     }
365 
366     public void handleTimeout(long timeout, TimeUnit unit)
367     {
368         String msg = "Timeout of " + unit.toMillis(timeout) + "ms exceeded (modify via -Dmule.test.timeoutSecs=XX)";
369 
370         if (failOnTimeout)
371         {
372             logger.fatal(msg + " - Attempting to interrupt thread for test " + this.getName());
373             if (currentTestRunningThread != null)
374             {
375                 currentTestRunningThread.interrupt();
376             }
377             giveTheTestSomeTimeToCleanUpAndThenKillIt("Interrupting didn't work. Killing the VM!. Test "
378                                                       + this.getName() + " did not finish correctly.");
379         }
380         else
381         {
382             logger.warn(msg);
383         }
384     }
385 
386     protected void giveTheTestSomeTimeToCleanUpAndThenKillIt(String messageIfNeedToKill)
387     {
388         try
389         {
390             Thread.sleep(5000);
391             logger.fatal(messageIfNeedToKill);
392             Runtime.getRuntime().halt(1);
393         }
394         catch (InterruptedException e)
395         {
396             logger.info(
397                 "Test thread has been interrupted, probably bt the call to watchdog.cancel() in teardown method.",
398                 e);
399         }
400     }
401 
402     /**
403      * Normal JUnit method
404      *
405      * @throws Exception
406      * @see #doSetUp()
407      */
408     @Override
409     protected final void setUp() throws Exception
410     {
411         // start a watchdog thread
412         watchdog = createWatchdog();
413         watchdog.start();
414        
415         // set up the free ports
416         if (numPorts > 0)
417         {
418             //find some free ports
419             ports = PortUtils.findFreePorts(numPorts);
420 
421             //set the port properties
422             setPortProperties();
423         }                
424         
425         currentTestRunningThread = Thread.currentThread();
426 
427         if (verbose)
428         {
429             System.out.println(StringMessageUtils.getBoilerPlate("Testing: " + getName(), '=', 80));
430         }
431 
432         try
433         {
434             if (getTestInfo().getRunCount() == 0)
435             {
436                 if (getTestInfo().isDisposeManagerPerSuite())
437                 {
438                     // We dispose here jut in case
439                     disposeManager();
440                 }
441                 suitePreSetUp();
442             }
443             if (!getTestInfo().isDisposeManagerPerSuite())
444             {
445                 // We dispose here just in case
446                 disposeManager();
447             }
448             
449             muleContext = createMuleContext();
450 
451             // wait for Mule to fully start when requested (default)
452 
453             // latch ref needs to be final for listener use, wrap in atomic ref
454             final AtomicReference<Latch> contextStartedLatch = new AtomicReference<Latch>();
455             if (isStartContext() && null != muleContext && muleContext.isStarted() == false)
456             {
457                 contextStartedLatch.set(new Latch());
458                 muleContext.registerListener(new MuleContextNotificationListener<MuleContextNotification>()
459                 {
460                     public void onNotification(MuleContextNotification notification)
461                     {
462                         if (notification.getAction() == MuleContextNotification.CONTEXT_STARTED)
463                         {
464                             contextStartedLatch.get().countDown();
465                         }
466                     }
467                 });
468                 muleContext.start();
469             }
470 
471             // if it's null, than
472             if (contextStartedLatch.get() != null)
473             {
474                 // wait no more than 20 secs
475                 contextStartedLatch.get().await(20, TimeUnit.SECONDS);
476             }
477             doSetUp();
478         }
479         catch (Exception e)
480         {
481             getTestInfo().incRunCount();
482             throw e;
483         }
484     }
485 
486     protected MuleContext createMuleContext() throws Exception
487     {
488         // Should we set up the manager for every method?
489         MuleContext context;
490         if (getTestInfo().isDisposeManagerPerSuite() && muleContext != null)
491         {
492             context = muleContext;
493         }
494         else
495         {
496             MuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
497             List<ConfigurationBuilder> builders = new ArrayList<ConfigurationBuilder>();
498             builders.add(new SimpleConfigurationBuilder(getStartUpProperties()));
499             //If the annotations module is on the classpath, add the annotations config builder to the list
500             //This will enable annotations config for this instance
501             if (ClassUtils.isClassOnPath(CLASSNAME_ANNOTATIONS_CONFIG_BUILDER, getClass()))
502             {
503                 builders.add((ConfigurationBuilder) ClassUtils.instanciateClass(CLASSNAME_ANNOTATIONS_CONFIG_BUILDER,
504                         ClassUtils.NO_ARGS, getClass()));
505             }
506             builders.add(getBuilder());
507             addBuilders(builders);
508             MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
509             configureMuleContext(contextBuilder);
510             context = muleContextFactory.createMuleContext(builders, contextBuilder);
511             if (!isGracefulShutdown())
512             {
513                 ((DefaultMuleConfiguration) context.getConfiguration()).setShutdownTimeout(0);
514             }
515         }
516         return context;
517     }
518 
519     //This sohuldn't be needed by Test cases but can be used by base testcases that wish to add further builders when
520     //creating the MuleContext.
521 
522     protected void addBuilders(List<ConfigurationBuilder> builders)
523     {
524         //No op
525     }
526 
527     /**
528      * Override this method to set properties of the MuleContextBuilder before it is
529      * used to create the MuleContext.
530      */
531     protected void configureMuleContext(MuleContextBuilder contextBuilder)
532     {
533         contextBuilder.setWorkListener(new TestingWorkListener());
534     }
535 
536     protected ConfigurationBuilder getBuilder() throws Exception
537     {
538         return new DefaultsConfigurationBuilder();
539     }
540 
541     protected String getConfigurationResources()
542     {
543         return StringUtils.EMPTY;
544     }
545 
546     protected Properties getStartUpProperties()
547     {
548         return null;
549     }
550 
551     /**
552      * Run <strong>before</strong> any testcase setup.
553      * This is called once only before the test suite runs.
554      */
555     protected void suitePreSetUp() throws Exception
556     {
557         // nothing to do
558     }
559 
560     /**
561      * Run <strong>after</strong> all testcase teardowns.
562      * This is called once only after all the tests in the suite have run.
563      */
564     protected void suitePostTearDown() throws Exception
565     {
566         // nothing to do
567     }
568 
569     /**
570      * Normal JUnit method
571      *
572      * @throws Exception
573      * @see #doTearDown()
574      */
575     @Override
576     protected final void tearDown() throws Exception
577     {
578         try
579         {
580             doTearDown();
581 
582             if (!getTestInfo().isDisposeManagerPerSuite())
583             {
584                 disposeManager();
585             }
586         }
587         finally
588         {
589             try
590             {
591                 getTestInfo().incRunCount();
592                 if (getTestInfo().getRunCount() == getTestInfo().getTestCount())
593                 {
594                     try
595                     {
596                         suitePostTearDown();
597                     }
598                     finally
599                     {
600                         clearInfo();
601                         disposeManager();
602                     }
603                 }
604             }
605             finally
606             {
607                 // remove the watchdog thread in any case
608                 watchdog.cancel();
609             }
610         }
611     }
612 
613     protected void disposeManager()
614     {
615         try
616         {
617             if (muleContext != null && !(muleContext.isDisposed() || muleContext.isDisposing()))
618             {
619                 muleContext.dispose();
620 
621                 final String workingDir = muleContext.getConfiguration().getWorkingDirectory();
622                 // do not delete TM recovery object store, everything else is good to
623                 // go
624                 FileUtils.deleteTree(FileUtils.newFile(workingDir), IGNORED_DOT_MULE_DIRS);
625             }
626             FileUtils.deleteTree(FileUtils.newFile("./ActiveMQ"));
627         }
628         finally
629         {
630             muleContext = null;
631         }
632     }
633 
634     /**
635      * Exactly the same a {@link #setUp()} in normal JUnit test cases.  this is called <strong>before</strong> a test
636      * method has been called.
637      *
638      * @throws Exception if something fails that should halt the testcase
639      */
640     protected void doSetUp() throws Exception
641     {
642         // template method
643     }
644 
645     /**
646      * Exactly the same a {@link #tearDown()} in normal JUnit test cases.  this is called <strong>after</strong> a test
647      * method has been called.
648      *
649      * @throws Exception if something fails that should halt the testcase
650      */
651     protected void doTearDown() throws Exception
652     {
653         RequestContext.clear();
654     }
655 
656     public static InboundEndpoint getTestInboundEndpoint(String name) throws Exception
657     {
658         return MuleTestUtils.getTestInboundEndpoint(name, muleContext);
659     }
660 
661     public static OutboundEndpoint getTestOutboundEndpoint(String name) throws Exception
662     {
663         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext);
664     }
665 
666     public static InboundEndpoint getTestInboundEndpoint(MessageExchangePattern mep) throws Exception
667     {
668         return MuleTestUtils.getTestInboundEndpoint(mep, muleContext);
669     }
670 
671     public static InboundEndpoint getTestTransactedInboundEndpoint(MessageExchangePattern mep) throws Exception
672     {
673         return MuleTestUtils.getTestTransactedInboundEndpoint(mep, muleContext);
674     }
675 
676     public static InboundEndpoint getTestInboundEndpoint(String name, String uri) throws Exception
677     {
678         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, uri, null, null, null, null);
679     }
680 
681     public static OutboundEndpoint getTestOutboundEndpoint(String name, String uri) throws Exception
682     {
683         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, uri, null, null, null);
684     }
685 
686     public static InboundEndpoint getTestInboundEndpoint(String name, List<Transformer> transformers) throws Exception
687     {
688         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, null, transformers, null, null, null);
689     }
690 
691     public static OutboundEndpoint getTestOutboundEndpoint(String name, List<Transformer> transformers) throws Exception
692     {
693         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, null, transformers, null, null);
694     }
695 
696     public static InboundEndpoint getTestInboundEndpoint(String name, String uri, 
697         List<Transformer> transformers, Filter filter, Map<Object, Object> properties, Connector connector) throws Exception
698     {
699         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, uri, transformers, filter, properties, connector);
700     }
701 
702     public static OutboundEndpoint getTestOutboundEndpoint(String name, String uri, 
703         List<Transformer> transformers, Filter filter, Map<Object, Object> properties) throws Exception
704     {
705         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, uri, transformers, filter, properties);
706     }
707 
708     public static OutboundEndpoint getTestOutboundEndpoint(String name, String uri, 
709         List<Transformer> transformers, Filter filter, Map<Object, Object> properties, Connector connector) throws Exception
710     {
711         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, uri, transformers, filter, properties, connector);
712     }
713 
714     public static MuleEvent getTestEvent(Object data, Service service) throws Exception
715     {
716         return MuleTestUtils.getTestEvent(data, service, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
717     }
718 
719     public static MuleEvent getTestEvent(Object data, Service service, MessageExchangePattern mep) throws Exception
720     {
721         return MuleTestUtils.getTestEvent(data, service, mep, muleContext);
722     }
723 
724     public static MuleEvent getTestEvent(Object data) throws Exception
725     {
726         return MuleTestUtils.getTestEvent(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
727     }
728     
729     public static MuleEvent getTestEventUsingFlow(Object data) throws Exception
730     {
731         return MuleTestUtils.getTestEventUsingFlow(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
732     }
733 
734     public static MuleEvent getTestEvent(Object data, MessageExchangePattern mep) throws Exception
735     {
736         return MuleTestUtils.getTestEvent(data, mep, muleContext);
737     }
738 
739     public static MuleEvent getTestInboundEvent(Object data, MuleSession session) throws Exception
740     {
741         return MuleTestUtils.getTestInboundEvent(data, session, muleContext);
742     }
743 
744     public static MuleEvent getTestInboundEvent(Object data) throws Exception
745     {
746         return MuleTestUtils.getTestInboundEvent(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
747     }
748 
749     public static MuleEvent getTestInboundEvent(Object data, MessageExchangePattern mep) throws Exception
750     {
751         return MuleTestUtils.getTestInboundEvent(data, mep, muleContext);
752     }
753 
754     public static MuleEventContext getTestEventContext(Object data) throws Exception
755     {
756         return MuleTestUtils.getTestEventContext(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
757     }
758 
759     public static MuleEventContext getTestEventContext(Object data, MessageExchangePattern mep) throws Exception
760     {
761         return MuleTestUtils.getTestEventContext(data, mep, muleContext);
762     }
763 
764     public static Transformer getTestTransformer() throws Exception
765     {
766         return MuleTestUtils.getTestTransformer();
767     }
768 
769     public static MuleEvent getTestEvent(Object data, ImmutableEndpoint endpoint) throws Exception
770     {
771         return MuleTestUtils.getTestEvent(data, endpoint, muleContext);
772     }
773 
774     public static MuleEvent getTestEvent(Object data, Service service, ImmutableEndpoint endpoint)
775             throws Exception
776     {
777         return MuleTestUtils.getTestEvent(data, service, endpoint, muleContext);
778     }
779 
780     public static MuleSession getTestSession(Service service, MuleContext context)
781     {
782         return MuleTestUtils.getTestSession(service, context);
783     }
784 
785     public static TestConnector getTestConnector() throws Exception
786     {
787         return MuleTestUtils.getTestConnector(muleContext);
788     }
789 
790     public static Service getTestService() throws Exception
791     {
792         return MuleTestUtils.getTestService(muleContext);
793     }
794 
795     public static Service getTestService(String name, Class<?> clazz) throws Exception
796     {
797         return MuleTestUtils.getTestService(name, clazz, muleContext);
798     }
799 
800     public static Service getTestService(String name, Class<?> clazz, Map<?, ?> props) throws Exception
801     {
802         return MuleTestUtils.getTestService(name, clazz, props, muleContext);
803     }
804 
805     public static class TestInfo
806     {
807         /**
808          * Whether to dispose the manager after every method or once all tests for
809          * the class have run
810          */
811         private final String name;
812         private boolean disposeManagerPerSuite = false;
813         private boolean excluded = false;
814         private volatile int testCount = 0;
815         private volatile int runCount = 0;
816         // @GuardedBy(this)
817         private Set<String> registeredTestMethod = new HashSet<String>();
818 
819         public TestInfo(TestCase test)
820         {
821             this.name = test.getClass().getName();
822 
823             // load test exclusions
824             try
825             {
826                 // We find the physical classpath root URL of the test class and
827                 // use that to find the correct resource. Works fine everywhere,
828                 // regardless of classloaders. See MULE-2414
829                 URL classUrl = ClassUtils.getClassPathRoot(test.getClass());
830                 URLClassLoader tempClassLoader = new URLClassLoader(new URL[]{classUrl});
831                 URL fileUrl = tempClassLoader.getResource("mule-test-exclusions.txt");
832                 if (fileUrl != null)
833                 {
834                     InputStream in = null;
835                     try
836                     {
837                         in = fileUrl.openStream();
838 
839                         // this iterates over all lines in the exclusion file
840                         Iterator<?> lines = IOUtils.lineIterator(in, "UTF-8");
841 
842                         // ..and this finds non-comments that match the test case name
843                         excluded = IteratorUtils.filteredIterator(lines, new Predicate()
844                         {
845                             public boolean evaluate(Object object)
846                             {
847                                 return StringUtils.equals(name, StringUtils.trimToEmpty((String) object));
848                             }
849                         }).hasNext();
850                     }
851                     finally
852                     {
853                         IOUtils.closeQuietly(in);
854                     }
855                 }
856             }
857             catch (IOException ioex)
858             {
859                 // ignore
860             }
861         }
862 
863         public int getTestCount()
864         {
865             return testCount;
866         }
867 
868         public synchronized void incTestCount(String testName)
869         {
870             if (!registeredTestMethod.contains(testName))
871             {
872                 testCount++;
873                 registeredTestMethod.add(testName);
874             }
875         }
876 
877         public int getRunCount()
878         {
879             return runCount;
880         }
881 
882         public void incRunCount()
883         {
884             runCount++;
885         }
886 
887         public String getName()
888         {
889             return name;
890         }
891 
892         public boolean isDisposeManagerPerSuite()
893         {
894             return disposeManagerPerSuite;
895         }
896 
897         public void setDisposeManagerPerSuite(boolean disposeManagerPerSuite)
898         {
899             this.disposeManagerPerSuite = disposeManagerPerSuite;
900         }
901 
902         public boolean isExcluded()
903         {
904             return excluded;
905         }
906 
907         @Override
908         public synchronized String toString()
909         {
910             StringBuffer buf = new StringBuffer();
911             return buf.append(name).append(", (").append(runCount).append(" / ").append(testCount).append(
912                     ") tests run, disposePerSuite=").append(disposeManagerPerSuite).toString();
913         }
914     }
915 
916     protected boolean isStartContext()
917     {
918         return startContext;
919     }
920 
921     protected void setStartContext(boolean startContext)
922     {
923         this.startContext = startContext;
924     }
925 
926     public void setFailOnTimeout(boolean failOnTimeout)
927     {
928         this.failOnTimeout = failOnTimeout;
929     }
930 
931     /**
932      * Determines if the test case should perform graceful shutdown or not.
933      * Default is false so that tests run more quickly.
934      *
935      * @return
936      */
937     protected boolean isGracefulShutdown()
938     {
939         return false;
940     }
941 
942     /**
943      * Create an object of instance <code>clazz</code>. It will then register the object with the registry so that any
944      * dependencies are injected and then the object will be initialised.
945      * Note that if the object needs to be configured with additional state that cannot be passed into the constructor you should
946      * create an instance first set any additional data on the object then call {@link #initialiseObject(Object)}.
947      *
948      * @param clazz the class to create an instance of.
949      * @param <T>   Object of this type will be returned
950      * @return an initialised instance of <code>class</code>
951      * @throws Exception if there is a problem creating or initializing the object
952      */
953     protected <T extends Object> T createObject(Class<T> clazz) throws Exception
954     {
955         return createObject(clazz, ClassUtils.NO_ARGS);
956     }
957 
958     /**
959      * Create an object of instance <code>clazz</code>. It will then register the object with the registry so that any
960      * dependencies are injected and then the object will be initialised.
961      * Note that if the object needs to be configured with additional state that cannot be passed into the constructor you should
962      * create an instance first set any additional data on the object then call {@link #initialiseObject(Object)}.
963      *
964      * @param clazz the class to create an instance of.
965      * @param args  constructor parameters
966      * @param <T>   Object of this type will be returned
967      * @return an initialised instance of <code>class</code>
968      * @throws Exception if there is a problem creating or initializing the object
969      */
970     @SuppressWarnings("unchecked")
971     protected <T extends Object> T createObject(Class<T> clazz, Object... args) throws Exception
972     {
973         if (args == null)
974         {
975             args = ClassUtils.NO_ARGS;
976         }
977         Object o = ClassUtils.instanciateClass(clazz, args);
978         muleContext.getRegistry().registerObject(String.valueOf(o.hashCode()), o);
979         return (T) o;
980     }
981 
982     /**
983      * A convenience method that will register an object in the registry using its hashcode as the key.  This will cause the object
984      * to have any objects injected and lifecycle methods called.  Note that the object lifecycle will be called to the same current
985      * lifecycle as the MuleContext
986      *
987      * @param o the object to register and initialize it
988      * @throws RegistrationException
989      */
990     protected void initialiseObject(Object o) throws RegistrationException
991     {
992         muleContext.getRegistry().registerObject(String.valueOf(o.hashCode()), o);
993     }
994     
995     public SensingNullMessageProcessor getSensingNullMessageProcessor()
996     {
997         return new SensingNullMessageProcessor();
998     }
999     
1000     public TriggerableMessageSource getTriggerableMessageSource(MessageProcessor listener)
1001     {
1002         return new TriggerableMessageSource(listener);
1003     }
1004 
1005     public TriggerableMessageSource getTriggerableMessageSource()
1006     {
1007         return new TriggerableMessageSource();
1008     }
1009 
1010     /**
1011      * Define the ports as java system properties, starting with 'port1'
1012      */
1013     private void setPortProperties()
1014     {
1015         for (int i = 0; i < ports.size(); i++)
1016         {
1017             System.setProperty("port" + (i + 1), String.valueOf(ports.get(i)));
1018         }
1019     }
1020 
1021     public List<Integer> getPorts()
1022     {
1023         return ports;
1024     }    
1025 }