Compile error testing in CBot

dev-time-step
krzys-h 2015-12-23 20:54:35 +01:00
parent 8437a9bdd2
commit b102f767d0
1 changed files with 101 additions and 46 deletions

View File

@ -21,44 +21,6 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
class CBotTestFail : public std::runtime_error {
public:
CBotTestFail(const std::string& message) : runtime_error(message)
{
}
CBotTestFail(std::string message, int cursor1, int cursor2) : CBotTestFail(message)
{
this->cursor1 = cursor1;
this->cursor2 = cursor2;
}
int cursor1 = -1;
int cursor2 = -1;
};
CBotTypResult cFail(CBotVar* &var, void* user)
{
if (var != nullptr)
{
if (var->GetType() != CBotTypString) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
}
if (var != nullptr) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypVoid);
}
bool rFail(CBotVar* var, CBotVar* result, int& exception, void* user)
{
std::string message = "CBot test failed";
if (var != nullptr)
{
message = var->GetValString();
}
throw CBotTestFail(message);
}
class CBotUT : public testing::Test class CBotUT : public testing::Test
{ {
public: public:
@ -73,7 +35,45 @@ public:
CBotProgram::Free(); CBotProgram::Free();
} }
protected: private:
class CBotTestFail : public std::runtime_error {
public:
CBotTestFail(const std::string& message) : runtime_error(message)
{
}
CBotTestFail(std::string message, int cursor1, int cursor2) : CBotTestFail(message)
{
this->cursor1 = cursor1;
this->cursor2 = cursor2;
}
int cursor1 = -1;
int cursor2 = -1;
};
static CBotTypResult cFail(CBotVar* &var, void* user)
{
if (var != nullptr)
{
if (var->GetType() != CBotTypString) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
}
if (var != nullptr) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypVoid);
}
static bool rFail(CBotVar* var, CBotVar* result, int& exception, void* user)
{
std::string message = "CBot test failed";
if (var != nullptr)
{
message = var->GetValString();
}
throw CBotTestFail(message);
}
// Modified version of PutList from src/script/script.cpp // Modified version of PutList from src/script/script.cpp
// Should be probably moved somewhere into the CBot library // Should be probably moved somewhere into the CBot library
void PrintVars(std::stringstream& ss, CBotVar* var, const std::string& baseName = "", bool bArray = false) void PrintVars(std::stringstream& ss, CBotVar* var, const std::string& baseName = "", bool bArray = false)
@ -136,18 +136,32 @@ protected:
} }
} }
protected:
void ExecuteTest(const std::string& code, CBotError expectedError = CBotNoErr) void ExecuteTest(const std::string& code, CBotError expectedError = CBotNoErr)
{ {
CBotError expectedCompileError = expectedError < 6000 ? expectedError : CBotNoErr;
CBotError expectedRuntimeError = expectedError >= 6000 ? expectedError : CBotNoErr;
auto program = std::unique_ptr<CBotProgram>(new CBotProgram()); auto program = std::unique_ptr<CBotProgram>(new CBotProgram());
std::vector<std::string> tests; std::vector<std::string> tests;
program->Compile(code, tests); program->Compile(code, tests);
CBotError error; CBotError error;
int cursor1, cursor2; int cursor1, cursor2;
if (program->GetError(error, cursor1, cursor2)) program->GetError(error, cursor1, cursor2);
if (error != expectedCompileError)
{ {
FAIL() << "Compile error - " << error << " (" << cursor1 << "-" << cursor2 << ")"; // TODO: Error messages are on Colobot side std::stringstream ss;
if (error != CBotNoErr)
{
FAIL() << "Compile error - " << error << " (" << cursor1 << "-" << cursor2 << ")"; // TODO: Error messages are on Colobot side
}
else
{
FAIL() << "No compile error, expected " << expectedCompileError; // TODO: Error messages are on Colobot side
}
} }
if (expectedCompileError != CBotNoErr) return;
for (const std::string& test : tests) for (const std::string& test : tests)
{ {
@ -156,7 +170,7 @@ protected:
program->Start(test); program->Start(test);
while (!program->Run()); while (!program->Run());
program->GetError(error, cursor1, cursor2); program->GetError(error, cursor1, cursor2);
if (error != expectedError) if (error != expectedRuntimeError)
{ {
std::stringstream ss; std::stringstream ss;
if (error != CBotNoErr) if (error != CBotNoErr)
@ -165,7 +179,7 @@ protected:
} }
else else
{ {
ss << "No runtime error, expected " << expectedError; // TODO: Error messages are on Colobot side ss << "No runtime error, expected " << expectedRuntimeError; // TODO: Error messages are on Colobot side
cursor1 = cursor2 = -1; cursor1 = cursor2 = -1;
} }
throw CBotTestFail(ss.str(), cursor1, cursor2); throw CBotTestFail(ss.str(), cursor1, cursor2);
@ -207,15 +221,56 @@ protected:
TEST_F(CBotUT, Test) TEST_F(CBotUT, Test)
{ {
ExecuteTest("extern void EmptyTest() { }"); ExecuteTest(
"extern void EmptyTest()"
"{"
"}"
);
} }
TEST_F(CBotUT, DISABLED_TestFail) TEST_F(CBotUT, DISABLED_TestFail)
{ {
ExecuteTest("extern void FailingTest() { FAIL(); } extern void AnotherFailingTest() { FAIL(\"This is a message\"); }"); ExecuteTest(
"extern void FailingTest()"
"{"
" FAIL();"
"}"
"extern void AnotherFailingTest()"
"{"
" FAIL(\"This is a message\");"
"}"
);
} }
TEST_F(CBotUT, DivideByZero) TEST_F(CBotUT, DivideByZero)
{ {
ExecuteTest("extern void DivideByZero() { float a = 5/0; }", CBotErrZeroDiv); ExecuteTest(
"extern void DivideByZero()"
"{"
" float a = 5/0;"
"}",
CBotErrZeroDiv
);
} }
TEST_F(CBotUT, MissingSemicolon)
{
ExecuteTest(
"extern void MissingSemicolon()"
"{"
" string a = \"hello\""
"}",
CBotErrNoTerminator
);
}
TEST_F(CBotUT, UndefinedFunction)
{
ExecuteTest(
"extern void UndefinedFunction()"
"{"
" foo();"
"}",
CBotErrUndefCall
);
}