From 93582b4ac0c5e04cd299e59b8570c49c9ad1d9ad Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 27 Jan 2016 02:17:06 +0100 Subject: [PATCH] added more tests, fixed some bugs --- .gitignore | 3 ++ application/commandlineutils.h | 4 +- io/inifile.cpp | 5 +- io/path.cpp | 37 ++++++++------- io/path.h | 2 +- misc/random.cpp | 5 +- testfiles/test.ini | 12 +++++ tests/iotests.cpp | 84 ++++++++++++++++++++++++++++++++++ 8 files changed, 129 insertions(+), 23 deletions(-) create mode 100644 testfiles/test.ini diff --git a/.gitignore b/.gitignore index c22aaeb..9a33e66 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ Makefile* # documentation /doc + +# tests +testfiles/output.* diff --git a/application/commandlineutils.h b/application/commandlineutils.h index e68adee..e83d19c 100644 --- a/application/commandlineutils.h +++ b/application/commandlineutils.h @@ -16,9 +16,9 @@ bool LIB_EXPORT confirmPrompt(const char *message, Response defaultResponse = Re #ifdef PLATFORM_WINDOWS void LIB_EXPORT startConsole(); -#define CMD_UTILS_START_CONSOLE ::ApplicationUtilities::startConsole(); +# define CMD_UTILS_START_CONSOLE ::ApplicationUtilities::startConsole(); #else -#define CMD_UTILS_START_CONSOLE +# define CMD_UTILS_START_CONSOLE #endif } // namespace ApplicationUtilities diff --git a/io/inifile.cpp b/io/inifile.cpp index 9ec9264..b5963b7 100644 --- a/io/inifile.cpp +++ b/io/inifile.cpp @@ -24,7 +24,10 @@ void IniFile::parse(std::istream &inputStream) value.reserve(256); // define actions for state machine // called when key/value pair is complete - const auto finishKeyValue = [&scope, &key, &value, &whitespace, this] { + const auto finishKeyValue = [&state, &scope, &key, &value, &whitespace, this] { + if(key.empty() && value.empty() && state != Value) { + return; + } if(m_data.empty() || m_data.back().first != scope) { m_data.emplace_back(make_pair(scope, decltype(m_data)::value_type::second_type())); } diff --git a/io/path.cpp b/io/path.cpp index def655a..0828814 100644 --- a/io/path.cpp +++ b/io/path.cpp @@ -25,13 +25,14 @@ #endif using namespace std; -using namespace IoUtilities; using namespace ConversionUtilities; +namespace IoUtilities { + /*! * \brief Returns the file name and extension of the specified \a path string. */ -string IoUtilities::fileName(const string &path) +string fileName(const string &path) { size_t lastSlash = path.rfind('/'); size_t lastBackSlash = path.rfind('\\'); @@ -48,19 +49,19 @@ string IoUtilities::fileName(const string &path) } /*! - * \brief Removes invalid characters from the specified \a path string. + * \brief Removes invalid characters from the specified \a fileName. * * The characters <, >, ?, !, *, |, /, :, \ and new lines are considered as invalid. */ -void IoUtilities::removeInvalidChars(string &path) +void removeInvalidChars(string &fileName) { size_t startPos = 0; static const char invalidPathChars[] = {'\"', '<', '>', '?', '!', '*', '|', '/', ':', '\\', '\n'}; for(const char *i = invalidPathChars, *end = invalidPathChars + sizeof(invalidPathChars); i != end; ++i) { - startPos = path.find(*i); + startPos = fileName.find(*i); while(startPos != string::npos) { - path.replace(startPos, 1, ""); - startPos = path.find(*i, startPos); + fileName.replace(startPos, 1, string()); + startPos = fileName.find(*i, startPos); } } } @@ -72,7 +73,7 @@ void IoUtilities::removeInvalidChars(string &path) * \param createApplicationDirectory Indicates wheter the application subdirectory should be created if not present. * \returns Returns if a settings directory could be located. */ -bool IoUtilities::settingsDirectory(string &result, string applicationDirectoryName, bool createApplicationDirectory) +bool settingsDirectory(string &result, string applicationDirectoryName, bool createApplicationDirectory) { result.clear(); fstream pathConfigFile("path.config", ios_base::in); @@ -92,12 +93,12 @@ bool IoUtilities::settingsDirectory(string &result, string applicationDirectoryN struct stat sb; return (stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)); #else -#ifdef PLATFORM_WINDOWS +# ifdef PLATFORM_WINDOWS DWORD ftyp = GetFileAttributesA(result.c_str()); return (ftyp != INVALID_FILE_ATTRIBUTES) && (ftyp & FILE_ATTRIBUTE_DIRECTORY); -#else -#error Platform not supported. -#endif +# else +# error Platform not supported. +# endif #endif } else { if(!applicationDirectoryName.empty()) { @@ -126,7 +127,7 @@ bool IoUtilities::settingsDirectory(string &result, string applicationDirectoryN } } #else -#ifdef PLATFORM_WINDOWS +# ifdef PLATFORM_WINDOWS if(char *appData = getenv("appdata")) { result = appData; if(!applicationDirectoryName.empty()) { @@ -149,10 +150,12 @@ bool IoUtilities::settingsDirectory(string &result, string applicationDirectoryN } else { return false; } - #else - #error Platform not supported. - #endif - #endif +# else +# error Platform not supported. +# endif +#endif } return true; } + +} diff --git a/io/path.h b/io/path.h index 3dbaacf..3f68c1c 100644 --- a/io/path.h +++ b/io/path.h @@ -11,7 +11,7 @@ namespace IoUtilities { LIB_EXPORT std::string fileName(const std::string &path); -LIB_EXPORT void removeInvalidChars(std::string &path); +LIB_EXPORT void removeInvalidChars(std::string &fileName); LIB_EXPORT bool settingsDirectory(std::string &result, std::string applicationDirectoryName = std::string(), bool createApplicationDirectory = false); } diff --git a/misc/random.cpp b/misc/random.cpp index 42a2db6..d0ca4e1 100644 --- a/misc/random.cpp +++ b/misc/random.cpp @@ -14,8 +14,7 @@ using namespace std; * \brief Contains miscellaneous utility functions. */ -namespace Utilities -{ +namespace RandomUtilities { //! @cond const char letters[28] = "qwertzuiopasdfghjklyxcvbnm"; @@ -26,6 +25,7 @@ const char symbols[24] = "!\"$%&/()=?'#*+~-_><.:,;"; /*! * \brief Generates a random character sequence using the given \a randomizer. + * \remarks Might be removed because not used anymore. */ void generateRandomCharacterSequence(char *result, unsigned int length, std::function randomizer, int highestRandomNumber, bool useSmallLetters, bool useCapitalLetters, bool useNumbers, bool useSymbols, bool useAtLeastOneOfEachCategory) { @@ -114,6 +114,7 @@ void generateRandomCharacterSequence(char *result, unsigned int length, std::fun /*! * \brief Generates a random character sequence using std::rand(). + * \remarks Might be removed because not used anymore. */ void generateRandomCharacterSequence(char *result, unsigned int length, bool useSmallLetters, bool useCapitalLetters, bool useNumbers, bool useSymbols, bool useAtLeastOneOfEachCategory) { diff --git a/testfiles/test.ini b/testfiles/test.ini new file mode 100644 index 0000000..f16b237 --- /dev/null +++ b/testfiles/test.ini @@ -0,0 +1,12 @@ +# file for testing INI parser +key0=value 0 + +[scope 1] +key1=value 1 # comment +key2=value=2 +key3=value 3 + +[scope 2] +key4=value 4 +#key5=value 5 +key6=value 6 diff --git a/tests/iotests.cpp b/tests/iotests.cpp index 9422b38..3fe8943 100644 --- a/tests/iotests.cpp +++ b/tests/iotests.cpp @@ -1,6 +1,9 @@ #include "../io/binaryreader.h" #include "../io/binarywriter.h" #include "../io/bitreader.h" +#include "../io/path.h" +#include "../io/inifile.h" +#include "../io/copy.h" #include #include @@ -24,6 +27,9 @@ class IoTests : public TestFixture CPPUNIT_TEST(testBinaryReader); CPPUNIT_TEST(testBinaryWriter); CPPUNIT_TEST(testBitReader); + CPPUNIT_TEST(testPathUtilities); + CPPUNIT_TEST(testIniFile); + CPPUNIT_TEST(testCopy); CPPUNIT_TEST_SUITE_END(); public: @@ -34,6 +40,9 @@ public: void testBinaryReader(); void testBinaryWriter(); void testBitReader(); + void testPathUtilities(); + void testIniFile(); + void testCopy(); }; CPPUNIT_TEST_SUITE_REGISTRATION(IoTests); @@ -185,3 +194,78 @@ void IoTests::testBitReader() CPPUNIT_ASSERT(reader.readBits(8) == 0x44); CPPUNIT_ASSERT_THROW(reader.readBit(), std::ios_base::failure); } + +/*! + * \brief Tests fileName() and removeInvalidChars(). + */ +void IoTests::testPathUtilities() +{ + CPPUNIT_ASSERT(fileName("/usr/lib/libc++utilities.so") == "libc++utilities.so"); + string invalidPath("lib/c++uti*lities.so?"); + removeInvalidChars(invalidPath); + CPPUNIT_ASSERT(invalidPath == "libc++utilities.so"); +} + +/*! + * \brief Tests IniFile. + */ +void IoTests::testIniFile() +{ + // prepare reading test file + fstream inputFile; + inputFile.exceptions(ios_base::failbit | ios_base::badbit); + inputFile.open(UnitTests::testFilesPath + "/test.ini", ios_base::in); + + IniFile ini; + ini.parse(inputFile); + const auto globalScope = ini.data().at(0); + const auto scope1 = ini.data().at(1); + const auto scope2 = ini.data().at(2); + CPPUNIT_ASSERT(globalScope.first.empty()); + CPPUNIT_ASSERT(globalScope.second.find("key0") != globalScope.second.cend()); + CPPUNIT_ASSERT(globalScope.second.find("key0")->second == "value 0"); + CPPUNIT_ASSERT(globalScope.second.find("key1") == globalScope.second.cend()); + CPPUNIT_ASSERT(scope1.first == "scope 1"); + CPPUNIT_ASSERT(scope1.second.find("key1") != scope1.second.cend()); + CPPUNIT_ASSERT(scope1.second.find("key1")->second == "value 1"); + CPPUNIT_ASSERT(scope1.second.find("key2") != scope1.second.cend()); + CPPUNIT_ASSERT(scope1.second.find("key2")->second == "value=2"); + CPPUNIT_ASSERT(scope2.first == "scope 2"); + CPPUNIT_ASSERT(scope2.second.find("key5") == scope2.second.cend()); + + // write values to another file + fstream outputFile; + outputFile.exceptions(ios_base::failbit | ios_base::badbit); + outputFile.open(UnitTests::testFilesPath + "/output.ini", ios_base::out | ios_base::trunc); + ini.make(outputFile); + + // parse written values (again) + outputFile.close(); + outputFile.open(UnitTests::testFilesPath + "/output.ini", ios_base::in); + IniFile ini2; + ini2.parse(outputFile); + CPPUNIT_ASSERT(ini.data() == ini2.data()); +} + +/*! + * \brief Tests CopyHelper. + */ +void IoTests::testCopy() +{ + // prepare streams + fstream testFile; + testFile.open(UnitTests::testFilesPath + "/some_data", ios_base::in | ios_base::binary); + testFile.exceptions(ios_base::failbit | ios_base::badbit); + stringstream outputStream(ios_base::in | ios_base::out | ios_base::binary); + outputStream.exceptions(ios_base::failbit | ios_base::badbit); + + // copy + CopyHelper<13> copyHelper; + copyHelper.copy(testFile, outputStream, 50); + + // test + testFile.seekg(0); + for(byte i = 0; i < 50; ++i) { + CPPUNIT_ASSERT(testFile.get() == outputStream.get()); + } +}