func (suite *TypeCheckerTestSuite) TestCyclicReferenceCheckerIfConditionRefersToBody() {
	questionExample := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	ifBodyExample := stmt.NewStmtList([]interfaces.Question{questionExample}, []interfaces.Conditional{})
	ifExample := stmt.NewIf(expr.NewVarExpr(vari.NewVarID("hasSoldHouse")), ifBodyExample)
	exampleFormBody := stmt.NewStmtList([]interfaces.Question{}, []interfaces.Conditional{ifExample})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleFormBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.CyclicDependencyError{}, 1)
}
func (suite *TypeCheckerTestSuite) TestQuestionTypeAndComputationTypeMismatch() {
	exampleQuestion := stmt.NewComputedQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()), expr.NewIntegerLiteral(11))
	exampleBody := stmt.NewStmtList([]interfaces.Question{exampleQuestion}, []interfaces.Conditional{})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.DeclaratedTypeAndActualTypeDeviateError{}, 1)
}
func (suite *TypeCheckerTestSuite) TestUndefinedQuestionReferenceChecker() {
	computedQuestion := stmt.NewComputedQuestion(expr.NewStringLiteral("Value residue:"), vari.NewVarDecl(vari.NewVarID("valueResidue"), expr.NewIntegerType()), expr.NewSub(expr.NewIntegerLiteral(100), expr.NewVarExpr(vari.NewVarID("hasMaintLoan"))))
	exampleBody := stmt.NewStmtList([]interfaces.Question{computedQuestion}, []interfaces.Conditional{})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.UndefinedQuestionReferenceError{}, 1)
}
func NewVarIDNode(identToken attrib) (vari.VarID, error) {
	sourcePosInfo := identToken.(*token.Token).Pos
	identifierString := string(identToken.(*token.Token).Lit)
	vari := vari.NewVarID(identifierString)
	vari.SetSourceInfo(sourcePosInfo)
	return vari, nil
}
func (suite *TypeCheckerTestSuite) TestDuplicateVarDeclChecker() {
	firstQuestion := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	secondQuestion := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewIntegerType()))
	exampleBody := stmt.NewStmtList([]interfaces.Question{firstQuestion, secondQuestion}, []interfaces.Conditional{})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.QuestionRedeclaredWithDifferentTypesError{}, 1)
}
func (suite *TypeCheckerTestSuite) TestNonBoolConditionalChecker() {
	exampleQuestion := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	exampleIf := stmt.NewIf(expr.NewIntegerLiteral(10), stmt.NewStmtList([]interfaces.Question{exampleQuestion}, []interfaces.Conditional{}))
	exampleBody := stmt.NewStmtList([]interfaces.Question{}, []interfaces.Conditional{exampleIf})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.NonBooleanConditionError{}, 1)
}
func TestVarExpr(t *testing.T) {
	exampleVarID := vari.NewVarID("TestIdentifier")

	symbols := symbols.NewVarIDValueSymbols()
	symbols.SetExprForVarID(NewIntegerLiteral(2), exampleVarID)

	assert.Equal(t, NewVarExpr(exampleVarID).Eval(symbols), NewIntValue(2))
}
func TestInputQuestion(t *testing.T) {
	exampleLabel := expr.NewStringLiteral("Did you sell a house in 2010?")
	exampleVarDecl := vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType())

	exampleQuestion := NewInputQuestion(exampleLabel, exampleVarDecl)

	assert.Equal(t, exampleQuestion.Label(), exampleLabel)
}
func (suite *TypeCheckerTestSuite) TestCyclicReferenceCheckerReferenceToEachOther() {
	questionPointingToSecondQuestion := stmt.NewComputedQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()), expr.NewVarExpr(vari.NewVarID("hasBoughtHouse")))
	questionPointingToFirstQuestion := stmt.NewComputedQuestion(expr.NewStringLiteral("Did you buy a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasBoughtHouse"), expr.NewBoolType()), expr.NewVarExpr(vari.NewVarID("hasSoldHouse")))
	exampleBody := stmt.NewStmtList([]interfaces.Question{questionPointingToFirstQuestion, questionPointingToSecondQuestion}, []interfaces.Conditional{})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.CyclicDependencyError{}, 1)
}
func TestFormWithEmptyContent(t *testing.T) {
	identifier := vari.NewVarID("TestForm")
	exampleForm := NewForm(identifier, NewEmptyStmtList())

	assert.Equal(t, exampleForm.Identifier(), identifier)
	assert.Zero(t, len(exampleForm.Content().Questions()))
	assert.Zero(t, len(exampleForm.Content().Conditionals()))
}
func TestFormWithNonEmptyContent(t *testing.T) {
	identifier := vari.NewVarID("TestForm")
	questionExample := NewInputQuestion(expr.NewStringLiteral("What was the selling price?"), vari.NewVarDecl(vari.NewVarID("sellingPrice"), expr.NewIntegerType()))
	questionsListExample := []interfaces.Question{questionExample}
	stmtListExample := NewStmtList(questionsListExample, []interfaces.Conditional{})
	exampleForm := NewForm(identifier, stmtListExample)

	assert.Equal(t, len(exampleForm.Content().Questions()), 1)
	assert.True(t, util.AreStmtListsEqual(exampleForm.Content(), stmtListExample))
}
func TestFormQuestion(t *testing.T) {
	exampleFormInput := "form TestForm { \"Did you sell a house in 2010?\" hasSoldHouse: boolean \"Did you enter a loan?\" hasMaintLoan: boolean }"

	firstQuestionOutput := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	secondQuestionOutput := stmt.NewInputQuestion(expr.NewStringLiteral("Did you enter a loan?"), vari.NewVarDecl(vari.NewVarID("hasMaintLoan"), expr.NewBoolType()))
	exampleBodyOutput := stmt.NewStmtList([]interfaces.Question{firstQuestionOutput, secondQuestionOutput}, []interfaces.Conditional{})
	exampleOutputForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBodyOutput)

	testStmtParse(t, exampleFormInput, exampleOutputForm)
}
func TestTypeCheckSymbolsAdd(t *testing.T) {
	symbols := NewTypeCheckSymbols()
	exampleVarID := vari.NewVarID("testIdentifier")
	symbols.SetTypeForVarID(expr.NewBoolType(), exampleVarID)
	valueTypeExample := expr.NewBoolType()

	if lookupValue := symbols.TypeForVarID(exampleVarID); lookupValue != valueTypeExample {
		t.Errorf("TypeCheckSymbols not updated correctly, expected value %s for key %s, is %s", valueTypeExample, exampleVarID, lookupValue)
	}
}
func TestVarIDValueSymbolsAdd(t *testing.T) {
	symbols := NewVarIDValueSymbols()
	exampleVarID := vari.NewVarID("testIdentifier")
	exprExample := expr.NewSub(expr.NewIntegerLiteral(1), expr.NewIntegerLiteral(2))
	symbols.SetExprForVarID(exprExample, exampleVarID)

	if lookupExprValue := symbols.ExprForVarID(exampleVarID); lookupExprValue != exprExample {
		t.Errorf("VarIDValueSymbols not updated correctly, expected value %s for key %s, is %s", exprExample, exampleVarID, lookupExprValue)
	}
}
func TestComputedQuestion(t *testing.T) {
	exampleLabel := expr.NewStringLiteral("Value residue")
	exampleVarDecl := vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewIntegerType())
	exampleComputation := expr.NewSub(expr.NewIntegerLiteral(10), expr.NewIntegerLiteral(5))

	exampleQuestion := NewComputedQuestion(exampleLabel, exampleVarDecl, exampleComputation)

	assert.Equal(t, exampleQuestion.Label(), exampleLabel)
	assert.Equal(t, exampleQuestion.Computation(), exampleComputation)
}
func TestFormComputedQuestion(t *testing.T) {
	exampleFormInput := "form TestForm { \"Did you sell a house in 2010?\" hasSoldHouse: integer \"Did you enter a loan?\" hasMaintLoan: integer \"Value residue:\" valueResidue: integer = (hasSoldHouse - hasMaintLoan) }"

	firstQuestionOutput := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewIntegerType()))
	secondQuestionOutput := stmt.NewInputQuestion(expr.NewStringLiteral("Did you enter a loan?"), vari.NewVarDecl(vari.NewVarID("hasMaintLoan"), expr.NewIntegerType()))
	computedQuestion := stmt.NewComputedQuestion(expr.NewStringLiteral("Value residue:"), vari.NewVarDecl(vari.NewVarID("valueResidue"), expr.NewIntegerType()), expr.NewSub(expr.NewVarExpr(vari.NewVarID("hasSoldHouse")), expr.NewVarExpr(vari.NewVarID("hasMaintLoan"))))
	exampleBodyOutput := stmt.NewStmtList([]interfaces.Question{firstQuestionOutput, secondQuestionOutput, computedQuestion}, []interfaces.Conditional{})
	exampleOutputForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBodyOutput)

	testStmtParse(t, exampleFormInput, exampleOutputForm)
}
func (suite *TypeCheckerTestSuite) TestThatCorrectFormYieldsNoErrorsOrWarnings() {
	firstQuestion := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	firstQuestionBody := stmt.NewInputQuestion(expr.NewStringLiteral("What was the selling price?"), vari.NewVarDecl(vari.NewVarID("sellingPrice"), expr.NewIntegerType()))
	ifBody := stmt.NewStmtList([]interfaces.Question{firstQuestionBody}, []interfaces.Conditional{})
	elseBody := stmt.NewStmtList([]interfaces.Question{firstQuestionBody}, []interfaces.Conditional{})
	ifExample := stmt.NewIfElse(expr.NewBoolLiteral(true), ifBody, elseBody)
	exampleBody := stmt.NewStmtList([]interfaces.Question{firstQuestion}, []interfaces.Conditional{ifExample})
	exampleForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBody)

	suite.testThatNumberOfErrorsOfPassedTypeArePresentForForm(exampleForm, errors.TypeCheckError{}, 0)
}
func TestFormIfElse(t *testing.T) {
	exampleFormInput := "form TestForm { \"Did you sell a house in 2010?\" hasSoldHouse: boolean if (true) { \"What was the selling price?\" sellingPrice: integer } else { \"What was the selling price?\" sellingPrice: integer } }"
	firstQuestionOutput := stmt.NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	firstQuestionBodyInput := stmt.NewInputQuestion(expr.NewStringLiteral("What was the selling price?"), vari.NewVarDecl(vari.NewVarID("sellingPrice"), expr.NewIntegerType()))
	ifBodyOutput := stmt.NewStmtList([]interfaces.Question{firstQuestionBodyInput}, []interfaces.Conditional{})
	elseBodyOutput := stmt.NewStmtList([]interfaces.Question{firstQuestionBodyInput}, []interfaces.Conditional{})
	ifOutput := stmt.NewIfElse(expr.NewBoolLiteral(true), ifBodyOutput, elseBodyOutput)
	exampleBodyOutput := stmt.NewStmtList([]interfaces.Question{firstQuestionOutput}, []interfaces.Conditional{ifOutput})
	exampleOutputForm := stmt.NewForm(vari.NewVarID("TestForm"), exampleBodyOutput)

	testStmtParse(t, exampleFormInput, exampleOutputForm)
}
func TestVarIDValueSymbolsSaveToDisk(t *testing.T) {
	symbols := NewVarIDValueSymbols()
	exampleVarID := vari.NewVarID("testIdentifier")
	symbols.SetExprForVarID(expr.NewStringLiteral("testValue"), exampleVarID)

	symbols.SaveToDisk()

	qlFile, err := ioutil.ReadFile("savedForm.json")
	if err != nil || !strings.Contains(string(qlFile), "testIdentifier\": \"testValue") {
		t.Errorf("Output file does not contain correct data %s", qlFile)
	}

	// clean up file
	removeOutputFileAfterTest()
}
func TestIf(t *testing.T) {
	questionExample := NewInputQuestion(expr.NewStringLiteral("What was the selling price?"), vari.NewVarDecl(vari.NewVarID("sellingPrice"), expr.NewIntegerType()))
	ifBodyExample := NewStmtList([]interfaces.Question{questionExample}, []interfaces.Conditional{})
	ifCondExample := expr.NewBoolLiteral(true)
	ifExample := NewIf(ifCondExample, ifBodyExample)

	assert.True(t, util.AreStmtListsEqual(ifExample.Body(), ifBodyExample))
	assert.Equal(t, ifExample.Condition(), ifCondExample)
	assert.Equal(t, true, ifExample.EvalConditionAsBool(nil))
}
func TestIfElse(t *testing.T) {
	ifQuestionExample := NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	ifBodyExample := NewStmtList([]interfaces.Question{ifQuestionExample}, []interfaces.Conditional{})
	ifCondExample := expr.NewBoolLiteral(true)

	elseQuestionExample := NewInputQuestion(expr.NewStringLiteral("What was the selling price?"), vari.NewVarDecl(vari.NewVarID("sellingPrice"), expr.NewIntegerType()))
	elseBodyExample := NewStmtList([]interfaces.Question{elseQuestionExample}, []interfaces.Conditional{})

	ifElseExample := NewIfElse(ifCondExample, ifBodyExample, elseBodyExample)

	assert.True(t, util.AreStmtListsEqual(ifElseExample.IfBody(), ifBodyExample))
	assert.True(t, util.AreStmtListsEqual(ifElseExample.ElseBody(), elseBodyExample))
	assert.Equal(t, ifElseExample.Condition(), ifCondExample)
	assert.Equal(t, true, ifElseExample.EvalConditionAsBool(nil))
}
func TestStmtList(t *testing.T) {
	questionExample := NewInputQuestion(expr.NewStringLiteral("Did you sell a house in 2010?"), vari.NewVarDecl(vari.NewVarID("hasSoldHouse"), expr.NewBoolType()))
	questionListExample := []interfaces.Question{questionExample}

	ifExample := NewIf(expr.NewBoolLiteral(true), NewEmptyStmtList())
	conditionalListExample := []interfaces.Conditional{ifExample}

	stmtListExample := NewStmtList(questionListExample, conditionalListExample)

	assert.Equal(t, len(stmtListExample.Questions()), len(questionListExample))
	assert.Equal(t, len(stmtListExample.Conditionals()), len(conditionalListExample))
}
func TestFormIdentifierExtraction(t *testing.T) {
	exampleEmptyForm := "form TestForm {}"

	exampleOutputForm := stmt.NewForm(vari.NewVarID("TestForm"), stmt.NewEmptyStmtList())
	testStmtParse(t, exampleEmptyForm, exampleOutputForm)
}