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