[libvirt] [PATCH 03/16] virconf: add typed value accessor methods

Daniel P. Berrange berrange at redhat.com
Mon Jul 11 09:45:22 UTC 2016


Currently many users of virConf APIs are defining the same
macros for calling virConfValue() and then doing type
checking. To remove this repeated code, add a set of
typesafe accessor methods.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/libvirt_private.syms |  10 +
 src/util/virconf.c       | 500 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/util/virconf.h       |  34 +++-
 tests/virconftest.c      | 335 +++++++++++++++++++++++++++++++
 4 files changed, 873 insertions(+), 6 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ad0af76..597ce5f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1393,6 +1393,16 @@ virRun;
 virConfFree;
 virConfFreeValue;
 virConfGetValue;
+virConfGetValueBool;
+virConfGetValueInt;
+virConfGetValueLLong;
+virConfGetValueSizeT;
+virConfGetValueSSizeT;
+virConfGetValueString;
+virConfGetValueStringList;
+virConfGetValueType;
+virConfGetValueUInt;
+virConfGetValueULLong;
 virConfLoadConfig;
 virConfNew;
 virConfReadFile;
diff --git a/src/util/virconf.c b/src/util/virconf.c
index 33e7744..5085768 100644
--- a/src/util/virconf.c
+++ b/src/util/virconf.c
@@ -99,7 +99,7 @@ struct _virConfEntry {
 };
 
 struct _virConf {
-    const char* filename;
+    char *filename;
     unsigned int flags;
     virConfEntryPtr entries;
 };
@@ -204,10 +204,15 @@ static virConfPtr
 virConfCreate(const char *filename, unsigned int flags)
 {
     virConfPtr ret = virConfNew();
-    if (ret) {
-        ret->filename = filename;
-        ret->flags = flags;
+    if (!ret)
+        return NULL;
+
+    if (VIR_STRDUP(ret->filename, filename) < 0) {
+        VIR_FREE(ret);
+        return NULL;
     }
+
+    ret->flags = flags;
     return ret;
 }
 
@@ -233,6 +238,7 @@ virConfAddEntry(virConfPtr conf, char *name, virConfValuePtr value, char *comm)
     if ((comm == NULL) && (name == NULL))
         return NULL;
 
+    VIR_DEBUG("Add entry %s %p", name, value);
     if (VIR_ALLOC(ret) < 0)
         return NULL;
 
@@ -275,8 +281,10 @@ virConfSaveValue(virBufferPtr buf, virConfValuePtr val)
         case VIR_CONF_NONE:
             return -1;
         case VIR_CONF_LONG:
+            virBufferAsprintf(buf, "%lld", val->l);
+            break;
         case VIR_CONF_ULONG:
-            virBufferAsprintf(buf, "%ld", val->l);
+            virBufferAsprintf(buf, "%llu", val->l);
             break;
         case VIR_CONF_STRING:
             if (strchr(val->str, '\n') != NULL) {
@@ -843,6 +851,7 @@ virConfFree(virConfPtr conf)
         VIR_FREE(tmp);
         tmp = next;
     }
+    VIR_FREE(conf->filename);
     VIR_FREE(conf);
     return 0;
 }
@@ -877,6 +886,487 @@ virConfGetValue(virConfPtr conf, const char *setting)
     return NULL;
 }
 
