commit 0dfc1d32da3d539129533341c4a2eb45a3848b78
parent 42b158159fc1188afc6b1afecf30ac0184fb0c52
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sat, 29 Jun 2024 12:32:41 +0200
Add test suite, bug fixing
Diffstat:
5 files changed, 130 insertions(+), 24 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
poafloc
- VERSION 1.0.1
+ VERSION 1.0.2
DESCRIPTION "Parser Of Arguments For Lines Of Commands"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/poafloc.git"
LANGUAGES C CXX
diff --git a/source/poafloc.cpp b/source/poafloc.cpp
@@ -103,7 +103,7 @@ Parser::Parser(const arg_t* argp, unsigned flags, void* input)
else
{
// duplicate key, silently ignoring
- if (!m_options.contains(opt.key)) continue;
+ if (m_options.contains(opt.key)) continue;
if (opt.name != nullptr) m_trie.insert(opt.name, opt.key);
m_options[key_last = opt.key] = &opt;
@@ -204,26 +204,33 @@ int Parser::parse(std::size_t argc, char* argv[])
const auto* option = m_options[key];
bool const is_opt = (option->flags & ARG_OPTIONAL) != 0;
+
if (option->arg == nullptr)
{
m_argp->parse(key, nullptr, this);
+ continue;
}
+
if (opt[j + 1] != 0)
{
m_argp->parse(key, opt.substr(j + 1).c_str(), this);
break;
}
- if (is_opt) m_argp->parse(key, nullptr, this);
- else if (idx + 1 != argc)
+
+ if (is_opt)
{
- m_argp->parse(key, args[++idx], this);
- break;
+ m_argp->parse(key, nullptr, this);
+ continue;
}
- else
+
+ if (idx + 1 != argc)
{
- err_code = handle_missing(true, args[idx]);
- goto error;
+ m_argp->parse(key, args[++idx], this);
+ break;
}
+
+ err_code = handle_missing(true, args[idx]);
+ goto error;
}
}
else
@@ -320,6 +327,7 @@ int Parser::parse(std::size_t argc, char* argv[])
return 0;
error:
+ m_argp->parse(Key::ERROR, nullptr, this);
return err_code;
}
@@ -329,7 +337,7 @@ int Parser::handle_unknown(bool shrt, const char* argv)
return m_argp->parse(Key::ERROR, nullptr, this);
static const char* const unknown_fmt[2] = {
- "unrem_argpized option '-%s'\n",
+ "unrecognized option '-%s'\n",
"invalid option -- '%s'\n",
};
diff --git a/source/trie.cpp b/source/trie.cpp
@@ -9,10 +9,7 @@ bool Parser::trie_t::insert(const std::string& option, int key)
{
trie_t* crnt = this;
- if (!is_valid(option))
- {
- return false;
- }
+ if (!is_valid(option)) return false;
for (const char chr : option)
{
@@ -36,10 +33,7 @@ int Parser::trie_t::get(const std::string& option) const
{
const trie_t* crnt = this;
- if (!is_valid(option))
- {
- return 0;
- }
+ if (!is_valid(option)) return 0;
for (const char chr : option)
{
@@ -49,10 +43,7 @@ int Parser::trie_t::get(const std::string& option) const
crnt = crnt->m_children.at(idx).get();
}
- if (!crnt->m_terminal && crnt->m_count > 1)
- {
- return 0;
- }
+ if (!crnt->m_terminal && crnt->m_count > 1) return 0;
return crnt->m_key;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
@@ -18,7 +18,56 @@ add_executable(poafloc_test source/poafloc_test.cpp)
target_link_libraries(poafloc_test PRIVATE poafloc::poafloc)
target_compile_features(poafloc_test PRIVATE cxx_std_20)
-add_test(NAME poafloc_test COMMAND poafloc_test)
+add_test(NAME poafloc_test_empty COMMAND poafloc_test)
+set_tests_properties(poafloc_test_empty PROPERTIES PASS_REGULAR_EXPRESSION "init\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_arg_one COMMAND poafloc_test a1)
+set_tests_properties(poafloc_test_arg_one PROPERTIES PASS_REGULAR_EXPRESSION "init\narg:a1\nend\nsuccess")
+
+add_test(NAME poafloc_test_arg_two COMMAND poafloc_test a1 a2)
+set_tests_properties(poafloc_test_arg_two PROPERTIES PASS_REGULAR_EXPRESSION "init\narg:a1\narg:a2\nend\nsuccess")
+
+add_test(NAME poafloc_test_short COMMAND poafloc_test -s)
+set_tests_properties(poafloc_test_short PROPERTIES PASS_REGULAR_EXPRESSION "init\ns\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_long COMMAND poafloc_test --long)
+set_tests_properties(poafloc_test_long PROPERTIES PASS_REGULAR_EXPRESSION "init\nl\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_short_arg COMMAND poafloc_test -a a1)
+set_tests_properties(poafloc_test_short_arg PROPERTIES PASS_REGULAR_EXPRESSION "init\na:a1\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_long_arg COMMAND poafloc_test --arg a1)
+set_tests_properties(poafloc_test_long_arg PROPERTIES PASS_REGULAR_EXPRESSION "init\na:a1\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_short_arg_equal COMMAND poafloc_test -aa1)
+set_tests_properties(poafloc_test_short_arg_equal PROPERTIES PASS_REGULAR_EXPRESSION "init\na:a1\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_long_arg_equal COMMAND poafloc_test --arg=a1)
+set_tests_properties(poafloc_test_long_arg_equal PROPERTIES PASS_REGULAR_EXPRESSION "init\na:a1\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_short_arg_without COMMAND poafloc_test -a)
+set_tests_properties(poafloc_test_short_arg_without PROPERTIES WILL_FAIL TRUE)
+
+add_test(NAME poafloc_test_long_arg_without COMMAND poafloc_test --arg)
+set_tests_properties(poafloc_test_long_arg_without PROPERTIES WILL_FAIL TRUE)
+
+add_test(NAME poafloc_test_short_opt COMMAND poafloc_test -oa1)
+set_tests_properties(poafloc_test_short_opt PROPERTIES PASS_REGULAR_EXPRESSION "init\no:a1\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_long_opt COMMAND poafloc_test --opt=a1)
+set_tests_properties(poafloc_test_long_opt PROPERTIES PASS_REGULAR_EXPRESSION "init\no:a1\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_short_opt_without COMMAND poafloc_test -o)
+set_tests_properties(poafloc_test_short_opt_without PROPERTIES PASS_REGULAR_EXPRESSION "init\no:default\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_long_opt_without COMMAND poafloc_test --opt)
+set_tests_properties(poafloc_test_long_opt_without PROPERTIES PASS_REGULAR_EXPRESSION "init\no:default\nnoargs\nend\nsuccess")
+
+add_test(NAME poafloc_test_short_opt_after COMMAND poafloc_test -o a1)
+set_tests_properties(poafloc_test_short_opt_after PROPERTIES PASS_REGULAR_EXPRESSION "init\no:default\narg:a1\nend\nsuccess")
+
+add_test(NAME poafloc_test_long_opt_after COMMAND poafloc_test --opt a1)
+set_tests_properties(poafloc_test_long_opt_after PROPERTIES PASS_REGULAR_EXPRESSION "init\no:default\narg:a1\nend\nsuccess")
# ---- End-of-file commands ----
diff --git a/test/source/poafloc_test.cpp b/test/source/poafloc_test.cpp
@@ -1,8 +1,66 @@
+#include <iostream>
#include <string>
#include "poafloc/poafloc.hpp"
-int main()
+using namespace poafloc; // NOLINT
+ //
+int parse_opt(int key, const char* arg, Parser* parser)
{
+ std::ignore = parser;
+
+ switch (key)
+ {
+ case 's':
+ std::cout << 's' << std::endl;
+ break;
+ case 'l':
+ std::cout << 'l' << std::endl;
+ break;
+ case 'a':
+ std::cout << "a:" << arg << std::endl;
+ break;
+ case 'o':
+ std::cout << "o:" << (arg != nullptr ? arg : "default") << std::endl;
+ break;
+ case ARG:
+ std::cout << "arg:" << arg << std::endl;
+ break;
+ case INIT:
+ std::cout << "init" << std::endl;
+ break;
+ case END:
+ std::cout << "end" << std::endl;
+ break;
+ case SUCCESS:
+ std::cout << "success" << std::endl;
+ break;
+ case ERROR:
+ std::cout << "error" << std::endl;
+ break;
+ case NO_ARGS:
+ std::cout << "noargs" << std::endl;
+ break;
+ default:
+ break;
+ }
+
return 0;
}
+
+// clang-format off
+static const option_t options[] = {
+ {nullptr, 's', nullptr, 0, ""},
+ { "long", 'l', nullptr, 0, ""},
+ { "arg", 'a', "arg", 0, ""},
+ { "opt", 'o', "arg", ARG_OPTIONAL, ""},
+ {},
+};
+// clang-format on
+
+static const arg_t argp = {options, parse_opt, "", ""};
+
+int main(int argc, char* argv[])
+{
+ return parse(&argp, argc, argv, 0, nullptr);
+}