00001 #include <boost/test/auto_unit_test.hpp>
00002
00003 #include "testsuite.hh"
00004 #include <utilmm/configfile/configfile.hh>
00005 #include <utilmm/configfile/commandline.hh>
00006 #include <boost/filesystem/path.hpp>
00007 #include <utilmm/stringtools.hh>
00008 #include <algorithm>
00009
00010 using namespace utilmm;
00011 using namespace boost::filesystem;
00012 using namespace std;
00013
00014 auto_ptr<config_file> setup()
00015 {
00016 path testdir = path(__FILE__).branch_path();
00017 #if BOOST_VERSION >= 104600
00018 return auto_ptr<config_file>(new config_file( (testdir / "test_configfile.config").string().c_str() ));
00019 #else
00020 return auto_ptr<config_file>(new config_file( (testdir / "test_configfile.config").native_file_string().c_str() ));
00021 #endif
00022 }
00023 #define SETUP auto_ptr<config_file> config( setup() )
00024
00025
00026 BOOST_AUTO_TEST_CASE( test_basic_properties )
00027 {
00028 SETUP;
00029
00030 BOOST_REQUIRE(! config->empty());
00031 config_set empty_set;
00032 BOOST_REQUIRE( empty_set.empty() );
00033 }
00034
00035 template<typename T>
00036 void test_get_scalar(config_set const& config, string const& name, T expected)
00037 {
00038 T val = config.get<T>(name);
00039 BOOST_REQUIRE_EQUAL(val, expected);
00040 }
00041 BOOST_AUTO_TEST_CASE( test_scalar )
00042 {
00043 SETUP;
00044
00045 BOOST_REQUIRE_EQUAL(config->get<string>("unknown_key", "defval"), "defval");
00046 BOOST_REQUIRE_EQUAL(config->get<string> ("str"), "a string");
00047 BOOST_REQUIRE_EQUAL(config->get<int>("int_one"), 1);
00048 BOOST_REQUIRE_EQUAL(config->get<bool>("bool_true"), true);
00049 BOOST_REQUIRE_EQUAL(config->get<bool>("bool_false"), false);
00050 BOOST_REQUIRE_THROW(config->get<bool>("bool_invalid"), boost::bad_lexical_cast);
00051 }
00052
00053 BOOST_AUTO_TEST_CASE( test_list )
00054 {
00055 SETUP;
00056
00057 list<int> values = config->get< list<int> >("list");
00058 BOOST_REQUIRE(!values.empty());
00059
00060 vector<int> expected(10, 0);
00061 for (list<int>::const_iterator it = values.begin(); it != values.end(); ++it)
00062 expected[*it] = 1;
00063
00064 BOOST_REQUIRE(find(expected.begin(), expected.end(), 0) == expected.end());
00065
00066 }
00067
00068 BOOST_AUTO_TEST_CASE( test_child )
00069 {
00070 SETUP;
00071
00072 std::list<config_set const*> children = config->children("child");
00073 BOOST_REQUIRE_EQUAL(children.size(), 1UL);
00074
00075 config_set const* child = children.front();
00076 BOOST_REQUIRE_EQUAL(child->get<string>("str"), "another string");
00077
00078 config_set const& only_child = config->child("child");
00079 BOOST_REQUIRE_EQUAL(child, &only_child);
00080
00081 config_set const& not_a_child = config->child("not_a_child");
00082 BOOST_REQUIRE(not_a_child.empty());
00083 }
00084
00085 BOOST_AUTO_TEST_CASE( test_cmdline_option_parsing )
00086 {
00087 SETUP;
00088
00089 { cmdline_option opt("*:include,I=string:include path");
00090 BOOST_REQUIRE(!opt.isRequired());
00091 BOOST_REQUIRE(opt.isMultiple());
00092 BOOST_REQUIRE_EQUAL("include", opt.getLong());
00093 BOOST_REQUIRE_EQUAL("include", opt.getConfigKey());
00094 BOOST_REQUIRE_EQUAL("I", opt.getShort());
00095 BOOST_REQUIRE(opt.hasArgument());
00096 BOOST_REQUIRE(!opt.isArgumentOptional());
00097 BOOST_REQUIRE(!opt.hasDefaultValue());
00098 BOOST_REQUIRE(opt.getArgumentFlags() & cmdline_option::StringArgument);
00099 BOOST_REQUIRE_EQUAL("include path", opt.getHelp());
00100 }
00101 { cmdline_option opt("!:required=bool:is a required argument");
00102 BOOST_REQUIRE(opt.isRequired());
00103 BOOST_REQUIRE(!opt.isMultiple());
00104 BOOST_REQUIRE_EQUAL("required", opt.getLong());
00105 BOOST_REQUIRE_EQUAL("required", opt.getConfigKey());
00106 BOOST_REQUIRE_EQUAL("", opt.getShort());
00107 BOOST_REQUIRE(opt.hasArgument());
00108 BOOST_REQUIRE(opt.getArgumentFlags() & cmdline_option::BoolArgument);
00109 BOOST_REQUIRE_EQUAL("is a required argument", opt.getHelp());
00110 }
00111 { cmdline_option opt("vkey:verbose,v?int,1:include path");
00112 BOOST_REQUIRE(!opt.isRequired());
00113 BOOST_REQUIRE(!opt.isMultiple());
00114 BOOST_REQUIRE_EQUAL("vkey", opt.getConfigKey());
00115 BOOST_REQUIRE_EQUAL("verbose", opt.getLong());
00116 BOOST_REQUIRE_EQUAL("v", opt.getShort());
00117 BOOST_REQUIRE(opt.hasArgument());
00118 BOOST_REQUIRE(opt.isArgumentOptional());
00119 BOOST_REQUIRE(opt.hasDefaultValue());
00120 BOOST_REQUIRE(opt.getArgumentFlags() & cmdline_option::IntArgument);
00121 BOOST_REQUIRE_EQUAL("1", opt.getDefaultValue());
00122 BOOST_REQUIRE_EQUAL("include path", opt.getHelp());
00123 }
00124 { cmdline_option opt(":quiet");
00125 BOOST_REQUIRE(!opt.isRequired());
00126 BOOST_REQUIRE(!opt.isMultiple());
00127 BOOST_REQUIRE_EQUAL("quiet", opt.getConfigKey());
00128 BOOST_REQUIRE_EQUAL("quiet", opt.getLong());
00129 BOOST_REQUIRE_EQUAL("", opt.getShort());
00130 BOOST_REQUIRE(!opt.hasArgument());
00131 BOOST_REQUIRE_EQUAL("", opt.getHelp());
00132 }
00133
00134
00135 BOOST_REQUIRE_THROW( cmdline_option option("*::bla"), bad_syntax );
00136
00137 BOOST_REQUIRE_THROW( cmdline_option option("*:invalid key:bla"), bad_syntax );
00138
00139 BOOST_REQUIRE_THROW( cmdline_option option(":blo=badtype"), bad_syntax );
00140
00141 BOOST_REQUIRE_THROW( cmdline_option option(":foo?int"), bad_syntax );
00142
00143 BOOST_REQUIRE_THROW( cmdline_option opt("!:required=bool,true:is a required argument"), bad_syntax );
00144
00145 BOOST_REQUIRE_NO_THROW( cmdline_option opt("!:required?bool,true:is a required argument") );
00146 }
00147
00148 void check_cmdline_properties(command_line& cmdline)
00149 {
00150 config_set config;
00151 const char* valid_argv[] = { "--required=false", "-I", "bla", "--include=test", "--quiet", "--verbose", "bla.cpp" };
00152
00153 cmdline.parse(7, valid_argv, config);
00154 BOOST_REQUIRE_EQUAL(1UL, cmdline.remaining().size() );
00155 BOOST_REQUIRE_EQUAL("bla.cpp", cmdline.remaining().front() );
00156
00157 list<string> includes = config.get< list<string> >("include");
00158 BOOST_REQUIRE_EQUAL(2UL, includes.size());
00159 BOOST_REQUIRE( "bla" == includes.back() || "bla" == includes.front() );
00160 BOOST_REQUIRE( "test" == includes.back() || "test" == includes.front() );
00161
00162 BOOST_REQUIRE_EQUAL( config.get<bool>("quiet"), true );
00163 BOOST_REQUIRE_EQUAL( config.get<bool>("vkey"), 1 );
00164 BOOST_REQUIRE_EQUAL( config.get<int>("defval"), 10 );
00165 }
00166
00167 BOOST_AUTO_TEST_CASE( test_commandline )
00168 {
00169 char const* valid_spec[] = {
00170 "*:include,I=string:include path",
00171 "!:required=bool:is a required argument",
00172 "vkey:verbose,v?int,1:include path",
00173 "defval:default-value=int,10:should be set to default value",
00174 ":quiet",
00175 0
00176 };
00177
00178 {
00179 list<string> strlist_spec;
00180 for (char const** specline = valid_spec; *specline; ++specline)
00181 strlist_spec.push_back(*specline);
00182
00183 command_line cmdline(valid_spec);
00184 check_cmdline_properties(cmdline);
00185 }
00186
00187 command_line cmdline(valid_spec);
00188 check_cmdline_properties(cmdline);
00189
00190 config_set config;
00191
00192 char const* missing_required[] = { "--quiet" };
00193 BOOST_REQUIRE_THROW( cmdline.parse(1, missing_required, config), commandline_error );
00194
00195 char const* missing_argument[] = { "--required=true", "--include" };
00196 BOOST_REQUIRE_THROW( cmdline.parse(2, missing_argument, config), commandline_error );
00197
00198 char const* missing_argument_short[] = { "--required=true", "-I", "--quiet" };
00199 BOOST_REQUIRE_THROW( cmdline.parse(3, missing_argument_short, config), commandline_error );
00200
00201 char const* invalid_argument_type[] = { "--required=true", "--verbose=bla" };
00202 BOOST_REQUIRE_THROW( cmdline.parse(2, invalid_argument_type, config), commandline_error );
00203
00204 char const* overriding_default_value[] = { "--required=true", "--default-value=20" };
00205 BOOST_REQUIRE_NO_THROW( cmdline.parse(2, overriding_default_value, config) );
00206 BOOST_REQUIRE_EQUAL(20, config.get<int>("defval"));
00207 }
00208