diff --git a/CMakeLists.txt b/CMakeLists.txt index aca73f4..5008145 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set( PROJECT_CODE_DIR ${PROJECT_SOURCE_DIR}/src ) set( PROJECT_HEADER_DIR ${PROJECT_SOURCE_DIR}/src ) set( PROJECT_DEP_DIR ${PROJECT_SOURCE_DIR}/dependencies) -set( PROJECT_TEST_DIR ${PROJECT_SOURCE_DIR}/test ) +set( PROJECT_TEST_DIR ${PROJECT_SOURCE_DIR}/tests ) # Find required libraries #> For Lua mod support @@ -101,6 +101,14 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") #TODO handle extra platforms/errors endif() +#Add unit tests directory +#>Enable testing globally. Individual tests may be found in the tests dir as set below +ENABLE_TESTING() + +ADD_SUBDIRECTORY( ${PROJECT_TEST_DIR} ) + +Message("-- See ${PROJECT_BINARY_DIR}/Testing/Temporary/LastTest.log for details on tests.") + # Collect source file paths into a var for later building file(GLOB_RECURSE PROJECT_SOURCES "${PROJECT_CODE_DIR}/*.cpp") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..ea33b6f --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +#pull in the project's headers +include_directories( ${PROJECT_HEADER_DIR} ) + +#add ConfigStore unit test +ADD_EXECUTABLE( test_ConfigStore test_ConfigStore.cpp ) +target_link_libraries( test_ConfigStore ModdingFramework) +ADD_TEST( ConfigStore test_ConfigStore ) + +#add ConfigLoader INI +ADD_EXECUTABLE( test_ConfigLoaderINI test_ConfigLoaderINI.cpp ) +target_link_libraries( test_ConfigLoaderINI ModdingFramework) +ADD_TEST( ConfigLoaderINI test_ConfigLoaderINI ) diff --git a/tests/TestBase.h b/tests/TestBase.h new file mode 100644 index 0000000..4ad4ff8 --- /dev/null +++ b/tests/TestBase.h @@ -0,0 +1,79 @@ +//copied and modified from https://github.com/Submanifold/Aleph 's test setup (MIT) + +#ifndef UNIT_TEST_BASE_H__ +#define UNIT_TEST_BASE_H__ + + +#include +#include +#include + +namespace UnitTests +{ + +#define ASSERT_EQUAL( x, y ) \ +{ \ + if( ( x ) != ( y ) ) \ + { \ + throw std::runtime_error( std::string( __FILE__ ) \ + + std::string( ":" ) \ + + std::to_string( __LINE__ ) \ + + std::string( " in " ) \ + + std::string( __PRETTY_FUNCTION__ ) \ + + std::string( ": " ) \ + + std::to_string( ( x ) ) \ + + std::string( " != " ) \ + + std::to_string( ( y ) ) \ + ); \ + } \ +} + + +#define ASSERT_THROW( condition ) \ +{ \ + if( !( condition ) ) \ + { \ + throw std::runtime_error( std::string( "Assert Failed: " ) \ + + std::string( __FILE__ ) \ + + std::string( ":" ) \ + + std::to_string( __LINE__ ) \ + + std::string( " in " ) \ + + std::string( __PRETTY_FUNCTION__ ) \ + ); \ + } \ +} + +#define EXPECT_EXCEPTION( expression, exception ) \ +{ \ + try \ + { \ + ( expression ); \ + } \ + catch( exception& e ) \ + { \ + } \ + catch( ... ) \ + { \ + throw std::runtime_error( std::string( __FILE__ ) \ + + std::string( ":" ) \ + + std::to_string( __LINE__ ) \ + + std::string( " in " ) \ + + std::string( __PRETTY_FUNCTION__ ) \ + ); \ + } \ +} + +#define TEST_BEGIN( name )\ +{\ + std::cerr << "-- Running test \"" << name << "\"...";\ +} + +#define TEST_END() \ +{\ + std::cerr << "finished\n";\ +} + + +} + +#endif diff --git a/tests/test_ConfigLoaderINI.cpp b/tests/test_ConfigLoaderINI.cpp new file mode 100755 index 0000000..ce7393b --- /dev/null +++ b/tests/test_ConfigLoaderINI.cpp @@ -0,0 +1,109 @@ + + +#include "TestBase.h" +#include "Configuration/ConfigLoaderINI.h" +#include "Configuration/FileOperations.h" + +#include +#include + +void addFile(std::string path, std::string contents) { + writeToTextFile(path, contents, 't'); +} + +int main (int argc, char* argv[]) { + + /*TEST_BEGIN( "test1" ); + ASSERT_EQUAL( 0, 0 ); + ASSERT_THROW( 0 == 0 ); + EXPECT_EXCEPTION( fakeFileLoad("does_not_exist.txt"), FileNotFound ); + TEST_END();*/ + + ConfigLoaderINI test_loader; + + //TEST_BEGIN( "Testing Validate Function: Success case" ); + //TODO need to implement validate function ASSERT_THROW(test_loader.validate("test2.ini") == true); + //TEST_END(); + + //TEST_BEGIN( "Testing Validate Function: Failure cases" ); + //TODO need to implement validate function ASSERT_THROW(test_loader.validate("DoesNotExist.ini") == false); + //TODO need to implement validate function ASSERT_THROW(test_loader.validate("test0.txt") == false); + //TODO need to implement validate function ASSERT_THROW(test_loader.validate("test1.txt") == false); + //TEST_END(); + + //values used in the test files + std::string id_testval = "112F24R433"; + std::string test_testval = "6"; + std::string test2_testval = "1+1=2"; + + + //invalid ext + std::shared_ptr store; + TEST_BEGIN( "Testing Parse Function Test 0: bad ext" ); + addFile("test0.txt", "id=112F24R433\n[mod]\ntest=6"); + store = test_loader.parse("test0.txt"); + + ASSERT_THROW( store->isPopulated() == false ); + TEST_END(); + + + //invalid format + TEST_BEGIN( "Testing Parse Function Test 1: bad format" ); + addFile("test1-1.ini", "id112F24R433\n[mod\ntest6"); + addFile("test1-2.ini", "id=id112F24R433\n[mod\ntest6"); + + store = test_loader.parse("test1-1.ini"); + ASSERT_THROW( store->isPopulated() == false ); + + store = test_loader.parse("test1-2.ini"); + ASSERT_THROW( store->isPopulated() == false ); + TEST_END(); + + + //valid format 1: keys, no sections, blank line, '=' in value + TEST_BEGIN( "Testing Parse Function Test 2: valid format 1; no sections, key/val pairs, '=' in val" ); + addFile("test2.ini", "id=112F24R433\n \ntest=6\ntest2=1+1=2"); + store = test_loader.parse("test2.ini"); + + + std::cout << store->isPopulated() << std::endl; + ASSERT_THROW( store->isPopulated() == true ); + std::cout << store->getStr("id") << std::endl; + ASSERT_THROW( store->getStr("id") == id_testval ); + std::cout << store->getStr("test") << std::endl; + ASSERT_THROW( store->getStr("test") == test_testval ); + std::cout << store->getStr("test2") << std::endl; + ASSERT_THROW( store->getStr("test2") == test2_testval ); + TEST_END(); + + //valid format 2: keys, section, comment + TEST_BEGIN( "Testing Parse Function Test 3: valid format, key/val, sections, comment" ); + addFile("test3.ini", "id=112F24R433\n[mod]\n;a comment\ntest=6"); + store = test_loader.parse("test3.ini"); + + ASSERT_THROW( store->isPopulated() == true ); + ASSERT_THROW( store->getStr("id") == id_testval ); + ASSERT_THROW( store->getNested("mod")->getStr("test") == test_testval ); + TEST_END(); + + TEST_BEGIN( "Testing Parse Function: Test 4" ); + addFile("test4.ini", "[intro]\nid=112F24R433\n[mod]\ntest=6"); //valid format 3: everything belongs in sections + store = test_loader.parse("test4.ini"); + + ASSERT_THROW( store->isPopulated() == true ); + ASSERT_THROW( store->getNested("intro")->getStr("id") == id_testval ); + ASSERT_THROW( store->getNested("mod")->getStr("test") == test_testval ); + TEST_END(); + + + + TEST_BEGIN( "Testing Serialize Function: Normal case" ); + + TEST_END(); + + TEST_BEGIN( "Testing Serialize Function: 3+levels Case" ); + test_loader.parse("test4"); + TEST_END(); + + return 0; +} diff --git a/tests/test_ConfigStore.cpp b/tests/test_ConfigStore.cpp new file mode 100755 index 0000000..5bfa025 --- /dev/null +++ b/tests/test_ConfigStore.cpp @@ -0,0 +1,63 @@ + + +#include "TestBase.h" +#include "Configuration/ConfigStore.h" + +#include + + +int main (int argc, char* argv[]) { + + //TEST_BEGIN( "test1" ); + //ASSERT_EQUAL( 0, 0 ); + //ASSERT_THROW( 0 == 0 ); + //EXPECT_EXCEPTION( fakeFileLoad("does_not_exist.txt"), FileNotFound ); + //TEST_END(); + + std::shared_ptr store1 = std::make_shared(), + store2 = std::make_shared(), + store3 = std::make_shared(); + + TEST_BEGIN( "isPopulated: Test ConfigStore is false" ); + ASSERT_THROW( store1->isPopulated() == false ); + TEST_END(); + + TEST_BEGIN( "getStr: Test getStr of invalid key" ); + ASSERT_THROW( store1->getStr("invalid key") == "" ); + TEST_END(); + + TEST_BEGIN( "getNested: Test getNested of invalid key" ); + ASSERT_THROW( store1->getNested("invalid key") == nullptr ); + TEST_END(); + + TEST_BEGIN( "set and getStr: Set and Get valid strings" ); + store1->set("data1", "str data"); + store3->set("data3", "str data3"); + ASSERT_THROW( store1->getStr("data1") == "str data"); + ASSERT_THROW( store3->getStr("data3") == "str data3"); + TEST_END(); + + TEST_BEGIN( "set and getNested: Set and Get valid ConfigStore" ); + store1->set("nest2", store2); + store2->set("nest3", store3); + ASSERT_THROW( store1->getNested("nest2") == store2); + ASSERT_THROW( store1->getNested("nest2")->getNested("nest3") == store3); + TEST_END(); + + TEST_BEGIN( "isPopulated: Test ConfigStore with only string is true" ); + ASSERT_THROW( store3->isPopulated() == true ); + TEST_END(); + + TEST_BEGIN( "isPopulated: Test ConfigStore with only nested ConfigStore is true" ); + ASSERT_THROW( store2->isPopulated() == true ); + TEST_END(); + + TEST_BEGIN( "isPopulated: Test ConfigStore with nested and string ConfigStore is true" ); + ASSERT_THROW( store1->isPopulated() == true ); + TEST_END(); + + //TODO need to test iterators + + + return 0; +}