package fitnesse.testsystems.slim;
import fitnesse.slim.SlimException;
import fitnesse.slim.SlimServer;
import fitnesse.slim.instructions.Instruction;
import fitnesse.slim.instructions.InstructionExecutor;
import fitnesse.slim.instructions.InstructionResult;
import fitnesse.testsystems.*;
import fitnesse.testsystems.slim.results.SlimExceptionResult;
import fitnesse.testsystems.slim.results.SlimTestResult;
import fitnesse.testsystems.slim.tables.SlimAssertion;
import fitnesse.testsystems.slim.tables.SlimExpectation;
import fitnesse.testsystems.slim.tables.SlimTable;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.*;
import static fitnesse.slim.SlimServer.EXCEPTION_TAG;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
/**
* See also FitNesseRoot/FitNesse/SuiteAcceptanceTests/SuiteSlimTests, StopSuite and StopTest in particular
*/
public class SlimTestSystemTableProcessingTest {
private final RecordingTestSystemListener listener = new RecordingTestSystemListener();
private final DummySlimTestSystem slimTestSystem = new DummySlimTestSystem();
@Before
public void setup() {
slimTestSystem.addTestSystemListener(listener);
}
@Test
public void normalFlowTwoTablesSamePage() throws TestExecutionException {
slimTestSystem.processTable(table("Table1"), false);
slimTestSystem.processTable(table("Table2"), false);
assertTestRecords(pass("Table1"), pass("Table2"));
}
@Test
public void tableFollowingRandomExceptionStillExecuted() throws TestExecutionException {
String exceptionId = EXCEPTION_TAG + "table1 with random exception";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.processTable(table("Table2"), false);
assertTestRecords(error(exceptionId), pass("Table2"));
}
@Test
public void tableFollowingStopTestExceptionSkipped() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_TEST_TAG + "StopTestException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.processTable(table("Table2"), false);
assertTestRecords(fail(exceptionId), ignore("Table2"));
}
@Test
public void nextTestFollowingStopTestExceptionExecuted() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_TEST_TAG + "StopTestException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.newTestPage();
slimTestSystem.processTable(table("NextTest"), false);
assertTestRecords(fail(exceptionId), pass("NextTest"));
}
@Test
public void tearDownFollowingStopTestExceptionStillExecuted() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_TEST_TAG + "StopTestException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.processTable(tearDownTable("TearDown"), false);
assertTestRecords(fail(exceptionId), pass("TearDown"));
}
@Test
public void suiteTearDownFollowingStopTestExceptionStillExecuted() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_TEST_TAG + "StopTestException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.newTestPage();
slimTestSystem.processTable(table("SuiteTearDown"), true);
assertTestRecords(fail(exceptionId), pass("SuiteTearDown"));
}
@Test
public void nextPageAndItsTeardownShouldBeSkipped() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_SUITE_TAG + "StopSuiteException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.newTestPage();
slimTestSystem.processTable(table("NextPage"), false);
slimTestSystem.processTable(tearDownTable("NextPageTearDown"), false);
assertTestRecords(error(exceptionId), ignore("NextPage"), ignore("NextPageTearDown"));
}
@Test
public void suiteTearDownAlsoOnSuiteStopExceptionExecuted() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_SUITE_TAG + "StopSuiteException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.newTestPage();
slimTestSystem.processTable(table("SuiteTearDown"), true);
assertTestRecords(error(exceptionId), pass("SuiteTearDown"));
}
@Test
public void tearDownThisPageStopSuiteExceptionShouldStillBeExecuted() throws TestExecutionException {
String exceptionId = SlimServer.EXCEPTION_STOP_SUITE_TAG + "StopSuiteException";
slimTestSystem.processTable(table(exceptionId), false);
slimTestSystem.processTable(tearDownTable("ThisPageTeardown"), false);
assertTestRecords(error(exceptionId), pass("ThisPageTeardown"));
}
private static DummySlimTable table(String exceptionId) {
return new DummySlimTable(exceptionId);
}
private static SlimTable tearDownTable(String key) {
DummySlimTable result = table(key);
result.setTearDown(true);
return result;
}
public void assertTestRecords(String... testRecords) {
assertEquals(Arrays.asList(testRecords), listener.getRecordedHistory());
}
public static String pass(String key) {
return formatTestRecord(ExecutionResult.PASS, key);
}
public static String ignore(String key) {
return formatTestRecord(ExecutionResult.IGNORE, key);
}
public static String error(String key) {
return formatTestRecord(ExecutionResult.ERROR, key);
}
public static String fail(String key) {
return formatTestRecord(ExecutionResult.FAIL, key);
}
private static String formatTestRecord(ExecutionResult executionResult, String key) {
return String.format("%s(\"%s\")", executionResult, key);
}
private static class RecordingTestSystemListener implements TestSystemListener {
private final List<String> recordedHistory = new ArrayList<>();
@Override
public void testExceptionOccurred(Assertion assertion, ExceptionResult exceptionResult) {
assertNotEquals("Exceptions are not expected to indicate success", exceptionResult.getExecutionResult(), ExecutionResult.PASS);
record(assertion, exceptionResult.getExecutionResult());
}
private void record(Assertion assertion, ExecutionResult executionResult) {
recordedHistory.add(formatTestRecord(executionResult, assertion.getInstruction().getId()));
}
public List<String> getRecordedHistory() {
return recordedHistory;
}
@Override
public void testSystemStarted(TestSystem testSystem) {
throw new UnsupportedOperationException();
}
@Override
public void testOutputChunk(String output) {
throw new UnsupportedOperationException();
}
@Override
public void testStarted(TestPage testPage) {
throw new UnsupportedOperationException();
}
@Override
public void testComplete(TestPage testPage, TestSummary testSummary) {
throw new UnsupportedOperationException();
}
@Override
public void testSystemStopped(TestSystem testSystem, Throwable cause) {
throw new UnsupportedOperationException();
}
@Override
public void testAssertionVerified(Assertion assertion, TestResult testResult) {
ExecutionResult executionResult = testResult.getExecutionResult();
record(assertion, executionResult);
}
}
private static class DummySlimTable extends SlimTable {
private final List<SlimAssertion> assertions;
public DummySlimTable(String assertionId) {
super(null, null, null);
this.assertions = Collections.singletonList(
new SlimAssertion(new DummyInstruction(assertionId),
new IgnoreOnNullPassOtherwiseSlimExpectation())
);
}
@Override
protected String getTableType() {
return "test";
}
@Override
public List<SlimAssertion> getAssertions() throws TestExecutionException {
return assertions;
}
}
private static class DummyInstruction extends Instruction {
public DummyInstruction(String assertion) {
super(assertion);
}
@Override
protected InstructionResult executeInternal(InstructionExecutor executor) throws SlimException {
throw new UnsupportedOperationException();
}
}
private static class DummySlimTestSystem extends SlimTestSystem {
public final InstructionIdMirroringSlimClient slimClientMock;
public DummySlimTestSystem() {
this(new InstructionIdMirroringSlimClient());
}
public DummySlimTestSystem(InstructionIdMirroringSlimClient slimClientMock) {
super(null, slimClientMock);
this.slimClientMock = slimClientMock;
}
@Override
protected void processAllTablesOnPage(TestPage testPage) throws TestExecutionException {
throw new UnsupportedOperationException();
}
public void newTestPage() {
stopTestCalled = false;
}
}
private static class InstructionIdMirroringSlimClient implements SlimClient {
@Override
public void start() throws IOException, SlimVersionMismatch {
throw new UnsupportedOperationException();
}
@Override
public Map<String, Object> invokeAndGetResponse(List<Instruction> statements) throws SlimCommunicationException {
Map<String, Object> response = new HashMap<>();
for (Instruction statement : statements) {
response.put(statement.getId(), statement.getId());
}
return response;
}
@Override
public void connect() throws IOException, SlimVersionMismatch {
throw new UnsupportedOperationException();
}
@Override
public void bye() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void kill() {
throw new UnsupportedOperationException();
}
}
private static class IgnoreOnNullPassOtherwiseSlimExpectation implements SlimExpectation {
@Override
public TestResult evaluateExpectation(Object returnValues) {
return new SlimTestResult(null == returnValues ? ExecutionResult.IGNORE : ExecutionResult.PASS);
}
@Override
public SlimExceptionResult evaluateException(SlimExceptionResult exceptionResult) {
return exceptionResult;
}
}
}