github.com/vmware/govmomi@v0.37.2/vim25/xml/extras_test.go (about)

     1  /*
     2  Copyright (c) 2014 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package xml
    18  
    19  import (
    20  	"bytes"
    21  	"reflect"
    22  	"testing"
    23  	"time"
    24  )
    25  
    26  type MyType struct {
    27  	Value string
    28  }
    29  
    30  var myTypes = map[string]reflect.Type{
    31  	"MyType":      reflect.TypeOf(MyType{}),
    32  	"ValueType":   reflect.TypeOf(ValueType{}),
    33  	"PointerType": reflect.TypeOf(PointerType{}),
    34  }
    35  
    36  func MyTypes(name string) (reflect.Type, bool) {
    37  	t, ok := myTypes[name]
    38  	return t, ok
    39  }
    40  
    41  func TestMarshalWithEmptyInterface(t *testing.T) {
    42  	var r1, r2 struct {
    43  		XMLName Name          `xml:"root"`
    44  		Values  []interface{} `xml:"value,typeattr"`
    45  	}
    46  
    47  	var tests = []struct {
    48  		Value interface{}
    49  	}{
    50  		{Value: bool(true)},
    51  		{Value: int8(-8)},
    52  		{Value: int16(-16)},
    53  		{Value: int32(-32)},
    54  		{Value: int64(-64)},
    55  		{Value: uint8(8)},
    56  		{Value: uint16(16)},
    57  		{Value: uint32(32)},
    58  		{Value: uint64(64)},
    59  		{Value: float32(32.0)},
    60  		{Value: float64(64.0)},
    61  		{Value: string("string")},
    62  		{Value: time.Now()},
    63  		{Value: ParseTime("2009-10-04T01:35:58+00:00")},
    64  		{Value: []byte("bytes")},
    65  		{Value: MyType{Value: "v"}},
    66  	}
    67  
    68  	for _, test := range tests {
    69  		r1.XMLName.Local = "root"
    70  		r1.Values = []interface{}{test.Value}
    71  		r2.XMLName = Name{}
    72  		r2.Values = nil
    73  
    74  		b, err := Marshal(r1)
    75  		if err != nil {
    76  			t.Fatalf("Marshal: %s", err)
    77  		}
    78  
    79  		dec := NewDecoder(bytes.NewReader(b))
    80  		dec.TypeFunc = MyTypes
    81  		err = dec.Decode(&r2)
    82  		if err != nil {
    83  			t.Fatalf("Unmarshal: %s", err)
    84  		}
    85  
    86  		switch r1.Values[0].(type) {
    87  		case time.Time:
    88  			if !r1.Values[0].(time.Time).Equal(r2.Values[0].(time.Time)) {
    89  				t.Errorf("Expected: %#v, actual: %#v", r1, r2)
    90  			}
    91  		default:
    92  			if !reflect.DeepEqual(r1, r2) {
    93  				t.Errorf("Expected: %#v, actual: %#v", r1, r2)
    94  			}
    95  		}
    96  	}
    97  }
    98  
    99  type VIntf interface {
   100  	V() string
   101  }
   102  
   103  type ValueType struct {
   104  	Value string `xml:",chardata"`
   105  }
   106  
   107  type PointerType struct {
   108  	Value string `xml:",chardata"`
   109  }
   110  
   111  func (t ValueType) V() string {
   112  	return t.Value
   113  }
   114  
   115  func (t *PointerType) V() string {
   116  	return t.Value
   117  }
   118  
   119  func TestMarshalWithInterface(t *testing.T) {
   120  	var r1, r2 struct {
   121  		XMLName Name    `xml:"root"`
   122  		Values  []VIntf `xml:"value,typeattr"`
   123  	}
   124  
   125  	r1.XMLName.Local = "root"
   126  	r1.Values = []VIntf{
   127  		ValueType{"v1"},
   128  		&PointerType{"v2"},
   129  	}
   130  
   131  	b, err := Marshal(r1)
   132  	if err != nil {
   133  		t.Fatalf("Marshal: %s", err)
   134  	}
   135  
   136  	dec := NewDecoder(bytes.NewReader(b))
   137  	dec.TypeFunc = MyTypes
   138  	err = dec.Decode(&r2)
   139  	if err != nil {
   140  		t.Fatalf("Unmarshal: %s", err)
   141  	}
   142  
   143  	if !reflect.DeepEqual(r1, r2) {
   144  		t.Errorf("expected: %#v, actual: %#v", r1, r2)
   145  	}
   146  }
   147  
   148  type test3iface interface {
   149  	Value() string
   150  }
   151  
   152  type test3a struct {
   153  	V string `xml:",chardata"`
   154  }
   155  
   156  func (t test3a) Value() string { return t.V }
   157  
   158  type test3b struct {
   159  	V string `xml:",chardata"`
   160  }
   161  
   162  func (t test3b) Value() string { return t.V }
   163  
   164  func TestUnmarshalInterfaceWithoutTypeAttr(t *testing.T) {
   165  	var r struct {
   166  		XMLName Name         `xml:"root"`
   167  		Values  []test3iface `xml:"value,typeattr"`
   168  	}
   169  
   170  	b := `
   171  	<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   172  	<value xsi:type="test3a">A</value>
   173  	<value>B</value>
   174  	</root>
   175  	`
   176  
   177  	fn := func(name string) (reflect.Type, bool) {
   178  		switch name {
   179  		case "test3a":
   180  			return reflect.TypeOf(test3a{}), true
   181  		case "test3iface":
   182  			return reflect.TypeOf(test3b{}), true
   183  		default:
   184  			return nil, false
   185  		}
   186  	}
   187  
   188  	dec := NewDecoder(bytes.NewReader([]byte(b)))
   189  	dec.TypeFunc = fn
   190  	err := dec.Decode(&r)
   191  	if err != nil {
   192  		t.Fatalf("Unmarshal: %s", err)
   193  	}
   194  
   195  	if len(r.Values) != 2 {
   196  		t.Errorf("Expected 2 values")
   197  	}
   198  
   199  	exps := []struct {
   200  		Typ reflect.Type
   201  		Val string
   202  	}{
   203  		{
   204  			Typ: reflect.TypeOf(test3a{}),
   205  			Val: "A",
   206  		},
   207  		{
   208  			Typ: reflect.TypeOf(test3b{}),
   209  			Val: "B",
   210  		},
   211  	}
   212  
   213  	for i, e := range exps {
   214  		if val := r.Values[i].Value(); val != e.Val {
   215  			t.Errorf("Expected: %s, got: %s", e.Val, val)
   216  		}
   217  
   218  		if typ := reflect.TypeOf(r.Values[i]); typ.Name() != e.Typ.Name() {
   219  			t.Errorf("Expected: %s, got: %s", e.Typ.Name(), typ.Name())
   220  		}
   221  	}
   222  }