github.com/vmware/govmomi@v0.51.0/vim25/xml/extras_test.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package xml 6 7 import ( 8 "bytes" 9 "reflect" 10 "testing" 11 "time" 12 ) 13 14 type MyType struct { 15 Value string 16 } 17 18 var myTypes = map[string]reflect.Type{ 19 "MyType": reflect.TypeOf(MyType{}), 20 "ValueType": reflect.TypeOf(ValueType{}), 21 "PointerType": reflect.TypeOf(PointerType{}), 22 } 23 24 func MyTypes(name string) (reflect.Type, bool) { 25 t, ok := myTypes[name] 26 return t, ok 27 } 28 29 func TestMarshalWithEmptyInterface(t *testing.T) { 30 var r1, r2 struct { 31 XMLName Name `xml:"root"` 32 Values []interface{} `xml:"value,typeattr"` 33 } 34 35 var tests = []struct { 36 Value interface{} 37 }{ 38 {Value: bool(true)}, 39 {Value: int8(-8)}, 40 {Value: int16(-16)}, 41 {Value: int32(-32)}, 42 {Value: int64(-64)}, 43 {Value: uint8(8)}, 44 {Value: uint16(16)}, 45 {Value: uint32(32)}, 46 {Value: uint64(64)}, 47 {Value: float32(32.0)}, 48 {Value: float64(64.0)}, 49 {Value: string("string")}, 50 {Value: time.Now()}, 51 {Value: ParseTime("2009-10-04T01:35:58+00:00")}, 52 {Value: []byte("bytes")}, 53 {Value: MyType{Value: "v"}}, 54 } 55 56 for _, test := range tests { 57 r1.XMLName.Local = "root" 58 r1.Values = []interface{}{test.Value} 59 r2.XMLName = Name{} 60 r2.Values = nil 61 62 b, err := Marshal(r1) 63 if err != nil { 64 t.Fatalf("Marshal: %s", err) 65 } 66 67 dec := NewDecoder(bytes.NewReader(b)) 68 dec.TypeFunc = MyTypes 69 err = dec.Decode(&r2) 70 if err != nil { 71 t.Fatalf("Unmarshal: %s", err) 72 } 73 74 switch r1.Values[0].(type) { 75 case time.Time: 76 if !r1.Values[0].(time.Time).Equal(r2.Values[0].(time.Time)) { 77 t.Errorf("Expected: %#v, actual: %#v", r1, r2) 78 } 79 default: 80 if !reflect.DeepEqual(r1, r2) { 81 t.Errorf("Expected: %#v, actual: %#v", r1, r2) 82 } 83 } 84 } 85 } 86 87 type VIntf interface { 88 V() string 89 } 90 91 type ValueType struct { 92 Value string `xml:",chardata"` 93 } 94 95 type PointerType struct { 96 Value string `xml:",chardata"` 97 } 98 99 func (t ValueType) V() string { 100 return t.Value 101 } 102 103 func (t *PointerType) V() string { 104 return t.Value 105 } 106 107 func TestMarshalWithInterface(t *testing.T) { 108 var r1, r2 struct { 109 XMLName Name `xml:"root"` 110 Values []VIntf `xml:"value,typeattr"` 111 } 112 113 r1.XMLName.Local = "root" 114 r1.Values = []VIntf{ 115 ValueType{"v1"}, 116 &PointerType{"v2"}, 117 } 118 119 b, err := Marshal(r1) 120 if err != nil { 121 t.Fatalf("Marshal: %s", err) 122 } 123 124 dec := NewDecoder(bytes.NewReader(b)) 125 dec.TypeFunc = MyTypes 126 err = dec.Decode(&r2) 127 if err != nil { 128 t.Fatalf("Unmarshal: %s", err) 129 } 130 131 if !reflect.DeepEqual(r1, r2) { 132 t.Errorf("expected: %#v, actual: %#v", r1, r2) 133 } 134 } 135 136 type test3iface interface { 137 Value() string 138 } 139 140 type test3a struct { 141 V string `xml:",chardata"` 142 } 143 144 func (t test3a) Value() string { return t.V } 145 146 type test3b struct { 147 V string `xml:",chardata"` 148 } 149 150 func (t test3b) Value() string { return t.V } 151 152 func TestUnmarshalInterfaceWithoutTypeAttr(t *testing.T) { 153 var r struct { 154 XMLName Name `xml:"root"` 155 Values []test3iface `xml:"value,typeattr"` 156 } 157 158 b := ` 159 <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 160 <value xsi:type="test3a">A</value> 161 <value>B</value> 162 </root> 163 ` 164 165 fn := func(name string) (reflect.Type, bool) { 166 switch name { 167 case "test3a": 168 return reflect.TypeOf(test3a{}), true 169 case "test3iface": 170 return reflect.TypeOf(test3b{}), true 171 default: 172 return nil, false 173 } 174 } 175 176 dec := NewDecoder(bytes.NewReader([]byte(b))) 177 dec.TypeFunc = fn 178 err := dec.Decode(&r) 179 if err != nil { 180 t.Fatalf("Unmarshal: %s", err) 181 } 182 183 if len(r.Values) != 2 { 184 t.Errorf("Expected 2 values") 185 } 186 187 exps := []struct { 188 Typ reflect.Type 189 Val string 190 }{ 191 { 192 Typ: reflect.TypeOf(test3a{}), 193 Val: "A", 194 }, 195 { 196 Typ: reflect.TypeOf(test3b{}), 197 Val: "B", 198 }, 199 } 200 201 for i, e := range exps { 202 if val := r.Values[i].Value(); val != e.Val { 203 t.Errorf("Expected: %s, got: %s", e.Val, val) 204 } 205 206 if typ := reflect.TypeOf(r.Values[i]); typ.Name() != e.Typ.Name() { 207 t.Errorf("Expected: %s, got: %s", e.Typ.Name(), typ.Name()) 208 } 209 } 210 } 211 212 // https://github.com/vmware/govmomi/issues/246 213 func TestNegativeValuesUnsignedFields(t *testing.T) { 214 type T struct { 215 I string 216 O any 217 U8 uint8 `xml:"u8"` 218 U16 uint16 `xml:"u16"` 219 U32 uint32 `xml:"u32"` 220 U64 uint64 `xml:"u64"` 221 } 222 223 var tests = []T{ 224 {I: "<T><u8>-128</u8></T>", O: uint8(0x80)}, 225 {I: "<T><u8>-1</u8></T>", O: uint8(0xff)}, 226 {I: "<T><u16>-32768</u16></T>", O: uint16(0x8000)}, 227 {I: "<T><u16>-1</u16></T>", O: uint16(0xffff)}, 228 {I: "<T><u32>-2147483648</u32></T>", O: uint32(0x80000000)}, 229 {I: "<T><u32>-1</u32></T>", O: uint32(0xffffffff)}, 230 {I: "<T><u64>-9223372036854775808</u64></T>", O: uint64(0x8000000000000000)}, 231 {I: "<T><u64>-1</u64></T>", O: uint64(0xffffffffffffffff)}, 232 } 233 234 for _, test := range tests { 235 err := Unmarshal([]byte(test.I), &test) 236 if err != nil { 237 t.Errorf("Unmarshal error: %v", err) 238 continue 239 } 240 241 var expected = test.O 242 var actual any 243 switch reflect.ValueOf(test.O).Type().Kind() { 244 case reflect.Uint8: 245 actual = test.U8 246 case reflect.Uint16: 247 actual = test.U16 248 case reflect.Uint32: 249 actual = test.U32 250 case reflect.Uint64: 251 actual = test.U64 252 } 253 254 if !reflect.DeepEqual(actual, expected) { 255 t.Errorf("Actual: %v, expected: %v", actual, expected) 256 } 257 } 258 }