* fix parseTopics() and add tests * remove printf * add ParseTopicsIntoMap() tests * fix FixedBytesTy * fix int and fixed bytes * golint topics_test.go
This commit is contained in:
		
							parent
							
								
									49cf000df7
								
							
						
					
					
						commit
						6ae9dc15cc
					
				| @ -178,6 +178,13 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er | ||||
| 
 | ||||
| 			case reflectBigInt: | ||||
| 				num := new(big.Int).SetBytes(topics[0][:]) | ||||
| 				if arg.Type.T == abi.IntTy { | ||||
| 					if num.Cmp(abi.MaxInt256) > 0 { | ||||
| 						num.Add(abi.MaxUint256, big.NewInt(0).Neg(num)) | ||||
| 						num.Add(num, big.NewInt(1)) | ||||
| 						num.Neg(num) | ||||
| 					} | ||||
| 				} | ||||
| 				field.Set(reflect.ValueOf(num)) | ||||
| 
 | ||||
| 			default: | ||||
| @ -212,8 +219,7 @@ func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics | ||||
| 		case abi.BoolTy: | ||||
| 			out[arg.Name] = topics[0][common.HashLength-1] == 1 | ||||
| 		case abi.IntTy, abi.UintTy: | ||||
| 			num := new(big.Int).SetBytes(topics[0][:]) | ||||
| 			out[arg.Name] = num | ||||
| 			out[arg.Name] = abi.ReadInteger(arg.Type.T, arg.Type.Kind, topics[0].Bytes()) | ||||
| 		case abi.AddressTy: | ||||
| 			var addr common.Address | ||||
| 			copy(addr[:], topics[0][common.HashLength-common.AddressLength:]) | ||||
| @ -221,7 +227,11 @@ func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics | ||||
| 		case abi.HashTy: | ||||
| 			out[arg.Name] = topics[0] | ||||
| 		case abi.FixedBytesTy: | ||||
| 			out[arg.Name] = topics[0][:] | ||||
| 			array, err := abi.ReadFixedBytes(arg.Type, topics[0].Bytes()) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			out[arg.Name] = array | ||||
| 		case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy: | ||||
| 			// Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash
 | ||||
| 			// whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash
 | ||||
|  | ||||
| @ -17,6 +17,7 @@ | ||||
| package bind | ||||
| 
 | ||||
