github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/rlp/encode_test.go (about) 1 // Copyright 2014 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum 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 30 type testEncoder struct { 31 err error 32 } 33 34 func (e *testEncoder) EncodeRLP(w io.Writer) error { 35 if e == nil { 36 w.Write([]byte{0, 0, 0, 0}) 37 } else if e.err != nil { 38 return e.err 39 } else { 40 w.Write([]byte{0, 1, 0, 1, 0, 1, 0, 1, 0, 1}) 41 } 42 return nil 43 } 44 45 type byteEncoder byte 46 47 func (e byteEncoder) EncodeRLP(w io.Writer) error { 48 w.Write(EmptyList) 49 return nil 50 } 51 52 type encodableReader struct { 53 A, B uint 54 } 55 56 func (e *encodableReader) Read(b []byte) (int, error) { 57 panic("called") 58 } 59 60 type namedByteType byte 61 62 var ( 63 _ = Encoder(&testEncoder{}) 64 _ = Encoder(byteEncoder(0)) 65 66 reader io.Reader = &encodableReader{1, 2} 67 ) 68 69 type encTest struct { 70 val interface{} 71 output, error string 72 } 73 74 var encTests = []encTest{ 75 // booleans 76 {val: true, output: "01"}, 77 {val: false, output: "80"}, 78 79 // integers 80 {val: uint32(0), output: "80"}, 81 {val: uint32(127), output: "7F"}, 82 {val: uint32(128), output: "8180"}, 83 {val: uint32(256), output: "820100"}, 84 {val: uint32(1024), output: "820400"}, 85 {val: uint32(0xFFFFFF), output: "83FFFFFF"}, 86 {val: uint32(0xFFFFFFFF), output: "84FFFFFFFF"}, 87 {val: uint64(0xFFFFFFFF), output: "84FFFFFFFF"}, 88 {val: uint64(0xFFFFFFFFFF), output: "85FFFFFFFFFF"}, 89 {val: uint64(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"}, 90 {val: uint64(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"}, 91 {val: uint64(0xFFFFFFFFFFFFFFFF), output: "88FFFFFFFFFFFFFFFF"}, 92 93 // big integers (should match uint for small values) 94 {val: big.NewInt(0), output: "80"}, 95 {val: big.NewInt(1), output: "01"}, 96 {val: big.NewInt(127), output: "7F"}, 97 {val: big.NewInt(128), output: "8180"}, 98 {val: big.NewInt(256), output: "820100"}, 99 {val: big.NewInt(1024), output: "820400"}, 100 {val: big.NewInt(0xFFFFFF), output: "83FFFFFF"}, 101 {val: big.NewInt(0xFFFFFFFF), output: "84FFFFFFFF"}, 102 {val: big.NewInt(0xFFFFFFFFFF), output: "85FFFFFFFFFF"}, 103 {val: big.NewInt(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"}, 104 {val: big.NewInt(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"}, 105 { 106 val: big.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")), 107 output: "8F102030405060708090A0B0C0D0E0F2", 108 }, 109 { 110 val: big.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")), 111 output: "9C0100020003000400050006000700080009000A000B000C000D000E01", 112 }, 113 { 114 val: big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")), 115 output: "A1010000000000000000000000000000000000000000000000000000000000000000", 116 }, 117 118 // non-pointer big.Int 119 {val: *big.NewInt(0), output: "80"}, 120 {val: *big.NewInt(0xFFFFFF), output: "83FFFFFF"}, 121 122 // negative ints are not supported 123 {val: big.NewInt(-1), error: "rlp: cannot encode negative *big.Int"}, 124 125 // byte slices, strings 126 {val: []byte{}, output: "80"}, 127 {val: []byte{0x7E}, output: "7E"}, 128 {val: []byte{0x7F}, output: "7F"}, 129 {val: []byte{0x80}, output: "8180"}, 130 {val: []byte{1, 2, 3}, output: "83010203"}, 131 132 {val: []namedByteType{1, 2, 3}, output: "83010203"}, 133 {val: [...]namedByteType{1, 2, 3}, output: "83010203"}, 134 135 {val: "", output: "80"}, 136 {val: "\x7E", output: "7E"}, 137 {val: "\x7F", output: "7F"}, 138 {val: "\x80", output: "8180"}, 139 {val: "dog", output: "83646F67"}, 140 { 141 val: "Lorem ipsum dolor sit amet, consectetur adipisicing eli", 142 output: "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69", 143 }, 144 { 145 val: "Lorem ipsum dolor sit amet, consectetur adipisicing elit", 146 output: "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974", 147 }, 148 { 149 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", 150 output: "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174", 151 }, 152 153 // slices 154 {val: []uint{}, output: "C0"}, 155 {val: []uint{1, 2, 3}, output: "C3010203"}, 156 { 157 // [ [], [[]], [ [], [[]] ] ] 158 val: []interface{}{[]interface{}{}, [][]interface{}{{}}, []interface{}{[]interface{}{}, [][]interface{}{{}}}}, 159 output: "C7C0C1C0C3C0C1C0", 160 }, 161 { 162 val: []string{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"}, 163 output: "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F", 164 }, 165 { 166 val: []interface{}{uint(1), uint(0xFFFFFF), []interface{}{[]uint{4, 5, 5}}, "abc"}, 167 output: "CE0183FFFFFFC4C304050583616263", 168 }, 169 { 170 val: [][]string{ 171 {"asdf", "qwer", "zxcv"}, 172 {"asdf", "qwer", "zxcv"}, 173 {"asdf", "qwer", "zxcv"}, 174 {"asdf", "qwer", "zxcv"}, 175 {"asdf", "qwer", "zxcv"}, 176 {"asdf", "qwer", "zxcv"}, 177 {"asdf", "qwer", "zxcv"}, 178 {"asdf", "qwer", "zxcv"}, 179 {"asdf", "qwer", "zxcv"}, 180 {"asdf", "qwer", "zxcv"}, 181 {"asdf", "qwer", "zxcv"}, 182 {"asdf", "qwer", "zxcv"}, 183 {"asdf", "qwer", "zxcv"}, 184 {"asdf", "qwer", "zxcv"}, 185 {"asdf", "qwer", "zxcv"}, 186 {"asdf", "qwer", "zxcv"}, 187 {"asdf", "qwer", "zxcv"}, 188 {"asdf", "qwer", "zxcv"}, 189 {"asdf", "qwer", "zxcv"}, 190 {"asdf", "qwer", "zxcv"}, 191 {"asdf", "qwer", "zxcv"}, 192 {"asdf", "qwer", "zxcv"}, 193 {"asdf", "qwer", "zxcv"}, 194 {"asdf", "qwer", "zxcv"}, 195 {"asdf", "qwer", "zxcv"}, 196 {"asdf", "qwer", "zxcv"}, 197 {"asdf", "qwer", "zxcv"}, 198 {"asdf", "qwer", "zxcv"}, 199 {"asdf", "qwer", "zxcv"}, 200 {"asdf", "qwer", "zxcv"}, 201 {"asdf", "qwer", "zxcv"}, 202 {"asdf", "qwer", "zxcv"}, 203 }, 204 output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376", 205 }, 206 207 // RawValue 208 {val: RawValue(unhex("01")), output: "01"}, 209 {val: RawValue(unhex("82FFFF")), output: "82FFFF"}, 210 {val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"}, 211 212 // structs 213 {val: simplestruct{}, output: "C28080"}, 214 {val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"}, 215 {val: &recstruct{5, nil}, output: "C205C0"}, 216 {val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"}, 217 {val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"}, 218 {val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"}, 219 {val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"}, 220 {val: &tailRaw{A: 1, Tail: nil}, output: "C101"}, 221 {val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"}, 222 223 // nil 224 {val: (*uint)(nil), output: "80"}, 225 {val: (*string)(nil), output: "80"}, 226 {val: (*[]byte)(nil), output: "80"}, 227 {val: (*[10]byte)(nil), output: "80"}, 228 {val: (*big.Int)(nil), output: "80"}, 229 {val: (*[]string)(nil), output: "C0"}, 230 {val: (*[10]string)(nil), output: "C0"}, 231 {val: (*[]interface{})(nil), output: "C0"}, 232 {val: (*[]struct{ uint })(nil), output: "C0"}, 233 {val: (*interface{})(nil), output: "C0"}, 234 235 // interfaces 236 {val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct 237 238 // Encoder 239 {val: (*testEncoder)(nil), output: "00000000"}, 240 {val: &testEncoder{}, output: "00010001000100010001"}, 241 {val: &testEncoder{errors.New("test error")}, error: "test error"}, 242 // verify that pointer method testEncoder.EncodeRLP is called for 243 // addressable non-pointer values. 244 {val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"}, 245 {val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"}, 246 // verify the error for non-addressable non-pointer Encoder 247 {val: testEncoder{}, error: "rlp: game over: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"}, 248 // verify the special case for []byte 249 {val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"}, 250 } 251 252 func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) { 253 for i, test := range encTests { 254 output, err := f(test.val) 255 if err != nil && test.error == "" { 256 t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T", 257 i, err, test.val, test.val) 258 continue 259 } 260 if test.error != "" && fmt.Sprint(err) != test.error { 261 t.Errorf("test %d: error mismatch\ngot %v\nwant %v\nvalue %#v\ntype %T", 262 i, err, test.error, test.val, test.val) 263 continue 264 } 265 if err == nil && !bytes.Equal(output, unhex(test.output)) { 266 t.Errorf("test %d: output mismatch:\ngot %X\nwant %s\nvalue %#v\ntype %T", 267 i, output, test.output, test.val, test.val) 268 } 269 } 270 } 271 272 func TestEncode(t *testing.T) { 273 runEncTests(t, func(val interface{}) ([]byte, error) { 274 b := new(bytes.Buffer) 275 err := Encode(b, val) 276 return b.Bytes(), err 277 }) 278 } 279 280 func TestEncodeToBytes(t *testing.T) { 281 runEncTests(t, EncodeToBytes) 282 } 283 284 func TestEncodeToReader(t *testing.T) { 285 runEncTests(t, func(val interface{}) ([]byte, error) { 286 _, r, err := EncodeToReader(val) 287 if err != nil { 288 return nil, err 289 } 290 return ioutil.ReadAll(r) 291 }) 292 } 293 294 func TestEncodeToReaderPiecewise(t *testing.T) { 295 runEncTests(t, func(val interface{}) ([]byte, error) { 296 size, r, err := EncodeToReader(val) 297 if err != nil { 298 return nil, err 299 } 300 301 // read output piecewise 302 output := make([]byte, size) 303 for start, end := 0, 0; start < size; start = end { 304 if remaining := size - start; remaining < 3 { 305 end += remaining 306 } else { 307 end = start + 3 308 } 309 n, err := r.Read(output[start:end]) 310 end = start + n 311 if err == io.EOF { 312 break 313 } else if err != nil { 314 return nil, err 315 } 316 } 317 return output, nil 318 }) 319 } 320 321 // This is a regression test verifying that encReader 322 // returns its encbuf to the pool only once. 323 func TestEncodeToReaderReturnToPool(t *testing.T) { 324 buf := make([]byte, 50) 325 wg := new(sync.WaitGroup) 326 for i := 0; i < 5; i++ { 327 wg.Add(1) 328 go func() { 329 for i := 0; i < 1000; i++ { 330 _, r, _ := EncodeToReader("foo") 331 ioutil.ReadAll(r) 332 r.Read(buf) 333 r.Read(buf) 334 r.Read(buf) 335 r.Read(buf) 336 } 337 wg.Done() 338 }() 339 } 340 wg.Wait() 341 }