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.RouterConfig;
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 Id<RouterConfig>(
84 config = new XMLRouterConfigurationImpl(routerConfig);
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), 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 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 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), 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), 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), 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.getId())
275 .thenReturn(new Id<Transformation>("trans"));
276 when(transformation.getFromType()).thenReturn("any");
277 when(transformation.getToType()).thenReturn("bla");
278 when(transformation.transform(same(source1))).thenReturn(source2);
279 routerConfig.transformationConfig().add(transformation);
280 config.setRouterConfig(routerConfig);
282 Destination destination = mock(Destination.class);
284 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
285 .thenReturn(Arrays.asList("bla"));
287 router.registerDestination(destination);
289 when(destination.receive(any(DOMSource.class))).thenReturn(true);
290 router.publish("bla", source1);
291 verify(listener).delivered(any(EventInfo.class),
292 anyListOf(Transformation.class), anyString(), eq(true));
294 verify(transformation).transform(source1);
295 verify(destination).receive(same(source2));
297 // now the same when the destination rejects the event.
298 when(destination.receive(any(DOMSource.class))).thenReturn(false);
299 router.publish("bla", source1);
300 verify(listener).notDelivered(any(EventInfo.class));
304 public void testMisbehavingTransformationOneDestination() {
305 registerDocumentType("any");
306 Transformation transformation = mock(Transformation.class);
307 when(transformation.getId())
308 .thenReturn(new Id<Transformation>("trans"));
309 when(transformation.getFromType()).thenReturn("any");
310 when(transformation.getToType()).thenReturn("bla");
311 doThrow(new RuntimeException("x")).when(transformation).transform(
313 routerConfig.transformationConfig().add(transformation);
315 Destination destination = mock(Destination.class);
317 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
318 .thenReturn(Arrays.asList("bla"));
320 router.registerDestination(destination);
322 when(destination.receive(any(DOMSource.class))).thenReturn(true);
323 router.publish("bla", source1);
324 verify(listener).notDelivered(any(EventInfo.class));
327 private Transformation createTransformation(String aFrom, String aTo,
328 DOMSource aSource, DOMSource aTarget) {
329 Transformation transformation = mock(Transformation.class);
330 when(transformation.getId())
331 .thenReturn(new Id<Transformation>("trans"));
332 when(transformation.getFromType()).thenReturn(aFrom);
333 when(transformation.getToType()).thenReturn(aTo);
334 when(transformation.transform(same(aSource))).thenReturn(aTarget);
335 return transformation;
339 public void testOneTransformationReturnsNull() {
340 registerDocumentType("any");
341 Transformation transformation = createTransformation("any", "bla",
344 routerConfig.transformationConfig().add(transformation);
345 config.setRouterConfig(routerConfig);
346 Destination destination = mock(Destination.class);
348 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
349 .thenReturn(Arrays.asList("bla"));
350 router.registerDestination(destination);
352 router.publish("bla", source1);
353 verify(listener).notDelivered(any(EventInfo.class));
355 verify(transformation).transform(source1);
356 verify(destination, never()).receive(any(DOMSource.class));
358 // add second transformation that behaves normally
359 Transformation transformation2 = createTransformation("any", "bla2",
362 routerConfig.transformationConfig().add(transformation2);
363 config.setRouterConfig(routerConfig);
365 destination.chooseFromTargetTypes((Collection<String>) anyObject()))
366 .thenReturn(Arrays.asList("bla", "bla2"));
368 reset(transformation);
369 when(transformation.getId())
370 .thenReturn(new Id<Transformation>("trans"));
371 when(transformation.getFromType()).thenReturn("any");
372 when(transformation.getToType()).thenReturn("bla");
373 when(transformation.transform(same(source1))).thenReturn(null);
375 when(destination.receive(any(DOMSource.class))).thenReturn(true);
376 router.publish("bla", source1);
377 verify(listener).delivered(any(EventInfo.class),
378 anyListOf(Transformation.class), anyString(), eq(true));
380 verify(transformation).transform(source1);
381 verify(transformation2).transform(source1);
383 verify(destination).receive(same(source2));
388 public void testChooseMultipleDestinationsOneType() {
389 Destination dest1 = registerDestination(true, "any");
390 Destination dest2 = registerDestination(true, "any");
391 registerDocumentType("any");
393 router.publish("source", source1);
394 verify(listener, times(2)).delivered(any(EventInfo.class),
395 anyListOf(Transformation.class), anyString(), eq(true));
397 verify(dest1).receive(same(source1));
398 verify(dest2).receive(same(source1));
402 public void testMultipleDeliveryToOneDestination() {
403 Destination dest = registerDestination(true, "any", "other");
404 registerDocumentType("any", source1);
405 registerDocumentType("other", source2);
406 Transformation transformation = createTransformation("any", "other",
408 routerConfig.transformationConfig().add(transformation);
409 config.setRouterConfig(routerConfig);
411 router.publish("source", source1);
412 verify(listener, times(2)).delivered(any(EventInfo.class),
413 anyListOf(Transformation.class), 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.setRouterConfig(routerConfig);
433 router.publish("source", source1);
434 verify(listener).delivered(any(EventInfo.class),
435 anyListOf(Transformation.class), anyString(), eq(true));
437 verify(dest).receive(same(source3));
441 public void testDestinationGivesError() {
442 Destination destination = mock(Destination.class);
443 when(destination.getName()).thenReturn("name");
444 when(destination.chooseFromTargetTypes(anyCollectionOf(String.class)))
445 .thenReturn(Arrays.asList("any"));
446 doThrow(new RuntimeException("x")).when(destination).receive(
447 any(DOMSource.class));
448 router.registerDestination(destination);
450 registerDocumentType("any");
452 router.publish("source", source1);
454 verify(listener).delivered(any(EventInfo.class),
455 anyListOf(Transformation.class), anyString(), eq(false));