| import ( | ||||
| 	"math/big" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| 
 | ||||
| @ -55,27 +56,44 @@ func TestMakeTopics(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestParseTopics(t *testing.T) { | ||||
| 	type bytesStruct struct { | ||||
| 		StaticBytes [5]byte | ||||
| 	} | ||||
| type args struct { | ||||
| 	createObj func() interface{} | ||||
| 	resultObj func() interface{} | ||||
| 	resultMap func() map[string]interface{} | ||||
| 	fields    abi.Arguments | ||||
| 	topics    []common.Hash | ||||
| } | ||||
| 
 | ||||
| type bytesStruct struct { | ||||
| 	StaticBytes [5]byte | ||||
| } | ||||
| type int8Struct struct { | ||||
| 	Int8Value int8 | ||||
| } | ||||
| type int256Struct struct { | ||||
| 	Int256Value *big.Int | ||||
| } | ||||
| 
 | ||||
| type topicTest struct { | ||||
| 	name    string | ||||
| 	args    args | ||||
| 	wantErr bool | ||||
| } | ||||
| 
 | ||||
| func setupTopicsTests() []topicTest { | ||||
| 	bytesType, _ := abi.NewType("bytes5", "", nil) | ||||
| 	type args struct { | ||||
| 		createObj func() interface{} | ||||
| 		resultObj func() interface{} | ||||
| 		fields    abi.Arguments | ||||
| 		topics    []common.Hash | ||||
| 	} | ||||
| 	tests := []struct { | ||||
| 		name    string | ||||
| 		args    args | ||||
| 		wantErr bool | ||||
| 	}{ | ||||
| 	int8Type, _ := abi.NewType("int8", "", nil) | ||||
| 	int256Type, _ := abi.NewType("int256", "", nil) | ||||
| 
 | ||||
| 	tests := []topicTest{ | ||||
| 		{ | ||||
| 			name: "support fixed byte types, right padded to 32 bytes", | ||||
| 			args: args{ | ||||
| 				createObj: func() interface{} { return &bytesStruct{} }, | ||||
| 				resultObj: func() interface{} { return &bytesStruct{StaticBytes: [5]byte{1, 2, 3, 4, 5}} }, | ||||
| 				resultMap: func() map[string]interface{} { | ||||
| 					return map[string]interface{}{"staticBytes": [5]byte{1, 2, 3, 4, 5}} | ||||
| 				}, | ||||
| 				fields: abi.Arguments{abi.Argument{ | ||||
| 					Name:    "staticBytes", | ||||
| 					Type:    bytesType, | ||||
| @ -87,7 +105,54 @@ func TestParseTopics(t *testing.T) { | ||||
| 			}, | ||||
| 			wantErr: false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "int8 with negative value", | ||||
| 			args: args{ | ||||
| 				createObj: func() interface{} { return &int8Struct{} }, | ||||
| 				resultObj: func() interface{} { return &int8Struct{Int8Value: -1} }, | ||||
| 				resultMap: func() map[string]interface{} { | ||||
| 					return map[string]interface{}{"int8Value": int8(-1)} | ||||
| 				}, | ||||
| 				fields: abi.Arguments{abi.Argument{ | ||||
| 					Name:    "int8Value", | ||||
| 					Type:    int8Type, | ||||
| 					Indexed: true, | ||||
| 				}}, | ||||
| 				topics: []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, 255}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			wantErr: false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "int256 with negative value", | ||||
| 			args: args{ | ||||
| 				createObj: func() interface{} { return &int256Struct{} }, | ||||
| 				resultObj: func() interface{} { return &int256Struct{Int256Value: big.NewInt(-1)} }, | ||||
| 				resultMap: func() map[string]interface{} { | ||||
| 					return map[string]interface{}{"int256Value": big.NewInt(-1)} | ||||
| 				}, | ||||
| 				fields: abi.Arguments{abi.Argument{ | ||||
| 					Name:    "int256Value", | ||||
| 					Type:    int256Type, | ||||
| 					Indexed: true, | ||||
| 				}}, | ||||
| 				topics: []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, 255}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			wantErr: false, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	return tests | ||||
| } | ||||
| 
 | ||||
| func TestParseTopics(t *testing.T) { | ||||
| 	tests := setupTopicsTests() | ||||
| 
 | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
| 			createObj := tt.args.createObj() | ||||
| @ -101,3 +166,20 @@ func TestParseTopics(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestParseTopicsIntoMap(t *testing.T) { | ||||
| 	tests := setupTopicsTests() | ||||
| 
 | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
| 			outMap := make(map[string]interface{}) | ||||
| 			if err := parseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr { | ||||
| 				t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr) | ||||
| 			} | ||||
| 			resultMap := tt.args.resultMap() | ||||
| 			if !reflect.DeepEqual(outMap, resultMap) { | ||||
| 				t.Errorf("parseTopicsIntoMap() = %v, want %v", outMap, resultMap) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,16 +26,18 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	maxUint256 = big.NewInt(0).Add( | ||||
| 	// MaxUint256 is the maximum value that can be represented by a uint256
 | ||||
| 	MaxUint256 = big.NewInt(0).Add( | ||||
| 		big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil), | ||||
| 		big.NewInt(-1)) | ||||
| 	maxInt256 = big.NewInt(0).Add( | ||||
| 	// MaxInt256 is the maximum value that can be represented by a int256
 | ||||
| 	MaxInt256 = big.NewInt(0).Add( | ||||
| 		big.NewInt(0).Exp(big.NewInt(2), big.NewInt(255), nil), | ||||
| 		big.NewInt(-1)) | ||||
| ) | ||||
| 
 | ||||
| // reads the integer based on its kind
 | ||||
| func readInteger(typ byte, kind reflect.Kind, b []byte) interface{} { | ||||
| // ReadInteger reads the integer based on its kind and returns the appropriate value
 | ||||
| func ReadInteger(typ byte, kind reflect.Kind, b []byte) interface{} { | ||||
| 	switch kind { | ||||
| 	case reflect.Uint8: | ||||
| 		return b[len(b)-1] | ||||
| @ -62,8 +64,8 @@ func readInteger(typ byte, kind reflect.Kind, b []byte) interface{} { | ||||
| 			return ret | ||||
| 		} | ||||
| 
 | ||||
| 		if ret.Cmp(maxInt256) > 0 { | ||||
| 			ret.Add(maxUint256, big.NewInt(0).Neg(ret)) | ||||
| 		if ret.Cmp(MaxInt256) > 0 { | ||||
| 			ret.Add(MaxUint256, big.NewInt(0).Neg(ret)) | ||||
| 			ret.Add(ret, big.NewInt(1)) | ||||
| 			ret.Neg(ret) | ||||
| 		} | ||||
| @ -102,8 +104,8 @@ func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) { | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // through reflection, creates a fixed array to be read from
 | ||||
| func readFixedBytes(t Type, word []byte) (interface{}, error) { | ||||
| // ReadFixedBytes uses reflection to create a fixed array to be read from
 | ||||
| func ReadFixedBytes(t Type, word []byte) (interface{}, error) { | ||||
| 	if t.T != FixedBytesTy { | ||||
| 		return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array") | ||||
| 	} | ||||
| @ -230,7 +232,7 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) { | ||||
| 	case StringTy: // variable arrays are written at the end of the return bytes
 | ||||
| 		return string(output[begin : begin+length]), nil | ||||
| 	case IntTy, UintTy: | ||||
| 		return readInteger(t.T, t.Kind, returnOutput), nil | ||||
| 		return ReadInteger(t.T, t.Kind, returnOutput), nil | ||||
| 	case BoolTy: | ||||
| 		return readBool(returnOutput) | ||||
| 	case AddressTy: | ||||
| @ -240,7 +242,7 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) { | ||||
| 	case BytesTy: | ||||
| 		return output[begin : begin+length], nil | ||||
| 	case FixedBytesTy: | ||||
| 		return readFixedBytes(t, returnOutput) | ||||
| 		return ReadFixedBytes(t, returnOutput) | ||||
| 	case FunctionTy: | ||||
| 		return readFunctionType(t, returnOutput) | ||||
| 	default: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user