gitlab.com/yannislg/go-pulse@v0.0.0-20210722055913-a3e24e95638d/accounts/abi/bind/topics_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package bind 18 19 import ( 20 "math/big" 21 "reflect" 22 "testing" 23 24 "github.com/ethereum/go-ethereum/accounts/abi" 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/crypto" 27 ) 28 29 func TestMakeTopics(t *testing.T) { 30 type args struct { 31 query [][]interface{} 32 } 33 tests := []struct { 34 name string 35 args args 36 want [][]common.Hash 37 wantErr bool 38 }{ 39 { 40 "support fixed byte types, right padded to 32 bytes", 41 args{[][]interface{}{{[5]byte{1, 2, 3, 4, 5}}}}, 42 [][]common.Hash{{common.Hash{1, 2, 3, 4, 5}}}, 43 false, 44 }, 45 { 46 "support common hash types in topics", 47 args{[][]interface{}{{common.Hash{1, 2, 3, 4, 5}}}}, 48 [][]common.Hash{{common.Hash{1, 2, 3, 4, 5}}}, 49 false, 50 }, 51 { 52 "support address types in topics", 53 args{[][]interface{}{{common.Address{1, 2, 3, 4, 5}}}}, 54 [][]common.Hash{{common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5}}}, 55 false, 56 }, 57 { 58 "support *big.Int types in topics", 59 args{[][]interface{}{{big.NewInt(1).Lsh(big.NewInt(2), 254)}}}, 60 [][]common.Hash{{common.Hash{128}}}, 61 false, 62 }, 63 { 64 "support boolean types in topics", 65 args{[][]interface{}{ 66 {true}, 67 {false}, 68 }}, 69 [][]common.Hash{ 70 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, 71 {common.Hash{0}}, 72 }, 73 false, 74 }, 75 { 76 "support int/uint(8/16/32/64) types in topics", 77 args{[][]interface{}{ 78 {int8(-2)}, 79 {int16(-3)}, 80 {int32(-4)}, 81 {int64(-5)}, 82 {int8(1)}, 83 {int16(256)}, 84 {int32(65536)}, 85 {int64(4294967296)}, 86 {uint8(1)}, 87 {uint16(256)}, 88 {uint32(65536)}, 89 {uint64(4294967296)}, 90 }}, 91 [][]common.Hash{ 92 {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254}}, 93 {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253}}, 94 {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252}}, 95 {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251}}, 96 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, 97 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}}, 98 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}}, 99 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}}, 100 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, 101 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}}, 102 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}}, 103 {common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}}, 104 }, 105 false, 106 }, 107 { 108 "support string types in topics", 109 args{[][]interface{}{{"hello world"}}}, 110 [][]common.Hash{{crypto.Keccak256Hash([]byte("hello world"))}}, 111 false, 112 }, 113 { 114 "support byte slice types in topics", 115 args{[][]interface{}{{[]byte{1, 2, 3}}}}, 116 [][]common.Hash{{crypto.Keccak256Hash([]byte{1, 2, 3})}}, 117 false, 118 }, 119 } 120 for _, tt := range tests { 121 t.Run(tt.name, func(t *testing.T) { 122 got, err := makeTopics(tt.args.query...) 123 if (err != nil) != tt.wantErr { 124 t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr) 125 return 126 } 127 if !reflect.DeepEqual(got, tt.want) { 128 t.Errorf("makeTopics() = %v, want %v", got, tt.want) 129 } 130 }) 131 } 132 } 133 134 type args struct { 135 createObj func() interface{} 136 resultObj func() interface{} 137 resultMap func() map[string]interface{} 138 fields abi.Arguments 139 topics []common.Hash 140 } 141 142 type bytesStruct struct { 143 StaticBytes [5]byte 144 } 145 type int8Struct struct { 146 Int8Value int8 147 } 148 type int256Struct struct { 149 Int256Value *big.Int 150 } 151 152 type topicTest struct { 153 name string 154 args args 155 wantErr bool 156 } 157 158 func setupTopicsTests() []topicTest { 159 bytesType, _ := abi.NewType("bytes5", "", nil) 160 int8Type, _ := abi.NewType("int8", "", nil) 161 int256Type, _ := abi.NewType("int256", "", nil) 162 tupleType, _ := abi.NewType("tuple(int256,int8)", "", nil) 163 164 tests := []topicTest{ 165 { 166 name: "support fixed byte types, right padded to 32 bytes", 167 args: args{ 168 createObj: func() interface{} { return &bytesStruct{} }, 169 resultObj: func() interface{} { return &bytesStruct{StaticBytes: [5]byte{1, 2, 3, 4, 5}} }, 170 resultMap: func() map[string]interface{} { 171 return map[string]interface{}{"staticBytes": [5]byte{1, 2, 3, 4, 5}} 172 }, 173 fields: abi.Arguments{abi.Argument{ 174 Name: "staticBytes", 175 Type: bytesType, 176 Indexed: true, 177 }}, 178 topics: []common.Hash{ 179 {1, 2, 3, 4, 5}, 180 }, 181 }, 182 wantErr: false, 183 }, 184 { 185 name: "int8 with negative value", 186 args: args{ 187 createObj: func() interface{} { return &int8Struct{} }, 188 resultObj: func() interface{} { return &int8Struct{Int8Value: -1} }, 189 resultMap: func() map[string]interface{} { 190 return map[string]interface{}{"int8Value": int8(-1)} 191 }, 192 fields: abi.Arguments{abi.Argument{ 193 Name: "int8Value", 194 Type: int8Type, 195 Indexed: true, 196 }}, 197 topics: []common.Hash{ 198 {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, 200 }, 201 }, 202 wantErr: false, 203 }, 204 { 205 name: "int256 with negative value", 206 args: args{ 207 createObj: func() interface{} { return &int256Struct{} }, 208 resultObj: func() interface{} { return &int256Struct{Int256Value: big.NewInt(-1)} }, 209 resultMap: func() map[string]interface{} { 210 return map[string]interface{}{"int256Value": big.NewInt(-1)} 211 }, 212 fields: abi.Arguments{abi.Argument{ 213 Name: "int256Value", 214 Type: int256Type, 215 Indexed: true, 216 }}, 217 topics: []common.Hash{ 218 {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 219 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, 220 }, 221 }, 222 wantErr: false, 223 }, 224 { 225 name: "tuple(int256, int8)", 226 args: args{ 227 createObj: func() interface{} { return nil }, 228 resultObj: func() interface{} { return nil }, 229 resultMap: func() map[string]interface{} { return make(map[string]interface{}) }, 230 fields: abi.Arguments{abi.Argument{ 231 Name: "tupletype", 232 Type: tupleType, 233 Indexed: true, 234 }}, 235 topics: []common.Hash{}, 236 }, 237 wantErr: true, 238 }, 239 } 240 241 return tests 242 } 243 244 func TestParseTopics(t *testing.T) { 245 tests := setupTopicsTests() 246 247 for _, tt := range tests { 248 t.Run(tt.name, func(t *testing.T) { 249 createObj := tt.args.createObj() 250 if err := parseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr { 251 t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr) 252 } 253 resultObj := tt.args.resultObj() 254 if !reflect.DeepEqual(createObj, resultObj) { 255 t.Errorf("parseTopics() = %v, want %v", createObj, resultObj) 256 } 257 }) 258 } 259 } 260 261 func TestParseTopicsIntoMap(t *testing.T) { 262 tests := setupTopicsTests() 263 264 for _, tt := range tests { 265 t.Run(tt.name, func(t *testing.T) { 266 outMap := make(map[string]interface{}) 267 if err := parseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr { 268 t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr) 269 } 270 resultMap := tt.args.resultMap() 271 if !reflect.DeepEqual(outMap, resultMap) { 272 t.Errorf("parseTopicsIntoMap() = %v, want %v", outMap, resultMap) 273 } 274 }) 275 } 276 }