package alice.tuprolog;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import alice.tuprolog.event.OutputEvent;
import alice.tuprolog.event.OutputListener;
public class CallTest {
Prolog engine;
String output;
@Before
public void setUp() {
engine = new Prolog();
try {
engine.setTheory(new Theory(
"b(X) :-\n" +
"Y = (write(X), X),\n" +
"call(Y).\n" +
"a(1).\n" +
"a(2)."));
} catch (InvalidTheoryException e) {
}
}
@Test public void callCut() throws PrologException {
SolveInfo solution = engine.solve("call(!).");
assertTrue(solution.isSuccess());
}
@Test public void callFail() throws PrologException {
SolveInfo solution = engine.solve("call(fail).");
assertFalse(solution.isSuccess());
}
@Test public void callAvoidInstantiationError() throws PrologException {
SolveInfo solution = engine.solve("call((fail, X)).");
assertFalse(solution.isSuccess());
}
@Test public void callAvoidTypeError() throws PrologException {
SolveInfo solution = engine.solve("call((fail, call(1))).");
assertFalse(solution.isSuccess());
}
@Test(expected=AssertionError.class)
public void callIndirectInstantiationError() throws PrologException {
output = "";
engine.addOutputListener(new OutputListener() {
@Override
public void onOutput(OutputEvent e) {
output += e.getMsg();
}
});
SolveInfo solution = engine.solve("b(_).");
assertFalse(solution.isSuccess());
// TODO Should throw instantiation_error
assertEquals("", output);
engine.removeAllOutputListeners();
}
@Test(expected=AssertionError.class)
public void callIndirectTypeError() throws PrologException {
output = "";
engine.addOutputListener(new OutputListener() {
@Override
public void onOutput(OutputEvent e) {
output += e.getMsg();
}
});
SolveInfo solution = engine.solve("b(3).");
assertFalse(solution.isSuccess());
// TODO Should throw type_error(callable, 3)
// According to the standard, the goal should output '3', but this
// behavior is incompatible with the type_error(callable, 3) that
// the standard prescribes the goal to throw
assertEquals("", output);
engine.removeAllOutputListeners();
}
@Test public void callBindingNoReexecution() throws PrologException {
SolveInfo solution = engine.solve("Z = !, call((Z=!, a(X), Z)).");
assertTrue(solution.isSuccess());
assertEquals(new Int(1), solution.getTerm("X"));
assertEquals(new Struct("!"), solution.getTerm("Z"));
assertFalse(solution.hasOpenAlternatives());
}
@Test public void callBindingWithReexecution() throws PrologException {
SolveInfo solution = engine.solve("call((Z=!, a(X), Z)).");
assertTrue(solution.isSuccess());
assertEquals(new Int(1), solution.getTerm("X"));
assertEquals(new Struct("!"), solution.getTerm("Z"));
solution = engine.solveNext();
assertTrue(solution.isSuccess());
assertEquals(new Int(2), solution.getTerm("X"));
assertEquals(new Struct("!"), solution.getTerm("Z"));
assertFalse(engine.hasOpenAlternatives());
}
@After
public void tearDown() {
engine.clearTheory();
}
@Test public void callOutputWithInstantiationError() throws PrologException {
output = "";
engine.addOutputListener(new OutputListener() {
@Override
public void onOutput(OutputEvent e) {
output += e.getMsg();
}
});
SolveInfo solution = engine.solve("call((write(3), X)).");
assertFalse(solution.isSuccess());
// TODO Should throw instantiation_error
assertEquals("3", output);
engine.removeAllOutputListeners();
}
@Test public void callOutputWithTypeError() throws PrologException {
output = "";
engine.addOutputListener(new OutputListener() {
@Override
public void onOutput(OutputEvent e) {
output += e.getMsg();
}
});
SolveInfo solution = engine.solve("call((write(3), call(1))).");
assertFalse(solution.isSuccess());
// TODO Should throw type_error(callable, 1)
assertEquals("3", output);
engine.removeAllOutputListeners();
}
@Test public void callInstantiationError() throws PrologException {
SolveInfo solution = engine.solve("call(X).");
assertFalse(solution.isSuccess());
// TODO Should throw instantiation_error
}
@Test public void callTypeError() throws PrologException {
SolveInfo solution = engine.solve("call(1).");
assertFalse(solution.isSuccess());
// TODO Should throw type_error(callable, 1)
}
@Test public void callConjunctionTypeError() throws PrologException {
SolveInfo solution = engine.solve("call((fail, 1)).");
assertFalse(solution.isSuccess());
// TODO Should throw type_error(callable, (fail, 1))
}
@Test public void callConjunctionTypeErrorWithoutOutput() throws PrologException {
output = "";
engine.addOutputListener(new OutputListener() {
@Override
public void onOutput(OutputEvent e) {
output += e.getMsg();
}
});
SolveInfo solution = engine.solve("call((write(3), 1)).");
assertFalse(solution.isSuccess());
// TODO Should throw type_error(callable, (write(3), 1))
assertEquals("", output);
engine.removeAllOutputListeners();
}
@Test public void callDisjunctionTypeError() throws PrologException {
SolveInfo solution = engine.solve("call((1;true)).");
assertFalse(solution.isSuccess());
// TODO Should throw type_error(callable, (1 ; true))
}
}