2013-02-26 18:31:14 +11:00
|
|
|
#include "options.hpp"
|
|
|
|
|
|
|
|
#include "debug.hpp"
|
2015-04-13 16:45:56 +10:00
|
|
|
#include "tap.hpp"
|
2013-02-26 18:31:14 +11:00
|
|
|
#include "types.hpp"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <string>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <limits>
|
|
|
|
#include <sstream>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:31:14 +11:00
|
|
|
// Check that null options don't throw anything
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_null_opt (void) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor());
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
p->add_option(std::make_unique<util::nulloption> ('n', "null", "testing null option"));
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2013-02-27 15:10:17 +11:00
|
|
|
static const char *argv1[] = { "./foo", "-n", "foo" };
|
2013-02-26 18:31:14 +11:00
|
|
|
p->parse_args(elems(argv1), argv1);
|
|
|
|
|
2013-02-27 15:10:17 +11:00
|
|
|
static const char *argv2[] = { "./foo", "--null", "foo" };
|
2013-02-26 18:31:14 +11:00
|
|
|
p->parse_args(elems(argv2), argv2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:31:14 +11:00
|
|
|
// Check if presence options can be used successfully
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_present_opt (void) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor());
|
2013-02-26 18:31:14 +11:00
|
|
|
bool is_present;
|
2015-04-30 21:03:18 +10:00
|
|
|
p->add_option(std::make_unique<util::presentoption> ('p', "present", "option is present", &is_present));
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
// Short option form
|
2013-02-27 15:10:17 +11:00
|
|
|
static const char *argv1[] = { "./foo", "-p" };
|
2013-02-26 18:31:14 +11:00
|
|
|
is_present = false;
|
|
|
|
p->parse_args(elems(argv1), argv1);
|
|
|
|
CHECK (is_present);
|
|
|
|
|
|
|
|
// Long option form
|
2013-02-27 15:10:17 +11:00
|
|
|
static const char *argv2[] = { "./foo", "--present" };
|
2013-02-26 18:31:14 +11:00
|
|
|
is_present = false;
|
|
|
|
p->parse_args(elems(argv2), argv2);
|
|
|
|
CHECK (is_present);
|
|
|
|
|
|
|
|
// Check that value is reset from true if not present
|
2013-02-27 15:10:17 +11:00
|
|
|
static const char *argv3[] = { "./foo" };
|
2013-02-26 18:31:14 +11:00
|
|
|
is_present = true;
|
|
|
|
p->parse_args(elems(argv3), argv3);
|
|
|
|
CHECK (!is_present);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:31:14 +11:00
|
|
|
// Check all forms of boolean inputs
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_bool_opt (void) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor());
|
2013-02-26 18:31:14 +11:00
|
|
|
bool value = false;
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
p->add_option (std::make_unique<util::valueoption<bool>> ('b', "bool", "testing boolean actions", &value));
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
// List all legal forms of positive or negative boolean values
|
2014-10-21 21:48:13 +11:00
|
|
|
std::array<const char*, 3> argv { "./foo", "-b", NULL };
|
2013-02-27 15:10:17 +11:00
|
|
|
static const char *positive[] = { "1", "true", "yes" };
|
|
|
|
static const char *negative[] = { "0", "false", "no" };
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
// For each boolean value, ensure that it returns as expected
|
2014-10-21 21:48:13 +11:00
|
|
|
for (auto i: positive) {
|
|
|
|
static size_t count;
|
|
|
|
std::cerr << "iter " << count++ << '\n';
|
|
|
|
argv[2] = i;
|
|
|
|
p->parse_args (argv.size (), argv.data ());
|
2013-02-26 18:31:14 +11:00
|
|
|
CHECK (value == true);
|
|
|
|
}
|
|
|
|
|
2014-10-21 21:48:13 +11:00
|
|
|
for (auto i: negative) {
|
|
|
|
argv[2] = i;
|
|
|
|
p->parse_args (argv.size (), argv.data ());
|
2013-02-26 18:31:14 +11:00
|
|
|
CHECK (value == false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that invalid forms of boolean all throw exceptions
|
2013-02-26 18:56:25 +11:00
|
|
|
const char* invalid[] = { "foo", "y", "null" };
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2014-10-21 21:48:13 +11:00
|
|
|
for (auto i: invalid) {
|
|
|
|
argv[2] = i;
|
2013-02-26 18:31:14 +11:00
|
|
|
CHECK_THROWS (
|
|
|
|
std::domain_error,
|
2014-10-21 21:48:13 +11:00
|
|
|
p->parse_args (argv.size (), argv.data ())
|
2013-02-26 18:31:14 +11:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:31:14 +11:00
|
|
|
template<typename T>
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_numeric_opt (void) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor ());
|
2013-02-26 18:31:14 +11:00
|
|
|
T value;
|
2015-04-30 21:03:18 +10:00
|
|
|
p->add_option (std::make_unique<util::valueoption<T>> ('t', "type", "testing type option", &value));
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
T values[] = {
|
|
|
|
// TODO: Enable minimum value testing. Currently disabled as
|
|
|
|
// a negative numerical value looks just like a proceeding
|
|
|
|
// option.
|
2015-04-30 21:03:18 +10:00
|
|
|
//std::numeric_limits<T>::min(),
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
std::numeric_limits<T>::max (),
|
2013-02-26 18:31:14 +11:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
const char * argv_short[] = { "./foo", "-t", NULL };
|
|
|
|
const char * argv_long[] = { "./foo", NULL };
|
|
|
|
|
2013-02-27 15:10:17 +11:00
|
|
|
for(size_t i = 0; i < elems (values); ++i) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::ostringstream out_short, out_long;
|
|
|
|
std::string str_short, str_long;
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
out_short << values[i];
|
2013-02-26 18:56:25 +11:00
|
|
|
str_short = out_short.str ();
|
|
|
|
argv_short[2] = str_short.c_str ();
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
value = 2;
|
2013-02-26 18:56:25 +11:00
|
|
|
p->parse_args (elems (argv_short), argv_short);
|
2013-02-26 18:31:14 +11:00
|
|
|
CHECK (value == values[i]);
|
|
|
|
|
|
|
|
out_long << "--type=" << values[i];
|
2013-02-26 18:56:25 +11:00
|
|
|
str_long = out_long.str ();
|
|
|
|
argv_long[1] = str_long.c_str ();
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
value = 2;
|
2013-02-26 18:56:25 +11:00
|
|
|
p->parse_args (elems (argv_long), argv_long);
|
2013-02-26 18:31:14 +11:00
|
|
|
CHECK (value == values[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_bytes_opt(void) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor ());
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2013-02-27 15:10:17 +11:00
|
|
|
static const struct {
|
2013-02-26 18:56:25 +11:00
|
|
|
const char *param;
|
2015-04-30 21:03:18 +10:00
|
|
|
util::bytesoption::bytestype type;
|
|
|
|
util::bytesoption::bytesmodifier mod;
|
2013-02-26 18:56:25 +11:00
|
|
|
size_t size;
|
2013-02-26 18:31:14 +11:00
|
|
|
} commands[] = {
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1", util::bytesoption::BYTES_MEGA,
|
|
|
|
util::bytesoption::BYTES_BASE2,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1024 * 1024 },
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1k", util::bytesoption::BYTES_KILO,
|
|
|
|
util::bytesoption::BYTES_BASE2,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1024 },
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1M", util::bytesoption::BYTES_SINGLE,
|
|
|
|
util::bytesoption::BYTES_BASE2,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1024 * 1024 },
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1G", util::bytesoption::BYTES_MEGA,
|
|
|
|
util::bytesoption::BYTES_BASE2,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1024 * 1024 * 1024 },
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1M", util::bytesoption::BYTES_SINGLE,
|
|
|
|
util::bytesoption::BYTES_BASE10,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1000 * 1000 },
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1MB", util::bytesoption::BYTES_SINGLE,
|
|
|
|
util::bytesoption::BYTES_BASE10,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1000 * 1000 },
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
{ "1MiB", util::bytesoption::BYTES_SINGLE,
|
|
|
|
util::bytesoption::BYTES_BASE10,
|
2013-02-26 18:31:14 +11:00
|
|
|
1UL * 1024 * 1024 },
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2015-04-13 18:06:08 +10:00
|
|
|
static const char *argv[] = {
|
2013-02-26 18:31:14 +11:00
|
|
|
"./foo",
|
|
|
|
"-b",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2013-02-26 18:56:25 +11:00
|
|
|
for (unsigned int i = 0; i < elems (commands); ++i) {
|
2013-02-26 18:31:14 +11:00
|
|
|
size_t size = 0;
|
2015-04-30 21:03:18 +10:00
|
|
|
p->add_option(std::make_unique<util::bytesoption> (
|
2013-02-27 15:10:17 +11:00
|
|
|
'b', "bytes",
|
|
|
|
"testing sizeof bytes", &size, commands[i].type,
|
2015-04-13 18:06:08 +10:00
|
|
|
commands[i].mod
|
2013-02-27 15:10:17 +11:00
|
|
|
));
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2013-02-26 18:56:25 +11:00
|
|
|
argv[elems (argv) - 1] = commands[i].param;
|
|
|
|
p->parse_args (elems (argv), argv);
|
2013-02-26 18:31:14 +11:00
|
|
|
|
|
|
|
CHECK_EQ (commands[i].size, size);
|
2013-02-27 15:10:17 +11:00
|
|
|
p->remove_option ('b');
|
2013-02-26 18:31:14 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_insert_remove_opt (void) {
|
2013-02-27 15:10:17 +11:00
|
|
|
{
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor ());
|
|
|
|
auto opt = std::make_unique<util::nulloption> ('n', "null-option", "null testing action");
|
2013-02-27 15:10:17 +11:00
|
|
|
auto cmp = opt.get ();
|
|
|
|
p->add_option (move (opt));
|
2015-04-30 21:03:18 +10:00
|
|
|
CHECK_EQ (p->remove_option ('n').get (), (util::option*)cmp);
|
2013-02-27 15:10:17 +11:00
|
|
|
}
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2013-02-27 15:10:17 +11:00
|
|
|
{
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor ());
|
|
|
|
auto opt = std::make_unique<util::nulloption> ('n', "null-option", "null testing action");
|
2013-02-27 15:10:17 +11:00
|
|
|
auto cmp = opt.get ();
|
|
|
|
p->add_option (move (opt));
|
2015-04-30 21:03:18 +10:00
|
|
|
CHECK_EQ (p->remove_option ("null-option").get (), (util::option*)cmp);
|
2013-02-27 15:10:17 +11:00
|
|
|
}
|
2013-02-26 18:31:14 +11:00
|
|
|
|
2013-02-27 15:10:17 +11:00
|
|
|
{
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p(new util::processor ());
|
|
|
|
auto opt1 = std::make_unique<util::nulloption> ('n', "null-option", "null testing action");
|
|
|
|
auto opt2 = std::make_unique<util::nulloption> ('n', "null-option", "null testing action");
|
2013-02-27 15:10:17 +11:00
|
|
|
p->add_option (move (opt1));
|
|
|
|
CHECK_THROWS (std::logic_error, p->add_option (move (opt2)));
|
|
|
|
}
|
2013-02-26 18:31:14 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:56:25 +11:00
|
|
|
void
|
|
|
|
test_required (void) {
|
2015-04-30 21:03:18 +10:00
|
|
|
std::unique_ptr<util::processor> p (new util::processor ());
|
|
|
|
p->add_option (std::make_unique <util::nulloption> (
|
2013-02-27 15:10:17 +11:00
|
|
|
'n',
|
|
|
|
"null",
|
|
|
|
"null testing",
|
|
|
|
true
|
|
|
|
));
|
|
|
|
|
2013-02-26 18:31:14 +11:00
|
|
|
static const char *argv[] = {
|
|
|
|
"./cpptest",
|
|
|
|
"-n",
|
|
|
|
"value"
|
|
|
|
};
|
|
|
|
|
2013-02-26 18:56:25 +11:00
|
|
|
CHECK_NOTHROW (p->parse_args (elems (argv), argv));
|
2013-02-26 18:31:14 +11:00
|
|
|
CHECK_THROWS (std::runtime_error, p->parse_args (1, argv));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-30 21:03:18 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-02-26 18:31:14 +11:00
|
|
|
int
|
2013-02-27 15:10:17 +11:00
|
|
|
main (int, char **) {
|
2013-02-26 18:31:14 +11:00
|
|
|
test_null_opt ();
|
|
|
|
test_present_opt ();
|
|
|
|
test_bool_opt ();
|
|
|
|
test_numeric_opt< int16_t> ();
|
|
|
|
test_numeric_opt< int32_t> ();
|
|
|
|
test_numeric_opt< int64_t> ();
|
|
|
|
test_numeric_opt<uint16_t> ();
|
|
|
|
test_numeric_opt<uint32_t> ();
|
|
|
|
test_numeric_opt<uint64_t> ();
|
|
|
|
test_bytes_opt ();
|
|
|
|
test_insert_remove_opt ();
|
|
|
|
test_required ();
|
2015-04-13 16:45:56 +10:00
|
|
|
|
|
|
|
util::TAP::logger tap;
|
|
|
|
tap.todo ("convert to TAP");
|
2013-02-26 18:31:14 +11:00
|
|
|
}
|