2 * Copyright 2005-2011 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.xmlrouter.impl;
18 import static org.mockito.Matchers.*;
19 import static org.mockito.Mockito.*;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.logging.Level;
25 import javax.xml.transform.dom.DOMSource;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.wamblee.general.SystemClock;
30 import org.wamblee.xmlrouter.common.Id;
31 import org.wamblee.xmlrouter.config.DocumentType;
32 import org.wamblee.xmlrouter.config.Filter;
33 import org.wamblee.xmlrouter.config.Transformation;
34 import org.wamblee.xmlrouter.listener.EventInfo;
35 import org.wamblee.xmlrouter.listener.EventListener;
36 import org.wamblee.xmlrouter.listener.LoggingEventListener;
37 import org.wamblee.xmlrouter.subscribe.Destination;
39 public class XMLRouterTest {
41 public static class MyDestination implements Destination {
43 private boolean receiveResult;
44 private Collection<String> types;
46 public MyDestination(boolean aReceiveResult, Collection<String> aTypes) {
47 receiveResult = aReceiveResult;
52 public Collection<String> chooseFromTargetTypes(
53 Collection<String> aPossibleTargetTypes) {
58 public String getName() {
63 public boolean receive(DOMSource aEvent) {
68 private XMLRouter router;
69 private DOMSource source1;
70 private DOMSource source2;
71 private DOMSource source3;
73 private Destination destinationSpy;
74 private Id<Destination> destinationId;
75 private EventListener listener;
79 EventListener logListener = new LoggingEventListener(Level.INFO);
80 listener = spy(logListener);
81 router = new XMLRouter(new SystemClock(), listener);
82 source1 = mock(DOMSource.class);
83 source2 = mock(DOMSource.class);
84 source3 = mock(DOMSource.class);
88 public void testNoInputDocumentsRegistered() {
89 Destination destination = new MyDestination(true, Arrays.asList("any"));
90 destinationSpy = spy(destination);
92 destinationId = router.registerDestination(destinationSpy);
93 router.publish("any", source1);
94 verify(listener).notDelivered(any(EventInfo.class));
98 public void testMisBehavingDocumentType() {
99 DocumentType type = mock(DocumentType.class);
100 doThrow(new RuntimeException("x")).when(type).isInstance(
101 any(DOMSource.class));
102 router.documentTypeConfig().add(type);
103 router.publish("xx", mock(DOMSource.class));
104 verify(listener).notDelivered(any(EventInfo.class));
105 // no exception should occur.
109 public void testMisBehavingFilter() {
110 registerDocumentType("any");
111 Filter filter = mock(Filter.class);
112 doThrow(new RuntimeException("x")).when(filter).isAllowed(anyString(),
113 any(DOMSource.class));
114 router.filterConfig().add(filter);
115 router.publish("xx", mock(DOMSource.class));
116 verify(listener).notDelivered(any(EventInfo.class));
117 // no exception should occur.
121 public void testOneDestinationNoTransformationSuccess() {
122 destinationSpy = registerDestination(true, "any");
123 registerDocumentType("any");
125 router.publish("any", source1);
126 verify(listener).delivered(any(EventInfo.class),
127 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
128 verify(destinationSpy).receive(same(source1));
130 // Unregister the destination.
131 router.unregisterDestination(destinationId);
133 router.publish("any", source2);
134 verify(listener).notDelivered(any(EventInfo.class));
135 verifyNoMoreInteractions(destinationSpy);
138 private void resetMocks() {
139 reset(destinationSpy);
143 private void registerDocumentType(String aType) {
144 DocumentType type = mock(DocumentType.class);
145 when(type.isInstance(any(DOMSource.class))).thenReturn(true);
146 when(type.getName()).thenReturn(aType);
147 Id<DocumentType> typeId = router.documentTypeConfig().add(type);
150 private void registerDocumentType(String aType, DOMSource aSource) {
151 DocumentType type = mock(DocumentType.class);
152 when(type.isInstance(same(aSource))).thenReturn(true);
153 when(type.getName()).thenReturn(aType);
154 Id<DocumentType> typeId = router.documentTypeConfig().add(type);
157 private Destination registerDestination(boolean aResult, String... types) {
158 Destination destination = new MyDestination(aResult,
159 Arrays.asList(types));
160 Destination myspy = spy(destination);
161 destinationId = router.registerDestination(myspy);
166 public void testOneDestinationNotMatches() {
167 destinationSpy = registerDestination(true);
168 registerDocumentType("any");
170 router.publish("any", source1);
171 verify(listener).notDelivered(any(EventInfo.class));
172 verify(destinationSpy, never()).receive(any(DOMSource.class));
176 public void testOneDestinationThrowsException() {
177 destinationSpy = registerDestination(true, "any");
178 registerDocumentType("any");
180 doThrow(new RuntimeException()).when(destinationSpy).receive(
181 any(DOMSource.class));
183 router.publish("any", source1);
184 verify(listener).notDelivered(any(EventInfo.class));
185 verify(destinationSpy).receive(same(source1));
189 public void testOneDestinationThrowsExceptionSecondDestinationStillHandled() {
190 testOneDestinationThrowsException();
191 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
192 Destination destinationSpy2 = spy(destination2);
193 Id<Destination> destinationId2 = router
194 .registerDestination(destinationSpy2);
196 router.publish("any", source1);
197 verify(listener).delivered(any(EventInfo.class),
198 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
200 verify(destinationSpy2).receive(same(source1));
205 public void testDestinationChooseFromTargetTypesThrowsException() {
206 destinationSpy = registerDestination(true, "any");
207 registerDocumentType("any");
209 doThrow(new RuntimeException()).when(destinationSpy)
210 .chooseFromTargetTypes((Collection<String>) anyObject());
212 router.publish("any", source1);
213 verify(listener).notDelivered(any(EventInfo.class));
214 verify(destinationSpy, never()).receive(same(source1));
218 public void testDestinationChooseFromTargetTypesThrowsExceptionSecondDestinationStillOk() {
219 testDestinationChooseFromTargetTypesThrowsException();
221 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
222 Destination destinationSpy2 = spy(destination2);
223 Id<Destination> destinationId2 = router
224 .registerDestination(destinationSpy2);
225 router.publish("any", source1);
226 verify(listener).delivered(any(EventInfo.class),
227 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
229 verify(destinationSpy, never()).receive(same(source1));
230 verify(destinationSpy2).receive(same(source1));
234 public void testDestinationChooseFromTargetTypesReturnsNull() {
235 destinationSpy = registerDestination(true, "any");
236 registerDocumentType("any");
240 .chooseFromTargetTypes((Collection<String>) anyObject()))
243 router.publish("any", source1);
244 verify(listener).notDelivered(any(EventInfo.class));
245 verify(destinationSpy, never()).receive(same(source1));
249 public void testDestinationChooseFromTargetTypesReturnsNullSecondDestinationStillOk() {
250 testDestinationChooseFromTargetTypesReturnsNull();
252 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
253 Destination destinationSpy2 = spy(destination2);
254 Id<Destination> destinationId2 = router
255 .registerDestination(destinationSpy2);
256 router.publish("any", source1);
257 verify(listener).delivered(any(EventInfo.class),
258 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
260 verify(destinationSpy, never()).receive(same(source1));
261 verify(destinationSpy2).receive(same(source1));
265 public void testOneTransformationOneDestination() {
266 registerDocumentType("any");
267 Transformation transformation = mock(Transformation.class);
268 when(transformation.getName()).thenReturn("trans");
269 when(transformation.getFromType()).thenReturn("any");
270 when(transformation.getToType()).thenReturn("bla");
271 when(transformation.transform(same(source1))).thenReturn(source2);
272 router.transformationConfig().add(transformation);
274 Destination destination = mock(Destination.class);
276 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
277 .thenReturn(Arrays.asList("bla"));
279 router.registerDestination(destination);
281 when(destination.receive(any(DOMSource.class))).thenReturn(true);
282 router.publish("bla", source1);
283 verify(listener).delivered(any(EventInfo.class),
284 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
286 verify(transformation).transform(source1);
287 verify(destination).receive(same(source2));
289 // now the same when the destination rejects the event.
290 when(destination.receive(any(DOMSource.class))).thenReturn(false);
291 router.publish("bla", source1);
292 verify(listener).notDelivered(any(EventInfo.class));
296 public void testMisbehavingTransformationOneDestination() {
297 registerDocumentType("any");
298 Transformation transformation = mock(Transformation.class);
299 when(transformation.getName()).thenReturn("trans");
300 when(transformation.getFromType()).thenReturn("any");
301 when(transformation.getToType()).thenReturn("bla");
302 doThrow(new RuntimeException("x")).when(transformation).transform(
304 router.transformationConfig().add(transformation);
306 Destination destination = mock(Destination.class);
308 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
309 .thenReturn(Arrays.asList("bla"));
311 router.registerDestination(destination);
313 when(destination.receive(any(DOMSource.class))).thenReturn(true);
314 router.publish("bla", source1);
315 verify(listener).notDelivered(any(EventInfo.class));
318 private Transformation createTransformation(String aFrom, String aTo,
319 DOMSource aSource, DOMSource aTarget) {
320 Transformation transformation = mock(Transformation.class);
321 when(transformation.getName()).thenReturn("trans");
322 when(transformation.getFromType()).thenReturn(aFrom);
323 when(transformation.getToType()).thenReturn(aTo);
324 when(transformation.transform(same(aSource))).thenReturn(aTarget);
325 return transformation;
329 public void testOneTransformationReturnsNull() {
330 registerDocumentType("any");
331 Transformation transformation = createTransformation("any", "bla",
334 router.transformationConfig().add(transformation);
336 Destination destination = mock(Destination.class);
338 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
339 .thenReturn(Arrays.asList("bla"));
340 router.registerDestination(destination);
342 router.publish("bla", source1);
343 verify(listener).notDelivered(any(EventInfo.class));
345 verify(transformation).transform(source1);
346 verify(destination, never()).receive(any(DOMSource.class));
348 // add second transformation that behaves normally
349 Transformation transformation2 = createTransformation("any", "bla2",
352 router.transformationConfig().add(transformation2);
354 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
355 .thenReturn(Arrays.asList("bla", "bla2"));
357 reset(transformation);
358 when(transformation.getName()).thenReturn("trans");
359 when(transformation.getFromType()).thenReturn("any");
360 when(transformation.getToType()).thenReturn("bla");
361 when(transformation.transform(same(source1))).thenReturn(null);
363 when(destination.receive(any(DOMSource.class))).thenReturn(true);
364 router.publish("bla", source1);
365 verify(listener).delivered(any(EventInfo.class),
366 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
368 verify(transformation).transform(source1);
369 verify(transformation2).transform(source1);
371 verify(destination).receive(same(source2));
376 public void testChooseMultipleDestinationsOneType() {
377 Destination dest1 = registerDestination(true, "any");
378 Destination dest2 = registerDestination(true, "any");
379 registerDocumentType("any");
381 router.publish("source", source1);
382 verify(listener, times(2)).delivered(any(EventInfo.class),
383 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
385 verify(dest1).receive(same(source1));
386 verify(dest2).receive(same(source1));
390 public void testMultipleDeliveryToOneDestination() {
391 Destination dest = registerDestination(true, "any", "other");
392 registerDocumentType("any", source1);
393 registerDocumentType("other", source2);
394 Transformation transformation = createTransformation("any", "other",
396 router.transformationConfig().add(transformation);
398 router.publish("source", source1);
399 verify(listener, times(2)).delivered(any(EventInfo.class),
400 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
402 verify(dest).receive(same(source1));
403 verify(dest).receive(same(source2));
407 public void testMultipleTransformations() {
408 Destination dest = registerDestination(true, "other");
409 registerDocumentType("any", source1);
410 registerDocumentType("other", source3);
412 Transformation t1 = createTransformation("any", "intermediate",
414 router.transformationConfig().add(t1);
415 Transformation t2 = createTransformation("intermediate", "other",
417 router.transformationConfig().add(t2);
419 router.publish("source", source1);
420 verify(listener).delivered(any(EventInfo.class),
421 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
423 verify(dest).receive(same(source3));
427 public void testDestinationGivesError() {
428 Destination destination = mock(Destination.class);
429 when(destination.getName()).thenReturn("name");
430 when(destination.chooseFromTargetTypes(anyCollectionOf(String.class)))
431 .thenReturn(Arrays.asList("any"));
432 doThrow(new RuntimeException("x")).when(destination).receive(
433 any(DOMSource.class));
434 router.registerDestination(destination);
436 registerDocumentType("any");
438 router.publish("source", source1);
440 verify(listener).delivered(any(EventInfo.class),
441 anyListOf(Transformation.class), anyLong(), anyString(), eq(false));