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  }