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 XMLRouter router;
71 private DOMSource source1;
72 private DOMSource source2;
73 private DOMSource source3;
75 private Destination destinationSpy;
76 private Id<Destination> destinationId;
77 private EventListener listener;
81 routerConfig = new SingleRouterConfig(new AtomicLong(1L));
82 EventListener logListener = new LoggingEventListener(Level.INFO);
83 listener = spy(logListener);
84 router = new XMLRouter(new SystemClock(), routerConfig, listener);
85 source1 = mock(DOMSource.class);
86 source2 = mock(DOMSource.class);
87 source3 = mock(DOMSource.class);
91 public void testNoInputDocumentsRegistered() {
92 Destination destination = new MyDestination(true, Arrays.asList("any"));
93 destinationSpy = spy(destination);
95 destinationId = router.registerDestination(destinationSpy);
96 router.publish("any", source1);
97 verify(listener).notDelivered(any(EventInfo.class));
101 public void testMisBehavingDocumentType() {
102 DocumentType type = mock(DocumentType.class);
103 doThrow(new RuntimeException("x")).when(type).isInstance(
104 any(DOMSource.class));
105 routerConfig.documentTypeConfig().add(type);
106 router.publish("xx", mock(DOMSource.class));
107 verify(listener).notDelivered(any(EventInfo.class));
108 // no exception should occur.
112 public void testMisBehavingFilter() {
113 registerDocumentType("any");
114 Filter filter = mock(Filter.class);
115 doThrow(new RuntimeException("x")).when(filter).isAllowed(anyString(),
116 any(DOMSource.class));
117 routerConfig.filterConfig().add(filter);
118 router.publish("xx", mock(DOMSource.class));
119 verify(listener).notDelivered(any(EventInfo.class));
120 // no exception should occur.
124 public void testOneDestinationNoTransformationSuccess() {
125 destinationSpy = registerDestination(true, "any");
126 registerDocumentType("any");
128 router.publish("any", source1);
129 verify(listener).delivered(any(EventInfo.class),
130 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
131 verify(destinationSpy).receive(same(source1));
133 // Unregister the destination.
134 router.unregisterDestination(destinationId);
136 router.publish("any", source2);
137 verify(listener).notDelivered(any(EventInfo.class));
138 verifyNoMoreInteractions(destinationSpy);
141 private void resetMocks() {
142 reset(destinationSpy);
146 private void registerDocumentType(String aType) {
147 DocumentType type = mock(DocumentType.class);
148 when(type.isInstance(any(DOMSource.class))).thenReturn(true);
149 when(type.getName()).thenReturn(aType);
150 Id<DocumentType> typeId = routerConfig.documentTypeConfig().add(type);
153 private void registerDocumentType(String aType, DOMSource aSource) {
154 DocumentType type = mock(DocumentType.class);
155 when(type.isInstance(same(aSource))).thenReturn(true);
156 when(type.getName()).thenReturn(aType);
157 Id<DocumentType> typeId = routerConfig.documentTypeConfig().add(type);
160 private Destination registerDestination(boolean aResult, String... types) {
161 Destination destination = new MyDestination(aResult,
162 Arrays.asList(types));
163 Destination myspy = spy(destination);
164 destinationId = router.registerDestination(myspy);
169 public void testOneDestinationNotMatches() {
170 destinationSpy = registerDestination(true);
171 registerDocumentType("any");
173 router.publish("any", source1);
174 verify(listener).notDelivered(any(EventInfo.class));
175 verify(destinationSpy, never()).receive(any(DOMSource.class));
179 public void testOneDestinationThrowsException() {
180 destinationSpy = registerDestination(true, "any");
181 registerDocumentType("any");
183 doThrow(new RuntimeException()).when(destinationSpy).receive(
184 any(DOMSource.class));
186 router.publish("any", source1);
187 verify(listener).notDelivered(any(EventInfo.class));
188 verify(destinationSpy).receive(same(source1));
192 public void testOneDestinationThrowsExceptionSecondDestinationStillHandled() {
193 testOneDestinationThrowsException();
194 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
195 Destination destinationSpy2 = spy(destination2);
196 Id<Destination> destinationId2 = router
197 .registerDestination(destinationSpy2);
199 router.publish("any", source1);
200 verify(listener).delivered(any(EventInfo.class),
201 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
203 verify(destinationSpy2).receive(same(source1));
208 public void testDestinationChooseFromTargetTypesThrowsException() {
209 destinationSpy = registerDestination(true, "any");
210 registerDocumentType("any");
212 doThrow(new RuntimeException()).when(destinationSpy)
213 .chooseFromTargetTypes((Collection<String>) anyObject());
215 router.publish("any", source1);
216 verify(listener).notDelivered(any(EventInfo.class));
217 verify(destinationSpy, never()).receive(same(source1));
221 public void testDestinationChooseFromTargetTypesThrowsExceptionSecondDestinationStillOk() {
222 testDestinationChooseFromTargetTypesThrowsException();
224 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
225 Destination destinationSpy2 = spy(destination2);
226 Id<Destination> destinationId2 = router
227 .registerDestination(destinationSpy2);
228 router.publish("any", source1);
229 verify(listener).delivered(any(EventInfo.class),
230 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
232 verify(destinationSpy, never()).receive(same(source1));
233 verify(destinationSpy2).receive(same(source1));
237 public void testDestinationChooseFromTargetTypesReturnsNull() {
238 destinationSpy = registerDestination(true, "any");
239 registerDocumentType("any");
243 .chooseFromTargetTypes((Collection<String>) anyObject()))
246 router.publish("any", source1);
247 verify(listener).notDelivered(any(EventInfo.class));
248 verify(destinationSpy, never()).receive(same(source1));
252 public void testDestinationChooseFromTargetTypesReturnsNullSecondDestinationStillOk() {
253 testDestinationChooseFromTargetTypesReturnsNull();
255 Destination destination2 = new MyDestination(true, Arrays.asList("any"));
256 Destination destinationSpy2 = spy(destination2);
257 Id<Destination> destinationId2 = router
258 .registerDestination(destinationSpy2);
259 router.publish("any", source1);
260 verify(listener).delivered(any(EventInfo.class),
261 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
263 verify(destinationSpy, never()).receive(same(source1));
264 verify(destinationSpy2).receive(same(source1));
268 public void testOneTransformationOneDestination() {
269 registerDocumentType("any");
270 Transformation transformation = mock(Transformation.class);
271 when(transformation.getName()).thenReturn("trans");
272 when(transformation.getFromType()).thenReturn("any");
273 when(transformation.getToType()).thenReturn("bla");
274 when(transformation.transform(same(source1))).thenReturn(source2);
275 routerConfig.transformationConfig().add(transformation);
277 Destination destination = mock(Destination.class);
279 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
280 .thenReturn(Arrays.asList("bla"));
282 router.registerDestination(destination);
284 when(destination.receive(any(DOMSource.class))).thenReturn(true);
285 router.publish("bla", source1);
286 verify(listener).delivered(any(EventInfo.class),
287 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
289 verify(transformation).transform(source1);
290 verify(destination).receive(same(source2));
292 // now the same when the destination rejects the event.
293 when(destination.receive(any(DOMSource.class))).thenReturn(false);
294 router.publish("bla", source1);
295 verify(listener).notDelivered(any(EventInfo.class));
299 public void testMisbehavingTransformationOneDestination() {
300 registerDocumentType("any");
301 Transformation transformation = mock(Transformation.class);
302 when(transformation.getName()).thenReturn("trans");
303 when(transformation.getFromType()).thenReturn("any");
304 when(transformation.getToType()).thenReturn("bla");
305 doThrow(new RuntimeException("x")).when(transformation).transform(
307 routerConfig.transformationConfig().add(transformation);
309 Destination destination = mock(Destination.class);
311 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
312 .thenReturn(Arrays.asList("bla"));
314 router.registerDestination(destination);
316 when(destination.receive(any(DOMSource.class))).thenReturn(true);
317 router.publish("bla", source1);
318 verify(listener).notDelivered(any(EventInfo.class));
321 private Transformation createTransformation(String aFrom, String aTo,
322 DOMSource aSource, DOMSource aTarget) {
323 Transformation transformation = mock(Transformation.class);
324 when(transformation.getName()).thenReturn("trans");
325 when(transformation.getFromType()).thenReturn(aFrom);
326 when(transformation.getToType()).thenReturn(aTo);
327 when(transformation.transform(same(aSource))).thenReturn(aTarget);
328 return transformation;
332 public void testOneTransformationReturnsNull() {
333 registerDocumentType("any");
334 Transformation transformation = createTransformation("any", "bla",
337 routerConfig.transformationConfig().add(transformation);
339 Destination destination = mock(Destination.class);
341 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
342 .thenReturn(Arrays.asList("bla"));
343 router.registerDestination(destination);
345 router.publish("bla", source1);
346 verify(listener).notDelivered(any(EventInfo.class));
348 verify(transformation).transform(source1);
349 verify(destination, never()).receive(any(DOMSource.class));
351 // add second transformation that behaves normally
352 Transformation transformation2 = createTransformation("any", "bla2",
355 routerConfig.transformationConfig().add(transformation2);
357 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
358 .thenReturn(Arrays.asList("bla", "bla2"));
360 reset(transformation);
361 when(transformation.getName()).thenReturn("trans");
362 when(transformation.getFromType()).thenReturn("any");
363 when(transformation.getToType()).thenReturn("bla");
364 when(transformation.transform(same(source1))).thenReturn(null);
366 when(destination.receive(any(DOMSource.class))).thenReturn(true);
367 router.publish("bla", source1);
368 verify(listener).delivered(any(EventInfo.class),
369 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
371 verify(transformation).transform(source1);
372 verify(transformation2).transform(source1);
374 verify(destination).receive(same(source2));
379 public void testChooseMultipleDestinationsOneType() {
380 Destination dest1 = registerDestination(true, "any");
381 Destination dest2 = registerDestination(true, "any");
382 registerDocumentType("any");
384 router.publish("source", source1);
385 verify(listener, times(2)).delivered(any(EventInfo.class),
386 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
388 verify(dest1).receive(same(source1));
389 verify(dest2).receive(same(source1));
393 public void testMultipleDeliveryToOneDestination() {
394 Destination dest = registerDestination(true, "any", "other");
395 registerDocumentType("any", source1);
396 registerDocumentType("other", source2);
397 Transformation transformation = createTransformation("any", "other",
399 routerConfig.transformationConfig().add(transformation);
401 router.publish("source", source1);
402 verify(listener, times(2)).delivered(any(EventInfo.class),
403 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
405 verify(dest).receive(same(source1));
406 verify(dest).receive(same(source2));
410 public void testMultipleTransformations() {
411 Destination dest = registerDestination(true, "other");
412 registerDocumentType("any", source1);
413 registerDocumentType("other", source3);
415 Transformation t1 = createTransformation("any", "intermediate",
417 routerConfig.transformationConfig().add(t1);
418 Transformation t2 = createTransformation("intermediate", "other",
420 routerConfig.transformationConfig().add(t2);
422 router.publish("source", source1);
423 verify(listener).delivered(any(EventInfo.class),
424 anyListOf(Transformation.class), anyLong(), anyString(), eq(true));
426 verify(dest).receive(same(source3));
430 public void testDestinationGivesError() {
431 Destination destination = mock(Destination.class);
432 when(destination.getName()).thenReturn("name");
433 when(destination.chooseFromTargetTypes(anyCollectionOf(String.class)))
434 .thenReturn(Arrays.asList("any"));
435 doThrow(new RuntimeException("x")).when(destination).receive(
436 any(DOMSource.class));
437 router.registerDestination(destination);
439 registerDocumentType("any");
441 router.publish("source", source1);
443 verify(listener).delivered(any(EventInfo.class),
444 anyListOf(Transformation.class), anyLong(), anyString(), eq(false));