|
|
@@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Map.Entry;
|
|
|
import java.util.SortedSet;
|
|
|
import java.util.TreeSet;
|
|
|
import java.util.function.Function;
|
|
|
@@ -34,7 +35,7 @@ import org.junit.Ignore;
|
|
|
* the first one for {@codee HashMap}.
|
|
|
* @author Ranides Atterwim <ranides@gmail.com>
|
|
|
*/
|
|
|
-public class TestContractRunner {
|
|
|
+public final class TestContractRunner {
|
|
|
|
|
|
private final SortedSet<MethodRunner> methods = new TreeSet<>();
|
|
|
|
|
|
@@ -52,10 +53,27 @@ public class TestContractRunner {
|
|
|
this.output = output;
|
|
|
}
|
|
|
|
|
|
+ public TestContractRunner(TestContractRunner runner) {
|
|
|
+ this(runner.output);
|
|
|
+ try {
|
|
|
+ for(TesterWrapper w : runner.testers) {
|
|
|
+ this.appendCopy(w);
|
|
|
+ }
|
|
|
+ this.ignored.addAll(runner.ignored);
|
|
|
+ this.debug = runner.debug;
|
|
|
+ } catch(ReflectiveOperationException cause) {
|
|
|
+ throw NewAssert.rethrow(cause);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public TestContractRunner debug(boolean value) {
|
|
|
this.debug = value;
|
|
|
return this;
|
|
|
}
|
|
|
+
|
|
|
+ public boolean debug() {
|
|
|
+ return this.debug;
|
|
|
+ }
|
|
|
|
|
|
public TestContractRunner ignore(String method) {
|
|
|
this.ignored.add(Pattern.compile(Pattern.quote(method)));
|
|
|
@@ -66,9 +84,25 @@ public class TestContractRunner {
|
|
|
this.ignored.add(method);
|
|
|
return this;
|
|
|
}
|
|
|
+
|
|
|
+ public TestContractRunner append(Object tester) {
|
|
|
+ appendWrapper(tester);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void appendCopy(TesterWrapper source) throws ReflectiveOperationException {
|
|
|
+ Object tester = source.object.getClass().newInstance();
|
|
|
+ TesterWrapper target = appendWrapper(tester);
|
|
|
+ for(Entry<String, IParam> entry : source.resources.entrySet()) {
|
|
|
+ String key = entry.getKey();
|
|
|
+ target.resources.get(key).set(entry.getValue().get());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
- public TestContractRunner append(Object tester) {
|
|
|
- testers.add(new TesterWrapper(tester));
|
|
|
+ public TesterWrapper appendWrapper(Object tester) {
|
|
|
+ TesterWrapper wrapper = new TesterWrapper(tester);
|
|
|
+ testers.add(wrapper);
|
|
|
for(Method m : tester.getClass().getMethods()) {
|
|
|
if(Modifier.isStatic(m.getModifiers()) ) {
|
|
|
continue;
|
|
|
@@ -90,7 +124,7 @@ public class TestContractRunner {
|
|
|
methods.add(mr);
|
|
|
}
|
|
|
}
|
|
|
- return this;
|
|
|
+ return wrapper;
|
|
|
}
|
|
|
|
|
|
public TestContractRunner param(String name, Object value) {
|
|
|
@@ -109,6 +143,9 @@ public class TestContractRunner {
|
|
|
}
|
|
|
|
|
|
private boolean irun(TGenerator generator) { //NOPMD
|
|
|
+ for(TesterWrapper tester : testers) {
|
|
|
+ tester.bind(this);
|
|
|
+ }
|
|
|
Class<?> type = generator.get().getClass();
|
|
|
Counter counter = new Counter();
|
|
|
List<String> failed = new ArrayList<>();
|
|
|
@@ -169,7 +206,7 @@ public class TestContractRunner {
|
|
|
public SMethodRunner(Object that, Method method) {
|
|
|
super(that, method);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@Override
|
|
|
protected void invoke(TGenerator argument) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
|
|
method.invoke(that, argument);
|
|
|
@@ -198,7 +235,7 @@ public class TestContractRunner {
|
|
|
this.uid = type.getName()+"#"+method.getDeclaringClass().getName() +"#" + method.getName();
|
|
|
this.nid = method.getDeclaringClass().getSimpleName() + "." + method.getName();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@Override
|
|
|
public int compareTo(MethodRunner object) {
|
|
|
return uid.compareTo(object.uid);
|
|
|
@@ -219,15 +256,16 @@ public class TestContractRunner {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
+ int index = counter.next();
|
|
|
try {
|
|
|
invoke(param);
|
|
|
if(debug) {
|
|
|
- printf(type, counter.next(), method, "");
|
|
|
+ printf(type, index, method, "");
|
|
|
}
|
|
|
} catch (IllegalAccessException | IllegalArgumentException ex) {
|
|
|
throw NewAssert.rethrow(ex);
|
|
|
} catch (InvocationTargetException ex) {
|
|
|
- printf(type, counter.next(), method, "FAILED");
|
|
|
+ printf(type, index, method, "FAILED");
|
|
|
throw NewAssert.rethrow(ex.getTargetException());
|
|
|
}
|
|
|
}
|
|
|
@@ -308,9 +346,14 @@ public class TestContractRunner {
|
|
|
|
|
|
private static final class TesterWrapper {
|
|
|
|
|
|
+ private final Object object;
|
|
|
+
|
|
|
private final Map<String, IParam> resources = new HashMap<>();
|
|
|
-
|
|
|
+
|
|
|
+ private final List<IParam> bindings = new ArrayList<>();
|
|
|
+
|
|
|
public TesterWrapper(Object object) {
|
|
|
+ this.object = object;
|
|
|
for(Class<?> c=object.getClass(); c!=null; c=c.getSuperclass()) {
|
|
|
for(Field f : c.getDeclaredFields()) {
|
|
|
Resource info = f.getAnnotation(Resource.class);
|
|
|
@@ -320,11 +363,21 @@ public class TestContractRunner {
|
|
|
name = f.getName();
|
|
|
}
|
|
|
f.setAccessible(true);
|
|
|
- resources.put(name, new IParam(object, f));
|
|
|
+ if( f.getType().equals(TestContractRunner.class) ) {
|
|
|
+ bindings.add(new IParam(object, f));
|
|
|
+ } else {
|
|
|
+ resources.put(name, new IParam(object, f));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public void bind(TestContractRunner runner) {
|
|
|
+ for(IParam p : bindings) {
|
|
|
+ p.set(runner);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
public void param(String name, Object value) {
|
|
|
if( resources.containsKey(name) ) {
|
|
|
@@ -405,6 +458,14 @@ public class TestContractRunner {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public Object get() {
|
|
|
+ try {
|
|
|
+ return field.get(object);
|
|
|
+ } catch(ReflectiveOperationException cause) {
|
|
|
+ throw NewAssert.rethrow(cause);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void reset() {
|
|
|
try {
|
|
|
field.set(object, value);
|