github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/xdr/encode_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  // TestMarshal executes all of the tests described by marshalTests.
    28  func TestMarshal(t *testing.T) {
    29  	// Variables for various unsupported Marshal types.
    30  	var nilInterface interface{}
    31  	var testChan chan int
    32  	var testFunc func()
    33  	var testComplex64 complex64
    34  	var testComplex128 complex128
    35  
    36  	// testInterface is used to test Marshal with values nested in an
    37  	// interface.
    38  	testInterface := interface{}(17)
    39  
    40  	// structMarshalTestIn is input data for the big struct test of all
    41  	// supported types.
    42  	structMarshalTestIn := allTypesTest{
    43  		127,                                // A
    44  		255,                                // B
    45  		32767,                              // C
    46  		65535,                              // D
    47  		2147483647,                         // E
    48  		4294967295,                         // F
    49  		9223372036854775807,                // G
    50  		18446744073709551615,               // H
    51  		true,                               // I
    52  		3.14,                               // J
    53  		3.141592653589793,                  // K
    54  		"xdr",                              // L
    55  		[]byte{1, 2, 3, 4},                 // M
    56  		[3]byte{1, 2, 3},                   // N
    57  		[]int16{512, 1024, 2048},           // O
    58  		[2]subTest{{"one", 1}, {"two", 2}}, // P
    59  		subTest{"bar", 3},                  // Q
    60  		map[string]uint32{"map1": 1},       // R
    61  		time.Unix(1396581888, 0).UTC(),     // S
    62  	}
    63  
    64  	// structMarshalTestWant is the expected output after marshalling
    65  	// structMarshalTestIn.
    66  	structMarshalTestWant := []byte{
    67  		0x00, 0x00, 0x00, 0x7F, // A
    68  		0x00, 0x00, 0x00, 0xFF, // B
    69  		0x00, 0x00, 0x7F, 0xFF, // C
    70  		0x00, 0x00, 0xFF, 0xFF, // D
    71  		0x7F, 0xFF, 0xFF, 0xFF, // E
    72  		0xFF, 0xFF, 0xFF, 0xFF, // F
    73  		0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // G
    74  		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // H
    75  		0x00, 0x00, 0x00, 0x01, // I
    76  		0x40, 0x48, 0xF5, 0xC3, // J
    77  		0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18, // K
    78  		0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00, // L
    79  		0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, // M
    80  		0x01, 0x02, 0x03, 0x00, // N
    81  		0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00,
    82  		0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, // O
    83  		0x00, 0x00, 0x00, 0x03, 0x6F, 0x6E, 0x65, 0x00, // P[0].A
    84  		0x00, 0x00, 0x00, 0x01, // P[0].B
    85  		0x00, 0x00, 0x00, 0x03, 0x74, 0x77, 0x6F, 0x00, // P[1].A
    86  		0x00, 0x00, 0x00, 0x02, // P[1].B
    87  		0x00, 0x00, 0x00, 0x03, 0x62, 0x61, 0x72, 0x00, // Q.A
    88  		0x00, 0x00, 0x00, 0x03, // Q.B
    89  		0x00, 0x00, 0x00, 0x01, // R length
    90  		0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31, // R key map1
    91  		0x00, 0x00, 0x00, 0x01, // R value map1
    92  		0x00, 0x00, 0x00, 0x14, 0x32, 0x30, 0x31, 0x34,
    93  		0x2d, 0x30, 0x34, 0x2d, 0x30, 0x34, 0x54, 0x30,
    94  		0x33, 0x3a, 0x32, 0x34, 0x3a, 0x34, 0x38, 0x5a, // S
    95  	}
    96  
    97  	tests := []struct {
    98  		in   interface{}
    99  		want []byte
   100  		err  error
   101  	}{
   102  		// interface
   103  		{testInterface, []byte{0x00, 0x00, 0x00, 0x11}, nil},
   104  		{&testInterface, []byte{0x00, 0x00, 0x00, 0x11}, nil},
   105  
   106  		// int8 - XDR Integer
   107  		{int8(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   108  		{int8(64), []byte{0x00, 0x00, 0x00, 0x40}, nil},
   109  		{int8(127), []byte{0x00, 0x00, 0x00, 0x7F}, nil},
   110  		{int8(-1), []byte{0xFF, 0xFF, 0xFF, 0xFF}, nil},
   111  		{int8(-128), []byte{0xFF, 0xFF, 0xFF, 0x80}, nil},
   112  
   113  		// uint8 - XDR Unsigned Integer
   114  		{uint8(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   115  		{uint8(64), []byte{0x00, 0x00, 0x00, 0x40}, nil},
   116  		{uint8(255), []byte{0x00, 0x00, 0x00, 0xFF}, nil},
   117  
   118  		// int16 - XDR Integer
   119  		{int16(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   120  		{int16(1024), []byte{0x00, 0x00, 0x04, 0x00}, nil},
   121  		{int16(32767), []byte{0x00, 0x00, 0x7F, 0xFF}, nil},
   122  		{int16(-1), []byte{0xFF, 0xFF, 0xFF, 0xFF}, nil},
   123  		{int16(-32768), []byte{0xFF, 0xFF, 0x80, 0x00}, nil},
   124  
   125  		// uint16 - XDR Unsigned Integer
   126  		{uint16(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   127  		{uint16(1024), []byte{0x00, 0x00, 0x04, 0x00}, nil},
   128  		{uint16(65535), []byte{0x00, 0x00, 0xFF, 0xFF}, nil},
   129  
   130  		// int32 - XDR Integer
   131  		{int32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   132  		{int32(262144), []byte{0x00, 0x04, 0x00, 0x00}, nil},
   133  		{int32(2147483647), []byte{0x7F, 0xFF, 0xFF, 0xFF}, nil},
   134  		{int32(-1), []byte{0xFF, 0xFF, 0xFF, 0xFF}, nil},
   135  		{int32(-2147483648), []byte{0x80, 0x00, 0x00, 0x00}, nil},
   136  
   137  		// uint32 - XDR Unsigned Integer
   138  		{uint32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   139  		{uint32(262144), []byte{0x00, 0x04, 0x00, 0x00}, nil},
   140  		{uint32(4294967295), []byte{0xFF, 0xFF, 0xFF, 0xFF}, nil},
   141  
   142  		// int64 - XDR Hyper Integer
   143  		{int64(0), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   144  		{int64(1 << 34), []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, nil},
   145  		{int64(1 << 42), []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   146  		{int64(9223372036854775807), []byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil},
   147  		{int64(-1), []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil},
   148  		{int64(-9223372036854775808), []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   149  
   150  		// uint64 - XDR Unsigned Hyper Integer
   151  		{uint64(0), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   152  		{uint64(1 << 34), []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, nil},
   153  		{uint64(1 << 42), []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   154  		{uint64(18446744073709551615), []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil},
   155  		{uint64(9223372036854775808), []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   156  
   157  		// bool - XDR Integer
   158  		{false, []byte{0x00, 0x00, 0x00, 0x00}, nil},
   159  		{true, []byte{0x00, 0x00, 0x00, 0x01}, nil},
   160  
   161  		// float32 - XDR Floating-Point
   162  		{float32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   163  		{float32(3.14), []byte{0x40, 0x48, 0xF5, 0xC3}, nil},
   164  		{float32(1234567.0), []byte{0x49, 0x96, 0xB4, 0x38}, nil},
   165  		{float32(math.Inf(-1)), []byte{0xFF, 0x80, 0x00, 0x00}, nil},
   166  		{float32(math.Inf(0)), []byte{0x7F, 0x80, 0x00, 0x00}, nil},
   167  
   168  		// float64 - XDR Double-precision Floating-Point
   169  		{float64(0), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   170  		{float64(3.141592653589793), []byte{0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18}, nil},
   171  		{float64(math.Inf(-1)), []byte{0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   172  		{float64(math.Inf(0)), []byte{0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   173  
   174  		// string - XDR String
   175  		{"", []byte{0x00, 0x00, 0x00, 0x00}, nil},
   176  		{"xdr", []byte{0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00}, nil},
   177  		{"τ=2π", []byte{0x00, 0x00, 0x00, 0x06, 0xCF, 0x84, 0x3D, 0x32, 0xCF, 0x80, 0x00, 0x00}, nil},
   178  
   179  		// []byte - XDR Variable Opaque
   180  		{[]byte{0x01}, []byte{0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00}, nil},
   181  		{[]byte{0x01, 0x02, 0x03}, []byte{0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00}, nil},
   182  
   183  		// [#]byte - XDR Fixed Opaque
   184  		{[1]byte{0x01}, []byte{0x01, 0x00, 0x00, 0x00}, nil}, // No & here to test unaddressable arrays
   185  		{&[2]byte{0x01, 0x02}, []byte{0x01, 0x02, 0x00, 0x00}, nil},
   186  		{&[3]byte{0x01, 0x02, 0x03}, []byte{0x01, 0x02, 0x03, 0x00}, nil},
   187  		{&[4]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil},
   188  		{&[5]byte{0x01, 0x02, 0x03, 0x04, 0x05}, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00}, nil},
   189  
   190  		// []<type> - XDR Variable-Length Array
   191  		{&[]int16{512, 1024, 2048},
   192  			[]byte{0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00},
   193  			nil},
   194  		{[]bool{true, false}, []byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, nil},
   195  
   196  		// [#]<type> - XDR Fixed-Length Array
   197  		{&[2]uint32{512, 1024}, []byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00}, nil},
   198  
   199  		// map[string]uint32
   200  		{map[string]uint32{"map1": 1},
   201  			[]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x6D, 0x61, 0x70, 0x31, 0x00, 0x00, 0x00, 0x01},
   202  			nil},
   203  
   204  		// time.Time - XDR String per RFC3339
   205  		{time.Unix(1396581888, 0).UTC(),
   206  			[]byte{
   207  				0x00, 0x00, 0x00, 0x14, 0x32, 0x30, 0x31, 0x34,
   208  				0x2d, 0x30, 0x34, 0x2d, 0x30, 0x34, 0x54, 0x30,
   209  				0x33, 0x3a, 0x32, 0x34, 0x3a, 0x34, 0x38, 0x5a,
   210  			}, nil},
   211  
   212  		// struct - XDR Structure -- test struct contains all supported types
   213  		{&structMarshalTestIn, structMarshalTestWant, nil},
   214  
   215  		// Expected errors
   216  		{nilInterface, nil, &MarshalError{ErrorCode: ErrNilInterface}},
   217  		{&nilInterface, nil, &MarshalError{ErrorCode: ErrNilInterface}},
   218  		{testChan, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   219  		{&testChan, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   220  		{testFunc, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   221  		{&testFunc, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   222  		{testComplex64, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   223  		{&testComplex64, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   224  		{testComplex128, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   225  		{&testComplex128, nil, &MarshalError{ErrorCode: ErrUnsupportedType}},
   226  	}
   227  
   228  	for i, test := range tests {
   229  		rv, err := Marshal(test.in)
   230  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   231  			t.Errorf("Marshal #%d failed to detect error - got: %v <%T> want: %T",
   232  				i, err, err, test.err)
   233  			continue
   234  		}
   235  		if rerr, ok := err.(*MarshalError); ok {
   236  			if terr, ok := test.err.(*MarshalError); ok {
   237  				if rerr.ErrorCode != terr.ErrorCode {
   238  					t.Errorf("Marshal #%d failed to detect error code - got: %v want: %v",
   239  						i, rerr.ErrorCode, terr.ErrorCode)
   240  					continue
   241  				}
   242  				// Got expected error.  Move on to the next test.
   243  				continue
   244  			}
   245  		}
   246  
   247  		if len(rv) != len(test.want) {
   248  			t.Errorf("Marshal #%d len got: %v want: %v\n", i, len(rv), len(test.want))
   249  			continue
   250  		}
   251  		if !reflect.DeepEqual(rv, test.want) {
   252  			t.Errorf("Marshal #%d got: %v want: %v\n", i, rv, test.want)
   253  			continue
   254  		}
   255  	}
   256  }
   257  
   258  // encodeFunc is used to identify which public function of the Encoder object
   259  // a test applies to.
   260  type encodeFunc int
   261  
   262  const (
   263  	fEncodeBool encodeFunc = iota
   264  	fEncodeDouble
   265  	fEncodeEnum
   266  	fEncodeFixedOpaque
   267  	fEncodeFloat
   268  	fEncodeHyper
   269  	fEncodeInt
   270  	fEncodeOpaque
   271  	fEncodeString
   272  	fEncodeUhyper
   273  	fEncodeUint
   274  )
   275  
   276  // Map of encodeFunc values to names for pretty printing.
   277  var encodeFuncStrings = map[encodeFunc]string{
   278  	fEncodeBool:        "EncodeBool",
   279  	fEncodeDouble:      "EncodeDouble",
   280  	fEncodeEnum:        "EncodeEnum",
   281  	fEncodeFixedOpaque: "EncodeFixedOpaque",
   282  	fEncodeFloat:       "EncodeFloat",
   283  	fEncodeHyper:       "EncodeHyper",
   284  	fEncodeInt:         "EncodeInt",
   285  	fEncodeOpaque:      "EncodeOpaque",
   286  	fEncodeString:      "EncodeString",
   287  	fEncodeUhyper:      "EncodeUhyper",
   288  	fEncodeUint:        "EncodeUint",
   289  }
   290  
   291  func (f encodeFunc) String() string {
   292  	if s := encodeFuncStrings[f]; s != "" {
   293  		return s
   294  	}
   295  	return fmt.Sprintf("Unknown encodeFunc (%d)", f)
   296  }
   297  
   298  // TestEncoder executes all of the tests described by encodeTests.
   299  func TestEncoder(t *testing.T) {
   300  	tests := []struct {
   301  		f    encodeFunc
   302  		in   interface{}
   303  		want []byte
   304  		err  error
   305  	}{
   306  		// Bool
   307  		{fEncodeBool, false, []byte{0x00, 0x00, 0x00, 0x00}, nil},
   308  		{fEncodeBool, true, []byte{0x00, 0x00, 0x00, 0x01}, nil},
   309  
   310  		// Double
   311  		{fEncodeDouble, float64(0), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   312  		{fEncodeDouble, float64(3.141592653589793), []byte{0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18}, nil},
   313  		{fEncodeDouble, float64(math.Inf(-1)), []byte{0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   314  		{fEncodeDouble, float64(math.Inf(0)), []byte{0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   315  
   316  		// Enum
   317  		{fEncodeEnum, int32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   318  		{fEncodeEnum, int32(1), []byte{0x00, 0x00, 0x00, 0x01}, nil},
   319  		{fEncodeEnum, int32(2), nil, &MarshalError{ErrorCode: ErrBadEnumValue}},
   320  		{fEncodeEnum, int32(1234), nil, &MarshalError{ErrorCode: ErrBadEnumValue}},
   321  
   322  		// FixedOpaque
   323  		{fEncodeFixedOpaque, []byte{0x01}, []byte{0x01, 0x00, 0x00, 0x00}, nil},
   324  		{fEncodeFixedOpaque, []byte{0x01, 0x02}, []byte{0x01, 0x02, 0x00, 0x00}, nil},
   325  		{fEncodeFixedOpaque, []byte{0x01, 0x02, 0x03}, []byte{0x01, 0x02, 0x03, 0x00}, nil},
   326  		{fEncodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil},
   327  		{fEncodeFixedOpaque, []byte{0x01, 0x02, 0x03, 0x04, 0x05}, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00}, nil},
   328  
   329  		// Float
   330  		{fEncodeFloat, float32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   331  		{fEncodeFloat, float32(3.14), []byte{0x40, 0x48, 0xF5, 0xC3}, nil},
   332  		{fEncodeFloat, float32(1234567.0), []byte{0x49, 0x96, 0xB4, 0x38}, nil},
   333  		{fEncodeFloat, float32(math.Inf(-1)), []byte{0xFF, 0x80, 0x00, 0x00}, nil},
   334  		{fEncodeFloat, float32(math.Inf(0)), []byte{0x7F, 0x80, 0x00, 0x00}, nil},
   335  
   336  		// Hyper
   337  		{fEncodeHyper, int64(0), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   338  		{fEncodeHyper, int64(1 << 34), []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, nil},
   339  		{fEncodeHyper, int64(1 << 42), []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   340  		{fEncodeHyper, int64(9223372036854775807), []byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil},
   341  		{fEncodeHyper, int64(-1), []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil},
   342  		{fEncodeHyper, int64(-9223372036854775808), []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   343  
   344  		// Int
   345  		{fEncodeInt, int32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   346  		{fEncodeInt, int32(262144), []byte{0x00, 0x04, 0x00, 0x00}, nil},
   347  		{fEncodeInt, int32(2147483647), []byte{0x7F, 0xFF, 0xFF, 0xFF}, nil},
   348  		{fEncodeInt, int32(-1), []byte{0xFF, 0xFF, 0xFF, 0xFF}, nil},
   349  		{fEncodeInt, int32(-2147483648), []byte{0x80, 0x00, 0x00, 0x00}, nil},
   350  
   351  		// Opaque
   352  		{fEncodeOpaque, []byte{0x01}, []byte{0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00}, nil},
   353  		{fEncodeOpaque, []byte{0x01, 0x02, 0x03}, []byte{0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00}, nil},
   354  
   355  		// String
   356  		{fEncodeString, "", []byte{0x00, 0x00, 0x00, 0x00}, nil},
   357  		{fEncodeString, "xdr", []byte{0x00, 0x00, 0x00, 0x03, 0x78, 0x64, 0x72, 0x00}, nil},
   358  		{fEncodeString, "τ=2π", []byte{0x00, 0x00, 0x00, 0x06, 0xCF, 0x84, 0x3D, 0x32, 0xCF, 0x80, 0x00, 0x00}, nil},
   359  
   360  		// Uhyper
   361  		{fEncodeUhyper, uint64(0), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   362  		{fEncodeUhyper, uint64(1 << 34), []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, nil},
   363  		{fEncodeUhyper, uint64(1 << 42), []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   364  		{fEncodeUhyper, uint64(18446744073709551615), []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil},
   365  		{fEncodeUhyper, uint64(9223372036854775808), []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, nil},
   366  
   367  		// Uint
   368  		{fEncodeUint, uint32(0), []byte{0x00, 0x00, 0x00, 0x00}, nil},
   369  		{fEncodeUint, uint32(262144), []byte{0x00, 0x04, 0x00, 0x00}, nil},
   370  		{fEncodeUint, uint32(4294967295), []byte{0xFF, 0xFF, 0xFF, 0xFF}, nil},
   371  	}
   372  
   373  	validEnums := make(map[int32]bool)
   374  	validEnums[0] = true
   375  	validEnums[1] = true
   376  
   377  	var err error
   378  	enc := NewEncoder()
   379  
   380  	for i, test := range tests {
   381  		err = nil
   382  		enc.Reset()
   383  		switch test.f {
   384  		case fEncodeBool:
   385  			in := test.in.(bool)
   386  			err = enc.EncodeBool(in)
   387  		case fEncodeDouble:
   388  			in := test.in.(float64)
   389  			err = enc.EncodeDouble(in)
   390  		case fEncodeEnum:
   391  			in := test.in.(int32)
   392  			err = enc.EncodeEnum(in, validEnums)
   393  		case fEncodeFixedOpaque:
   394  			in := test.in.([]byte)
   395  			err = enc.EncodeFixedOpaque(in)
   396  		case fEncodeFloat:
   397  			in := test.in.(float32)
   398  			err = enc.EncodeFloat(in)
   399  		case fEncodeHyper:
   400  			in := test.in.(int64)
   401  			err = enc.EncodeHyper(in)
   402  		case fEncodeInt:
   403  			in := test.in.(int32)
   404  			err = enc.EncodeInt(in)
   405  		case fEncodeOpaque:
   406  			in := test.in.([]byte)
   407  			err = enc.EncodeOpaque(in)
   408  		case fEncodeString:
   409  			in := test.in.(string)
   410  			err = enc.EncodeString(in)
   411  		case fEncodeUhyper:
   412  			in := test.in.(uint64)
   413  			err = enc.EncodeUhyper(in)
   414  		case fEncodeUint:
   415  			in := test.in.(uint32)
   416  			err = enc.EncodeUint(in)
   417  		default:
   418  			t.Errorf("%v #%d unrecognized function", test.f, i)
   419  			continue
   420  		}
   421  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   422  			t.Errorf("%v #%d failed to detect error - got: %v <%T> want: %T",
   423  				test.f, i, err, err, test.err)
   424  			continue
   425  		}
   426  		if rerr, ok := err.(*MarshalError); ok {
   427  			if terr, ok := test.err.(*MarshalError); ok {
   428  				if rerr.ErrorCode != terr.ErrorCode {
   429  					t.Errorf("%v #%d failed to detect error code - got: %v want: %v",
   430  						test.f, i, rerr.ErrorCode, terr.ErrorCode)
   431  					continue
   432  				}
   433  				// Got expected error.  Move on to the next test.
   434  				continue
   435  			}
   436  		}
   437  
   438  		rv := enc.Data()
   439  		if len(rv) != len(test.want) {
   440  			t.Errorf("%v #%d len got: %v want: %v\n", test.f, i, len(rv), len(test.want))
   441  			continue
   442  		}
   443  		if !reflect.DeepEqual(rv, test.want) {
   444  			t.Errorf("%v #%d got: %v want: %v\n", test.f, i, rv, test.want)
   445  			continue
   446  		}
   447  	}
   448  }