github.com/zhaoxuat/libvirt-go-xml@v6.3.1-0.20200612053919-a025f1d30c41+incompatible/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  }
   190  
   191  var extraExpectNodes = map[string][]string{
   192  	"testdata/libvirt/tests/qemuxml2argvdata/usb-redir-filter.xml": []string{
   193  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@vendor",
   194  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@product",
   195  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@class",
   196  		"/domain[0]/devices[0]/redirfilter[0]/usbdev[1]/@version",
   197  	},
   198  	"testdata/libvirt/tests/domainschemadata/domain-parallels-ct-simple.xml": []string{
   199  		"/domain[0]/description[0]",
   200  	},
   201  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-encrypt1.xml":                  []string{volsrc},
   202  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-encrypt2.xml":                  []string{volsrc},
   203  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-backing.xml":              []string{volsrc},
   204  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-iso.xml":                  []string{volsrc},
   205  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-naming.xml":               []string{volsrc},
   206  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file-qcow2.xml":                []string{volsrc},
   207  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-file.xml":                      []string{volsrc},
   208  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-gluster-dir-neg-uid.xml":       []string{volsrc},
   209  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-gluster-dir.xml":               []string{volsrc},
   210  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-logical-backing.xml":           []string{volsrc},
   211  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-logical.xml":                   []string{volsrc},
   212  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-luks-cipher.xml":               []string{volsrc},
   213  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-luks-convert.xml":              []string{volsrc},
   214  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-luks.xml":                      []string{volsrc},
   215  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-partition.xml":                 []string{volsrc},
   216  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-0.10-lazy.xml":           []string{volsrc},
   217  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-1.1.xml":                 []string{volsrc},
   218  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-lazy.xml":                []string{volsrc},
   219  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-encryption.xml":          []string{volsrc},
   220  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nobacking.xml":           []string{volsrc},
   221  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nocapacity-backing.xml":  []string{volsrc},
   222  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nocapacity.xml":          []string{volsrc},
   223  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2-nocow.xml":               []string{volsrc},
   224  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-qcow2.xml":                     []string{volsrc},
   225  	"testdata/libvirt/tests/storagevolxml2xmlin/vol-sheepdog.xml":                  []string{volsrc},
   226  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file-backing.xml":             []string{volsrc},
   227  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file-iso.xml":                 []string{volsrc},
   228  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file-naming.xml":              []string{volsrc},
   229  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-file.xml":                     []string{volsrc},
   230  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-gluster-dir-neg-uid.xml":      []string{volsrc},
   231  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-gluster-dir.xml":              []string{volsrc},
   232  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-logical-backing.xml":          []string{volsrc},
   233  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-logical.xml":                  []string{volsrc},
   234  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-luks-cipher.xml":              []string{volsrc},
   235  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-luks.xml":                     []string{volsrc},
   236  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-partition.xml":                []string{volsrc},
   237  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-0.10-lazy.xml":          []string{volsrc},
   238  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-1.1.xml":                []string{volsrc},
   239  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-encryption.xml":         []string{volsrc},
   240  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-lazy.xml":               []string{volsrc},
   241  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nobacking.xml":          []string{volsrc},
   242  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nocapacity-backing.xml": []string{volsrc},
   243  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nocapacity.xml":         []string{volsrc},
   244  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2-nocow.xml":              []string{volsrc},
   245  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-qcow2.xml":                    []string{volsrc},
   246  	"testdata/libvirt/tests/storagevolxml2xmlout/vol-sheepdog.xml":                 []string{volsrc},
   247  	"testdata/libvirt/tests/qemudomainsnapshotxml2xmlin/disk_snapshot.xml": []string{
   248  		"/domainsnapshot[0]/disks[0]/disk[3]/source[0]",
   249  	},
   250  }
   251  
   252  func trimXML(xml string) string {
   253  	xml = strings.TrimSpace(xml)
   254  	if strings.HasPrefix(xml, "<?xml") {
   255  		end := strings.Index(xml, "?>")
   256  		if end != -1 {
   257  			xml = xml[end+2:]
   258  			xml = strings.TrimSpace(xml)
   259  		}
   260  	}
   261  	if strings.HasPrefix(xml, "<!--") {
   262  		end := strings.Index(xml, "-->")
   263  		if end != -1 {
   264  			xml = xml[end+3:]
   265  			xml = strings.TrimSpace(xml)
   266  		}
   267  	}
   268  	return xml
   269  }
   270  
   271  func testRoundTrip(t *testing.T, xml string, filename string) {
   272  	if strings.HasSuffix(filename, "-invalid.xml") {
   273  		return
   274  	}
   275  
   276  	xml = trimXML(xml)
   277  
   278  	var doc Document
   279  	if strings.HasPrefix(xml, "<domain ") {
   280  		doc = &Domain{}
   281  	} else if strings.HasPrefix(xml, "<capabilities") {
   282  		doc = &Caps{}
   283  	} else if strings.HasPrefix(xml, "<networkport") {
   284  		doc = &NetworkPort{}
   285  	} else if strings.HasPrefix(xml, "<network") {
   286  		doc = &Network{}
   287  	} else if strings.HasPrefix(xml, "<secret") {
   288  		doc = &Secret{}
   289  	} else if strings.HasPrefix(xml, "<device") {
   290  		doc = &NodeDevice{}
   291  	} else if strings.HasPrefix(xml, "<volume") {
   292  		doc = &StorageVolume{}
   293  	} else if strings.HasPrefix(xml, "<pool") {
   294  		doc = &StoragePool{}
   295  	} else if strings.HasPrefix(xml, "<cpuTest") || strings.HasPrefix(xml, "<cpudata") {
   296  		// Not a public schema
   297  		return
   298  	} else if strings.HasPrefix(xml, "<cpu") {
   299  		if strings.Contains(xml, "mode=") || strings.Contains(xml, "match=") {
   300  			doc = &DomainCPU{}
   301  		} else {
   302  			doc = &CapsHostCPU{}
   303  		}
   304  	} else if strings.HasPrefix(xml, "<filterbinding") {
   305  		doc = &NWFilterBinding{}
   306  	} else if strings.HasPrefix(xml, "<filter") {
   307  		doc = &NWFilter{}
   308  	} else if strings.HasPrefix(xml, "<interface") {
   309  		if strings.Contains(filename, "networkxml") {
   310  			doc = &NetworkForwardInterface{}
   311  		} else {
   312  			doc = &Interface{}
   313  		}
   314  	} else if strings.HasPrefix(xml, "<domainsnapshot") {
   315  		doc = &DomainSnapshot{}
   316  	} else if strings.HasPrefix(xml, "<domainCapabilities") {
   317  		doc = &DomainCaps{}
   318  	} else if strings.HasPrefix(xml, "<disk") {
   319  		doc = &DomainDisk{}
   320  	} else if strings.HasPrefix(xml, "<console") {
   321  		doc = &DomainConsole{}
   322  	} else if strings.HasPrefix(xml, "<channel") {
   323  		doc = &DomainChannel{}
   324  	} else if strings.HasPrefix(xml, "<watchdog") {
   325  		doc = &DomainWatchdog{}
   326  	} else if strings.HasPrefix(xml, "<shmem") {
   327  		doc = &DomainShmem{}
   328  	} else if strings.HasPrefix(xml, "<graphics") {
   329  		doc = &DomainGraphic{}
   330  	} else if strings.HasPrefix(xml, "<hostdev") {
   331  		doc = &DomainHostdev{}
   332  	} else if strings.HasPrefix(xml, "<host") {
   333  		if strings.Contains(xml, "mac=") {
   334  			doc = &NetworkDHCPHost{}
   335  		} else {
   336  			doc = &NetworkDNSHost{}
   337  		}
   338  	} else if strings.HasPrefix(xml, "<portgroup") {
   339  		doc = &NetworkPortGroup{}
   340  	} else if strings.HasPrefix(xml, "<txt") {
   341  		doc = &NetworkDNSTXT{}
   342  	} else if strings.HasPrefix(xml, "<srv") {
   343  		doc = &NetworkDNSSRV{}
   344  	} else if strings.HasPrefix(xml, "<range") {
   345  		doc = &NetworkDHCPRange{}
   346  	} else if strings.HasPrefix(xml, "<qemuCaps") ||
   347  		strings.HasPrefix(xml, "<sources") ||
   348  		strings.HasPrefix(xml, "<cpudata") ||
   349  		strings.HasPrefix(xml, "<cliOutput") {
   350  		// Private libvirt internal XML schemas we don't
   351  		// need public API coverage for
   352  		return
   353  	} else {
   354  		t.Fatal(fmt.Errorf("Unexpected XML document schema in %s\n", filename))
   355  	}
   356  	err := doc.Unmarshal(xml)
   357  	if err != nil {
   358  		t.Fatal(fmt.Errorf("Cannot parse file %s: %s\n", filename, err))
   359  	}
   360  
   361  	newxml, err := doc.Marshal()
   362  	if err != nil {
   363  		t.Fatal(err)
   364  	}
   365  
   366  	extraExpectNodes, _ := extraExpectNodes[filename]
   367  	extraActualNodes, _ := extraActualNodes[filename]
   368  	err = testCompareXML(filename, xml, newxml, extraExpectNodes, extraActualNodes)
   369  	if err != nil {
   370  		if os.Getenv("LIBVIRT_DEBUG") == "1" {
   371  			fmt.Printf("Expected %s\n", xml)
   372  			fmt.Printf("Actual %s\n", newxml)
   373  		}
   374  		t.Fatal(err)
   375  	}
   376  }
   377  
   378  func syncGit(t *testing.T) {
   379  	_, err := os.Stat("testdata/libvirt/tests")
   380  	if err != nil {
   381  		if os.IsNotExist(err) {
   382  			msg, err := exec.Command("git", "clone", "--depth", "1", "https://libvirt.org/git/libvirt.git", "testdata/libvirt").CombinedOutput()
   383  			if err != nil {
   384  				t.Fatal(fmt.Errorf("Unable to clone libvirt.git: %s: %s", err, msg))
   385  			}
   386  		} else {
   387  			t.Fatal(err)
   388  		}
   389  	} else {
   390  		here, err := os.Getwd()
   391  		if err != nil {
   392  			t.Fatal(err)
   393  		}
   394  		err = os.Chdir("testdata/libvirt")
   395  		if err != nil {
   396  			t.Fatal(err)
   397  		}
   398  		defer func() {
   399  			os.Chdir(here)
   400  		}()
   401  		msg, err := exec.Command("git", "pull").CombinedOutput()
   402  		if err != nil {
   403  			t.Fatal(fmt.Errorf("Unable to update libvirt.git: %s: %s", err, msg))
   404  		}
   405  
   406  		ref := os.Getenv("LIBVIRT_REF")
   407  		if ref == "" {
   408  			ref = "master"
   409  		}
   410  		msg, err = exec.Command("git", "checkout", "--force", ref).CombinedOutput()
   411  		if err != nil {
   412  			t.Fatal(fmt.Errorf("Unable to checkout %s: %s: %s", ref, err, msg))
   413  		}
   414  	}
   415  }
   416  
   417  func TestRoundTrip(t *testing.T) {
   418  	syncGit(t)
   419  	singlefile := os.Getenv("LIBVIRT_XML_TESTFILE")
   420  	for _, xmldir := range xmldirs {
   421  		xmlfiles, err := ioutil.ReadDir(xmldir)
   422  		if err != nil {
   423  			t.Fatal(err)
   424  		}
   425  
   426  		for _, xmlfile := range xmlfiles {
   427  			if !xmlfile.IsDir() && strings.HasSuffix(xmlfile.Name(), ".xml") {
   428  				fname := xmldir + "/" + xmlfile.Name()
   429  				_, ok := blacklist[fname]
   430  				if ok {
   431  					continue
   432  				}
   433  				if singlefile != "" && fname != singlefile {
   434  					continue
   435  				}
   436  				xml, err := ioutil.ReadFile(fname)
   437  				if err != nil {
   438  					t.Fatal(err)
   439  				}
   440  				testRoundTrip(t, string(xml), fname)
   441  			}
   442  		}
   443  	}
   444  }