github.com/core-coin/go-core/v2@v2.1.9/rlp/encode_test.go (about) 1 // Copyright 2014 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rlp 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "math/big" 26 "sync" 27 "testing" 28 29 "github.com/core-coin/go-core/v2/common/math" 30 ) 31 32 type testEncoder struct { 33 err error 34 } 35 36 func (e *testEncoder) EncodeRLP(w io.Writer) error { 37 if e == nil { 38 panic("EncodeRLP called on nil value") 39 } 40 if e.err != nil { 41 return e.err 42 } 43 w.Write([]byte{0, 1, 0, 1, 0, 1, 0, 1, 0, 1}) 44 return nil 45 } 46 47 type testEncoderValueMethod struct{} 48 49 func (e testEncoderValueMethod) EncodeRLP(w io.Writer) error { 50 w.Write([]byte{0xFA, 0xFE, 0xF0}) 51 return nil 52 } 53 54 type byteEncoder byte 55 56 func (e byteEncoder) EncodeRLP(w io.Writer) error { 57 w.Write(EmptyList) 58 return nil 59 } 60 61 type undecodableEncoder func() 62 63 func (f undecodableEncoder) EncodeRLP(w io.Writer) error { 64 w.Write([]byte{0xF5, 0xF5, 0xF5}) 65 return nil 66 } 67 68 type encodableReader struct { 69 A, B uint 70 } 71 72 func (e *encodableReader) Read(b []byte) (int, error) { 73 panic("called") 74 } 75 76 type namedByteType byte 77 78 var ( 79 _ = Encoder(&testEncoder{}) 80 _ = Encoder(byteEncoder(0)) 81 82 reader io.Reader = &encodableReader{1, 2} 83 ) 84 85 type encTest struct { 86 val interface{} 87 output, error string 88 } 89 90 var encTests = []encTest{ 91 // booleans 92 {val: true, output: "01"}, 93 {val: false, output: "80"}, 94 95 // integers 96 {val: uint32(0), output: "80"}, 97 {val: uint32(127), output: "7F"}, 98 {val: uint32(128), output: "8180"}, 99 {val: uint32(256), output: "820100"}, 100 {val: uint32(1024), output: "820400"}, 101 {val: uint32(0xFFFFFF), output: "83FFFFFF"}, 102 {val: uint32(0xFFFFFFFF), output: "84FFFFFFFF"}, 103 {val: uint64(0xFFFFFFFF), output: "84FFFFFFFF"}, 104 {val: uint64(0xFFFFFFFFFF), output: "85FFFFFFFFFF"}, 105 {val: uint64(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"}, 106 {val: uint64(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"}, 107 {val: uint64(0xFFFFFFFFFFFFFFFF), output: "88FFFFFFFFFFFFFFFF"}, 108 109 // big integers (should match uint for small values) 110 {val: big.NewInt(0), output: "80"}, 111 {val: big.NewInt(1), output: "01"}, 112 {val: big.NewInt(127), output: "7F"}, 113 {val: big.NewInt(128), output: "8180"}, 114 {val: big.NewInt(256), output: "820100"}, 115 {val: big.NewInt(1024), output: "820400"}, 116 {val: big.NewInt(0xFFFFFF), output: "83FFFFFF"}, 117 {val: big.NewInt(0xFFFFFFFF), output: "84FFFFFFFF"}, 118 {val: big.NewInt(0xFFFFFFFFFF), output: "85FFFFFFFFFF"}, 119 {val: big.NewInt(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"}, 120 {val: big.NewInt(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"}, 121 { 122 val: big.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")), 123 output: "8F102030405060708090A0B0C0D0E0F2", 124 }, 125 { 126 val: big.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")), 127 output: "9C0100020003000400050006000700080009000A000B000C000D000E01", 128 }, 129 { 130 val: big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")), 131 output: "A1010000000000000000000000000000000000000000000000000000000000000000", 132 }, 133 134 // non-pointer big.Int 135 {val: *big.NewInt(0), output: "80"}, 136 {val: *big.NewInt(0xFFFFFF), output: "83FFFFFF"}, 137 138 // negative ints are not supported 139 {val: big.NewInt(-1), error: "rlp: cannot encode negative *big.Int"}, 140 141 // byte arrays 142 {val: [0]byte{}, output: "80"}, 143 {val: [1]byte{0}, output: "00"}, 144 {val: [1]byte{1}, output: "01"}, 145 {val: [1]byte{0x7F}, output: "7F"}, 146 {val: [1]byte{0x80}, output: "8180"}, 147 {val: [1]byte{0xFF}, output: "81FF"}, 148 {val: [3]byte{1, 2, 3}, output: "83010203"}, 149 {val: [57]byte{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, 150 151 // named byte type arrays 152 {val: [0]namedByteType{}, output: "80"}, 153 {val: [1]namedByteType{0}, output: "00"}, 154 {val: [1]namedByteType{1}, output: "01"}, 155 {val: [1]namedByteType{0x7F}, output: "7F"}, 156 {val: [1]namedByteType{0x80}, output: "8180"}, 157 {val: [1]namedByteType{0xFF}, output: "81FF"}, 158 {val: [3]namedByteType{1, 2, 3}, output: "83010203"}, 159 {val: [57]namedByteType{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, 160 161 // byte slices 162 {val: []byte{}, output: "80"}, 163 {val: []byte{0}, output: "00"}, 164 {val: []byte{0x7E}, output: "7E"}, 165 {val: []byte{0x7F}, output: "7F"}, 166 {val: []byte{0x80}, output: "8180"}, 167 {val: []byte{1, 2, 3}, output: "83010203"}, 168 169 // named byte type slices 170 {val: []namedByteType{}, output: "80"}, 171 {val: []namedByteType{0}, output: "00"}, 172 {val: []namedByteType{0x7E}, output: "7E"}, 173 {val: []namedByteType{0x7F}, output: "7F"}, 174 {val: []namedByteType{0x80}, output: "8180"}, 175 {val: []namedByteType{1, 2, 3}, output: "83010203"}, 176 177 // strings 178 {val: "", output: "80"}, 179 {val: "\x7E", output: "7E"}, 180 {val: "\x7F", output: "7F"}, 181 {val: "\x80", output: "8180"}, 182 {val: "dog", output: "83646F67"}, 183 { 184 val: "Lorem ipsum dolor sit amet, consectetur adipisicing eli", 185 output: "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69", 186 }, 187 { 188 val: "Lorem ipsum dolor sit amet, consectetur adipisicing elit", 189 output: "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974", 190 }, 191 { 192 val: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat", 193 output: "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174", 194 }, 195 196 // slices 197 {val: []uint{}, output: "C0"}, 198 {val: []uint{1, 2, 3}, output: "C3010203"}, 199 { 200 // [ [], [[]], [ [], [[]] ] ] 201 val: []interface{}{[]interface{}{}, [][]interface{}{{}}, []interface{}{[]interface{}{}, [][]interface{}{{}}}}, 202 output: "C7C0C1C0C3C0C1C0", 203 }, 204 { 205 val: []string{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"}, 206 output: "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F", 207 }, 208 { 209 val: []interface{}{uint(1), uint(0xFFFFFF), []interface{}{[]uint{4, 5, 5}}, "abc"}, 210 output: "CE0183FFFFFFC4C304050583616263", 211 }, 212 { 213 val: [][]string{ 214 {"asdf", "qwer", "zxcv"}, 215 {"asdf", "qwer", "zxcv"}, 216 {"asdf", "qwer", "zxcv"}, 217 {"asdf", "qwer", "zxcv"}, 218 {"asdf", "qwer", "zxcv"}, 219 {"asdf", "qwer", "zxcv"}, 220 {"asdf", "qwer", "zxcv"}, 221 {"asdf", "qwer", "zxcv"}, 222 {"asdf", "qwer", "zxcv"}, 223 {"asdf", "qwer", "zxcv"}, 224 {"asdf", "qwer", "zxcv"}, 225 {"asdf", "qwer", "zxcv"}, 226 {"asdf", "qwer", "zxcv"}, 227 {"asdf", "qwer", "zxcv"}, 228 {"asdf", "qwer", "zxcv"}, 229 {"asdf", "qwer", "zxcv"}, 230 {"asdf", "qwer", "zxcv"}, 231 {"asdf", "qwer", "zxcv"}, 232 {"asdf", "qwer", "zxcv"}, 233 {"asdf", "qwer", "zxcv"}, 234 {"asdf", "qwer", "zxcv"}, 235 {"asdf", "qwer", "zxcv"}, 236 {"asdf", "qwer", "zxcv"}, 237 {"asdf", "qwer", "zxcv"}, 238 {"asdf", "qwer", "zxcv"}, 239 {"asdf", "qwer", "zxcv"}, 240 {"asdf", "qwer", "zxcv"}, 241 {"asdf", "qwer", "zxcv"}, 242 {"asdf", "qwer", "zxcv"}, 243 {"asdf", "qwer", "zxcv"}, 244 {"asdf", "qwer", "zxcv"}, 245 {"asdf", "qwer", "zxcv"}, 246 }, 247 output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376", 248 }, 249 250 // RawValue 251 {val: RawValue(unhex("01")), output: "01"}, 252 {val: RawValue(unhex("82FFFF")), output: "82FFFF"}, 253 {val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"}, 254 255 // structs 256 {val: simplestruct{}, output: "C28080"}, 257 {val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"}, 258 {val: &recstruct{5, nil}, output: "C205C0"}, 259 {val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"}, 260 {val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"}, 261 {val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"}, 262 {val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"}, 263 {val: &tailRaw{A: 1, Tail: nil}, output: "C101"}, 264 {val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"}, 265 {val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"}, 266 267 // nil 268 {val: (*uint)(nil), output: "80"}, 269 {val: (*string)(nil), output: "80"}, 270 {val: (*[]byte)(nil), output: "80"}, 271 {val: (*[10]byte)(nil), output: "80"}, 272 {val: (*big.Int)(nil), output: "80"}, 273 {val: (*[]string)(nil), output: "C0"}, 274 {val: (*[10]string)(nil), output: "C0"}, 275 {val: (*[]interface{})(nil), output: "C0"}, 276 {val: (*[]struct{ uint })(nil), output: "C0"}, 277 {val: (*interface{})(nil), output: "C0"}, 278 279 // nil struct fields 280 { 281 val: struct { 282 X *[]byte 283 }{}, 284 output: "C180", 285 }, 286 { 287 val: struct { 288 X *[2]byte 289 }{}, 290 output: "C180", 291 }, 292 { 293 val: struct { 294 X *uint64 295 }{}, 296 output: "C180", 297 }, 298 { 299 val: struct { 300 X *uint64 `rlp:"nilList"` 301 }{}, 302 output: "C1C0", 303 }, 304 { 305 val: struct { 306 X *[]uint64 307 }{}, 308 output: "C1C0", 309 }, 310 { 311 val: struct { 312 X *[]uint64 `rlp:"nilString"` 313 }{}, 314 output: "C180", 315 }, 316 317 // interfaces 318 {val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct 319 320 // Encoder 321 {val: (*testEncoder)(nil), output: "C0"}, 322 {val: &testEncoder{}, output: "00010001000100010001"}, 323 {val: &testEncoder{errors.New("test error")}, error: "test error"}, 324 {val: struct{ E testEncoderValueMethod }{}, output: "C3FAFEF0"}, 325 {val: struct{ E *testEncoderValueMethod }{}, output: "C1C0"}, 326 327 // Verify that the Encoder interface works for unsupported types like func(). 328 {val: undecodableEncoder(func() {}), output: "F5F5F5"}, 329 330 // Verify that pointer method testEncoder.EncodeRLP is called for 331 // addressable non-pointer values. 332 {val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"}, 333 {val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"}, 334 335 // Verify the error for non-addressable non-pointer Encoder. 336 {val: testEncoder{}, error: "rlp: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"}, 337 338 // Verify Encoder takes precedence over []byte. 339 {val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"}, 340 } 341 342 func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) { 343 for i, test := range encTests { 344 output, err := f(test.val) 345 if err != nil && test.error == "" { 346 t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T", 347 i, err, test.val, test.val) 348 continue 349 } 350 if test.error != "" && fmt.Sprint(err) != test.error { 351 t.Errorf("test %d: error mismatch\ngot %v\nwant %v\nvalue %#v\ntype %T", 352 i, err, test.error, test.val, test.val) 353 continue 354 } 355 if err == nil && !bytes.Equal(output, unhex(test.output)) { 356 t.Errorf("test %d: output mismatch:\ngot %X\nwant %s\nvalue %#v\ntype %T", 357 i, output, test.output, test.val, test.val) 358 } 359 } 360 } 361 362 func TestEncode(t *testing.T) { 363 runEncTests(t, func(val interface{}) ([]byte, error) { 364 b := new(bytes.Buffer) 365 err := Encode(b, val) 366 return b.Bytes(), err 367 }) 368 } 369 370 func TestEncodeToBytes(t *testing.T) { 371 runEncTests(t, EncodeToBytes) 372 } 373 374 func TestEncodeToReader(t *testing.T) { 375 runEncTests(t, func(val interface{}) ([]byte, error) { 376 _, r, err := EncodeToReader(val) 377 if err != nil { 378 return nil, err 379 } 380 return ioutil.ReadAll(r) 381 }) 382 } 383 384 func TestEncodeToReaderPiecewise(t *testing.T) { 385 runEncTests(t, func(val interface{}) ([]byte, error) { 386 size, r, err := EncodeToReader(val) 387 if err != nil { 388 return nil, err 389 } 390 391 // read output piecewise 392 output := make([]byte, size) 393 for start, end := 0, 0; start < size; start = end { 394 if remaining := size - start; remaining < 3 { 395 end += remaining 396 } else { 397 end = start + 3 398 } 399 n, err := r.Read(output[start:end]) 400 end = start + n 401 if err == io.EOF { 402 break 403 } else if err != nil { 404 return nil, err 405 } 406 } 407 return output, nil 408 }) 409 } 410 411 // This is a regression test verifying that encReader 412 // returns its encbuf to the pool only once. 413 func TestEncodeToReaderReturnToPool(t *testing.T) { 414 buf := make([]byte, 50) 415 wg := new(sync.WaitGroup) 416 for i := 0; i < 5; i++ { 417 wg.Add(1) 418 go func() { 419 for i := 0; i < 1000; i++ { 420 _, r, _ := EncodeToReader("foo") 421 ioutil.ReadAll(r) 422 r.Read(buf) 423 r.Read(buf) 424 r.Read(buf) 425 r.Read(buf) 426 } 427 wg.Done() 428 }() 429 } 430 wg.Wait() 431 } 432 433 var sink interface{} 434 435 func BenchmarkIntsize(b *testing.B) { 436 for i := 0; i < b.N; i++ { 437 sink = intsize(0x12345678) 438 } 439 } 440 441 func BenchmarkPutint(b *testing.B) { 442 buf := make([]byte, 8) 443 for i := 0; i < b.N; i++ { 444 putint(buf, 0x12345678) 445 sink = buf 446 } 447 } 448 449 func BenchmarkEncodeBigInts(b *testing.B) { 450 ints := make([]*big.Int, 200) 451 for i := range ints { 452 ints[i] = math.BigPow(2, int64(i)) 453 } 454 out := bytes.NewBuffer(make([]byte, 0, 4096)) 455 b.ResetTimer() 456 b.ReportAllocs() 457 458 for i := 0; i < b.N; i++ { 459 out.Reset() 460 if err := Encode(out, ints); err != nil { 461 b.Fatal(err) 462 } 463 } 464 }