topics_test.go 8.7 KB

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