github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/tests/rlp_test_util.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:45</date> 10 //</624450122406694912> 11 12 13 package tests 14 15 import ( 16 "bytes" 17 "encoding/hex" 18 "errors" 19 "fmt" 20 "math/big" 21 "strings" 22 23 "github.com/ethereum/go-ethereum/rlp" 24 ) 25 26 //rlp test是单个rlp测试的JSON结构。 27 type RLPTest struct { 28 //如果in的值为“无效”或“有效”,则测试 29 //检查是否可以将out解码为值 30 //键入interface。 31 // 32 //对于其他JSON值,in被视为 33 //调用rlp.stream。测试还验证编码 34 //In产生输入输出字节。 35 In interface{} 36 37 //out是十六进制编码的rlp值。 38 Out string 39 } 40 41 //运行执行测试。 42 func (t *RLPTest) Run() error { 43 outb, err := hex.DecodeString(t.Out) 44 if err != nil { 45 return fmt.Errorf("invalid hex in Out") 46 } 47 48 //处理没有实际值的简单解码测试。 49 if t.In == "VALID" || t.In == "INVALID" { 50 return checkDecodeInterface(outb, t.In == "VALID") 51 } 52 53 //检查编码值是否产生相同的字节。 54 in := translateJSON(t.In) 55 b, err := rlp.EncodeToBytes(in) 56 if err != nil { 57 return fmt.Errorf("encode failed: %v", err) 58 } 59 if !bytes.Equal(b, outb) { 60 return fmt.Errorf("encode produced %x, want %x", b, outb) 61 } 62 //测试流解码。 63 s := rlp.NewStream(bytes.NewReader(outb), 0) 64 return checkDecodeFromJSON(s, in) 65 } 66 67 func checkDecodeInterface(b []byte, isValid bool) error { 68 err := rlp.DecodeBytes(b, new(interface{})) 69 switch { 70 case isValid && err != nil: 71 return fmt.Errorf("decoding failed: %v", err) 72 case !isValid && err == nil: 73 return fmt.Errorf("decoding of invalid value succeeded") 74 } 75 return nil 76 } 77 78 //translateJSON使测试JSON值可以用rlp编码。 79 func translateJSON(v interface{}) interface{} { 80 switch v := v.(type) { 81 case float64: 82 return uint64(v) 83 case string: 84 if len(v) > 0 && v[0] == '#' { //开始一个假大内景。 85 big, ok := new(big.Int).SetString(v[1:], 10) 86 if !ok { 87 panic(fmt.Errorf("bad test: bad big int: %q", v)) 88 } 89 return big 90 } 91 return []byte(v) 92 case []interface{}: 93 new := make([]interface{}, len(v)) 94 for i := range v { 95 new[i] = translateJSON(v[i]) 96 } 97 return new 98 default: 99 panic(fmt.Errorf("can't handle %T", v)) 100 } 101 } 102 103 //checkdecodefromjson从exp.exp引导的s解码驱动 104 //通过调用基于解码操作(uint、big、list…)的流 105 //每个值的类型。从RLP流解码的值 106 //必须与JSON值匹配。 107 func checkDecodeFromJSON(s *rlp.Stream, exp interface{}) error { 108 switch exp := exp.(type) { 109 case uint64: 110 i, err := s.Uint() 111 if err != nil { 112 return addStack("Uint", exp, err) 113 } 114 if i != exp { 115 return addStack("Uint", exp, fmt.Errorf("result mismatch: got %d", i)) 116 } 117 case *big.Int: 118 big := new(big.Int) 119 if err := s.Decode(&big); err != nil { 120 return addStack("Big", exp, err) 121 } 122 if big.Cmp(exp) != 0 { 123 return addStack("Big", exp, fmt.Errorf("result mismatch: got %d", big)) 124 } 125 case []byte: 126 b, err := s.Bytes() 127 if err != nil { 128 return addStack("Bytes", exp, err) 129 } 130 if !bytes.Equal(b, exp) { 131 return addStack("Bytes", exp, fmt.Errorf("result mismatch: got %x", b)) 132 } 133 case []interface{}: 134 if _, err := s.List(); err != nil { 135 return addStack("List", exp, err) 136 } 137 for i, v := range exp { 138 if err := checkDecodeFromJSON(s, v); err != nil { 139 return addStack(fmt.Sprintf("[%d]", i), exp, err) 140 } 141 } 142 if err := s.ListEnd(); err != nil { 143 return addStack("ListEnd", exp, err) 144 } 145 default: 146 panic(fmt.Errorf("unhandled type: %T", exp)) 147 } 148 return nil 149 } 150 151 func addStack(op string, val interface{}, err error) error { 152 lines := strings.Split(err.Error(), "\n") 153 lines = append(lines, fmt.Sprintf("\t%s: %v", op, val)) 154 return errors.New(strings.Join(lines, "\n")) 155 } 156