package nl.uva.softwcons.ql.validation;
import static nl.uva.softwcons.helper.TestHelper.getCheckerErrors;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import nl.uva.softwcons.ql.validation.type.TypeChecker;
import nl.uva.softwcons.ql.validation.type.error.InvalidConditionType;
import nl.uva.softwcons.ql.validation.type.error.InvalidOperatorTypes;
import nl.uva.softwcons.ql.validation.type.error.InvalidQuestionExpressionType;
import nl.uva.softwcons.ql.validation.type.error.UndefinedReference;
import org.junit.Test;
public class TypeCheckerTest {
@Test
public void validateNoInitialErrors() {
final String question = "question: \"Label 1\" boolean";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).isEmpty();
}
@Test
public void testValidQuestionWithBooleanType() {
final String question = "question: \"Label 1\" boolean (true && false)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).isEmpty();
}
@Test
public void testValidQuestionWithNumberType() {
final String question = "question: \"Label 1\" number (6 * 5.0)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).isEmpty();
}
@Test
public void testValidQuestionWithStringType() {
final String question = "question: \"Label 1\" string (\"plain string\")";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).isEmpty();
}
@Test
public void testValidConditionalWithBooleanExpressionType() {
final String question = "if (true) { question: \"Label 1\" boolean }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).isEmpty();
}
@Test
public void testInvalidQuestionWithBooleanType() {
final String question = "question: \"Label 1\" boolean (3 * 4)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).hasOnlyElementsOfType(InvalidQuestionExpressionType.class);
}
@Test
public void testInvalidQuestionWithNumberType() {
final String question = "question: \"Label 1\" number (true && false)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).hasOnlyElementsOfType(InvalidQuestionExpressionType.class);
}
@Test
public void testInvalidQuestionWithStringType() {
final String question = "question: \"Label 1\" string (6 * 5)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).hasOnlyElementsOfType(InvalidQuestionExpressionType.class);
}
@Test
public void testInvalidConditionalWithDecimalExpressionType() {
final String question = "if (6.0 * 5) { question: \"Label 1\" boolean }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).hasOnlyElementsOfType(InvalidConditionType.class);
}
@Test
public void testInvalidConditionalWithNumberExpressionType() {
final String question = "if (4 * 5) { question: \"Label 1\" boolean }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).hasOnlyElementsOfType(InvalidConditionType.class);
}
@Test
public void testInvalidConditionalWithStringExpressionType() {
final String question = "if (\"test\") { question: \"Label 1\" boolean }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).hasOnlyElementsOfType(InvalidConditionType.class);
}
@Test
public void testValidExpressionOperands() {
final String question = "question: \"Label 1\" boolean(true)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).isEmpty();
}
@Test
public void testInvalidArithmeticExpressionOperands() {
final String[] questions = { "question: \"Label 1\" number(6 + false)",
"question: \"Label 1\" number(6 - false)", "question: \"Label 1\" number(6 * false)",
"question: \"Label 1\" number(6 / false)" };
for (final String question : questions) {
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).extracting("class").contains(InvalidOperatorTypes.class);
}
}
@Test
public void testInvalidComparisonExpressionOperands() {
final String[] questions = { "question: \"Label 1\" boolean(6 < false)",
"question: \"Label 1\" boolean(6 > false)", "question: \"Label 1\" boolean(6 >= false)",
"question: \"Label 1\" boolean(6 <= false)" };
for (final String question : questions) {
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).extracting("class").contains(InvalidOperatorTypes.class);
}
}
@Test
public void testInvalidLogicalExpressionOperands() {
final String[] questions = { "question: \"Label 1\" boolean(6 && false)",
"question: \"Label 1\" boolean(6 || false)", "question: \"Label 1\" boolean(!6)" };
for (final String question : questions) {
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).extracting("class").contains(InvalidOperatorTypes.class);
}
}
@Test
public void testInvalidEqualityExpressionOperands() {
final String[] questions = { "question: \"Label 1\" boolean(6 == false)",
"question: \"Label 1\" boolean(6 != false)" };
for (final String question : questions) {
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).extracting("class").contains(InvalidOperatorTypes.class);
}
}
@Test
public void testInvalidExpressionOperandsReferringAQuestion() {
final String question1 = "question1: \"Label 1\" boolean";
final String question2 = "question2: \"Label 2\" number(6 + question1)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question1, question2);
assertThat(validationErrors).hasSize(1);
assertThat(validationErrors).extracting("class").contains(InvalidOperatorTypes.class);
}
@Test
public void testUndefinedQuestionReferenceInComputedQuestion() {
final String question = "question: \"Label 1\" boolean(notAQuestion)";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(2);
assertThat(validationErrors).extracting("class").contains(UndefinedReference.class,
InvalidQuestionExpressionType.class);
}
@Test
public void testUndefinedQuestionReferenceInConditional() {
final String question = "if (notAQuestion) { question: \"Label 1\" boolean(true) }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(2);
assertThat(validationErrors).extracting("class").contains(UndefinedReference.class, InvalidConditionType.class);
}
@Test
public void testUndefinedQuestionReferenceNestedInConditional() {
final String question = "if (notDefined > 4*(5 / 2)) { question: \"Label 1\" boolean(true) }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question);
assertThat(validationErrors).hasSize(2);
assertThat(validationErrors).extracting("class").contains(UndefinedReference.class, InvalidOperatorTypes.class);
}
@Test
public void testComplexFormWithMultipleErrors() {
final String question1 = "question1: \"Label 1\" boolean";
// reference to an undefined question, invalid operands in the division
// expression
final String question2 = "question2: \"Label 2\" number(question11 / 2)";
// expression type not matching the question type
final String question3 = "question3: \"Label 3\" number (1 == 0)";
// invalid operands in the addition expression, invalid type for the
// conditional and duplicate questions inside
final String ifStatement = "if (question1 + (3 == 4)) { question11: \"Label 1\" boolean"
+ " question11: \"Label 1\" boolean }";
final List<Error> validationErrors = getCheckerErrors(TypeChecker::check, question1, question2, question3,
ifStatement);
assertThat(validationErrors).hasSize(5);
assertThat(validationErrors).extracting("class").contains(UndefinedReference.class, InvalidOperatorTypes.class,
InvalidQuestionExpressionType.class, InvalidOperatorTypes.class, InvalidConditionType.class);
}
}