github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/xdr3/decode_test.go (about)

     1  /*
     2   * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
     3   *
     4   * Permission to use, copy, modify, and distribute this software for any
     5   * purpose with or without fee is hereby granted, provided that the above
     6   * copyright notice and this permission notice appear in all copies.
     7   *
     8   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     9   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    10   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    11   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    13   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    14   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    15   */
    16  
    17  package xdr_test
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/base64"
    22  	"fmt"
    23  	"math"
    24  	"reflect"
    25  	"testing"
    26  	"time"
    27  
    28  	. "github.com/stellar/go-xdr/xdr3"
    29  )
    30  
    31  // subTest is used to allow testing of the Unmarshal function into struct fields
    32  // which are structs themselves.
    33  type subTest struct {
    34  	A string
    35  	B uint8
    36  }
    37  
    38  // allTypesTest is used to allow testing of the Unmarshal function into struct
    39  // fields of all supported types.
    40  type allTypesTest struct {
    41  	A int8
    42  	B uint8
    43  	C int16
    44  	D uint16
    45  	E int32
    46  	F uint32
    47  	G int64
    48  	H uint64
    49  	I bool
    50  	J float32
    51  	K float64
    52  	L string
    53  	M []byte
    54  	N [3]byte
    55  	O []int16
    56  	P [2]subTest
    57  	Q subTest
    58  	R map[string]uint32
    59  	S time.Time
    60  }
    61  
    62  // opaqueStruct is used to test handling of uint8 slices and arrays.
    63  type opaqueStruct struct {
    64  	Slice []uint8  `xdropaque:"false"`
    65  	Array [1]uint8 `xdropaque:"false"`
    66  }
    67  
    68  type AnEnum int32
    69  
    70  func (e AnEnum) ValidEnum(v int32) bool {
    71  	return v < 3
    72  }
    73  
    74  type aUnion struct {
    75  	Type AnEnum
    76  	Data *int32
    77  	Text *string `xdrmaxsize:"28"`
    78  }
    79  
    80  func (u aUnion) SwitchFieldName() string {
    81  	return "Type"
    82  }
    83  
    84  func (u aUnion) ArmForSwitch(sw int32) (string, bool) {
    85  	switch sw {
    86  	case 0:
    87  		return "Data", true
    88  	case 1:
    89  		return "Text", true
    90  	case 2: // void
    91  		return "", true
    92  	}
    93  
    94  	return "-", false
    95  }
    96  
    97  type structWithPointer struct {
    98  	Data *string
    99  }
   100  
   101  // testExpectedURet is a convenience method to test an expected number of bytes
   102  // read and error for an unmarshal.
   103  func testExpectedURet(t *testing.T, name string, n, wantN int, err, wantErr error) bool {
   104  	// First ensure the number of bytes read is the expected value.  The
   105  	// byes read should be accurate even when an error occurs.
   106  	if n != wantN {
   107  		t.Errorf("%s: unexpected num bytes read - got: %v want: %v\n",
   108  			name, n, wantN)
   109  		return false
   110  	}
   111  
   112  	// Next check for the expected error.
   113  	return assertError(t, name, err, wantErr)
   114  }
   115  
   116  func assertError(t *testing.T, name string, err, wantErr error) bool {
   117  	if reflect.TypeOf(err) != reflect.TypeOf(wantErr) {
   118  		t.Errorf("%s: failed to detect error - got: %v <%[2]T> want: %T",
   119  			name, err, wantErr)
   120  		return false
   121  	}
   122  
   123  	if rerr, ok := err.(*UnmarshalError); ok {
   124  		if werr, ok := wantErr.(*UnmarshalError); ok {
   125  			if rerr.ErrorCode != werr.ErrorCode {
   126  				t.Errorf("%s: failed to detect error code - "+
   127  					"got: %v want: %v", name,
   128  					rerr.ErrorCode, werr.ErrorCode)
   129  				return false
   130  			}
   131  		}
   132  	}
   133  
   134  	return true
   135  }
   136  
   137  // TestUnmarshal ensures the Unmarshal function works properly with all types.
   138  func TestUnmarshal(t *testing.T) {
   139  	// Variables for various unsupported Unmarshal types.
   140  	var nilInterface interface{}
   141  	var testChan chan int
   142  	var testFunc func()
   143  	var testComplex64 complex64
   144  	var testComplex128 complex128
   145  
   146  	// structTestIn is input data for the big struct test of all supported
   147  	// types.
   148  	structTestIn := []byte{
   149  		0x00, 0x00, 0x00, 0x7F, // A
   150  		0x00, 0x00, 0x00, 0xFF, // B
   151  		0x00, 0x00, 0x7F, 0xFF, // C
   152  		0x00, 0x00, 0xFF, 0xFF, // D
   153  		0x7F, 0xFF, 0xFF, 0xFF, // E
   154  		0xFF, 0xFF, 0xFF, 0xFF, // F
   155  		0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // G
   156  		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // H
   157  		0x00, 0x00, 0x00, 0x01, // I
   158  		0x40, 0x48, 0xF5, 0xC3, // J
   159  		0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18, // K
   160  		0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00, // L
   161  		0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, // M
   162  		0x01, 0x02, 0x03, 0x00, // N
   163  		0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00,
   164  		0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, // O
   165  		0x00, 0x00, 0x00, 0x03, 0x6F, 0x6E, 0x65, 0x00, // P[0].A
   166  		0x00, 0x00, 0x00, 0x01, // P[0].B
   167  		0x00, 0x00, 0x00, 0x03, 0x74, 0x77, 0x6F, 0x00, // P[1].A
   168  		0x00, 0x00, 0x00, 0x02, // P[1].B
   169  		0x00, 0x00, 0x00, 0x03, 0x62, 0x61, 0x72, 0x00, // Q.A
   170  		0x00, 0x00, 0x00, 0x03, // Q.B
   171  		0x00, 0x00, 0x00, 0x02, // R length
   172  		0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31, // R key map1
   173  		0x00, 0x00, 0x00, 0x01, // R value map1
   174  		0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x32, // R key map2
   175  		0x00, 0x00, 0x00, 0x02, // R value map2
   176  		0x00, 0x00, 0x00, 0x14, 0x32, 0x30, 0x31, 0x34,
   177  		0x2d, 0x30, 0x34, 0x2d, 0x30, 0x34, 0x54, 0x30,
   178  		0x33, 0x3a, 0x32, 0x34, 0x3a, 0x34, 0x38, 0x5a, // S
   179  	}
   180  
   181  	// structTestWant is the expected output after unmarshalling
   182  	// structTestIn.
   183  	structTestWant := allTypesTest{
   184  		127,                                     // A
   185  		255,                                     // B
   186  		32767,                                   // C
   187  		65535,                                   // D
   188  		2147483647,                              // E
   189  		4294967295,                              // F
   190  		9223372036854775807,                     // G
   191  		18446744073709551615,                    // H
   192  		true,                                    // I
   193  		3.14,                                    // J
   194  		3.141592653589793,                       // K
   195  		"xdr",                                   // L
   196  		[]byte{1, 2, 3, 4},                      // M
   197  		[3]byte{1, 2, 3},                        // N
   198  		[]int16{512, 1024, 2048},                // O
   199  		[2]subTest{{"one", 1}, {"two", 2}},      // P
   200  		subTest{"bar", 3},                       // Q
   201  		map[string]uint32{"map1": 1, "map2": 2}, // R
   202  		time.Unix(1396581888, 0).UTC(),          // S
   203  	}
   204  
   205  	tests := []struct {
   206  		in      []byte      // input bytes
   207  		wantVal interface{} // expected value
   208  		wantN   int         // expected number of bytes read
   209  		err     error       // expected error
   210  	}{
   211  		// int8 - XDR Integer
   212  		{[]byte{0x00, 0x00, 0x00, 0x00}, int8(0), 4, nil},
   213  		{[]byte{0x00, 0x00, 0x00, 0x40}, int8(64), 4, nil},
   214  		{[]byte{0x00, 0x00, 0x00, 0x7F}, int8(127), 4, nil},
   215  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, int8(-1), 4, nil},
   216  		{[]byte{0xFF, 0xFF, 0xFF, 0x80}, int8(-128), 4, nil},
   217  		// Expected Failures -- 128, -129 overflow int8 and not enough
   218  		// bytes
   219  		{[]byte{0x00, 0x00, 0x00, 0x80}, int8(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   220  		{[]byte{0xFF, 0xFF, 0xFF, 0x7F}, int8(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   221  		{[]byte{0x00, 0x00, 0x00}, int8(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   222  
   223  		// uint8 - XDR Unsigned Integer
   224  		{[]byte{0x00, 0x00, 0x00, 0x00}, uint8(0), 4, nil},
   225  		{[]byte{0x00, 0x00, 0x00, 0x40}, uint8(64), 4, nil},
   226  		{[]byte{0x00, 0x00, 0x00, 0xFF}, uint8(255), 4, nil},
   227  		// Expected Failures -- 256, -1 overflow uint8 and not enough
   228  		// bytes
   229  		{[]byte{0x00, 0x00, 0x01, 0x00}, uint8(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   230  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, uint8(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   231  		{[]byte{0x00, 0x00, 0x00}, uint8(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   232  
   233  		// int16 - XDR Integer
   234  		{[]byte{0x00, 0x00, 0x00, 0x00}, int16(0), 4, nil},
   235  		{[]byte{0x00, 0x00, 0x04, 0x00}, int16(1024), 4, nil},
   236  		{[]byte{0x00, 0x00, 0x7F, 0xFF}, int16(32767), 4, nil},
   237  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, int16(-1), 4, nil},
   238  		{[]byte{0xFF, 0xFF, 0x80, 0x00}, int16(-32768), 4, nil},
   239  		// Expected Failures -- 32768, -32769 overflow int16 and not
   240  		// enough bytes
   241  		{[]byte{0x00, 0x00, 0x80, 0x00}, int16(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   242  		{[]byte{0xFF, 0xFF, 0x7F, 0xFF}, int16(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   243  		{[]byte{0x00, 0x00, 0x00}, uint16(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   244  
   245  		// uint16 - XDR Unsigned Integer
   246  		{[]byte{0x00, 0x00, 0x00, 0x00}, uint16(0), 4, nil},
   247  		{[]byte{0x00, 0x00, 0x04, 0x00}, uint16(1024), 4, nil},
   248  		{[]byte{0x00, 0x00, 0xFF, 0xFF}, uint16(65535), 4, nil},
   249  		// Expected Failures -- 65536, -1 overflow uint16 and not enough
   250  		// bytes
   251  		{[]byte{0x00, 0x01, 0x00, 0x00}, uint16(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   252  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, uint16(0), 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   253  		{[]byte{0x00, 0x00, 0x00}, uint16(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   254  
   255  		// int32 - XDR Integer
   256  		{[]byte{0x00, 0x00, 0x00, 0x00}, int32(0), 4, nil},
   257  		{[]byte{0x00, 0x04, 0x00, 0x00}, int32(262144), 4, nil},
   258  		{[]byte{0x7F, 0xFF, 0xFF, 0xFF}, int32(2147483647), 4, nil},
   259  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, int32(-1), 4, nil},
   260  		{[]byte{0x80, 0x00, 0x00, 0x00}, int32(-2147483648), 4, nil},
   261  		// Expected Failure -- not enough bytes
   262  		{[]byte{0x00, 0x00, 0x00}, int32(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   263  
   264  		// uint32 - XDR Unsigned Integer
   265  		{[]byte{0x00, 0x00, 0x00, 0x00}, uint32(0), 4, nil},
   266  		{[]byte{0x00, 0x04, 0x00, 0x00}, uint32(262144), 4, nil},
   267  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, uint32(4294967295), 4, nil},
   268  		// Expected Failure -- not enough bytes
   269  		{[]byte{0x00, 0x00, 0x00}, uint32(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   270  
   271  		// int64 - XDR Hyper Integer
   272  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(0), 8, nil},
   273  		{[]byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, int64(1 << 34), 8, nil},
   274  		{[]byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(1 << 42), 8, nil},
   275  		{[]byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(9223372036854775807), 8, nil},
   276  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(-1), 8, nil},
   277  		{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(-9223372036854775808), 8, nil},
   278  		// Expected Failures -- not enough bytes
   279  		{[]byte{0x7f, 0xff, 0xff}, int64(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   280  		{[]byte{0x7f, 0x00, 0xff, 0x00}, int64(0), 4, &UnmarshalError{ErrorCode: ErrIO}},
   281  
   282  		// uint64 - XDR Unsigned Hyper Integer
   283  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(0), 8, nil},
   284  		{[]byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 34), 8, nil},
   285  		{[]byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 42), 8, nil},
   286  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, uint64(18446744073709551615), 8, nil},
   287  		{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(9223372036854775808), 8, nil},
   288  		// Expected Failures -- not enough bytes
   289  		{[]byte{0xff, 0xff, 0xff}, uint64(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   290  		{[]byte{0xff, 0x00, 0xff, 0x00}, uint64(0), 4, &UnmarshalError{ErrorCode: ErrIO}},
   291  
   292  		// bool - XDR Integer
   293  		{[]byte{0x00, 0x00, 0x00, 0x00}, false, 4, nil},
   294  		{[]byte{0x00, 0x00, 0x00, 0x01}, true, 4, nil},
   295  		// Expected Failures -- only 0 or 1 is a valid bool
   296  		{[]byte{0x01, 0x00, 0x00, 0x00}, true, 4, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   297  		{[]byte{0x00, 0x00, 0x40, 0x00}, true, 4, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   298  
   299  		// float32 - XDR Floating-Point
   300  		{[]byte{0x00, 0x00, 0x00, 0x00}, float32(0), 4, nil},
   301  		{[]byte{0x40, 0x48, 0xF5, 0xC3}, float32(3.14), 4, nil},
   302  		{[]byte{0x49, 0x96, 0xB4, 0x38}, float32(1234567.0), 4, nil},
   303  		{[]byte{0xFF, 0x80, 0x00, 0x00}, float32(math.Inf(-1)), 4, nil},
   304  		{[]byte{0x7F, 0x80, 0x00, 0x00}, float32(math.Inf(0)), 4, nil},
   305  		// Expected Failures -- not enough bytes
   306  		{[]byte{0xff, 0xff}, float32(0), 2, &UnmarshalError{ErrorCode: ErrIO}},
   307  		{[]byte{0xff, 0x00, 0xff}, float32(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   308  
   309  		// float64 - XDR Double-precision Floating-Point
   310  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(0), 8, nil},
   311  		{[]byte{0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18}, float64(3.141592653589793), 8, nil},
   312  		{[]byte{0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(-1)), 8, nil},
   313  		{[]byte{0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(0)), 8, nil},
   314  		// Expected Failures -- not enough bytes
   315  		{[]byte{0xff, 0xff, 0xff}, float64(0), 3, &UnmarshalError{ErrorCode: ErrIO}},
   316  		{[]byte{0xff, 0x00, 0xff, 0x00}, float64(0), 4, &UnmarshalError{ErrorCode: ErrIO}},
   317  
   318  		// string - XDR String
   319  		{[]byte{0x00, 0x00, 0x00, 0x00}, "", 4, nil},
   320  		{[]byte{0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00}, "xdr", 8, nil},
   321  		{[]byte{0x00, 0x00, 0x00, 0x06, 0xCF, 0x84, 0x3D, 0x32, 0xCF, 0x80, 0x00, 0x00}, "τ=2π", 12, nil},
   322  		// Expected Failures -- not enough bytes for length, length
   323  		// larger than allowed, and len larger than available bytes.
   324  		{[]byte{0x00, 0x00, 0xFF}, "", 3, &UnmarshalError{ErrorCode: ErrIO}},
   325  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, "", 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   326  		{[]byte{0x00, 0x00, 0x00, 0xFF}, "", 4, &UnmarshalError{ErrorCode: ErrIO}},
   327  
   328  		// []byte - XDR Variable Opaque
   329  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00}, []byte{0x01}, 8, nil},
   330  		{[]byte{0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00}, []byte{0x01, 0x02, 0x03}, 8, nil},
   331  		// Expected Failures -- not enough bytes for length, length
   332  		// larger than allowed, and data larger than available bytes.
   333  		{[]byte{0x00, 0x00, 0xFF}, []byte{}, 3, &UnmarshalError{ErrorCode: ErrIO}},
   334  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, []byte{}, 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   335  		{[]byte{0x00, 0x00, 0x00, 0xFF}, []byte{}, 4, &UnmarshalError{ErrorCode: ErrIO}},
   336  
   337  		// [#]byte - XDR Fixed Opaque
   338  		{[]byte{0x01, 0x00, 0x00, 0x00}, [1]byte{0x01}, 4, nil},
   339  		{[]byte{0x01, 0x02, 0x00, 0x00}, [2]byte{0x01, 0x02}, 4, nil},
   340  		{[]byte{0x01, 0x02, 0x03, 0x00}, [3]byte{0x01, 0x02, 0x03}, 4, nil},
   341  		{[]byte{0x01, 0x02, 0x03, 0x04}, [4]byte{0x01, 0x02, 0x03, 0x04}, 4, nil},
   342  		{[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00}, [5]byte{0x01, 0x02, 0x03, 0x04, 0x05}, 8, nil},
   343  		// Expected Failure -- fixed opaque data not padded
   344  		{[]byte{0x01}, [1]byte{}, 1, &UnmarshalError{ErrorCode: ErrIO}},
   345  
   346  		// []<type> - XDR Variable-Length Array
   347  		{[]byte{0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00},
   348  			[]int16{512, 1024, 2048}, 16, nil},
   349  		{[]byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, []bool{true, false}, 12, nil},
   350  		// Expected Failure -- 2 entries in array - not enough bytes
   351  		{[]byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, []bool{}, 8, &UnmarshalError{ErrorCode: ErrIO}},
   352  
   353  		// [#]<type> - XDR Fixed-Length Array
   354  		{[]byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00}, [2]uint32{512, 1024}, 8, nil},
   355  		// Expected Failure -- 2 entries in array - not enough bytes
   356  		{[]byte{0x00, 0x00, 0x00, 0x02}, [2]uint32{}, 4, &UnmarshalError{ErrorCode: ErrIO}},
   357  
   358  		// map[string]uint32
   359  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31, 0x00, 0x00, 0x00, 0x01},
   360  			map[string]uint32{"map1": 1}, 16, nil},
   361  		// Expected Failures -- not enough bytes in length, 1 map
   362  		// element no extra bytes, 1 map element not enough bytes for
   363  		// key, 1 map element not enough bytes for value.
   364  		{[]byte{0x00, 0x00, 0x00}, map[string]uint32{}, 3, &UnmarshalError{ErrorCode: ErrIO}},
   365  		{[]byte{0x00, 0x00, 0x00, 0x01}, map[string]uint32{}, 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   366  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, map[string]uint32{}, 7, &UnmarshalError{ErrorCode: ErrIO}},
   367  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31},
   368  			map[string]uint32{}, 12, &UnmarshalError{ErrorCode: ErrIO}},
   369  
   370  		// time.Time - XDR String per RFC3339
   371  		{[]byte{
   372  			0x00, 0x00, 0x00, 0x14, 0x32, 0x30, 0x31, 0x34,
   373  			0x2d, 0x30, 0x34, 0x2d, 0x30, 0x34, 0x54, 0x30,
   374  			0x33, 0x3a, 0x32, 0x34, 0x3a, 0x34, 0x38, 0x5a,
   375  		}, time.Unix(1396581888, 0).UTC(), 24, nil},
   376  		// Expected Failures -- not enough bytes, improperly formatted
   377  		// time
   378  		{[]byte{0x00, 0x00, 0x00}, time.Time{}, 3, &UnmarshalError{ErrorCode: ErrIO}},
   379  		{[]byte{0x00, 0x00, 0x00, 0x00}, time.Time{}, 4, &UnmarshalError{ErrorCode: ErrParseTime}},
   380  
   381  		// struct - XDR Structure -- test struct contains all supported types
   382  		{structTestIn, structTestWant, len(structTestIn), nil},
   383  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02},
   384  			opaqueStruct{[]uint8{1}, [1]uint8{2}}, 12, nil},
   385  		// Expected Failures -- normal struct not enough bytes, non
   386  		// opaque data not enough bytes for slice, non opaque data not
   387  		// enough bytes for slice.
   388  		{[]byte{0x00, 0x00}, allTypesTest{}, 2, &UnmarshalError{ErrorCode: ErrIO}},
   389  		{[]byte{0x00, 0x00, 0x00}, opaqueStruct{}, 3, &UnmarshalError{ErrorCode: ErrIO}},
   390  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00}, opaqueStruct{}, 5, &UnmarshalError{ErrorCode: ErrIO}},
   391  
   392  		// Expected errors
   393  		{nil, nilInterface, 0, &UnmarshalError{ErrorCode: ErrNilInterface}},
   394  		{nil, &nilInterface, 0, &UnmarshalError{ErrorCode: ErrIO}},
   395  		{nil, testChan, 0, &UnmarshalError{ErrorCode: ErrUnsupportedType}},
   396  		{nil, &testChan, 0, &UnmarshalError{ErrorCode: ErrIO}},
   397  		{nil, testFunc, 0, &UnmarshalError{ErrorCode: ErrUnsupportedType}},
   398  		{nil, &testFunc, 0, &UnmarshalError{ErrorCode: ErrIO}},
   399  		{nil, testComplex64, 0, &UnmarshalError{ErrorCode: ErrUnsupportedType}},
   400  		{nil, &testComplex64, 0, &UnmarshalError{ErrorCode: ErrIO}},
   401  		{nil, testComplex128, 0, &UnmarshalError{ErrorCode: ErrUnsupportedType}},
   402  		{nil, &testComplex128, 0, &UnmarshalError{ErrorCode: ErrIO}},
   403  	}
   404  
   405  	for i, test := range tests {
   406  		// Attempt to unmarshal to a non-pointer version of each
   407  		// positive test type to ensure the appropriate error is
   408  		// returned.
   409  		if test.err == nil && test.wantVal != nil {
   410  			testName := fmt.Sprintf("Unmarshal #%d (non-pointer)", i)
   411  			wantErr := &UnmarshalError{ErrorCode: ErrBadArguments}
   412  
   413  			wvt := reflect.TypeOf(test.wantVal)
   414  			want := reflect.New(wvt).Elem().Interface()
   415  			n, err := Unmarshal(bytes.NewReader(test.in), want)
   416  			if !testExpectedURet(t, testName, n, 0, err, wantErr) {
   417  				continue
   418  			}
   419  		}
   420  
   421  		testName := fmt.Sprintf("Unmarshal #%d", i)
   422  		// Create a new pointer to the appropriate type.
   423  		var want interface{}
   424  		if test.wantVal != nil {
   425  			wvt := reflect.TypeOf(test.wantVal)
   426  			want = reflect.New(wvt).Interface()
   427  		}
   428  		n, err := Unmarshal(bytes.NewReader(test.in), want)
   429  
   430  		// First ensure the number of bytes read is the expected value
   431  		// and the error is the expected one.
   432  		if !testExpectedURet(t, testName, n, test.wantN, err, test.err) {
   433  			continue
   434  		}
   435  		if test.err != nil {
   436  			continue
   437  		}
   438  
   439  		// Finally, ensure the read value is the expected one.
   440  		wantElem := reflect.Indirect(reflect.ValueOf(want)).Interface()
   441  		if !reflect.DeepEqual(wantElem, test.wantVal) {
   442  			t.Errorf("%s: unexpected result - got: %v want: %v\n",
   443  				testName, wantElem, test.wantVal)
   444  			continue
   445  		}
   446  	}
   447  
   448  	// successful enum decoding
   449  	var anEnum AnEnum
   450  	_, err := Unmarshal(bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x01}), &anEnum)
   451  
   452  	if err != nil {
   453  		t.Errorf("enum decode: expected no error, got: %v\n", err)
   454  	}
   455  
   456  	if anEnum != AnEnum(1) {
   457  		t.Errorf("enum decode: expected 1, got: %v\n", anEnum)
   458  	}
   459  
   460  	// failed enum decoding
   461  	_, err = Unmarshal(bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x03}), &anEnum)
   462  
   463  	if err == nil {
   464  		t.Errorf("enum decode: expected error, got none")
   465  	}
   466  
   467  	// union decoding
   468  	var u aUnion
   469  	// void arm
   470  	_, err = Unmarshal(bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x02}), &u)
   471  	if err != nil {
   472  		t.Errorf("union decode: expected no error, got: %v\n", err)
   473  	}
   474  
   475  	if u.Type != AnEnum(2) {
   476  		t.Errorf("union decode: expected type == 2, got: %v\n", u.Type)
   477  	}
   478  
   479  	if u.Data != nil {
   480  		t.Errorf("union decode: expected data to be nil, it was not.")
   481  	}
   482  
   483  	// non-void arm
   484  	_, err = Unmarshal(bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}), &u)
   485  	if err != nil {
   486  		t.Errorf("union decode: expected no error, got: %v\n", err)
   487  	}
   488  
   489  	if u.Type != AnEnum(0) {
   490  		t.Errorf("union decode: expected type == 0, got: %v\n", u.Type)
   491  	}
   492  
   493  	if u.Data == nil {
   494  		t.Errorf("union decode: expected data to be filled, it was not.")
   495  	}
   496  
   497  	if *u.Data != 5 {
   498  		t.Errorf("union decode: expected data to be 5, got: %v\n", *u.Data)
   499  	}
   500  
   501  	// non-void arm: xdrmaxsize
   502  	_, err = Unmarshal(bytes.NewReader([]byte{
   503  		0x00, 0x00, 0x00, 0x01, // Text
   504  		0x00, 0x00, 0x00, 0x1D, // String length = 29
   505  		0x74, 0x65, 0x73, 0x74, // "test" 4
   506  		0x74, 0x65, 0x73, 0x74, // "test" 8
   507  		0x74, 0x65, 0x73, 0x74, // "test" 12
   508  		0x74, 0x65, 0x73, 0x74, // "test" 16
   509  		0x74, 0x65, 0x73, 0x74, // "test" 20
   510  		0x74, 0x65, 0x73, 0x74, // "test" 24
   511  		0x74, 0x65, 0x73, 0x74, // "test" 28
   512  		0x74, 0x00, 0x00, 0x00, // "test" 29
   513  	}), &u)
   514  	if err == nil {
   515  		t.Errorf("union decode: expected error")
   516  	}
   517  
   518  	if err.Error() != "xdr:DecodeString: data exceeds max slice limit - read: '29'" {
   519  		t.Errorf("union decode: expected 'data exceeds max slice limit' error")
   520  	}
   521  
   522  	// invalid enum for switch
   523  	_, err = Unmarshal(bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x03}), &u)
   524  	if err == nil {
   525  		t.Errorf("union decode: expected error, got nil")
   526  	}
   527  
   528  	// invalid arm for switch
   529  	_, err = Unmarshal(bytes.NewReader([]byte{0xFF, 0xFF, 0xFF, 0xFF}), &u)
   530  	if err == nil {
   531  		t.Errorf("union decode: expected error, got nil")
   532  	}
   533  }
   534  
   535  // decodeFunc is used to identify which public function of the Decoder object
   536  // a test applies to.
   537  type decodeFunc int
   538  
   539  const (
   540  	fDecodeBool decodeFunc = iota
   541  	fDecodeDouble
   542  	fDecodeEnum
   543  	fDecodeFixedOpaque
   544  	fDecodeFloat
   545  	fDecodeHyper
   546  	fDecodeInt
   547  	fDecodeOpaque
   548  	fDecodeString
   549  	fDecodeUhyper
   550  	fDecodeUint
   551  )
   552  
   553  // Map of decodeFunc values to names for pretty printing.
   554  var decodeFuncStrings = map[decodeFunc]string{
   555  	fDecodeBool:        "DecodeBool",
   556  	fDecodeDouble:      "DecodeDouble",
   557  	fDecodeEnum:        "DecodeEnum",
   558  	fDecodeFixedOpaque: "DecodeFixedOpaque",
   559  	fDecodeFloat:       "DecodeFloat",
   560  	fDecodeHyper:       "DecodeHyper",
   561  	fDecodeInt:         "DecodeInt",
   562  	fDecodeOpaque:      "DecodeOpaque",
   563  	fDecodeString:      "DecodeString",
   564  	fDecodeUhyper:      "DecodeUhyper",
   565  	fDecodeUint:        "DecodeUint",
   566  }
   567  
   568  // String implements the fmt.Stringer interface and returns the encode function
   569  // as a human-readable string.
   570  func (f decodeFunc) String() string {
   571  	if s := decodeFuncStrings[f]; s != "" {
   572  		return s
   573  	}
   574  	return fmt.Sprintf("Unknown decodeFunc (%d)", f)
   575  }
   576  
   577  // TestDecoder ensures a Decoder works as intended.
   578  func TestDecoder(t *testing.T) {
   579  	tests := []struct {
   580  		f       decodeFunc  // function to use to decode
   581  		in      []byte      // input bytes
   582  		wantVal interface{} // expected value
   583  		wantN   int         // expected number of bytes read
   584  		err     error       // expected error
   585  	}{
   586  		// Bool
   587  		{fDecodeBool, []byte{0x00, 0x00, 0x00, 0x00}, false, 4, nil},
   588  		{fDecodeBool, []byte{0x00, 0x00, 0x00, 0x01}, true, 4, nil},
   589  		// Expected Failures -- only 0 or 1 is a valid bool
   590  		{fDecodeBool, []byte{0x01, 0x00, 0x00, 0x00}, true, 4, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   591  		{fDecodeBool, []byte{0x00, 0x00, 0x40, 0x00}, true, 4, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   592  
   593  		// Double
   594  		{fDecodeDouble, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(0), 8, nil},
   595  		{fDecodeDouble, []byte{0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18}, float64(3.141592653589793), 8, nil},
   596  		{fDecodeDouble, []byte{0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(-1)), 8, nil},
   597  		{fDecodeDouble, []byte{0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(0)), 8, nil},
   598  
   599  		// Enum
   600  		{fDecodeEnum, []byte{0x00, 0x00, 0x00, 0x00}, int32(0), 4, nil},
   601  		{fDecodeEnum, []byte{0x00, 0x00, 0x00, 0x01}, int32(1), 4, nil},
   602  		{fDecodeEnum, []byte{0x00, 0x00, 0x00, 0x02}, nil, 4, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   603  		{fDecodeEnum, []byte{0x12, 0x34, 0x56, 0x78}, nil, 4, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   604  		{fDecodeEnum, []byte{0x00}, nil, 1, &UnmarshalError{ErrorCode: ErrIO}},
   605  
   606  		// FixedOpaque
   607  		{fDecodeFixedOpaque, []byte{0x01, 0x00, 0x00, 0x00}, []byte{0x01}, 4, nil},
   608  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x00, 0x00}, []byte{0x01, 0x02}, 4, nil},
   609  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x00}, []byte{0x01, 0x02, 0x03}, 4, nil},
   610  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, 4, nil},
   611  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00}, []byte{0x01, 0x02, 0x03, 0x04, 0x05}, 8, nil},
   612  		// Expected Failure -- fixed opaque data not padded
   613  		{fDecodeFixedOpaque, []byte{0x01}, []byte{0x00}, 1, &UnmarshalError{ErrorCode: ErrIO}},
   614  
   615  		// Float
   616  		{fDecodeFloat, []byte{0x00, 0x00, 0x00, 0x00}, float32(0), 4, nil},
   617  		{fDecodeFloat, []byte{0x40, 0x48, 0xF5, 0xC3}, float32(3.14), 4, nil},
   618  		{fDecodeFloat, []byte{0x49, 0x96, 0xB4, 0x38}, float32(1234567.0), 4, nil},
   619  		{fDecodeFloat, []byte{0xFF, 0x80, 0x00, 0x00}, float32(math.Inf(-1)), 4, nil},
   620  		{fDecodeFloat, []byte{0x7F, 0x80, 0x00, 0x00}, float32(math.Inf(0)), 4, nil},
   621  
   622  		// Hyper
   623  		{fDecodeHyper, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(0), 8, nil},
   624  		{fDecodeHyper, []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, int64(1 << 34), 8, nil},
   625  		{fDecodeHyper, []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(1 << 42), 8, nil},
   626  		{fDecodeHyper, []byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(9223372036854775807), 8, nil},
   627  		{fDecodeHyper, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(-1), 8, nil},
   628  		{fDecodeHyper, []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(-9223372036854775808), 8, nil},
   629  
   630  		// Int
   631  		{fDecodeInt, []byte{0x00, 0x00, 0x00, 0x00}, int32(0), 4, nil},
   632  		{fDecodeInt, []byte{0x00, 0x04, 0x00, 0x00}, int32(262144), 4, nil},
   633  		{fDecodeInt, []byte{0x7F, 0xFF, 0xFF, 0xFF}, int32(2147483647), 4, nil},
   634  		{fDecodeInt, []byte{0xFF, 0xFF, 0xFF, 0xFF}, int32(-1), 4, nil},
   635  		{fDecodeInt, []byte{0x80, 0x00, 0x00, 0x00}, int32(-2147483648), 4, nil},
   636  
   637  		// Opaque
   638  		{fDecodeOpaque, []byte{0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00}, []byte{0x01}, 8, nil},
   639  		{fDecodeOpaque, []byte{0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00}, []byte{0x01, 0x02, 0x03}, 8, nil},
   640  		// Expected Failures -- not enough bytes for length, length
   641  		// larger than allowed, and data larger than available bytes.
   642  		{fDecodeOpaque, []byte{0x00, 0x00, 0xFF}, []byte{}, 3, &UnmarshalError{ErrorCode: ErrIO}},
   643  		{fDecodeOpaque, []byte{0xFF, 0xFF, 0xFF, 0xFF}, []byte{}, 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   644  		{fDecodeOpaque, []byte{0x7F, 0xFF, 0xFF, 0xFD}, []byte{}, 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   645  		{fDecodeOpaque, []byte{0x00, 0x00, 0x00, 0xFF}, []byte{}, 4, &UnmarshalError{ErrorCode: ErrIO}},
   646  
   647  		// String
   648  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0x00}, "", 4, nil},
   649  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00}, "xdr", 8, nil},
   650  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0x06, 0xCF, 0x84, 0x3D, 0x32, 0xCF, 0x80, 0x00, 0x00}, "τ=2π", 12, nil},
   651  		// Expected Failures -- not enough bytes for length, length
   652  		// larger than allowed, and len larger than available bytes.
   653  		{fDecodeString, []byte{0x00, 0x00, 0xFF}, "", 3, &UnmarshalError{ErrorCode: ErrIO}},
   654  		{fDecodeString, []byte{0xFF, 0xFF, 0xFF, 0xFF}, "", 4, &UnmarshalError{ErrorCode: ErrOverflow}},
   655  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0xFF}, "", 4, &UnmarshalError{ErrorCode: ErrIO}},
   656  
   657  		// Uhyper
   658  		{fDecodeUhyper, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(0), 8, nil},
   659  		{fDecodeUhyper, []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 34), 8, nil},
   660  		{fDecodeUhyper, []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 42), 8, nil},
   661  		{fDecodeUhyper, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, uint64(18446744073709551615), 8, nil},
   662  		{fDecodeUhyper, []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(9223372036854775808), 8, nil},
   663  
   664  		// Uint
   665  		{fDecodeUint, []byte{0x00, 0x00, 0x00, 0x00}, uint32(0), 4, nil},
   666  		{fDecodeUint, []byte{0x00, 0x04, 0x00, 0x00}, uint32(262144), 4, nil},
   667  		{fDecodeUint, []byte{0xFF, 0xFF, 0xFF, 0xFF}, uint32(4294967295), 4, nil},
   668  	}
   669  
   670  	validEnums := make(map[int32]bool)
   671  	validEnums[0] = true
   672  	validEnums[1] = true
   673  
   674  	var rv interface{}
   675  	var n int
   676  	var err error
   677  
   678  	for i, test := range tests {
   679  		err = nil
   680  		dec := NewDecoder(bytes.NewReader(test.in))
   681  		switch test.f {
   682  		case fDecodeBool:
   683  			rv, n, err = dec.DecodeBool()
   684  		case fDecodeDouble:
   685  			rv, n, err = dec.DecodeDouble()
   686  		case fDecodeEnum:
   687  			rv, n, err = dec.DecodeEnum(validEnums)
   688  		case fDecodeFixedOpaque:
   689  			want := test.wantVal.([]byte)
   690  			rv, n, err = dec.DecodeFixedOpaque(int32(len(want)))
   691  		case fDecodeFloat:
   692  			rv, n, err = dec.DecodeFloat()
   693  		case fDecodeHyper:
   694  			rv, n, err = dec.DecodeHyper()
   695  		case fDecodeInt:
   696  			rv, n, err = dec.DecodeInt()
   697  		case fDecodeOpaque:
   698  			rv, n, err = dec.DecodeOpaque(0)
   699  		case fDecodeString:
   700  			rv, n, err = dec.DecodeString(0)
   701  		case fDecodeUhyper:
   702  			rv, n, err = dec.DecodeUhyper()
   703  		case fDecodeUint:
   704  			rv, n, err = dec.DecodeUint()
   705  		default:
   706  			t.Errorf("%v #%d unrecognized function", test.f, i)
   707  			continue
   708  		}
   709  
   710  		// First ensure the number of bytes read is the expected value
   711  		// and the error is the expected one.
   712  		testName := fmt.Sprintf("%v #%d", test.f, i)
   713  		if !testExpectedURet(t, testName, n, test.wantN, err, test.err) {
   714  			continue
   715  		}
   716  		if test.err != nil {
   717  			continue
   718  		}
   719  
   720  		// Finally, ensure the read value is the expected one.
   721  		if !reflect.DeepEqual(rv, test.wantVal) {
   722  			t.Errorf("%s: unexpected result - got: %v want: %v\n",
   723  				testName, rv, test.wantVal)
   724  			continue
   725  		}
   726  	}
   727  }
   728  
   729  // TestUnmarshalCorners ensures the Unmarshal function properly handles various
   730  // cases not already covered by the other tests.
   731  func TestUnmarshalCorners(t *testing.T) {
   732  	buf := []byte{
   733  		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
   734  		0x00, 0x00, 0x00, 0x02,
   735  	}
   736  
   737  	// Ensure unmarshal to unsettable pointer returns the expected error.
   738  	testName := "Unmarshal to unsettable pointer"
   739  	var i32p *int32
   740  	expectedN := 0
   741  	expectedErr := error(&UnmarshalError{ErrorCode: ErrNotSettable})
   742  	n, err := Unmarshal(bytes.NewReader(buf), i32p)
   743  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   744  
   745  	// Ensure decode of unsettable pointer returns the expected error.
   746  	testName = "Decode to unsettable pointer"
   747  	expectedN = 4
   748  	expectedErr = &UnmarshalError{ErrorCode: ErrNotSettable}
   749  	n, err = TstDecode(bytes.NewReader(buf))(reflect.ValueOf(i32p), 0, DecodeDefaultMaxDepth)
   750  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   751  
   752  	// Ensure unmarshal to indirected unsettable pointer returns the
   753  	// expected error.
   754  	testName = "Unmarshal to indirected unsettable pointer"
   755  	ii32p := interface{}(i32p)
   756  	expectedN = 0
   757  	expectedErr = &UnmarshalError{ErrorCode: ErrNotSettable}
   758  	n, err = Unmarshal(bytes.NewReader(buf), &ii32p)
   759  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   760  
   761  	// Ensure unmarshal to embedded unsettable interface value returns the
   762  	// expected error.
   763  	testName = "Unmarshal to embedded unsettable interface value"
   764  	var i32 int32
   765  	ii32 := interface{}(i32)
   766  	expectedN = 0
   767  	expectedErr = &UnmarshalError{ErrorCode: ErrNotSettable}
   768  	n, err = Unmarshal(bytes.NewReader(buf), &ii32)
   769  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   770  
   771  	// Ensure unmarshal to embedded interface value works properly.
   772  	testName = "Unmarshal to embedded interface value"
   773  	ii32vp := interface{}(&i32)
   774  	expectedN = 4
   775  	expectedErr = nil
   776  	ii32vpr := int32(1)
   777  	expectedVal := interface{}(&ii32vpr)
   778  	n, err = Unmarshal(bytes.NewReader(buf), &ii32vp)
   779  	if testExpectedURet(t, testName, n, expectedN, err, expectedErr) {
   780  		if !reflect.DeepEqual(ii32vp, expectedVal) {
   781  			t.Errorf("%s: unexpected result - got: %v want: %v\n",
   782  				testName, ii32vp, expectedVal)
   783  		}
   784  	}
   785  
   786  	// Ensure decode of an invalid reflect value returns the expected
   787  	// error.
   788  	testName = "Decode invalid reflect value"
   789  	expectedN = 0
   790  	expectedErr = error(&UnmarshalError{ErrorCode: ErrUnsupportedType})
   791  	n, err = TstDecode(bytes.NewReader(buf))(reflect.Value{}, 0, DecodeDefaultMaxDepth)
   792  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   793  
   794  	// Ensure unmarshal to a slice with a cap and 0 length adjusts the
   795  	// length properly.
   796  	testName = "Unmarshal to capped slice"
   797  	cappedSlice := make([]bool, 0, 1)
   798  	expectedN = 8
   799  	expectedErr = nil
   800  	expectedVal = []bool{true}
   801  	n, err = Unmarshal(bytes.NewReader(buf), &cappedSlice)
   802  	if testExpectedURet(t, testName, n, expectedN, err, expectedErr) {
   803  		if !reflect.DeepEqual(cappedSlice, expectedVal) {
   804  			t.Errorf("%s: unexpected result - got: %v want: %v\n",
   805  				testName, cappedSlice, expectedVal)
   806  		}
   807  	}
   808  
   809  	// Ensure decode to a slice retuns expected number of elements
   810  	testName = "Unmarshal to oversized slice"
   811  	oversizedSlice := make([]bool, 2, 2)
   812  	expectedN = 8
   813  	expectedErr = nil
   814  	expectedVal = []bool{true}
   815  	n, err = Unmarshal(bytes.NewReader(buf), &oversizedSlice)
   816  	if testExpectedURet(t, testName, n, expectedN, err, expectedErr) {
   817  		if !reflect.DeepEqual(oversizedSlice, expectedVal) {
   818  			t.Errorf("%s: unexpected result - got: %v want: %v\n",
   819  				testName, oversizedSlice, expectedVal)
   820  		}
   821  	}
   822  
   823  	// Ensure unmarshal to struct with both exported and unexported fields
   824  	// skips the unexported fields but still unmarshals to the exported
   825  	// fields.
   826  	type unexportedStruct struct {
   827  		unexported int
   828  		Exported   int
   829  	}
   830  	testName = "Unmarshal to struct with exported and unexported fields"
   831  	var tstruct unexportedStruct
   832  	expectedN = 4
   833  	expectedErr = nil
   834  	expectedVal = unexportedStruct{0, 1}
   835  	n, err = Unmarshal(bytes.NewReader(buf), &tstruct)
   836  	if testExpectedURet(t, testName, n, expectedN, err, expectedErr) {
   837  		if !reflect.DeepEqual(tstruct, expectedVal) {
   838  			t.Errorf("%s: unexpected result - got: %v want: %v\n",
   839  				testName, tstruct, expectedVal)
   840  		}
   841  	}
   842  
   843  	// Ensure decode to struct with unsettable fields return expected error.
   844  	type unsettableStruct struct {
   845  		Exported int
   846  	}
   847  	testName = "Decode to struct with unsettable fields"
   848  	var ustruct unsettableStruct
   849  	expectedN = 0
   850  	expectedErr = error(&UnmarshalError{ErrorCode: ErrNotSettable})
   851  	n, err = TstDecode(bytes.NewReader(buf))(reflect.ValueOf(ustruct), 0, DecodeDefaultMaxDepth)
   852  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   853  
   854  	// Ensure decode to struct with unsettable pointer fields return
   855  	// expected error.
   856  	type unsettablePointerStruct struct {
   857  		Exported *int
   858  	}
   859  	testName = "Decode to struct with unsettable pointer fields"
   860  	var upstruct unsettablePointerStruct
   861  	expectedN = 0
   862  	expectedErr = error(&UnmarshalError{ErrorCode: ErrNotSettable})
   863  	n, err = TstDecode(bytes.NewReader(buf))(reflect.ValueOf(upstruct), 0, DecodeDefaultMaxDepth)
   864  	testExpectedURet(t, testName, n, expectedN, err, expectedErr)
   865  }
   866  
   867  type String32 string
   868  
   869  var _ Sized = String32("hello")
   870  
   871  func (s String32) XDRMaxSize() int {
   872  	return 32
   873  }
   874  
   875  func TestSizedType(t *testing.T) {
   876  	cases := map[string]struct {
   877  		input []byte
   878  		out   string
   879  		err   error
   880  	}{
   881  		// works for 0 length
   882  		"0 length": {[]byte{0x00, 0x00, 0x00, 0x00}, "", nil},
   883  		// works for 1 length
   884  		"1 length": {[]byte{0x00, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00}, "H", nil},
   885  		// works for 32 length
   886  		"32 length": {
   887  			[]byte{
   888  				0x00, 0x00, 0x00, 0x20,
   889  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   890  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   891  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   892  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   893  			},
   894  			"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH",
   895  			nil,
   896  		},
   897  		// fails for 33 length
   898  		"33 length": {
   899  			[]byte{
   900  				0x00, 0x00, 0x00, 0x21,
   901  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   902  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   903  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   904  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   905  				0x48, 0x00, 0x00, 0x00,
   906  			},
   907  			"",
   908  			&UnmarshalError{ErrorCode: ErrOverflow},
   909  		},
   910  	}
   911  
   912  	for name, kase := range cases {
   913  		var out String32
   914  		r := bytes.NewReader(kase.input)
   915  		_, err := Unmarshal(r, &out)
   916  
   917  		if !assertError(t, name, err, kase.err) {
   918  			continue
   919  		}
   920  
   921  		if string(out) != kase.out {
   922  			t.Errorf("%s: expected output to be %#v, but got %#v", name, kase.out, out)
   923  			continue
   924  		}
   925  	}
   926  }
   927  
   928  type sizedField struct {
   929  	Val string `xdrmaxsize:"32"`
   930  }
   931  
   932  func TestSizedField(t *testing.T) {
   933  	cases := map[string]struct {
   934  		input []byte
   935  		out   string
   936  		err   error
   937  	}{
   938  		// works for 0 length
   939  		"0 length": {[]byte{0x00, 0x00, 0x00, 0x00}, "", nil},
   940  		// works for 1 length
   941  		"1 length": {[]byte{0x00, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00}, "H", nil},
   942  		// works for 32 length
   943  		"32 length": {
   944  			[]byte{
   945  				0x00, 0x00, 0x00, 0x20,
   946  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   947  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   948  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   949  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   950  			},
   951  			"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH",
   952  			nil,
   953  		},
   954  		// fails for 33 length
   955  		"33 length": {
   956  			[]byte{
   957  				0x00, 0x00, 0x00, 0x21,
   958  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   959  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   960  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   961  				0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
   962  				0x48, 0x00, 0x00, 0x00,
   963  			},
   964  			"",
   965  			&UnmarshalError{ErrorCode: ErrOverflow},
   966  		},
   967  	}
   968  
   969  	for name, kase := range cases {
   970  		var out sizedField
   971  		r := bytes.NewReader(kase.input)
   972  		_, err := Unmarshal(r, &out)
   973  
   974  		if !assertError(t, name, err, kase.err) {
   975  			continue
   976  		}
   977  
   978  		if out.Val != kase.out {
   979  			t.Errorf("%s: expected output to be %#v, but got %#v", name, kase.out, out.Val)
   980  			continue
   981  		}
   982  	}
   983  }
   984  
   985  type defEnum int32
   986  
   987  func (e defEnum) ValidEnum(v int32) bool {
   988  	return v < 1
   989  }
   990  
   991  type defUnion struct {
   992  	Type defEnum
   993  	Data *int32
   994  }
   995  
   996  func (u defUnion) SwitchFieldName() string {
   997  	return "Type"
   998  }
   999  
  1000  func (u defUnion) ArmForSwitch(sw int32) (string, bool) {
  1001  	switch sw {
  1002  	case 0:
  1003  		return "Data", true
  1004  	}
  1005  
  1006  	return "-", false
  1007  }
  1008  
  1009  func TestUnion_EnumValidation(t *testing.T) {
  1010  
  1011  	var u defUnion
  1012  	var buf bytes.Buffer
  1013  
  1014  	// encode a union with invalid value fails
  1015  	u.Type = defEnum(3)
  1016  	_, err := Marshal(&buf, u)
  1017  
  1018  	if err == nil {
  1019  		t.Errorf("expected error when marshaling invalid enum, got none.  result: %#v", buf.Bytes())
  1020  	}
  1021  
  1022  	// decoding an invalid enum value into a union results in an error
  1023  	u = defUnion{}
  1024  	invalid := []byte{0x0, 0x0, 0x0, 0x3}
  1025  	_, err = Unmarshal(bytes.NewReader(invalid), &u)
  1026  	if err == nil {
  1027  		t.Errorf("expected error when unmarshaling invalid enum into union, got none.  result: %#v", u)
  1028  	}
  1029  }
  1030  
  1031  func TestPaddedReads(t *testing.T) {
  1032  	// regression test for non-zeroed padding
  1033  
  1034  	// opaque
  1035  	dec := NewDecoder(bytes.NewReader([]byte{0x0, 0x0, 0x1, 0x1}))
  1036  	_, _, err := dec.DecodeFixedOpaque(3)
  1037  	if err == nil {
  1038  		t.Error("expected error when unmarshaling opaque with non-zero padding byte, got none")
  1039  	}
  1040  
  1041  	// string
  1042  	dec = NewDecoder(bytes.NewReader([]byte{
  1043  		0x0, 0x0, 0x0, 0x1,
  1044  		0x1, 0x1, 0x0, 0x0,
  1045  	}))
  1046  	_, _, err = dec.DecodeString(3)
  1047  	if err == nil {
  1048  		t.Error("expected error when unmarshaling string with non-zero padding byte, got none")
  1049  	}
  1050  
  1051  	// read varopaque
  1052  	dec = NewDecoder(bytes.NewReader([]byte{
  1053  		0x0, 0x0, 0x0, 0x1,
  1054  		0x1, 0x0, 0x0, 0x1,
  1055  	}))
  1056  	_, _, err = dec.DecodeOpaque(3)
  1057  	if err == nil {
  1058  		t.Error("expected error when unmarshaling varopaque with non-zero padding byte, got none")
  1059  	}
  1060  }
  1061  
  1062  func TestDecodeNilPointerIntoExistingObjectWithNotNilPointer(t *testing.T) {
  1063  	var buf bytes.Buffer
  1064  	data := "data"
  1065  	_, err := Marshal(&buf, structWithPointer{Data: &data})
  1066  	if err != nil {
  1067  		t.Error("unexpected error")
  1068  	}
  1069  
  1070  	var s structWithPointer
  1071  	_, err = Unmarshal(&buf, &s)
  1072  	if err != nil {
  1073  		t.Error("unexpected error")
  1074  	}
  1075  
  1076  	// Note:
  1077  	// 1. structWithPointer.Data is nil.
  1078  	// 2. We unmarshal into previously used object.
  1079  	_, err = Marshal(&buf, structWithPointer{})
  1080  	if err != nil {
  1081  		t.Error("unexpected error")
  1082  	}
  1083  
  1084  	_, err = Unmarshal(&buf, &s)
  1085  	if err != nil {
  1086  		t.Error("unexpected error")
  1087  	}
  1088  
  1089  	if s.Data != nil {
  1090  		t.Error("Data should be nil")
  1091  	}
  1092  }
  1093  
  1094  func TestDecodeUnionIntoExistingObject(t *testing.T) {
  1095  	var buf bytes.Buffer
  1096  	var idata int32 = 1
  1097  	sdata := "data"
  1098  	_, err := Marshal(&buf, aUnion{
  1099  		Type: 0,
  1100  		Data: &idata,
  1101  	})
  1102  	if err != nil {
  1103  		t.Error("unexpected error")
  1104  	}
  1105  
  1106  	var s aUnion
  1107  	_, err = Unmarshal(&buf, &s)
  1108  	if err != nil {
  1109  		t.Error("unexpected error")
  1110  	}
  1111  
  1112  	_, err = Marshal(&buf, aUnion{
  1113  		Type: 1,
  1114  		Text: &sdata,
  1115  	})
  1116  	if err != nil {
  1117  		t.Error("unexpected error")
  1118  	}
  1119  
  1120  	_, err = Unmarshal(&buf, &s)
  1121  	if err != nil {
  1122  		t.Error("unexpected error")
  1123  	}
  1124  
  1125  	if s.Data != nil {
  1126  		t.Error("Data should be nil")
  1127  	}
  1128  
  1129  	if s.Type != 1 {
  1130  		t.Error("Type does not match")
  1131  	}
  1132  
  1133  	if *s.Text != sdata {
  1134  		t.Error("Text does not match")
  1135  	}
  1136  }
  1137  
  1138  func TestDecodeMaxDepth(t *testing.T) {
  1139  	var buf bytes.Buffer
  1140  	data := "data"
  1141  	_, err := Marshal(&buf, structWithPointer{Data: &data})
  1142  	if err != nil {
  1143  		t.Error("unexpected error")
  1144  	}
  1145  
  1146  	bufCopy := buf
  1147  	decoder := NewDecoderWithOptions(&bufCopy, DecodeOptions{MaxDepth: 3})
  1148  	var s structWithPointer
  1149  	_, err = decoder.Decode(&s)
  1150  	if err != nil {
  1151  		t.Error("unexpected error")
  1152  	}
  1153  
  1154  	bufCopy = buf
  1155  	decoder = NewDecoderWithOptions(&bufCopy, DecodeOptions{MaxDepth: 2})
  1156  	_, err = decoder.Decode(&s)
  1157  	assertError(t, "", err, &UnmarshalError{ErrorCode: ErrMaxDecodingDepth})
  1158  }
  1159  
  1160  func TestDecodeMaxAllocationCheck_ImplicitLenReader(t *testing.T) {
  1161  	var buf bytes.Buffer
  1162  	_, err := Marshal(&buf, "thisstringis23charslong")
  1163  	if err != nil {
  1164  		t.Error("unexpected error")
  1165  	}
  1166  
  1167  	// Reduce the buffer size so that the length of the buffer
  1168  	// is shorter than the encoded XDR  length
  1169  	buf.Truncate(buf.Len() - 4)
  1170  
  1171  	decoder := NewDecoder(&buf)
  1172  	var s string
  1173  	_, err = decoder.Decode(&s)
  1174  	assertError(t, "", err, &UnmarshalError{ErrorCode: ErrOverflow})
  1175  }
  1176  
  1177  func TestDecodeMaxAllocationCheck_ExplicitLenReader(t *testing.T) {
  1178  	var buf bytes.Buffer
  1179  	encoder := base64.NewEncoder(base64.StdEncoding, &buf)
  1180  	_, err := Marshal(encoder, "thisstringis23charslong")
  1181  	if err != nil {
  1182  		t.Error("unexpected error")
  1183  	}
  1184  
  1185  	xdrLen := base64.StdEncoding.DecodedLen(buf.Len())
  1186  	// Reduce the buffer size so that the length of the buffer
  1187  	// is shorter than the encoded XDR length
  1188  	reducedLen := xdrLen - 4
  1189  
  1190  	decoder := NewDecoderWithOptions(&buf, DecodeOptions{MaxInputLen: reducedLen})
  1191  	var s string
  1192  	_, err = decoder.Decode(&s)
  1193  	assertError(t, "", err, &UnmarshalError{ErrorCode: ErrOverflow})
  1194  }