+
+/**
+ * virConfGetValueType:
+ * @conf: the config object
+ * @setting: the config entry name
+ *
+ * Query the type of the configuration entry @setting.
+ *
+ * Returns: the entry type, or VIR_CONF_NONE if not set.
+ */
+virConfType virConfGetValueType(virConfPtr conf,
+                                const char *setting)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+    if (!cval)
+        return VIR_CONF_NONE;
+
+    return cval->type;
+}
+
+
+/**
+ * virConfGetValueString:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold string value
+ *
+ * Get the string value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type.
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueString(virConfPtr conf,
+                          const char *setting,
+                          char **value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value string %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_STRING) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected a string for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    VIR_FREE(*value);
+    if (VIR_STRDUP(*value, cval->str) < 0)
+        return -1;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueStringList:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @compatString: true to treat string entry as a 1 element list
+ * @value: pointer to hold NULL terminated string list
+ *
+ * Get the string list value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified. If @compatString is set to true
+ * and the value is present as a string, this will be turned into
+ * a 1 element list. The returned @value will be NULL terminated
+ * if set.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type.
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueStringList(virConfPtr conf,
+                              const char *setting,
+                              bool compatString,
+                              char ***values)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+    size_t len;
+    virConfValuePtr eval;
+
+    VIR_DEBUG("Get value string list %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    virStringFreeList(*values);
+    *values = NULL;
+
+    switch (cval->type) {
+    case VIR_CONF_LIST:
+        /* Calc length and check items */
+        for (len = 0, eval = cval->list; eval; len++, eval = eval->next) {
+            if (eval->type != VIR_CONF_STRING) {
+                virReportError(VIR_ERR_CONF_SYNTAX,
+                               _("%s: expected a string list for '%s' parameter"),
+                               conf->filename, setting);
+                return -1;
+            }
+        }
+
+        if (VIR_ALLOC_N(*values, len + 1) < 0)
+            return -1;
+
+        for (len = 0, eval = cval->list; eval; len++, eval = eval->next) {
+            if (VIR_STRDUP((*values)[len], eval->str) < 0) {
+                virStringFreeList(*values);
+                *values = NULL;
+                return -1;
+            }
+        }
+        break;
+
+    case VIR_CONF_STRING:
+        if (compatString) {
+            if (VIR_ALLOC_N(*values, cval->str ? 2 : 1) < 0)
+                return -1;
+            if (cval->str &&
+                VIR_STRDUP((*values)[0], cval->str) < 0) {
+                VIR_FREE(values);
+                return -1;
+            }
+            break;
+        }
+        /* fallthrough */
+
+    default:
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       compatString ?
+                       _("%s: expected a string or string list for '%s' parameter") :
+                       _("%s: expected a string list for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueBool:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold boolean value
+ *
+ * Get the boolean value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type, or if the value set is not 1 or 0.
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueBool(virConfPtr conf,
+                        const char *setting,
+                        bool *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value bool %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected a bool for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    if (cval->l < 0 || cval->l > 1) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: value for '%s' parameter must be 0 or 1"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    *value = cval->l == 1;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueInt:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold integer value
+ *
+ * Get the integer value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type, or if the value is outside the
+ * range that can be stored in an 'int'
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueInt(virConfPtr conf,
+                       const char *setting,
+                       int *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value int %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_LONG &&
+        cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected a signed integer for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    if (cval->l > INT_MAX || cval->l < INT_MIN) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: value for '%s' parameter must be in range %d:%d"),
+                       conf->filename, setting, INT_MIN, INT_MAX);
+        return -1;
+    }
+
+    *value = cval->l;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueUInt:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold integer value
+ *
+ * Get the unsigned integer value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type, or if the value is outside the
+ * range that can be stored in an 'unsigned int'
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueUInt(virConfPtr conf,
+                        const char *setting,
+                        unsigned int *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value uint %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected an unsigned integer for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    if (cval->l > UINT_MAX || cval->l < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: value for '%s' parameter must be in range 0:%u"),
+                       conf->filename, setting, UINT_MAX);
+        return -1;
+    }
+
+    *value = cval->l;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueSizeT:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold integer value
+ *
+ * Get the integer value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type, or if the value is outside the
+ * range that can be stored in a 'size_t'
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueSizeT(virConfPtr conf,
+                         const char *setting,
+                         size_t *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value size_t %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected an unsigned integer for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    if (cval->l > SIZE_MAX || cval->l < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: value for '%s' parameter must be in range 0:%zu"),
+                       conf->filename, setting, SIZE_MAX);
+        return -1;
+    }
+
+    *value = cval->l;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueSSizeT:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold integer value
+ *
+ * Get the integer value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type, or if the value is outside the
+ * range that can be stored in an 'ssize_t'
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueSSizeT(virConfPtr conf,
+                          const char *setting,
+                          ssize_t *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value ssize_t %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_LONG &&
+        cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected a signed integer for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    if (cval->l > SSIZE_MAX || cval->l < (-SSIZE_MAX - 1)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: value for '%s' parameter must be in range %zd:%zd"),
+                       conf->filename, setting, -SSIZE_MAX - 1, SSIZE_MAX);
+        return -1;
+    }
+
+    *value = cval->l;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueLLong:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold integer value
+ *
+ * Get the integer value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type, or if the value is outside the
+ * range that can be stored in an 'long long'
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueLLong(virConfPtr conf,
+                        const char *setting,
+                        long long *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value long long %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_LONG &&
+        cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected a signed integer for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    if (cval->type == VIR_CONF_ULONG &&
+        cval->l > LLONG_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: value for '%s' parameter must be in range 0:%lld"),
+                       conf->filename, setting, LLONG_MAX);
+        return -1;
+    }
+
+    *value = cval->l;
+
+    return 1;
+}
+
+
+/**
+ * virConfGetValueULongLong:
+ * @conf: the config object
+ * @setting: the config entry name
+ * @value: pointer to hold integer value
+ *
+ * Get the integer value of the config name @setting, storing
+ * it in @value. If the config entry is not present, then
+ * @value will be unmodified.
+ *
+ * Reports an error if the config entry is set but has
+ * an unexpected type.
+ *
+ * Returns: 1 if the value was present, 0 if missing, -1 on error
+ */
+int virConfGetValueULLong(virConfPtr conf,
+                          const char *setting,
+                          unsigned long long *value)
+{
+    virConfValuePtr cval = virConfGetValue(conf, setting);
+
+    VIR_DEBUG("Get value unsigned long long %p %d",
+              cval, cval ? cval->type : VIR_CONF_NONE);
+
+    if (!cval)
+        return 0;
+
+    if (cval->type != VIR_CONF_LONG &&
+        cval->type != VIR_CONF_ULONG) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("%s: expected an unsigned integer for '%s' parameter"),
+                       conf->filename, setting);
+        return -1;
+    }
+
+    *value = cval->l;
+
+    return 1;
+}
+
 /**
  * virConfSetValue:
  * @conf: a configuration file handle
diff --git a/src/util/virconf.h b/src/util/virconf.h
index 239ab39..ccae9d9 100644
--- a/src/util/virconf.h
+++ b/src/util/virconf.h
@@ -61,7 +61,7 @@ typedef virConfValue *virConfValuePtr;
 struct _virConfValue {
     virConfType type;		/* the virConfType */
     virConfValuePtr next;	/* next element if in a list */
