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 new TransformationPaths());
85 EventListener logListener = new LoggingEventListener(Level.INFO);
86 listener = spy(logListener);
87 router = new XMLRouter(new SystemClock(), config, listener);
88 source1 = mock(DOMSource.class);
89 source2 = mock(DOMSource.class);
90 source3 = mock(DOMSource.class);
94 public void testNoInputDocumentsRegistered() {
95 Destination destination = new MyDestination(true, Arrays.asList("any"));
96 destinationSpy = spy(destination);
98 destinationId = router.registerDestination(destinationSpy);
99 router.publish("any", source1);
100 verify(listener).notDelivered(any(EventInfo.class));
104 public void testMisBehavingDocumentType() {
105 DocumentType type = mock(DocumentType.class);
106 doThrow(new RuntimeException("x")).when(type).isInstance(
107 any(DOMSource.class));
108 routerConfig.documentTypeConfig().add(type);
109 router.publish("xx", mock(DOMSource.class));
110 verify(listener).notDelivered(any(EventInfo.class));
111 // no exception should occur.
115 public void testMisBehavingFilter() {
116 registerDocumentType("any");
117 Filter filter = mock(Filter.class);
118 doThrow(new RuntimeException("x")).when(filter).isAllowed(anyString(),
119 any(DOMSource.class));
120 routerConfig.filterConfig().add(filter);
121 router.publish("xx", mock(DOMSource.class));
122 verify(listener).notDelivered(any(EventInfo.class));
123 // no exception should occur.
127 public void testOneDestinationNoTransformationSuccess() {
128 destinationSpy = registerDestination(true, "any");
129 registerDocumentType("any");
131 router.publish("any", source1);
132 verify(listener).delivered(any(EventInfo.class),
133 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
134 verify(destinationSpy).receive(same(source1));
136 // Unregister the destination.
137 router.unregisterDestination(destinationId);
139 router.publish("any", source2);
140 verify(listener).notDelivered(any(EventInfo.class));
141 verifyNoMoreInteractions(destinationSpy);
144 private void resetMocks() {
145 reset(destinationSpy);
149 private void registerDocumentType(String aType) {
150 DocumentType type = mock(DocumentType.class);
151 when(type.isInstance(any(DOMSource.class))).thenReturn(true);
152 when(type.getName()).thenReturn(aType);
153 Id<DocumentType> typeId = routerConfig.documentTypeConfig().add(type);
156 private void registerDocumentType(String aType, DOMSource aSource) {
157 DocumentType type = mock(DocumentType.class);
158 when(type.isInstance(same(aSource))).thenReturn(true);
159 when(type.getName()).thenReturn(aType);
160 Id<DocumentType> typeId = routerConfig.documentTypeConfig().add(type);
163 private Destination registerDestination(boolean aResult, String... types) {
164 Destination destination = new MyDestination(aResult,
165 Arrays.asList(types));
166 Destination myspy = spy(destination);
167 destinationId = router.registerDestination(myspy);
172 public void testOneDestinationNotMatches() {
173 destinationSpy = registerDestination(true);
174 registerDocumentType("any");
176 router.publish("any", source1);
177 verify(listener).notDelivered(any(EventInfo.class));
178 verify(destinationSpy, never()).receive(any(DOMSource.class));
182 public void testOneDestinationThrowsException() {
183 destinationSpy = registerDestination(true, "any");
184 registerDocumentType("any");
186 doThrow(new RuntimeException()).when(destinationSpy).receive(
187 any(DOMSource.class));
189 router.publish("any", source1);
190 verify(listener).notDelivered(any(EventInfo.class));
191 verify(destinationSpy).receive(same(source1));
195 public void testOneDestinationThrowsExceptionSecondDestinationStillHandled() {
196 testOneDestinationThrowsException();
197 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
198 Destination destinationSpy2 = spy(destination2);
199 Id<Destination> destinationId2 = router
200 .registerDestination(destinationSpy2);
202 router.publish("any", source1);
203 verify(listener).delivered(any(EventInfo.class),
204 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
206 verify(destinationSpy2).receive(same(source1));
211 public void testDestinationChooseFromTargetTypesThrowsException() {
212 destinationSpy = registerDestination(true, "any");
213 registerDocumentType("any");
215 doThrow(new RuntimeException()).when(destinationSpy)
216 .chooseFromTargetTypes((Collection<String>) anyObject());
218 router.publish("any", source1);
219 verify(listener).notDelivered(any(EventInfo.class));
220 verify(destinationSpy, never()).receive(same(source1));
224 public void testDestinationChooseFromTargetTypesThrowsExceptionSecondDestinationStillOk() {
225 testDestinationChooseFromTargetTypesThrowsException();
227 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
228 Destination destinationSpy2 = spy(destination2);
229 Id<Destination> destinationId2 = router
230 .registerDestination(destinationSpy2);
231 router.publish("any", source1);
232 verify(listener).delivered(any(EventInfo.class),
233 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
235 verify(destinationSpy, never()).receive(same(source1));
236 verify(destinationSpy2).receive(same(source1));
240 public void testDestinationChooseFromTargetTypesReturnsNull() {
241 destinationSpy = registerDestination(true, "any");
242 registerDocumentType("any");
246 .chooseFromTargetTypes((Collection<String>) anyObject()))
249 router.publish("any", source1);
250 verify(listener).notDelivered(any(EventInfo.class));
251 verify(destinationSpy, never()).receive(same(source1));
255 public void testDestinationChooseFromTargetTypesReturnsNullSecondDestinationStillOk() {
256 testDestinationChooseFromTargetTypesReturnsNull();
258 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
259 Destination destinationSpy2 = spy(destination2);
260 Id<Destination> destinationId2 = router
261 .registerDestination(destinationSpy2);
262 router.publish("any", source1);
263 verify(listener).delivered(any(EventInfo.class),
264 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
266 verify(destinationSpy, never()).receive(same(source1));
267 verify(destinationSpy2).receive(same(source1));
271 public void testOneTransformationOneDestination() {
272 registerDocumentType("any");
273 Transformation transformation = mock(Transformation.class);
274 when(transformation.getName()).thenReturn("trans");
275 when(transformation.getFromType()).thenReturn("any");
276 when(transformation.getToType()).thenReturn("bla");
277 when(transformation.transform(same(source1))).thenReturn(source2);
278 routerConfig.transformationConfig().add(transformation);
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);
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);
360 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
361 .thenReturn(Arrays.asList("bla", "bla2"));
363 reset(transformation);
364 when(transformation.getName()).thenReturn("trans");
365 when(transformation.getFromType()).thenReturn("any");
366 when(transformation.getToType()).thenReturn("bla");
367 when(transformation.transform(same(source1))).thenReturn(null);
369 when(destination.receive(any(DOMSource.class))).thenReturn(true);
370 router.publish("bla", source1);
371 verify(listener).delivered(any(EventInfo.class),
372 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
374 verify(transformation).transform(source1);
375 verify(transformation2).transform(source1);
377 verify(destination).receive(same(source2));
382 public void testChooseMultipleDestinationsOneType() {
383 Destination dest1 = registerDestination(true, "any");
384 Destination dest2 = registerDestination(true, "any");
385 registerDocumentType("any");
387 router.publish("source", source1);
388 verify(listener, times(2)).delivered(any(EventInfo.class),
389 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
391 verify(dest1).receive(same(source1));
392 verify(dest2).receive(same(source1));
396 public void testMultipleDeliveryToOneDestination() {
397 Destination dest = registerDestination(true, "any", "other");
398 registerDocumentType("any", source1);
399 registerDocumentType("other", source2);
400 Transformation transformation = createTransformation("any", "other",
402 routerConfig.transformationConfig().add(transformation);
404 router.publish("source", source1);
405 verify(listener, times(2)).delivered(any(EventInfo.class),
406 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
408 verify(dest).receive(same(source1));
409 verify(dest).receive(same(source2));
413 public void testMultipleTransformations() {
414 Destination dest = registerDestination(true, "other");
415 registerDocumentType("any", source1);
416 registerDocumentType("other", source3);
418 Transformation t1 = createTransformation("any", "intermediate",
420 routerConfig.transformationConfig().add(t1);
421 Transformation t2 = createTransformation("intermediate", "other",
423 routerConfig.transformationConfig().add(t2);
425 router.publish("source", source1);
426 verify(listener).delivered(any(EventInfo.class),
427 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
429 verify(dest).receive(same(source3));
433 public void testDestinationGivesError() {
434 Destination destination = mock(Destination.class);
435 when(destination.getName()).thenReturn("name");
436 when(destination.chooseFromTargetTypes(anyCollectionOf(String.class)))
437 .thenReturn(Arrays.asList("any"));
438 doThrow(new RuntimeException("x")).when(destination).receive(
439 any(DOMSource.class));
440 router.registerDestination(destination);
442 registerDocumentType("any");
444 router.publish("source", source1);
446 verify(listener).delivered(any(EventInfo.class),
447 anyListOf(Transformation.class), anyLong(), anyString(), eq(false));