cxxopts/test/options.cpp
Mario Badr e005d07656 Use cmake interface library
Fixes #33.

This PR uses cmake's interface library feature:

  An INTERFACE library target does not directly create build output,
  though it may have properties set on it and it may be installed,
  exported and imported.

This makes it easier to include the header only library in a cmake
project. After using add_subdirectory on the cxxopts directory, one
simply needs to include cxxopts in their target_link_libraries, which
will allow the user's target to inherit the properties of the cxxopts
header library (see changes to example and test).
2016-12-03 07:50:14 +11:00

156 lines
3.4 KiB
C++

#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <initializer_list>
#include "cxxopts.hpp"
class Argv {
public:
Argv(std::initializer_list<const char*> argv)
: m_argv(new char*[argv.size()])
, m_argc(argv.size())
{
int i = 0;
auto iter = argv.begin();
while (iter != argv.end()) {
auto len = strlen(*iter) + 1;
auto ptr = std::unique_ptr<char[]>(new char[len]);
strcpy(ptr.get(), *iter);
m_args.push_back(std::move(ptr));
m_argv.get()[i] = m_args.back().get();
++iter;
++i;
}
}
char** argv() const {
return m_argv.get();
}
int argc() const {
return m_argc;
}
private:
std::vector<std::unique_ptr<char[]>> m_args;
std::unique_ptr<char*[]> m_argv;
int m_argc;
};
TEST_CASE("Basic options", "[options]")
{
cxxopts::Options options("tester", " - test basic options");
options.add_options()
("long", "a long option")
("s,short", "a short option")
("value", "an option with a value", cxxopts::value<std::string>())
("a,av", "a short option with a value", cxxopts::value<std::string>())
("6,six", "a short number option")
;
Argv argv({
"tester",
"--long",
"-s",
"--value",
"value",
"-a",
"b",
"-6"
});
char** actual_argv = argv.argv();
auto argc = argv.argc();
options.parse(argc, actual_argv);
CHECK(options.count("long") == 1);
CHECK(options.count("s") == 1);
CHECK(options.count("value") == 1);
CHECK(options.count("a") == 1);
CHECK(options["value"].as<std::string>() == "value");
CHECK(options["a"].as<std::string>() == "b");
CHECK(options.count("6") == 1);
}
TEST_CASE("No positional", "[positional]")
{
cxxopts::Options options("test_no_positional",
" - test no positional options");
Argv av({"tester", "a", "b", "def"});
char** argv = av.argv();
auto argc = av.argc();
options.parse(argc, argv);
REQUIRE(argc == 4);
CHECK(strcmp(argv[1], "a") == 0);
}
TEST_CASE("All positional", "[positional]")
{
std::vector<std::string> positional;
cxxopts::Options options("test_all_positional", " - test all positional");
options.add_options()
("positional", "Positional parameters",
cxxopts::value<std::vector<std::string>>(positional))
;
Argv av({"tester", "a", "b", "c"});
auto argc = av.argc();
auto argv = av.argv();
options.parse_positional("positional");
options.parse(argc, argv);
REQUIRE(argc == 1);
REQUIRE(positional.size() == 3);
CHECK(positional[0] == "a");
CHECK(positional[1] == "b");
CHECK(positional[2] == "c");
}
TEST_CASE("Some positional explicit", "[positional]")
{
cxxopts::Options options("positional_explicit", " - test positional");
options.add_options()
("input", "Input file", cxxopts::value<std::string>())
("output", "Output file", cxxopts::value<std::string>())
("positional", "Positional parameters",
cxxopts::value<std::vector<std::string>>())
;
options.parse_positional({"input", "output", "positional"});
Argv av({"tester", "--output", "a", "b", "c", "d"});
char** argv = av.argv();
auto argc = av.argc();
options.parse(argc, argv);
CHECK(argc == 1);
CHECK(options.count("output"));
CHECK(options["input"].as<std::string>() == "b");
CHECK(options["output"].as<std::string>() == "a");
auto& positional = options["positional"].as<std::vector<std::string>>();
REQUIRE(positional.size() == 2);
CHECK(positional[0] == "c");
CHECK(positional[1] == "d");
}