String fname = function.getName();
Environment declEnv = function.getEnv();
IValueFactory vf = function.getEval().getValueFactory();
Type formals = function.getFormals();
String expected = null;
if(function.hasTag(EXPECT_TAG)){
expected = ((IString) function.getTag(EXPECT_TAG)).getValue();
}
Type[] types = new Type[formals.getArity()];
IValue[] values = new IValue[formals.getArity()];
for (int n = 0; n < formals.getArity(); n++) {
types[n] = formals.getFieldType(n);
}
if (formals.getArity() == 0) {
tries = 1;
}
TypeParameterVisitor tpvisit = new TypeParameterVisitor();
for (int i = 0; i < tries; i++) {
values = new IValue[formals.getArity()];
HashMap<Type, Type> tpbindings = tpvisit.bindTypeParameters(formals);
for (int n = 0; n < formals.getArity(); n++) {
values[n] = arbitrary(types[n], maxDepth, declEnv.getRoot(), vf, tpbindings);
}
boolean expectedThrown = false;
try {
Type[] actualTypes = new Type[formals.getArity()];
for(int j = 0; j < types.length; j ++) {
actualTypes[j] = types[j].instantiate(tpbindings);
}
IValue result = function.call(actualTypes, values, null).getValue();
function.getEval().getStdOut().flush();
if (!((IBool) result).getValue()) {
reportFailed(fname, "test returns false", tpbindings, formals, values, out);
return false;
} else if (verbose && formals.getArity() > 0) {
out.println((i + 1) + ": Checked with " + Arrays.toString(values) + ": true");
}
} catch (Throw e){
if(expected == null || !((IConstructor)e.getException()).getName().equals(expected)){
return reportFailed(fname, e.getMessage(), tpbindings, formals, values, out);
}
expectedThrown = true;
}
catch (Throwable e) {
if(expected == null || !e.getClass().toString().endsWith("." + expected)){
return reportFailed(fname, e.getMessage(), tpbindings, formals, values, out);
}
expectedThrown = true;
}
if(expected != null && !expectedThrown){
return reportMissingException(fname, expected, out);
}
}
out.println("Test " + fname + (formals.getArity() > 0 ? " not refuted after " + tries + " tries with maximum depth " + maxDepth
: " succeeded"));
return true;
}