📄 cmdline_test.cpp
字号:
// Copyright Vladimir Prus 2002-2004.// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt// or copy at http://www.boost.org/LICENSE_1_0.txt)#include <boost/program_options/cmdline.hpp>#include <boost/program_options/options_description.hpp>#include <boost/program_options/detail/cmdline.hpp>using namespace boost::program_options;using boost::program_options::detail::cmdline;#include <iostream>#include <sstream>#include <vector>#include <cassert>using namespace std;#include "minitest.hpp"/* To facilitate testing, declare a number of error codes. Otherwise, we'd have to specify the type of exception that should be thrown.*/const int s_success = 0;const int s_unknown_option = 1;const int s_ambiguous_option = 2;const int s_long_not_allowed = 3;const int s_long_adjacent_not_allowed = 4;const int s_short_adjacent_not_allowed = 5;const int s_empty_adjacent_parameter = 6;const int s_missing_parameter = 7;const int s_extra_parameter = 8;int translate_syntax_error_kind(invalid_command_line_syntax::kind_t k){ invalid_command_line_syntax::kind_t table[] = { invalid_command_line_syntax::long_not_allowed, invalid_command_line_syntax::long_adjacent_not_allowed, invalid_command_line_syntax::short_adjacent_not_allowed, invalid_command_line_syntax::empty_adjacent_parameter, invalid_command_line_syntax::missing_parameter, invalid_command_line_syntax::extra_parameter, }; invalid_command_line_syntax::kind_t *b, *e, *i; b = table; e = table + sizeof(table)/sizeof(table[0]); i = std::find(b, e, k); assert(i != e); return std::distance(b, i) + 3;}struct test_case { const char* input; int expected_status; const char* expected_result;};/* Parses the syntax description in 'syntax' and initialized 'cmd' accordingly' The "boost::program_options" in parameter type is needed because CW9 has std::detail and it causes an ambiguity.*/void apply_syntax(options_description& desc, const char* syntax){ string s; stringstream ss; ss << syntax; while(ss >> s) { value_semantic* v = 0; if (*(s.end()-1) == '=') { v = value<string>(); s.resize(s.size()-1); } else if (*(s.end()-1) == '?') { //v = value<string>()->implicit(); v = value<string>(); s.resize(s.size()-1); } else if (*(s.end()-1) == '*') { v = value<vector<string> >()->multitoken(); s.resize(s.size()-1); } else if (*(s.end()-1) == '+') { v = value<vector<string> >()->multitoken(); s.resize(s.size()-1); } if (v) { desc.add_options() (s.c_str(), v, ""); } else { desc.add_options() (s.c_str(), ""); } }}void test_cmdline(const char* syntax, command_line_style::style_t style, const test_case* cases){ for (int i = 0; cases[i].input; ++i) { // Parse input vector<string> xinput; { string s; stringstream ss; ss << cases[i].input; while (ss >> s) { xinput.push_back(s); } } options_description desc; apply_syntax(desc, syntax); cmdline cmd(xinput); cmd.style(style); cmd.set_options_description(desc); string result; int status = 0; try { vector<option> options = cmd.run(); for(unsigned i = 0; i < options.size(); ++i) { option opt = options[i]; if (opt.position_key != -1) { if (!result.empty()) result += " "; result += opt.value[0]; } else { if (!result.empty()) result += " "; result += opt.string_key + ":"; for (size_t j = 0; j < opt.value.size(); ++j) { if (j != 0) result += "-"; result += opt.value[j]; } } } } catch(unknown_option& e) { status = s_unknown_option; } catch(ambiguous_option& e) { status = s_ambiguous_option; } catch(invalid_command_line_syntax& e) { status = translate_syntax_error_kind(e.kind()); } BOOST_CHECK_EQUAL(status, cases[i].expected_status); BOOST_CHECK_EQUAL(result, cases[i].expected_result); }}void test_long_options(){ using namespace command_line_style; cmdline::style_t style = cmdline::style_t( allow_long | long_allow_adjacent); test_case test_cases1[] = { // Test that long options are recognized and everything else // is treated like arguments {"--foo foo -123 /asd", s_success, "foo: foo -123 /asd"}, // Unknown option {"--unk", s_unknown_option, ""}, // Test that abbreviated names do not work {"--fo", s_unknown_option, ""}, // Test for disallowed parameter {"--foo=13", s_extra_parameter, ""}, // Test option with required parameter {"--bar=", s_empty_adjacent_parameter, ""}, {"--bar", s_missing_parameter, ""}, {"--bar=123", s_success, "bar:123"}, {0} }; test_cmdline("foo bar=", style, test_cases1); style = cmdline::style_t( allow_long | long_allow_next); test_case test_cases2[] = { {"--bar 10", s_success, "bar:10"}, {"--bar", s_missing_parameter, ""}, // Since --bar accepts a parameter, --foo is // considered a value, even though it looks like // an option. {"--bar --foo", s_success, "bar:--foo"}, {0} }; test_cmdline("foo bar=", style, test_cases2); style = cmdline::style_t( allow_long | long_allow_adjacent | long_allow_next); test_case test_cases3[] = { {"--bar=10", s_success, "bar:10"}, {"--bar 11", s_success, "bar:11"}, {0} }; test_cmdline("foo bar=", style, test_cases3); style = cmdline::style_t( allow_long | long_allow_adjacent | long_allow_next | case_insensitive);// FIXME: restore#if 0 // Test case insensitive style. // Note that option names are normalized to lower case. test_case test_cases4[] = { {"--foo", s_success, "foo:"}, {"--Foo", s_success, "foo:"}, {"--bar=Ab", s_success, "bar:Ab"}, {"--Bar=ab", s_success, "bar:ab"}, {"--giz", s_success, "Giz:"}, {0} }; test_cmdline("foo bar= baz? Giz", style, test_cases4);#endif}void test_short_options(){ using namespace command_line_style; cmdline::style_t style; style = cmdline::style_t( allow_short | allow_dash_for_short | short_allow_adjacent); test_case test_cases1[] = { {"-d d /bar", s_success, "-d: d /bar"}, // This is treated as error when long options are disabled {"--foo", s_success, "--foo"}, {"-d13", s_extra_parameter, ""}, {"-f14", s_success, "-f:14"}, {"-g -f1", s_success, "-g: -f:1"}, {"-f", s_missing_parameter, ""}, {0} }; test_cmdline(",d ,f= ,g", style, test_cases1); style = cmdline::style_t( allow_short | allow_dash_for_short | short_allow_next); test_case test_cases2[] = { {"-f 13", s_success, "-f:13"}, {"-f -13", s_success, "-f:-13"}, {"-f", s_missing_parameter, ""}, {"-f /foo", s_success, "-f:/foo"}, {"-f -d", s_success, "-f:-d"}, {0} }; test_cmdline(",d ,f=", style, test_cases2); style = cmdline::style_t( allow_short | short_allow_next | allow_dash_for_short | short_allow_adjacent); test_case test_cases3[] = { {"-f10", s_success, "-f:10"}, {"-f 10", s_success, "-f:10"}, {"-f -d", s_success, "-f:-d"}, {0} }; test_cmdline(",d ,f=", style, test_cases3); style = cmdline::style_t( allow_short | short_allow_next | allow_dash_for_short | short_allow_adjacent | allow_sticky); test_case test_cases4[] = { {"-de", s_success, "-d: -e:"}, {"-df10", s_success, "-d: -f:10"}, // FIXME: review //{"-d12", s_extra_parameter, ""}, {"-f12", s_success, "-f:12"}, {"-fe", s_success, "-f:e"}, {0} }; test_cmdline(",d ,f= ,e", style, test_cases4);}void test_dos_options(){ using namespace command_line_style; cmdline::style_t style; style = cmdline::style_t( allow_short | allow_slash_for_short | short_allow_adjacent);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -