reflect_test.go 4.2 KB

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