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(a)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