提交 6381c89f 编写于 作者: D Daniel P. Berrange

virconf: add typed value accessor methods

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: NDaniel P. Berrange <berrange@redhat.com>
上级 fe2d3729
...@@ -1393,6 +1393,16 @@ virRun; ...@@ -1393,6 +1393,16 @@ virRun;
virConfFree; virConfFree;
virConfFreeValue; virConfFreeValue;
virConfGetValue; virConfGetValue;
virConfGetValueBool;
virConfGetValueInt;
virConfGetValueLLong;
virConfGetValueSizeT;
virConfGetValueSSizeT;
virConfGetValueString;
virConfGetValueStringList;
virConfGetValueType;
virConfGetValueUInt;
virConfGetValueULLong;
virConfLoadConfig; virConfLoadConfig;
virConfNew; virConfNew;
virConfReadFile; virConfReadFile;
......
...@@ -99,7 +99,7 @@ struct _virConfEntry { ...@@ -99,7 +99,7 @@ struct _virConfEntry {
}; };
struct _virConf { struct _virConf {
const char* filename; char *filename;
unsigned int flags; unsigned int flags;
virConfEntryPtr entries; virConfEntryPtr entries;
}; };
...@@ -204,10 +204,15 @@ static virConfPtr ...@@ -204,10 +204,15 @@ static virConfPtr
virConfCreate(const char *filename, unsigned int flags) virConfCreate(const char *filename, unsigned int flags)
{ {
virConfPtr ret = virConfNew(); virConfPtr ret = virConfNew();
if (ret) { if (!ret)
ret->filename = filename; return NULL;
ret->flags = flags;
if (VIR_STRDUP(ret->filename, filename) < 0) {
VIR_FREE(ret);
return NULL;
} }
ret->flags = flags;
return ret; return ret;
} }
...@@ -233,6 +238,7 @@ virConfAddEntry(virConfPtr conf, char *name, virConfValuePtr value, char *comm) ...@@ -233,6 +238,7 @@ virConfAddEntry(virConfPtr conf, char *name, virConfValuePtr value, char *comm)
if ((comm == NULL) && (name == NULL)) if ((comm == NULL) && (name == NULL))
return NULL; return NULL;
VIR_DEBUG("Add entry %s %p", name, value);
if (VIR_ALLOC(ret) < 0) if (VIR_ALLOC(ret) < 0)
return NULL; return NULL;
...@@ -275,8 +281,10 @@ virConfSaveValue(virBufferPtr buf, virConfValuePtr val) ...@@ -275,8 +281,10 @@ virConfSaveValue(virBufferPtr buf, virConfValuePtr val)
case VIR_CONF_NONE: case VIR_CONF_NONE:
return -1; return -1;
case VIR_CONF_LONG: case VIR_CONF_LONG:
virBufferAsprintf(buf, "%lld", val->l);
break;
case VIR_CONF_ULONG: case VIR_CONF_ULONG:
virBufferAsprintf(buf, "%ld", val->l); virBufferAsprintf(buf, "%llu", val->l);
break; break;
case VIR_CONF_STRING: case VIR_CONF_STRING:
if (strchr(val->str, '\n') != NULL) { if (strchr(val->str, '\n') != NULL) {
...@@ -843,6 +851,7 @@ virConfFree(virConfPtr conf) ...@@ -843,6 +851,7 @@ virConfFree(virConfPtr conf)
VIR_FREE(tmp); VIR_FREE(tmp);
tmp = next; tmp = next;
} }
VIR_FREE(conf->filename);
VIR_FREE(conf); VIR_FREE(conf);
return 0; return 0;
} }
...@@ -877,6 +886,487 @@ virConfGetValue(virConfPtr conf, const char *setting) ...@@ -877,6 +886,487 @@ virConfGetValue(virConfPtr conf, const char *setting)
return NULL; 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: * virConfSetValue:
* @conf: a configuration file handle * @conf: a configuration file handle
......
...@@ -61,7 +61,7 @@ typedef virConfValue *virConfValuePtr; ...@@ -61,7 +61,7 @@ typedef virConfValue *virConfValuePtr;
struct _virConfValue { struct _virConfValue {
virConfType type; /* the virConfType */ virConfType type; /* the virConfType */
virConfValuePtr next; /* next element if in a list */ 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 */ char *str; /* pointer to 0 terminated string */
virConfValuePtr list; /* list of a list */ virConfValuePtr list; /* list of a list */
}; };
...@@ -85,6 +85,38 @@ int virConfFree(virConfPtr conf); ...@@ -85,6 +85,38 @@ int virConfFree(virConfPtr conf);
void virConfFreeValue(virConfValuePtr val); void virConfFreeValue(virConfValuePtr val);
virConfValuePtr virConfGetValue(virConfPtr conf, virConfValuePtr virConfGetValue(virConfPtr conf,
const char *setting); 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, int virConfSetValue(virConfPtr conf,
const char *setting, const char *setting,
virConfValuePtr value); virConfValuePtr value);
......
...@@ -77,6 +77,329 @@ static int testConfRoundTrip(const void *opaque) ...@@ -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 static int
mymain(void) mymain(void)
{ {
...@@ -91,6 +414,18 @@ mymain(void) ...@@ -91,6 +414,18 @@ mymain(void)
if (virTestRun("no-newline", testConfRoundTrip, "no-newline") < 0) if (virTestRun("no-newline", testConfRoundTrip, "no-newline") < 0)
ret = -1; 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; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册