mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-27 16:15:23 +00:00
4ceac4bf29
We use the "vir" prefix pretty consistently in our APIs, both external and internal, which made these macros stood out.
312 lines
8.2 KiB
C
312 lines
8.2 KiB
C
/*
|
|
* Copyright (C) 2013 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Peter Krempa <pkrempa@redhat.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "testutils.h"
|
|
|
|
#include "virerror.h"
|
|
#include "virxml.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
static const char metadata1[] =
|
|
"<derp xmlns:foobar='http://foo.bar/'>\n"
|
|
" <bar>foobar</bar>\n"
|
|
" <foo fooish='blurb'>foofoo</foo>\n"
|
|
" <foobar:baz>zomg</foobar:baz>\n"
|
|
"</derp>";
|
|
|
|
|
|
static const char metadata1_ns[] =
|
|
"<herp:derp xmlns:foobar='http://foo.bar/' xmlns:herp='http://herp.derp/'>\n"
|
|
" <herp:bar>foobar</herp:bar>\n"
|
|
" <herp:foo fooish='blurb'>foofoo</herp:foo>\n"
|
|
" <foobar:baz>zomg</foobar:baz>\n"
|
|
"</herp:derp>";
|
|
|
|
|
|
static const char metadata2[] =
|
|
"<foo>\n"
|
|
" <bar>baz</bar>\n"
|
|
"</foo>";
|
|
|
|
|
|
static const char metadata2_ns[] =
|
|
"<blurb:foo xmlns:blurb='http://herp.derp/'>\n"
|
|
" <blurb:bar>baz</blurb:bar>\n"
|
|
"</blurb:foo>";
|
|
|
|
|
|
static char *
|
|
getMetadataFromXML(virDomainPtr dom)
|
|
{
|
|
xmlDocPtr doc = NULL;
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
xmlNodePtr node;
|
|
|
|
char *xml = NULL;
|
|
char *ret = NULL;
|
|
|
|
if (!(xml = virDomainGetXMLDesc(dom, 0)))
|
|
goto cleanup;
|
|
|
|
if (!(doc = virXMLParseStringCtxt(xml, "(domain_definition)", &ctxt)))
|
|
goto cleanup;
|
|
|
|
if (!(node = virXPathNode("//metadata/*", ctxt)))
|
|
goto cleanup;
|
|
|
|
ret = virXMLNodeToString(node->doc, node);
|
|
|
|
cleanup:
|
|
VIR_FREE(xml);
|
|
xmlFreeDoc(doc);
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void
|
|
metadataXMLConvertApostrophe(char *str)
|
|
{
|
|
do {
|
|
if (*str == '\"')
|
|
*str = '\'';
|
|
} while ((*++str) != '\0');
|
|
}
|
|
|
|
|
|
static bool
|
|
verifyMetadata(virDomainPtr dom,
|
|
const char *expectXML,
|
|
const char *expectAPI,
|
|
const char *uri)
|
|
{
|
|
bool ret = false;
|
|
char *metadataXML = NULL;
|
|
char *metadataAPI = NULL;
|
|
|
|
if (!expectAPI) {
|
|
if ((metadataAPI = virDomainGetMetadata(dom,
|
|
VIR_DOMAIN_METADATA_ELEMENT,
|
|
uri, 0))) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"expected no metadata in API, but got:\n[%s]",
|
|
metadataAPI);
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
if (!(metadataAPI = virDomainGetMetadata(dom,
|
|
VIR_DOMAIN_METADATA_ELEMENT,
|
|
uri, 0)))
|
|
goto cleanup;
|
|
|
|
metadataXMLConvertApostrophe(metadataAPI);
|
|
|
|
if (STRNEQ(metadataAPI, expectAPI)) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"XML metadata in API doesn't match expected metadata: "
|
|
"expected:\n[%s]\ngot:\n[%s]",
|
|
expectAPI, metadataAPI);
|
|
goto cleanup;
|
|
}
|
|
|
|
}
|
|
|
|
if (!expectXML) {
|
|
if ((metadataXML = getMetadataFromXML(dom))) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"expected no metadata in XML, but got:\n[%s]",
|
|
metadataXML);
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
if (!(metadataXML = getMetadataFromXML(dom)))
|
|
goto cleanup;
|
|
|
|
metadataXMLConvertApostrophe(metadataXML);
|
|
|
|
if (STRNEQ(metadataXML, expectXML)) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"XML in dump doesn't match expected metadata: "
|
|
"expected:\n[%s]\ngot:\n[%s]",
|
|
expectXML, metadataXML);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
ret = true;
|
|
|
|
cleanup:
|
|
VIR_FREE(metadataXML);
|
|
VIR_FREE(metadataAPI);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
struct metadataTest {
|
|
virConnectPtr conn;
|
|
virDomainPtr dom;
|
|
|
|
const char *data;
|
|
int type;
|
|
bool fail;
|
|
};
|
|
|
|
|
|
static int
|
|
testAssignMetadata(const void *data)
|
|
{
|
|
const struct metadataTest *test = data;
|
|
|
|
if (virDomainSetMetadata(test->dom, VIR_DOMAIN_METADATA_ELEMENT,
|
|
metadata1, "herp", "http://herp.derp/", 0) < 0)
|
|
return -1;
|
|
|
|
if (!verifyMetadata(test->dom, metadata1_ns, metadata1, "http://herp.derp/"))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
testRewriteMetadata(const void *data)
|
|
{
|
|
const struct metadataTest *test = data;
|
|
|
|
if (virDomainSetMetadata(test->dom, VIR_DOMAIN_METADATA_ELEMENT,
|
|
metadata2, "blurb", "http://herp.derp/", 0) < 0)
|
|
return -1;
|
|
|
|
if (!verifyMetadata(test->dom, metadata2_ns, metadata2, "http://herp.derp/"))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
testEraseMetadata(const void *data)
|
|
{
|
|
const struct metadataTest *test = data;
|
|
|
|
if (virDomainSetMetadata(test->dom, VIR_DOMAIN_METADATA_ELEMENT,
|
|
NULL, NULL, "http://herp.derp/", 0) < 0)
|
|
return -1;
|
|
|
|
if (!verifyMetadata(test->dom, NULL, NULL, "http://herp.derp/"))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
testTextMetadata(const void *data)
|
|
{
|
|
const struct metadataTest *test = data;
|
|
char *actual = NULL;
|
|
int ret = -1;
|
|
|
|
if (virDomainSetMetadata(test->dom, test->type, test->data, NULL, NULL, 0) < 0) {
|
|
if (test->fail)
|
|
return 0;
|
|
return -1;
|
|
}
|
|
|
|
actual = virDomainGetMetadata(test->dom, test->type, NULL, 0);
|
|
|
|
if (STRNEQ_NULLABLE(test->data, actual)) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"expected metadata doesn't match actual: "
|
|
"expected:'%s'\ngot: '%s'",
|
|
NULLSTR(test->data), NULLSTR(actual));
|
|
goto cleanup;
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
VIR_FREE(actual);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#define TEST_TEXT_METADATA(INDEX, TYPE, DATA, FAIL) \
|
|
do { \
|
|
test.type = VIR_DOMAIN_METADATA_ ## TYPE; \
|
|
test.data = DATA; \
|
|
test.fail = FAIL; \
|
|
\
|
|
if (virTestRun("text metadata: " #TYPE " " INDEX " ", \
|
|
testTextMetadata, &test) < 0) \
|
|
ret = EXIT_FAILURE; \
|
|
} while (0)
|
|
|
|
#define TEST_TITLE(INDEX, DATA) TEST_TEXT_METADATA(INDEX, TITLE, DATA, false)
|
|
#define TEST_TITLE_FAIL(INDEX, DATA) TEST_TEXT_METADATA(INDEX, TITLE, DATA, true)
|
|
#define TEST_DESCR(INDEX, DATA) TEST_TEXT_METADATA(INDEX, DESCRIPTION, DATA, false)
|
|
|
|
static int
|
|
mymain(void)
|
|
{
|
|
struct metadataTest test;
|
|
int ret = EXIT_SUCCESS;
|
|
|
|
if (!(test.conn = virConnectOpen("test:///default")))
|
|
return EXIT_FAILURE;
|
|
|
|
if (!(test.dom = virDomainLookupByName(test.conn, "test"))) {
|
|
virConnectClose(test.conn);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
virTestQuiesceLibvirtErrors(false);
|
|
|
|
if (virTestRun("Assign metadata ", testAssignMetadata, &test) < 0)
|
|
ret = EXIT_FAILURE;
|
|
if (virTestRun("Rewrite Metadata ", testRewriteMetadata, &test) < 0)
|
|
ret = EXIT_FAILURE;
|
|
if (virTestRun("Erase metadata ", testEraseMetadata, &test) < 0)
|
|
ret = EXIT_FAILURE;
|
|
|
|
TEST_TITLE("1", "qwert");
|
|
TEST_TITLE("2", NULL);
|
|
TEST_TITLE("3", "blah");
|
|
TEST_TITLE_FAIL("4", "qwe\nrt");
|
|
TEST_TITLE("5", "");
|
|
TEST_TITLE_FAIL("6", "qwert\n");
|
|
TEST_TITLE_FAIL("7", "\n");
|
|
|
|
TEST_DESCR("1", "qwert\nqwert");
|
|
TEST_DESCR("2", NULL);
|
|
TEST_DESCR("3", "qwert");
|
|
TEST_DESCR("4", "\n");
|
|
TEST_DESCR("5", "");
|
|
|
|
virDomainFree(test.dom);
|
|
virConnectClose(test.conn);
|
|
|
|
return ret;
|
|
}
|
|
|
|
VIR_TEST_MAIN(mymain)
|