-    long  l;			/* long integer */
+    long long  l;		/* very long integer */
     char *str;			/* pointer to 0 terminated string */
     virConfValuePtr list;	/* list of a list */
 };
@@ -85,6 +85,38 @@ int virConfFree(virConfPtr conf);
 void virConfFreeValue(virConfValuePtr val);
 virConfValuePtr virConfGetValue(virConfPtr conf,
                                 const char *setting);
+
+virConfType virConfGetValueType(virConfPtr conf,
+                                const char *setting);
+int virConfGetValueString(virConfPtr conf,
+                          const char *setting,
+                          char **value);
+int virConfGetValueStringList(virConfPtr conf,
+                              const char *setting,
+                              bool compatString,
+                              char ***values);
+int virConfGetValueBool(virConfPtr conf,
+                        const char *setting,
+                        bool *value);
+int virConfGetValueInt(virConfPtr conf,
+                       const char *setting,
+                       int *value);
+int virConfGetValueUInt(virConfPtr conf,
+                        const char *setting,
+                        unsigned int *value);
+int virConfGetValueSizeT(virConfPtr conf,
+                         const char *setting,
+                         size_t *value);
+int virConfGetValueSSizeT(virConfPtr conf,
+                          const char *setting,
+                          ssize_t *value);
+int virConfGetValueLLong(virConfPtr conf,
+                        const char *setting,
+                        long long *value);
+int virConfGetValueULLong(virConfPtr conf,
+                          const char *setting,
+                          unsigned long long *value);
+
 int virConfSetValue(virConfPtr conf,
                     const char *setting,
                     virConfValuePtr value);
diff --git a/tests/virconftest.c b/tests/virconftest.c
index c71b491..d9ebda4 100644
--- a/tests/virconftest.c
+++ b/tests/virconftest.c
@@ -77,6 +77,329 @@ static int testConfRoundTrip(const void *opaque)
 }
 
 
