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.concurrent.atomic.AtomicLong;
24 import java.util.logging.Level;
26 import javax.xml.transform.dom.DOMSource;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.wamblee.general.SystemClock;
31 import org.wamblee.xmlrouter.common.Id;
32 import org.wamblee.xmlrouter.config.DocumentType;
33 import org.wamblee.xmlrouter.config.Filter;
34 import org.wamblee.xmlrouter.config.Transformation;
35 import org.wamblee.xmlrouter.listener.EventInfo;
36 import org.wamblee.xmlrouter.listener.EventListener;
37 import org.wamblee.xmlrouter.listener.LoggingEventListener;
38 import org.wamblee.xmlrouter.subscribe.Destination;
40 public class XMLRouterTest {
42 public static class MyDestination implements Destination {
44 private boolean receiveResult;
45 private Collection<String> types;
47 public MyDestination(boolean aReceiveResult, Collection<String> aTypes) {
48 receiveResult = aReceiveResult;
53 public Collection<String> chooseFromTargetTypes(
54 Collection<String> aPossibleTargetTypes) {
59 public String getName() {
64 public boolean receive(DOMSource aEvent) {
69 private ExtendedRouterConfig routerConfig;
70 private XMLRouterConfiguration config;
71 private XMLRouter router;
72 private DOMSource source1;
73 private DOMSource source2;
74 private DOMSource source3;
76 private Destination destinationSpy;
77 private Id<Destination> destinationId;
78 private EventListener listener;
82 routerConfig = new SingleRouterConfig(new AtomicLong(1L));
83 config = new XMLRouterConfigurationImpl(routerConfig);
84 EventListener logListener = new LoggingEventListener(Level.INFO);
85 listener = spy(logListener);
86 router = new XMLRouter(new SystemClock(), config, listener);
87 source1 = mock(DOMSource.class);
88 source2 = mock(DOMSource.class);
89 source3 = mock(DOMSource.class);
93 public void testNoInputDocumentsRegistered() {
94 Destination destination = new MyDestination(true, Arrays.asList("any"));
95 destinationSpy = spy(destination);
97 destinationId = router.registerDestination(destinationSpy);
98 router.publish("any", source1);
99 verify(listener).notDelivered(any(EventInfo.class));
103 public void testMisBehavingDocumentType() {
104 DocumentType type = mock(DocumentType.class);
105 doThrow(new RuntimeException("x")).when(type).isInstance(
106 any(DOMSource.class));
107 routerConfig.documentTypeConfig().add(type);
108 router.publish("xx", mock(DOMSource.class));
109 verify(listener).notDelivered(any(EventInfo.class));
110 // no exception should occur.
114 public void testMisBehavingFilter() {
115 registerDocumentType("any");
116 Filter filter = mock(Filter.class);
117 doThrow(new RuntimeException("x")).when(filter).isAllowed(anyString(),
118 any(DOMSource.class));
119 routerConfig.filterConfig().add(filter);
120 router.publish("xx", mock(DOMSource.class));
121 verify(listener).notDelivered(any(EventInfo.class));
122 // no exception should occur.
126 public void testOneDestinationNoTransformationSuccess() {
127 destinationSpy = registerDestination(true, "any");
128 registerDocumentType("any");
130 router.publish("any", source1);
131 verify(listener).delivered(any(EventInfo.class),
132 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
133 verify(destinationSpy).receive(same(source1));
135 // Unregister the destination.
136 router.unregisterDestination(destinationId);
138 router.publish("any", source2);
139 verify(listener).notDelivered(any(EventInfo.class));
140 verifyNoMoreInteractions(destinationSpy);
143 private void resetMocks() {
144 reset(destinationSpy);
148 private void registerDocumentType(String aType) {
149 DocumentType type = mock(DocumentType.class);
150 when(type.isInstance(any(DOMSource.class))).thenReturn(true);
151 when(type.getName()).thenReturn(aType);
152 Id<DocumentType> typeId = routerConfig.documentTypeConfig().add(type);
155 private void registerDocumentType(String aType, DOMSource aSource) {
156 DocumentType type = mock(DocumentType.class);
157 when(type.isInstance(same(aSource))).thenReturn(true);
158 when(type.getName()).thenReturn(aType);
159 Id<DocumentType> typeId = routerConfig.documentTypeConfig().add(type);
162 private Destination registerDestination(boolean aResult, String... types) {
163 Destination destination = new MyDestination(aResult,
164 Arrays.asList(types));
165 Destination myspy = spy(destination);
166 destinationId = router.registerDestination(myspy);
171 public void testOneDestinationNotMatches() {
172 destinationSpy = registerDestination(true);
173 registerDocumentType("any");
175 router.publish("any", source1);
176 verify(listener).notDelivered(any(EventInfo.class));
177 verify(destinationSpy, never()).receive(any(DOMSource.class));
181 public void testOneDestinationThrowsException() {
182 destinationSpy = registerDestination(true, "any");
183 registerDocumentType("any");
185 doThrow(new RuntimeException()).when(destinationSpy).receive(
186 any(DOMSource.class));
188 router.publish("any", source1);
189 verify(listener).notDelivered(any(EventInfo.class));
190 verify(destinationSpy).receive(same(source1));
194 public void testOneDestinationThrowsExceptionSecondDestinationStillHandled() {
195 testOneDestinationThrowsException();
196 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
197 Destination destinationSpy2 = spy(destination2);
198 Id<Destination> destinationId2 = router
199 .registerDestination(destinationSpy2);
201 router.publish("any", source1);
202 verify(listener).delivered(any(EventInfo.class),
203 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
205 verify(destinationSpy2).receive(same(source1));
210 public void testDestinationChooseFromTargetTypesThrowsException() {
211 destinationSpy = registerDestination(true, "any");
212 registerDocumentType("any");
214 doThrow(new RuntimeException()).when(destinationSpy)
215 .chooseFromTargetTypes((Collection<String>) anyObject());
217 router.publish("any", source1);
218 verify(listener).notDelivered(any(EventInfo.class));
219 verify(destinationSpy, never()).receive(same(source1));
223 public void testDestinationChooseFromTargetTypesThrowsExceptionSecondDestinationStillOk() {
224 testDestinationChooseFromTargetTypesThrowsException();
226 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
227 Destination destinationSpy2 = spy(destination2);
228 Id<Destination> destinationId2 = router
229 .registerDestination(destinationSpy2);
230 router.publish("any", source1);
231 verify(listener).delivered(any(EventInfo.class),
232 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
234 verify(destinationSpy, never()).receive(same(source1));
235 verify(destinationSpy2).receive(same(source1));
239 public void testDestinationChooseFromTargetTypesReturnsNull() {
240 destinationSpy = registerDestination(true, "any");
241 registerDocumentType("any");
245 .chooseFromTargetTypes((Collection<String>) anyObject()))
248 router.publish("any", source1);
249 verify(listener).notDelivered(any(EventInfo.class));
250 verify(destinationSpy, never()).receive(same(source1));
254 public void testDestinationChooseFromTargetTypesReturnsNullSecondDestinationStillOk() {
255 testDestinationChooseFromTargetTypesReturnsNull();
257 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
258 Destination destinationSpy2 = spy(destination2);
259 Id<Destination> destinationId2 = router
260 .registerDestination(destinationSpy2);
261 router.publish("any", source1);
262 verify(listener).delivered(any(EventInfo.class),
263 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
265 verify(destinationSpy, never()).receive(same(source1));
266 verify(destinationSpy2).receive(same(source1));
270 public void testOneTransformationOneDestination() {
271 registerDocumentType("any");
272 Transformation transformation = mock(Transformation.class);
273 when(transformation.getName()).thenReturn("trans");
274 when(transformation.getFromType()).thenReturn("any");
275 when(transformation.getToType()).thenReturn("bla");
276 when(transformation.transform(same(source1))).thenReturn(source2);
277 routerConfig.transformationConfig().add(transformation);
278 config.setRouterConfig(routerConfig);
280 Destination destination = mock(Destination.class);
282 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
283 .thenReturn(Arrays.asList("bla"));
285 router.registerDestination(destination);
287 when(destination.receive(any(DOMSource.class))).thenReturn(true);
288 router.publish("bla", source1);
289 verify(listener).delivered(any(EventInfo.class),
290 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
292 verify(transformation).transform(source1);
293 verify(destination).receive(same(source2));
295 // now the same when the destination rejects the event.
296 when(destination.receive(any(DOMSource.class))).thenReturn(false);
297 router.publish("bla", source1);
298 verify(listener).notDelivered(any(EventInfo.class));
302 public void testMisbehavingTransformationOneDestination() {
303 registerDocumentType("any");
304 Transformation transformation = mock(Transformation.class);
305 when(transformation.getName()).thenReturn("trans");
306 when(transformation.getFromType()).thenReturn("any");
307 when(transformation.getToType()).thenReturn("bla");
308 doThrow(new RuntimeException("x")).when(transformation).transform(
310 routerConfig.transformationConfig().add(transformation);
312 Destination destination = mock(Destination.class);
314 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
315 .thenReturn(Arrays.asList("bla"));
317 router.registerDestination(destination);
319 when(destination.receive(any(DOMSource.class))).thenReturn(true);
320 router.publish("bla", source1);
321 verify(listener).notDelivered(any(EventInfo.class));
324 private Transformation createTransformation(String aFrom, String aTo,
325 DOMSource aSource, DOMSource aTarget) {
326 Transformation transformation = mock(Transformation.class);
327 when(transformation.getName()).thenReturn("trans");
328 when(transformation.getFromType()).thenReturn(aFrom);
329 when(transformation.getToType()).thenReturn(aTo);
330 when(transformation.transform(same(aSource))).thenReturn(aTarget);
331 return transformation;
335 public void testOneTransformationReturnsNull() {
336 registerDocumentType("any");
337 Transformation transformation = createTransformation("any", "bla",
340 routerConfig.transformationConfig().add(transformation);
341 config.setRouterConfig(routerConfig);
342 Destination destination = mock(Destination.class);
344 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
345 .thenReturn(Arrays.asList("bla"));
346 router.registerDestination(destination);
348 router.publish("bla", source1);
349 verify(listener).notDelivered(any(EventInfo.class));
351 verify(transformation).transform(source1);
352 verify(destination, never()).receive(any(DOMSource.class));
354 // add second transformation that behaves normally
355 Transformation transformation2 = createTransformation("any", "bla2",
358 routerConfig.transformationConfig().add(transformation2);
359 config.setRouterConfig(routerConfig);
361 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
362 .thenReturn(Arrays.asList("bla", "bla2"));
364 reset(transformation);
365 when(transformation.getName()).thenReturn("trans");
366 when(transformation.getFromType()).thenReturn("any");
367 when(transformation.getToType()).thenReturn("bla");
368 when(transformation.transform(same(source1))).thenReturn(null);
370 when(destination.receive(any(DOMSource.class))).thenReturn(true);
371 router.publish("bla", source1);
372 verify(listener).delivered(any(EventInfo.class),
373 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
375 verify(transformation).transform(source1);
376 verify(transformation2).transform(source1);
378 verify(destination).receive(same(source2));
383 public void testChooseMultipleDestinationsOneType() {
384 Destination dest1 = registerDestination(true, "any");
385 Destination dest2 = registerDestination(true, "any");
386 registerDocumentType("any");
388 router.publish("source", source1);
389 verify(listener, times(2)).delivered(any(EventInfo.class),
390 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
392 verify(dest1).receive(same(source1));
393 verify(dest2).receive(same(source1));
397 public void testMultipleDeliveryToOneDestination() {
398 Destination dest = registerDestination(true, "any", "other");
399 registerDocumentType("any", source1);
400 registerDocumentType("other", source2);
401 Transformation transformation = createTransformation("any", "other",
403 routerConfig.transformationConfig().add(transformation);
404 config.setRouterConfig(routerConfig);
406 router.publish("source", source1);
407 verify(listener, times(2)).delivered(any(EventInfo.class),
408 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
410 verify(dest).receive(same(source1));
411 verify(dest).receive(same(source2));
415 public void testMultipleTransformations() {
416 Destination dest = registerDestination(true, "other");
417 registerDocumentType("any", source1);
418 registerDocumentType("other", source3);
420 Transformation t1 = createTransformation("any", "intermediate",
422 routerConfig.transformationConfig().add(t1);
423 Transformation t2 = createTransformation("intermediate", "other",
425 routerConfig.transformationConfig().add(t2);
426 config.setRouterConfig(routerConfig);
428 router.publish("source", source1);
429 verify(listener).delivered(any(EventInfo.class),
430 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
432 verify(dest).receive(same(source3));
436 public void testDestinationGivesError() {
437 Destination destination = mock(Destination.class);
438 when(destination.getName()).thenReturn("name");
439 when(destination.chooseFromTargetTypes(anyCollectionOf(String.class)))
440 .thenReturn(Arrays.asList("any"));
441 doThrow(new RuntimeException("x")).when(destination).receive(
442 any(DOMSource.class));
443 router.registerDestination(destination);
445 registerDocumentType("any");
447 router.publish("source", source1);
449 verify(listener).delivered(any(EventInfo.class),
450 anyListOf(Transformation.class), anyLong(), anyString(), eq(false));