gopkg.in/libvirt/libvirt-go-xml.v7@v7.4.0/xml_test.go (about)

     1  // +build xmlroundtrip
     2  
     3  /*
     4   * This file is part of the libvirt-go-xml project
     5   *
     6   * Permission is hereby granted, free of charge, to any person obtaining a copy
     7   * of this software and associated documentation files (the "Software"), to deal
     8   * in the Software without restriction, including without limitation the rights
     9   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10   * copies of the Software, and to permit persons to whom the Software is
    11   * furnished to do so, subject to the following conditions:
    12   *
    13   * The above copyright notice and this permission notice shall be included in
    14   * all copies or substantial portions of the Software.
    15   *
    16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22   * THE SOFTWARE.
    23   *
    24   * Copyright (C) 2016 Red Hat, Inc.
    25   *
    26   */
    27  
    28  package libvirtxml
    29  
    30  import (
    31  	"fmt"
    32  	"io/ioutil"
    33  	"os"
    34  	"os/exec"
    35  	"strings"
    36  	"testing"
    37  )
    38  
    39  var xmldirs = []string{
    40  	"testdata/libvirt/tests/bhyveargv2xmldata",
    41  	"testdata/libvirt/tests/bhyvexml2argvdata",
    42  	"testdata/libvirt/tests/bhyvexml2xmloutdata",
    43  	"testdata/libvirt/tests/capabilityschemadata",
    44  	"testdata/libvirt/tests/cputestdata",
    45  	"testdata/libvirt/tests/domaincapsdata",
    46  	"testdata/libvirt/tests/domainconfdata",
    47  	"testdata/libvirt/tests/domainschemadata",
    48  	"testdata/libvirt/tests/genericxml2xmlindata",
    49  	"testdata/libvirt/tests/genericxml2xmloutdata",
    50  	"testdata/libvirt/tests/interfaceschemadata",
    51  	"testdata/libvirt/tests/libxlxml2domconfigdata",
    52  	"testdata/libvirt/tests/lxcconf2xmldata",
    53  	"testdata/libvirt/tests/lxcxml2xmldata",
    54  	"testdata/libvirt/tests/lxcxml2xmloutdata",
    55  	"testdata/libvirt/tests/networkxml2confdata",
    56  	"testdata/libvirt/tests/networkxml2firewalldata",
    57  	"testdata/libvirt/tests/networkxml2xmlin",
    58  	"testdata/libvirt/tests/networkxml2xmlout",
    59  	"testdata/libvirt/tests/networkxml2xmlupdatein",
    60  	"testdata/libvirt/tests/networkxml2xmlupdateout",
    61  	"testdata/libvirt/tests/nodedevschemadata",
    62  	"testdata/libvirt/tests/nwfilterxml2firewalldata",
    63  	"testdata/libvirt/tests/nwfilterxml2xmlin",
    64  	"testdata/libvirt/tests/nwfilterxml2xmlout",
    65  	"testdata/libvirt/tests/qemuagentdata",
    66  	"testdata/libvirt/tests/qemucapabilitiesdata",
    67  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlin",
    68  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlout",
    69  	"testdata/libvirt/tests/qemuhotplugtestcpus",
    70  	"testdata/libvirt/tests/qemuhotplugtestdevices",
    71  	"testdata/libvirt/tests/qemuhotplugtestdomains",
    72  	"testdata/libvirt/tests/qemumemlockdata",
    73  	"testdata/libvirt/tests/qemuxml2argvdata",
    74  	"testdata/libvirt/tests/qemuxml2xmloutdata",
    75  	"testdata/libvirt/tests/secretxml2xmlin",
    76  	"testdata/libvirt/tests/securityselinuxlabeldata",
    77  	"testdata/libvirt/tests/storagepoolschemadata",
    78  	"testdata/libvirt/tests/storagepoolxml2xmlin",
    79  	"testdata/libvirt/tests/storagepoolxml2xmlout",
    80  	"testdata/libvirt/tests/storagevolschemadata",
    81  	"testdata/libvirt/tests/storagevolxml2xmlin",
    82  	"testdata/libvirt/tests/storagevolxml2xmlout",
    83  	"testdata/libvirt/tests/vircaps2xmldata",
    84  	"testdata/libvirt/tests/virnwfilterbindingxml2xmldata",
    85  	"testdata/libvirt/tests/virnetworkportxml2xmldata",
    86  	"testdata/libvirt/tests/virnwfilterbindingxml2xmldata",
    87  	"testdata/libvirt/tests/virstorageutildata",
    88  	"testdata/libvirt/tests/vmx2xmldata",
    89  	"testdata/libvirt/tests/xlconfigdata",
    90  	"testdata/libvirt/tests/xmconfigdata",
    91  	"testdata/libvirt/tests/xml2vmxdata",
    92  }
    93  
    94  var consoletype = "/domain[0]/devices[0]/console[0]/@type"
    95  var volsrc = "/volume[0]/source[0]"
    96  
    97  var blacklist = map[string]bool{
    98  	// intentionally invalid xml
    99  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-unix-redirdev-missing-path.xml":  true,
   100  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-unix-rng-missing-path.xml":       true,
   101  	"testdata/libvirt/tests/qemuxml2argvdata/virtio-rng-egd-crash.xml":                    true,
   102  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-unix-smartcard-missing-path.xml": true,
   103  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-tcp-multiple-source.xml":         true,
   104  	"testdata/libvirt/tests/networkxml2xmlupdatein/dns-host-gateway-incomplete.xml":       true,
   105  	"testdata/libvirt/tests/networkxml2xmlupdatein/host-new-incomplete.xml":               true,
   106  	"testdata/libvirt/tests/networkxml2xmlupdatein/unparsable-dns-host.xml":               true,
   107  	// udp source in different order
   108  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-udp.xml":                 true,
   109  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-udp-multiple-source.xml": true,
   110  }
   111  
   112  var extraActualNodes = map[string][]string{
   113  
   114  	"testdata/libvirt/tests/qemuxml2argvdata/disk-discard.xml": []string{
   115  		"/domain[0]/devices[0]/disk[0]/@type",
   116  	},
   117  	"testdata/libvirt/tests/qemuxml2argvdata/fs9p-ccw.xml": []string{
   118  		"/domain[0]/devices[0]/filesystem[1]/@type",
   119  		"/domain[0]/devices[0]/filesystem[2]/@type",
   120  	},
   121  	"testdata/libvirt/tests/qemuxml2argvdata/fs9p.xml": []string{
   122  		"/domain[0]/devices[0]/filesystem[1]/@type",
   123  		"/domain[0]/devices[0]/filesystem[2]/@type",
   124  	},
   125  	"testdata/libvirt/tests/qemuxml2argvdata/disk-drive-discard.xml": []string{
   126  		"/domain[0]/devices[0]/disk[0]/@type",
   127  	},
   128  	"testdata/libvirt/tests/genericxml2xmlindata/chardev-udp.xml": []string{
   129  		"/domain[0]/devices[0]/channel[0]/source[0]/@mode",
   130  	},
   131  	"testdata/libvirt/tests/qemuxml2argvdata/disk-mirror-old.xml": []string{
   132  		"/domain[0]/devices[0]/disk[0]/mirror[0]/@type",
   133  		"/domain[0]/devices[0]/disk[0]/mirror[0]/source[0]",
   134  		"/domain[0]/devices[0]/disk[2]/mirror[0]/@type",
   135  		"/domain[0]/devices[0]/disk[2]/mirror[0]/format[0]",
   136  		"/domain[0]/devices[0]/disk[2]/mirror[0]/source[0]",
   137  	},
   138  	"testdata/libvirt/tests/xlconfigdata/test-fullvirt-ovswitch-tagged.xml": []string{
   139  		"/domain[0]/devices[0]/interface[0]/virtualport[0]/parameters[0]",
   140  	},
   141  	"testdata/libvirt/tests/xlconfigdata/test-fullvirt-ovswitch-trunked.xml": []string{
   142  		"/domain[0]/devices[0]/interface[0]/virtualport[0]/parameters[0]",
   143  	},
   144  
   145  	"testdata/libvirt/tests/networkxml2xmlin/openvswitch-net.xml": []string{
   146  		"/network[0]/virtualport[0]/parameters[0]",
   147  	},
   148  	"testdata/libvirt/tests/networkxml2xmlout/openvswitch-net.xml": []string{
   149  		"/network[0]/virtualport[0]/parameters[0]",
   150  	},
   151  	"testdata/libvirt/tests/networkxml2xmlupdateout/openvswitch-net-modified.xml": []string{
   152  		"/network[0]/virtualport[0]/parameters[0]",
   153  	},
   154  	"testdata/libvirt/tests/networkxml2xmlupdateout/openvswitch-net-more-portgroups.xml": []string{
   155  		"/network[0]/virtualport[0]/parameters[0]",
   156  	},
   157  	"testdata/libvirt/tests/networkxml2xmlupdateout/openvswitch-net-without-alice.xml": []string{
   158  		"/network[0]/virtualport[0]/parameters[0]",
   159  	},
   160  	"testdata/libvirt/tests/interfaceschemadata/bridge-vlan.xml": []string{
   161  		"/interface[0]/bridge[0]/interface[0]/vlan[0]/interface[0]/@type",
   162  	},
   163  	"testdata/libvirt/tests/interfaceschemadata/vlan.xml": []string{
   164  		"/interface[0]/vlan[0]/interface[0]/@type",
   165  	},
   166  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlin/disk_driver_name_null.xml": []string{
   167  		"/domainsnapshot[0]/disks[0]/disk[0]/@type",
   168  	},
   169  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlin/disk_snapshot.xml": []string{
   170  		"/domainsnapshot[0]/disks[0]/disk[0]/@type",
   171  		"/domainsnapshot[0]/disks[0]/disk[1]/@type",
   172  		"/domainsnapshot[0]/disks[0]/disk[2]/@type",
   173  		"/domainsnapshot[0]/disks[0]/disk[3]/@type",
   174  		"/domainsnapshot[0]/disks[0]/disk[4]/@type",
   175  	},
   176  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlout/disk_snapshot.xml": []string{
   177  		"/domainsnapshot[0]/disks[0]/disk[0]/@type",
   178  		"/domainsnapshot[0]/disks[0]/disk[1]/@type",
   179  		"/domainsnapshot[0]/disks[0]/disk[2]/@type",
   180  	},
   181  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlout/disk_snapshot_redefine.xml": []string{
   182  		"/domainsnapshot[0]/disks[0]/disk[0]/@type",
   183  		"/domainsnapshot[0]/disks[0]/disk[1]/@type",
   184  		"/domainsnapshot[0]/disks[0]/disk[2]/@type",
   185  	},
   186  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlout/external_vm_redefine.xml": []string{
   187  		"/domainsnapshot[0]/disks[0]/disk[0]/@type",
   188  	},
   189  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlin/qcow2-metadata-cache.xml": []string{
   190  		"/domainsnapshot[0]/disks[0]/disk[0]/@type",
   191  	},
   192  	"testdata/libvirt/tests/bhyvexml2argvdata/bhyvexml2argv-fs-9p.xml": []string{
   193  		"/domain[0]/devices[0]/filesystem[0]/@type",
   194  	},
   195  	"testdata/libvirt/tests/bhyvexml2argvdata/bhyvexml2argv-fs-9p-readonly.xml": []string{
   196  		"/domain[0]/devices[0]/filesystem[0]/@type",
   197  	},
   198  	"testdata/libvirt/tests/bhyvexml2argvdata/bhyvexml2argv-fs-9p-unsupported-accessmode.xml": []string{
   199  		"/domain[0]/devices[0]/filesystem[0]/@type",
   200  	},
   201  	"testdata/libvirt/tests/bhyvexml2argvdata/bhyvexml2argv-fs-9p-unsupported-driver.xml": []string{
   202  		"/domain[0]/devices[0]/filesystem[0]/@type",
   203  	},
   204  	"testdata/libvirt/tests/bhyvexml2argvdata/bhyvexml2argv-console-master-slave-not-specified.xml": []string{
   205  		"/domain[0]/devices[0]/console[0]/source[0]",
   206  	},
   207  }
   208  
   209  var extraExpectNodes = map[string][]string{
   210  	"testdata/libvirt/tests/qemuxml2argvdata/usb-redir-filter.xml": []string{
   211  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@vendor",
   212  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@product",
   213  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@class",
   214  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@version",
   215  	},
   216  	"testdata/libvirt/tests/domainschemadata/domain-parallels-ct-simple.xml": []string{
   217  		"/domain[0]/description[0]",
   218  	},
   219  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-encrypt1.xml":                  []string{volsrc},
   220  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-encrypt2.xml":                  []string{volsrc},
   221  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-backing.xml":              []string{volsrc},
   222  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-iso.xml":                  []string{volsrc},
   223  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-naming.xml":               []string{volsrc},
   224  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-qcow2.xml":                []string{volsrc},
   225  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file.xml":                      []string{volsrc},
   226  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-gluster-dir-neg-uid.xml":       []string{volsrc},
   227  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-gluster-dir.xml":               []string{volsrc},
   228  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-logical-backing.xml":           []string{volsrc},
   229  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-logical.xml":                   []string{volsrc},
   230  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-luks-cipher.xml":               []string{volsrc},
   231  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-luks-convert.xml":              []string{volsrc},
   232  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-luks.xml":                      []string{volsrc},
   233  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-partition.xml":                 []string{volsrc},
   234  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-0.10-lazy.xml":           []string{volsrc},
   235  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-1.1.xml":                 []string{volsrc},
   236  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-lazy.xml":                []string{volsrc},
   237  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-luks.xml":                []string{volsrc},
   238  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-luks-convert.xml":        []string{volsrc},
   239  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-encryption.xml":          []string{volsrc},
   240  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nobacking.xml":           []string{volsrc},
   241  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nocapacity-backing.xml":  []string{volsrc},
   242  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nocapacity.xml":          []string{volsrc},
   243  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nocow.xml":               []string{volsrc},
   244  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2.xml":                     []string{volsrc},
   245  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-sheepdog.xml":                  []string{volsrc},
   246  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file-backing.xml":             []string{volsrc},
   247  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file-iso.xml":                 []string{volsrc},
   248  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file-naming.xml":              []string{volsrc},
   249  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file.xml":                     []string{volsrc},
   250  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-gluster-dir-neg-uid.xml":      []string{volsrc},
   251  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-gluster-dir.xml":              []string{volsrc},
   252  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-logical-backing.xml":          []string{volsrc},
   253  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-logical.xml":                  []string{volsrc},
   254  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-luks-cipher.xml":              []string{volsrc},
   255  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-luks.xml":                     []string{volsrc},
   256  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-partition.xml":                []string{volsrc},
   257  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-0.10-lazy.xml":          []string{volsrc},
   258  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-1.1.xml":                []string{volsrc},
   259  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-encryption.xml":         []string{volsrc},
   260  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-lazy.xml":               []string{volsrc},
   261  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-luks.xml":               []string{volsrc},
   262  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nobacking.xml":          []string{volsrc},
   263  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nocapacity-backing.xml": []string{volsrc},
   264  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nocapacity.xml":         []string{volsrc},
   265  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nocow.xml":              []string{volsrc},
   266  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2.xml":                    []string{volsrc},
   267  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-sheepdog.xml":                 []string{volsrc},
   268  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlin/disk_snapshot.xml": []string{
   269  		"/domainsnapshot[0]/disks[0]/disk[3]/source[0]",
   270  	},
   271  }
   272  
   273  func trimXML(xml string) string {
   274  	xml = strings.TrimSpace(xml)
   275  	if strings.HasPrefix(xml, "<?xml") {
   276  		end := strings.Index(xml, "?>")
   277  		if end != -1 {
   278  			xml = xml[end+2:]
   279  			xml = strings.TrimSpace(xml)
   280  		}
   281  	}
   282  	if strings.HasPrefix(xml, "<!--") {
   283  		end := strings.Index(xml, "-->")
   284  		if end != -1 {
   285  			xml = xml[end+3:]
   286  			xml = strings.TrimSpace(xml)
   287  		}
   288  	}
   289  	return xml
   290  }
   291  
   292  func testRoundTrip(t *testing.T, xml string, filename string) {
   293  	if strings.HasSuffix(filename, "-invalid.xml") {
   294  		return
   295  	}
   296  
   297  	xml = trimXML(xml)
   298  
   299  	var doc Document
   300  	if strings.HasPrefix(xml, "<domain ") {
   301  		doc = &Domain{}
   302  	} else if strings.HasPrefix(xml, "<capabilities") {
   303  		doc = &Caps{}
   304  	} else if strings.HasPrefix(xml, "<networkport") {
   305  		doc = &NetworkPort{}
   306  	} else if strings.HasPrefix(xml, "<network") {
   307  		doc = &Network{}
   308  	} else if strings.HasPrefix(xml, "<secret") {
   309  		doc = &Secret{}
   310  	} else if strings.HasPrefix(xml, "<device") {
   311  		doc = &NodeDevice{}
   312  	} else if strings.HasPrefix(xml, "<volume") {
   313  		doc = &StorageVolume{}
   314  	} else if strings.HasPrefix(xml, "<pool") {
   315  		doc = &StoragePool{}
   316  	} else if strings.HasPrefix(xml, "<cpuTest") || strings.HasPrefix(xml, "<cpudata") {
   317  		// Not a public schema
   318  		return
   319  	} else if strings.HasPrefix(xml, "<cpu") {
   320  		if strings.Contains(xml, "mode=") || strings.Contains(xml, "match=") {
   321  			doc = &DomainCPU{}
   322  		} else {
   323  			doc = &CapsHostCPU{}
   324  		}
   325  	} else if strings.HasPrefix(xml, "<filterbinding") {
   326  		doc = &NWFilterBinding{}
   327  	} else if strings.HasPrefix(xml, "<filter") {
   328  		doc = &NWFilter{}
   329  	} else if strings.HasPrefix(xml, "<interface") {
   330  		if strings.Contains(filename, "networkxml") {
   331  			doc = &NetworkForwardInterface{}
   332  		} else if strings.Contains(filename, "qemuhotplug") {
   333  			doc = &DomainInterface{}
   334  		} else {
   335  			doc = &Interface{}
   336  		}
   337  	} else if strings.HasPrefix(xml, "<domainsnapshot") {
   338  		doc = &DomainSnapshot{}
   339  	} else if strings.HasPrefix(xml, "<domainCapabilities") {
   340  		doc = &DomainCaps{}
   341  	} else if strings.HasPrefix(xml, "<disk") {
   342  		doc = &DomainDisk{}
   343  	} else if strings.HasPrefix(xml, "<console") {
   344  		doc = &DomainConsole{}
   345  	} else if strings.HasPrefix(xml, "<channel") {
   346  		doc = &DomainChannel{}
   347  	} else if strings.HasPrefix(xml, "<watchdog") {
   348  		doc = &DomainWatchdog{}
   349  	} else if strings.HasPrefix(xml, "<shmem") {
   350  		doc = &DomainShmem{}
   351  	} else if strings.HasPrefix(xml, "<graphics") {
   352  		doc = &DomainGraphic{}
   353  	} else if strings.HasPrefix(xml, "<hostdev") {
   354  		doc = &DomainHostdev{}
   355  	} else if strings.HasPrefix(xml, "<host") {
   356  		if strings.Contains(xml, "mac=") {
   357  			doc = &NetworkDHCPHost{}
   358  		} else {
   359  			doc = &NetworkDNSHost{}
   360  		}
   361  	} else if strings.HasPrefix(xml, "<portgroup") {
   362  		doc = &NetworkPortGroup{}
   363  	} else if strings.HasPrefix(xml, "<txt") {
   364  		doc = &NetworkDNSTXT{}
   365  	} else if strings.HasPrefix(xml, "<srv") {
   366  		doc = &NetworkDNSSRV{}
   367  	} else if strings.HasPrefix(xml, "<range") {
   368  		doc = &NetworkDHCPRange{}
   369  	} else if strings.HasPrefix(xml, "<qemuCaps") ||
   370  		strings.HasPrefix(xml, "<sources") ||
   371  		strings.HasPrefix(xml, "<cpudata") ||
   372  		strings.HasPrefix(xml, "<cliOutput") {
   373  		// Private libvirt internal XML schemas we don't
   374  		// need public API coverage for
   375  		return
   376  	} else {
   377  		t.Fatal(fmt.Errorf("Unexpected XML document schema in %s\n", filename))
   378  	}
   379  	err := doc.Unmarshal(xml)
   380  	if err != nil {
   381  		t.Fatal(fmt.Errorf("Cannot parse file %s: %s\n", filename, err))
   382  	}
   383  
   384  	newxml, err := doc.Marshal()
   385  	if err != nil {
   386  		t.Fatal(err)
   387  	}
   388  
   389  	extraExpectNodes, _ := extraExpectNodes[filename]
   390  	extraActualNodes, _ := extraActualNodes[filename]
   391  	err = testCompareXML(filename, xml, newxml, extraExpectNodes, extraActualNodes)
   392  	if err != nil {
   393  		if os.Getenv("LIBVIRT_DEBUG") == "1" {
   394  			fmt.Printf("Expected %s\n", xml)
   395  			fmt.Printf("Actual %s\n", newxml)
   396  		}
   397  		t.Fatal(err)
   398  	}
   399  }
   400  
   401  func syncGit(t *testing.T) {
   402  	_, err := os.Stat("testdata/libvirt/tests")
   403  	if err != nil {
   404  		if os.IsNotExist(err) {
   405  			msg, err := exec.Command("git", "clone", "--depth", "1", "https://gitlab.com/libvirt/libvirt", "testdata/libvirt").CombinedOutput()
   406  			if err != nil {
   407  				t.Fatal(fmt.Errorf("Unable to clone libvirt.git: %s: %s", err, msg))
   408  			}
   409  		} else {
   410  			t.Fatal(err)
   411  		}
   412  	} else {
   413  		here, err := os.Getwd()
   414  		if err != nil {
   415  			t.Fatal(err)
   416  		}
   417  		err = os.Chdir("testdata/libvirt")
   418  		if err != nil {
   419  			t.Fatal(err)
   420  		}
   421  		defer func() {
   422  			os.Chdir(here)
   423  		}()
   424  		msg, err := exec.Command("git", "pull").CombinedOutput()
   425  		if err != nil {
   426  			t.Fatal(fmt.Errorf("Unable to update libvirt.git: %s: %s", err, msg))
   427  		}
   428  
   429  		ref := os.Getenv("LIBVIRT_REF")
   430  		if ref == "" {
   431  			ref = "master"
   432  		}
   433  		msg, err = exec.Command("git", "checkout", "--force", ref).CombinedOutput()
   434  		if err != nil {
   435  			t.Fatal(fmt.Errorf("Unable to checkout %s: %s: %s", ref, err, msg))
   436  		}
   437  	}
   438  }
   439  
   440  func TestRoundTrip(t *testing.T) {
   441  	syncGit(t)
   442  	singlefile := os.Getenv("LIBVIRT_XML_TESTFILE")
   443  	for _, xmldir := range xmldirs {
   444  		xmlfiles, err := ioutil.ReadDir(xmldir)
   445  		if err != nil {
   446  			t.Fatal(err)
   447  		}
   448  
   449  		for _, xmlfile := range xmlfiles {
   450  			if !xmlfile.IsDir() && strings.HasSuffix(xmlfile.Name(), ".xml") {
   451  				fname := xmldir + "/" + xmlfile.Name()
   452  				_, ok := blacklist[fname]
   453  				if ok {
   454  					continue
   455  				}
   456  				if singlefile != "" && fname != singlefile {
   457  					continue
   458  				}
   459  				xml, err := ioutil.ReadFile(fname)
   460  				if err != nil {
   461  					t.Fatal(err)
   462  				}
   463  				testRoundTrip(t, string(xml), fname)
   464  			}
   465  		}
   466  	}
   467  }