Fix checkstyle violations
[lispflowmapping.git] / commons / unittest_tools / src / main / java / org / opendaylight / lispflowmapping / tools / junit / BaseExpectations.java
1 /*
2  * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.lispflowmapping.tools.junit;
10
11 import java.lang.reflect.Field;
12 import java.lang.reflect.InvocationTargetException;
13 import java.lang.reflect.Method;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19
20 import org.hamcrest.BaseMatcher;
21 import org.hamcrest.Description;
22 import org.hamcrest.Matcher;
23 import org.hamcrest.TypeSafeMatcher;
24 import org.jmock.Expectations;
25 import org.jmock.Mockery;
26 import org.jmock.api.Action;
27 import org.jmock.api.Invocation;
28 import org.jmock.internal.InvocationExpectationBuilder;
29 import org.jmock.internal.ReturnDefaultValueAction;
30 import org.jmock.lib.concurrent.Synchroniser;
31 import org.jmock.lib.legacy.ClassImposteriser;
32 import org.jmock.syntax.ReceiverClause;
33 import org.junit.After;
34 import org.junit.Assert;
35 import org.junit.Before;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public abstract class BaseExpectations extends Expectations {
40     protected Mockery context;
41     protected boolean showAllExpectations;
42     private final Synchroniser synchroniser = new Synchroniser();
43     protected static final Logger LOG = LoggerFactory.getLogger(BaseExpectations.class);
44
45     @Before
46     public void before() throws Exception {
47         context = new Mockery() {
48             {
49                 setImposteriser(ClassImposteriser.INSTANCE);
50                 // otherwise we get errors on the finalizer thread:
51                 setThreadingPolicy(synchroniser);
52             }
53         };
54         defaultAction = new ReturnDefaultValueAction(ClassImposteriser.INSTANCE);
55     }
56
57     @After
58     public void after() throws Exception {
59         context.assertIsSatisfied();
60     }
61
62     // New suger syntax
63
64     protected final void ret(Object result) {
65         will(returnValue(result));
66     }
67
68     protected final void rethrow(Throwable throwable) {
69         will(throwException(throwable));
70     }
71
72     protected final void retField(Object container, String fieldName) throws Exception {
73         will(new ReturnField(container, fieldName));
74     }
75
76     protected final void rets(Object... results) {
77         will(returnValues(results));
78     }
79
80     protected final <T> T wany(Class<T> type) {
81         return with(any(type));
82     }
83
84     protected final int wanyint() {
85         return with(any(int.class));
86     }
87
88     protected final long wanylong() {
89         return with(any(long.class));
90     }
91
92     protected final boolean wanybool() {
93         return with(any(boolean.class));
94     }
95
96     protected final <T> T wsame(T instance) {
97         return with(same(instance));
98     }
99
100     protected final <T> T weq(T instance) {
101         return with(equal(instance));
102     }
103
104     protected final short weq(short instance) {
105         return with(equal(instance));
106     }
107
108     protected final int weq(int instance) {
109         return with(equal(instance));
110     }
111
112     protected final long weq(long instance) {
113         return with(equal(instance));
114     }
115
116     protected final boolean weq(boolean instance) {
117         return with(equal(instance));
118     }
119
120     public static Action returnValues(Object... result) {
121         return new ActionSequenceValue(result);
122     }
123
124     protected void retMethod(final String methodName) {
125         will(new MethodAction(this, methodName));
126     }
127
128     private static class MethodAction implements Action {
129         private Object testInstance;
130         private String methodName;
131         private Method method;
132
133         MethodAction(Object testInstance, String methodName) {
134             this.testInstance = testInstance;
135             this.methodName = methodName;
136             method = findMethod(testInstance.getClass());
137             Assert.assertNotNull("Cannot locate '" + methodName + "'", method);
138         }
139
140         private Method findMethod(Class<? extends Object> clazz) {
141             if (Object.class.equals(clazz)) {
142                 return null;
143             }
144             try {
145                 return clazz.getMethod(methodName, Invocation.class);
146             } catch (SecurityException e) {
147                 LOG.debug("Catched SecurityException", e);
148             } catch (NoSuchMethodException e) {
149                 LOG.debug("Catched NoSuchMethodException", e);
150             }
151
152             return findMethod(clazz.getSuperclass());
153         }
154
155         public void describeTo(Description arg0) {
156             arg0.appendText("running " + methodName);
157         }
158
159         public Object invoke(Invocation invocation) throws Throwable {
160             Exception e = null;
161             try {
162                 return method.invoke(testInstance, invocation);
163             } catch (SecurityException se) {
164                 e = se;
165             } catch (IllegalAccessException iae) {
166                 e = iae;
167             } catch (InvocationTargetException ite) {
168                 throw ite.getTargetException();
169             }
170             Assert.fail("Got " + e.getMessage() + " while trying to execute '" + methodName + "'");
171             return null;
172         }
173
174     }
175
176     private static class ActionSequenceValue implements Action {
177         private final Object[] values;
178         private int i = 0;
179
180         ActionSequenceValue(Object... values) {
181             this.values = values;
182         }
183
184         public Object invoke(Invocation invocation) throws Throwable {
185             if (i < values.length) {
186                 return values[i++];
187             }
188             throw new RuntimeException("no morCxtrmExpectationse actions available: " + invocation);
189         }
190
191         public void describeTo(Description description) {
192             description.appendText(", and then ").appendText(Arrays.toString(values));
193         }
194     }
195
196     protected static final class ReturnField implements Action {
197         private final Object container;
198         private final Field field;
199
200         public ReturnField(Object container, String fieldName) throws Exception {
201             this.container = container;
202             field = container.getClass().getDeclaredField(fieldName);
203             field.setAccessible(true);
204         }
205
206         public void describeTo(Description description) {
207             description.appendText("return " + container.getClass().getName() + "." + field.getName());
208         }
209
210         public Object invoke(Invocation invocation) throws Throwable {
211             return field.get(container);
212         }
213     }
214
215     public static class ValueSaverAction<T> extends BaseMatcher<T> implements Action {
216         private final String logMatch;
217         private final boolean logInvocation;
218         public T lastValue;
219         public final List<T> values = new ArrayList<T>();
220
221         public ValueSaverAction() {
222             this(null, false);
223         }
224
225         public ValueSaverAction(String logMatch, boolean logInvocation) {
226             this.logMatch = logMatch;
227             this.logInvocation = logInvocation;
228         }
229
230         @SuppressWarnings("unchecked")
231         public final boolean matches(Object arg) {
232             T value = (T) arg;
233             if (!validate(value)) {
234                 return false;
235             }
236             lastValue = transformOnMatch(value);
237             values.add(lastValue);
238             boolean match = match(lastValue);
239             if (match && (logMatch != null)) {
240                 LOG.trace("Match: " + logMatch + " " + value);
241             }
242             return match;
243         }
244
245         protected T onMatch(T value) {
246             return value;
247         }
248
249         protected boolean match(T lastValue2) {
250             return true;
251         }
252
253         protected boolean validate(T value) {
254             return true;
255         }
256
257         protected T transformOnMatch(T value) {
258             return value;
259         }
260
261         public void describeTo(Description arg0) {
262         }
263
264         public Object invoke(Invocation invocation) throws Throwable {
265             if (logInvocation) {
266                 LOG.trace("Invoke: returning " + lastValue);
267             }
268             return lastValue;
269         }
270
271         @Override
272         public String toString() {
273             return "ValueSavers: " + values.toString();
274         }
275     }
276
277     @SafeVarargs
278     protected static final <T> Matcher<T[]> contains(final T... expected) {
279         return new BaseMatcher<T[]>() {
280             @SuppressWarnings("unchecked")
281             public boolean matches(Object actual) {
282                 T[] arr = (T[]) actual;
283                 if (arr.length != expected.length) {
284                     return false;
285                 }
286                 for (T expectedInstance : expected) {
287                     boolean found = false;
288                     for (int j = 0; (j < arr.length) && !found; j++) {
289                         found = (arr[j] == expectedInstance);
290                     }
291                     if (!found) {
292                         return false;
293                     }
294                 }
295                 return true;
296             }
297
298             public void describeTo(Description arg0) {
299             }
300         };
301     }
302
303     @SafeVarargs
304     protected static final <T> Matcher<T[]> sameArbitraryArray(final T... expectedArr) {
305         return new TypeSafeMatcher<T[]>() {
306             @Override
307             public boolean matchesSafely(T[] actualArr) {
308                 Set<T> expected = new HashSet<T>();
309                 for (T val : expectedArr) {
310                     expected.add(val);
311                 }
312                 Set<T> actual = new HashSet<T>();
313                 actual.addAll(Arrays.asList(actualArr));
314                 return actual.equals(expected);
315             }
316
317             public void describeTo(Description description) {
318                 description.appendText("Same arbitrary array as " + Arrays.toString(expectedArr));
319             }
320         };
321     }
322
323     @SafeVarargs
324     protected static final <T> Matcher<T[]> doseNotContain(final T... forbiddenValues) {
325         return new TypeSafeMatcher<T[]>() {
326             @Override
327             public boolean matchesSafely(T[] arr) {
328                 for (T forbiddenInstance : forbiddenValues) {
329                     for (T element : arr) {
330                         if (element == forbiddenInstance) {
331                             return false;
332                         }
333                     }
334                 }
335                 return true;
336             }
337
338             public void describeTo(Description description) {
339             }
340         };
341     }
342
343     public final class StringArrayMatcher extends BaseMatcher<String[]> {
344         private final Object[] expected;
345
346         /**
347          * @param expected
348          *            null are considered "any"
349          */
350         StringArrayMatcher(Object... expected) {
351             this.expected = expected;
352         }
353
354         public boolean matches(Object item) {
355             if (!(item instanceof String[])) {
356                 return false;
357             }
358             String[] actual = (String[]) item;
359             if (expected.length != actual.length) {
360                 return false;
361             }
362             for (int i = 0; i < expected.length; i++) {
363                 if ((expected[i] != null) && !expected[i].toString().equals(actual[i])) {
364                     return false;
365                 }
366             }
367             return true;
368         }
369
370         public void describeTo(Description description) {
371             description.appendText("String" + Arrays.toString(expected));
372         }
373     }
374
375     /**
376      * @param expected
377      *            null are considered "any"
378      */
379     public final String[] wStrArr(Object... expected) {
380         return with(new StringArrayMatcher(expected));
381     }
382
383     // ////////////////////////////////////////////////////////////
384     // Make expectations work in our new ConteXtream better way //
385     // ////////////////////////////////////////////////////////////
386     private ReturnDefaultValueAction defaultAction;
387
388     protected InvocationExpectationBuilder getCurrentBuilder() {
389         try {
390             return currentBuilder();
391         } catch (IllegalStateException e) {
392             LOG.debug("Catched IllegalStateException", e);
393             return null;
394         }
395     }
396
397     private void addCurrentExpectation() {
398         context.addExpectation(currentBuilder().toExpectation(defaultAction));
399     }
400
401     @Override
402     public ReceiverClause exactly(int count) {
403         ReceiverClause ret = super.exactly(count);
404         addCurrentExpectation();
405         return ret;
406     }
407
408     @Override
409     public ReceiverClause atLeast(int count) {
410         ReceiverClause ret = super.atLeast(count);
411         addCurrentExpectation();
412         return ret;
413     }
414
415     @Override
416     public ReceiverClause between(int minCount, int maxCount) {
417         ReceiverClause ret = super.between(minCount, maxCount);
418         addCurrentExpectation();
419         return ret;
420     }
421
422     @Override
423     public ReceiverClause atMost(int count) {
424         ReceiverClause ret = super.atMost(count);
425         addCurrentExpectation();
426         return ret;
427     }
428
429 }