1   /*
2    * $Id: ExceptionBasedRouterTestCase.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.routing.outbound;
12  
13  import org.mule.impl.MuleMessage;
14  import org.mule.impl.endpoint.MuleEndpoint;
15  import org.mule.impl.endpoint.MuleEndpointURI;
16  import org.mule.impl.message.ExceptionPayload;
17  import org.mule.routing.LoggingCatchAllStrategy;
18  import org.mule.routing.filters.RegExFilter;
19  import org.mule.tck.AbstractMuleTestCase;
20  import org.mule.tck.MuleTestUtils;
21  import org.mule.umo.UMOException;
22  import org.mule.umo.UMOMessage;
23  import org.mule.umo.UMOSession;
24  import org.mule.umo.endpoint.UMOEndpoint;
25  import org.mule.umo.routing.CouldNotRouteOutboundMessageException;
26  import org.mule.umo.routing.RoutingException;
27  
28  import com.mockobjects.dynamic.C;
29  import com.mockobjects.dynamic.Mock;
30  
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  public class ExceptionBasedRouterTestCase extends AbstractMuleTestCase
35  {
36  
37      /**
38       * Multiple endpoints, no failures. Event dispatched asynchronously, but forced
39       * into sync mode. Test case ends here.
40       */
41      public void testSuccessfulExceptionRouter() throws Exception
42      {
43          Mock session = MuleTestUtils.getMockSession();
44          OutboundRouterCollection messageRouter = new OutboundRouterCollection();
45          messageRouter.setCatchAllStrategy(new LoggingCatchAllStrategy());
46  
47          UMOEndpoint endpoint1 = new MuleEndpoint("test://Dummy1", false);
48          UMOEndpoint endpoint2 = new MuleEndpoint("test://Dummy2", false);
49  
50          UMOEndpoint endpoint3 = new MuleEndpoint("test://Dummy3", false);
51  
52          ExceptionBasedRouter router = new ExceptionBasedRouter();
53          RegExFilter filter = new RegExFilter("(.*) event");
54          router.setFilter(filter);
55          List endpoints = new ArrayList();
56          endpoints.add(endpoint1);
57          endpoints.add(endpoint2);
58          endpoints.add(endpoint3);
59          router.setEndpoints(endpoints);
60  
61          assertEquals(filter, router.getFilter());
62  
63          UMOMessage message = new MuleMessage("test event");
64  
65          assertTrue(router.isMatch(message));
66  
67          session.expect("sendEvent", C.eq(message, endpoint1));
68          UMOMessage result = router.route(message, (UMOSession)session.proxy(), false);
69          assertNull("Async call should've returned null.", result);
70          session.verify();
71  
72          message = new MuleMessage("test event");
73  
74          // only one send should be called and succeed, the others should not be
75          // called
76          session.expectAndReturn("sendEvent", C.eq(message, endpoint1), message);
77          result = router.route(message, (UMOSession)session.proxy(), true);
78          assertNotNull(result);
79          assertEquals(message, result);
80          session.verify();
81      }
82  
83      /**
84       * Both endpoints fail during dispatch. The first endpoint should be forced into
85       * sync mode.
86       */
87      public void testBothFailing() throws Exception
88      {
89          Mock mockSession = MuleTestUtils.getMockSession();
90          OutboundRouterCollection messageRouter = new OutboundRouterCollection();
91          messageRouter.setCatchAllStrategy(new LoggingCatchAllStrategy());
92  
93          UMOEndpoint endpoint1 = new MuleEndpoint("test://AlwaysFail", false);
94          UMOEndpoint endpoint2 = new MuleEndpoint("test://AlwaysFail", false);
95  
96          ExceptionBasedRouter router = new ExceptionBasedRouter();
97          RegExFilter filter = new RegExFilter("(.*) event");
98          router.setFilter(filter);
99          List endpoints = new ArrayList();
100         endpoints.add(endpoint1);
101         endpoints.add(endpoint2);
102         router.setEndpoints(endpoints);
103 
104         assertEquals(filter, router.getFilter());
105 
106         UMOMessage message = new MuleMessage("test event");
107 
108         assertTrue(router.isMatch(message));
109 
110         // exception to throw
111         UMOException rex = new RoutingException(message, endpoint1);
112         mockSession.expectAndThrow("sendEvent", C.args(C.eq(message), C.eq(endpoint1)), rex);
113         mockSession.expectAndThrow("dispatchEvent", C.args(C.eq(message), C.eq(endpoint2)), rex);
114         UMOSession session = (UMOSession)mockSession.proxy();
115         UMOMessage result = null;
116         try
117         {
118             result = router.route(message, session, false);
119             fail("Should have thrown exception as both endpoints would have failed");
120         }
121         catch (CouldNotRouteOutboundMessageException e)
122         {
123             // expected
124         }
125         assertNull("Async call should've returned null.", result);
126         mockSession.verify();
127 
128         message = new MuleMessage("test event");
129 
130     }
131 
132     /**
133      * The first endpoint fails, second succeeds. Events are being sent
134      * synchronously.
135      */
136     public void testFailFirstSuccessSecondSync() throws Exception
137     {
138         Mock mockSession = MuleTestUtils.getMockSession();
139 
140         UMOEndpoint endpoint1 = getTestEndpoint("TestFailEndpoint", UMOEndpoint.ENDPOINT_TYPE_SENDER);
141         endpoint1.setEndpointURI(new MuleEndpointURI("test://Failure"));
142         UMOEndpoint endpoint2 = getTestEndpoint("TestSuccessEndpoint", UMOEndpoint.ENDPOINT_TYPE_SENDER);
143         endpoint2.setEndpointURI(new MuleEndpointURI("test://Success"));
144 
145         ExceptionBasedRouter router = new ExceptionBasedRouter();
146         router.addEndpoint(endpoint1);
147         router.addEndpoint(endpoint2);
148 
149         UMOMessage message = new MuleMessage("test event");
150         UMOMessage expectedResultMessage = new MuleMessage("Return event");
151 
152         assertTrue(router.isMatch(message));
153 
154         final UMOSession session = (UMOSession)mockSession.proxy();
155         // exception to throw
156         UMOException rex = new RoutingException(message, endpoint1);
157         // 1st failure
158         mockSession.expectAndThrow("sendEvent", C.args(C.eq(message), C.eq(endpoint1)), rex);
159         // next endpoint
160         mockSession.expectAndReturn("sendEvent", C.args(C.eq(message), C.eq(endpoint2)),
161             expectedResultMessage);
162         UMOMessage actualResultMessage = router.route(message, session, true);
163         mockSession.verify();
164 
165         assertEquals("Got an invalid return message.", expectedResultMessage, actualResultMessage);
166     }
167 
168     /**
169      * The first endpoint fails, second succeeds. Events are being forced into a sync
170      * mode, until we reach the last one.
171      */
172     public void testFailFirstSuccessSecondAsync() throws Exception
173     {
174         Mock mockSession = MuleTestUtils.getMockSession();
175 
176         UMOEndpoint endpoint1 = getTestEndpoint("TestFailEndpoint", UMOEndpoint.ENDPOINT_TYPE_SENDER);
177         endpoint1.setEndpointURI(new MuleEndpointURI("test://Failure"));
178         UMOEndpoint endpoint2 = getTestEndpoint("TestSuccessEndpoint", UMOEndpoint.ENDPOINT_TYPE_SENDER);
179         endpoint2.setEndpointURI(new MuleEndpointURI("test://Success"));
180 
181         ExceptionBasedRouter router = new ExceptionBasedRouter();
182         router.addEndpoint(endpoint1);
183         router.addEndpoint(endpoint2);
184 
185         UMOMessage message = new MuleMessage("test event");
186         UMOMessage expectedResultMessage = new MuleMessage("Return event");
187 
188         assertTrue(router.isMatch(message));
189 
190         final UMOSession session = (UMOSession)mockSession.proxy();
191         // exception to throw
192         UMOException rex = new RoutingException(message, endpoint1);
193         // 1st failure
194         mockSession.expectAndThrow("sendEvent", C.args(C.eq(message), C.eq(endpoint1)), rex);
195         // next endpoint
196         mockSession.expectAndReturn("dispatchEvent", C.args(C.eq(message), C.eq(endpoint2)),
197             expectedResultMessage);
198         UMOMessage actualResultMessage = router.route(message, session, false);
199         assertNull("Async call should not return any results.", actualResultMessage);
200         mockSession.verify();
201     }
202 
203     /**
204      * The first endpoint contains exception payload in return message, second
205      * succeeds. Events are being sent synchronously.
206      */
207     public void testFirstHadExceptionPayloadSuccessSecondSyncWithExceptionPayload() throws Exception
208     {
209         Mock mockSession = MuleTestUtils.getMockSession();
210 
211         UMOEndpoint endpoint1 = getTestEndpoint("TestFailEndpoint", UMOEndpoint.ENDPOINT_TYPE_SENDER);
212         endpoint1.setEndpointURI(new MuleEndpointURI("test://Failure"));
213         UMOEndpoint endpoint2 = getTestEndpoint("TestSuccessEndpoint", UMOEndpoint.ENDPOINT_TYPE_SENDER);
214         endpoint2.setEndpointURI(new MuleEndpointURI("test://Success"));
215 
216         ExceptionBasedRouter router = new ExceptionBasedRouter();
217         router.addEndpoint(endpoint1);
218         router.addEndpoint(endpoint2);
219 
220         UMOMessage message = new MuleMessage("test event");
221         UMOMessage expectedResultMessage = new MuleMessage("Return event");
222 
223         assertTrue(router.isMatch(message));
224 
225         // remote endpoint failed and set an exception payload on the returned
226         // message
227         UMOMessage exPayloadMessage = new MuleMessage("there was a failure");
228         exPayloadMessage.setExceptionPayload(new ExceptionPayload(new RuntimeException()));
229 
230         final UMOSession session = (UMOSession)mockSession.proxy();
231         // 1st failure
232         mockSession.expectAndReturn("sendEvent", C.args(C.eq(message), C.eq(endpoint1)), exPayloadMessage);
233         // next endpoint
234         mockSession.expectAndReturn("sendEvent", C.args(C.eq(message), C.eq(endpoint2)),
235             expectedResultMessage);
236         UMOMessage actualResultMessage = router.route(message, session, true);
237         mockSession.verify();
238 
239         assertEquals("Got an invalid return message.", expectedResultMessage, actualResultMessage);
240     }
241 }