1
2
3
4
5
6
7
8
9
10
11 package org.mule.routing;
12
13 import org.mule.api.MuleEvent;
14 import org.mule.api.MuleException;
15 import org.mule.api.endpoint.EndpointBuilder;
16 import org.mule.api.endpoint.OutboundEndpoint;
17 import org.mule.api.processor.MessageProcessor;
18 import org.mule.api.store.ListableObjectStore;
19 import org.mule.tck.junit4.AbstractMuleContextTestCase;
20 import org.mule.util.store.SimpleMemoryObjectStore;
21
22 import java.io.ByteArrayInputStream;
23
24 import org.junit.Test;
25
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertNull;
28 import static org.mockito.Matchers.any;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32
33 public class UntilSuccessfulTestCase extends AbstractMuleContextTestCase
34 {
35 public static class ConfigurableMessageProcessor implements MessageProcessor
36 {
37 private volatile int eventCount;
38 private volatile MuleEvent event;
39 private volatile int numberOfFailuresToSimulate;
40
41 @Override
42 public MuleEvent process(final MuleEvent evt) throws MuleException
43 {
44 eventCount++;
45 if (numberOfFailuresToSimulate-- > 0)
46 {
47 throw new RuntimeException("simulated problem");
48 }
49 this.event = evt;
50 return evt;
51 }
52
53 public MuleEvent getEventReceived()
54 {
55 return event;
56 }
57
58 public int getEventCount()
59 {
60 return eventCount;
61 }
62
63 public void setNumberOfFailuresToSimulate(int numberOfFailuresToSimulate)
64 {
65 this.numberOfFailuresToSimulate = numberOfFailuresToSimulate;
66 }
67 }
68
69 private UntilSuccessful untilSuccessful;
70
71 private ListableObjectStore<MuleEvent> objectStore;
72 private ConfigurableMessageProcessor targetMessageProcessor;
73
74 @Override
75 protected void doSetUp() throws Exception
76 {
77 super.doSetUp();
78
79 untilSuccessful = new UntilSuccessful();
80 untilSuccessful.setMuleContext(muleContext);
81 untilSuccessful.setFlowConstruct(getTestService());
82 untilSuccessful.setMaxRetries(2);
83 untilSuccessful.setSecondsBetweenRetries(1);
84
85 objectStore = new SimpleMemoryObjectStore<MuleEvent>();
86 untilSuccessful.setObjectStore(objectStore);
87
88 targetMessageProcessor = new ConfigurableMessageProcessor();
89 untilSuccessful.addRoute(targetMessageProcessor);
90 }
91
92 @Override
93 protected void doTearDown() throws Exception
94 {
95 untilSuccessful.stop();
96 }
97
98 @Test
99 public void testSuccessfulDelivery() throws Exception
100 {
101 untilSuccessful.initialise();
102 untilSuccessful.start();
103
104 final MuleEvent testEvent = getTestEvent("test_data");
105 assertNull(untilSuccessful.process(testEvent));
106 ponderUntilEventProcessed(testEvent);
107 }
108
109 @Test
110 public void testSuccessfulDeliveryStreamPayload() throws Exception
111 {
112 untilSuccessful.initialise();
113 untilSuccessful.start();
114
115 final MuleEvent testEvent = getTestEvent(new ByteArrayInputStream("test_data".getBytes()));
116 assertNull(untilSuccessful.process(testEvent));
117 ponderUntilEventProcessed(testEvent);
118 }
119
120 @Test
121 public void testSuccessfulDeliveryAckExpression() throws Exception
122 {
123 untilSuccessful.setAckExpression("#[string:ACK]");
124 untilSuccessful.initialise();
125 untilSuccessful.start();
126
127 final MuleEvent testEvent = getTestEvent("test_data");
128 assertEquals("ACK", untilSuccessful.process(testEvent).getMessageAsString());
129 ponderUntilEventProcessed(testEvent);
130 }
131
132 @Test
133 public void testSuccessfulDeliveryFailureExpression() throws Exception
134 {
135 untilSuccessful.setFailureExpression("#[regex:(?i)error]");
136 untilSuccessful.initialise();
137 untilSuccessful.start();
138
139 final MuleEvent testEvent = getTestEvent("test_data");
140 assertNull(untilSuccessful.process(testEvent));
141 ponderUntilEventProcessed(testEvent);
142 }
143
144 @Test
145 public void testPermanentDeliveryFailure() throws Exception
146 {
147 targetMessageProcessor.setNumberOfFailuresToSimulate(Integer.MAX_VALUE);
148
149 untilSuccessful.initialise();
150 untilSuccessful.start();
151
152 final MuleEvent testEvent = getTestEvent("ERROR");
153 assertNull(untilSuccessful.process(testEvent));
154 ponderUntilEventAborted(testEvent);
155 }
156
157 @Test
158 public void testPermanentDeliveryFailureExpression() throws Exception
159 {
160 untilSuccessful.setFailureExpression("#[regex:(?i)error]");
161 untilSuccessful.initialise();
162 untilSuccessful.start();
163
164 final MuleEvent testEvent = getTestEvent("ERROR");
165 assertNull(untilSuccessful.process(testEvent));
166 ponderUntilEventAborted(testEvent);
167 }
168
169 @Test
170 public void testPermanentDeliveryFailureDLQ() throws Exception
171 {
172 targetMessageProcessor.setNumberOfFailuresToSimulate(Integer.MAX_VALUE);
173 EndpointBuilder dlqEndpointBuilder = mock(EndpointBuilder.class);
174 OutboundEndpoint dlqEndpoint = mock(OutboundEndpoint.class);
175 when(dlqEndpointBuilder.buildOutboundEndpoint()).thenReturn(dlqEndpoint);
176 untilSuccessful.setDeadLetterQueue(dlqEndpointBuilder);
177 untilSuccessful.initialise();
178 untilSuccessful.start();
179
180 final MuleEvent testEvent = getTestEvent("ERROR");
181 assertNull(untilSuccessful.process(testEvent));
182 ponderUntilEventAborted(testEvent);
183
184 verify(dlqEndpoint).process(any(MuleEvent.class));
185 }
186
187 @Test
188 public void testTemporaryDeliveryFailure() throws Exception
189 {
190 targetMessageProcessor.setNumberOfFailuresToSimulate(untilSuccessful.getMaxRetries());
191
192 untilSuccessful.initialise();
193 untilSuccessful.start();
194
195 final MuleEvent testEvent = getTestEvent("ERROR");
196 assertNull(untilSuccessful.process(testEvent));
197 ponderUntilEventProcessed(testEvent);
198 assertEquals(targetMessageProcessor.getEventCount(), untilSuccessful.getMaxRetries() + 1);
199 }
200
201 @Test
202 public void testPreExistingEvents() throws Exception
203 {
204 final MuleEvent testEvent = getTestEvent("test_data");
205 objectStore.store(UntilSuccessful.EventStoreKey.buildFor(testEvent), testEvent);
206 untilSuccessful.initialise();
207 untilSuccessful.start();
208 ponderUntilEventProcessed(testEvent);
209 }
210
211 private void ponderUntilEventProcessed(final MuleEvent testEvent)
212 throws InterruptedException, MuleException
213 {
214 while (targetMessageProcessor.getEventReceived() == null)
215 {
216 Thread.yield();
217 Thread.sleep(250L);
218 }
219
220 assertEquals(0, objectStore.allKeys().size());
221 assertLogicallyEqualEvents(testEvent, targetMessageProcessor.getEventReceived());
222 }
223
224 private void ponderUntilEventAborted(final MuleEvent testEvent)
225 throws InterruptedException, MuleException
226 {
227 while (targetMessageProcessor.getEventCount() <= untilSuccessful.getMaxRetries())
228 {
229 Thread.yield();
230 Thread.sleep(250L);
231 }
232
233 assertEquals(0, objectStore.allKeys().size());
234 assertEquals(targetMessageProcessor.getEventCount(), 1 + untilSuccessful.getMaxRetries());
235 }
236
237 private void assertLogicallyEqualEvents(final MuleEvent testEvent, MuleEvent eventReceived)
238 throws MuleException
239 {
240
241 assertEquals(testEvent.getMessage().getCorrelationId(), eventReceived.getMessage().getCorrelationId());
242
243 assertEquals(testEvent.getMessageAsString(), eventReceived.getMessageAsString());
244 }
245 }