You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2011/06/05 07:42:25 UTC
svn commit: r1131866 - in /incubator/mesos/trunk/src: configuration.cpp
configuration.hpp tests/test_configuration.cpp
Author: benh
Date: Sun Jun 5 05:42:25 2011
New Revision: 1131866
URL: http://svn.apache.org/viewvc?rev=1131866&view=rev
Log:
Validator added plus tests.
Modified:
incubator/mesos/trunk/src/configuration.cpp
incubator/mesos/trunk/src/configuration.hpp
incubator/mesos/trunk/src/tests/test_configuration.cpp
Modified: incubator/mesos/trunk/src/configuration.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/configuration.cpp?rev=1131866&r1=1131865&r2=1131866&view=diff
==============================================================================
--- incubator/mesos/trunk/src/configuration.cpp (original)
+++ incubator/mesos/trunk/src/configuration.cpp Sun Jun 5 05:42:25 2011
@@ -21,11 +21,39 @@ const char* Configuration::CONFIG_FILE_N
const char* Configuration::ENV_VAR_PREFIX = "MESOS_";
-Configuration::Configuration(const map<string, string>& _params)
+void Configuration::validate()
+{
+ foreachpair(const string& key, const Option& opt, options) {
+ if (params.contains(key) && opt.validator && !opt.validator->isValid(params[key])) {
+ throw BadOptionValueException(params[key].c_str());
+ }
+ }
+}
+
+
+void Configuration::loadEnvCmdConf(int argc, char** argv, bool inferMesosHomeFromArg0)
+{
+ loadEnv();
+ loadCommandLine(argc, argv, inferMesosHomeFromArg0);
+ loadConfigFileIfGiven();
+ validate();
+}
+
+
+void Configuration::loadEnvConf()
+{
+ loadEnv();
+ loadConfigFileIfGiven();
+ validate();
+}
+
+
+void Configuration::loadEnvMapConf(const map<string, string>& _params)
{
loadEnv();
params.loadMap(_params);
loadConfigFileIfGiven();
+ validate();
}
Modified: incubator/mesos/trunk/src/configuration.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/configuration.hpp?rev=1131866&r1=1131865&r2=1131866&view=diff
==============================================================================
--- incubator/mesos/trunk/src/configuration.hpp (original)
+++ incubator/mesos/trunk/src/configuration.hpp Sun Jun 5 05:42:25 2011
@@ -19,7 +19,48 @@ using std::cerr;
using std::endl;
using std::ifstream;
using std::map;
+using boost::lexical_cast;
+using boost::bad_lexical_cast;
+/**
+ * Interface of a validator
+ **/
+class ValidatorBase {
+public:
+ virtual bool isValid(const string& val) const = 0;
+ virtual ValidatorBase* clone() const = 0;
+};
+
+/**
+ * Validator that checks if a string can be cast to its templated type.
+ **/
+template <class T>
+class Validator : public ValidatorBase {
+public:
+ Validator() {}
+
+ /**
+ * Checks if the provided string can be cast to a T.
+ * @param val value associated with some option
+ * @return true if val can be cast to a T, otherwise false.
+ **/
+ virtual bool isValid(const string& val) const
+ {
+ try {
+ lexical_cast<T>(val);
+ }
+ catch(const bad_lexical_cast& ex) {
+ return false;
+ }
+ return true;
+ }
+
+ virtual ValidatorBase* clone() const
+ {
+ return new Validator<T>();
+ }
+
+};
/**
* Exception type thrown by Configuration.
@@ -32,16 +73,60 @@ struct ConfigurationException : std::exc
};
/**
- * Registered option with help string and defautl value
+ * Exception type thrown if the the value of an Option
+ * doesn't match the default value type.
+ */
+struct BadOptionValueException : std::exception
+{
+ const char* message;
+ BadOptionValueException(const char* msg): message(msg) {}
+ const char* what() const throw () { return message; }
+};
+
+/**
+ * Registered option with help string and default value
**/
struct Option {
- Option(string _helpString, string _defaultValue="") :
- helpString(_helpString), defaultValue(_defaultValue) {}
+ Option(string _helpString) :
+ helpString(_helpString), defaultValue(""), validator(NULL) {}
+
+
+ Option(string _helpString, string _defaultValue,
+ const ValidatorBase& _validator) :
+ helpString(_helpString), defaultValue(_defaultValue)
+ {
+ validator = _validator.clone();
+ }
+
+
+ Option() : validator(NULL) {}
+
+
+ Option(const Option& opt) :
+ helpString(opt.helpString), defaultValue(opt.defaultValue)
+ {
+ validator = opt.validator == NULL ? NULL : opt.validator->clone();
+ }
+
+
+ Option &operator=(const Option& opt)
+ {
+ helpString = opt.helpString;
+ defaultValue = opt.defaultValue;
+ validator = opt.validator == NULL ? NULL : opt.validator->clone();
+ return *this;
+ }
+
+
+ ~Option()
+ {
+ if (validator != 0) delete validator;
+ }
- Option() {}
string helpString;
string defaultValue;
+ ValidatorBase *validator;
};
/**
@@ -70,18 +155,10 @@ private:
public:
/**
- * Constructor that initializes an empty Params
+ * Initializes an empty Params
**/
Configuration() {}
- /**
- * Constructor that populates Params from environment, a map,
- * and any config file specified through these.
- *
- * @param argc number of paramters in argv
- * @param argv array of c-strings from the command line
- **/
- Configuration(const map<string, string>& _params);
/**
* Returns the Params object parsed by this Configuration.
@@ -89,12 +166,14 @@ public:
**/
Params& getParams();
+
/**
* Returns a usage string with all registered options
* @see addOption()
* @return usage string
**/
string getUsage() const;
+
/**
* Adds a registered option together with a default value and a help string.
@@ -115,7 +194,7 @@ public:
return -1;
ostringstream os;
os << defaultValue;
- options[optName] = Option(helpString, os.str());
+ options[optName] = Option(helpString, os.str(), Validator<T>());
if (!params.contains(optName)) // insert default value
params[optName] = os.str();
@@ -123,6 +202,7 @@ public:
return 0;
}
+
/**
* Adds a registered option together with a help string
* It's recommended to use the other version of this method,
@@ -140,12 +220,77 @@ public:
**/
string getOptionDefault(string optName) const;
+
/**
* Returns the name of all options.
* @return name of every registered option
**/
vector<string> getOptions() const;
+
+ /**
+ * Validates the values of all keys that it has a default option for.
+ * @throws BadOptionValueException with the key of the parameter
+ * that has the wrong type.
+ **/
+ void validate();
+
+
+ /**
+ * Populates its internal Params with key/value params from environment,
+ * command line, and config file.
+ * <i>Environment:</i><br>
+ * Parses the environment variables and populates a Params.
+ * It picks all environment variables that start with MESOS_.
+ * The environment variable MESOS_HOME=/dir would lead to key=HOME val=/dir<br>
+ * <i>Command line:</i><br>
+ * It extracts four type of command line parameters:
+ * "--key=val", "-key val", "--key", "-key". The two last cases will
+ * have default value "1" in the Params. <br>
+ * <i>Config file:</i><br>
+ * The config file should contain key=value pairs, one per line.
+ * Comments, which should start with #, are ignored.
+ *
+ * @param argc is the number of parameters in argv
+ * @param argv is an array of c-strings containing params
+ * @param inferMesosHomeFromArg0 whether to set mesos home to directory
+ * containing argv[0] (the program being run)
+ **/
+ void loadEnvCmdConf(int argc, char** argv, bool inferMesosHomeFromArg0=false);
+
+
+ /**
+ * Populates its internal Params with key/value params from environment,
+ * and config file.
+ * <i>Environment:</i><br>
+ * Parses the environment variables and populates a Params.
+ * It picks all environment variables that start with MESOS_.
+ * The environment variable MESOS_HOME=/dir would lead to key=HOME val=/dir <br>
+ * <i>Config file:</i><br>
+ * The config file should contain key=value pairs, one per line.
+ * Comments, which should start with #, are ignored.
+ **/
+ void loadEnvConf();
+
+
+ /**
+ * Populates its internal Params with key/value params from environment,
+ * a provided map, and config file.
+ * <i>Environment:</i><br>
+ * Parses the environment variables and populates a Params.
+ * It picks all environment variables that start with MESOS_.
+ * The environment variable MESOS_HOME=/dir would lead to key=HOME val=/dir <br>
+ * <i>Map:</i><br>
+ * Containing a string to string map. <br>
+ * <i>Config file:</i><br>
+ * The config file should contain key=value pairs, one per line.
+ * Comments, which should start with #, are ignored.
+ *
+ * @param _params map containing key value pairs to be loaded
+ **/
+ void loadEnvMapConf(const map<string, string>& _params);
+
+private:
/**
* Parses the environment variables and populates a Params.
* It picks all environment variables that start with MESOS_.
Modified: incubator/mesos/trunk/src/tests/test_configuration.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/test_configuration.cpp?rev=1131866&r1=1131865&r2=1131866&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/test_configuration.cpp (original)
+++ incubator/mesos/trunk/src/tests/test_configuration.cpp Sun Jun 5 05:42:25 2011
@@ -23,8 +23,7 @@ TEST(ConfigurationTest, Environment)
{
setenv("MESOS_TEST", "working", true);
Configuration conf;
- conf.loadEnv();
- conf.loadConfigFileIfGiven();
+ conf.loadEnvConf();
unsetenv("MESOS_TEST");
EXPECT_EQ("working", conf.getParams()["test"]);
@@ -33,27 +32,32 @@ TEST(ConfigurationTest, Environment)
TEST(ConfigurationTest, DefaultOptions)
{
- const int ARGC = 3;
+ const int ARGC = 4;
char* argv[ARGC];
argv[0] = (char*) "./filename";
- argv[1] = (char*) "--test1=text1";
+ argv[1] = (char*) "--test1=501";
argv[2] = (char*) "--test2";
+ argv[3] = (char*) "--excp=txt";
Configuration conf;
- conf.addOption("test1", "Testing option", 500);
- conf.addOption("test2", "Another tester", 0);
- conf.addOption("test3", "Tests the default\noption.", 2010);
- conf.addOption("test4", "Option without default\noption.");
-
- conf.loadEnv();
- conf.loadCommandLine(ARGC, argv, false);
- conf.loadConfigFileIfGiven();
+ EXPECT_NO_THROW( {
+ conf.addOption<int>("test1", "Testing option", 500);
+ conf.addOption<short>("test2", "Another tester", 0);
+ conf.addOption<long>("test3", "Tests the default\noption.", 2010);
+ conf.addOption("test4", "Option without default\noption.");
+ conf.addOption<string>("test5", "Option with a default string.", "arb");
+ conf.loadEnvCmdConf(ARGC, argv, false);
+ } );
+
+ conf.addOption<int>("excp", "Exception tester.", 50);
+ EXPECT_THROW(conf.validate(), BadOptionValueException);
- EXPECT_EQ("text1", conf.getParams()["test1"]);
+ EXPECT_EQ("501", conf.getParams()["test1"]);
EXPECT_EQ("1", conf.getParams()["test2"]);
EXPECT_EQ("2010", conf.getParams()["test3"]);
EXPECT_EQ("", conf.getParams()["test4"]);
+ EXPECT_EQ("arb", conf.getParams()["test5"]);
}
@@ -73,9 +77,7 @@ TEST(ConfigurationTest, CommandLine)
argv[9] = (char*) "--space=Long String";
Configuration conf;
- conf.loadEnv();
- conf.loadCommandLine(ARGC, argv, false);
- conf.loadConfigFileIfGiven();
+ conf.loadEnvCmdConf(ARGC, argv, false);
EXPECT_EQ("text1", conf.getParams()["test1"]);
EXPECT_EQ("1", conf.getParams()["test2"]);
@@ -101,8 +103,7 @@ TEST_WITH_WORKDIR(ConfigurationTest, Con
setenv("MESOS_HOME", ".", 1);
Configuration conf;
- conf.loadEnv();
- conf.loadConfigFileIfGiven();
+ conf.loadEnvConf();
unsetenv("MESOS_HOME");
EXPECT_EQ("coffee", conf.getParams()["test1"]);
@@ -122,8 +123,7 @@ TEST_WITH_WORKDIR(ConfigurationTest, Con
file.close();
setenv("MESOS_CONF", "conf2", 1);
Configuration conf;
- conf.loadEnv();
- conf.loadConfigFileIfGiven();
+ conf.loadEnvConf();
unsetenv("MESOS_CONF");
EXPECT_EQ("shake", conf.getParams()["test3"]);
@@ -145,8 +145,7 @@ TEST_WITH_WORKDIR(ConfigurationTest, Con
setenv("MESOS_HOME", ".", 1);
setenv("MESOS_CONF", "conf2", 1);
Configuration conf;
- conf.loadEnv();
- conf.loadConfigFileIfGiven();
+ conf.loadEnvConf();
unsetenv("MESOS_CONF");
unsetenv("MESOS_HOME");
@@ -175,9 +174,7 @@ TEST_WITH_WORKDIR(ConfigurationTest, Com
argv[3] = (char*) "--d=fromCmdLine";
Configuration conf;
- conf.loadEnv();
- conf.loadCommandLine(ARGC, argv, false);
- conf.loadConfigFileIfGiven();
+ conf.loadEnvCmdConf(ARGC, argv, false);
EXPECT_EQ("1", conf.getParams()["a"]);
EXPECT_EQ("overridden", conf.getParams()["b"]);
@@ -215,9 +212,7 @@ TEST_WITH_WORKDIR(ConfigurationTest, Loa
argv[2] = (char*) "--c=fromCmdLine";
Configuration conf;
- conf.loadEnv();
- conf.loadCommandLine(ARGC, argv, false);
- conf.loadConfigFileIfGiven();
+ conf.loadEnvCmdConf(ARGC, argv, false);
// Clear the environment vars set above
unsetenv("MESOS_HOME");