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.getTransformations().replaceTransformations(
279 routerConfig.transformationConfig().map());
281 Destination destination = mock(Destination.class);
283 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
284 .thenReturn(Arrays.asList("bla"));
286 router.registerDestination(destination);
288 when(destination.receive(any(DOMSource.class))).thenReturn(true);
289 router.publish("bla", source1);
290 verify(listener).delivered(any(EventInfo.class),
291 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
293 verify(transformation).transform(source1);
294 verify(destination).receive(same(source2));
296 // now the same when the destination rejects the event.
297 when(destination.receive(any(DOMSource.class))).thenReturn(false);
298 router.publish("bla", source1);
299 verify(listener).notDelivered(any(EventInfo.class));
303 public void testMisbehavingTransformationOneDestination() {
304 registerDocumentType("any");
305 Transformation transformation = mock(Transformation.class);
306 when(transformation.getName()).thenReturn("trans");
307 when(transformation.getFromType()).thenReturn("any");
308 when(transformation.getToType()).thenReturn("bla");
309 doThrow(new RuntimeException("x")).when(transformation).transform(
311 routerConfig.transformationConfig().add(transformation);
313 Destination destination = mock(Destination.class);
315 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
316 .thenReturn(Arrays.asList("bla"));
318 router.registerDestination(destination);
320 when(destination.receive(any(DOMSource.class))).thenReturn(true);
321 router.publish("bla", source1);
322 verify(listener).notDelivered(any(EventInfo.class));
325 private Transformation createTransformation(String aFrom, String aTo,
326 DOMSource aSource, DOMSource aTarget) {
327 Transformation transformation = mock(Transformation.class);
328 when(transformation.getName()).thenReturn("trans");
329 when(transformation.getFromType()).thenReturn(aFrom);
330 when(transformation.getToType()).thenReturn(aTo);
331 when(transformation.transform(same(aSource))).thenReturn(aTarget);
332 return transformation;
336 public void testOneTransformationReturnsNull() {
337 registerDocumentType("any");
338 Transformation transformation = createTransformation("any", "bla",
341 routerConfig.transformationConfig().add(transformation);
342 config.getTransformations().replaceTransformations(
343 routerConfig.transformationConfig().map());
345 Destination destination = mock(Destination.class);
347 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
348 .thenReturn(Arrays.asList("bla"));
349 router.registerDestination(destination);
351 router.publish("bla", source1);
352 verify(listener).notDelivered(any(EventInfo.class));
354 verify(transformation).transform(source1);
355 verify(destination, never()).receive(any(DOMSource.class));
357 // add second transformation that behaves normally
358 Transformation transformation2 = createTransformation("any", "bla2",
361 routerConfig.transformationConfig().add(transformation2);
362 config.getTransformations().replaceTransformations(
363 routerConfig.transformationConfig().map());
365 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
366 .thenReturn(Arrays.asList("bla", "bla2"));
368 reset(transformation);
369 when(transformation.getName()).thenReturn("trans");
370 when(transformation.getFromType()).thenReturn("any");
371 when(transformation.getToType()).thenReturn("bla");
372 when(transformation.transform(same(source1))).thenReturn(null);
374 when(destination.receive(any(DOMSource.class))).thenReturn(true);
375 router.publish("bla", source1);
376 verify(listener).delivered(any(EventInfo.class),
377 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
379 verify(transformation).transform(source1);
380 verify(transformation2).transform(source1);
382 verify(destination).receive(same(source2));
387 public void testChooseMultipleDestinationsOneType() {
388 Destination dest1 = registerDestination(true, "any");
389 Destination dest2 = registerDestination(true, "any");
390 registerDocumentType("any");
392 router.publish("source", source1);
393 verify(listener, times(2)).delivered(any(EventInfo.class),
394 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
396 verify(dest1).receive(same(source1));
397 verify(dest2).receive(same(source1));
401 public void testMultipleDeliveryToOneDestination() {
402 Destination dest = registerDestination(true, "any", "other");
403 registerDocumentType("any", source1);
404 registerDocumentType("other", source2);
405 Transformation transformation = createTransformation("any", "other",
407 routerConfig.transformationConfig().add(transformation);
408 config.getTransformations().replaceTransformations(
409 routerConfig.transformationConfig().map());
411 router.publish("source", source1);
412 verify(listener, times(2)).delivered(any(EventInfo.class),
413 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
415 verify(dest).receive(same(source1));
416 verify(dest).receive(same(source2));
420 public void testMultipleTransformations() {
421 Destination dest = registerDestination(true, "other");
422 registerDocumentType("any", source1);
423 registerDocumentType("other", source3);
425 Transformation t1 = createTransformation("any", "intermediate",
427 routerConfig.transformationConfig().add(t1);
428 Transformation t2 = createTransformation("intermediate", "other",
430 routerConfig.transformationConfig().add(t2);
431 config.getTransformations().replaceTransformations(
432 routerConfig.transformationConfig().map());
434 router.publish("source", source1);
435 verify(listener).delivered(any(EventInfo.class),
436 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
438 verify(dest).receive(same(source3));
442 public void testDestinationGivesError() {
443 Destination destination = mock(Destination.class);
444 when(destination.getName()).thenReturn("name");
445 when(destination.chooseFromTargetTypes(anyCollectionOf(String.class)))
446 .thenReturn(Arrays.asList("any"));
447 doThrow(new RuntimeException("x")).when(destination).receive(
448 any(DOMSource.class));
449 router.registerDestination(destination);
451 registerDocumentType("any");
453 router.publish("source", source1);
455 verify(listener).delivered(any(EventInfo.class),
456 anyListOf(Transformation.class), anyLong(), anyString(), eq(false));