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  }