// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #include #include #include #include "pointerlist.h" class PointerListTest : public uUnit { public: PointerListTest() { uTEST(PointerListTest::test_zom_pointerlist_push); uTEST(PointerListTest::test_zom_pointerlist_from_args); uTEST(PointerListTest::test_zom_envmap_insert); uTEST(PointerListTest::test_zom_envmap_from_env); uTEST(PointerListTest::test_exceptional_env); } void test_zom_pointerlist_push() { using namespace std::string_literals; { // Zero PointerList args; uASSERT_EQUAL(0u, args.size()); auto [argc, argv] = args.get(); uASSERT_EQUAL(0, argc); uASSERT(nullptr != argv); uASSERT_EQUAL(nullptr, argv[0]); } { // One PointerList args; args.push_back("hello"); uASSERT_EQUAL(1u, args.size()); auto [argc, argv] = args.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello"s, std::string(argv[0])); } { // Many PointerList args; args.push_back("hello"); args.push_back("dear"); args.push_back("world"); uASSERT_EQUAL(3u, args.size()); auto [argc, argv] = args.get(); uASSERT_EQUAL(3, argc); uASSERT_EQUAL("hello"s, std::string(argv[0])); uASSERT_EQUAL("dear"s, std::string(argv[1])); uASSERT_EQUAL("world"s, std::string(argv[2])); } } void test_zom_pointerlist_from_args() { using namespace std::string_literals; { // Zero PointerList args(0, nullptr); uASSERT_EQUAL(0u, args.size()); auto [argc, argv] = args.get(); uASSERT_EQUAL(0, argc); uASSERT(nullptr != argv); uASSERT_EQUAL(nullptr, argv[0]); } { // One int _argc{1}; const char* _argv[] = { "hello" }; PointerList args(_argc, _argv); uASSERT_EQUAL(1u, args.size()); auto [argc, argv] = args.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello"s, std::string(argv[0])); } { // Many int _argc{3}; const char* _argv[] = { "hello", "dear", "world" }; PointerList args(_argc, _argv); uASSERT_EQUAL(3u, args.size()); auto [argc, argv] = args.get(); uASSERT_EQUAL(3, argc); // order must be preserved uASSERT_EQUAL("hello"s, std::string(argv[0])); uASSERT_EQUAL("dear"s, std::string(argv[1])); uASSERT_EQUAL("world"s, std::string(argv[2])); } } void test_zom_envmap_insert() { using namespace std::string_literals; { // Zero EnvMap env; uASSERT_EQUAL(0u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(0, argc); uASSERT(nullptr != argv); uASSERT_EQUAL(nullptr, argv[0]); auto str = env.stringify(); uASSERT_EQUAL(1u, str.size()); uASSERT_EQUAL('\0', str[0]); } { // One (key only) EnvMap env; env.insert("hello"); uASSERT_EQUAL(1u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello="s, std::string(argv[0])); uASSERT_EQUAL(""s, env["hello"]); } { // One (with value) EnvMap env; env.insert("hello=world"); uASSERT_EQUAL(1u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello=world"s, std::string(argv[0])); uASSERT_EQUAL("world"s, env["hello"]); uASSERT_EQUAL("hello=world\0\0"s, env.stringify()); } { // Overwrite one EnvMap env; env.insert("hello=world"); uASSERT_EQUAL(1u, env.size()); uASSERT_EQUAL("world"s, env["hello"s]); env.insert("hello=foo"); uASSERT_EQUAL(1u, env.size()); uASSERT_EQUAL("foo"s, env["hello"s]); } { // Many EnvMap env; env.insert("hello=world"); env.insert("world=leader"); env.insert("dear=boar"); uASSERT_EQUAL(3u, env.size()); uASSERT_EQUAL("boar"s, env["dear"s]); uASSERT_EQUAL("world"s, env["hello"s]); uASSERT_EQUAL("leader"s, env["world"s]); auto [argc, argv] = env.get(); uASSERT_EQUAL(3, argc); // store and sort to verify unordered std::vector vals{argv[0], argv[1], argv[2]}; std::ranges::sort(vals); uASSERT_EQUAL("dear=boar"s, vals[0]); uASSERT_EQUAL("hello=world"s, vals[1]); uASSERT_EQUAL("world=leader"s, vals[2]); // test all combinations since ordering is not a requirement // exactly one of the must be true (boolean XOR) auto str = env.stringify(); uASSERT(((((("dear=boar\0hello=world\0world=leader\0\0"s == str) != ("dear=boar\0world=leader\0hello=world\0\0"s == str)) != ("hello=world\0dear=boar\0world=leader\0\0"s == str)) != ("hello=world\0world=leader\0dear=boar\0\0"s == str)) != ("world=leader\0dear=boar\0hello=world\0\0"s == str)) != ("world=leader\0hello=world\0dear=boar\0\0"s == str)); } } void test_zom_envmap_from_env() { using namespace std::string_literals; { // Zero const char* penv = nullptr; EnvMap env(penv); uASSERT_EQUAL(0u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(0, argc); uASSERT(nullptr != argv); uASSERT_EQUAL(nullptr, argv[0]); } { // Zero const char** ppenv = nullptr; EnvMap env(ppenv); uASSERT_EQUAL(0u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(0, argc); uASSERT(nullptr != argv); uASSERT_EQUAL(nullptr, argv[0]); } { // One (key only) const char* ptr = "hello\0\0"; EnvMap env(ptr); uASSERT_EQUAL(1u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello="s, std::string(argv[0])); uASSERT_EQUAL(""s, env["hello"]); } { // One (key only) const char* ptr[] = {"hello", nullptr}; EnvMap env(ptr); uASSERT_EQUAL(1u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello="s, std::string(argv[0])); uASSERT_EQUAL(""s, env["hello"]); } { // One (with value) const char* ptr = "hello=world\0\0"; EnvMap env(ptr); uASSERT_EQUAL(1u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello=world"s, std::string(argv[0])); uASSERT_EQUAL("world"s, env["hello"]); uASSERT_EQUAL("hello=world\0\0"s, env.stringify()); } { // One (with value) const char* ptr[] = {"hello=world\0", nullptr}; EnvMap env(ptr); uASSERT_EQUAL(1u, env.size()); auto [argc, argv] = env.get(); uASSERT_EQUAL(1, argc); uASSERT_EQUAL("hello=world"s, std::string(argv[0])); uASSERT_EQUAL("world"s, env["hello"]); uASSERT_EQUAL("hello=world\0\0"s, env.stringify()); } { // Many const char* ptr = "hello=world\0world=leader\0dear=boar\0\0"; EnvMap env(ptr); uASSERT_EQUAL(3u, env.size()); uASSERT_EQUAL("boar"s, env["dear"s]); uASSERT_EQUAL("world"s, env["hello"s]); uASSERT_EQUAL("leader"s, env["world"s]); auto [argc, argv] = env.get(); uASSERT_EQUAL(3, argc); // store and sort to verify unordered std::vector vals{argv[0], argv[1], argv[2]}; std::ranges::sort(vals); uASSERT_EQUAL("dear=boar"s, vals[0]); uASSERT_EQUAL("hello=world"s, vals[1]); uASSERT_EQUAL("world=leader"s, vals[2]); // test all combinations since ordering is not a requirement // exactly one of the must be true (boolean XOR) auto str = env.stringify(); uASSERT(((((("dear=boar\0hello=world\0world=leader\0\0"s == str) != ("dear=boar\0world=leader\0hello=world\0\0"s == str)) != ("hello=world\0dear=boar\0world=leader\0\0"s == str)) != ("hello=world\0world=leader\0dear=boar\0\0"s == str)) != ("world=leader\0dear=boar\0hello=world\0\0"s == str)) != ("world=leader\0hello=world\0dear=boar\0\0"s == str)); } { // Many const char* ptr[] = {"hello=world\0", "world=leader\0", "dear=boar\0", nullptr}; EnvMap env(ptr); uASSERT_EQUAL(3u, env.size()); uASSERT_EQUAL("boar"s, env["dear"s]); uASSERT_EQUAL("world"s, env["hello"s]); uASSERT_EQUAL("leader"s, env["world"s]); auto [argc, argv] = env.get(); uASSERT_EQUAL(3, argc); // store and sort to verify unordered std::vector vals{argv[0], argv[1], argv[2]}; std::ranges::sort(vals); uASSERT_EQUAL("dear=boar"s, vals[0]); uASSERT_EQUAL("hello=world"s, vals[1]); uASSERT_EQUAL("world=leader"s, vals[2]); // test all combinations since ordering is not a requirement // exactly one of the must be true (boolean XOR) auto str = env.stringify(); uASSERT(((((("dear=boar\0hello=world\0world=leader\0\0"s == str) != ("dear=boar\0world=leader\0hello=world\0\0"s == str)) != ("hello=world\0dear=boar\0world=leader\0\0"s == str)) != ("hello=world\0world=leader\0dear=boar\0\0"s == str)) != ("world=leader\0dear=boar\0hello=world\0\0"s == str)) != ("world=leader\0hello=world\0dear=boar\0\0"s == str)); } } void test_exceptional_env() { using namespace std::string_literals; { // Zero EnvMap env; uASSERT_EQUAL(0u, env.size()); uASSERT_EQUAL(""s, env["foo"]); // lookup of non-existing key } } }; // Registers the fixture into the 'registry' static PointerListTest test;