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