001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.test;
018    
019    import java.io.File;
020    import java.util.Collection;
021    import java.util.List;
022    import java.util.Locale;
023    
024    import junit.framework.TestCase;
025    import org.apache.camel.CamelContext;
026    import org.apache.camel.Channel;
027    import org.apache.camel.Endpoint;
028    import org.apache.camel.Exchange;
029    import org.apache.camel.Expression;
030    import org.apache.camel.InvalidPayloadException;
031    import org.apache.camel.Message;
032    import org.apache.camel.Predicate;
033    import org.apache.camel.Processor;
034    import org.apache.camel.Route;
035    import org.apache.camel.builder.Builder;
036    import org.apache.camel.builder.RouteBuilder;
037    import org.apache.camel.builder.ValueBuilder;
038    import org.apache.camel.impl.DefaultCamelContext;
039    import org.apache.camel.impl.DefaultExchange;
040    import org.apache.camel.processor.DelegateProcessor;
041    import org.apache.camel.util.ExchangeHelper;
042    import org.apache.camel.util.PredicateAssertHelper;
043    import org.apache.commons.logging.Log;
044    import org.apache.commons.logging.LogFactory;
045    
046    /**
047     * A bunch of useful testing methods
048     *
049     * @version $Revision: 20241 $
050     */
051    public abstract class TestSupport extends TestCase {
052        private static final Log LOG = LogFactory.getLog(TestSupport.class);    
053        protected transient Log log = LogFactory.getLog(getClass());    
054        
055        /**
056         * Runs the bare test sequence only if this platform is supported
057         * @exception Throwable if any exception is thrown
058         */
059        @Override
060        public void runBare() throws Throwable {
061            if (canRunOnThisPlatform()) {
062                //start with a clean slate
063                DefaultCamelContext.setContextCounter(0);
064                TestSupportNodeIdFactory.resetCounters();
065                super.runBare();
066            }
067        }
068    
069        protected boolean canRunOnThisPlatform() {
070            return true;
071        }
072    
073        // Builder methods for expressions used when testing
074        // -------------------------------------------------------------------------
075    
076        /**
077         * Returns a value builder for the given header
078         */
079        public static ValueBuilder header(String name) {
080            return Builder.header(name);
081        }
082    
083        /**
084         * Returns a value builder for the given property
085         */
086        public static ValueBuilder property(String name) {
087            return Builder.property(name);
088        }    
089        
090        /**
091         * Returns a predicate and value builder for the inbound body on an exchange
092         */
093        public static ValueBuilder body() {
094            return Builder.body();
095        }
096    
097        /**
098         * Returns a predicate and value builder for the inbound message body as a
099         * specific type
100         */
101        public static <T> ValueBuilder bodyAs(Class<T> type) {
102            return Builder.bodyAs(type);
103        }
104    
105        /**
106         * Returns a predicate and value builder for the outbound body on an
107         * exchange
108         */
109        public static ValueBuilder outBody() {
110            return Builder.outBody();
111        }
112    
113        /**
114         * Returns a predicate and value builder for the outbound message body as a
115         * specific type
116         */
117        public static <T> ValueBuilder outBodyAs(Class<T> type) {
118            return Builder.outBodyAs(type);
119        }
120    
121        /**
122         * Returns a predicate and value builder for the fault body on an
123         * exchange
124         */
125        public static ValueBuilder faultBody() {
126            return Builder.faultBody();
127        }
128    
129        /**
130         * Returns a predicate and value builder for the fault message body as a
131         * specific type
132         */
133        public static <T> ValueBuilder faultBodyAs(Class<T> type) {
134            return Builder.faultBodyAs(type);
135        }
136    
137        /**
138         * Returns a value builder for the given system property
139         */
140        public static ValueBuilder systemProperty(String name) {
141            return Builder.systemProperty(name);
142        }
143    
144        /**
145         * Returns a value builder for the given system property
146         */
147        public static ValueBuilder systemProperty(String name, String defaultValue) {
148            return Builder.systemProperty(name, defaultValue);
149        }
150    
151        // Assertions
152        // -----------------------------------------------------------------------
153    
154        public static <T> T assertIsInstanceOf(Class<T> expectedType, Object value) {
155            assertNotNull("Expected an instance of type: " + expectedType.getName() + " but was null", value);
156            assertTrue("object should be a " + expectedType.getName() + " but was: " + value + " with type: "
157                       + value.getClass().getName(), expectedType.isInstance(value));
158            return expectedType.cast(value);
159        }
160    
161        public static void assertEndpointUri(Endpoint endpoint, String uri) {
162            assertNotNull("Endpoint is null when expecting endpoint for: " + uri, endpoint);
163            assertEquals("Endpoint uri for: " + endpoint, uri, endpoint.getEndpointUri());
164        }
165    
166        /**
167         * Asserts the In message on the exchange contains the expected value
168         */
169        public static Object assertInMessageHeader(Exchange exchange, String name, Object expected) {
170            return assertMessageHeader(exchange.getIn(), name, expected);
171        }
172    
173        /**
174         * Asserts the Out message on the exchange contains the expected value
175         */
176        public static Object assertOutMessageHeader(Exchange exchange, String name, Object expected) {
177            return assertMessageHeader(exchange.getOut(), name, expected);
178        }
179    
180        /**
181         * Asserts that the given exchange has an OUT message of the given body value
182         *
183         * @param exchange the exchange which should have an OUT message
184         * @param expected the expected value of the OUT message
185         * @throws InvalidPayloadException is thrown if the payload is not the expected class type
186         */
187        public static void assertInMessageBodyEquals(Exchange exchange, Object expected) throws InvalidPayloadException {
188            assertNotNull("Should have a response exchange!", exchange);
189    
190            Object actual;
191            if (expected == null) {
192                actual = ExchangeHelper.getMandatoryInBody(exchange);
193                assertEquals("in body of: " + exchange, expected, actual);
194            } else {
195                actual = ExchangeHelper.getMandatoryInBody(exchange, expected.getClass());
196            }
197            assertEquals("in body of: " + exchange, expected, actual);
198    
199            LOG.debug("Received response: " + exchange + " with in: " + exchange.getIn());
200        }
201    
202        /**
203         * Asserts that the given exchange has an OUT message of the given body value
204         *
205         * @param exchange the exchange which should have an OUT message
206         * @param expected the expected value of the OUT message
207         * @throws InvalidPayloadException is thrown if the payload is not the expected class type
208         */
209        public static void assertOutMessageBodyEquals(Exchange exchange, Object expected) throws InvalidPayloadException {
210            assertNotNull("Should have a response exchange!", exchange);
211    
212            Object actual;
213            if (expected == null) {
214                actual = ExchangeHelper.getMandatoryOutBody(exchange);
215                assertEquals("output body of: " + exchange, expected, actual);
216            } else {
217                actual = ExchangeHelper.getMandatoryOutBody(exchange, expected.getClass());
218            }
219            assertEquals("output body of: " + exchange, expected, actual);
220    
221            LOG.debug("Received response: " + exchange + " with out: " + exchange.getOut());
222        }
223    
224        public static Object assertMessageHeader(Message message, String name, Object expected) {
225            Object value = message.getHeader(name);
226            assertEquals("Header: " + name + " on Message: " + message, expected, value);
227            return value;
228        }
229    
230        /**
231         * Asserts that the given expression when evaluated returns the given answer
232         */
233        public static Object assertExpression(Expression expression, Exchange exchange, Object expected) {
234            Object value;
235            if (expected != null) {
236                value = expression.evaluate(exchange, expected.getClass());
237            } else {
238                value = expression.evaluate(exchange, Object.class);
239            }
240    
241            LOG.debug("Evaluated expression: " + expression + " on exchange: " + exchange + " result: " + value);
242    
243            assertEquals("Expression: " + expression + " on Exchange: " + exchange, expected, value);
244            return value;
245        }
246    
247        /**
248         * Asserts that the predicate returns the expected value on the exchange
249         */
250        public static void assertPredicateMatches(Predicate predicate, Exchange exchange) {
251            assertPredicate(predicate, exchange, true);
252        }
253    
254        /**
255         * Asserts that the predicate returns the expected value on the exchange
256         */
257        public static void assertPredicateDoesNotMatch(Predicate predicate, Exchange exchange) {
258            try {
259                PredicateAssertHelper.assertMatches(predicate, "Predicate should match: ", exchange);
260            } catch (AssertionError e) {
261                LOG.debug("Caught expected assertion error: " + e);
262            }
263            assertPredicate(predicate, exchange, false);
264        }
265    
266        /**
267         * Asserts that the predicate returns the expected value on the exchange
268         */
269        public static boolean assertPredicate(final Predicate predicate, Exchange exchange, boolean expected) {
270            if (expected) {
271                PredicateAssertHelper.assertMatches(predicate, "Predicate failed: ", exchange);
272            }
273            boolean value = predicate.matches(exchange);
274    
275            LOG.debug("Evaluated predicate: " + predicate + " on exchange: " + exchange + " result: " + value);
276    
277            assertEquals("Predicate: " + predicate + " on Exchange: " + exchange, expected, value);
278            return value;
279        }
280    
281        /**
282         * Resolves an endpoint and asserts that it is found
283         */
284        public static Endpoint resolveMandatoryEndpoint(CamelContext context, String uri) {
285            Endpoint endpoint = context.getEndpoint(uri);
286    
287            assertNotNull("No endpoint found for URI: " + uri, endpoint);
288    
289            return endpoint;
290        }
291    
292        /**
293         * Resolves an endpoint and asserts that it is found
294         */
295        public static <T extends Endpoint> T resolveMandatoryEndpoint(CamelContext context, String uri,
296                                                                  Class<T> endpointType) {
297            T endpoint = context.getEndpoint(uri, endpointType);
298    
299            assertNotNull("No endpoint found for URI: " + uri, endpoint);
300    
301            return endpoint;
302        }
303    
304        /**
305         * Creates an exchange with the given body
306         */
307        protected Exchange createExchangeWithBody(CamelContext camelContext, Object body) {
308            Exchange exchange = new DefaultExchange(camelContext);
309            Message message = exchange.getIn();
310            message.setHeader("testName", getName());
311            message.setHeader("testClass", getClass().getName());
312            message.setBody(body);
313            return exchange;
314        }
315    
316        public static <T> T assertOneElement(List<T> list) {
317            assertEquals("Size of list should be 1: " + list, 1, list.size());
318            return list.get(0);
319        }
320    
321        /**
322         * Asserts that a list is of the given size
323         */
324        public static <T> List<T> assertListSize(List<T> list, int size) {
325            return assertListSize("List", list, size);
326        }
327    
328        /**
329         * Asserts that a list is of the given size
330         */
331        public static <T> List<T> assertListSize(String message, List<T> list, int size) {
332            assertEquals(message + " should be of size: "
333                    + size + " but is: " + list, size, list.size());
334            return list;
335        }
336    
337        /**
338         * Asserts that a list is of the given size
339         */
340        public static <T> Collection<T> assertCollectionSize(Collection<T> list, int size) {
341            return assertCollectionSize("List", list, size);
342        }
343    
344        /**
345         * Asserts that a list is of the given size
346         */
347        public static <T> Collection<T> assertCollectionSize(String message, Collection<T> list, int size) {
348            assertEquals(message + " should be of size: "
349                    + size + " but is: " + list, size, list.size());
350            return list;
351        }
352    
353        /**
354         * A helper method to create a list of Route objects for a given route builder
355         */
356        public static List<Route> getRouteList(RouteBuilder builder) throws Exception {
357            CamelContext context = new DefaultCamelContext();
358            context.addRoutes(builder);
359            context.start();
360            List<Route> answer = context.getRoutes();
361            context.stop();
362            return answer;
363        }
364    
365        /**
366         * Asserts that the text contains the given string
367         *
368         * @param text the text to compare
369         * @param containedText the text which must be contained inside the other text parameter
370         */
371        public static void assertStringContains(String text, String containedText) {
372            assertNotNull("Text should not be null!", text);
373            assertTrue("Text: " + text + " does not contain: " + containedText, text.contains(containedText));
374        }
375    
376        /**
377         * If a processor is wrapped with a bunch of DelegateProcessor or DelegateAsyncProcessor objects
378         * this call will drill through them and return the wrapped Processor.
379         */
380        public static Processor unwrap(Processor processor) {
381            while (true) {
382                if (processor instanceof DelegateProcessor) {
383                    processor = ((DelegateProcessor)processor).getProcessor();
384                } else {
385                    return processor;
386                }
387            }
388        }
389    
390        /**
391         * If a processor is wrapped with a bunch of DelegateProcessor or DelegateAsyncProcessor objects
392         * this call will drill through them and return the Channel.
393         * <p/>
394         * Returns null if no channel is found.
395         */
396        public static Channel unwrapChannel(Processor processor) {
397            while (true) {
398                if (processor instanceof Channel) {
399                    return (Channel) processor;
400                } else if (processor instanceof DelegateProcessor) {
401                    processor = ((DelegateProcessor)processor).getProcessor();
402                } else {
403                    return null;
404                }
405            }
406        }
407    
408        /**
409         * Recursively delete a directory, useful to zapping test data
410         *
411         * @param file the directory to be deleted
412         */
413        public static void deleteDirectory(String file) {
414            deleteDirectory(new File(file));
415        }
416    
417        /**
418         * Recursively delete a directory, useful to zapping test data
419         *
420         * @param file the directory to be deleted
421         */
422        public static void deleteDirectory(File file) {
423            if (file.isDirectory()) {
424                File[] files = file.listFiles();
425                for (int i = 0; i < files.length; i++) {
426                    deleteDirectory(files[i]);
427                }
428            }
429            file.delete();
430        }
431    
432        /**
433         * create the directory
434         *
435         * @param file the directory to be created
436         */
437        public static void createDirectory(String file) {
438            File dir = new File(file);
439            dir.mkdirs();
440        }
441    
442        /**
443         * To be used for folder/directory comparison that works across different platforms such
444         * as Window, Mac and Linux.
445         */
446        public static void assertDirectoryEquals(String expected, String actual) {
447            assertDirectoryEquals(null, expected, actual);
448        }
449    
450        /**
451         * To be used for folder/directory comparison that works across different platforms such
452         * as Window, Mac and Linux.
453         */
454        public static void assertDirectoryEquals(String message, String expected, String actual) {
455            // must use single / as path separators
456            String expectedPath = expected.replace('\\', '/');
457            String actualPath = actual.replace('\\', '/');
458    
459            if (message != null) {
460                assertEquals(message, expectedPath, actualPath);
461            } else {
462                assertEquals(expectedPath, actualPath);
463            }
464        }
465    
466        /**
467         * Is this OS the given platform.
468         * <p/>
469         * Uses <tt>os.name</tt> from the system properties to determine the OS.
470         *
471         * @param platform such as Windows
472         * @return <tt>true</tt> if its that platform.
473         */
474        public static boolean isPlatform(String platform) {
475            String osName = System.getProperty("os.name").toLowerCase(Locale.US);
476            return osName.indexOf(platform.toLowerCase(Locale.US)) > -1;
477        }
478    
479        /**
480         * Is this Java by the given vendor.
481         * <p/>
482         * Uses <tt>java.vendor</tt> from the system properties to determine the vendor.
483         *
484         * @param vendor such as IBM
485         * @return <tt>true</tt> if its that vendor.
486         */
487        public static boolean isJavaVendor(String vendor) {
488            String javaVendor = System.getProperty("java.vendor").toLowerCase(Locale.US);
489            return javaVendor.indexOf(vendor.toLowerCase(Locale.US)) > -1;
490        }
491    
492        /**
493         * Gets the current test method name
494         *
495         * @return the method name
496         */
497        public String getTestMethodName() {
498            return getName();
499        }
500    
501    }