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");