View Javadoc

1   /*
2    * $Id: AbstractMuleTestCase.java 23054 2011-10-02 05:31:18Z 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.tck;
12  
13  import org.mule.MessageExchangePattern;
14  import org.mule.RequestContext;
15  import org.mule.api.MuleContext;
16  import org.mule.api.MuleEvent;
17  import org.mule.api.MuleEventContext;
18  import org.mule.api.MuleSession;
19  import org.mule.api.config.ConfigurationBuilder;
20  import org.mule.api.context.MuleContextBuilder;
21  import org.mule.api.context.MuleContextFactory;
22  import org.mule.api.context.notification.MuleContextNotificationListener;
23  import org.mule.api.endpoint.InboundEndpoint;
24  import org.mule.api.endpoint.OutboundEndpoint;
25  import org.mule.api.processor.MessageProcessor;
26  import org.mule.api.registry.RegistrationException;
27  import org.mule.api.routing.filter.Filter;
28  import org.mule.api.service.Service;
29  import org.mule.api.transformer.Transformer;
30  import org.mule.api.transport.Connector;
31  import org.mule.config.DefaultMuleConfiguration;
32  import org.mule.config.builders.DefaultsConfigurationBuilder;
33  import org.mule.config.builders.SimpleConfigurationBuilder;
34  import org.mule.context.DefaultMuleContextBuilder;
35  import org.mule.context.DefaultMuleContextFactory;
36  import org.mule.context.notification.MuleContextNotification;
37  import org.mule.tck.testmodels.mule.TestConnector;
38  import org.mule.util.ClassUtils;
39  import org.mule.util.FileUtils;
40  import org.mule.util.IOUtils;
41  import org.mule.util.MuleUrlStreamHandlerFactory;
42  import org.mule.util.StringMessageUtils;
43  import org.mule.util.StringUtils;
44  import org.mule.util.SystemUtils;
45  import org.mule.util.concurrent.Latch;
46  
47  import java.io.IOException;
48  import java.io.InputStream;
49  import java.net.URL;
50  import java.net.URLClassLoader;
51  import java.util.ArrayList;
52  import java.util.Collections;
53  import java.util.HashMap;
54  import java.util.HashSet;
55  import java.util.Iterator;
56  import java.util.List;
57  import java.util.Map;
58  import java.util.Properties;
59  import java.util.Set;
60  import java.util.concurrent.TimeUnit;
61  import java.util.concurrent.atomic.AtomicReference;
62  
63  import junit.framework.TestCase;
64  import junit.framework.TestResult;
65  
66  import org.apache.commons.collections.IteratorUtils;
67  import org.apache.commons.collections.Predicate;
68  import org.apache.commons.logging.Log;
69  import org.apache.commons.logging.LogFactory;
70  
71  /**
72   * <code>AbstractMuleTestCase</code> is a base class for Mule testcases. This
73   * implementation provides services to test code for creating mock and test objects.
74   */
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         printTestHeader();
428 
429         try
430         {
431             if (getTestInfo().getRunCount() == 0)
432             {
433                 if (getTestInfo().isDisposeManagerPerSuite())
434                 {
435                     // We dispose here jut in case
436                     disposeManager();
437                 }
438                 suitePreSetUp();
439             }
440             if (!getTestInfo().isDisposeManagerPerSuite())
441             {
442                 // We dispose here just in case
443                 disposeManager();
444             }
445 
446             muleContext = createMuleContext();
447 
448             // wait for Mule to fully start when requested (default)
449 
450             // latch ref needs to be final for listener use, wrap in atomic ref
451             final AtomicReference<Latch> contextStartedLatch = new AtomicReference<Latch>();
452             if (isStartContext() && null != muleContext && muleContext.isStarted() == false)
453             {
454                 contextStartedLatch.set(new Latch());
455                 muleContext.registerListener(new MuleContextNotificationListener<MuleContextNotification>()
456                 {
457                     public void onNotification(MuleContextNotification notification)
458                     {
459                         if (notification.getAction() == MuleContextNotification.CONTEXT_STARTED)
460                         {
461                             contextStartedLatch.get().countDown();
462                         }
463                     }
464                 });
465                 muleContext.start();
466             }
467 
468             // if it's null, than
469             if (contextStartedLatch.get() != null)
470             {
471                 // wait no more than 20 secs
472                 contextStartedLatch.get().await(20, TimeUnit.SECONDS);
473             }
474             doSetUp();
475         }
476         catch (Exception e)
477         {
478             getTestInfo().incRunCount();
479             throw e;
480         }
481     }
482 
483     protected void printTestHeader()
484     {
485         if (verbose)
486         {
487             System.out.println(StringMessageUtils.getBoilerPlate(getTestHeader(), '=', 80));
488         }
489     }
490 
491     protected String getTestHeader()
492     {
493         return "Testing: " + getName();
494     }
495 
496     protected MuleContext createMuleContext() throws Exception
497     {
498         // Should we set up the manager for every method?
499         MuleContext context;
500         if (getTestInfo().isDisposeManagerPerSuite() && muleContext != null)
501         {
502             context = muleContext;
503         }
504         else
505         {
506             MuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
507             List<ConfigurationBuilder> builders = new ArrayList<ConfigurationBuilder>();
508             builders.add(new SimpleConfigurationBuilder(getStartUpProperties()));
509             //If the annotations module is on the classpath, add the annotations config builder to the list
510             //This will enable annotations config for this instance
511             if (ClassUtils.isClassOnPath(CLASSNAME_ANNOTATIONS_CONFIG_BUILDER, getClass()))
512             {
513                 builders.add((ConfigurationBuilder) ClassUtils.instanciateClass(CLASSNAME_ANNOTATIONS_CONFIG_BUILDER,
514                         ClassUtils.NO_ARGS, getClass()));
515             }
516             builders.add(getBuilder());
517             addBuilders(builders);
518             MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
519             configureMuleContext(contextBuilder);
520             context = muleContextFactory.createMuleContext(builders, contextBuilder);
521             if (!isGracefulShutdown())
522             {
523                 ((DefaultMuleConfiguration) context.getConfiguration()).setShutdownTimeout(0);
524             }
525         }
526         return context;
527     }
528 
529     //This sohuldn't be needed by Test cases but can be used by base testcases that wish to add further builders when
530     //creating the MuleContext.
531 
532     protected void addBuilders(List<ConfigurationBuilder> builders)
533     {
534         //No op
535     }
536 
537     /**
538      * Override this method to set properties of the MuleContextBuilder before it is
539      * used to create the MuleContext.
540      */
541     protected void configureMuleContext(MuleContextBuilder contextBuilder)
542     {
543         contextBuilder.setWorkListener(new TestingWorkListener());
544     }
545 
546     protected ConfigurationBuilder getBuilder() throws Exception
547     {
548         return new DefaultsConfigurationBuilder();
549     }
550 
551     protected String getConfigurationResources()
552     {
553         return StringUtils.EMPTY;
554     }
555 
556     protected Properties getStartUpProperties()
557     {
558         return null;
559     }
560 
561     /**
562      * Run <strong>before</strong> any testcase setup.
563      * This is called once only before the test suite runs.
564      */
565     protected void suitePreSetUp() throws Exception
566     {
567         // nothing to do
568     }
569 
570     /**
571      * Run <strong>after</strong> all testcase teardowns.
572      * This is called once only after all the tests in the suite have run.
573      */
574     protected void suitePostTearDown() throws Exception
575     {
576         // nothing to do
577     }
578 
579     /**
580      * Normal JUnit method
581      *
582      * @throws Exception
583      * @see #doTearDown()
584      */
585     @Override
586     protected final void tearDown() throws Exception
587     {
588         try
589         {
590             doTearDown();
591 
592             if (!getTestInfo().isDisposeManagerPerSuite())
593             {
594                 disposeManager();
595             }
596         }
597         finally
598         {
599             try
600             {
601                 getTestInfo().incRunCount();
602                 if (getTestInfo().getRunCount() == getTestInfo().getTestCount())
603                 {
604                     try
605                     {
606                         suitePostTearDown();
607                     }
608                     finally
609                     {
610                         clearInfo();
611                         disposeManager();
612                     }
613                 }
614             }
615             finally
616             {
617                 // remove the watchdog thread in any case
618                 watchdog.cancel();
619             }
620         }
621     }
622 
623     protected void disposeManager()
624     {
625         try
626         {
627             if (muleContext != null && !(muleContext.isDisposed() || muleContext.isDisposing()))
628             {
629                 muleContext.dispose();
630 
631                 final String workingDir = muleContext.getConfiguration().getWorkingDirectory();
632                 // do not delete TM recovery object store, everything else is good to
633                 // go
634                 FileUtils.deleteTree(FileUtils.newFile(workingDir), IGNORED_DOT_MULE_DIRS);
635             }
636             FileUtils.deleteTree(FileUtils.newFile("./ActiveMQ"));
637         }
638         finally
639         {
640             muleContext = null;
641         }
642     }
643 
644     /**
645      * Exactly the same a {@link #setUp()} in normal JUnit test cases.  this is called <strong>before</strong> a test
646      * method has been called.
647      *
648      * @throws Exception if something fails that should halt the testcase
649      */
650     protected void doSetUp() throws Exception
651     {
652         // template method
653     }
654 
655     /**
656      * Exactly the same a {@link #tearDown()} in normal JUnit test cases.  this is called <strong>after</strong> a test
657      * method has been called.
658      *
659      * @throws Exception if something fails that should halt the testcase
660      */
661     protected void doTearDown() throws Exception
662     {
663         RequestContext.clear();
664     }
665 
666     public static InboundEndpoint getTestInboundEndpoint(String name) throws Exception
667     {
668         return MuleTestUtils.getTestInboundEndpoint(name, muleContext);
669     }
670 
671     public static OutboundEndpoint getTestOutboundEndpoint(String name) throws Exception
672     {
673         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext);
674     }
675 
676     public static InboundEndpoint getTestInboundEndpoint(MessageExchangePattern mep) throws Exception
677     {
678         return MuleTestUtils.getTestInboundEndpoint(mep, muleContext);
679     }
680 
681     public static InboundEndpoint getTestTransactedInboundEndpoint(MessageExchangePattern mep) throws Exception
682     {
683         return MuleTestUtils.getTestTransactedInboundEndpoint(mep, muleContext);
684     }
685 
686     public static InboundEndpoint getTestInboundEndpoint(String name, String uri) throws Exception
687     {
688         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, uri, null, null, null, null);
689     }
690 
691     public static OutboundEndpoint getTestOutboundEndpoint(String name, String uri) throws Exception
692     {
693         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, uri, null, null, null);
694     }
695 
696     public static InboundEndpoint getTestInboundEndpoint(String name, List<Transformer> transformers) throws Exception
697     {
698         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, null, transformers, null, null, null);
699     }
700 
701     public static OutboundEndpoint getTestOutboundEndpoint(String name, List<Transformer> transformers) throws Exception
702     {
703         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, null, transformers, null, null);
704     }
705 
706     public static InboundEndpoint getTestInboundEndpoint(String name, String uri,
707         List<Transformer> transformers, Filter filter, Map<Object, Object> properties, Connector connector) throws Exception
708     {
709         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, uri, transformers, filter, properties, connector);
710     }
711 
712     public static OutboundEndpoint getTestOutboundEndpoint(String name, String uri,
713         List<Transformer> transformers, Filter filter, Map<Object, Object> properties) throws Exception
714     {
715         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, uri, transformers, filter, properties);
716     }
717 
718     public static InboundEndpoint getTestInboundEndpoint(String name,
719                                                           String uri,
720                                                           List<Transformer> transformers,
721                                                           Filter filter,
722                                                           Map<Object, Object> properties) throws Exception
723     {
724         return MuleTestUtils.getTestInboundEndpoint(name, muleContext, uri, transformers, filter, properties);
725     }
726 
727     public static OutboundEndpoint getTestOutboundEndpoint(String name, String uri,
728         List<Transformer> transformers, Filter filter, Map<Object, Object> properties, Connector connector) throws Exception
729     {
730         return MuleTestUtils.getTestOutboundEndpoint(name, muleContext, uri, transformers, filter, properties, connector);
731     }
732 
733     public static MuleEvent getTestEvent(Object data, Service service) throws Exception
734     {
735         return MuleTestUtils.getTestEvent(data, service, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
736     }
737 
738     public static MuleEvent getTestEvent(Object data, Service service, MessageExchangePattern mep) throws Exception
739     {
740         return MuleTestUtils.getTestEvent(data, service, mep, muleContext);
741     }
742 
743     public static MuleEvent getTestEvent(Object data) throws Exception
744     {
745         return MuleTestUtils.getTestEvent(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
746     }
747 
748     public static MuleEvent getTestEventUsingFlow(Object data) throws Exception
749     {
750         return MuleTestUtils.getTestEventUsingFlow(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
751     }
752 
753     public static MuleEvent getTestEvent(Object data, MessageExchangePattern mep) throws Exception
754     {
755         return MuleTestUtils.getTestEvent(data, mep, muleContext);
756     }
757 
758     public static MuleEvent getTestEvent(Object data, MuleSession session) throws Exception
759     {
760         return MuleTestUtils.getTestEvent(data, session, muleContext);
761     }
762 
763 //    public static MuleEvent getTestInboundEvent(Object data) throws Exception
764 //    {
765 //        return MuleTestUtils.getTestInboundEvent(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
766 //    }
767 //
768 //    public static MuleEvent getTestInboundEvent(Object data, MessageExchangePattern mep) throws Exception
769 //    {
770 //        return MuleTestUtils.getTestInboundEvent(data, mep, muleContext);
771 //    }
772 
773     public static MuleEventContext getTestEventContext(Object data) throws Exception
774     {
775         return MuleTestUtils.getTestEventContext(data, MessageExchangePattern.REQUEST_RESPONSE, muleContext);
776     }
777 
778     public static MuleEventContext getTestEventContext(Object data, MessageExchangePattern mep) throws Exception
779     {
780         return MuleTestUtils.getTestEventContext(data, mep, muleContext);
781     }
782 
783     public static Transformer getTestTransformer() throws Exception
784     {
785         return MuleTestUtils.getTestTransformer();
786     }
787 
788     public static MuleEvent getTestEvent(Object data, InboundEndpoint endpoint) throws Exception
789     {
790         return MuleTestUtils.getTestEvent(data, endpoint, muleContext);
791     }
792 
793     public static MuleEvent getTestEvent(Object data, Service service, InboundEndpoint endpoint)
794             throws Exception
795     {
796         return MuleTestUtils.getTestEvent(data, service, endpoint, muleContext);
797     }
798 
799     public static MuleSession getTestSession(Service service, MuleContext context)
800     {
801         return MuleTestUtils.getTestSession(service, context);
802     }
803 
804     public static TestConnector getTestConnector() throws Exception
805     {
806         return MuleTestUtils.getTestConnector(muleContext);
807     }
808 
809     public static Service getTestService() throws Exception
810     {
811         return MuleTestUtils.getTestService(muleContext);
812     }
813 
814     public static Service getTestService(String name, Class<?> clazz) throws Exception
815     {
816         return MuleTestUtils.getTestService(name, clazz, muleContext);
817     }
818 
819     public static Service getTestService(String name, Class<?> clazz, Map<?, ?> props) throws Exception
820     {
821         return MuleTestUtils.getTestService(name, clazz, props, muleContext);
822     }
823 
824     public static class TestInfo
825     {
826         /**
827          * Whether to dispose the manager after every method or once all tests for
828          * the class have run
829          */
830         private final String name;
831         private boolean disposeManagerPerSuite = false;
832         private boolean excluded = false;
833         private volatile int testCount = 0;
834         private volatile int runCount = 0;
835         // @GuardedBy(this)
836         private Set<String> registeredTestMethod = new HashSet<String>();
837 
838         public TestInfo(TestCase test)
839         {
840             this.name = test.getClass().getName();
841 
842             // load test exclusions
843             try
844             {
845                 // We find the physical classpath root URL of the test class and
846                 // use that to find the correct resource. Works fine everywhere,
847                 // regardless of classloaders. See MULE-2414
848                 URL classUrl = ClassUtils.getClassPathRoot(test.getClass());
849                 URLClassLoader tempClassLoader = new URLClassLoader(new URL[]{classUrl});
850                 URL fileUrl = tempClassLoader.getResource("mule-test-exclusions.txt");
851                 if (fileUrl != null)
852                 {
853                     InputStream in = null;
854                     try
855                     {
856                         in = fileUrl.openStream();
857 
858                         // this iterates over all lines in the exclusion file
859                         Iterator<?> lines = IOUtils.lineIterator(in, "UTF-8");
860 
861                         // ..and this finds non-comments that match the test case name
862                         excluded = IteratorUtils.filteredIterator(lines, new Predicate()
863                         {
864                             public boolean evaluate(Object object)
865                             {
866                                 return StringUtils.equals(name, StringUtils.trimToEmpty((String) object));
867                             }
868                         }).hasNext();
869                     }
870                     finally
871                     {
872                         IOUtils.closeQuietly(in);
873                     }
874                 }
875             }
876             catch (IOException ioex)
877             {
878                 // ignore
879             }
880         }
881 
882         public int getTestCount()
883         {
884             return testCount;
885         }
886 
887         public synchronized void incTestCount(String testName)
888         {
889             if (!registeredTestMethod.contains(testName))
890             {
891                 testCount++;
892                 registeredTestMethod.add(testName);
893             }
894         }
895 
896         public int getRunCount()
897         {
898             return runCount;
899         }
900 
901         public void incRunCount()
902         {
903             runCount++;
904         }
905 
906         public String getName()
907         {
908             return name;
909         }
910 
911         public boolean isDisposeManagerPerSuite()
912         {
913             return disposeManagerPerSuite;
914         }
915 
916         public void setDisposeManagerPerSuite(boolean disposeManagerPerSuite)
917         {
918             this.disposeManagerPerSuite = disposeManagerPerSuite;
919         }
920 
921         public boolean isExcluded()
922         {
923             return excluded;
924         }
925 
926         @Override
927         public synchronized String toString()
928         {
929             StringBuffer buf = new StringBuffer();
930             return buf.append(name).append(", (").append(runCount).append(" / ").append(testCount).append(
931                     ") tests run, disposePerSuite=").append(disposeManagerPerSuite).toString();
932         }
933     }
934 
935     protected boolean isStartContext()
936     {
937         return startContext;
938     }
939 
940     protected void setStartContext(boolean startContext)
941     {
942         this.startContext = startContext;
943     }
944 
945     public void setFailOnTimeout(boolean failOnTimeout)
946     {
947         this.failOnTimeout = failOnTimeout;
948     }
949 
950     /**
951      * Determines if the test case should perform graceful shutdown or not.
952      * Default is false so that tests run more quickly.
953      */
954     protected boolean isGracefulShutdown()
955     {
956         return false;
957     }
958 
959     /**
960      * Create an object of instance <code>clazz</code>. It will then register the object with the registry so that any
961      * dependencies are injected and then the object will be initialised.
962      * Note that if the object needs to be configured with additional state that cannot be passed into the constructor you should
963      * create an instance first set any additional data on the object then call {@link #initialiseObject(Object)}.
964      *
965      * @param clazz the class to create an instance of.
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     protected <T extends Object> T createObject(Class<T> clazz) throws Exception
971     {
972         return createObject(clazz, ClassUtils.NO_ARGS);
973     }
974 
975     /**
976      * Create an object of instance <code>clazz</code>. It will then register the object with the registry so that any
977      * dependencies are injected and then the object will be initialised.
978      * Note that if the object needs to be configured with additional state that cannot be passed into the constructor you should
979      * create an instance first set any additional data on the object then call {@link #initialiseObject(Object)}.
980      *
981      * @param clazz the class to create an instance of.
982      * @param args  constructor parameters
983      * @param <T>   Object of this type will be returned
984      * @return an initialised instance of <code>class</code>
985      * @throws Exception if there is a problem creating or initializing the object
986      */
987     @SuppressWarnings("unchecked")
988     protected <T extends Object> T createObject(Class<T> clazz, Object... args) throws Exception
989     {
990         if (args == null)
991         {
992             args = ClassUtils.NO_ARGS;
993         }
994         Object o = ClassUtils.instanciateClass(clazz, args);
995         muleContext.getRegistry().registerObject(String.valueOf(o.hashCode()), o);
996         return (T) o;
997     }
998 
999     /**
1000      * A convenience method that will register an object in the registry using its hashcode as the key.  This will cause the object
1001      * to have any objects injected and lifecycle methods called.  Note that the object lifecycle will be called to the same current
1002      * lifecycle as the MuleContext
1003      *
1004      * @param o the object to register and initialize it
1005      * @throws RegistrationException
1006      */
1007     protected void initialiseObject(Object o) throws RegistrationException
1008     {
1009         muleContext.getRegistry().registerObject(String.valueOf(o.hashCode()), o);
1010     }
1011 
1012     public SensingNullMessageProcessor getSensingNullMessageProcessor()
1013     {
1014         return new SensingNullMessageProcessor();
1015     }
1016 
1017     public TriggerableMessageSource getTriggerableMessageSource(MessageProcessor listener)
1018     {
1019         return new TriggerableMessageSource(listener);
1020     }
1021 
1022     public TriggerableMessageSource getTriggerableMessageSource()
1023     {
1024         return new TriggerableMessageSource();
1025     }
1026 
1027     /**
1028      * Define the ports as java system properties, starting with 'port1'
1029      */
1030     private void setPortProperties()
1031     {
1032         for (int i = 0; i < ports.size(); i++)
1033         {
1034             System.setProperty("port" + (i + 1), String.valueOf(ports.get(i)));
1035         }
1036     }
1037 
1038     public List<Integer> getPorts()
1039     {
1040         return ports;
1041     }
1042 }