separate testing environment

-Separate main for running unit tests
-Move unit tests into testing folder
This commit is contained in:
marauder2k7 2023-07-24 12:38:36 +01:00
parent 2e8f5795fa
commit c09f79d199
265 changed files with 84537 additions and 334 deletions

View file

@ -210,6 +210,11 @@ if (UNIX AND NOT APPLE)
torqueAddSourceDirectories("platformX11")
endif (UNIX AND NOT APPLE)
if(TORQUE_TESTING)
torqueAddSourceDirectories("testing")
set(TORQUE_COMPILE_DEFINITIONS ${TORQUE_COMPILE_DEFINITIONS} TORQUE_SHARED SDL_MAIN_HANDLED)
endif(TORQUE_TESTING)
# Add the collected files to our engine group
source_group(TREE "${CMAKE_SOURCE_DIR}/Engine/source" PREFIX "Engine" FILES ${TORQUE_SOURCE_FILES})
@ -312,7 +317,7 @@ if (NOT TORQUE_NET_CURL)
endif()
################# Executable Generation ###################
if (TORQUE_DYNAMIC_LIBRARY)
if (TORQUE_DYNAMIC_LIBRARY AND NOT TORQUE_TESTING)
set(TORQUE_COMPILE_DEFINITIONS ${TORQUE_COMPILE_DEFINITIONS} TORQUE_SHARED)
# Build the main engine library
@ -325,8 +330,10 @@ if (TORQUE_DYNAMIC_LIBRARY)
set(TORQUE_SOURCE_FILES "main/main.cpp")
set(TORQUE_LINK_LIBRARIES TorqueEngine)
else()
set(TORQUE_SOURCE_FILES "main/main.cpp" ${TORQUE_SOURCE_FILES})
endif (TORQUE_DYNAMIC_LIBRARY)
if(NOT TORQUE_TESTING)
set(TORQUE_SOURCE_FILES "main/main.cpp" ${TORQUE_SOURCE_FILES})
endif()
endif (TORQUE_DYNAMIC_LIBRARY AND NOT TORQUE_TESTING)
if (APPLE)
add_executable(${TORQUE_APP_NAME} MACOSX_BUNDLE ${TORQUE_SOURCE_FILES})
@ -377,6 +384,15 @@ target_compile_definitions(${TORQUE_APP_NAME} PUBLIC ${TORQUE_COMPILE_DEFINITION
target_link_libraries(${TORQUE_APP_NAME} ${TORQUE_LINK_LIBRARIES})
target_include_directories(${TORQUE_APP_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_BINARY_DIR}/temp" ${TORQUE_INCLUDE_DIRECTORIES})
target_compile_features(${TORQUE_APP_NAME} PRIVATE cxx_std_20)
if(TORQUE_TESTING)
if(WIN32)
target_link_options(${TORQUE_APP_NAME} PRIVATE "/SUBSYSTEM:CONSOLE")
set_target_properties(gtest PROPERTIES COMPILE_FLAGS "/Zc:wchar_t-")
set_target_properties(gmock PROPERTIES COMPILE_FLAGS "/Zc:wchar_t-")
endif()
endif(TORQUE_TESTING)
append_defs()
# Process library binaries - these are coming from modules that are providing links to external, precompiled code that should be included

View file

@ -19,8 +19,6 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/platform.h"
#include "console/simBase.h"
@ -29,13 +27,31 @@
#include "console/engineAPI.h"
#include "math/mMath.h"
#include "console/stringStack.h"
#include "gui/buttons/guiIconButtonCtrl.h"
inline ConsoleValue RunScript(const char* str)
{
return std::move(Con::evaluate(str, false, NULL));
}
TEST(Script, Basic_Arithmetic)
using ::testing::Matcher;
using ::testing::TypedEq;
class ScriptTest : public ::testing::Test
{
protected:
ScriptTest()
{
}
void SetUp() override
{
}
};
TEST_F(ScriptTest, Basic_Arithmetic)
{
ConsoleValue add = RunScript(R"(
return 1.0 + 1;
@ -116,7 +132,7 @@ TEST(Script, Basic_Arithmetic)
ASSERT_EQ(mm.getInt(), 1);
}
TEST(Script, Complex_Arithmetic)
TEST_F(ScriptTest, Complex_Arithmetic)
{
ConsoleValue result = RunScript(R"(
return 1 * 2 - (0.5 * 2);
@ -131,7 +147,7 @@ TEST(Script, Complex_Arithmetic)
ASSERT_EQ(result2.getInt(), 0);
}
TEST(Script, Basic_Concatination)
TEST_F(ScriptTest, Basic_Concatination)
{
ConsoleValue result1 = RunScript(R"(
return "a" @ "b";
@ -164,7 +180,7 @@ TEST(Script, Basic_Concatination)
ASSERT_STREQ(complex.getString(), "abcd");
}
TEST(Script, Basic_Global_Variable_Tests)
TEST_F(ScriptTest, Basic_Global_Variable_Tests)
{
ConsoleValue value = RunScript(R"(
$a = 1;
@ -174,7 +190,7 @@ TEST(Script, Basic_Global_Variable_Tests)
ASSERT_EQ(value.getInt(), 1);
}
TEST(Script, Variable_Chaining_And_Usage)
TEST_F(ScriptTest, Variable_Chaining_And_Usage)
{
ConsoleValue value = RunScript(R"(
function t()
@ -212,7 +228,7 @@ TEST(Script, Variable_Chaining_And_Usage)
ASSERT_EQ(value2.getInt(), 4);
}
TEST(Script, Basic_Function_Call_And_Local_Variable_Testing)
TEST_F(ScriptTest, Basic_Function_Call_And_Local_Variable_Testing)
{
ConsoleValue value = RunScript(R"(
function t() { %a = 2; return %a; }
@ -251,7 +267,7 @@ TEST(Script, Basic_Function_Call_And_Local_Variable_Testing)
ASSERT_EQ(staticCall.getInt(), 3);
}
TEST(Script, Basic_Conditional_Statements)
TEST_F(ScriptTest, Basic_Conditional_Statements)
{
ConsoleValue value = RunScript(R"(
$a = "hello";
@ -269,7 +285,7 @@ TEST(Script, Basic_Conditional_Statements)
ASSERT_STREQ(ternaryValue.getString(), "World");
}
TEST(Script, Basic_Loop_Statements)
TEST_F(ScriptTest, Basic_Loop_Statements)
{
ConsoleValue whileValue = RunScript(R"(
$count = 0;
@ -331,7 +347,7 @@ TEST(Script, Basic_Loop_Statements)
ASSERT_STREQ(forIfValue.getString(), "0, 1, 2, 3, 4");
}
TEST(Script, ForEachLoop)
TEST_F(ScriptTest, ForEachLoop)
{
ConsoleValue forEach1 = RunScript(R"(
$theSimSet = new SimSet();
@ -525,7 +541,7 @@ TEST(Script, ForEachLoop)
ASSERT_EQ(forEachNestedReturn.getInt(), 42);
}
TEST(Script, TorqueScript_Array_Testing)
TEST_F(ScriptTest, TorqueScript_Array_Testing)
{
ConsoleValue value = RunScript(R"(
function t(%idx) { %a[%idx] = 2; return %a[%idx]; }
@ -542,7 +558,7 @@ TEST(Script, TorqueScript_Array_Testing)
ASSERT_EQ(value2.getInt(), 2);
}
TEST(Script, SimObject_Tests)
TEST_F(ScriptTest, SimObject_Tests)
{
ConsoleValue object = RunScript(R"(
return new SimObject(FudgeCollector)
@ -697,7 +713,7 @@ TEST(Script, SimObject_Tests)
ASSERT_EQ(inheritedObjectTest.getInt(), 11);
}
TEST(Script, Internal_Name)
TEST_F(ScriptTest, Internal_Name)
{
ConsoleValue value = RunScript(R"(
function TheFirstInner::_internalCall(%this)
@ -763,7 +779,7 @@ TEST(Script, Internal_Name)
ASSERT_EQ(recursiveValue.getInt(), 12);
}
TEST(Script, Basic_Package)
TEST_F(ScriptTest, Basic_Package)
{
ConsoleValue value = RunScript(R"(
function a() { return 3; }
@ -791,7 +807,7 @@ TEST(Script, Basic_Package)
ASSERT_EQ(deactivatedValue.getInt(), 3);
}
TEST(Script, Sugar_Syntax)
TEST_F(ScriptTest, Sugar_Syntax)
{
ConsoleValue value = RunScript(R"(
function a()
@ -873,7 +889,7 @@ TEST(Script, Sugar_Syntax)
ASSERT_EQ(globalValueSet.getFloat(), 4);
}
TEST(Script, InnerObjectTests)
TEST_F(ScriptTest, InnerObjectTests)
{
ConsoleValue theObject = RunScript(R"(
function a()
@ -927,7 +943,7 @@ TEST(Script, InnerObjectTests)
ASSERT_EQ(nestedFuncCall.getInt(), 123);
}
TEST(Script, MiscTesting)
TEST_F(ScriptTest, MiscTesting)
{
ConsoleValue test1 = RunScript(R"(
function testNotPassedInParameters(%a, %b, %c, %d)
@ -961,7 +977,7 @@ TEST(Script, MiscTesting)
ASSERT_EQ(test2.getBool(), true);
}
TEST(Script, MiscRegressions)
TEST_F(ScriptTest, RegressionInt)
{
ConsoleValue regression1 = RunScript(R"(
new SimObject(TheRegressionObject);
@ -1001,6 +1017,87 @@ TEST(Script, MiscRegressions)
ASSERT_EQ(regression2.getInt(), 400);
ConsoleValue regression3 = RunScript(R"(
function noOpInc()
{
%count = 0;
%var[%count++] = 2;
return %var[1];
}
return noOpInc();
)");
ASSERT_EQ(regression3.getInt(), 2);
}
TEST_F(ScriptTest, RegressionFloat)
{
ConsoleValue regression = RunScript(R"(
function doTest()
{
%slider = new GuiSliderCtrl()
{
range = "0 2";
ticks = 5;
active = true;
};
%slider.setValue(0.5);
return %slider.getValue();
}
return doTest();
)");
ASSERT_EQ(regression.getFloat(), 0.5);
}
TEST_F(ScriptTest, RegressionBool)
{
ConsoleValue regression = RunScript(R"(
function SimObject::burnBool(%this, %line)
{
return %line @ "1";
}
function doTest()
{
%obj = new SimObject();
for (%i = 0; %i < 100; %i++)
{
%function = "burnBool";
if (%obj.isMethod(%function))
{
%line = "abcdefg";
%output = %obj.call(%function, %line);
}
}
return true;
}
return doTest();
)");
ASSERT_EQ(regression.getBool(), true);
}
TEST_F(ScriptTest, RegressionString)
{
ConsoleValue regression = RunScript(R"(
function Tween::vectorAdd(%v1, %v2)
{
%temp = "";
for (%i = 0; %i < getWordCount(%v1); %i++) {
%e = getWord(%v1, %i) + getWord(%v2, %i);
%temp = %i == 0 ? %e : %temp SPC %e;
}
return %temp;
}
return Tween::vectorAdd("1 2 3", "4 5 6");
)");
ASSERT_STREQ(regression.getString(), "5 7 9");
ConsoleValue regression2 = RunScript(R"(
function doTest()
{
%button = new GuiIconButtonCtrl()
@ -1021,80 +1118,5 @@ TEST(Script, MiscRegressions)
return doTest();
)");
ASSERT_STREQ(regression3.getString(), "120 20");
ConsoleValue regression4 = RunScript(R"(
function doTest()
{
%slider = new GuiSliderCtrl()
{
range = "0 2";
ticks = 5;
active = true;
};
%slider.setValue(0.5);
return %slider.getValue();
}
return doTest();
)");
ASSERT_EQ(regression4.getFloat(), 0.5);
ConsoleValue regression5 = RunScript(R"(
function noOpInc()
{
%count = 0;
%var[%count++] = 2;
return %var[1];
}
return noOpInc();
)");
ASSERT_EQ(regression5.getInt(), 2);
ConsoleValue regression6 = RunScript(R"(
function SimObject::crashMe(%this, %line)
{
return %line @ "1";
}
function doTest()
{
%obj = new SimObject();
for (%i = 0; %i < 99999; %i++)
{
%function = "crashMe";
if (%obj.isMethod(%function))
{
%line = "abcdefg";
%output = %obj.call(%function, %line);
}
}
return true;
}
return doTest();
)");
ASSERT_EQ(regression6.getBool(), true);
ConsoleValue regression7 = RunScript(R"(
function Tween::vectorAdd(%v1, %v2)
{
%temp = "";
for (%i = 0; %i < getWordCount(%v1); %i++) {
%e = getWord(%v1, %i) + getWord(%v2, %i);
%temp = %i == 0 ? %e : %temp SPC %e;
}
return %temp;
}
return Tween::vectorAdd("1 2 3", "4 5 6");
)");
ASSERT_STREQ(regression7.getString(), "5 7 9");
ASSERT_STREQ(regression2.getString(), "120 20");
}
#endif

View file

@ -1,9 +1,9 @@
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/platform.h"
#include "console/simBase.h"
#include "console/consoleTypes.h"
#include "console/scriptObjects.h"
#include "console/simBase.h"
#include "console/engineAPI.h"
#include "math/mMath.h"
@ -13,57 +13,69 @@
// Stupid globals not declared in a header
extern ExprEvalState gEvalState;
TEST(Con, executef)
using ::testing::Matcher;
using ::testing::TypedEq;
class ConsoleTest : public ::testing::Test
{
char buffer[128];
Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction TestConExec::testThisFunction(%this,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\nnew ScriptObject(TestConExec);\r\n", false, "test");
protected:
ConsoleTest()
{
}
SimObject *testObject = NULL;
Sim::findObject("TestConExec", testObject);
void SetUp() override
{
}
};
EXPECT_TRUE(testObject != NULL)
<< "TestConExec object should exist";
TEST_F(ConsoleTest, executef)
{
char buffer[128];
Con::evaluate("function testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction testThisFunction(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j, %this){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\n", false, "test");
// Check basic calls with SimObject. We'll do this for every single possible call just to make sure.
ConsoleValue returnValue;
returnValue = Con::executef(testObject, "testThisFunction");
returnValue = Con::executef("testThisFunction");
EXPECT_STREQ(returnValue, " ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a");
returnValue = Con::executef("testThisFunction", "a");
EXPECT_STREQ(returnValue, "a ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b");
returnValue = Con::executef("testThisFunction", "a", "b");
EXPECT_STREQ(returnValue, "a b ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c");
returnValue = Con::executef("testThisFunction", "a", "b", "c");
EXPECT_STREQ(returnValue, "a b c ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d");
returnValue = Con::executef("testThisFunction", "a", "b", "c", "d");
EXPECT_STREQ(returnValue, "a b c d ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e");
returnValue = Con::executef("testThisFunction", "a", "b", "c", "d", "e");
EXPECT_STREQ(returnValue, "a b c d e ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f");
returnValue = Con::executef("testThisFunction", "a", "b", "c", "d", "e", "f");
EXPECT_STREQ(returnValue, "a b c d e f ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f", "g");
returnValue = Con::executef("testThisFunction", "a", "b", "c", "d", "e", "f", "g");
EXPECT_STREQ(returnValue, "a b c d e f g ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f", "g", "h");
returnValue = Con::executef("testThisFunction", "a", "b", "c", "d", "e", "f", "g", "h");
EXPECT_STREQ(returnValue, "a b c d e f g h ") <<
"All values should be printed in the correct order";
returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f", "g", "h", "i");
returnValue = Con::executef("testThisFunction", "a", "b", "c", "d", "e", "f", "g", "h", "i");
EXPECT_STREQ(returnValue, "a b c d e f g h i ") <<
"All values should be printed in the correct order";
@ -116,7 +128,7 @@ TEST(Con, executef)
// Test type conversions with and without SimObject...
// Integer
returnValue = Con::executef(testObject, "testThisFunction", 123);
returnValue = Con::executef("testThisFunction", 123);
EXPECT_STREQ(returnValue, "123 ") <<
"Integer should be converted";
returnValue = Con::executef("testExecutef", 123);
@ -124,26 +136,17 @@ TEST(Con, executef)
"Integer should be converted";
// Float
returnValue = Con::executef(testObject, "testThisFunction", (F32)123.0);
returnValue = Con::executef("testThisFunction", (F32)123.0);
EXPECT_STREQ(returnValue, "123 ") <<
"Float should be converted";
returnValue = Con::executef("testExecutef", (F32)123.0);
EXPECT_STREQ(returnValue, "123 ") <<
"Float should be converted";
// SimObject
dSprintf(buffer, sizeof(buffer), "%i ", testObject->getId());
returnValue = Con::executef(testObject, "testThisFunction", testObject);
EXPECT_STREQ(returnValue, buffer) <<
"SimObject should be converted";
dSprintf(buffer, sizeof(buffer), "%i ", testObject->getId());
returnValue = Con::executef("testExecutef", testObject);
EXPECT_STREQ(returnValue, buffer) <<
"SimObject should be converted";
// Point3F
Point3F point(1,2,3);
returnValue = Con::executef(testObject, "testThisFunction", point);
returnValue = Con::executef("testThisFunction", point);
EXPECT_STREQ(returnValue, "1 2 3 ") <<
"Point3F should be converted";
returnValue = Con::executef("testExecutef", point);
@ -167,29 +170,18 @@ TEST(Con, executef)
floatArg = Con::getFloatArg(1.23);
EXPECT_GT(STR.mFunctionOffset, 0) <<
"Function offset should not be 0";
Con::executef("testImaginaryFunction_", floatArg);
EXPECT_EQ(STR.mFunctionOffset, 0) <<
"Function offset should be 0";
}
TEST(Con, execute)
TEST_F(ConsoleTest, execute)
{
Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testScriptExecuteFunction(%a,%b) {return %a SPC %b;}\nfunction TestConExec::testScriptExecuteFunction(%this, %a,%b) {return %a SPC %b;}new ScriptObject(TestConExec);\r\n", false, "testExecute");
Con::evaluate("function testScriptExecuteFunction(%a,%b) {return %a SPC %b;}\nfunction testScriptExecuteFunction(%a,%b,%this) {return %a SPC %b;}\r\n", false, "testExecute");
U32 startStackPos = gEvalState.getStackDepth();
U32 startStringStackPos = STR.mStart;
SimObject *testObject = NULL;
Sim::findObject("TestConExec", testObject);
EXPECT_TRUE(testObject != NULL)
<< "TestConExec object should exist";
// const char* versions of execute should maintain stack
const char *argv[] = {"testScriptExecuteFunction", "1", "2"};
const char *argvObject[] = {"testScriptExecuteFunction", "", "1", "2"};
const char *argvObject[] = {"testScriptExecuteFunction", "1", "2", ""};
ConsoleValue returnValue = Con::execute(3, argv);
EXPECT_STREQ(returnValue, "1 2") <<
@ -198,7 +190,7 @@ TEST(Con, execute)
EXPECT_EQ(gEvalState.getStackDepth(), startStackPos) <<
"execute should restore stack";
returnValue = Con::execute(testObject, 4, argvObject);
returnValue = Con::execute(4, argvObject);
EXPECT_STREQ(returnValue, "1 2") <<
"execute should return 1 2";
@ -206,5 +198,3 @@ TEST(Con, execute)
EXPECT_EQ(gEvalState.getStackDepth(), startStackPos) <<
"execute should restore stack";
}
#endif

View file

@ -1,14 +1,33 @@
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/platform.h"
#include "console/simBase.h"
#include "console/consoleTypes.h"
#include "console/scriptObjects.h"
#include "console/simBase.h"
#include "console/engineAPI.h"
#include "math/mMath.h"
using ::testing::Matcher;
using ::testing::TypedEq;
TEST(EngineAPI, EngineMarshallData)
class EngineAPITest : public ::testing::Test
{
protected:
EngineAPITest()
{
}
void SetUp() override
{
ScriptObject* test = new ScriptObject();
test->assignName("TestConExec");
}
};
TEST_F(EngineAPITest, EngineMarshallData)
{
// Reserve some values
ConsoleValue values[16];
@ -97,7 +116,7 @@ TEST(EngineAPI, EngineMarshallData)
foo->deleteObject();
}
TEST(EngineAPI, EngineUnMarshallData)
TEST_F(EngineAPITest, EngineUnMarshallData)
{
SimObject *foo = new SimObject();
foo->registerObject();
@ -114,7 +133,7 @@ TEST(EngineAPI, EngineUnMarshallData)
foo->deleteObject();
}
TEST(EngineAPI, _EngineConsoleCallbackHelper)
TEST_F(EngineAPITest, _EngineConsoleCallbackHelper)
{
Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction TestConExec::testThisFunction(%this,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\nnew ScriptObject(TestConExec);\r\n", false, "test");
@ -135,7 +154,7 @@ TEST(EngineAPI, _EngineConsoleCallbackHelper)
}
// NOTE: this is also indirectly tested by the executef tests
TEST(EngineAPI, _EngineConsoleExecCallbackHelper)
TEST_F(EngineAPITest, _EngineConsoleExecCallbackHelper)
{
Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction TestConExec::testThisFunction(%this,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\nnew ScriptObject(TestConExec);\r\n", false, "test");
@ -155,4 +174,3 @@ TEST(EngineAPI, _EngineConsoleExecCallbackHelper)
"All values should be printed in the correct order";
}
#endif

View file

@ -20,14 +20,38 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/platform.h"
#include "core/fileio.h"
#include "core/util/tVector.h"
#include "console/console.h"
TEST(Platform, ExcludedDirectories)
class PlatformFileIOTest : public ::testing::Test
{
protected:
PlatformFileIOTest()
{
// create a file for tests.
f.open("testTouch.file", File::WriteAppend);
f.close();
Platform::getFileTimes("testTouch.file", &initCreate, NULL);
}
void SetUp() override
{
}
File f;
FileTime initCreate;
void TearDown() override
{
// Clean up..
dFileDelete("testTouch.file");
}
};
TEST_F(PlatformFileIOTest, ExcludedDirectories)
{
// Just dump everything under the current directory. We should
// find at least one file.
@ -57,53 +81,53 @@ TEST(Platform, ExcludedDirectories)
Platform::clearExcludedDirectories();
};
TEST(File, TouchAndTime)
TEST_F(PlatformFileIOTest, CreateTest)
{
FileTime create[2], modify[2];
EXPECT_TRUE(Platform::isFile("testTouch.file"))
<< "Class should have created this file.";
}
// Create a file and sleep for a second.
File f;
f.open("testTouch.file", File::WriteAppend);
f.close();
TEST_F(PlatformFileIOTest, CreateTimeTest)
{
FileTime testCreate;
Platform::getFileTimes("testTouch.file", &testCreate, NULL);
EXPECT_EQ(Platform::compareFileTimes(testCreate, initCreate), 0)
<< "Create timestamps should match.";
}
TEST_F(PlatformFileIOTest, ModifyTimesTest)
{
FileTime modify[2];
// Touch a file and note its last-modified.
dFileTouch("testTouch.file");
// Sleep for a tick
Platform::sleep(32);
Platform::getFileTimes("testTouch.file", NULL, &modify[0]);
EXPECT_TRUE(Platform::isFile("testTouch.file"))
<< "We just touched this file - it should exist.";
EXPECT_TRUE(Platform::getFileTimes("testTouch.file", &create[0], &modify[0]))
<< "Failed to get filetimes for a file we just created.";
// Sleep for a second
Platform::sleep(1000);
// Sleep for a tick
Platform::sleep(32);
// Touch it again, and compare the last-modifieds.
EXPECT_TRUE(Platform::isFile("testTouch.file"))
<< "We just touched this file - it should exist.";
dFileTouch("testTouch.file");
EXPECT_TRUE(Platform::isFile("testTouch.file"))
<< "We just touched this file - it should exist.";
EXPECT_TRUE(Platform::getFileTimes("testTouch.file", &create[1], &modify[1]))
<< "Failed to get filetimes for a file we just created.";
Platform::getFileTimes("testTouch.file", NULL, &modify[1]);
// Now compare the times...
EXPECT_LT(Platform::compareFileTimes(modify[0], modify[1]), 0)
<< "Timestamps are wrong - modify[0] should be before modify[1]!";
EXPECT_EQ(Platform::compareFileTimes(create[0], create[1]), 0)
<< "Create timestamps should match - we didn't delete the file during this test.";
};
TEST_F(PlatformFileIOTest, DeleteFileTest)
{
// Clean up..
dFileDelete("testTouch.file");
EXPECT_FALSE(Platform::isFile("testTouch.file"))
<< "Somehow failed to delete our test file.";
};
}
// Mac/Linux have no implementations for these functions, so we 'def it out for now.
#ifdef WIN32
TEST(Platform, Volumes)
TEST_F(PlatformFileIOTest, Volumes)
{
Vector<const char*> names;
Platform::getVolumeNamesList(names);
@ -119,4 +143,3 @@ TEST(Platform, Volumes)
};
#endif
#endif

View file

@ -19,14 +19,12 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/platformTimer.h"
#include "core/util/journal/process.h"
#include "math/mMath.h"
TEST(Platform, AdvanceTime)
TEST(PlatformTimerTest, AdvanceTime)
{
U32 time = Platform::getVirtualMilliseconds();
Platform::advanceTime(10);
@ -35,7 +33,7 @@ TEST(Platform, AdvanceTime)
<< "We advanced 10ms but didn't get a 10ms delta!";
}
TEST(Platform, Sleep)
TEST(PlatformTimerTest, Sleep)
{
U32 start = Platform::getRealMilliseconds();
Platform::sleep(500);
@ -61,7 +59,7 @@ struct handle
}
};
TEST(TimeManager, BasicAPI)
TEST(PlatformTimerTest, BasicAPI)
{
handle handler;
@ -91,5 +89,3 @@ TEST(TimeManager, BasicAPI)
EXPECT_GT(handler.mNumberCalls, 0)
<< "Somehow got no event callbacks from TimeManager?";
};
#endif

View file

@ -19,13 +19,11 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "unitTesting.h"
#include "platform/platform.h"
#include "core/util/endian.h"
TEST(PlatformTypes, Sizes)
TEST(PlatformTypesTest, Sizes)
{
// Run through all the types and ensure they're the right size.
#define CheckType(typeName, expectedSize) \
@ -58,7 +56,7 @@ TEST(PlatformTypes, Sizes)
#undef CheckType
};
TEST(PlatformTypes, EndianConversion)
TEST(PlatformTypesTest, EndianConversion)
{
// Convenient and non-palindrome byte patterns to test with.
const U16 U16Test = 0xA1B2;
@ -104,7 +102,7 @@ TEST(PlatformTypes, EndianConversion)
#undef CheckEndianRoundTrip
};
TEST(PlatformTypes, EndianSwap)
TEST(PlatformTypesTest, EndianSwap)
{
U32 swap32 = 0xABCDEF12;
U16 swap16 = 0xABCD;
@ -114,5 +112,3 @@ TEST(PlatformTypes, EndianSwap)
EXPECT_EQ(endianSwap(swap16), 0xCDAB)
<< "16 bit endianSwap should reverse byte order, but didn't.";
};
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "platform/platform.h" // Allows us to see TORQUE_ENABLE_PROFILER
#ifdef TORQUE_ENABLE_PROFILER
@ -46,4 +45,3 @@ TEST(Profiler, ProfileScope)
}
#endif
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/platform.h"
#include "console/simBase.h"
@ -49,7 +48,7 @@ void RuntimeRegisteredSimObject::initPersistFields()
addField("fooField", TypeBool, Offset(mFoo, RuntimeRegisteredSimObject));
}
TEST(Console, RuntimeClassRep)
TEST(RunTimeClassRepTest, RuntimeClassRep)
{
// First test to make sure that the test class is not registered (don't
// know how it could be, but that's programming for you). Stop the test if
@ -104,5 +103,3 @@ TEST(Console, RuntimeClassRep)
EXPECT_TRUE(conobj == NULL)
<< "Unregistration of type failed";
}
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/threads/semaphore.h"
#include "platform/threads/thread.h"
@ -86,5 +85,3 @@ TEST(Semaphore, MultiThreadSynchronization)
thread2.start();
thread2.join();
}
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/threads/threadPool.h"
#include "console/console.h"
@ -117,5 +116,3 @@ TEST_FIX(ThreadPool, Synchronous)
EXPECT_EQ(true, item->hasExecuted());
}
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/threads/threadSafeDeque.h"
@ -177,10 +176,8 @@ TEST_FIX(ThreadSafeDeque, PopBack)
ASSERT_TRUE(deque.isEmpty());
}
// Test deque in a concurrent setting.
// Test many items in a row
TEST_FIX(ThreadSafeDeque, Concurrent1)
TEST_FIX(ThreadSafeDeque, Concurrent)
{
const U32 NumValues = 100;
@ -200,29 +197,3 @@ TEST_FIX(ThreadSafeDeque, Concurrent1)
mValues.clear();
};
/*
// Test a few items many times to catch any race-condition in start-up
TEST_FIX(ThreadSafeDeque, Concurrent2)
{
for (int i = 0; i < 10000; ++i)
{
Deque mDeque;
Vector<U32> mValues;
mValues.setSize(5);
ProducerThread pThread(mValues, mDeque);
ConsumerThread cThread(mValues, mDeque);
cThread.start();
pThread.start();
pThread.join();
cThread.join();
mValues.clear();
if (::testing::Test::HasFailure()) break;
}
};
*/
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/threads/threadSafePriorityQueue.h"
#include "platform/threads/thread.h"
@ -142,5 +141,3 @@ TEST(ThreadSafePriorityQueue, Concurrent)
#undef MAX
#undef LEN
}
#endif

View file

@ -20,7 +20,6 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
// This unit test will blow up without thread static support
@ -31,7 +30,7 @@
DITTS(U32, gUnitTestFoo, 42);
DITTS(F32, gUnitTestF32, 1.0);
TEST(ThreadStatic, BasicAPI)
TEST(ThreadStaticTest, BasicAPI)
{
// ThreadStatic list should be initialized right now, so lets see if it has
// any entries.
@ -95,7 +94,7 @@ TEST(ThreadStatic, BasicAPI)
DITTS(U32, gInstancedStaticFoo, 42);
static U32 gTrueStaticFoo = 42;
TEST(ThreadStatic, StressThreadStatic)
TEST(ThreadStaticTest, StressThreadStatic)
{
ASSERT_FALSE(gProfiler->isEnabled())
<< "Profiler is currently enabled, test cannot continue";
@ -136,4 +135,3 @@ TEST(ThreadStatic, StressThreadStatic)
#endif
#endif
#endif

View file

@ -20,11 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "platform/threads/thread.h"
TEST(Thread, CallbackAPI)
TEST(ThreadTest, CallbackAPI)
{
#define VALUE_TO_SET 10
@ -53,7 +52,7 @@ TEST(Thread, CallbackAPI)
#undef VALUE_TO_SET
}
TEST(Thread, InheritanceAPI)
TEST(ThreadTest, InheritanceAPI)
{
#define VALUE_TO_SET 10
@ -83,5 +82,3 @@ TEST(Thread, InheritanceAPI)
#undef VALUE_TO_SET
}
#endif

View file

@ -19,63 +19,75 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "unitTesting.h"
#ifdef TORQUE_TESTS_ENABLED
#include "app/mainLoop.h"
#include "console/console.h"
#include "console/codeBlock.h"
#include "console/engineAPI.h"
#include "console/consoleInternal.h"
#include "unitTesting.h"
#include "memoryTester.h"
#include <gtest/src/gtest-all.cc>
//-----------------------------------------------------------------------------
class TorqueUnitTestListener : public ::testing::EmptyTestEventListener
{
// Called before a test starts.
virtual void OnTestStart( const ::testing::TestInfo& testInfo )
virtual void OnTestStart(const ::testing::TestInfo& testInfo)
{
if( mVerbose )
if (mVerbose)
Con::printf("> Starting Test '%s.%s'",
testInfo.test_case_name(), testInfo.name());
}
// Called after a failed assertion or a SUCCEED() invocation.
virtual void OnTestPartResult( const ::testing::TestPartResult& testPartResult )
virtual void OnTestPartResult(const ::testing::TestPartResult& testPartResult)
{
if ( testPartResult.failed() )
if (testPartResult.failed())
{
Con::warnf(">> Failed with '%s' in '%s' at (line:%d)\n",
testPartResult.summary(),
testPartResult.file_name(),
testPartResult.line_number()
);
);
}
else if( mVerbose )
else if (mVerbose)
{
Con::printf(">> Passed with '%s' in '%s' at (line:%d)",
testPartResult.summary(),
testPartResult.file_name(),
testPartResult.line_number()
);
);
}
}
// Called after a test ends.
virtual void OnTestEnd( const ::testing::TestInfo& testInfo )
virtual void OnTestEnd(const ::testing::TestInfo& testInfo)
{
if( mVerbose )
Con::printf("> Ending Test '%s.%s'\n",
if (testInfo.result()->Failed())
{
Con::printf("TestClass:%s Test:%s Failed!",
testInfo.test_case_name(), testInfo.name());
}
else if(testInfo.result()->Passed())
{
Con::printf("TestClass:%s Test:%s Succeeded!",
testInfo.test_case_name(), testInfo.name());
}
else
{
Con::printf("TestClass:%s Test:%s Skipped!",
testInfo.test_case_name(), testInfo.name());
}
Con::printf("> Ending Test\n");
}
bool mVerbose;
public:
TorqueUnitTestListener( bool verbose ) : mVerbose( verbose ) {}
TorqueUnitTestListener(bool verbose) : mVerbose(verbose) {}
};
class TorqueScriptFixture : public testing::Test {};
@ -92,7 +104,33 @@ private:
const char* mFunctionName;
};
DefineEngineFunction( addUnitTest, void, (const char* function),,
// uncomment to debug tests and use the test explorer.
//#define TEST_EXPLORER
#if !defined(TEST_EXPLORER)
int main(int argc, char** argv)
{
StandardMainLoop::init();
StandardMainLoop::handleCommandLine(argc, (const char**)argv);
StandardMainLoop::shutdown();
return StandardMainLoop::getReturnStatus();
}
#else
int main(int argc, char** argv)
{
StandardMainLoop::init();
printf("Running main() from %s\n", __FILE__);
// setup simular to runTests
Con::evaluate("GFXInit::createNullDevice();");
Con::evaluate("if (!isObject(GuiDefaultProfile)) new GuiControlProfile(GuiDefaultProfile){}; if (!isObject(GuiTooltipProfile)) new GuiControlProfile(GuiTooltipProfile){};");
testing::InitGoogleTest(&argc, argv);
int res = RUN_ALL_TESTS();
StandardMainLoop::shutdown();
return res;
}
#endif
DefineEngineFunction(addUnitTest, void, (const char* function), ,
"Add a TorqueScript function as a GTest unit test.\n"
"@note This is only implemented rudimentarily to open the door for future development in unit-testing the engine.\n"
"@tsexample\n"
@ -129,7 +167,7 @@ String scriptFileMessage(const char* message)
return String::ToString("at %s: %s", scriptLine, message);
}
DefineEngineFunction( expectTrue, void, (bool test, const char* message),(""),
DefineEngineFunction(expectTrue, void, (bool test, const char* message), (""),
"TorqueScript wrapper around the EXPECT_TRUE assertion in GTest.\n"
"@tsexample\n"
"expectTrue(2+2 == 4, \"basic math should work\");\n"
@ -138,7 +176,7 @@ DefineEngineFunction( expectTrue, void, (bool test, const char* message),(""),
EXPECT_TRUE(test) << scriptFileMessage(message).c_str();
}
DefineEngineFunction( runAllUnitTests, int, (const char* testSpecs, const char* reportFormat), (""),
DefineEngineFunction(runAllUnitTests, int, (const char* testSpecs, const char* reportFormat), (""),
"Runs engine unit tests. Some tests are marked as 'stress' tests which do not "
"necessarily check correctness, just performance or possible nondeterministic "
"glitches. There may also be interactive or networking tests which may be "
@ -154,7 +192,7 @@ DefineEngineFunction( runAllUnitTests, int, (const char* testSpecs, const char*
Vector<char*> args;
args.push_back(NULL); // Program name is unused by googletest.
String specsArg;
if ( dStrlen( testSpecs ) > 0 )
if (dStrlen(testSpecs) > 0)
{
specsArg = testSpecs;
specsArg.replace(' ', ':');
@ -163,16 +201,16 @@ DefineEngineFunction( runAllUnitTests, int, (const char* testSpecs, const char*
}
String reportFormatArg;
if ( dStrlen(reportFormat) > 0 )
if (dStrlen(reportFormat) > 0)
{
reportFormatArg = String::ToString("--gtest_output=%s", reportFormat);
args.push_back(const_cast<char*>(reportFormatArg.c_str()));
}
S32 argc = args.size();
// Initialize Google Test.
testing::InitGoogleTest( &argc, args.address() );
testing::InitGoogleTest(&argc, args.address());
// Fetch the unit test instance.
testing::UnitTest& unitTest = *testing::UnitTest::GetInstance();
@ -180,22 +218,20 @@ DefineEngineFunction( runAllUnitTests, int, (const char* testSpecs, const char*
testing::TestEventListeners& listeners = unitTest.listeners();
// Release the default listener.
delete listeners.Release( listeners.default_result_printer() );
delete listeners.Release(listeners.default_result_printer());
if ( Con::getBoolVariable( "$Testing::CheckMemoryLeaks", false ) ) {
if (Con::getBoolVariable("$Testing::CheckMemoryLeaks", false)) {
// Add the memory leak tester.
listeners.Append( new testing::MemoryLeakDetector );
listeners.Append(new testing::MemoryLeakDetector);
}
// Add the Torque unit test listener.
listeners.Append( new TorqueUnitTestListener(false) );
listeners.Append(new TorqueUnitTestListener(true));
// Perform googletest run.
Con::printf( "\nUnit Tests Starting...\n" );
Con::printf("\nUnit Tests Starting...\n");
const S32 result = RUN_ALL_TESTS();
Con::printf( "... Unit Tests Ended.\n" );
Con::printf("... Unit Tests Ended.\n");
return result;
}
#endif // TORQUE_TESTS_ENABLED

View file

@ -23,9 +23,12 @@
#ifndef _UNIT_TESTING_H_
#define _UNIT_TESTING_H_
#ifdef TORQUE_TESTS_ENABLED
#if defined(SDL_MAIN_AVAILABLE)
#undef SDL_MAIN_AVAILABLE
#endif
#include <gtest/gtest.h>
#include <gmock/gmock.h>
/// Convenience to define a test fixture with a Fixture suffix for use with
/// TEST_FIX.
@ -38,6 +41,4 @@
GTEST_TEST_(test_fixture, test_name, test_fixture##Fixture, \
::testing::internal::GetTypeId<test_fixture##Fixture>())
#endif // TORQUE_TESTS_ENABLED
#endif // _UNIT_TESTING_H_

View file

@ -19,31 +19,73 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "unitTesting.h"
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "windowManager/platformWindow.h"
#include "windowManager/platformWindowMgr.h"
#include "platform/platformInput.h"
#include "platform/input/IProcessInput.h"
#include "windowManager/sdl/sdlWindowMgr.h"
#include "core/util/tVector.h"
// Mysteriously, TEST(WindowManager, BasicAPI) gives an error. Huh.
TEST(WinMgr, BasicAPI)
using ::testing::Matcher;
using ::testing::TypedEq;
class PlatformWindowManagerSDLTest : public ::testing::Test
{
PlatformWindowManager *pwm = CreatePlatformWindowManager();
EXPECT_TRUE(pwm)
<< "CreatePlatformWindowManager creation Failed!";
if (!pwm)
return;
protected:
PlatformWindowManagerSDLTest()
{
putenv("SDL_VIDEODRIVER=dummy");
putenv("SDL_AUDIODRIVER=dummy");
S32 monitorCount = PlatformWindowManager::get()->getMonitorCount();
EXPECT_GT(monitorCount, 0)
<< "no monitor to test against!";
if (monitorCount == 0)
return;
// for tests in this class we probably only need the init_video an nothing else.
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE);
}
void SetUp() override
{
}
};
TEST_F(PlatformWindowManagerSDLTest, Constructor)
{
PlatformWindowManagerSDL* pwm = static_cast<PlatformWindowManagerSDL*>(CreatePlatformWindowManager());
ASSERT_TRUE(pwm) << "no monitor to test against!";
}
TEST_F(PlatformWindowManagerSDLTest, PrimaryRectTest)
{
PlatformWindowManagerSDL* pwm = static_cast<PlatformWindowManagerSDL*>(CreatePlatformWindowManager());
// Check out the primary desktop area...
RectI primary = pwm->getPrimaryDesktopArea();
EXPECT_TRUE(primary.isValidRect())
<< "Got some sort of invalid rect from the window manager!";
}
TEST_F(PlatformWindowManagerSDLTest, MonitorRectsValid)
{
PlatformWindowManagerSDL* pwm = static_cast<PlatformWindowManagerSDL*>(CreatePlatformWindowManager());
// Now try to get info about all the monitors.
Vector<RectI> monitorRects;
pwm->getMonitorRegions(monitorRects);
// should override the function above to test this with multiple setups.
for (S32 i = 0; i < monitorRects.size(); i++)
{
EXPECT_TRUE(monitorRects[i].isValidRect())
<< "Got an invalid rect for this monitor - no good.";
}
}
TEST_F(PlatformWindowManagerSDLTest, MonitorRectsAtLeastOne)
{
PlatformWindowManagerSDL* pwm = static_cast<PlatformWindowManagerSDL*>(CreatePlatformWindowManager());
// Now try to get info about all the monitors.
Vector<RectI> monitorRects;
@ -51,18 +93,17 @@ TEST(WinMgr, BasicAPI)
EXPECT_GT(monitorRects.size(), 0)
<< "Should get at least one monitor rect back from getMonitorRegions!";
}
TEST_F(PlatformWindowManagerSDLTest, MonitorRectsOverflow)
{
PlatformWindowManagerSDL* pwm = static_cast<PlatformWindowManagerSDL*>(CreatePlatformWindowManager());
// Now try to get info about all the monitors.
Vector<RectI> monitorRects;
pwm->getMonitorRegions(monitorRects);
// This test is here just to detect overflow/runaway situations. -- BJG
EXPECT_LT(monitorRects.size(), 64)
<< "Either something's wrong, or you have a lot of monitors...";
for(S32 i=0; i<monitorRects.size(); i++)
{
EXPECT_TRUE(monitorRects[i].isValidRect())
<< "Got an invalid rect for this monitor - no good.";
}
// No way to destroy the window manager.
};
#endif
}