github.com/sbrajchuk/go-ethereum@v1.9.7/accounts/abi/reflect_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 abi
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  )
    23  
    24  type reflectTest struct {
    25  	name  string
    26  	args  []string
    27  	struc interface{}
    28  	want  map[string]string
    29  	err   string
    30  }
    31  
    32  var reflectTests = []reflectTest{
    33  	{
    34  		name: "OneToOneCorrespondance",
    35  		args: []string{"fieldA"},
    36  		struc: struct {
    37  			FieldA int `abi:"fieldA"`
    38  		}{},
    39  		want: map[string]string{
    40  			"fieldA": "FieldA",
    41  		},
    42  	},
    43  	{
    44  		name: "MissingFieldsInStruct",
    45  		args: []string{"fieldA", "fieldB"},
    46  		struc: struct {
    47  			FieldA int `abi:"fieldA"`
    48  		}{},
    49  		want: map[string]string{
    50  			"fieldA": "FieldA",
    51  		},
    52  	},
    53  	{
    54  		name: "MoreFieldsInStructThanArgs",
    55  		args: []string{"fieldA"},
    56  		struc: struct {
    57  			FieldA int `abi:"fieldA"`
    58  			FieldB int
    59  		}{},
    60  		want: map[string]string{
    61  			"fieldA": "FieldA",
    62  		},
    63  	},
    64  	{
    65  		name: "MissingFieldInArgs",
    66  		args: []string{"fieldA"},
    67  		struc: struct {
    68  			FieldA int `abi:"fieldA"`
    69  			FieldB int `abi:"fieldB"`
    70  		}{},
    71  		err: "struct: abi tag 'fieldB' defined but not found in abi",
    72  	},
    73  	{
    74  		name: "NoAbiDescriptor",
    75  		args: []string{"fieldA"},
    76  		struc: struct {
    77  			FieldA int
    78  		}{},
    79  		want: map[string]string{
    80  			"fieldA": "FieldA",
    81  		},
    82  	},
    83  	{
    84  		name: "NoArgs",
    85  		args: []string{},
    86  		struc: struct {
    87  			FieldA int `abi:"fieldA"`
    88  		}{},
    89  		err: "struct: abi tag 'fieldA' defined but not found in abi",
    90  	},
    91  	{
    92  		name: "DifferentName",
    93  		args: []string{"fieldB"},
    94  		struc: struct {
    95  			FieldA int `abi:"fieldB"`
    96  		}{},
    97  		want: map[string]string{
    98  			"fieldB": "FieldA",
    99  		},
   100  	},
   101  	{
   102  		name: "DifferentName",
   103  		args: []string{"fieldB"},
   104  		struc: struct {
   105  			FieldA int `abi:"fieldB"`
   106  		}{},
   107  		want: map[string]string{
   108  			"fieldB": "FieldA",
   109  		},
   110  	},
   111  	{
   112  		name: "MultipleFields",
   113  		args: []string{"fieldA", "fieldB"},
   114  		struc: struct {
   115  			FieldA int `abi:"fieldA"`
   116  			FieldB int `abi:"fieldB"`
   117  		}{},
   118  		want: map[string]string{
   119  			"fieldA": "FieldA",
   120  			"fieldB": "FieldB",
   121  		},
   122  	},
   123  	{
   124  		name: "MultipleFieldsABIMissing",
   125  		args: []string{"fieldA", "fieldB"},
   126  		struc: struct {
   127  			FieldA int `abi:"fieldA"`
   128  			FieldB int
   129  		}{},
   130  		want: map[string]string{
   131  			"fieldA": "FieldA",
   132  			"fieldB": "FieldB",
   133  		},
   134  	},
   135  	{
   136  		name: "NameConflict",
   137  		args: []string{"fieldB"},
   138  		struc: struct {
   139  			FieldA int `abi:"fieldB"`
   140  			FieldB int
   141  		}{},
   142  		err: "abi: multiple variables maps to the same abi field 'fieldB'",
   143  	},
   144  	{
   145  		name: "Underscored",
   146  		args: []string{"_"},
   147  		struc: struct {
   148  			FieldA int
   149  		}{},
   150  		err: "abi: purely underscored output cannot unpack to struct",
   151  	},
   152  	{
   153  		name: "DoubleMapping",
   154  		args: []string{"fieldB", "fieldC", "fieldA"},
   155  		struc: struct {
   156  			FieldA int `abi:"fieldC"`
   157  			FieldB int
   158  		}{},
   159  		err: "abi: multiple outputs mapping to the same struct field 'FieldA'",
   160  	},
   161  	{
   162  		name: "AlreadyMapped",
   163  		args: []string{"fieldB", "fieldB"},
   164  		struc: struct {
   165  			FieldB int `abi:"fieldB"`
   166  		}{},
   167  		err: "struct: abi tag in 'FieldB' already mapped",
   168  	},
   169  }
   170  
   171  func TestReflectNameToStruct(t *testing.T) {
   172  	for _, test := range reflectTests {
   173  		t.Run(test.name, func(t *testing.T) {
   174  			m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
   175  			if len(test.err) > 0 {
   176  				if err == nil || err.Error() != test.err {
   177  					t.Fatalf("Invalid error: expected %v, got %v", test.err, err)
   178  				}
   179  			} else {
   180  				if err != nil {
   181  					t.Fatalf("Unexpected error: %v", err)
   182  				}
   183  				for fname := range test.want {
   184  					if m[fname] != test.want[fname] {
   185  						t.Fatalf("Incorrect value for field %s: expected %v, got %v", fname, test.want[fname], m[fname])
   186  					}
   187  				}
   188  			}
   189  		})
   190  	}
   191  }