github.com/lmittmann/w3@v0.20.0/internal/abi/copy_test.go (about) 1 package abi 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "testing" 8 9 "github.com/ethereum/go-ethereum/common" 10 "github.com/google/go-cmp/cmp" 11 "github.com/lmittmann/w3/internal" 12 ) 13 14 func TestCopy(t *testing.T) { 15 tests := []struct { 16 Dst, Src any 17 WantDst any 18 WantErr error 19 }{ 20 // uint256 21 { 22 Dst: nil, 23 Src: big.NewInt(42), 24 WantErr: errors.New("abi: decode nil"), 25 }, 26 { 27 Dst: func() *big.Int { 28 var b *big.Int 29 return b 30 }(), 31 Src: big.NewInt(42), 32 WantErr: errors.New("abi: decode nil *big.Int"), 33 }, 34 { 35 Dst: big.Int{}, 36 Src: big.NewInt(42), 37 WantErr: errors.New("abi: decode non-pointer big.Int"), 38 }, 39 { 40 Dst: new(big.Int), 41 Src: big.NewInt(42), 42 WantDst: big.NewInt(42), 43 }, 44 { 45 Dst: func() **big.Int { 46 var b *big.Int 47 return &b 48 }(), 49 Src: big.NewInt(42), 50 WantDst: ptr(big.NewInt(42)), 51 }, 52 { 53 Dst: new(big.Int), 54 Src: val(big.NewInt(42)), 55 WantErr: errors.New("abi: can't assign big.Int to *big.Int"), 56 }, 57 58 // uint 59 { 60 Dst: ptr[uint](0), 61 Src: uint(42), 62 WantDst: ptr[uint](42), 63 }, 64 { 65 Dst: ptr[uint](0), 66 Src: ptr[uint](42), 67 WantErr: errors.New("abi: unsupported src type *uint"), 68 }, 69 { 70 Dst: ptr(ptr[uint](0)), 71 Src: uint(42), 72 WantDst: ptr(ptr[uint](42)), 73 }, 74 { 75 Dst: uint(0), 76 Src: uint(42), 77 WantErr: errors.New("abi: decode non-pointer uint"), 78 }, 79 { 80 Dst: ptr[uint32](0), 81 Src: uint64(42), 82 WantErr: errors.New("abi: can't assign uint64 to *uint32"), 83 }, 84 85 // bytes 86 { 87 Dst: ptr(make([]byte, 0)), 88 Src: []byte{0xc0, 0xfe}, 89 WantDst: ptr([]byte{0xc0, 0xfe}), 90 }, 91 92 // slices 93 { 94 Dst: ptr(make([]common.Address, 0)), 95 Src: []common.Address{{1}, {2}, {3}}, 96 WantDst: ptr([]common.Address{{1}, {2}, {3}}), 97 }, 98 { 99 Dst: func() *[]common.Address { 100 var s []common.Address 101 return &s 102 }(), 103 Src: []common.Address{{1}, {2}, {3}}, 104 WantDst: ptr([]common.Address{{1}, {2}, {3}}), 105 }, 106 107 // arrays 108 { 109 Dst: ptr([3]common.Address{}), 110 Src: [3]common.Address{{1}, {2}, {3}}, 111 WantDst: ptr([3]common.Address{{1}, {2}, {3}}), 112 }, 113 { 114 Dst: func() *[3]common.Address { 115 var a [3]common.Address 116 return &a 117 }(), 118 Src: [3]common.Address{{1}, {2}, {3}}, 119 WantDst: ptr([3]common.Address{{1}, {2}, {3}}), 120 }, 121 122 // 2d slices/arrays 123 { 124 Dst: ptr(make([][]common.Address, 0)), 125 Src: [][]common.Address{{{1}, {2}}, {{2}, {3}}}, 126 WantDst: ptr([][]common.Address{{{1}, {2}}, {{2}, {3}}}), 127 }, 128 { 129 Dst: func() *[][]common.Address { 130 var s [][]common.Address 131 return &s 132 }(), 133 Src: [][]common.Address{{{1}, {2}}, {{2}, {3}}}, 134 WantDst: ptr([][]common.Address{{{1}, {2}}, {{2}, {3}}}), 135 }, 136 { 137 Dst: ptr(make([][2]common.Address, 0)), 138 Src: [][2]common.Address{{{1}, {2}}, {{2}, {3}}}, 139 WantDst: ptr([][2]common.Address{{{1}, {2}}, {{2}, {3}}}), 140 }, 141 { 142 Dst: ptr([2][]common.Address{}), 143 Src: [2][]common.Address{{{1}, {2}}, {{2}, {3}}}, 144 WantDst: ptr([2][]common.Address{{{1}, {2}}, {{2}, {3}}}), 145 }, 146 { 147 Dst: ptr([2][2]common.Address{}), 148 Src: [2][2]common.Address{{{1}, {2}}, {{2}, {3}}}, 149 WantDst: ptr([2][2]common.Address{{{1}, {2}}, {{2}, {3}}}), 150 }, 151 152 // tuples 153 { 154 Dst: new(tuple0), 155 Src: struct { 156 Uint *big.Int 157 Addr common.Address 158 }{Uint: big.NewInt(1), Addr: common.Address{1}}, 159 WantDst: &tuple0{Uint: big.NewInt(1), Addr: common.Address{1}}, 160 }, 161 { 162 Dst: new(tuple0), 163 Src: tuple0{Uint: big.NewInt(1), Addr: common.Address{1}}, 164 WantDst: &tuple0{Uint: big.NewInt(1), Addr: common.Address{1}}, 165 }, 166 { 167 Dst: ptr(new(tuple0)), 168 Src: struct { 169 Uint *big.Int 170 Addr common.Address 171 }{Uint: big.NewInt(1), Addr: common.Address{1}}, 172 WantDst: ptr(&tuple0{Uint: big.NewInt(1), Addr: common.Address{1}}), 173 }, 174 { 175 Dst: new(tuple0), 176 Src: struct { 177 Uint *big.Int 178 }{Uint: big.NewInt(1)}, 179 WantDst: &tuple0{Uint: big.NewInt(1)}, 180 }, 181 { 182 Dst: new(tuple1), 183 Src: struct { 184 Uint *big.Int 185 Addr common.Address 186 }{Uint: big.NewInt(1), Addr: common.Address{1}}, 187 WantDst: &tuple1{Uint: big.NewInt(1), XAddr: common.Address{1}}, 188 }, 189 { 190 Dst: new(tuple2), 191 Src: struct { 192 Uint *big.Int 193 Tuple struct { 194 Uint *big.Int 195 Addr common.Address 196 } 197 }{Uint: big.NewInt(1), Tuple: struct { 198 Uint *big.Int 199 Addr common.Address 200 }{Uint: big.NewInt(1), Addr: common.Address{1}}}, 201 WantDst: &tuple2{Uint: big.NewInt(1), Tuple: &tuple0{Uint: big.NewInt(1), Addr: common.Address{1}}}, 202 }, 203 204 // tuple with nested tuple slice 205 { 206 Dst: new(tuple3), 207 Src: struct { 208 Uint *big.Int 209 Tuple []struct { 210 Uint *big.Int 211 Addr common.Address 212 } 213 }{Uint: big.NewInt(1), Tuple: []struct { 214 Uint *big.Int 215 Addr common.Address 216 }{ 217 {Uint: big.NewInt(1), Addr: common.Address{1}}, 218 {Uint: big.NewInt(2), Addr: common.Address{2}}, 219 }}, 220 WantDst: &tuple3{Uint: big.NewInt(1), Tuple: []*tuple0{ 221 {Uint: big.NewInt(1), Addr: common.Address{1}}, 222 {Uint: big.NewInt(2), Addr: common.Address{2}}, 223 }}, 224 }, 225 226 // tuple slice 227 { 228 Dst: ptr(make([]*tuple0, 0)), 229 Src: []struct { 230 Uint *big.Int 231 Addr common.Address 232 }{ 233 {Uint: big.NewInt(1), Addr: common.Address{1}}, 234 {Uint: big.NewInt(2), Addr: common.Address{2}}, 235 }, 236 WantDst: ptr([]*tuple0{ 237 {Uint: big.NewInt(1), Addr: common.Address{1}}, 238 {Uint: big.NewInt(2), Addr: common.Address{2}}, 239 }), 240 }, 241 { 242 Dst: func() *[]*tuple0 { 243 var s []*tuple0 244 return &s 245 }(), 246 Src: []struct { 247 Uint *big.Int 248 Addr common.Address 249 }{ 250 {Uint: big.NewInt(1), Addr: common.Address{1}}, 251 {Uint: big.NewInt(2), Addr: common.Address{2}}, 252 }, 253 WantDst: ptr([]*tuple0{ 254 {Uint: big.NewInt(1), Addr: common.Address{1}}, 255 {Uint: big.NewInt(2), Addr: common.Address{2}}, 256 }), 257 }, 258 259 // tuple array 260 { 261 Dst: ptr([2]*tuple0{}), 262 Src: [2]struct { 263 Uint *big.Int 264 Addr common.Address 265 }{ 266 {Uint: big.NewInt(1), Addr: common.Address{1}}, 267 {Uint: big.NewInt(2), Addr: common.Address{2}}, 268 }, 269 WantDst: ptr([2]*tuple0{ 270 {Uint: big.NewInt(1), Addr: common.Address{1}}, 271 {Uint: big.NewInt(2), Addr: common.Address{2}}, 272 }), 273 }, 274 { 275 Dst: func() *[2]*tuple0 { 276 var s [2]*tuple0 277 return &s 278 }(), 279 Src: [2]struct { 280 Uint *big.Int 281 Addr common.Address 282 }{ 283 {Uint: big.NewInt(1), Addr: common.Address{1}}, 284 {Uint: big.NewInt(2), Addr: common.Address{2}}, 285 }, 286 WantDst: ptr([2]*tuple0{ 287 {Uint: big.NewInt(1), Addr: common.Address{1}}, 288 {Uint: big.NewInt(2), Addr: common.Address{2}}, 289 }), 290 }, 291 } 292 293 for i, test := range tests { 294 t.Run(fmt.Sprintf("%d_%T_%T", i, test.Dst, test.Src), func(t *testing.T) { 295 err := Copy(test.Dst, test.Src) 296 if diff := cmp.Diff(test.WantErr, err, 297 internal.EquateErrors(), 298 ); diff != "" { 299 t.Fatalf("Err: (-want +got)\n%s", diff) 300 } else if err != nil { 301 return 302 } 303 304 if diff := cmp.Diff(test.WantDst, test.Dst, 305 cmp.AllowUnexported(big.Int{}), 306 ); diff != "" { 307 t.Fatalf("Dst: (-want +got)\n%s", diff) 308 } 309 }) 310 } 311 } 312 313 func ptr[T any](v T) *T { return &v } 314 func val[T any](v *T) T { return *v } 315 316 type tuple0 struct { 317 Uint *big.Int 318 Addr common.Address 319 } 320 321 type tuple1 struct { 322 Uint *big.Int 323 XAddr common.Address `abi:"addr"` 324 } 325 326 type tuple2 struct { 327 Uint *big.Int 328 Tuple *tuple0 329 } 330 331 type tuple3 struct { 332 Uint *big.Int 333 Tuple []*tuple0 334 }