package kvm import ( "encoding/xml" "strings" "testing" "time" ) func TestInstanceMetadata_roundTrip(t *testing.T) { t.Parallel() created := time.Date(2026, 9, 4, 12, 30, 0, 0, time.FixedZone("CEST", 2*3600)) raw, err := xml.Marshal(newInstanceMetadata("uid-1", created)) if err != nil { t.Fatalf("Marshal() error = %v", err) } if !strings.Contains(string(raw), `xmlns="`+metadataURI+`"`) { t.Errorf("marshalled metadata lacks the namespace declaration: %s", raw) } m, err := parseInstanceMetadata(string(raw)) if err != nil { t.Fatalf("parseInstanceMetadata() error = %v", err) } if !m.managed() || m.UID != "uid-1" { t.Errorf("parsed = %+v, want managed with uid-1", m) } if got := m.createdAt(); !got.Equal(created) || got.Location() != time.UTC { t.Errorf("createdAt() = %v, want %v in UTC", got, created) } } func TestParseInstanceMetadata(t *testing.T) { t.Parallel() tests := []struct { name string in string wantErr bool wantManaged bool wantUID string wantCreated time.Time }{ { // libvirt re-serialises the stored element with whatever prefix it // chooses; only the namespace URI is contractual. name: "libvirt prefixed form", in: `` + `trueuid-2` + `2026-09-04T10:00:00Z`, wantManaged: true, wantUID: "uid-2", wantCreated: time.Date(2026, 9, 4, 10, 0, 0, 0, time.UTC), }, { // What libvirt 11.6 actually returns from DomainGetMetadata: the // element selected by our URI, serialised without any namespace // declaration. name: "libvirt bare form", in: `trueuid-3` + `2026-09-10T07:30:00Z`, wantManaged: true, wantUID: "uid-3", wantCreated: time.Date(2026, 9, 10, 7, 30, 0, 0, time.UTC), }, {name: "managed false", in: `falseu`, wantUID: "u"}, {name: "foreign element", in: `true`, wantErr: true}, {name: "garbage", in: `not xml`, wantErr: true}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { t.Parallel() m, err := parseInstanceMetadata(tc.in) if (err != nil) != tc.wantErr { t.Fatalf("error = %v, wantErr %v", err, tc.wantErr) } if m.managed() != tc.wantManaged || m.UID != tc.wantUID || !m.createdAt().Equal(tc.wantCreated) { t.Errorf("parsed = %+v, want managed=%v uid=%q createdAt=%v", m, tc.wantManaged, tc.wantUID, tc.wantCreated) } }) } } func TestInstanceMetadata_createdAtMalformedIsZero(t *testing.T) { t.Parallel() m := instanceMetadata{CreatedAt: "yesterday"} if !m.createdAt().IsZero() { t.Errorf("createdAt() = %v, want zero time", m.createdAt()) } }