1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.MuleException;
15 import org.mule.api.context.WorkManager;
16 import org.mule.api.endpoint.ImmutableEndpoint;
17 import org.mule.api.retry.RetryCallback;
18 import org.mule.api.retry.RetryPolicyTemplate;
19 import org.mule.endpoint.MuleEndpointURI;
20 import org.mule.transport.MuleAbstractConnectableTestCase.MethodInvocation.MethodPart;
21
22 import java.util.List;
23 import java.util.Vector;
24 import java.util.concurrent.atomic.AtomicBoolean;
25
26 import edu.umd.cs.mtc.MultithreadedTestCase;
27 import edu.umd.cs.mtc.TestFramework;
28
29 import org.apache.commons.lang.builder.EqualsBuilder;
30 import org.apache.commons.lang.builder.HashCodeBuilder;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.junit.After;
34 import org.junit.Before;
35 import org.junit.Ignore;
36 import org.junit.Test;
37 import org.mockito.invocation.InvocationOnMock;
38 import org.mockito.stubbing.Answer;
39
40 import static org.junit.Assert.fail;
41 import static org.mockito.Matchers.any;
42 import static org.mockito.Mockito.mock;
43 import static org.mockito.Mockito.when;
44
45
46
47
48
49
50 public class MuleAbstractConnectableTestCase
51 {
52
53
54
55 static Log log = LogFactory.getLog(MuleAbstractConnectableTestCase.class);
56
57 @Test
58 public void testStartRethrowsMuleExceptionCorrectly() throws Exception
59 {
60 final MuleException someMuleException = mock(MuleException.class);
61 AbstractConnectable connectable = new AbstractConnectable(createDummyEndpoint())
62 {
63 @Override
64 protected void doStart() throws MuleException
65 {
66 throw someMuleException;
67 }
68
69 @Override
70 protected WorkManager getWorkManager()
71 {
72 return null;
73 }
74
75 @Override
76 protected ConnectableLifecycleManager createLifecycleManager()
77 {
78 return new ConnectableLifecycleManager("test", this);
79 }
80 };
81 connectable.initialise();
82 connectable.connect();
83 try
84 {
85 connectable.start();
86 fail("Should have thrown a " + MuleException.class.getSimpleName());
87 }
88 catch (MuleException caughtException)
89 {
90 assertExceptionIsInCaughtException(someMuleException, caughtException);
91 }
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106 @Ignore
107 @Test
108 public void testStartIsThreadSafe() throws Throwable
109 {
110 TestFramework.runOnce(new AbstractConnectableMultithreaded());
111 }
112
113
114
115
116
117
118 @Ignore
119 class AbstractConnectableMultithreaded extends MultithreadedTestCase
120 {
121 private volatile AbstractConnectableForTest connectable;
122
123
124
125
126
127 @Override
128 public void initialize()
129 {
130 try
131 {
132 ImmutableEndpoint endpoint = createDummyEndpoint();
133
134 connectable = new AbstractConnectableForTest(endpoint);
135 connectable.initialise();
136 }
137 catch (Exception e)
138 {
139 throw new RuntimeException(e);
140 }
141 }
142
143
144
145
146
147
148
149
150 public void thread1() throws Exception
151 {
152 connectable.start();
153 }
154
155
156
157
158
159 public void thread2() throws Exception
160 {
161
162
163 waitForTick(1);
164 connectable.start();
165 }
166
167
168
169
170
171 @Override
172 public void finish()
173 {
174 for (MethodInvocation methodInvocation : connectable.methodInvocations)
175 {
176 log.debug(methodInvocation);
177 }
178
179 int i = 0;
180 assertEquals("doConnect", connectable.methodInvocations.get(i++).getMethodName());
181 assertEquals("doConnect", connectable.methodInvocations.get(i++).getMethodName());
182 assertEquals("doStart", connectable.methodInvocations.get(i++).getMethodName());
183 assertEquals("doStart", connectable.methodInvocations.get(i++).getMethodName());
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197 @Ignore
198 class AbstractConnectableForTest extends AbstractConnectable
199 {
200 private final AtomicBoolean doConnectCalled = new AtomicBoolean();
201 private final AtomicBoolean doStartCalled = new AtomicBoolean();
202
203
204
205
206
207
208 List<MethodInvocation> methodInvocations = new Vector<MethodInvocation>();
209
210 public AbstractConnectableForTest(ImmutableEndpoint endpoint)
211 {
212 super(endpoint);
213 }
214
215 @Override
216 protected WorkManager getWorkManager()
217 {
218 return null;
219 }
220
221 @Override
222 protected ConnectableLifecycleManager createLifecycleManager()
223 {
224 return new ConnectableLifecycleManager("test", this);
225 }
226
227 @Override
228 protected void doConnect() throws Exception
229 {
230 methodInvocations.add(new MethodInvocation(Thread.currentThread(), "doConnect",
231 MethodPart.BEGINNING));
232 assertTrue(doConnectCalled.compareAndSet(false, true));
233 assertFalse(doStartCalled.get());
234
235
236
237
238
239
240
241 waitForTick(2);
242
243 assertFalse(doStartCalled.get());
244
245 methodInvocations.add(new MethodInvocation(Thread.currentThread(), "doConnect",
246 MethodPart.END));
247 }
248
249 @Override
250 protected void doStart() throws MuleException
251 {
252 methodInvocations.add(new MethodInvocation(Thread.currentThread(), "doStart",
253 MethodPart.BEGINNING));
254 assertTrue(doStartCalled.compareAndSet(false, true));
255 assertTrue(doConnectCalled.get());
256 methodInvocations.add(new MethodInvocation(Thread.currentThread(), "doStart", MethodPart.END));
257 }
258
259 }
260 }
261
262
263
264
265
266 @org.junit.Ignore
267 static class MethodInvocation
268 {
269 @Ignore
270 static enum MethodPart
271 {
272 BEGINNING, END
273 }
274
275 private final Thread thread;
276 private final String methodName;
277 private final MethodPart methodPart;
278
279 public MethodInvocation(Thread thread, String methodName, MethodPart methodPart)
280 {
281 this.thread = thread;
282 this.methodName = methodName;
283 this.methodPart = methodPart;
284 }
285
286 public Thread getThread()
287 {
288 return thread;
289 }
290
291 public String getMethodName()
292 {
293 return methodName;
294 }
295
296 public MethodPart getMethodPart()
297 {
298 return methodPart;
299 }
300
301 @Override
302 public boolean equals(Object obj)
303 {
304 if (this == obj)
305 {
306 return true;
307 }
308 else if (obj == null || obj.getClass() != this.getClass())
309 {
310 return false;
311 }
312 else
313 {
314 MethodInvocation other = (MethodInvocation) obj;
315 return new EqualsBuilder().append(this.thread, other.thread).append(this.methodName,
316 other.methodName).append(this.methodPart, other.methodPart).isEquals();
317 }
318 }
319
320 @Override
321 public int hashCode()
322 {
323 return new HashCodeBuilder().append(this.thread)
324 .append(this.methodName)
325 .append(this.methodPart)
326 .toHashCode();
327 }
328
329 @Override
330 public String toString()
331 {
332 return "Thread " + this.thread + " passing through " + this.methodName + "() at the "
333 + this.methodPart;
334 }
335 }
336
337 private void assertExceptionIsInCaughtException(MuleException someMuleException, MuleException caughtException)
338 {
339 boolean found = false;
340 Throwable candidate = caughtException;
341 while (candidate != null)
342 {
343 if (someMuleException.equals(candidate))
344 {
345 found = true;
346 break;
347 }
348
349 candidate = candidate.getCause();
350 }
351
352 if (found == false)
353 {
354 fail();
355 }
356 }
357
358
359
360
361
362
363 ImmutableEndpoint createDummyEndpoint() throws Exception
364 {
365 ImmutableEndpoint endpoint = mock(ImmutableEndpoint.class);
366 MuleContext muleContext = mock(MuleContext.class);
367 when(endpoint.getEndpointURI()).thenReturn(new MuleEndpointURI("http://dummy.endpoint/", muleContext));
368 AbstractConnector connector = mock(AbstractConnector.class);
369 when(endpoint.getConnector()).thenReturn(connector);
370
371 RetryPolicyTemplate retryPolicyTemplate = mock(RetryPolicyTemplate.class);
372 when(endpoint.getRetryPolicyTemplate()).thenReturn(retryPolicyTemplate);
373 when(retryPolicyTemplate.execute(any(RetryCallback.class), any(WorkManager.class))).thenAnswer(
374 new Answer<Object>()
375 {
376 public Object answer(InvocationOnMock invocation) throws Throwable
377 {
378 RetryCallback retryCallback = (RetryCallback) invocation.getArguments()[0];
379 retryCallback.doWork(null);
380 return null;
381 }
382 });
383
384 return endpoint;
385 }
386 }