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