Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Convert config module to unit testing
[simgrid.git] / src / xbt / config.c
index 81c8fb4..618ec71 100644 (file)
@@ -9,8 +9,6 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
-#include <stdio.h> /* FIXME: killme */
-
 #include "xbt/misc.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
@@ -210,11 +208,12 @@ xbt_cfg_register(xbt_cfg_t cfg,
   xbt_assert4(type>=xbt_cfgelm_int && type<=xbt_cfgelm_host,
               "type of %s not valid (%d should be between %d and %d)",
               name,type,xbt_cfgelm_int, xbt_cfgelm_host);
-  DEBUG5("Register cfg elm %s (%d to %d %s (=%d))",name,min,max,xbt_cfgelm_type_name[type],type);
+  DEBUG5("Register cfg elm %s (%d to %d %s (=%d))",
+        name,min,max,xbt_cfgelm_type_name[type],type);
   TRY {
     res = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
+    if (e.category == not_found_error) {
       found = 1;
       xbt_ex_free(e);
     } else {
@@ -265,11 +264,12 @@ xbt_cfg_register(xbt_cfg_t cfg,
  *  @arg name the name of the elem to be freed
  * 
  *  Note that it removes both the description and the actual content.
+ *  Throws not_found when no such element exists.
  */
 
-xbt_error_t
+void
 xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
-  return xbt_dict_remove((xbt_dict_t)cfg,name);
+  xbt_dict_remove((xbt_dict_t)cfg,name);
 }
 
 /**
@@ -283,7 +283,7 @@ xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
  * with type being one of  'string','int', 'host' or 'double'.
  */
 
-xbt_error_t
+void
 xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
   char *entrycpy=xbt_strdup(entry);
   char *tok;
@@ -292,66 +292,42 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
   e_xbt_cfgelm_type_t type;
 
   tok=strchr(entrycpy, ':');
-  if (!tok) {
-    ERROR3("%s%s%s",
-         "Invalid config element descriptor: ",entry,
-         "; Should be <name>:<min nb>_to_<max nb>_<type>");
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert2(tok,"Invalid config element descriptor: %s%s",
+             entry,
+             "; Should be <name>:<min nb>_to_<max nb>_<type>");
   *(tok++)='\0';
 
   min=strtol(tok, &tok, 10);
-  if (!tok) {
-    ERROR1("Invalid minimum in config element descriptor %s",entry);
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert1(tok,"Invalid minimum in config element descriptor %s",entry);
 
-  if (!strcmp(tok,"_to_")){
-    ERROR3("%s%s%s",
-         "Invalid config element descriptor: ",entry,
-         "; Should be <name>:<min nb>_to_<max nb>_<type>");
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert2(strcmp(tok,"_to_"),
+             "Invalid config element descriptor : %s%s",           
+             entry,
+             "; Should be <name>:<min nb>_to_<max nb>_<type>");
   tok += strlen("_to_");
 
   max=strtol(tok, &tok, 10);
-  if (!tok) {
-    ERROR1("Invalid maximum in config element descriptor %s",entry);
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert1(tok,"Invalid maximum in config element descriptor %s",entry);
 
-  if (*(tok++)!='_') {
-    ERROR3("%s%s%s",
-         "Invalid config element descriptor: ",entry,
-         "; Should be <name>:<min nb>_to_<max nb>_<type>");
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert2( *(tok++) =='_',
+              "Invalid config element descriptor: %s%s",entry,
+              "; Should be <name>:<min nb>_to_<max nb>_<type>");
 
   for (type=0; 
        type<xbt_cfgelm_type_count && strcmp(tok,xbt_cfgelm_type_name[type]); 
        type++);
-  if (type == xbt_cfgelm_type_count) {
-    ERROR3("%s%s%s",
-         "Invalid type in config element descriptor: ",entry,
+  xbt_assert2(type < xbt_cfgelm_type_count,
+         "Invalid type in config element descriptor: %s%s",entry,
          "; Should be one of 'string', 'int', 'host' or 'double'.");
-    free(entrycpy);
-    xbt_abort();
-  }
 
   xbt_cfg_register(cfg,entrycpy,type,min,max,NULL,NULL);
 
   free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
-  return no_error;
 }
 
 /** @brief Check that each variable have the right amount of values */
 
-xbt_error_t
+void
 xbt_cfg_check(xbt_cfg_t cfg) {
   xbt_dict_cursor_t cursor; 
   xbt_cfgelm_t variable;
@@ -363,44 +339,42 @@ xbt_cfg_check(xbt_cfg_t cfg) {
   xbt_dict_foreach((xbt_dict_t)cfg,cursor,name,variable) {
     size = xbt_dynar_length(variable->content);
     if (variable->min > size) { 
-      ERROR4("Config elem %s needs at least %d %s, but there is only %d values.",
+      xbt_dict_cursor_free(&cursor);
+      THROW4(mismatch_error,0,
+            "Config elem %s needs at least %d %s, but there is only %d values.",
             name,
             variable->min,
             xbt_cfgelm_type_name[variable->type],
             size); 
-      xbt_dict_cursor_free(&cursor);
-      return mismatch_error;
     }
 
     if (variable->max > 0 && variable->max < size) {
-      ERROR4("Config elem %s accepts at most %d %s, but there is %d values.",
+      xbt_dict_cursor_free(&cursor);
+      THROW4(mismatch_error,0,
+            "Config elem %s accepts at most %d %s, but there is %d values.",
             name,
             variable->max,
             xbt_cfgelm_type_name[variable->type],
             size);
-      xbt_dict_cursor_free(&cursor);
-      return mismatch_error;
     }
-
   }
 
   xbt_dict_cursor_free(&cursor);
-  return no_error;
 }
 
 static xbt_cfgelm_t xbt_cfgelm_get(xbt_cfg_t  cfg,
                                   const char *name,
                                   e_xbt_cfgelm_type_t type){
-  xbt_cfgelm_t res;
+  xbt_cfgelm_t res=NULL;
   xbt_ex_t e;
 
   TRY {
     res = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
-      THROW1(mismatch_error,0,
-            "No registered variable '%s' in this config set",name);
+    if (e.category == not_found_error) {
       xbt_ex_free(e);
+      THROW1(not_found_error,0,
+            "No registered variable '%s' in this config set",name);
     }
     RETHROW;
   }
@@ -431,10 +405,10 @@ xbt_cfg_get_type(xbt_cfg_t cfg, const char *name) {
   TRY {
     variable = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
-      THROW1(mismatch_error,0,
-            "Can't get the type of '%s' since this variable does not exist",name);
+    if (e.category == not_found_error) { 
       xbt_ex_free(e);
+      THROW1(not_found_error,0,
+            "Can't get the type of '%s' since this variable does not exist",name);
     }
     RETHROW;
   }
@@ -458,16 +432,16 @@ xbt_cfg_set_vargs(xbt_cfg_t cfg, const char *name, va_list pa) {
   char *str;
   int i;
   double d;
-  e_xbt_cfgelm_type_t type;
+  e_xbt_cfgelm_type_t type=0; /* Set a dummy value to make gcc happy. It cannot get uninitialized */
 
   xbt_ex_t e;
   
   TRY {
     type = xbt_cfg_get_type(cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
+    if (e.category == not_found_error) {
       xbt_ex_free(e);
-      THROW1(mismatch_error,0,"Can't set the property '%s' since it's not registered",name);
+      THROW1(not_found_error,0,"Can't set the property '%s' since it's not registered",name);
     }
     RETHROW;
   }
@@ -534,7 +508,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
   double d;
   char *str;
 
-  xbt_cfgelm_t variable;
+  xbt_cfgelm_t variable=NULL;
   char *optionlist_cpy;
   char *option,  *name,*val;
 
@@ -567,8 +541,8 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
       option=NULL; /* don't do next iteration */
 
     } else {
-      DEBUG3("Boundary on '%c'. len=%d;option-name=%d",
-            *option,len,option-name);
+      DEBUG3("Boundary on '%c'. len=%d;option-name=%ld",
+            *option,len,(long)(option-name));
 
       /* Pass the following blank chars */
       *(option++)='\0';
@@ -591,7 +565,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
     if (!val) {
       free(optionlist_cpy);
       xbt_assert1(FALSE,
-            "Malformated option: '%s'; Should be of the form 'name:value'",
+            "Option '%s' badly formated. Should be of the form 'name:value'",
                  name);
     }
     *(val++)='\0';
@@ -601,10 +575,12 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
     TRY {
       variable = xbt_dict_get((xbt_dict_t)cfg,name);
     } CATCH(e) {
+      /* put it back on what won't get freed, ie within "options" and out of "optionlist_cpy" */
+      name = (char*) (optionlist_cpy-name + options); 
       free(optionlist_cpy);
-      if (e.category == mismatch_error) {
+      if (e.category == not_found_error) {
        xbt_ex_free(e);
-       THROW1(mismatch_error,0,"No registrated variable corresponding to '%s'.",name);
+       THROW1(not_found_error,0,"No registrated variable corresponding to '%s'.",name);
       }
       RETHROW;
     }
@@ -839,7 +815,7 @@ void xbt_cfg_rm_int(xbt_cfg_t cfg,const char*name, int val) {
     }
   }
 
-  THROW2(mismatch_error,0,
+  THROW2(not_found_error,0,
         "Can't remove the value %d of config element %s: value not found.",val,name);
 }
 
@@ -871,7 +847,7 @@ void xbt_cfg_rm_double(xbt_cfg_t cfg,const char*name, double val) {
     }
   }
 
-  THROW2(mismatch_error,0,
+  THROW2(not_found_error,0,
         "Can't remove the value %f of config element %s: value not found.",val,name);
 }
 
@@ -903,7 +879,7 @@ xbt_cfg_rm_string(xbt_cfg_t cfg,const char*name, const char *val) {
     }
   }
 
-  THROW2(mismatch_error,0,
+  THROW2(not_found_error,0,
         "Can't remove the value %s of config element %s: value not found.",val,name);
 }
 
@@ -936,7 +912,7 @@ xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
     }
   }
 
-  THROW3(mismatch_error,0,
+  THROW3(not_found_error,0,
         "Can't remove the value %s:%d of config element %s: value not found.",
         host,port,name);
 }
@@ -966,18 +942,18 @@ void xbt_cfg_rm_at   (xbt_cfg_t cfg, const char *name, int pos) {
 
 void
 xbt_cfg_empty(xbt_cfg_t cfg,const char*name) {
-  xbt_cfgelm_t variable;
+  xbt_cfgelm_t variable=NULL;
   xbt_ex_t e;
 
   TRY {
     variable = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
-      xbt_ex_free(e);
-      THROW1(mismatch_error,0,
-            "Can't empty  '%s' since this config element does not exist", name);
-    }
-    RETHROW;
+    if (e.category != not_found_error)
+      RETHROW;
+
+    xbt_ex_free(e);
+    THROW1(not_found_error,0,
+          "Can't empty  '%s' since this config element does not exist", name);
   }
 
   if (variable) {
@@ -1109,15 +1085,15 @@ void xbt_cfg_get_host  (xbt_cfg_t   cfg,  const char *name,
  * \warning the returned value is the actual content of the config set
  */
 xbt_dynar_t xbt_cfg_get_dynar (xbt_cfg_t    cfg, const char *name) {
-  xbt_cfgelm_t variable;
+  xbt_cfgelm_t variable=NULL;
   xbt_ex_t     e;
 
   TRY {
     variable = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
+    if (e.category == not_found_error) {
       xbt_ex_free(e);
-      THROW1(mismatch_error,0,
+      THROW1(not_found_error,0,
             "No registered variable %s in this config set",name);
     }
     RETHROW;
@@ -1163,3 +1139,114 @@ xbt_cfg_get_host_at(xbt_cfg_t cfg, const char *name, int pos,
   *port = val->port;
   *host = val->name;
 }
+
+
+#ifdef SIMGRID_TEST
+#include "xbt.h"
+#include "xbt/ex.h"
+
+XBT_TEST_SUITE("config","Configuration support");
+
+static xbt_cfg_t make_set(){
+  xbt_cfg_t set=NULL; 
+
+  set = xbt_cfg_new();
+  xbt_cfg_register_str(set,"speed:1_to_2_int");
+  xbt_cfg_register_str(set,"hostname:1_to_1_string");
+  xbt_cfg_register_str(set,"user:1_to_10_string");
+
+  return set;
+} /* end_of_make_set */
+
+XBT_TEST_UNIT("memuse",test_config_memuse,"Alloc and free a config set") {
+  xbt_cfg_t set=make_set();
+  xbt_test_add0("Alloc and free a config set");
+  xbt_cfg_set_parse(set, "hostname:veloce user:mquinson\nuser:oaumage\tuser:alegrand");
+  xbt_cfg_free(&set);
+  xbt_cfg_free(&set);
+}
+
+XBT_TEST_UNIT("validation",test_config_validation,"Validation tests") {
+  xbt_cfg_t set = set=make_set();
+  xbt_ex_t e;
+  
+  xbt_test_add0("Having too few elements for speed");
+  xbt_cfg_set_parse(set, "hostname:veloce user:mquinson\nuser:oaumage\tuser:alegrand");
+  TRY {
+    xbt_cfg_check(set);
+  } CATCH(e) {
+    if (e.category != mismatch_error || 
+       strncmp(e.msg,"Config elem speed needs",strlen("Config elem speed needs")))
+      xbt_test_fail1("Got an exception. msg=%s",e.msg);
+    xbt_ex_free(e);
+  }
+  xbt_cfg_free(&set);
+  xbt_cfg_free(&set);
+
+
+
+  xbt_test_add0("Having too much values of 'speed'");
+  set=make_set(); 
+  xbt_cfg_set_parse(set,"hostname:toto:42 user:alegrand");
+  TRY {
+    xbt_cfg_set_parse(set,"speed:42 speed:24 speed:34");
+  } CATCH(e) {
+    if (e.category != mismatch_error ||
+       strncmp(e.msg,"Cannot add value 34 to the config elem speed",
+               strlen("Config elem speed needs")))
+      xbt_test_fail1("Got an exception. msg=%s",e.msg);
+    xbt_ex_free(e);
+  }
+  xbt_cfg_check(set);
+  xbt_cfg_free(&set);
+  xbt_cfg_free(&set);
+
+}
+
+XBT_TEST_UNIT("use",test_config_use,"Data retrieving tests") {
+  xbt_cfg_t set = set=make_set();
+
+  xbt_test_add0("Get a single value");
+  {    
+    /* get_single_value */
+    int ival;
+    xbt_cfg_t myset=make_set();
+    
+    xbt_cfg_set_parse(myset,"hostname:toto:42 speed:42");
+    ival = xbt_cfg_get_int(myset,"speed"); 
+    if (ival != 42) 
+      xbt_test_fail1("Speed value = %d, I expected 42",ival);
+    xbt_cfg_free(&myset);
+  }
+
+  xbt_test_add0("Get multiple values");
+  {    
+    /* get_multiple_value */
+    xbt_dynar_t dyn; 
+    xbt_cfg_t myset=make_set();
+    
+    xbt_cfg_set_parse(myset, "hostname:veloce user:foo\nuser:bar\tuser:toto");
+    xbt_cfg_set_parse(myset,"speed:42");
+    xbt_cfg_check(myset); 
+    dyn = xbt_cfg_get_dynar(myset,"user");
+
+    if (xbt_dynar_length(dyn) != 3) 
+      xbt_test_fail1("Dynar length = %d, I expected 3",
+                    (int)xbt_dynar_length(dyn));
+
+    if (strcmp(xbt_dynar_get_as(dyn,0,char*),"foo"))
+      xbt_test_fail1("Dynar[0] = %s, I expected foo",
+                    xbt_dynar_get_as(dyn,0,char*));
+
+    if (strcmp(xbt_dynar_get_as(dyn,1,char*),"bar"))
+      xbt_test_fail1("Dynar[1] = %s, I expected bar",
+                    xbt_dynar_get_as(dyn,1,char*));
+
+    if (strcmp(xbt_dynar_get_as(dyn,2,char*),"toto"))
+      xbt_test_fail1("Dynar[2] = %s, I expected toto",
+                    xbt_dynar_get_as(dyn,2,char*));
+    
+  }
+}
+#endif /* SIMGRID_TEST */