github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/encoding/marshal_test.go (about)

     1  package encoding
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"reflect"
     9  	"strings"
    10  	"testing"
    11  
    12  	"SiaPrime/build"
    13  )
    14  
    15  // dummy types to test encoding
    16  type (
    17  	// basic
    18  	test0 struct {
    19  		B bool
    20  		I int32
    21  		U uint16
    22  		S string
    23  	}
    24  	// slice/array
    25  	test1 struct {
    26  		Is []int32
    27  		Bs []byte
    28  		Sa [3]string
    29  		Ba [3]byte
    30  	}
    31  	// nested
    32  	test2 struct {
    33  		T test0
    34  	}
    35  	// embedded
    36  	test3 struct {
    37  		test2
    38  	}
    39  	// pointer
    40  	test4 struct {
    41  		P *test1
    42  	}
    43  	// private field -- need to implement MarshalSia/UnmarshalSia
    44  	test5 struct {
    45  		s string
    46  	}
    47  	// private field with pointer receiver
    48  	test6 struct {
    49  		s string
    50  	}
    51  )
    52  
    53  func (t test5) MarshalSia(w io.Writer) error {
    54  	return NewEncoder(w).WritePrefixedBytes([]byte(t.s))
    55  }
    56  
    57  func (t *test5) UnmarshalSia(r io.Reader) error {
    58  	d := NewDecoder(r)
    59  	t.s = string(d.ReadPrefixedBytes())
    60  	return d.Err()
    61  }
    62  
    63  // same as above methods, but with a pointer receiver
    64  func (t *test6) MarshalSia(w io.Writer) error {
    65  	return NewEncoder(w).WritePrefixedBytes([]byte(t.s))
    66  }
    67  
    68  func (t *test6) UnmarshalSia(r io.Reader) error {
    69  	d := NewDecoder(r)
    70  	t.s = string(d.ReadPrefixedBytes())
    71  	return d.Err()
    72  }
    73  
    74  var testStructs = []interface{}{
    75  	test0{false, 65537, 256, "foo"},
    76  	test1{[]int32{1, 2, 3}, []byte("foo"), [3]string{"foo", "bar", "baz"}, [3]byte{'f', 'o', 'o'}},
    77  	test2{test0{false, 65537, 256, "foo"}},
    78  	test3{test2{test0{false, 65537, 256, "foo"}}},
    79  	test4{&test1{[]int32{1, 2, 3}, []byte("foo"), [3]string{"foo", "bar", "baz"}, [3]byte{'f', 'o', 'o'}}},
    80  	test5{"foo"},
    81  	&test6{"foo"},
    82  }
    83  
    84  var testEncodings = [][]byte{
    85  	{0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o'},
    86  	{3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
    87  		0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 3,
    88  		0, 0, 0, 0, 0, 0, 0, 'b', 'a', 'r', 3, 0, 0, 0, 0, 0, 0, 0, 'b', 'a', 'z', 'f', 'o', 'o'},
    89  	{0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o'},
    90  	{0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o'},
    91  	{1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
    92  		0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 3,
    93  		0, 0, 0, 0, 0, 0, 0, 'b', 'a', 'r', 3, 0, 0, 0, 0, 0, 0, 0, 'b', 'a', 'z', 'f', 'o', 'o'},
    94  	{3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o'},
    95  	{3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o'},
    96  }
    97  
    98  // TestEncode tests the Encode function.
    99  func TestEncode(t *testing.T) {
   100  	// use Marshal for convenience
   101  	for i := range testStructs {
   102  		b := Marshal(testStructs[i])
   103  		if !bytes.Equal(b, testEncodings[i]) {
   104  			t.Errorf("bad encoding of testStructs[%d]: \nexp:\t%v\ngot:\t%v", i, testEncodings[i], b)
   105  		}
   106  	}
   107  
   108  	// bad type
   109  	defer func() {
   110  		if recover() == nil {
   111  			t.Error("expected panic, got nil")
   112  		}
   113  	}()
   114  	NewEncoder(ioutil.Discard).Encode(map[int]int{})
   115  }
   116  
   117  // TestDecode tests the Decode function.
   118  func TestDecode(t *testing.T) {
   119  	if testing.Short() {
   120  		t.SkipNow()
   121  	}
   122  	// use Unmarshal for convenience
   123  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   124  	for i := range testEncodings {
   125  		err := Unmarshal(testEncodings[i], emptyStructs[i])
   126  		if err != nil {
   127  			t.Error(err)
   128  		}
   129  	}
   130  
   131  	// bad boolean
   132  	err := Unmarshal([]byte{3}, new(bool))
   133  	if err == nil || err.Error() != "could not decode type bool: boolean value was not 0 or 1" {
   134  		t.Error("expected bool error, got", err)
   135  	}
   136  
   137  	// non-pointer
   138  	err = Unmarshal([]byte{1, 2, 3}, "foo")
   139  	if err != errBadPointer {
   140  		t.Error("expected errBadPointer, got", err)
   141  	}
   142  
   143  	// unknown type
   144  	err = Unmarshal([]byte{1, 2, 3}, new(map[int]int))
   145  	if err == nil || err.Error() != "could not decode type map[int]int: unknown type" {
   146  		t.Error("expected unknown type error, got", err)
   147  	}
   148  
   149  	// big slice (larger than MaxSliceSize)
   150  	err = Unmarshal(EncUint64(MaxSliceSize+1), new([]byte))
   151  	if err == nil || !strings.Contains(err.Error(), "exceeds size limit") {
   152  		t.Error("expected large slice error, got", err)
   153  	}
   154  
   155  	// massive slice (larger than MaxInt32)
   156  	err = Unmarshal(EncUint64(1<<32), new([]byte))
   157  	if err == nil || !strings.Contains(err.Error(), "exceeds size limit") {
   158  		t.Error("expected large slice error, got", err)
   159  	}
   160  
   161  	// many small slices (total larger than maxDecodeLen)
   162  	bigSlice := strings.Split(strings.Repeat("0123456789abcdefghijklmnopqrstuvwxyz", (MaxSliceSize/16)-1), "0")
   163  	err = Unmarshal(Marshal(bigSlice), new([]string))
   164  	if err == nil || !strings.Contains(err.Error(), "exceeds size limit") {
   165  		t.Error("expected size limit error, got", err)
   166  	}
   167  
   168  	// badReader should fail on every decode
   169  	dec := NewDecoder(new(badReader))
   170  	for i := range testEncodings {
   171  		err := dec.Decode(emptyStructs[i])
   172  		if err == nil {
   173  			t.Error("expected error, got nil")
   174  		}
   175  	}
   176  	// special case, not covered by testStructs
   177  	err = dec.Decode(new([3]byte))
   178  	if err == nil || err.Error() != "could not decode type [3]uint8: EOF" {
   179  		t.Error("expected EOF error, got", err)
   180  	}
   181  }
   182  
   183  // TestMarshalUnmarshal tests the Marshal and Unmarshal functions, which are
   184  // inverses of each other.
   185  func TestMarshalUnmarshal(t *testing.T) {
   186  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   187  	for i := range testStructs {
   188  		b := Marshal(testStructs[i])
   189  		err := Unmarshal(b, emptyStructs[i])
   190  		if err != nil {
   191  			t.Error(err)
   192  		}
   193  	}
   194  }
   195  
   196  // TestEncodeDecode tests the Encode and Decode functions, which are inverses
   197  // of each other.
   198  func TestEncodeDecode(t *testing.T) {
   199  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   200  	b := new(bytes.Buffer)
   201  	enc := NewEncoder(b)
   202  	dec := NewDecoder(b)
   203  	for i := range testStructs {
   204  		enc.Encode(testStructs[i])
   205  		err := dec.Decode(emptyStructs[i])
   206  		if err != nil {
   207  			t.Error(err)
   208  		}
   209  	}
   210  }
   211  
   212  // TestEncodeAll tests the EncodeAll function.
   213  func TestEncodeAll(t *testing.T) {
   214  	// EncodeAll should produce the same result as individually encoding each
   215  	// object
   216  	exp := new(bytes.Buffer)
   217  	enc := NewEncoder(exp)
   218  	for i := range testStructs {
   219  		enc.Encode(testStructs[i])
   220  	}
   221  
   222  	b := new(bytes.Buffer)
   223  	NewEncoder(b).EncodeAll(testStructs...)
   224  	if !bytes.Equal(b.Bytes(), exp.Bytes()) {
   225  		t.Errorf("expected %v, got %v", exp.Bytes(), b.Bytes())
   226  	}
   227  
   228  	// hardcoded check
   229  	exp.Reset()
   230  	exp.Write([]byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 1})
   231  
   232  	b.Reset()
   233  	NewEncoder(b).EncodeAll(1, 2, "foo", true)
   234  	if !bytes.Equal(b.Bytes(), exp.Bytes()) {
   235  		t.Errorf("expected %v, got %v", exp.Bytes(), b.Bytes())
   236  	}
   237  }
   238  
   239  // TestDecodeAll tests the DecodeAll function.
   240  func TestDecodeAll(t *testing.T) {
   241  	b := new(bytes.Buffer)
   242  	NewEncoder(b).EncodeAll(testStructs...)
   243  
   244  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   245  	err := NewDecoder(b).DecodeAll(emptyStructs...)
   246  	if err != nil {
   247  		t.Error(err)
   248  	}
   249  	empty0 := *emptyStructs[0].(*test0)
   250  	if !reflect.DeepEqual(empty0, testStructs[0]) {
   251  		t.Error("deep equal:", empty0, testStructs[0])
   252  	}
   253  	empty6 := emptyStructs[6].(*test6)
   254  	if !reflect.DeepEqual(empty6, testStructs[6]) {
   255  		t.Error("deep equal:", empty6, testStructs[6])
   256  	}
   257  
   258  	// hardcoded check
   259  	b.Reset()
   260  	b.Write([]byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 1})
   261  
   262  	var (
   263  		one, two uint64
   264  		foo      string
   265  		tru      bool
   266  	)
   267  	err = NewDecoder(b).DecodeAll(&one, &two, &foo, &tru)
   268  	if err != nil {
   269  		t.Fatal(err)
   270  	} else if one != 1 || two != 2 || foo != "foo" || tru != true {
   271  		t.Error("values were not decoded correctly:", one, two, foo, tru)
   272  	}
   273  }
   274  
   275  // TestMarshalAll tests the MarshalAll function.
   276  func TestMarshalAll(t *testing.T) {
   277  	// MarshalAll should produce the same result as individually marshalling
   278  	// each object
   279  	var expected []byte
   280  	for i := range testStructs {
   281  		expected = append(expected, Marshal(testStructs[i])...)
   282  	}
   283  
   284  	b := MarshalAll(testStructs...)
   285  	if !bytes.Equal(b, expected) {
   286  		t.Errorf("expected %v, got %v", expected, b)
   287  	}
   288  
   289  	// hardcoded check
   290  	exp := []byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 1}
   291  	b = MarshalAll(1, 2, "foo", true)
   292  	if !bytes.Equal(b, exp) {
   293  		t.Errorf("expected %v, got %v", exp, b)
   294  	}
   295  }
   296  
   297  // TestUnmarshalAll tests the UnmarshalAll function.
   298  func TestUnmarshalAll(t *testing.T) {
   299  	b := MarshalAll(testStructs...)
   300  
   301  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   302  	err := UnmarshalAll(b, emptyStructs...)
   303  	if err != nil {
   304  		t.Error(err)
   305  	}
   306  	empty1 := *emptyStructs[1].(*test1)
   307  	if !reflect.DeepEqual(empty1, testStructs[1]) {
   308  		t.Error("deep equal:", empty1, testStructs[1])
   309  	}
   310  	empty5 := *emptyStructs[5].(*test5)
   311  	if !reflect.DeepEqual(empty5, testStructs[5]) {
   312  		t.Error("deep equal:", empty5, testStructs[5])
   313  	}
   314  
   315  	// hardcoded check
   316  	b = []byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 1}
   317  	var (
   318  		one, two uint64
   319  		foo      string
   320  		tru      bool
   321  	)
   322  	err = UnmarshalAll(b, &one, &two, &foo, &tru)
   323  	if err != nil {
   324  		t.Fatal(err)
   325  	} else if one != 1 || two != 2 || foo != "foo" || tru != true {
   326  		t.Error("values were not decoded correctly:", one, two, foo, tru)
   327  	}
   328  }
   329  
   330  // TestReadWriteFile tests the ReadFiles and WriteFile functions, which are
   331  // inverses of each other.
   332  func TestReadWriteFile(t *testing.T) {
   333  	// standard
   334  	os.MkdirAll(build.TempDir("encoding"), 0777)
   335  	path := build.TempDir("encoding", t.Name())
   336  	err := WriteFile(path, testStructs[3])
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  
   341  	var obj test4
   342  	err = ReadFile(path, &obj)
   343  	if err != nil {
   344  		t.Error(err)
   345  	}
   346  
   347  	// bad paths
   348  	err = WriteFile("/foo/bar", "baz")
   349  	if err == nil {
   350  		t.Error("expected error, got nil")
   351  	}
   352  	err = ReadFile("/foo/bar", nil)
   353  	if err == nil {
   354  		t.Error("expected error, got nil")
   355  	}
   356  }
   357  
   358  // i5-4670K, 9a90f86: 33 MB/s
   359  func BenchmarkEncode(b *testing.B) {
   360  	b.ReportAllocs()
   361  	buf := new(bytes.Buffer)
   362  	enc := NewEncoder(buf)
   363  	for i := 0; i < b.N; i++ {
   364  		buf.Reset()
   365  		for i := range testStructs {
   366  			err := enc.Encode(testStructs[i])
   367  			if err != nil {
   368  				b.Fatal(err)
   369  			}
   370  		}
   371  	}
   372  	b.SetBytes(int64(buf.Len()))
   373  }
   374  
   375  // i5-4670K, 9a90f86: 26 MB/s
   376  func BenchmarkDecode(b *testing.B) {
   377  	b.ReportAllocs()
   378  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   379  	var numBytes int64
   380  	for i := 0; i < b.N; i++ {
   381  		numBytes = 0
   382  		for i := range testEncodings {
   383  			err := Unmarshal(testEncodings[i], emptyStructs[i])
   384  			if err != nil {
   385  				b.Fatal(err)
   386  			}
   387  			numBytes += int64(len(testEncodings[i]))
   388  		}
   389  	}
   390  	b.SetBytes(numBytes)
   391  }
   392  
   393  // i5-4670K, 2059112: 44 MB/s
   394  func BenchmarkMarshalAll(b *testing.B) {
   395  	b.ReportAllocs()
   396  	for i := 0; i < b.N; i++ {
   397  		_ = MarshalAll(testStructs...)
   398  	}
   399  	b.SetBytes(int64(len(bytes.Join(testEncodings, nil))))
   400  }
   401  
   402  // i5-4670K, 2059112: 36 MB/s
   403  func BenchmarkUnmarshalAll(b *testing.B) {
   404  	b.ReportAllocs()
   405  	var emptyStructs = []interface{}{&test0{}, &test1{}, &test2{}, &test3{}, &test4{}, &test5{}, &test6{}}
   406  	structBytes := bytes.Join(testEncodings, nil)
   407  	for i := 0; i < b.N; i++ {
   408  		err := UnmarshalAll(structBytes, emptyStructs...)
   409  		if err != nil {
   410  			b.Fatal(err)
   411  		}
   412  	}
   413  	b.SetBytes(int64(len(structBytes)))
   414  }