+static int testConfParseInt(const void *opaque ATTRIBUTE_UNUSED)
+{
+    const char *srcdata =                       \
+        "int = -1729\n"                         \
+        "uint = 1729\n"                         \
+        "llong = -6963472309248\n"              \
+        "ullong = 6963472309248\n"              \
+        "size_t = 87539319\n"                   \
+        "ssize_t = -87539319\n"                 \
+        "string = \"foo\"\n";
+
+    int ret = -1;
+    virConfPtr conf = virConfReadMem(srcdata, strlen(srcdata), 0);
+    int iv;
+    unsigned int ui;
+    size_t s;
+    ssize_t ss;
+    long long l;
+    unsigned long long ul;
+
+    if (!conf)
+        return -1;
+
+    if (virConfGetValueType(conf, "int") !=
+        VIR_CONF_LONG) {
+        fprintf(stderr, "expected a long for 'int'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueInt(conf, "int", &iv) < 0)
+        goto cleanup;
+
+    if (iv != -1729) {
+        fprintf(stderr, "Expected -1729 got %d\n", iv);
+        goto cleanup;
+    }
+
+    if (virConfGetValueInt(conf, "string", &iv) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+
+    if (virConfGetValueType(conf, "uint") !=
+        VIR_CONF_ULONG) {
+        fprintf(stderr, "expected a unsigned long for 'uint'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueUInt(conf, "uint", &ui) < 0)
+        goto cleanup;
+
+    if (ui != 1729) {
+        fprintf(stderr, "Expected 1729 got %u\n", ui);
+        goto cleanup;
+    }
+
+    if (virConfGetValueUInt(conf, "string", &ui) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+
+
+    if (virConfGetValueType(conf, "llong") !=
+        VIR_CONF_LONG) {
+        fprintf(stderr, "expected a long for 'llong'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueLLong(conf, "llong", &l) < 0)
+        goto cleanup;
+
+    if (l != -6963472309248) {
+        fprintf(stderr, "Expected -6963472309248 got %lld\n", l);
+        goto cleanup;
+    }
+
+    if (virConfGetValueLLong(conf, "string", &l) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+
+
+    if (virConfGetValueType(conf, "ullong") !=
+        VIR_CONF_ULONG) {
+        fprintf(stderr, "expected a unsigned long for 'ullong'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueULLong(conf, "ullong", &ul) < 0)
+        goto cleanup;
+
+    if (ul != 6963472309248) {
+        fprintf(stderr, "Expected 6963472309248 got %llu\n", ul);
+        goto cleanup;
+    }
+
+    if (virConfGetValueULLong(conf, "string", &ul) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+
+
+    if (virConfGetValueType(conf, "size_t") !=
+        VIR_CONF_ULONG) {
+        fprintf(stderr, "expected a unsigned long for 'size_T'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueSizeT(conf, "size_t", &s) < 0)
+        goto cleanup;
+
+    if (s != 87539319) {
+        fprintf(stderr, "Expected 87539319 got %zu\n", s);
+        goto cleanup;
+    }
+
+    if (virConfGetValueSizeT(conf, "string", &s) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+
+
+    if (virConfGetValueType(conf, "ssize_t") !=
+        VIR_CONF_LONG) {
+        fprintf(stderr, "expected a unsigned long for 'ssize_t'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueSSizeT(conf, "ssize_t", &ss) < 0)
+        goto cleanup;
+
+    if (ss != -87539319) {
+        fprintf(stderr, "Expected -87539319 got %zd\n", ss);
+        goto cleanup;
+    }
+
+    if (virConfGetValueSSizeT(conf, "string", &ss) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    virConfFree(conf);
+    return ret;
+}
+
+static int testConfParseBool(const void *opaque ATTRIBUTE_UNUSED)
+{
+    const char *srcdata =                         \
+        "false = 0\n"                             \
+        "true = 1\n"                              \
+        "int = 6963472309248\n"                   \
+        "string = \"foo\"\n";
+
+    int ret = -1;
+    virConfPtr conf = virConfReadMem(srcdata, strlen(srcdata), 0);
+    bool f = true;
+    bool t = false;
+
+    if (!conf)
+        return -1;
+
+    if (virConfGetValueType(conf, "false") !=
+        VIR_CONF_ULONG) {
+        fprintf(stderr, "expected a long for 'false'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueBool(conf, "false", &f) < 0)
+        goto cleanup;
+
+    if (f != false) {
+        fprintf(stderr, "Expected 0 got %d\n", f);
+        goto cleanup;
+    }
+
+
+
+    if (virConfGetValueType(conf, "true") !=
+        VIR_CONF_ULONG) {
+        fprintf(stderr, "expected a long for 'true'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueBool(conf, "true", &t) < 0)
+        goto cleanup;
+
+    if (t != true) {
+        fprintf(stderr, "Expected 1 got %d\n", t);
+        goto cleanup;
+    }
+
+
+
+    if (virConfGetValueBool(conf, "int", &t) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueBool(conf, "string", &t) != -1) {
+        fprintf(stderr, "Expected error for 'string' param\n");
+        goto cleanup;
+    }
+
+
+    ret = 0;
+ cleanup:
+    virConfFree(conf);
+    return ret;
+}
+
+
+static int testConfParseString(const void *opaque ATTRIBUTE_UNUSED)
+{
+    const char *srcdata =                         \
+        "int = 6963472309248\n"                   \
+        "string = \"foo\"\n";
+
+    int ret = -1;
+    virConfPtr conf = virConfReadMem(srcdata, strlen(srcdata), 0);
+    char *str = NULL;
+
+    if (!conf)
+        return -1;
+
+    if (virConfGetValueType(conf, "string") !=
+        VIR_CONF_STRING) {
+        fprintf(stderr, "expected a string for 'string'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueString(conf, "string", &str) < 0)
+        goto cleanup;
+
+    if (STRNEQ_NULLABLE(str, "foo")) {
+        fprintf(stderr, "Expected 'foo' got '%s'\n", str);
+        goto cleanup;
+    }
+
+    if (virConfGetValueString(conf, "int", &str) != -1) {
+        fprintf(stderr, "Expected error for 'int'\n");
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(str);
+    virConfFree(conf);
+    return ret;
+}
+
+
+static int testConfParseStringList(const void *opaque ATTRIBUTE_UNUSED)
+{
+    const char *srcdata =                         \
+        "string_list = [\"foo\", \"bar\"]\n"      \
+        "string = \"foo\"\n";
+
+    int ret = -1;
+    virConfPtr conf = virConfReadMem(srcdata, strlen(srcdata), 0);
+    char **str = NULL;
+
+    if (!conf)
+        return -1;
+
+    if (virConfGetValueType(conf, "string_list") !=
+        VIR_CONF_LIST) {
+        fprintf(stderr, "expected a list for 'string_list'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueStringList(conf, "string_list", false, &str) < 0)
+        goto cleanup;
+
+    if (virStringListLength((const char *const*)str) != 2) {
+        fprintf(stderr, "expected a 2 element list\n");
+        goto cleanup;
+    }
+
+    if (STRNEQ_NULLABLE(str[0], "foo")) {
+        fprintf(stderr, "Expected 'foo' got '%s'\n", str[0]);
+        goto cleanup;
+    }
+
+    if (STRNEQ_NULLABLE(str[1], "bar")) {
+        fprintf(stderr, "Expected 'bar' got '%s'\n", str[1]);
+        goto cleanup;
+    }
+
+
+    if (virConfGetValueStringList(conf, "string", false, &str) != -1) {
+        fprintf(stderr, "Expected error for 'string'\n");
+        goto cleanup;
+    }
+
+    if (virConfGetValueStringList(conf, "string", true, &str) < 0)
+        goto cleanup;
+
+    if (virStringListLength((const char *const*)str) != 1) {
+        fprintf(stderr, "expected a 1 element list\n");
+        goto cleanup;
+    }
+
+    if (STRNEQ_NULLABLE(str[0], "foo")) {
+        fprintf(stderr, "Expected 'foo' got '%s'\n", str[0]);
+        goto cleanup;
+    }
+
+
+    ret = 0;
+ cleanup:
+    virStringFreeList(str);
+    virConfFree(conf);
+    return ret;
+}
+
+
 static int
 mymain(void)
 {
@@ -91,6 +414,18 @@ mymain(void)
     if (virTestRun("no-newline", testConfRoundTrip, "no-newline") < 0)
         ret = -1;
 
+    if (virTestRun("int", testConfParseInt, NULL) < 0)
+        ret = -1;
+
+    if (virTestRun("bool", testConfParseBool, NULL) < 0)
+        ret = -1;
+
+    if (virTestRun("string", testConfParseString, NULL) < 0)
+        ret = -1;
+
+    if (virTestRun("string-list", testConfParseStringList, NULL) < 0)
+        ret = -1;
+
     return ret;
 }
 
-- 
2.7.4




More information about the libvir-list mailing list