#include #include #include #include #include #include "lest.hpp" #include "mini/ini.h" using T_LineData = std::vector; using T_INIFileData = std::pair; // // helper functions // bool writeTestFile(T_INIFileData const& testData) { std::string const& filename = testData.first; T_LineData const& lines = testData.second; std::ofstream fileWriteStream(filename); if (fileWriteStream.is_open()) { if (lines.size()) { auto it = lines.begin(); for (;;) { fileWriteStream << *it; if (++it == lines.end()) { break; } fileWriteStream << std::endl; } } return true; } return false; } void outputData(mINI::INIStructure const& ini) { for (auto const& it : ini) { auto const& section = it.first; auto const& collection = it.second; std::cout << "[" << section << "]" << std::endl; for (auto const& it2 : collection) { auto const& key = it2.first; auto const& value = it2.second; std::cout << key << "=" << value << std::endl; } std::cout << std::endl; } } // // test data // const T_INIFileData testDataBasic = { // filename "data01.ini", // test data { "[fruit]", "bananas=1", "apples=2", "grapes=3", "[veggies]", "lettuce=scarce", "onions=sufficient", "potatoes=plentiful", "[section with spaces]", "key with spaces = value with spaces" } }; const T_INIFileData testDataWellFormed = { // filename "data02.ini", // test data { "; this is a comment", "[first section]", "someKey = 1", "anotherKey = 2", "", "; this is another comment", "[second section]", "humans = 16", "orcs = 8", "barbarians = 20", "", "; this is yet another comment", "[third section]", "spiders=25", "bugs=0", "ants=100", "flies=5" } }; const T_INIFileData testDataNotWellFormed = { // filename "data03.ini", // test data { "GARBAGE", "; this is a comment", " ; abcd ", "[first section] ;test comment", "someKey= 1", "GARBAGE", "anotherKey =2", "", "; this is another comment", "GARBAGE", "GARBAGE", " [second section]", "GARBAGE", "hUmAnS=16", "GARBAGE", " orcs = 8 ", " barbarians = 20 ", "", " GARBAGE", "; this is yet another comment", "[ third section ] ;;; test comment[]]] ", "spiders = 25", "bugs =0 ", "ants= 100", "GARBAGE ", "GARBAGE ", "FLIES = 5", "GARBAGE " } }; const T_INIFileData testDataEmpty = { // filename "data04.ini", // test data {} }; const T_INIFileData testDataEdgeCase1 = { // filename "data05.ini", // test data { "ignored1=value1", "ignored2=value2" } }; const T_INIFileData testDataEdgeCase2 = { // filename "data06.ini", // test data { "ignored1=value1", "ignored2=value2", "[data]", "proper1=a", "proper2=b" } }; const T_INIFileData testDataEdgeCase3 = { // filename "data07.ini", // test data { "[empty]" } }; const T_INIFileData testDataEdgeCase4 = { // filename "data08.ini", // test data { "[empty1]", "[empty2]", "[empty3]", "[empty4]", "[empty5]" } }; const T_INIFileData testDataEdgeCase5 = { // filename "data09.ini", // test data { "[data]", "valueA=1", // expected: ignored "valueA=2" // expected: not ignored } }; const T_INIFileData testDataEdgeCase6 = { // filename "data10.ini", // test data { "[data]", // expected: ignored "valueA=10", // expected: ignored "valueB=20", // expected: not ignored "[data]", "valueA=30" // expected: not ignored } }; const T_INIFileData testDataEdgeCase7 = { // filename "data11.ini", // test data { "[]", "key1=value1", "[a]", "key2=value2" } }; const T_INIFileData testDataEdgeCase8 = { // filename "data12.ini", // test data { "[a]", "=1" } }; const T_INIFileData testDataMalformed1 = { // filename "data13.ini", // test data { "[[name1]", "key=value", "[name2]]", "key=value", "[[name3]]", "key=value" } }; const T_INIFileData testDataMalformed2 = { // filename "data14.ini", // test data { "[name]", "key\\==value", "\\===", // expected key: "=" expected value: "=" "a\\= \\===b", // expected key: "a= =" expected value: "=b" " c\\= \\= = =d " // expected key: "c= =" expected value: "=d" } }; // // test cases // const lest::test mINI_tests[] = { CASE("Test: Basic read") { // read a basic INI file and check if values are read correctly auto const& filename = testDataBasic.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); std::cout << filename << std::endl; outputData(ini); EXPECT(ini["fruit"]["bananas"] == "1"); EXPECT(ini["fruit"]["apples"] == "2"); EXPECT(ini["fruit"]["grapes"] == "3"); EXPECT(ini["veggies"]["lettuce"] == "scarce"); EXPECT(ini["veggies"]["onions"] == "sufficient"); EXPECT(ini["veggies"]["potatoes"] == "plentiful"); EXPECT(ini["section with spaces"]["key with spaces"] == "value with spaces"); }, CASE("Test: Read and compare") { // read two INI files with differing form and check if all read values match auto const& filename1 = testDataWellFormed.first; auto const& filename2 = testDataNotWellFormed.first; mINI::INIFile file1(filename1); mINI::INIFile file2(filename2); mINI::INIStructure ini1, ini2; EXPECT(file1.read(ini1) == true); EXPECT(file2.read(ini2) == true); std::cout << filename1 << std::endl; outputData(ini1); std::cout << filename2 << std::endl; outputData(ini2); // compare sizes EXPECT(ini1.size() == ini2.size()); EXPECT(ini1.get("first section").size() == ini2.get("first section").size()); EXPECT(ini1.get("second section").size() == ini2.get("second section").size()); EXPECT(ini1.get("third section").size() == ini2.get("third section").size()); // compare data EXPECT(ini1.get("first section").get("somekey") == ini2.get("first section").get("somekey")); EXPECT(ini1["first section"]["anotherkey"] == ini2["first section"]["anotherkey"]); EXPECT(ini1["second section"]["humans"] == ini2["second section"]["humans"]); EXPECT(ini1["second section"]["orcs"] == ini2["second section"]["orcs"]); EXPECT(ini1["second section"]["barbarians"] == ini2["second section"]["barbarians"]); EXPECT(ini1["third section"]["spiders"] == ini2["third section"]["spiders"]); EXPECT(ini1["third section"]["bugs"] == ini2["third section"]["bugs"]); EXPECT(ini1["third section"]["ants"] == ini2["third section"]["ants"]); EXPECT(ini1["third section"]["flies"] == ini2["third section"]["flies"]); }, CASE("Test: Read empty") { auto const& filename = testDataEmpty.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 0u); }, CASE("Test: Edge case 1") { auto const& filename = testDataEdgeCase1.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 0u); }, CASE("Test: Edge case 2") { auto const& filename = testDataEdgeCase2.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 1u); EXPECT(ini.get("data").size() == 2u); EXPECT(ini["data"]["proper1"] == "a"); EXPECT(ini["data"]["proper2"] == "b"); }, CASE("Test: Edge case 3") { auto const& filename = testDataEdgeCase3.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 1u); EXPECT(ini.get("empty").size() == 0u); }, CASE("Test: Edge case 4") { auto const& filename = testDataEdgeCase4.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 5u); EXPECT(ini.get("empty1").size() == 0u); EXPECT(ini.get("empty2").size() == 0u); EXPECT(ini.get("empty3").size() == 0u); EXPECT(ini.get("empty4").size() == 0u); EXPECT(ini.get("empty5").size() == 0u); }, CASE("Test: Edge case 5") { auto const& filename = testDataEdgeCase5.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 1u); EXPECT(ini.get("data").size() == 1u); EXPECT(ini["data"]["valueA"] == "2"); }, CASE("Test: Edge case 6") { auto const& filename = testDataEdgeCase6.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 1u); EXPECT(ini.get("data").size() == 2u); EXPECT(ini["data"]["valueA"] == "30"); EXPECT(ini["data"]["valueB"] == "20"); }, CASE("Test: Edge case 7") { auto const& filename = testDataEdgeCase7.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 2u); EXPECT(ini.get("").size() == 1u); EXPECT(ini.get("").get("key1") == "value1"); EXPECT(ini.get("a").size() == 1u); EXPECT(ini["a"]["key2"] == "value2"); }, CASE("Test: Edge case 8") { auto const& filename = testDataEdgeCase8.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 1u); EXPECT(ini.get("a").size() == 1u); EXPECT(ini["a"][""] == "1"); }, CASE("Test: Malformed case 1") { // read INI with malformed section names auto const& filename = testDataMalformed1.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.size() == 3u); EXPECT(ini.get("[name1").size() == 1u); EXPECT(ini.get("name2]").size() == 1u); EXPECT(ini.get("[name3]").size() == 1u); }, CASE("Test: Malformed case 2") { // read INI with malformed key names auto const& filename = testDataMalformed2.first; mINI::INIFile file(filename); mINI::INIStructure ini; EXPECT(file.read(ini) == true); EXPECT(ini.get("name").get("key=") == "value"); EXPECT(ini.get("name").get("=") == "="); EXPECT(ini.get("name").get("a= =") == "=b"); EXPECT(ini.get("name").get("c= =") == "=d"); } }; int main(int argc, char** argv) { // write test files writeTestFile(testDataBasic); writeTestFile(testDataWellFormed); writeTestFile(testDataNotWellFormed); writeTestFile(testDataEmpty); writeTestFile(testDataEdgeCase1); writeTestFile(testDataEdgeCase2); writeTestFile(testDataEdgeCase3); writeTestFile(testDataEdgeCase4); writeTestFile(testDataEdgeCase5); writeTestFile(testDataEdgeCase6); writeTestFile(testDataEdgeCase7); writeTestFile(testDataEdgeCase8); writeTestFile(testDataMalformed1); writeTestFile(testDataMalformed2); // run tests if (int failures = lest::run(mINI_tests, argc, argv)) { return failures; } return std::cout << std::endl << "All tests passed!" << std::endl, EXIT_SUCCESS; }