Add some tests to make sure xmlgen's validity. Signed-off-by: Shi Lei <shi_lei@xxxxxxxxxxxxxx> --- tests/meson.build | 1 + tests/xmlgenin/conf/array.h | 17 + tests/xmlgenin/conf/empty.h | 7 + tests/xmlgenin/conf/enum-first-item.h | 12 + tests/xmlgenin/conf/external.h | 9 + tests/xmlgenin/conf/genformat-separate.h | 11 + tests/xmlgenin/conf/genformat.h | 11 + tests/xmlgenin/conf/genparse.h | 11 + tests/xmlgenin/conf/namespace.h | 12 + tests/xmlgenin/conf/required.h | 9 + tests/xmlgenin/conf/skipparse.h | 10 + tests/xmlgenin/conf/specify.h | 13 + tests/xmlgenin/conf/xmlattr.h | 10 + tests/xmlgenin/conf/xmlelem.h | 10 + tests/xmlgenin/conf/xmlgroup.h | 8 + tests/xmlgenin/conf/xmlswitch.h | 17 + tests/xmlgenin/util/enums.h | 58 +++ tests/xmlgenin/util/structs.h | 67 ++++ tests/xmlgenout/array.txt | 364 ++++++++++++++++++ tests/xmlgenout/empty.txt | 181 +++++++++ tests/xmlgenout/enum-first-item.txt | 297 ++++++++++++++ tests/xmlgenout/external.txt | 205 ++++++++++ tests/xmlgenout/genformat-separate.txt | 190 +++++++++ tests/xmlgenout/genformat.txt | 142 +++++++ tests/xmlgenout/genparse.txt | 154 ++++++++ tests/xmlgenout/namespace.txt | 222 +++++++++++ tests/xmlgenout/required.txt | 236 ++++++++++++ tests/xmlgenout/skipparse.txt | 223 +++++++++++ tests/xmlgenout/specify.txt | 291 ++++++++++++++ tests/xmlgenout/xmlattr.txt | 252 ++++++++++++ tests/xmlgenout/xmlelem.txt | 243 ++++++++++++ tests/xmlgenout/xmlgroup.txt | 204 ++++++++++ tests/xmlgenout/xmlswitch.txt | 470 +++++++++++++++++++++++ tests/xmlgentest.c | 107 ++++++ 34 files changed, 4074 insertions(+) create mode 100644 tests/xmlgenin/conf/array.h create mode 100644 tests/xmlgenin/conf/empty.h create mode 100644 tests/xmlgenin/conf/enum-first-item.h create mode 100644 tests/xmlgenin/conf/external.h create mode 100644 tests/xmlgenin/conf/genformat-separate.h create mode 100644 tests/xmlgenin/conf/genformat.h create mode 100644 tests/xmlgenin/conf/genparse.h create mode 100644 tests/xmlgenin/conf/namespace.h create mode 100644 tests/xmlgenin/conf/required.h create mode 100644 tests/xmlgenin/conf/skipparse.h create mode 100644 tests/xmlgenin/conf/specify.h create mode 100644 tests/xmlgenin/conf/xmlattr.h create mode 100644 tests/xmlgenin/conf/xmlelem.h create mode 100644 tests/xmlgenin/conf/xmlgroup.h create mode 100644 tests/xmlgenin/conf/xmlswitch.h create mode 100644 tests/xmlgenin/util/enums.h create mode 100644 tests/xmlgenin/util/structs.h create mode 100644 tests/xmlgenout/array.txt create mode 100644 tests/xmlgenout/empty.txt create mode 100644 tests/xmlgenout/enum-first-item.txt create mode 100644 tests/xmlgenout/external.txt create mode 100644 tests/xmlgenout/genformat-separate.txt create mode 100644 tests/xmlgenout/genformat.txt create mode 100644 tests/xmlgenout/genparse.txt create mode 100644 tests/xmlgenout/namespace.txt create mode 100644 tests/xmlgenout/required.txt create mode 100644 tests/xmlgenout/skipparse.txt create mode 100644 tests/xmlgenout/specify.txt create mode 100644 tests/xmlgenout/xmlattr.txt create mode 100644 tests/xmlgenout/xmlelem.txt create mode 100644 tests/xmlgenout/xmlgroup.txt create mode 100644 tests/xmlgenout/xmlswitch.txt create mode 100644 tests/xmlgentest.c diff --git a/tests/meson.build b/tests/meson.build index 14ace476..166416cc 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -340,6 +340,7 @@ tests += [ { 'name': 'viruritest' }, { 'name': 'vshtabletest', 'link_with': [ libvirt_shell_lib ] }, { 'name': 'virmigtest' }, + { 'name': 'xmlgentest' }, ] if host_machine.system() == 'linux' diff --git a/tests/xmlgenin/conf/array.h b/tests/xmlgenin/conf/array.h new file mode 100644 index 00000000..8f003be4 --- /dev/null +++ b/tests/xmlgenin/conf/array.h @@ -0,0 +1,17 @@ +/* Test array features */ + +#pragma once + +typedef struct _virArrayDef virArrayDef; +struct _virArrayDef { /* genparse, genformat */ + size_t nnames; + char **names; /* xmlelem:hostname, array */ + size_t nfwds; + virNetworkDNSForwarder *forwarders; /* xmlelem, array:nfwds */ + size_t ntxts; + virNetworkDNSTxtDef *txts; /* xmlelem, array */ + + size_t nroutes; + /* ptr to array of static routes on this interface */ + virNetDevIPRoute **routes; /* xmlelem, array */ +}; diff --git a/tests/xmlgenin/conf/empty.h b/tests/xmlgenin/conf/empty.h new file mode 100644 index 00000000..c8292c8e --- /dev/null +++ b/tests/xmlgenin/conf/empty.h @@ -0,0 +1,7 @@ +/* Test empty struct */ + +#pragma once + +typedef struct _virEmptyDef virEmptyDef; +struct _virEmptyDef { /* genparse, genformat */ +}; diff --git a/tests/xmlgenin/conf/enum-first-item.h b/tests/xmlgenin/conf/enum-first-item.h new file mode 100644 index 00000000..c62dfe8a --- /dev/null +++ b/tests/xmlgenin/conf/enum-first-item.h @@ -0,0 +1,12 @@ +/* Test first item for enum features */ + +#pragma once + +typedef struct _virEnumFirstItemDef virEnumFirstItemDef; +struct _virEnumFirstItemDef { /* genparse, genformat */ + virNetworkBridgeMACTableManagerType has_def; /* xmlattr */ + virNetworkForwardType has_none; /* xmlattr */ + virTristateBool has_absent; /* xmlattr */ + + virDomainGraphicsType no_default; /* xmlattr */ +}; diff --git a/tests/xmlgenin/conf/external.h b/tests/xmlgenin/conf/external.h new file mode 100644 index 00000000..52b46acd --- /dev/null +++ b/tests/xmlgenin/conf/external.h @@ -0,0 +1,9 @@ +/* Test specify features */ + +#pragma once + +typedef struct _virExternalDef virExternalDef; +struct _virExternalDef { /* genparse, genformat */ + /* xmlNode is an external type which is not defined in libvirt */ + xmlNode *metadata; /* xmlelem */ +}; diff --git a/tests/xmlgenin/conf/genformat-separate.h b/tests/xmlgenin/conf/genformat-separate.h new file mode 100644 index 00000000..8e4643af --- /dev/null +++ b/tests/xmlgenin/conf/genformat-separate.h @@ -0,0 +1,11 @@ +/* Test genformat-separate features */ + +#pragma once + +typedef struct _virSeparateDef virSeparateDef; +struct _virSeparateDef { /* genformat:separate */ + virTristateBool enable; /* xmlattr */ + virSocketAddr ip; /* xmlelem */ + size_t ntxts; + virNetworkDNSTxtDef *txts; /* xmlelem, array */ +}; diff --git a/tests/xmlgenin/conf/genformat.h b/tests/xmlgenin/conf/genformat.h new file mode 100644 index 00000000..fb92351a --- /dev/null +++ b/tests/xmlgenin/conf/genformat.h @@ -0,0 +1,11 @@ +/* Test genformat features */ + +#pragma once + +typedef struct _virGenFormatDef virGenFormatDef; +struct _virGenFormatDef { /* genformat */ + virTristateBool enable; /* xmlattr */ + virSocketAddr ip; /* xmlelem */ + size_t ntxts; + virNetworkDNSTxtDef *txts; /* xmlelem, array */ +}; diff --git a/tests/xmlgenin/conf/genparse.h b/tests/xmlgenin/conf/genparse.h new file mode 100644 index 00000000..daf53817 --- /dev/null +++ b/tests/xmlgenin/conf/genparse.h @@ -0,0 +1,11 @@ +/* Test genparse features */ + +#pragma once + +typedef struct _virGenParseDef virGenParseDef; +struct _virGenParseDef { /* genparse */ + virTristateBool enable; /* xmlattr */ + virSocketAddr ip; /* xmlelem */ + size_t ntxts; + virNetworkDNSTxtDef *txts; /* xmlelem, array */ +}; diff --git a/tests/xmlgenin/conf/namespace.h b/tests/xmlgenin/conf/namespace.h new file mode 100644 index 00000000..0637e64a --- /dev/null +++ b/tests/xmlgenin/conf/namespace.h @@ -0,0 +1,12 @@ +/* Test namespace features */ + +#pragma once + +typedef struct _virNameSpaceDef virNameSpaceDef; +struct _virNameSpaceDef { /* genparse, genformat */ + char *name; /* xmlelem */ + + /* Network specific XML namespace data */ + void *namespaceData; + virXMLNamespace ns; +}; diff --git a/tests/xmlgenin/conf/required.h b/tests/xmlgenin/conf/required.h new file mode 100644 index 00000000..d45af727 --- /dev/null +++ b/tests/xmlgenin/conf/required.h @@ -0,0 +1,9 @@ +/* Test required features */ + +#pragma once + +typedef struct _virRequiredDef virRequiredDef; +struct _virRequiredDef { /* genparse, genformat */ + char *name; /* xmlattr, required */ + virNetworkBootpDef bootp; /* xmlelem, required */ +}; diff --git a/tests/xmlgenin/conf/skipparse.h b/tests/xmlgenin/conf/skipparse.h new file mode 100644 index 00000000..680a1107 --- /dev/null +++ b/tests/xmlgenin/conf/skipparse.h @@ -0,0 +1,10 @@ +/* Test skipparse features */ + +#pragma once + +typedef struct _virSkipParseDef virSkipParseDef; +struct _virSkipParseDef { /* genparse, genformat */ + int connections; /* xmlattr, skipparse */ + size_t nifs; + virNetworkForwardIfDef *ifs; /* xmlelem, array, skipparse */ +}; diff --git a/tests/xmlgenin/conf/specify.h b/tests/xmlgenin/conf/specify.h new file mode 100644 index 00000000..419bd24d --- /dev/null +++ b/tests/xmlgenin/conf/specify.h @@ -0,0 +1,13 @@ +/* Test specify features */ + +#pragma once + +typedef struct _virSpecifyDef virSpecifyDef; +struct _virSpecifyDef { /* genparse, genformat */ + virNetworkDHCPLeaseTimeUnitType unit; /* xmlattr */ + unsigned long expiry; /* xmlattr, specify:unit */ + virMacAddr mac; /* xmlattr:mac/address */ + bool mac_specified; /* specify:mac */ + virUUID uuid; /* xmlelem, xmltext */ + bool uuid_specified; /* specify:uuid */ +}; diff --git a/tests/xmlgenin/conf/xmlattr.h b/tests/xmlgenin/conf/xmlattr.h new file mode 100644 index 00000000..60dfae9a --- /dev/null +++ b/tests/xmlgenin/conf/xmlattr.h @@ -0,0 +1,10 @@ +/* Test xmlattr features */ + +#pragma once + +typedef struct _virXMLAttrDef virXMLAttrDef; +struct _virXMLAttrDef { /* genparse, genformat */ + char *family; /* xmlattr */ + virTristateBool localPTR; /* xmlattr:localPtr */ + char *tftproot; /* xmlattr:tftp/root */ +}; diff --git a/tests/xmlgenin/conf/xmlelem.h b/tests/xmlgenin/conf/xmlelem.h new file mode 100644 index 00000000..d111f2b5 --- /dev/null +++ b/tests/xmlgenin/conf/xmlelem.h @@ -0,0 +1,10 @@ +/* Test xmlelem features */ + +#pragma once + +typedef struct _virXMLElemDef virXMLElemDef; +struct _virXMLElemDef { /* genparse, genformat */ + virPortRange port; /* xmlelem */ + virSocketAddrRange addr; /* xmlelem:address */ + virUUID uuid; /* xmlelem, xmltext */ +}; diff --git a/tests/xmlgenin/conf/xmlgroup.h b/tests/xmlgenin/conf/xmlgroup.h new file mode 100644 index 00000000..ed12d919 --- /dev/null +++ b/tests/xmlgenin/conf/xmlgroup.h @@ -0,0 +1,8 @@ +/* Test xmlgroup features */ + +#pragma once + +typedef struct _virXMLGroupDef virXMLGroupDef; +struct _virXMLGroupDef { /* genparse, genformat */ + virUtilAuthDef auth; /* xmlgroup */ +}; diff --git a/tests/xmlgenin/conf/xmlswitch.h b/tests/xmlgenin/conf/xmlswitch.h new file mode 100644 index 00000000..8730f1b3 --- /dev/null +++ b/tests/xmlgenin/conf/xmlswitch.h @@ -0,0 +1,17 @@ +/* Test xmlswitch features */ + +#pragma once + +typedef struct _virXMLSwitchDef virXMLSwitchDef; +struct _virXMLSwitchDef { /* genparse, genformat */ + virDomainGraphicsType type; /* xmlattr */ + + union { + virDomainGraphicsSDLDef sdl; /* xmlgroup */ + virDomainGraphicsVNCDef vnc; /* xmlgroup */ + virDomainGraphicsRDPDef rdp; /* xmlgroup */ + virDomainGraphicsDesktopDef desktop; /* xmlgroup */ + virDomainGraphicsSpiceDef spice; /* xmlgroup */ + virDomainGraphicsEGLHeadlessDef egl_headless; /* xmlgroup */ + } data; /* xmlswitch:type */ +}; diff --git a/tests/xmlgenin/util/enums.h b/tests/xmlgenin/util/enums.h new file mode 100644 index 00000000..89d2eccd --- /dev/null +++ b/tests/xmlgenin/util/enums.h @@ -0,0 +1,58 @@ +/* Basic enum */ + +#pragma once + +/* + * The tool xmlgen scans all header-files in 'util' and 'conf' + * to find all enum types, and further, to determine whether + * they have default item. + * + */ + +typedef enum { + VIR_DOMAIN_GRAPHICS_TYPE_SDL, + VIR_DOMAIN_GRAPHICS_TYPE_VNC, + VIR_DOMAIN_GRAPHICS_TYPE_RDP, + VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP, + VIR_DOMAIN_GRAPHICS_TYPE_SPICE, + VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS, + + VIR_DOMAIN_GRAPHICS_TYPE_LAST +} virDomainGraphicsType; + +typedef enum { + VIR_NETWORK_FORWARD_NONE = 0, + VIR_NETWORK_FORWARD_NAT, + VIR_NETWORK_FORWARD_ROUTE, + VIR_NETWORK_FORWARD_OPEN, + VIR_NETWORK_FORWARD_BRIDGE, + VIR_NETWORK_FORWARD_PRIVATE, + VIR_NETWORK_FORWARD_VEPA, + VIR_NETWORK_FORWARD_PASSTHROUGH, + VIR_NETWORK_FORWARD_HOSTDEV, + + VIR_NETWORK_FORWARD_LAST, +} virNetworkForwardType; + +typedef enum { + VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_DEFAULT = 0, + VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_KERNEL, + VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT, + VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LAST, +} virNetworkBridgeMACTableManagerType; + +typedef enum { + VIR_TRISTATE_BOOL_ABSENT = 0, + VIR_TRISTATE_BOOL_YES, + VIR_TRISTATE_BOOL_NO, + + VIR_TRISTATE_BOOL_LAST +} virTristateBool; + +typedef enum { + VIR_NETWORK_DHCP_LEASETIME_UNIT_SECONDS = 0, + VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES, + VIR_NETWORK_DHCP_LEASETIME_UNIT_HOURS, + + VIR_NETWORK_DHCP_LEASETIME_UNIT_LAST, +} virNetworkDHCPLeaseTimeUnitType; diff --git a/tests/xmlgenin/util/structs.h b/tests/xmlgenin/util/structs.h new file mode 100644 index 00000000..80c10096 --- /dev/null +++ b/tests/xmlgenin/util/structs.h @@ -0,0 +1,67 @@ +/* Basic structs */ + +#pragma once + +/* + * The tool xmlgen scans all header-files in 'util' and 'conf' + * to find all struct types. + * For tests, it's unnecessary to include any members for these structs. + */ + +typedef struct _virNetDevIPRoute virNetDevIPRoute; +struct _virNetDevIPRoute { +}; + +typedef struct _virNetworkDNSForwarder virNetworkDNSForwarder; +struct _virNetworkDNSForwarder { +}; + +typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef; +struct _virNetworkDNSTxtDef { +}; + +typedef struct _virSocketAddr virSocketAddr; +struct _virSocketAddr { +}; + +typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef; +struct _virNetworkForwardIfDef { +}; + +typedef struct _virPortRange virPortRange; +struct _virPortRange { +}; + +typedef struct _virSocketAddrRange virSocketAddrRange; +struct _virSocketAddrRange { +}; + +typedef struct _virUtilAuthDef virUtilAuthDef; +struct _virUtilAuthDef { +}; + +typedef struct _virNetworkBootpDef virNetworkBootpDef; +struct _virNetworkBootpDef { +}; + +typedef struct _virMacAddr virMacAddr; +struct _virMacAddr { +}; + +struct _virDomainGraphicsSDLDef { +}; + +struct _virDomainGraphicsVNCDef { +}; + +struct _virDomainGraphicsRDPDef { +}; + +struct _virDomainGraphicsDesktopDef { +}; + +struct _virDomainGraphicsSpiceDef { +}; + +struct _virDomainGraphicsEGLHeadlessDef { +}; diff --git a/tests/xmlgenout/array.txt b/tests/xmlgenout/array.txt new file mode 100644 index 00000000..ccb2d168 --- /dev/null +++ b/tests/xmlgenout/array.txt @@ -0,0 +1,364 @@ +[conf/array.generated.h] + +void +virArrayDefClear(virArrayDef *def); + + +[conf/array.generated.c] + +void +virArrayDefClear(virArrayDef *def) +{ + if (!def) + return; + + if (def->nnames) { + size_t i; + for (i = 0; i < def->nnames; i++) { + g_free(def->names[i]); + def->names[i] = NULL; + } + } + g_free(def->names); + def->names = NULL; + def->nnames = 0; + + if (def->nfwds) { + size_t i; + for (i = 0; i < def->nfwds; i++) + virNetworkDNSForwarderClear(&def->forwarders[i]); + } + g_free(def->forwarders); + def->forwarders = NULL; + def->nfwds = 0; + + if (def->ntxts) { + size_t i; + for (i = 0; i < def->ntxts; i++) + virNetworkDNSTxtDefClear(&def->txts[i]); + } + g_free(def->txts); + def->txts = NULL; + def->ntxts = 0; + + if (def->nroutes) { + size_t i; + for (i = 0; i < def->nroutes; i++) { + virNetDevIPRouteClear(def->routes[i]); + g_free(def->routes[i]); + def->routes[i] = NULL; + } + } + g_free(def->routes); + def->routes = NULL; + def->nroutes = 0; +} + + +[conf/array.generated.h] + +int +virArrayDefParseXML(xmlNodePtr node, + virArrayDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/array.generated.h] + +#ifdef ENABLE_VIR_ARRAY_DEF_PARSE_HOOK + +int +virArrayDefParseHook(xmlNodePtr node, + virArrayDef *def, + const char *instname, + void *parent, + void *opaque, + int nHostnameNodes, + int nForwarderNodes, + int nTxtNodes, + int nRouteNodes); + +#endif + + +[conf/array.generated.h] + +#ifdef ENABLE_VIR_ARRAY_DEF_PARSE_HOOK_SET_ARGS + +void +virArrayDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/array.generated.c] + +int +virArrayDefParseXML(xmlNodePtr node, + virArrayDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + int nHostnameNodes = 0; + xmlNodePtr *nodes = NULL; + int nForwarderNodes = 0; + int nTxtNodes = 0; + int nRouteNodes = 0; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_ARRAY_DEF_PARSE_HOOK_SET_ARGS + virArrayDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + nHostnameNodes = virXMLChildNodeSet(node, "hostname", &nodes); + if (nHostnameNodes > 0) { + size_t i; + + def->names = g_new0(typeof(*def->names), nHostnameNodes); + for (i = 0; i < nHostnameNodes; i++) { + xmlNodePtr tnode = nodes[i]; + def->names[i] = virXMLNodeContentString(tnode); + } + def->nnames = nHostnameNodes; + g_free(nodes); + nodes = NULL; + } else if (nHostnameNodes < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid %s element found."), + "hostname"); + goto error; + } + + nForwarderNodes = virXMLChildNodeSet(node, "forwarder", &nodes); + if (nForwarderNodes > 0) { + size_t i; + + def->forwarders = g_new0(typeof(*def->forwarders), nForwarderNodes); + for (i = 0; i < nForwarderNodes; i++) { + xmlNodePtr tnode = nodes[i]; + if (virNetworkDNSForwarderParseXML(tnode, &def->forwarders[i], instname, arg_parent, arg_opaque) < 0) + goto error; + } + def->nfwds = nForwarderNodes; + g_free(nodes); + nodes = NULL; + } else if (nForwarderNodes < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid %s element found."), + "forwarder"); + goto error; + } + + nTxtNodes = virXMLChildNodeSet(node, "txt", &nodes); + if (nTxtNodes > 0) { + size_t i; + + def->txts = g_new0(typeof(*def->txts), nTxtNodes); + for (i = 0; i < nTxtNodes; i++) { + xmlNodePtr tnode = nodes[i]; + if (virNetworkDNSTxtDefParseXML(tnode, &def->txts[i], instname, arg_parent, arg_opaque) < 0) + goto error; + } + def->ntxts = nTxtNodes; + g_free(nodes); + nodes = NULL; + } else if (nTxtNodes < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid %s element found."), + "txt"); + goto error; + } + + nRouteNodes = virXMLChildNodeSet(node, "route", &nodes); + if (nRouteNodes > 0) { + size_t i; + + def->routes = g_new0(typeof(*def->routes), nRouteNodes); + for (i = 0; i < nRouteNodes; i++) { + xmlNodePtr tnode = nodes[i]; + def->routes[i] = g_new0(typeof(*def->routes[i]), 1); + if (virNetDevIPRouteParseXML(tnode, def->routes[i], instname, arg_parent, arg_opaque) < 0) + goto error; + } + def->nroutes = nRouteNodes; + g_free(nodes); + nodes = NULL; + } else if (nRouteNodes < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid %s element found."), + "route"); + goto error; + } + +#ifdef ENABLE_VIR_ARRAY_DEF_PARSE_HOOK + if (virArrayDefParseHook(node, def, instname, parent, opaque, nHostnameNodes, nForwarderNodes, nTxtNodes, nRouteNodes) < 0) + goto error; +#endif + + return 0; + + error: + g_free(nodes); + nodes = NULL; + virArrayDefClear(def); + return -1; +} + + +[conf/array.generated.h] + +int +virArrayDefFormatBuf(virBuffer *buf, + const char *name, + const virArrayDef *def, + const void *parent, + void *opaque); + + +[conf/array.generated.h] + +#ifdef ENABLE_VIR_ARRAY_DEF_FORMAT_HOOK + +int +virArrayDefFormatHook(const virArrayDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *namesBuf, + virBuffer *forwardersBuf, + virBuffer *txtsBuf, + virBuffer *routesBuf); + +#endif /* ENABLE_VIR_ARRAY_DEF_FORMAT_HOOK */ + + +[conf/array.generated.c] + +int +virArrayDefFormatBuf(virBuffer *buf, + const char *name, + const virArrayDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) namesBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) forwardersBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) txtsBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) routesBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_ARRAY_DEF_FORMAT_HOOK + if (virArrayDefFormatHook(def, parent, opaque, &empty, &shortcut, &namesBuf, &forwardersBuf, &txtsBuf, &routesBuf) < 0) + return -1; +#endif /* ENABLE_VIR_ARRAY_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->nnames || def->nfwds || def->ntxts || def->nroutes)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&namesBuf, buf); + if (!virBufferTouched(&namesBuf) && def->nnames) { + size_t i; + for (i = 0; i < def->nnames; i++) + virBufferEscapeString(buf, "<hostname>%s</hostname>\n", def->names[i]); + } + virBufferAddBuffer(buf, &namesBuf); + + virBufferInheritIndent(&forwardersBuf, buf); + if (!virBufferTouched(&forwardersBuf) && def->nfwds) { + size_t i; + for (i = 0; i < def->nfwds; i++) { + if (virNetworkDNSForwarderFormatBuf(buf, "forwarder", &def->forwarders[i], def, opaque) < 0) + return -1; + } + } + virBufferAddBuffer(buf, &forwardersBuf); + + virBufferInheritIndent(&txtsBuf, buf); + if (!virBufferTouched(&txtsBuf) && def->ntxts) { + size_t i; + for (i = 0; i < def->ntxts; i++) { + if (virNetworkDNSTxtDefFormatBuf(buf, "txt", &def->txts[i], def, opaque) < 0) + return -1; + } + } + virBufferAddBuffer(buf, &txtsBuf); + + virBufferInheritIndent(&routesBuf, buf); + if (!virBufferTouched(&routesBuf) && def->nroutes) { + size_t i; + for (i = 0; i < def->nroutes; i++) { + if (virNetDevIPRouteFormatBuf(buf, "route", def->routes[i], def, opaque) < 0) + return -1; + } + } + virBufferAddBuffer(buf, &routesBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/array.generated.h] + +bool +virArrayDefCheck(const virArrayDef *def, + const void *parent, + void *opaque); + + +[conf/array.generated.c] + +#ifndef RESET_VIR_ARRAY_DEF_CHECK + +bool +virArrayDefCheck(const virArrayDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->nnames || def->nfwds || def->ntxts || def->nroutes; +} + +#endif /* RESET_VIR_ARRAY_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/array.h" */ +/* Makesure "array.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_ARRAY_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_ARRAY_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_ARRAY_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_ARRAY_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "array.generated.h" diff --git a/tests/xmlgenout/empty.txt b/tests/xmlgenout/empty.txt new file mode 100644 index 00000000..c83a2c12 --- /dev/null +++ b/tests/xmlgenout/empty.txt @@ -0,0 +1,181 @@ +[conf/empty.generated.h] + +void +virEmptyDefClear(virEmptyDef *def); + + +[conf/empty.generated.c] + +void +virEmptyDefClear(virEmptyDef *def) +{ + if (!def) + return; +} + + +[conf/empty.generated.h] + +int +virEmptyDefParseXML(xmlNodePtr node, + virEmptyDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/empty.generated.h] + +#ifdef ENABLE_VIR_EMPTY_DEF_PARSE_HOOK + +int +virEmptyDefParseHook(xmlNodePtr node, + virEmptyDef *def, + const char *instname, + void *parent, + void *opaque); + +#endif + + +[conf/empty.generated.h] + +#ifdef ENABLE_VIR_EMPTY_DEF_PARSE_HOOK_SET_ARGS + +void +virEmptyDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/empty.generated.c] + +int +virEmptyDefParseXML(xmlNodePtr node, + virEmptyDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_EMPTY_DEF_PARSE_HOOK_SET_ARGS + virEmptyDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + +#ifdef ENABLE_VIR_EMPTY_DEF_PARSE_HOOK + if (virEmptyDefParseHook(node, def, instname, parent, opaque) < 0) + goto error; +#endif + + return 0; + + error: + virEmptyDefClear(def); + return -1; +} + + +[conf/empty.generated.h] + +int +virEmptyDefFormatBuf(virBuffer *buf, + const char *name, + const virEmptyDef *def, + const void *parent, + void *opaque); + + +[conf/empty.generated.h] + +#ifdef ENABLE_VIR_EMPTY_DEF_FORMAT_HOOK + +int +virEmptyDefFormatHook(const virEmptyDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut); + +#endif /* ENABLE_VIR_EMPTY_DEF_FORMAT_HOOK */ + + +[conf/empty.generated.c] + +int +virEmptyDefFormatBuf(virBuffer *buf, + const char *name, + const virEmptyDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_EMPTY_DEF_FORMAT_HOOK + if (virEmptyDefFormatHook(def, parent, opaque, &empty, &shortcut) < 0) + return -1; +#endif /* ENABLE_VIR_EMPTY_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferAddLit(buf, "/>\n"); + + return 0; +} + + +[conf/empty.generated.h] + +bool +virEmptyDefCheck(const virEmptyDef *def, + const void *parent, + void *opaque); + + +[conf/empty.generated.c] + +#ifndef RESET_VIR_EMPTY_DEF_CHECK + +bool +virEmptyDefCheck(const virEmptyDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return false; +} + +#endif /* RESET_VIR_EMPTY_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/empty.h" */ +/* Makesure "empty.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_EMPTY_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_EMPTY_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_EMPTY_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_EMPTY_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "empty.generated.h" diff --git a/tests/xmlgenout/enum-first-item.txt b/tests/xmlgenout/enum-first-item.txt new file mode 100644 index 00000000..4186d46d --- /dev/null +++ b/tests/xmlgenout/enum-first-item.txt @@ -0,0 +1,297 @@ +[conf/enum-first-item.generated.h] + +void +virEnumFirstItemDefClear(virEnumFirstItemDef *def); + + +[conf/enum-first-item.generated.c] + +void +virEnumFirstItemDefClear(virEnumFirstItemDef *def) +{ + if (!def) + return; + + def->has_def = 0; + + def->has_none = 0; + + def->has_absent = 0; + + def->no_default = 0; +} + + +[conf/enum-first-item.generated.h] + +int +virEnumFirstItemDefParseXML(xmlNodePtr node, + virEnumFirstItemDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/enum-first-item.generated.h] + +#ifdef ENABLE_VIR_ENUM_FIRST_ITEM_DEF_PARSE_HOOK + +int +virEnumFirstItemDefParseHook(xmlNodePtr node, + virEnumFirstItemDef *def, + const char *instname, + void *parent, + void *opaque, + const char *has_defStr, + const char *has_noneStr, + const char *has_absentStr, + const char *no_defaultStr); + +#endif + + +[conf/enum-first-item.generated.h] + +#ifdef ENABLE_VIR_ENUM_FIRST_ITEM_DEF_PARSE_HOOK_SET_ARGS + +void +virEnumFirstItemDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/enum-first-item.generated.c] + +int +virEnumFirstItemDefParseXML(xmlNodePtr node, + virEnumFirstItemDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + g_autofree char *has_defStr = NULL; + g_autofree char *has_noneStr = NULL; + g_autofree char *has_absentStr = NULL; + g_autofree char *no_defaultStr = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_ENUM_FIRST_ITEM_DEF_PARSE_HOOK_SET_ARGS + virEnumFirstItemDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + has_defStr = virXMLPropString(node, "has_def"); + if (has_defStr) { + if ((def->has_def = virNetworkBridgeMACTableManagerTypeFromString(has_defStr)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "has_def", has_defStr, instname); + goto error; + } + } + + has_noneStr = virXMLPropString(node, "has_none"); + if (has_noneStr) { + if ((def->has_none = virNetworkForwardTypeFromString(has_noneStr)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "has_none", has_noneStr, instname); + goto error; + } + } + + has_absentStr = virXMLPropString(node, "has_absent"); + if (has_absentStr) { + if ((def->has_absent = virTristateBoolTypeFromString(has_absentStr)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "has_absent", has_absentStr, instname); + goto error; + } + } + + no_defaultStr = virXMLPropString(node, "no_default"); + if (no_defaultStr) { + if ((def->no_default = virDomainGraphicsTypeFromString(no_defaultStr)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "no_default", no_defaultStr, instname); + goto error; + } + } + +#ifdef ENABLE_VIR_ENUM_FIRST_ITEM_DEF_PARSE_HOOK + if (virEnumFirstItemDefParseHook(node, def, instname, parent, opaque, has_defStr, has_noneStr, has_absentStr, no_defaultStr) < 0) + goto error; +#endif + + return 0; + + error: + virEnumFirstItemDefClear(def); + return -1; +} + + +[conf/enum-first-item.generated.h] + +int +virEnumFirstItemDefFormatBuf(virBuffer *buf, + const char *name, + const virEnumFirstItemDef *def, + const void *parent, + void *opaque); + + +[conf/enum-first-item.generated.h] + +#ifdef ENABLE_VIR_ENUM_FIRST_ITEM_DEF_FORMAT_HOOK + +int +virEnumFirstItemDefFormatHook(const virEnumFirstItemDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *has_defBuf, + virBuffer *has_noneBuf, + virBuffer *has_absentBuf, + virBuffer *no_defaultBuf); + +#endif /* ENABLE_VIR_ENUM_FIRST_ITEM_DEF_FORMAT_HOOK */ + + +[conf/enum-first-item.generated.c] + +int +virEnumFirstItemDefFormatBuf(virBuffer *buf, + const char *name, + const virEnumFirstItemDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) has_defBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) has_noneBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) has_absentBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) no_defaultBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_ENUM_FIRST_ITEM_DEF_FORMAT_HOOK + if (virEnumFirstItemDefFormatHook(def, parent, opaque, &empty, &shortcut, &has_defBuf, &has_noneBuf, &has_absentBuf, &no_defaultBuf) < 0) + return -1; +#endif /* ENABLE_VIR_ENUM_FIRST_ITEM_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->has_def > 0 || def->has_none > 0 || def->has_absent > 0 || def->no_default >= 0)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&has_defBuf, buf); + if (!virBufferTouched(&has_defBuf) && def->has_def > 0) { + const char *str = virNetworkBridgeMACTableManagerTypeToString(def->has_def); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "has_def", def->has_def); + return -1; + } + virBufferAsprintf(&has_defBuf, " has_def='%s'", str); + } + virBufferAddBuffer(buf, &has_defBuf); + + virBufferInheritIndent(&has_noneBuf, buf); + if (!virBufferTouched(&has_noneBuf) && def->has_none > 0) { + const char *str = virNetworkForwardTypeToString(def->has_none); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "has_none", def->has_none); + return -1; + } + virBufferAsprintf(&has_noneBuf, " has_none='%s'", str); + } + virBufferAddBuffer(buf, &has_noneBuf); + + virBufferInheritIndent(&has_absentBuf, buf); + if (!virBufferTouched(&has_absentBuf) && def->has_absent > 0) { + const char *str = virTristateBoolTypeToString(def->has_absent); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "has_absent", def->has_absent); + return -1; + } + virBufferAsprintf(&has_absentBuf, " has_absent='%s'", str); + } + virBufferAddBuffer(buf, &has_absentBuf); + + virBufferInheritIndent(&no_defaultBuf, buf); + if (!virBufferTouched(&no_defaultBuf) && def->no_default >= 0) { + const char *str = virDomainGraphicsTypeToString(def->no_default); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "no_default", def->no_default); + return -1; + } + virBufferAsprintf(&no_defaultBuf, " no_default='%s'", str); + } + virBufferAddBuffer(buf, &no_defaultBuf); + + virBufferAddLit(buf, "/>\n"); + + return 0; +} + + +[conf/enum-first-item.generated.h] + +bool +virEnumFirstItemDefCheck(const virEnumFirstItemDef *def, + const void *parent, + void *opaque); + + +[conf/enum-first-item.generated.c] + +#ifndef RESET_VIR_ENUM_FIRST_ITEM_DEF_CHECK + +bool +virEnumFirstItemDefCheck(const virEnumFirstItemDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->has_def > 0 || def->has_none > 0 || def->has_absent > 0 || def->no_default >= 0; +} + +#endif /* RESET_VIR_ENUM_FIRST_ITEM_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/enum-first-item.h" */ +/* Makesure "enum-first-item.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_ENUM_FIRST_ITEM_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_ENUM_FIRST_ITEM_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_ENUM_FIRST_ITEM_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_ENUM_FIRST_ITEM_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "enum-first-item.generated.h" diff --git a/tests/xmlgenout/external.txt b/tests/xmlgenout/external.txt new file mode 100644 index 00000000..4f0ea691 --- /dev/null +++ b/tests/xmlgenout/external.txt @@ -0,0 +1,205 @@ +[conf/external.generated.h] + +void +virExternalDefClear(virExternalDef *def); + + +[conf/external.generated.c] + +void +virExternalDefClear(virExternalDef *def) +{ + if (!def) + return; + + xmlNodeClear(&def->metadata); +} + + +[conf/external.generated.h] + +int +virExternalDefParseXML(xmlNodePtr node, + virExternalDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/external.generated.h] + +#ifdef ENABLE_VIR_EXTERNAL_DEF_PARSE_HOOK + +int +virExternalDefParseHook(xmlNodePtr node, + virExternalDef *def, + const char *instname, + void *parent, + void *opaque, + xmlNodePtr metadataNode); + +#endif + + +[conf/external.generated.h] + +#ifdef ENABLE_VIR_EXTERNAL_DEF_PARSE_HOOK_SET_ARGS + +void +virExternalDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/external.generated.c] + +int +virExternalDefParseXML(xmlNodePtr node, + virExternalDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + xmlNodePtr metadataNode = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_EXTERNAL_DEF_PARSE_HOOK_SET_ARGS + virExternalDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + metadataNode = virXMLChildNode(node, "metadata"); + if (metadataNode) { + if (xmlNodeParseXML(metadataNode, &def->metadata, instname, arg_parent, arg_opaque) < 0) + goto error; + } + +#ifdef ENABLE_VIR_EXTERNAL_DEF_PARSE_HOOK + if (virExternalDefParseHook(node, def, instname, parent, opaque, metadataNode) < 0) + goto error; +#endif + + return 0; + + error: + virExternalDefClear(def); + return -1; +} + + +[conf/external.generated.h] + +int +virExternalDefFormatBuf(virBuffer *buf, + const char *name, + const virExternalDef *def, + const void *parent, + void *opaque); + + +[conf/external.generated.h] + +#ifdef ENABLE_VIR_EXTERNAL_DEF_FORMAT_HOOK + +int +virExternalDefFormatHook(const virExternalDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *metadataBuf); + +#endif /* ENABLE_VIR_EXTERNAL_DEF_FORMAT_HOOK */ + + +[conf/external.generated.c] + +int +virExternalDefFormatBuf(virBuffer *buf, + const char *name, + const virExternalDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) metadataBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_EXTERNAL_DEF_FORMAT_HOOK + if (virExternalDefFormatHook(def, parent, opaque, &empty, &shortcut, &metadataBuf) < 0) + return -1; +#endif /* ENABLE_VIR_EXTERNAL_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(xmlNodeCheck(&def->metadata, def, opaque))) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&metadataBuf, buf); + if (!virBufferTouched(&metadataBuf) && xmlNodeCheck(&def->metadata, def, opaque)) { + if (xmlNodeFormatBuf(&metadataBuf, "metadata", &def->metadata, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &metadataBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/external.generated.h] + +bool +virExternalDefCheck(const virExternalDef *def, + const void *parent, + void *opaque); + + +[conf/external.generated.c] + +#ifndef RESET_VIR_EXTERNAL_DEF_CHECK + +bool +virExternalDefCheck(const virExternalDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return xmlNodeCheck(&def->metadata, def, opaque); +} + +#endif /* RESET_VIR_EXTERNAL_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/external.h" */ +/* Makesure "external.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_EXTERNAL_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_EXTERNAL_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_EXTERNAL_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_EXTERNAL_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "external.generated.h" diff --git a/tests/xmlgenout/genformat-separate.txt b/tests/xmlgenout/genformat-separate.txt new file mode 100644 index 00000000..90729d2a --- /dev/null +++ b/tests/xmlgenout/genformat-separate.txt @@ -0,0 +1,190 @@ +[conf/genformat-separate.generated.h] + +#ifdef ENABLE_VIR_SEPARATE_DEF_FORMAT_ATTR_HOOK + +int +virSeparateDefFormatAttrHook(const virSeparateDef *def, + const void *parent, + const void *opaque, + virBuffer *enableBuf); + +#endif /* ENABLE_VIR_SEPARATE_DEF_FORMAT_ATTR_HOOK */ + + +[conf/genformat-separate.generated.h] + +int +virSeparateDefFormatAttr(virBuffer *buf, + const virSeparateDef *def, + const void *parent, + void *opaque); + + +[conf/genformat-separate.generated.c] + +int +virSeparateDefFormatAttr(virBuffer *buf, + const virSeparateDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) enableBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_SEPARATE_DEF_FORMAT_ATTR_HOOK + if (virSeparateDefFormatAttrHook(def, parent, opaque, &enableBuf) < 0) + return -1; +#endif /* ENABLE_VIR_SEPARATE_DEF_FORMAT_ATTR_HOOK */ + + virBufferInheritIndent(&enableBuf, buf); + if (!virBufferTouched(&enableBuf) && def->enable > 0) { + const char *str = virTristateBoolTypeToString(def->enable); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "enable", def->enable); + return -1; + } + virBufferAsprintf(&enableBuf, " enable='%s'", str); + } + virBufferAddBuffer(buf, &enableBuf); + + return 0; +} + + +[conf/genformat-separate.generated.h] + +bool +virSeparateDefCheckAttr(const virSeparateDef *def, + const void *parent, + void *opaque); + + +[conf/genformat-separate.generated.c] + +#ifndef RESET_VIR_SEPARATE_DEF_CHECK_ATTR + +bool +virSeparateDefCheckAttr(const virSeparateDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->enable > 0; +} + +#endif /* RESET_VIR_SEPARATE_DEF_CHECK_ATTR */ + + +[conf/genformat-separate.generated.h] + +#ifdef ENABLE_VIR_SEPARATE_DEF_FORMAT_ELEM_HOOK + +int +virSeparateDefFormatElemHook(const virSeparateDef *def, + const void *parent, + const void *opaque, + virBuffer *ipBuf, + virBuffer *txtsBuf); + +#endif /* ENABLE_VIR_SEPARATE_DEF_FORMAT_ELEM_HOOK */ + + +[conf/genformat-separate.generated.h] + +int +virSeparateDefFormatElem(virBuffer *buf, + const virSeparateDef *def, + const void *parent, + void *opaque); + + +[conf/genformat-separate.generated.c] + +int +virSeparateDefFormatElem(virBuffer *buf, + const virSeparateDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) ipBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) txtsBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_SEPARATE_DEF_FORMAT_ELEM_HOOK + if (virSeparateDefFormatElemHook(def, parent, opaque, &ipBuf, &txtsBuf) < 0) + return -1; +#endif /* ENABLE_VIR_SEPARATE_DEF_FORMAT_ELEM_HOOK */ + + virBufferInheritIndent(&ipBuf, buf); + if (!virBufferTouched(&ipBuf) && virSocketAddrCheck(&def->ip, def, opaque)) { + if (virSocketAddrFormatBuf(&ipBuf, "ip", &def->ip, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &ipBuf); + + virBufferInheritIndent(&txtsBuf, buf); + if (!virBufferTouched(&txtsBuf) && def->ntxts) { + size_t i; + for (i = 0; i < def->ntxts; i++) { + if (virNetworkDNSTxtDefFormatBuf(buf, "txt", &def->txts[i], def, opaque) < 0) + return -1; + } + } + virBufferAddBuffer(buf, &txtsBuf); + + return 0; +} + + +[conf/genformat-separate.generated.h] + +bool +virSeparateDefCheckElem(const virSeparateDef *def, + const void *parent, + void *opaque); + + +[conf/genformat-separate.generated.c] + +#ifndef RESET_VIR_SEPARATE_DEF_CHECK_ELEM + +bool +virSeparateDefCheckElem(const virSeparateDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return virSocketAddrCheck(&def->ip, def, opaque) || def->ntxts; +} + +#endif /* RESET_VIR_SEPARATE_DEF_CHECK_ELEM */ + + +[Tips] + +/* Put these lines at the bottom of "conf/genformat-separate.h" */ +/* Makesure "genformat-separate.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_SEPARATE_DEF_FORMAT_ATTR_HOOK */ +/* #define ENABLE_VIR_SEPARATE_DEF_FORMAT_ELEM_HOOK */ + +/* #define RESET_VIR_SEPARATE_DEF_CHECK_ATTR */ +/* #define RESET_VIR_SEPARATE_DEF_CHECK_ELEM */ + +/* Makesure below is the bottom line! */ +#include "genformat-separate.generated.h" diff --git a/tests/xmlgenout/genformat.txt b/tests/xmlgenout/genformat.txt new file mode 100644 index 00000000..72e4e0c0 --- /dev/null +++ b/tests/xmlgenout/genformat.txt @@ -0,0 +1,142 @@ +[conf/genformat.generated.h] + +int +virGenFormatDefFormatBuf(virBuffer *buf, + const char *name, + const virGenFormatDef *def, + const void *parent, + void *opaque); + + +[conf/genformat.generated.h] + +#ifdef ENABLE_VIR_GEN_FORMAT_DEF_FORMAT_HOOK + +int +virGenFormatDefFormatHook(const virGenFormatDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *enableBuf, + virBuffer *ipBuf, + virBuffer *txtsBuf); + +#endif /* ENABLE_VIR_GEN_FORMAT_DEF_FORMAT_HOOK */ + + +[conf/genformat.generated.c] + +int +virGenFormatDefFormatBuf(virBuffer *buf, + const char *name, + const virGenFormatDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) enableBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) ipBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) txtsBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_GEN_FORMAT_DEF_FORMAT_HOOK + if (virGenFormatDefFormatHook(def, parent, opaque, &empty, &shortcut, &enableBuf, &ipBuf, &txtsBuf) < 0) + return -1; +#endif /* ENABLE_VIR_GEN_FORMAT_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->enable > 0 || virSocketAddrCheck(&def->ip, def, opaque) || def->ntxts)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&enableBuf, buf); + if (!virBufferTouched(&enableBuf) && def->enable > 0) { + const char *str = virTristateBoolTypeToString(def->enable); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "enable", def->enable); + return -1; + } + virBufferAsprintf(&enableBuf, " enable='%s'", str); + } + virBufferAddBuffer(buf, &enableBuf); + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(virSocketAddrCheck(&def->ip, def, opaque) || def->ntxts)) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&ipBuf, buf); + if (!virBufferTouched(&ipBuf) && virSocketAddrCheck(&def->ip, def, opaque)) { + if (virSocketAddrFormatBuf(&ipBuf, "ip", &def->ip, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &ipBuf); + + virBufferInheritIndent(&txtsBuf, buf); + if (!virBufferTouched(&txtsBuf) && def->ntxts) { + size_t i; + for (i = 0; i < def->ntxts; i++) { + if (virNetworkDNSTxtDefFormatBuf(buf, "txt", &def->txts[i], def, opaque) < 0) + return -1; + } + } + virBufferAddBuffer(buf, &txtsBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/genformat.generated.h] + +bool +virGenFormatDefCheck(const virGenFormatDef *def, + const void *parent, + void *opaque); + + +[conf/genformat.generated.c] + +#ifndef RESET_VIR_GEN_FORMAT_DEF_CHECK + +bool +virGenFormatDefCheck(const virGenFormatDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->enable > 0 || virSocketAddrCheck(&def->ip, def, opaque) || def->ntxts; +} + +#endif /* RESET_VIR_GEN_FORMAT_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/genformat.h" */ +/* Makesure "genformat.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_GEN_FORMAT_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_GEN_FORMAT_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "genformat.generated.h" diff --git a/tests/xmlgenout/genparse.txt b/tests/xmlgenout/genparse.txt new file mode 100644 index 00000000..e24762e1 --- /dev/null +++ b/tests/xmlgenout/genparse.txt @@ -0,0 +1,154 @@ +[conf/genparse.generated.h] + +void +virGenParseDefClear(virGenParseDef *def); + + +[conf/genparse.generated.c] + +void +virGenParseDefClear(virGenParseDef *def) +{ + if (!def) + return; + + def->enable = 0; + + virSocketAddrClear(&def->ip); + + if (def->ntxts) { + size_t i; + for (i = 0; i < def->ntxts; i++) + virNetworkDNSTxtDefClear(&def->txts[i]); + } + g_free(def->txts); + def->txts = NULL; + def->ntxts = 0; +} + + +[conf/genparse.generated.h] + +int +virGenParseDefParseXML(xmlNodePtr node, + virGenParseDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/genparse.generated.h] + +#ifdef ENABLE_VIR_GEN_PARSE_DEF_PARSE_HOOK + +int +virGenParseDefParseHook(xmlNodePtr node, + virGenParseDef *def, + const char *instname, + void *parent, + void *opaque, + const char *enableStr, + xmlNodePtr ipNode, + int nTxtNodes); + +#endif + + +[conf/genparse.generated.h] + +#ifdef ENABLE_VIR_GEN_PARSE_DEF_PARSE_HOOK_SET_ARGS + +void +virGenParseDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/genparse.generated.c] + +int +virGenParseDefParseXML(xmlNodePtr node, + virGenParseDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + g_autofree char *enableStr = NULL; + xmlNodePtr ipNode = NULL; + int nTxtNodes = 0; + xmlNodePtr *nodes = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_GEN_PARSE_DEF_PARSE_HOOK_SET_ARGS + virGenParseDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + enableStr = virXMLPropString(node, "enable"); + if (enableStr) { + if ((def->enable = virTristateBoolTypeFromString(enableStr)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "enable", enableStr, instname); + goto error; + } + } + + ipNode = virXMLChildNode(node, "ip"); + if (ipNode) { + if (virSocketAddrParseXML(ipNode, &def->ip, instname, arg_parent, arg_opaque) < 0) + goto error; + } + + nTxtNodes = virXMLChildNodeSet(node, "txt", &nodes); + if (nTxtNodes > 0) { + size_t i; + + def->txts = g_new0(typeof(*def->txts), nTxtNodes); + for (i = 0; i < nTxtNodes; i++) { + xmlNodePtr tnode = nodes[i]; + if (virNetworkDNSTxtDefParseXML(tnode, &def->txts[i], instname, arg_parent, arg_opaque) < 0) + goto error; + } + def->ntxts = nTxtNodes; + g_free(nodes); + nodes = NULL; + } else if (nTxtNodes < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid %s element found."), + "txt"); + goto error; + } + +#ifdef ENABLE_VIR_GEN_PARSE_DEF_PARSE_HOOK + if (virGenParseDefParseHook(node, def, instname, parent, opaque, enableStr, ipNode, nTxtNodes) < 0) + goto error; +#endif + + return 0; + + error: + g_free(nodes); + nodes = NULL; + virGenParseDefClear(def); + return -1; +} + + +[Tips] + +/* Put these lines at the bottom of "conf/genparse.h" */ +/* Makesure "genparse.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_GEN_PARSE_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_GEN_PARSE_DEF_PARSE_HOOK_SET_ARGS */ + +/* Makesure below is the bottom line! */ +#include "genparse.generated.h" diff --git a/tests/xmlgenout/namespace.txt b/tests/xmlgenout/namespace.txt new file mode 100644 index 00000000..df1660dd --- /dev/null +++ b/tests/xmlgenout/namespace.txt @@ -0,0 +1,222 @@ +[conf/namespace.generated.h] + +void +virNameSpaceDefClear(virNameSpaceDef *def); + + +[conf/namespace.generated.c] + +void +virNameSpaceDefClear(virNameSpaceDef *def) +{ + if (!def) + return; + + g_free(def->name); + def->name = NULL; + + if (def->namespaceData && def->ns.free) + (def->ns.free)(def->namespaceData); +} + + +[conf/namespace.generated.h] + +int +virNameSpaceDefParseXML(xmlNodePtr node, + virNameSpaceDef *def, + const char *instname, + void *parent, + void *opaque, + xmlXPathContextPtr ctxt, + virNetworkXMLOption *xmlopt); + + +[conf/namespace.generated.h] + +#ifdef ENABLE_VIR_NAME_SPACE_DEF_PARSE_HOOK + +int +virNameSpaceDefParseHook(xmlNodePtr node, + virNameSpaceDef *def, + const char *instname, + void *parent, + void *opaque, + xmlXPathContextPtr ctxt, + virNetworkXMLOption *xmlopt); + +#endif + + +[conf/namespace.generated.h] + +#ifdef ENABLE_VIR_NAME_SPACE_DEF_PARSE_HOOK_SET_ARGS + +void +virNameSpaceDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/namespace.generated.c] + +int +virNameSpaceDefParseXML(xmlNodePtr node, + virNameSpaceDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED, + xmlXPathContextPtr ctxt, + virNetworkXMLOption *xmlopt) +{ + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_NAME_SPACE_DEF_PARSE_HOOK_SET_ARGS + virNameSpaceDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + def->name = virXMLChildNodeContent(node, "name"); + +#ifdef ENABLE_VIR_NAME_SPACE_DEF_PARSE_HOOK + if (virNameSpaceDefParseHook(node, def, instname, parent, opaque, ctxt, xmlopt) < 0) + goto error; +#endif + + if (xmlopt) + def->ns = xmlopt->ns; + if (def->ns.parse) { + if (virXMLNamespaceRegister(ctxt, &def->ns) < 0) + goto error; + if ((def->ns.parse)(ctxt, &def->namespaceData) < 0) + goto error; + } + return 0; + + error: + virNameSpaceDefClear(def); + return -1; +} + + +[conf/namespace.generated.h] + +int +virNameSpaceDefFormatBuf(virBuffer *buf, + const char *name, + const virNameSpaceDef *def, + const void *parent, + void *opaque); + + +[conf/namespace.generated.h] + +#ifdef ENABLE_VIR_NAME_SPACE_DEF_FORMAT_HOOK + +int +virNameSpaceDefFormatHook(const virNameSpaceDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *nameBuf); + +#endif /* ENABLE_VIR_NAME_SPACE_DEF_FORMAT_HOOK */ + + +[conf/namespace.generated.c] + +int +virNameSpaceDefFormatBuf(virBuffer *buf, + const char *name, + const virNameSpaceDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) nameBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_NAME_SPACE_DEF_FORMAT_HOOK + if (virNameSpaceDefFormatHook(def, parent, opaque, &empty, &shortcut, &nameBuf) < 0) + return -1; +#endif /* ENABLE_VIR_NAME_SPACE_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->name)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + if (def->namespaceData && def->ns.format) + virXMLNamespaceFormatNS(buf, &def->ns); + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&nameBuf, buf); + if (!virBufferTouched(&nameBuf) && def->name) + virBufferEscapeString(&nameBuf, "<name>%s</name>\n", def->name); + virBufferAddBuffer(buf, &nameBuf); + + if (def->namespaceData && def->ns.format) { + if ((def->ns.format)(buf, def->namespaceData) < 0) + return -1; + } + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/namespace.generated.h] + +bool +virNameSpaceDefCheck(const virNameSpaceDef *def, + const void *parent, + void *opaque); + + +[conf/namespace.generated.c] + +#ifndef RESET_VIR_NAME_SPACE_DEF_CHECK + +bool +virNameSpaceDefCheck(const virNameSpaceDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->name; +} + +#endif /* RESET_VIR_NAME_SPACE_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/namespace.h" */ +/* Makesure "namespace.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_NAME_SPACE_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_NAME_SPACE_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_NAME_SPACE_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_NAME_SPACE_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "namespace.generated.h" diff --git a/tests/xmlgenout/required.txt b/tests/xmlgenout/required.txt new file mode 100644 index 00000000..df509284 --- /dev/null +++ b/tests/xmlgenout/required.txt @@ -0,0 +1,236 @@ +[conf/required.generated.h] + +void +virRequiredDefClear(virRequiredDef *def); + + +[conf/required.generated.c] + +void +virRequiredDefClear(virRequiredDef *def) +{ + if (!def) + return; + + g_free(def->name); + def->name = NULL; + + virNetworkBootpDefClear(&def->bootp); +} + + +[conf/required.generated.h] + +int +virRequiredDefParseXML(xmlNodePtr node, + virRequiredDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/required.generated.h] + +#ifdef ENABLE_VIR_REQUIRED_DEF_PARSE_HOOK + +int +virRequiredDefParseHook(xmlNodePtr node, + virRequiredDef *def, + const char *instname, + void *parent, + void *opaque, + xmlNodePtr bootpNode); + +#endif + + +[conf/required.generated.h] + +#ifdef ENABLE_VIR_REQUIRED_DEF_PARSE_HOOK_SET_ARGS + +void +virRequiredDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/required.generated.c] + +int +virRequiredDefParseXML(xmlNodePtr node, + virRequiredDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + xmlNodePtr bootpNode = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_REQUIRED_DEF_PARSE_HOOK_SET_ARGS + virRequiredDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + def->name = virXMLPropString(node, "name"); + if (def->name == NULL) { + virReportError(VIR_ERR_XML_ERROR, + _("Missing '%s' setting in '%s'"), + "name", instname); + goto error; + } + + bootpNode = virXMLChildNode(node, "bootp"); + if (bootpNode == NULL) { + virReportError(VIR_ERR_XML_ERROR, + _("Missing '%s' setting in '%s'"), + "bootp", instname); + goto error; + } + if (bootpNode) { + if (virNetworkBootpDefParseXML(bootpNode, &def->bootp, instname, arg_parent, arg_opaque) < 0) + goto error; + } + +#ifdef ENABLE_VIR_REQUIRED_DEF_PARSE_HOOK + if (virRequiredDefParseHook(node, def, instname, parent, opaque, bootpNode) < 0) + goto error; +#endif + + return 0; + + error: + virRequiredDefClear(def); + return -1; +} + + +[conf/required.generated.h] + +int +virRequiredDefFormatBuf(virBuffer *buf, + const char *name, + const virRequiredDef *def, + const void *parent, + void *opaque); + + +[conf/required.generated.h] + +#ifdef ENABLE_VIR_REQUIRED_DEF_FORMAT_HOOK + +int +virRequiredDefFormatHook(const virRequiredDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *nameBuf, + virBuffer *bootpBuf); + +#endif /* ENABLE_VIR_REQUIRED_DEF_FORMAT_HOOK */ + + +[conf/required.generated.c] + +int +virRequiredDefFormatBuf(virBuffer *buf, + const char *name, + const virRequiredDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) nameBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) bootpBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_REQUIRED_DEF_FORMAT_HOOK + if (virRequiredDefFormatHook(def, parent, opaque, &empty, &shortcut, &nameBuf, &bootpBuf) < 0) + return -1; +#endif /* ENABLE_VIR_REQUIRED_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->name || virNetworkBootpDefCheck(&def->bootp, def, opaque))) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&nameBuf, buf); + if (!virBufferTouched(&nameBuf)) + virBufferEscapeString(&nameBuf, " name='%s'", def->name); + virBufferAddBuffer(buf, &nameBuf); + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(virNetworkBootpDefCheck(&def->bootp, def, opaque))) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&bootpBuf, buf); + if (!virBufferTouched(&bootpBuf)) { + if (virNetworkBootpDefFormatBuf(&bootpBuf, "bootp", &def->bootp, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &bootpBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/required.generated.h] + +bool +virRequiredDefCheck(const virRequiredDef *def, + const void *parent, + void *opaque); + + +[conf/required.generated.c] + +#ifndef RESET_VIR_REQUIRED_DEF_CHECK + +bool +virRequiredDefCheck(const virRequiredDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->name || virNetworkBootpDefCheck(&def->bootp, def, opaque); +} + +#endif /* RESET_VIR_REQUIRED_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/required.h" */ +/* Makesure "required.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_REQUIRED_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_REQUIRED_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_REQUIRED_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_REQUIRED_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "required.generated.h" diff --git a/tests/xmlgenout/skipparse.txt b/tests/xmlgenout/skipparse.txt new file mode 100644 index 00000000..b6f6546a --- /dev/null +++ b/tests/xmlgenout/skipparse.txt @@ -0,0 +1,223 @@ +[conf/skipparse.generated.h] + +void +virSkipParseDefClear(virSkipParseDef *def); + + +[conf/skipparse.generated.c] + +void +virSkipParseDefClear(virSkipParseDef *def) +{ + if (!def) + return; + + def->connections = 0; + + if (def->nifs) { + size_t i; + for (i = 0; i < def->nifs; i++) + virNetworkForwardIfDefClear(&def->ifs[i]); + } + g_free(def->ifs); + def->ifs = NULL; + def->nifs = 0; +} + + +[conf/skipparse.generated.h] + +int +virSkipParseDefParseXML(xmlNodePtr node, + virSkipParseDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/skipparse.generated.h] + +#ifdef ENABLE_VIR_SKIP_PARSE_DEF_PARSE_HOOK + +int +virSkipParseDefParseHook(xmlNodePtr node, + virSkipParseDef *def, + const char *instname, + void *parent, + void *opaque); + +#endif + + +[conf/skipparse.generated.h] + +#ifdef ENABLE_VIR_SKIP_PARSE_DEF_PARSE_HOOK_SET_ARGS + +void +virSkipParseDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/skipparse.generated.c] + +int +virSkipParseDefParseXML(xmlNodePtr node, + virSkipParseDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_SKIP_PARSE_DEF_PARSE_HOOK_SET_ARGS + virSkipParseDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + +#ifdef ENABLE_VIR_SKIP_PARSE_DEF_PARSE_HOOK + if (virSkipParseDefParseHook(node, def, instname, parent, opaque) < 0) + goto error; +#endif + + return 0; + + error: + virSkipParseDefClear(def); + return -1; +} + + +[conf/skipparse.generated.h] + +int +virSkipParseDefFormatBuf(virBuffer *buf, + const char *name, + const virSkipParseDef *def, + const void *parent, + void *opaque); + + +[conf/skipparse.generated.h] + +#ifdef ENABLE_VIR_SKIP_PARSE_DEF_FORMAT_HOOK + +int +virSkipParseDefFormatHook(const virSkipParseDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *connectionsBuf, + virBuffer *ifsBuf); + +#endif /* ENABLE_VIR_SKIP_PARSE_DEF_FORMAT_HOOK */ + + +[conf/skipparse.generated.c] + +int +virSkipParseDefFormatBuf(virBuffer *buf, + const char *name, + const virSkipParseDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) connectionsBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) ifsBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_SKIP_PARSE_DEF_FORMAT_HOOK + if (virSkipParseDefFormatHook(def, parent, opaque, &empty, &shortcut, &connectionsBuf, &ifsBuf) < 0) + return -1; +#endif /* ENABLE_VIR_SKIP_PARSE_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->connections || def->nifs)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&connectionsBuf, buf); + if (!virBufferTouched(&connectionsBuf) && def->connections) + virBufferAsprintf(&connectionsBuf, " connections='%d'", def->connections); + virBufferAddBuffer(buf, &connectionsBuf); + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(def->nifs)) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&ifsBuf, buf); + if (!virBufferTouched(&ifsBuf) && def->nifs) { + size_t i; + for (i = 0; i < def->nifs; i++) { + if (virNetworkForwardIfDefFormatBuf(buf, "if", &def->ifs[i], def, opaque) < 0) + return -1; + } + } + virBufferAddBuffer(buf, &ifsBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/skipparse.generated.h] + +bool +virSkipParseDefCheck(const virSkipParseDef *def, + const void *parent, + void *opaque); + + +[conf/skipparse.generated.c] + +#ifndef RESET_VIR_SKIP_PARSE_DEF_CHECK + +bool +virSkipParseDefCheck(const virSkipParseDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->connections || def->nifs; +} + +#endif /* RESET_VIR_SKIP_PARSE_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/skipparse.h" */ +/* Makesure "skipparse.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_SKIP_PARSE_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_SKIP_PARSE_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_SKIP_PARSE_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_SKIP_PARSE_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "skipparse.generated.h" diff --git a/tests/xmlgenout/specify.txt b/tests/xmlgenout/specify.txt new file mode 100644 index 00000000..dd6dac9c --- /dev/null +++ b/tests/xmlgenout/specify.txt @@ -0,0 +1,291 @@ +[conf/specify.generated.h] + +void +virSpecifyDefClear(virSpecifyDef *def); + + +[conf/specify.generated.c] + +void +virSpecifyDefClear(virSpecifyDef *def) +{ + if (!def) + return; + + def->unit = 0; + + def->expiry = 0; + + virMacAddrClear(&def->mac); + def->mac_specified = false; + + virUUIDClear(&def->uuid); + def->uuid_specified = false; +} + + +[conf/specify.generated.h] + +int +virSpecifyDefParseXML(xmlNodePtr node, + virSpecifyDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/specify.generated.h] + +#ifdef ENABLE_VIR_SPECIFY_DEF_PARSE_HOOK + +int +virSpecifyDefParseHook(xmlNodePtr node, + virSpecifyDef *def, + const char *instname, + void *parent, + void *opaque, + const char *unitStr, + const char *expiryStr, + const char *macStr, + const char *uuidStr); + +#endif + + +[conf/specify.generated.h] + +#ifdef ENABLE_VIR_SPECIFY_DEF_PARSE_HOOK_SET_ARGS + +void +virSpecifyDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/specify.generated.c] + +int +virSpecifyDefParseXML(xmlNodePtr node, + virSpecifyDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + g_autofree char *unitStr = NULL; + g_autofree char *expiryStr = NULL; + g_autofree char *macStr = NULL; + g_autofree char *uuidStr = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_SPECIFY_DEF_PARSE_HOOK_SET_ARGS + virSpecifyDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + unitStr = virXMLPropString(node, "unit"); + if (unitStr) { + if ((def->unit = virNetworkDHCPLeaseTimeUnitTypeFromString(unitStr)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "unit", unitStr, instname); + goto error; + } + } + + expiryStr = virXMLPropString(node, "expiry"); + if (expiryStr) { + if (virStrToLong_ulp(expiryStr, NULL, 0, &def->expiry) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "expiry", expiryStr, instname); + goto error; + } + } + + macStr = virXMLChildPropString(node, "mac/address"); + if (macStr) { + if (virMacAddrParseXML(macStr, &def->mac, instname, arg_parent, arg_opaque) < 0) + goto error; + def->mac_specified = true; + } + + uuidStr = virXMLChildNodeContent(node, "uuid"); + if (uuidStr) { + if (virUUIDParseXML(uuidStr, &def->uuid, instname, arg_parent, arg_opaque) < 0) + goto error; + def->uuid_specified = true; + } + +#ifdef ENABLE_VIR_SPECIFY_DEF_PARSE_HOOK + if (virSpecifyDefParseHook(node, def, instname, parent, opaque, unitStr, expiryStr, macStr, uuidStr) < 0) + goto error; +#endif + + return 0; + + error: + virSpecifyDefClear(def); + return -1; +} + + +[conf/specify.generated.h] + +int +virSpecifyDefFormatBuf(virBuffer *buf, + const char *name, + const virSpecifyDef *def, + const void *parent, + void *opaque); + + +[conf/specify.generated.h] + +#ifdef ENABLE_VIR_SPECIFY_DEF_FORMAT_HOOK + +int +virSpecifyDefFormatHook(const virSpecifyDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *unitBuf, + virBuffer *expiryBuf, + virBuffer *mac_addressBuf, + virBuffer *uuidBuf); + +#endif /* ENABLE_VIR_SPECIFY_DEF_FORMAT_HOOK */ + + +[conf/specify.generated.c] + +int +virSpecifyDefFormatBuf(virBuffer *buf, + const char *name, + const virSpecifyDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) unitBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) expiryBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) mac_addressBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) uuidBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_SPECIFY_DEF_FORMAT_HOOK + if (virSpecifyDefFormatHook(def, parent, opaque, &empty, &shortcut, &unitBuf, &expiryBuf, &mac_addressBuf, &uuidBuf) < 0) + return -1; +#endif /* ENABLE_VIR_SPECIFY_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->expiry || def->uuid_specified || def->mac_specified)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&unitBuf, buf); + if (!virBufferTouched(&unitBuf) && def->expiry) { + const char *str = virNetworkDHCPLeaseTimeUnitTypeToString(def->unit); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "unit", def->unit); + return -1; + } + virBufferAsprintf(&unitBuf, " unit='%s'", str); + } + virBufferAddBuffer(buf, &unitBuf); + + virBufferInheritIndent(&expiryBuf, buf); + if (!virBufferTouched(&expiryBuf) && def->expiry) + virBufferAsprintf(&expiryBuf, " expiry='%lu'", def->expiry); + virBufferAddBuffer(buf, &expiryBuf); + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(def->uuid_specified || def->mac_specified)) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + if (virBufferUse(&mac_addressBuf) || def->mac_specified) { + virBufferAddLit(buf, "<mac"); + + virBufferInheritIndent(&mac_addressBuf, buf); + if (!virBufferTouched(&mac_addressBuf) && def->mac_specified) { + if (virMacAddrFormatBuf(&mac_addressBuf, " address='%s'", &def->mac, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &mac_addressBuf); + + virBufferAddLit(buf, "/>\n"); + } + + virBufferInheritIndent(&uuidBuf, buf); + if (!virBufferTouched(&uuidBuf) && def->uuid_specified) { + if (virUUIDFormatBuf(&uuidBuf, "<uuid>%s</uuid>\n", &def->uuid, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &uuidBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/specify.generated.h] + +bool +virSpecifyDefCheck(const virSpecifyDef *def, + const void *parent, + void *opaque); + + +[conf/specify.generated.c] + +#ifndef RESET_VIR_SPECIFY_DEF_CHECK + +bool +virSpecifyDefCheck(const virSpecifyDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->expiry || def->uuid_specified || def->mac_specified; +} + +#endif /* RESET_VIR_SPECIFY_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/specify.h" */ +/* Makesure "specify.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_SPECIFY_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_SPECIFY_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_SPECIFY_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_SPECIFY_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "specify.generated.h" diff --git a/tests/xmlgenout/xmlattr.txt b/tests/xmlgenout/xmlattr.txt new file mode 100644 index 00000000..228eb3cc --- /dev/null +++ b/tests/xmlgenout/xmlattr.txt @@ -0,0 +1,252 @@ +[conf/xmlattr.generated.h] + +void +virXMLAttrDefClear(virXMLAttrDef *def); + + +[conf/xmlattr.generated.c] + +void +virXMLAttrDefClear(virXMLAttrDef *def) +{ + if (!def) + return; + + g_free(def->family); + def->family = NULL; + + def->localPTR = 0; + + g_free(def->tftproot); + def->tftproot = NULL; +} + + +[conf/xmlattr.generated.h] + +int +virXMLAttrDefParseXML(xmlNodePtr node, + virXMLAttrDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/xmlattr.generated.h] + +#ifdef ENABLE_VIR_XMLATTR_DEF_PARSE_HOOK + +int +virXMLAttrDefParseHook(xmlNodePtr node, + virXMLAttrDef *def, + const char *instname, + void *parent, + void *opaque, + const char *localPTRStr); + +#endif + + +[conf/xmlattr.generated.h] + +#ifdef ENABLE_VIR_XMLATTR_DEF_PARSE_HOOK_SET_ARGS + +void +virXMLAttrDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/xmlattr.generated.c] + +int +virXMLAttrDefParseXML(xmlNodePtr node, + virXMLAttrDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + g_autofree char *localPTRStr = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_XMLATTR_DEF_PARSE_HOOK_SET_ARGS + virXMLAttrDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + def->family = virXMLPropString(node, "family"); + + localPTRStr = virXMLPropString(node, "localPtr"); + if (localPTRStr) { + if ((def->localPTR = virTristateBoolTypeFromString(localPTRStr)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "localPtr", localPTRStr, instname); + goto error; + } + } + + def->tftproot = virXMLChildPropString(node, "tftp/root"); + +#ifdef ENABLE_VIR_XMLATTR_DEF_PARSE_HOOK + if (virXMLAttrDefParseHook(node, def, instname, parent, opaque, localPTRStr) < 0) + goto error; +#endif + + return 0; + + error: + virXMLAttrDefClear(def); + return -1; +} + + +[conf/xmlattr.generated.h] + +int +virXMLAttrDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLAttrDef *def, + const void *parent, + void *opaque); + + +[conf/xmlattr.generated.h] + +#ifdef ENABLE_VIR_XMLATTR_DEF_FORMAT_HOOK + +int +virXMLAttrDefFormatHook(const virXMLAttrDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *familyBuf, + virBuffer *localPTRBuf, + virBuffer *tftp_rootBuf); + +#endif /* ENABLE_VIR_XMLATTR_DEF_FORMAT_HOOK */ + + +[conf/xmlattr.generated.c] + +int +virXMLAttrDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLAttrDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) familyBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) localPTRBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) tftp_rootBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_XMLATTR_DEF_FORMAT_HOOK + if (virXMLAttrDefFormatHook(def, parent, opaque, &empty, &shortcut, &familyBuf, &localPTRBuf, &tftp_rootBuf) < 0) + return -1; +#endif /* ENABLE_VIR_XMLATTR_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->family || def->localPTR > 0 || def->tftproot)) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&familyBuf, buf); + if (!virBufferTouched(&familyBuf) && def->family) + virBufferEscapeString(&familyBuf, " family='%s'", def->family); + virBufferAddBuffer(buf, &familyBuf); + + virBufferInheritIndent(&localPTRBuf, buf); + if (!virBufferTouched(&localPTRBuf) && def->localPTR > 0) { + const char *str = virTristateBoolTypeToString(def->localPTR); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "localPtr", def->localPTR); + return -1; + } + virBufferAsprintf(&localPTRBuf, " localPtr='%s'", str); + } + virBufferAddBuffer(buf, &localPTRBuf); + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(def->tftproot)) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + if (virBufferUse(&tftp_rootBuf) || def->tftproot) { + virBufferAddLit(buf, "<tftp"); + + virBufferInheritIndent(&tftp_rootBuf, buf); + if (!virBufferTouched(&tftp_rootBuf) && def->tftproot) + virBufferEscapeString(&tftp_rootBuf, " root='%s'", def->tftproot); + virBufferAddBuffer(buf, &tftp_rootBuf); + + virBufferAddLit(buf, "/>\n"); + } + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/xmlattr.generated.h] + +bool +virXMLAttrDefCheck(const virXMLAttrDef *def, + const void *parent, + void *opaque); + + +[conf/xmlattr.generated.c] + +#ifndef RESET_VIR_XMLATTR_DEF_CHECK + +bool +virXMLAttrDefCheck(const virXMLAttrDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->family || def->localPTR > 0 || def->tftproot; +} + +#endif /* RESET_VIR_XMLATTR_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/xmlattr.h" */ +/* Makesure "xmlattr.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_XMLATTR_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_XMLATTR_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_XMLATTR_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_XMLATTR_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "xmlattr.generated.h" diff --git a/tests/xmlgenout/xmlelem.txt b/tests/xmlgenout/xmlelem.txt new file mode 100644 index 00000000..d910eda2 --- /dev/null +++ b/tests/xmlgenout/xmlelem.txt @@ -0,0 +1,243 @@ +[conf/xmlelem.generated.h] + +void +virXMLElemDefClear(virXMLElemDef *def); + + +[conf/xmlelem.generated.c] + +void +virXMLElemDefClear(virXMLElemDef *def) +{ + if (!def) + return; + + virPortRangeClear(&def->port); + + virSocketAddrRangeClear(&def->addr); + + virUUIDClear(&def->uuid); +} + + +[conf/xmlelem.generated.h] + +int +virXMLElemDefParseXML(xmlNodePtr node, + virXMLElemDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/xmlelem.generated.h] + +#ifdef ENABLE_VIR_XMLELEM_DEF_PARSE_HOOK + +int +virXMLElemDefParseHook(xmlNodePtr node, + virXMLElemDef *def, + const char *instname, + void *parent, + void *opaque, + xmlNodePtr portNode, + xmlNodePtr addrNode, + const char *uuidStr); + +#endif + + +[conf/xmlelem.generated.h] + +#ifdef ENABLE_VIR_XMLELEM_DEF_PARSE_HOOK_SET_ARGS + +void +virXMLElemDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/xmlelem.generated.c] + +int +virXMLElemDefParseXML(xmlNodePtr node, + virXMLElemDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + xmlNodePtr portNode = NULL; + xmlNodePtr addrNode = NULL; + g_autofree char *uuidStr = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_XMLELEM_DEF_PARSE_HOOK_SET_ARGS + virXMLElemDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + portNode = virXMLChildNode(node, "port"); + if (portNode) { + if (virPortRangeParseXML(portNode, &def->port, instname, arg_parent, arg_opaque) < 0) + goto error; + } + + addrNode = virXMLChildNode(node, "address"); + if (addrNode) { + if (virSocketAddrRangeParseXML(addrNode, &def->addr, instname, arg_parent, arg_opaque) < 0) + goto error; + } + + uuidStr = virXMLChildNodeContent(node, "uuid"); + if (uuidStr) { + if (virUUIDParseXML(uuidStr, &def->uuid, instname, arg_parent, arg_opaque) < 0) + goto error; + } + +#ifdef ENABLE_VIR_XMLELEM_DEF_PARSE_HOOK + if (virXMLElemDefParseHook(node, def, instname, parent, opaque, portNode, addrNode, uuidStr) < 0) + goto error; +#endif + + return 0; + + error: + virXMLElemDefClear(def); + return -1; +} + + +[conf/xmlelem.generated.h] + +int +virXMLElemDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLElemDef *def, + const void *parent, + void *opaque); + + +[conf/xmlelem.generated.h] + +#ifdef ENABLE_VIR_XMLELEM_DEF_FORMAT_HOOK + +int +virXMLElemDefFormatHook(const virXMLElemDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *portBuf, + virBuffer *addrBuf, + virBuffer *uuidBuf); + +#endif /* ENABLE_VIR_XMLELEM_DEF_FORMAT_HOOK */ + + +[conf/xmlelem.generated.c] + +int +virXMLElemDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLElemDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) portBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) addrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) uuidBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_XMLELEM_DEF_FORMAT_HOOK + if (virXMLElemDefFormatHook(def, parent, opaque, &empty, &shortcut, &portBuf, &addrBuf, &uuidBuf) < 0) + return -1; +#endif /* ENABLE_VIR_XMLELEM_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(virPortRangeCheck(&def->port, def, opaque) || virSocketAddrRangeCheck(&def->addr, def, opaque) || virUUIDCheck(&def->uuid, def, opaque))) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + virBufferInheritIndent(&portBuf, buf); + if (!virBufferTouched(&portBuf) && virPortRangeCheck(&def->port, def, opaque)) { + if (virPortRangeFormatBuf(&portBuf, "port", &def->port, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &portBuf); + + virBufferInheritIndent(&addrBuf, buf); + if (!virBufferTouched(&addrBuf) && virSocketAddrRangeCheck(&def->addr, def, opaque)) { + if (virSocketAddrRangeFormatBuf(&addrBuf, "address", &def->addr, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &addrBuf); + + virBufferInheritIndent(&uuidBuf, buf); + if (!virBufferTouched(&uuidBuf) && virUUIDCheck(&def->uuid, def, opaque)) { + if (virUUIDFormatBuf(&uuidBuf, "<uuid>%s</uuid>\n", &def->uuid, def, opaque) < 0) + return -1; + } + virBufferAddBuffer(buf, &uuidBuf); + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/xmlelem.generated.h] + +bool +virXMLElemDefCheck(const virXMLElemDef *def, + const void *parent, + void *opaque); + + +[conf/xmlelem.generated.c] + +#ifndef RESET_VIR_XMLELEM_DEF_CHECK + +bool +virXMLElemDefCheck(const virXMLElemDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return virPortRangeCheck(&def->port, def, opaque) || virSocketAddrRangeCheck(&def->addr, def, opaque) || virUUIDCheck(&def->uuid, def, opaque); +} + +#endif /* RESET_VIR_XMLELEM_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/xmlelem.h" */ +/* Makesure "xmlelem.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_XMLELEM_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_XMLELEM_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_XMLELEM_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_XMLELEM_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "xmlelem.generated.h" diff --git a/tests/xmlgenout/xmlgroup.txt b/tests/xmlgenout/xmlgroup.txt new file mode 100644 index 00000000..ff9d7e09 --- /dev/null +++ b/tests/xmlgenout/xmlgroup.txt @@ -0,0 +1,204 @@ +[conf/xmlgroup.generated.h] + +void +virXMLGroupDefClear(virXMLGroupDef *def); + + +[conf/xmlgroup.generated.c] + +void +virXMLGroupDefClear(virXMLGroupDef *def) +{ + if (!def) + return; + + virUtilAuthDefClear(&def->auth); +} + + +[conf/xmlgroup.generated.h] + +int +virXMLGroupDefParseXML(xmlNodePtr node, + virXMLGroupDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/xmlgroup.generated.h] + +#ifdef ENABLE_VIR_XMLGROUP_DEF_PARSE_HOOK + +int +virXMLGroupDefParseHook(xmlNodePtr node, + virXMLGroupDef *def, + const char *instname, + void *parent, + void *opaque); + +#endif + + +[conf/xmlgroup.generated.h] + +#ifdef ENABLE_VIR_XMLGROUP_DEF_PARSE_HOOK_SET_ARGS + +void +virXMLGroupDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/xmlgroup.generated.c] + +int +virXMLGroupDefParseXML(xmlNodePtr node, + virXMLGroupDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_XMLGROUP_DEF_PARSE_HOOK_SET_ARGS + virXMLGroupDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + if (virUtilAuthDefParseXML(node, &def->auth, instname, arg_parent, arg_opaque) < 0) + goto error; + +#ifdef ENABLE_VIR_XMLGROUP_DEF_PARSE_HOOK + if (virXMLGroupDefParseHook(node, def, instname, parent, opaque) < 0) + goto error; +#endif + + return 0; + + error: + virXMLGroupDefClear(def); + return -1; +} + + +[conf/xmlgroup.generated.h] + +int +virXMLGroupDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLGroupDef *def, + const void *parent, + void *opaque); + + +[conf/xmlgroup.generated.h] + +#ifdef ENABLE_VIR_XMLGROUP_DEF_FORMAT_HOOK + +int +virXMLGroupDefFormatHook(const virXMLGroupDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut); + +#endif /* ENABLE_VIR_XMLGROUP_DEF_FORMAT_HOOK */ + + +[conf/xmlgroup.generated.c] + +int +virXMLGroupDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLGroupDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_XMLGROUP_DEF_FORMAT_HOOK + if (virXMLGroupDefFormatHook(def, parent, opaque, &empty, &shortcut) < 0) + return -1; +#endif /* ENABLE_VIR_XMLGROUP_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(virUtilAuthDefCheckAttr(&def->auth, def, opaque) || virUtilAuthDefCheckElem(&def->auth, def, opaque))) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + if (virUtilAuthDefFormatAttr(buf, &def->auth, def, opaque) < 0) + return -1; + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(virUtilAuthDefCheckElem(&def->auth, def, opaque))) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + if (virUtilAuthDefFormatElem(buf, &def->auth, def, opaque) < 0) + return -1; + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/xmlgroup.generated.h] + +bool +virXMLGroupDefCheck(const virXMLGroupDef *def, + const void *parent, + void *opaque); + + +[conf/xmlgroup.generated.c] + +#ifndef RESET_VIR_XMLGROUP_DEF_CHECK + +bool +virXMLGroupDefCheck(const virXMLGroupDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return virUtilAuthDefCheckAttr(&def->auth, def, opaque) || virUtilAuthDefCheckElem(&def->auth, def, opaque); +} + +#endif /* RESET_VIR_XMLGROUP_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/xmlgroup.h" */ +/* Makesure "xmlgroup.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_XMLGROUP_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_XMLGROUP_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_XMLGROUP_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_XMLGROUP_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "xmlgroup.generated.h" diff --git a/tests/xmlgenout/xmlswitch.txt b/tests/xmlgenout/xmlswitch.txt new file mode 100644 index 00000000..772f1353 --- /dev/null +++ b/tests/xmlgenout/xmlswitch.txt @@ -0,0 +1,470 @@ +[conf/xmlswitch.generated.h] + +void +virXMLSwitchDefClear(virXMLSwitchDef *def); + + +[conf/xmlswitch.generated.c] + +void +virXMLSwitchDefClear(virXMLSwitchDef *def) +{ + if (!def) + return; + + switch (def->type) { + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + virDomainGraphicsSDLDefClear(&def->data.sdl); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + virDomainGraphicsVNCDefClear(&def->data.vnc); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + virDomainGraphicsRDPDefClear(&def->data.rdp); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + virDomainGraphicsDesktopDefClear(&def->data.desktop); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + virDomainGraphicsSpiceDefClear(&def->data.spice); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + virDomainGraphicsEGLHeadlessDefClear(&def->data.egl_headless); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } + + def->type = 0; +} + + +[conf/xmlswitch.generated.h] + +int +virXMLSwitchDefParseXML(xmlNodePtr node, + virXMLSwitchDef *def, + const char *instname, + void *parent, + void *opaque); + + +[conf/xmlswitch.generated.h] + +#ifdef ENABLE_VIR_XMLSWITCH_DEF_PARSE_HOOK + +int +virXMLSwitchDefParseHook(xmlNodePtr node, + virXMLSwitchDef *def, + const char *instname, + void *parent, + void *opaque, + const char *typeStr); + +#endif + + +[conf/xmlswitch.generated.h] + +#ifdef ENABLE_VIR_XMLSWITCH_DEF_PARSE_HOOK_SET_ARGS + +void +virXMLSwitchDefParseXMLSetArgs(xmlNodePtr node, + void *parent, + void **pparent, + void **popaque); + +#endif + + +[conf/xmlswitch.generated.c] + +int +virXMLSwitchDefParseXML(xmlNodePtr node, + virXMLSwitchDef *def, + const char *instname G_GNUC_UNUSED, + void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + g_autofree char *typeStr = NULL; + void *arg_parent G_GNUC_UNUSED = def; + void *arg_opaque G_GNUC_UNUSED = opaque; + + if (!def) + goto error; + +#ifdef ENABLE_VIR_XMLSWITCH_DEF_PARSE_HOOK_SET_ARGS + virXMLSwitchDefParseXMLSetArgs(node, parent, &arg_parent, &arg_opaque); +#endif + + typeStr = virXMLPropString(node, "type"); + if (typeStr) { + if ((def->type = virDomainGraphicsTypeFromString(typeStr)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid '%s' setting '%s' in '%s'"), + "type", typeStr, instname); + goto error; + } + } + + switch (def->type) { + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (virDomainGraphicsSDLDefParseXML(node, &def->data.sdl, instname, arg_parent, arg_opaque) < 0) + goto error; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (virDomainGraphicsVNCDefParseXML(node, &def->data.vnc, instname, arg_parent, arg_opaque) < 0) + goto error; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + if (virDomainGraphicsRDPDefParseXML(node, &def->data.rdp, instname, arg_parent, arg_opaque) < 0) + goto error; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + if (virDomainGraphicsDesktopDefParseXML(node, &def->data.desktop, instname, arg_parent, arg_opaque) < 0) + goto error; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + if (virDomainGraphicsSpiceDefParseXML(node, &def->data.spice, instname, arg_parent, arg_opaque) < 0) + goto error; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + if (virDomainGraphicsEGLHeadlessDefParseXML(node, &def->data.egl_headless, instname, arg_parent, arg_opaque) < 0) + goto error; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } + +#ifdef ENABLE_VIR_XMLSWITCH_DEF_PARSE_HOOK + if (virXMLSwitchDefParseHook(node, def, instname, parent, opaque, typeStr) < 0) + goto error; +#endif + + return 0; + + error: + virXMLSwitchDefClear(def); + return -1; +} + + +[conf/xmlswitch.generated.h] + +bool +virXMLSwitchDefDataCheckAttr(const virXMLSwitchDef *def, + void *opaque); + + +[conf/xmlswitch.generated.c] + +#ifndef RESET_VIR_XMLSWITCH_DEF_DATA_CHECK_ATTR + +bool +virXMLSwitchDefDataCheckAttr(const virXMLSwitchDef *def, + void *opaque G_GNUC_UNUSED) +{ + bool ret = false; + if (!def) + return false; + + switch (def->type) { + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + ret = virDomainGraphicsSDLDefCheckAttr(&def->data.sdl, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + ret = virDomainGraphicsVNCDefCheckAttr(&def->data.vnc, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + ret = virDomainGraphicsRDPDefCheckAttr(&def->data.rdp, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + ret = virDomainGraphicsDesktopDefCheckAttr(&def->data.desktop, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + ret = virDomainGraphicsSpiceDefCheckAttr(&def->data.spice, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + ret = virDomainGraphicsEGLHeadlessDefCheckAttr(&def->data.egl_headless, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } + + return ret; +} + +#endif /* RESET_VIR_XMLSWITCH_DEF_DATA_CHECK_ATTR */ + + +[conf/xmlswitch.generated.h] + +bool +virXMLSwitchDefDataCheckElem(const virXMLSwitchDef *def, + void *opaque); + + +[conf/xmlswitch.generated.c] + +#ifndef RESET_VIR_XMLSWITCH_DEF_DATA_CHECK_ELEM + +bool +virXMLSwitchDefDataCheckElem(const virXMLSwitchDef *def, + void *opaque G_GNUC_UNUSED) +{ + bool ret = false; + if (!def) + return false; + + switch (def->type) { + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + ret = virDomainGraphicsSDLDefCheckElem(&def->data.sdl, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + ret = virDomainGraphicsVNCDefCheckElem(&def->data.vnc, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + ret = virDomainGraphicsRDPDefCheckElem(&def->data.rdp, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + ret = virDomainGraphicsDesktopDefCheckElem(&def->data.desktop, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + ret = virDomainGraphicsSpiceDefCheckElem(&def->data.spice, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + ret = virDomainGraphicsEGLHeadlessDefCheckElem(&def->data.egl_headless, def, opaque); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } + + return ret; +} + +#endif /* RESET_VIR_XMLSWITCH_DEF_DATA_CHECK_ELEM */ + + +[conf/xmlswitch.generated.h] + +int +virXMLSwitchDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLSwitchDef *def, + const void *parent, + void *opaque); + + +[conf/xmlswitch.generated.h] + +#ifdef ENABLE_VIR_XMLSWITCH_DEF_FORMAT_HOOK + +int +virXMLSwitchDefFormatHook(const virXMLSwitchDef *def, + const void *parent, + const void *opaque, + virTristateBool *empty, + virTristateBool *shortcut, + virBuffer *typeBuf); + +#endif /* ENABLE_VIR_XMLSWITCH_DEF_FORMAT_HOOK */ + + +[conf/xmlswitch.generated.c] + +int +virXMLSwitchDefFormatBuf(virBuffer *buf, + const char *name, + const virXMLSwitchDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virTristateBool empty G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool shortcut G_GNUC_UNUSED = VIR_TRISTATE_BOOL_ABSENT; + g_auto(virBuffer) typeBuf = VIR_BUFFER_INITIALIZER; + + if (!def || !buf) + return 0; + +#ifdef ENABLE_VIR_XMLSWITCH_DEF_FORMAT_HOOK + if (virXMLSwitchDefFormatHook(def, parent, opaque, &empty, &shortcut, &typeBuf) < 0) + return -1; +#endif /* ENABLE_VIR_XMLSWITCH_DEF_FORMAT_HOOK */ + + if (empty != VIR_TRISTATE_BOOL_NO) + if (empty || !(def->type >= 0 || virXMLSwitchDefDataCheckAttr(def, opaque) || virXMLSwitchDefDataCheckElem(def, opaque))) + return 0; + + virBufferAsprintf(buf, "<%s", name); + + virBufferInheritIndent(&typeBuf, buf); + if (!virBufferTouched(&typeBuf) && def->type >= 0) { + const char *str = virDomainGraphicsTypeToString(def->type); + if (!str) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown %s type %d"), + "type", def->type); + return -1; + } + virBufferAsprintf(&typeBuf, " type='%s'", str); + } + virBufferAddBuffer(buf, &typeBuf); + + switch (def->type) { + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (virDomainGraphicsSDLDefFormatAttr(buf, &def->data.sdl, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (virDomainGraphicsVNCDefFormatAttr(buf, &def->data.vnc, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + if (virDomainGraphicsRDPDefFormatAttr(buf, &def->data.rdp, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + if (virDomainGraphicsDesktopDefFormatAttr(buf, &def->data.desktop, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + if (virDomainGraphicsSpiceDefFormatAttr(buf, &def->data.spice, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + if (virDomainGraphicsEGLHeadlessDefFormatAttr(buf, &def->data.egl_headless, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } + + if (shortcut != VIR_TRISTATE_BOOL_NO) { + if (shortcut || !(virXMLSwitchDefDataCheckElem(def, opaque))) { + virBufferAddLit(buf, "/>\n"); + return 0; + } + } + + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + + switch (def->type) { + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (virDomainGraphicsSDLDefFormatElem(buf, &def->data.sdl, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (virDomainGraphicsVNCDefFormatElem(buf, &def->data.vnc, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + if (virDomainGraphicsRDPDefFormatElem(buf, &def->data.rdp, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + if (virDomainGraphicsDesktopDefFormatElem(buf, &def->data.desktop, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + if (virDomainGraphicsSpiceDefFormatElem(buf, &def->data.spice, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + if (virDomainGraphicsEGLHeadlessDefFormatElem(buf, &def->data.egl_headless, def, opaque) < 0) + return -1; + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } + + virBufferAdjustIndent(buf, -2); + virBufferAsprintf(buf, "</%s>\n", name); + + return 0; +} + + +[conf/xmlswitch.generated.h] + +bool +virXMLSwitchDefCheck(const virXMLSwitchDef *def, + const void *parent, + void *opaque); + + +[conf/xmlswitch.generated.c] + +#ifndef RESET_VIR_XMLSWITCH_DEF_CHECK + +bool +virXMLSwitchDefCheck(const virXMLSwitchDef *def, + const void *parent G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (!def) + return false; + + return def->type >= 0 || virXMLSwitchDefDataCheckAttr(def, opaque) || virXMLSwitchDefDataCheckElem(def, opaque); +} + +#endif /* RESET_VIR_XMLSWITCH_DEF_CHECK */ + + +[Tips] + +/* Put these lines at the bottom of "conf/xmlswitch.h" */ +/* Makesure "xmlswitch.h" to be appended into conf_xmlgen_input in src/conf/meson.build */ + +/* Define macro to enable hook or redefine check when necessary */ +/* #define ENABLE_VIR_XMLSWITCH_DEF_PARSE_HOOK */ +/* #define ENABLE_VIR_XMLSWITCH_DEF_PARSE_HOOK_SET_ARGS */ +/* #define ENABLE_VIR_XMLSWITCH_DEF_FORMAT_HOOK */ + +/* #define RESET_VIR_XMLSWITCH_DEF_CHECK */ + +/* Makesure below is the bottom line! */ +#include "xmlswitch.generated.h" diff --git a/tests/xmlgentest.c b/tests/xmlgentest.c new file mode 100644 index 00000000..a20773dc --- /dev/null +++ b/tests/xmlgentest.c @@ -0,0 +1,107 @@ +#include <config.h> + +#include "internal.h" +#include "testutils.h" +#include "vircommand.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +typedef enum { + TEST_COMPARE_RESULT_SUCCESS, + TEST_COMPARE_RESULT_FAIL_GENERATE, + TEST_COMPARE_RESULT_FAIL_COMPARE, +} testCompareResult; + +struct testInfo { + const char *name; + const char *target; + testCompareResult expectResult; +}; + +static int +testCompareGenFiles(const void *data) +{ + int ret = 0; + testCompareResult result = TEST_COMPARE_RESULT_SUCCESS; + const struct testInfo *info = data; + g_autofree char *outbuf = NULL; + g_autoptr(virCommand) cmd = NULL; + g_autofree char *outfile = NULL; + char *actual = NULL; + + cmd = virCommandNewArgList(PYTHON3, "-B", + abs_top_srcdir "/scripts/xmlgen/main.py", + "-s", abs_srcdir "/xmlgenin", + "-b", abs_builddir "/xmlgenin", + "-d", "", + "show", info->target, NULL); + + virCommandSetOutputBuffer(cmd, &outbuf); + + if (virCommandRun(cmd, NULL) < 0) { + result = TEST_COMPARE_RESULT_FAIL_GENERATE; + goto cleanup; + } + + /* Skip first empty line */ + if (outbuf && outbuf[0] == '\n') + actual = outbuf + 1; + else + actual = outbuf; + + outfile = g_strdup_printf("%s/xmlgenout/%s.txt", abs_srcdir, info->name); + if (virTestCompareToFile(actual, outfile) < 0) { + result = TEST_COMPARE_RESULT_FAIL_COMPARE; + goto cleanup; + } + + cleanup: + if (result == info->expectResult) { + ret = 0; + if (info->expectResult != TEST_COMPARE_RESULT_SUCCESS) { + VIR_TEST_DEBUG("Got expected failure code=%d msg=%s", + result, virGetLastErrorMessage()); + } + } else { + ret = -1; + VIR_TEST_DEBUG("Expected result code=%d but received code=%d", + info->expectResult, result); + } + virResetLastError(); + + return ret; +} + +static int +mymain(void) +{ + int ret = 0; + +#define DO_TEST(name, target) \ + do { \ + const struct testInfo info = {name, target, TEST_COMPARE_RESULT_SUCCESS}; \ + if (virTestRun("xmlgen: generate for " target " in test " name, \ + testCompareGenFiles, &info) < 0) \ + ret = -1; \ + } while (0) + + DO_TEST("empty", "virEmptyDef"); + DO_TEST("genparse", "virGenParseDef"); + DO_TEST("genformat", "virGenFormatDef"); + DO_TEST("genformat-separate", "virSeparateDef"); + DO_TEST("xmlattr", "virXMLAttrDef"); + DO_TEST("xmlelem", "virXMLElemDef"); + DO_TEST("array", "virArrayDef"); + DO_TEST("required", "virRequiredDef"); + DO_TEST("specify", "virSpecifyDef"); + DO_TEST("skipparse", "virSkipParseDef"); + DO_TEST("xmlgroup", "virXMLGroupDef"); + DO_TEST("xmlswitch", "virXMLSwitchDef"); + DO_TEST("enum-first-item", "virEnumFirstItemDef"); + DO_TEST("namespace", "virNameSpaceDef"); + DO_TEST("external", "virExternalDef"); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIR_TEST_MAIN(mymain) -- 2.25.1