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 }