github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/xdr/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
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"reflect"
    23  	"testing"
    24  	"time"
    25  )
    26  
    27  // subTest is used to allow testing of the Unmarshal function into struct fields
    28  // which are structs themselves.
    29  type subTest struct {
    30  	A string
    31  	B uint8
    32  }
    33  
    34  // allTypesTest is used to allow testing of the Unmarshal function into struct
    35  // fields of all supported types.
    36  type allTypesTest struct {
    37  	A int8
    38  	B uint8
    39  	C int16
    40  	D uint16
    41  	E int32
    42  	F uint32
    43  	G int64
    44  	H uint64
    45  	I bool
    46  	J float32
    47  	K float64
    48  	L string
    49  	M []byte
    50  	N [3]byte
    51  	O []int16
    52  	P [2]subTest
    53  	Q subTest
    54  	R map[string]uint32
    55  	S time.Time
    56  }
    57  
    58  // TestUnmarshal executes all of the tests described by unmarshalTests.
    59  func TestUnmarshal(t *testing.T) {
    60  	// structTestIn is input data for the big struct test of all supported
    61  	// types.
    62  	structTestIn := []byte{
    63  		0x00, 0x00, 0x00, 0x7F, // A
    64  		0x00, 0x00, 0x00, 0xFF, // B
    65  		0x00, 0x00, 0x7F, 0xFF, // C
    66  		0x00, 0x00, 0xFF, 0xFF, // D
    67  		0x7F, 0xFF, 0xFF, 0xFF, // E
    68  		0xFF, 0xFF, 0xFF, 0xFF, // F
    69  		0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // G
    70  		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // H
    71  		0x00, 0x00, 0x00, 0x01, // I
    72  		0x40, 0x48, 0xF5, 0xC3, // J
    73  		0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18, // K
    74  		0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00, // L
    75  		0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, // M
    76  		0x01, 0x02, 0x03, 0x00, // N
    77  		0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00,
    78  		0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, // O
    79  		0x00, 0x00, 0x00, 0x03, 0x6F, 0x6E, 0x65, 0x00, // P[0].A
    80  		0x00, 0x00, 0x00, 0x01, // P[0].B
    81  		0x00, 0x00, 0x00, 0x03, 0x74, 0x77, 0x6F, 0x00, // P[1].A
    82  		0x00, 0x00, 0x00, 0x02, // P[1].B
    83  		0x00, 0x00, 0x00, 0x03, 0x62, 0x61, 0x72, 0x00, // Q.A
    84  		0x00, 0x00, 0x00, 0x03, // Q.B
    85  		0x00, 0x00, 0x00, 0x02, // R length
    86  		0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31, // R key map1
    87  		0x00, 0x00, 0x00, 0x01, // R value map1
    88  		0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x32, // R key map2
    89  		0x00, 0x00, 0x00, 0x02, // R value map2
    90  		0x00, 0x00, 0x00, 0x14, 0x32, 0x30, 0x31, 0x34,
    91  		0x2d, 0x30, 0x34, 0x2d, 0x30, 0x34, 0x54, 0x30,
    92  		0x33, 0x3a, 0x32, 0x34, 0x3a, 0x34, 0x38, 0x5a, // S
    93  	}
    94  
    95  	// structTestWant is the expected output after unmarshalling
    96  	// structTestIn.
    97  	structTestWant := allTypesTest{
    98  		127,                                     // A
    99  		255,                                     // B
   100  		32767,                                   // C
   101  		65535,                                   // D
   102  		2147483647,                              // E
   103  		4294967295,                              // F
   104  		9223372036854775807,                     // G
   105  		18446744073709551615,                    // H
   106  		true,                                    // I
   107  		3.14,                                    // J
   108  		3.141592653589793,                       // K
   109  		"xdr",                                   // L
   110  		[]byte{1, 2, 3, 4},                      // M
   111  		[3]byte{1, 2, 3},                        // N
   112  		[]int16{512, 1024, 2048},                // O
   113  		[2]subTest{{"one", 1}, {"two", 2}},      // P
   114  		subTest{"bar", 3},                       // Q
   115  		map[string]uint32{"map1": 1, "map2": 2}, // R
   116  		time.Unix(1396581888, 0).UTC(),          // S
   117  	}
   118  
   119  	tests := []struct {
   120  		in   []byte
   121  		want interface{}
   122  		err  error
   123  	}{
   124  		// int8 - XDR Integer
   125  		{[]byte{0x00, 0x00, 0x00, 0x00}, int8(0), nil},
   126  		{[]byte{0x00, 0x00, 0x00, 0x40}, int8(64), nil},
   127  		{[]byte{0x00, 0x00, 0x00, 0x7F}, int8(127), nil},
   128  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, int8(-1), nil},
   129  		{[]byte{0xFF, 0xFF, 0xFF, 0x80}, int8(-128), nil},
   130  		// Expected Failures -- 128, -129 overflow int8
   131  		{[]byte{0x00, 0x00, 0x00, 0x80}, int8(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   132  		{[]byte{0xFF, 0xFF, 0xFF, 0x7F}, int8(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   133  
   134  		// uint8 - XDR Unsigned Integer
   135  		{[]byte{0x00, 0x00, 0x00, 0x00}, uint8(0), nil},
   136  		{[]byte{0x00, 0x00, 0x00, 0x40}, uint8(64), nil},
   137  		{[]byte{0x00, 0x00, 0x00, 0xFF}, uint8(255), nil},
   138  		// Expected Failures -- 256, -1 overflow uint8
   139  		{[]byte{0x00, 0x00, 0x01, 0x00}, uint8(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   140  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, uint8(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   141  
   142  		// int16 - XDR Integer
   143  		{[]byte{0x00, 0x00, 0x00, 0x00}, int16(0), nil},
   144  		{[]byte{0x00, 0x00, 0x04, 0x00}, int16(1024), nil},
   145  		{[]byte{0x00, 0x00, 0x7F, 0xFF}, int16(32767), nil},
   146  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, int16(-1), nil},
   147  		{[]byte{0xFF, 0xFF, 0x80, 0x00}, int16(-32768), nil},
   148  		// Expected Failures -- 32768, -32769 overflow int16
   149  		{[]byte{0x00, 0x00, 0x80, 0x00}, int16(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   150  		{[]byte{0xFF, 0xFF, 0x7F, 0xFF}, int16(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   151  
   152  		// uint16 - XDR Unsigned Integer
   153  		{[]byte{0x00, 0x00, 0x00, 0x00}, uint16(0), nil},
   154  		{[]byte{0x00, 0x00, 0x04, 0x00}, uint16(1024), nil},
   155  		{[]byte{0x00, 0x00, 0xFF, 0xFF}, uint16(65535), nil},
   156  		// Expected Failures -- 65536, -1 overflow uint16
   157  		{[]byte{0x00, 0x01, 0x00, 0x00}, uint16(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   158  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, uint16(0), &UnmarshalError{ErrorCode: ErrOverflow}},
   159  
   160  		// int32 - XDR Integer
   161  		{[]byte{0x00, 0x00, 0x00, 0x00}, int32(0), nil},
   162  		{[]byte{0x00, 0x04, 0x00, 0x00}, int32(262144), nil},
   163  		{[]byte{0x7F, 0xFF, 0xFF, 0xFF}, int32(2147483647), nil},
   164  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, int32(-1), nil},
   165  		{[]byte{0x80, 0x00, 0x00, 0x00}, int32(-2147483648), nil},
   166  
   167  		// uint32 - XDR Unsigned Integer
   168  		{[]byte{0x00, 0x00, 0x00, 0x00}, uint32(0), nil},
   169  		{[]byte{0x00, 0x04, 0x00, 0x00}, uint32(262144), nil},
   170  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF}, uint32(4294967295), nil},
   171  
   172  		// int64 - XDR Hyper Integer
   173  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(0), nil},
   174  		{[]byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, int64(1 << 34), nil},
   175  		{[]byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(1 << 42), nil},
   176  		{[]byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(9223372036854775807), nil},
   177  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(-1), nil},
   178  		{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(-9223372036854775808), nil},
   179  
   180  		// uint64 - XDR Unsigned Hyper Integer
   181  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(0), nil},
   182  		{[]byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 34), nil},
   183  		{[]byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 42), nil},
   184  		{[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, uint64(18446744073709551615), nil},
   185  		{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(9223372036854775808), nil},
   186  
   187  		// bool - XDR Integer
   188  		{[]byte{0x00, 0x00, 0x00, 0x00}, false, nil},
   189  		{[]byte{0x00, 0x00, 0x00, 0x01}, true, nil},
   190  		// Expected Failures -- only 0 or 1 is a valid bool
   191  		{[]byte{0x01, 0x00, 0x00, 0x00}, true, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   192  		{[]byte{0x00, 0x00, 0x40, 0x00}, true, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   193  
   194  		// float32 - XDR Floating-Point
   195  		{[]byte{0x00, 0x00, 0x00, 0x00}, float32(0), nil},
   196  		{[]byte{0x40, 0x48, 0xF5, 0xC3}, float32(3.14), nil},
   197  		{[]byte{0x49, 0x96, 0xB4, 0x38}, float32(1234567.0), nil},
   198  		{[]byte{0xFF, 0x80, 0x00, 0x00}, float32(math.Inf(-1)), nil},
   199  		{[]byte{0x7F, 0x80, 0x00, 0x00}, float32(math.Inf(0)), nil},
   200  
   201  		// float64 - XDR Double-precision Floating-Point
   202  		{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(0), nil},
   203  		{[]byte{0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18}, float64(3.141592653589793), nil},
   204  		{[]byte{0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(-1)), nil},
   205  		{[]byte{0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(0)), nil},
   206  
   207  		// string - XDR String
   208  		{[]byte{0x00, 0x00, 0x00, 0x00}, "", nil},
   209  		{[]byte{0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00}, "xdr", nil},
   210  		{[]byte{0x00, 0x00, 0x00, 0x06, 0xCF, 0x84, 0x3D, 0x32, 0xCF, 0x80, 0x00, 0x00}, "τ=2π", nil},
   211  		// Expected Failure -- String len 255 larger than available bytes
   212  		{[]byte{0x00, 0x00, 0x00, 0xFF}, "", &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   213  
   214  		// []byte - XDR Variable Opaque
   215  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00}, []byte{0x01}, nil},
   216  		{[]byte{0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00}, []byte{0x01, 0x02, 0x03}, nil},
   217  		// Expected Failure -- 255 bytes of opaque data larger than available bytes
   218  		{[]byte{0x00, 0x00, 0x00, 0xFF}, []byte{}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   219  
   220  		// [#]byte - XDR Fixed Opaque
   221  		{[]byte{0x01, 0x00, 0x00, 0x00}, [1]byte{0x01}, nil},
   222  		{[]byte{0x01, 0x02, 0x00, 0x00}, [2]byte{0x01, 0x02}, nil},
   223  		{[]byte{0x01, 0x02, 0x03, 0x00}, [3]byte{0x01, 0x02, 0x03}, nil},
   224  		{[]byte{0x01, 0x02, 0x03, 0x04}, [4]byte{0x01, 0x02, 0x03, 0x04}, nil},
   225  		{[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00}, [5]byte{0x01, 0x02, 0x03, 0x04, 0x05}, nil},
   226  		// Expected Failure -- fixed opaque data not padded
   227  		{[]byte{0x01}, [1]byte{}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   228  
   229  		// []<type> - XDR Variable-Length Array
   230  		{[]byte{0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00},
   231  			[]int16{512, 1024, 2048}, nil},
   232  		{[]byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, []bool{true, false}, nil},
   233  		// Expected Failure -- 2 entries in array - not enough bytes
   234  		{[]byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, []bool{}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   235  
   236  		// [#]<type> - XDR Fixed-Length Array
   237  		{[]byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00}, [2]uint32{512, 1024}, nil},
   238  		{[]byte{0x00, 0x00, 0x02, 0x00}, [2]uint32{}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   239  
   240  		// map[string]uint32
   241  		{[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31, 0x00, 0x00, 0x00, 0x01},
   242  			map[string]uint32{"map1": 1}, nil},
   243  		// Expected Failure -- 1 map element - not enough bytes
   244  		{[]byte{0x00, 0x00, 0x00, 0x01}, map[string]uint32{}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   245  
   246  		// time.Time - XDR String per RFC3339
   247  		{[]byte{
   248  			0x00, 0x00, 0x00, 0x14, 0x32, 0x30, 0x31, 0x34,
   249  			0x2d, 0x30, 0x34, 0x2d, 0x30, 0x34, 0x54, 0x30,
   250  			0x33, 0x3a, 0x32, 0x34, 0x3a, 0x34, 0x38, 0x5a,
   251  		}, time.Unix(1396581888, 0).UTC(), nil},
   252  
   253  		// struct - XDR Structure -- test struct contains all supported types
   254  		{structTestIn, structTestWant, nil},
   255  	}
   256  
   257  	for i, test := range tests {
   258  		// Create a new pointer to the appropriate type
   259  		want := reflect.New(reflect.TypeOf(test.want)).Interface()
   260  		rest, err := Unmarshal(test.in, want)
   261  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   262  			t.Errorf("Unmarshal #%d failed to detect error - got: %v <%T> want: %T",
   263  				i, err, err, test.err)
   264  			continue
   265  		}
   266  		if rerr, ok := err.(*UnmarshalError); ok {
   267  			if terr, ok := test.err.(*UnmarshalError); ok {
   268  				if rerr.ErrorCode != terr.ErrorCode {
   269  					t.Errorf("Unmarshal #%d failed to detect error code - got: %v want: %v",
   270  						i, rerr.ErrorCode, terr.ErrorCode)
   271  					continue
   272  				}
   273  				// Got expected error.  Move on to the next test.
   274  				continue
   275  			}
   276  		}
   277  
   278  		if len(rest) != 0 {
   279  			t.Errorf("Unmarshal #%d len got: %v want: %v\n", i, len(rest), 0)
   280  			continue
   281  		}
   282  		wantElem := reflect.Indirect(reflect.ValueOf(want)).Interface()
   283  		if !reflect.DeepEqual(wantElem, test.want) {
   284  			t.Errorf("Unmarshal #%d got: %v want: %v\n", i, wantElem, test.want)
   285  			continue
   286  		}
   287  	}
   288  }
   289  
   290  // decodeFunc is used to identify which public function of the Decoder object
   291  // a test applies to.
   292  type decodeFunc int
   293  
   294  const (
   295  	fDecodeBool decodeFunc = iota
   296  	fDecodeDouble
   297  	fDecodeEnum
   298  	fDecodeFixedOpaque
   299  	fDecodeFloat
   300  	fDecodeHyper
   301  	fDecodeInt
   302  	fDecodeOpaque
   303  	fDecodeString
   304  	fDecodeUhyper
   305  	fDecodeUint
   306  )
   307  
   308  // Map of decodeFunc values to names for pretty printing.
   309  var decodeFuncStrings = map[decodeFunc]string{
   310  	fDecodeBool:        "DecodeBool",
   311  	fDecodeDouble:      "DecodeDouble",
   312  	fDecodeEnum:        "DecodeEnum",
   313  	fDecodeFixedOpaque: "DecodeFixedOpaque",
   314  	fDecodeFloat:       "DecodeFloat",
   315  	fDecodeHyper:       "DecodeHyper",
   316  	fDecodeInt:         "DecodeInt",
   317  	fDecodeOpaque:      "DecodeOpaque",
   318  	fDecodeString:      "DecodeString",
   319  	fDecodeUhyper:      "DecodeUhyper",
   320  	fDecodeUint:        "DecodeUint",
   321  }
   322  
   323  func (f decodeFunc) String() string {
   324  	if s := decodeFuncStrings[f]; s != "" {
   325  		return s
   326  	}
   327  	return fmt.Sprintf("Unknown decodeFunc (%d)", f)
   328  }
   329  
   330  // TestDecoder executes all of the tests described by decodeTests.
   331  func TestDecoder(t *testing.T) {
   332  	tests := []struct {
   333  		f    decodeFunc
   334  		in   []byte
   335  		want interface{}
   336  		err  error
   337  	}{
   338  		// Bool
   339  		{fDecodeBool, []byte{0x00, 0x00, 0x00, 0x00}, false, nil},
   340  		{fDecodeBool, []byte{0x00, 0x00, 0x00, 0x01}, true, nil},
   341  		// Expected Failures -- only 0 or 1 is a valid bool
   342  		{fDecodeBool, []byte{0x01, 0x00, 0x00, 0x00}, true, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   343  		{fDecodeBool, []byte{0x00, 0x00, 0x40, 0x00}, true, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   344  
   345  		// Double
   346  		{fDecodeDouble, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(0), nil},
   347  		{fDecodeDouble, []byte{0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18}, float64(3.141592653589793), nil},
   348  		{fDecodeDouble, []byte{0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(-1)), nil},
   349  		{fDecodeDouble, []byte{0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, float64(math.Inf(0)), nil},
   350  
   351  		// Enum
   352  		{fDecodeEnum, []byte{0x00, 0x00, 0x00, 0x00}, int32(0), nil},
   353  		{fDecodeEnum, []byte{0x00, 0x00, 0x00, 0x01}, int32(1), nil},
   354  		{fDecodeEnum, []byte{0x00, 0x00, 0x00, 0x02}, nil, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   355  		{fDecodeEnum, []byte{0x12, 0x34, 0x56, 0x78}, nil, &UnmarshalError{ErrorCode: ErrBadEnumValue}},
   356  
   357  		// FixedOpaque
   358  		{fDecodeFixedOpaque, []byte{0x01, 0x00, 0x00, 0x00}, []byte{0x01}, nil},
   359  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x00, 0x00}, []byte{0x01, 0x02}, nil},
   360  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x00}, []byte{0x01, 0x02, 0x03}, nil},
   361  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil},
   362  		{fDecodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00}, []byte{0x01, 0x02, 0x03, 0x04, 0x05}, nil},
   363  		// Expected Failure -- fixed opaque data not padded
   364  		{fDecodeFixedOpaque, []byte{0x01}, []byte{0x00}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   365  
   366  		// Float
   367  		{fDecodeFloat, []byte{0x00, 0x00, 0x00, 0x00}, float32(0), nil},
   368  		{fDecodeFloat, []byte{0x40, 0x48, 0xF5, 0xC3}, float32(3.14), nil},
   369  		{fDecodeFloat, []byte{0x49, 0x96, 0xB4, 0x38}, float32(1234567.0), nil},
   370  		{fDecodeFloat, []byte{0xFF, 0x80, 0x00, 0x00}, float32(math.Inf(-1)), nil},
   371  		{fDecodeFloat, []byte{0x7F, 0x80, 0x00, 0x00}, float32(math.Inf(0)), nil},
   372  
   373  		// Hyper
   374  		{fDecodeHyper, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(0), nil},
   375  		{fDecodeHyper, []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, int64(1 << 34), nil},
   376  		{fDecodeHyper, []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(1 << 42), nil},
   377  		{fDecodeHyper, []byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(9223372036854775807), nil},
   378  		{fDecodeHyper, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, int64(-1), nil},
   379  		{fDecodeHyper, []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, int64(-9223372036854775808), nil},
   380  
   381  		// Int
   382  		{fDecodeInt, []byte{0x00, 0x00, 0x00, 0x00}, int32(0), nil},
   383  		{fDecodeInt, []byte{0x00, 0x04, 0x00, 0x00}, int32(262144), nil},
   384  		{fDecodeInt, []byte{0x7F, 0xFF, 0xFF, 0xFF}, int32(2147483647), nil},
   385  		{fDecodeInt, []byte{0xFF, 0xFF, 0xFF, 0xFF}, int32(-1), nil},
   386  		{fDecodeInt, []byte{0x80, 0x00, 0x00, 0x00}, int32(-2147483648), nil},
   387  
   388  		// Opaque
   389  		{fDecodeOpaque, []byte{0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00}, []byte{0x01}, nil},
   390  		{fDecodeOpaque, []byte{0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00}, []byte{0x01, 0x02, 0x03}, nil},
   391  		// Expected Failure -- 255 bytes of opaque data larger than available bytes
   392  		{fDecodeOpaque, []byte{0x00, 0x00, 0x00, 0xFF}, []byte{}, &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   393  
   394  		// String
   395  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0x00}, "", nil},
   396  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00}, "xdr", nil},
   397  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0x06, 0xCF, 0x84, 0x3D, 0x32, 0xCF, 0x80, 0x00, 0x00}, "τ=2π", nil},
   398  		// Expected Failure -- String len 255 larger than available bytes
   399  		{fDecodeString, []byte{0x00, 0x00, 0x00, 0xFF}, "", &UnmarshalError{ErrorCode: ErrUnexpectedEnd}},
   400  
   401  		// Uhyper
   402  		{fDecodeUhyper, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(0), nil},
   403  		{fDecodeUhyper, []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 34), nil},
   404  		{fDecodeUhyper, []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(1 << 42), nil},
   405  		{fDecodeUhyper, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, uint64(18446744073709551615), nil},
   406  		{fDecodeUhyper, []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, uint64(9223372036854775808), nil},
   407  
   408  		// Uint
   409  		{fDecodeUint, []byte{0x00, 0x00, 0x00, 0x00}, uint32(0), nil},
   410  		{fDecodeUint, []byte{0x00, 0x04, 0x00, 0x00}, uint32(262144), nil},
   411  		{fDecodeUint, []byte{0xFF, 0xFF, 0xFF, 0xFF}, uint32(4294967295), nil},
   412  	}
   413  
   414  	validEnums := make(map[int32]bool)
   415  	validEnums[0] = true
   416  	validEnums[1] = true
   417  
   418  	var rv interface{}
   419  	var err error
   420  
   421  	for i, test := range tests {
   422  		err = nil
   423  		dec := NewDecoder(test.in)
   424  		switch test.f {
   425  		case fDecodeBool:
   426  			rv, err = dec.DecodeBool()
   427  		case fDecodeDouble:
   428  			rv, err = dec.DecodeDouble()
   429  		case fDecodeEnum:
   430  			rv, err = dec.DecodeEnum(validEnums)
   431  		case fDecodeFixedOpaque:
   432  			want := test.want.([]byte)
   433  			rv, err = dec.DecodeFixedOpaque(int32(len(want)))
   434  		case fDecodeFloat:
   435  			rv, err = dec.DecodeFloat()
   436  		case fDecodeHyper:
   437  			rv, err = dec.DecodeHyper()
   438  		case fDecodeInt:
   439  			rv, err = dec.DecodeInt()
   440  		case fDecodeOpaque:
   441  			rv, err = dec.DecodeOpaque()
   442  		case fDecodeString:
   443  			rv, err = dec.DecodeString()
   444  		case fDecodeUhyper:
   445  			rv, err = dec.DecodeUhyper()
   446  		case fDecodeUint:
   447  			rv, err = dec.DecodeUint()
   448  		default:
   449  			t.Errorf("%v #%d unrecognized function", test.f, i)
   450  			continue
   451  		}
   452  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   453  			t.Errorf("%v #%d failed to detect error - got: %v <%T> want: %T",
   454  				test.f, i, err, err, test.err)
   455  			continue
   456  		}
   457  		if rerr, ok := err.(*UnmarshalError); ok {
   458  			if terr, ok := test.err.(*UnmarshalError); ok {
   459  				if rerr.ErrorCode != terr.ErrorCode {
   460  					t.Errorf("%v #%d failed to detect error code - got: %v want: %v",
   461  						test.f, i, rerr.ErrorCode, terr.ErrorCode)
   462  					continue
   463  				}
   464  				// Got expected error.  Move on to the next test.
   465  				continue
   466  			}
   467  		}
   468  
   469  		if !reflect.DeepEqual(rv, test.want) {
   470  			t.Errorf("%v #%d got: %v want: %v\n", test.f, i, rv, test.want)
   471  			continue
   472  		}
   473  	}
   474  }