github.com/lmittmann/w3@v0.20.0/util_test.go (about)

     1  package w3_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math/big"
     7  	"strconv"
     8  	"testing"
     9  
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/lmittmann/w3"
    12  )
    13  
    14  func ExampleI() {
    15  	fmt.Printf("%v wei\n", w3.I("0x1111d67bb1bb0000"))
    16  	fmt.Printf("%v wei\n", w3.I("1230000000000000000"))
    17  	fmt.Printf("%v wei\n", w3.I("1.23 ether"))
    18  	fmt.Printf("%v wei\n", w3.I("1.23 gwei"))
    19  	// Output:
    20  	// 1230000000000000000 wei
    21  	// 1230000000000000000 wei
    22  	// 1230000000000000000 wei
    23  	// 1230000000 wei
    24  }
    25  
    26  func ExampleFromWei() {
    27  	wei := big.NewInt(1_230000000_000000000)
    28  	fmt.Printf("%s Ether\n", w3.FromWei(wei, 18))
    29  	// Output:
    30  	// 1.23 Ether
    31  }
    32  
    33  func TestA(t *testing.T) {
    34  	tests := []struct {
    35  		HexAddress  string
    36  		WantPanic   string
    37  		WantAddress common.Address
    38  	}{
    39  		{
    40  			HexAddress:  "0x000000000000000000000000000000000000c0Fe",
    41  			WantAddress: common.HexToAddress("0x000000000000000000000000000000000000c0Fe"),
    42  		},
    43  		{
    44  			HexAddress:  "000000000000000000000000000000000000c0Fe",
    45  			WantAddress: common.HexToAddress("0x000000000000000000000000000000000000c0Fe"),
    46  		},
    47  		{HexAddress: "0xcofe", WantPanic: `invalid address "cofe": encoding/hex: invalid byte: U+006F 'o'`},
    48  		{HexAddress: "0xc0Fe", WantPanic: `invalid address "c0Fe": must have 20 bytes`},
    49  	}
    50  
    51  	for i, test := range tests {
    52  		t.Run(strconv.Itoa(i), func(t *testing.T) {
    53  			defer func() {
    54  				var gotPanic string
    55  				if r := recover(); r != nil {
    56  					gotPanic = r.(string)
    57  				}
    58  				if test.WantPanic != gotPanic {
    59  					t.Fatalf("want %q, got %q", test.WantPanic, gotPanic)
    60  				}
    61  			}()
    62  
    63  			gotAddr := w3.A(test.HexAddress)
    64  			if test.WantPanic == "" && test.WantAddress != gotAddr {
    65  				t.Fatalf("want: %s, got: %s", test.WantAddress, gotAddr)
    66  			}
    67  		})
    68  	}
    69  }
    70  
    71  func TestB(t *testing.T) {
    72  	tests := []struct {
    73  		HexBytes  string
    74  		WantPanic string
    75  		WantBytes []byte
    76  	}{
    77  		{HexBytes: "0xc0fe", WantBytes: []byte{0xc0, 0xfe}},
    78  		{HexBytes: "c0fe", WantBytes: []byte{0xc0, 0xfe}},
    79  		{HexBytes: "0xcofe", WantPanic: `invalid bytes "cofe": encoding/hex: invalid byte: U+006F 'o'`},
    80  		{HexBytes: "0xc0f", WantPanic: `invalid bytes "c0f": encoding/hex: odd length hex string`},
    81  	}
    82  
    83  	for i, test := range tests {
    84  		t.Run(strconv.Itoa(i), func(t *testing.T) {
    85  			defer func() {
    86  				var gotPanic string
    87  				if r := recover(); r != nil {
    88  					gotPanic = r.(string)
    89  				}
    90  				if test.WantPanic != gotPanic {
    91  					t.Fatalf("want %q, got %q", test.WantPanic, gotPanic)
    92  				}
    93  			}()
    94  
    95  			gotBytes := w3.B(test.HexBytes)
    96  			if test.WantPanic == "" && !bytes.Equal(test.WantBytes, gotBytes) {
    97  				t.Fatalf("want: %x, got: %x", test.WantBytes, gotBytes)
    98  			}
    99  		})
   100  	}
   101  }
   102  
   103  func TestH(t *testing.T) {
   104  	tests := []struct {
   105  		HexHash   string
   106  		WantPanic string
   107  		WantHash  common.Hash
   108  	}{
   109  		{
   110  			HexHash:  "0x000000000000000000000000000000000000000000000000000000000000c0fe",
   111  			WantHash: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000c0fe"),
   112  		},
   113  		{
   114  			HexHash:  "000000000000000000000000000000000000000000000000000000000000c0fe",
   115  			WantHash: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000c0fe"),
   116  		},
   117  		{HexHash: "0xcofe", WantPanic: `invalid hash "cofe": encoding/hex: invalid byte: U+006F 'o'`},
   118  		{HexHash: "0xc0fe", WantPanic: `invalid hash "c0fe": must have 32 bytes`},
   119  	}
   120  
   121  	for i, test := range tests {
   122  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   123  			defer func() {
   124  				var gotPanic string
   125  				if r := recover(); r != nil {
   126  					gotPanic = r.(string)
   127  				}
   128  				if test.WantPanic != gotPanic {
   129  					t.Fatalf("want %q, got %q", test.WantPanic, gotPanic)
   130  				}
   131  			}()
   132  
   133  			gotHash := w3.H(test.HexHash)
   134  			if test.WantPanic == "" && test.WantHash != gotHash {
   135  				t.Fatalf("want: %s, got: %s", test.WantHash, gotHash)
   136  			}
   137  		})
   138  	}
   139  }
   140  
   141  func TestI(t *testing.T) {
   142  	tests := []struct {
   143  		StrInt    string
   144  		WantPanic string
   145  		WantBig   *big.Int
   146  	}{
   147  		// hex big's
   148  		{StrInt: "0x0", WantBig: big.NewInt(0)},
   149  		{StrInt: "0x1", WantBig: big.NewInt(1)},
   150  		{StrInt: "0xff", WantBig: big.NewInt(255)},
   151  		{StrInt: "0xO", WantPanic: `invalid hex big "0xO"`},
   152  
   153  		// int big's
   154  		{StrInt: "0", WantBig: big.NewInt(0)},
   155  		{StrInt: "1", WantBig: big.NewInt(1)},
   156  		{StrInt: "255", WantBig: big.NewInt(255)},
   157  		{StrInt: "X", WantPanic: `str big "X" must be number`},
   158  		{StrInt: "888916043834286157872", WantBig: strBig("888916043834286157872")},
   159  
   160  		// unit big's
   161  		{StrInt: "0 ether", WantBig: big.NewInt(0)},
   162  		{StrInt: "0 eth", WantBig: big.NewInt(0)},
   163  		{StrInt: "0 gwei", WantBig: big.NewInt(0)},
   164  		{StrInt: "1 ether", WantBig: big.NewInt(1_000000000_000000000)},
   165  		{StrInt: "1 eth", WantBig: big.NewInt(1_000000000_000000000)},
   166  		{StrInt: "1ether", WantPanic: `str big "1ether" must be number`},
   167  		{StrInt: "1.2 ether", WantBig: big.NewInt(1_200000000_000000000)},
   168  		{StrInt: "01.2 ether", WantBig: big.NewInt(1_200000000_000000000)},
   169  		{StrInt: "1.20 ether", WantBig: big.NewInt(1_200000000_000000000)},
   170  		{StrInt: "1.200000000000000003 ether", WantBig: big.NewInt(1_200000000_000000003)},
   171  		{StrInt: "1.2000000000000000034 ether", WantPanic: `str big "1.2000000000000000034 ether" exceeds precision`},
   172  		{StrInt: "1 gwei", WantBig: big.NewInt(1_000000000)},
   173  		{StrInt: "1.2 gwei", WantBig: big.NewInt(1_200000000)},
   174  		{StrInt: "1.200000003 gwei", WantBig: big.NewInt(1_200000003)},
   175  		{StrInt: "1.2000000034 gwei", WantPanic: `str big "1.2000000034 gwei" exceeds precision`},
   176  		{StrInt: ".", WantPanic: `str big "." must be number`},
   177  		{StrInt: ". ether", WantPanic: `str big ". ether" must be number`},
   178  		{StrInt: "1.", WantPanic: `str big "1." without unit must be integer`},
   179  		{StrInt: "1. ether", WantPanic: `str big "1. ether" must be number`},
   180  		{StrInt: ".1", WantPanic: `str big ".1" must be number`},
   181  		{StrInt: ".1 ether", WantPanic: `str big ".1 ether" must be number`},
   182  		{StrInt: "0.1 ether", WantBig: big.NewInt(100000000_000000000)},
   183  		{StrInt: "0.10 ether", WantBig: big.NewInt(100000000_000000000)},
   184  		{StrInt: "00.10 ether", WantBig: big.NewInt(100000000_000000000)},
   185  		{StrInt: " 1 ether", WantPanic: `str big " 1 ether" must be number`},
   186  		{StrInt: "1 ether ", WantPanic: `str big "1 ether " has invalid unit "ether "`},
   187  		{StrInt: "1  ether", WantPanic: `str big "1  ether" has invalid unit " ether"`},
   188  		{StrInt: "-1", WantBig: big.NewInt(-1)},
   189  	}
   190  
   191  	for i, test := range tests {
   192  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   193  			defer func() {
   194  				var gotPanic string
   195  				if r := recover(); r != nil {
   196  					gotPanic = r.(string)
   197  				}
   198  				if test.WantPanic != gotPanic {
   199  					t.Fatalf("want %q, got %q", test.WantPanic, gotPanic)
   200  				}
   201  			}()
   202  
   203  			gotBig := w3.I(test.StrInt)
   204  			if test.WantPanic == "" && test.WantBig.Cmp(gotBig) != 0 {
   205  				t.Fatalf("want %v, got %v", test.WantBig, gotBig)
   206  			}
   207  		})
   208  	}
   209  }
   210  
   211  func strBig(s string) *big.Int {
   212  	big, _ := new(big.Int).SetString(s, 10)
   213  	return big
   214  }
   215  
   216  func FuzzI(f *testing.F) {
   217  	f.Add([]byte{0x2a})
   218  	f.Fuzz(func(t *testing.T, b []byte) {
   219  		wantBig := new(big.Int).SetBytes(b)
   220  		bigStr := wantBig.String()
   221  		if gotBig := w3.I(bigStr); wantBig.Cmp(gotBig) != 0 {
   222  			t.Fatalf("want %v, got %v", wantBig, gotBig)
   223  		}
   224  
   225  		bigHexstr := wantBig.Text(16)
   226  		if gotBig := w3.I("0x" + bigHexstr); wantBig.Cmp(gotBig) != 0 {
   227  			t.Fatalf("want %v, got %v", wantBig, gotBig)
   228  		}
   229  	})
   230  }
   231  
   232  func BenchmarkI(b *testing.B) {
   233  	benchmarks := []string{
   234  		"0x123456",
   235  		"1.23456 ether",
   236  		"1.000000000000000000 ether",
   237  		"1.000000000000000000123456 ether",
   238  	}
   239  
   240  	for _, bench := range benchmarks {
   241  		b.Run(bench, func(b *testing.B) {
   242  			b.ReportAllocs()
   243  
   244  			for range b.N {
   245  				w3.I(bench)
   246  			}
   247  		})
   248  	}
   249  }
   250  
   251  func TestFromWei(t *testing.T) {
   252  	tests := []struct {
   253  		Wei      *big.Int
   254  		Decimals uint8
   255  		Want     string
   256  	}{
   257  		{nil, 0, "<nil>"},
   258  		{nil, 0, fmt.Sprint(nil)},
   259  		{big.NewInt(0), 0, "0"},
   260  		{big.NewInt(1), 0, "1"},
   261  		{big.NewInt(0), 18, "0"},
   262  		{big.NewInt(1), 18, "0.000000000000000001"},
   263  		{big.NewInt(1000), 18, "0.000000000000001"},
   264  		{big.NewInt(1000000), 18, "0.000000000001"},
   265  		{big.NewInt(1000000000), 18, "0.000000001"},
   266  		{big.NewInt(1000000000000), 18, "0.000001"},
   267  		{big.NewInt(1000000000000000), 18, "0.001"},
   268  		{big.NewInt(1000000000000000000), 18, "1"},
   269  		{big.NewInt(-1), 18, "-0.000000000000000001"},
   270  		{big.NewInt(-1000), 18, "-0.000000000000001"},
   271  		{big.NewInt(-1000000), 18, "-0.000000000001"},
   272  		{big.NewInt(-1000000000), 18, "-0.000000001"},
   273  		{big.NewInt(-1000000000000), 18, "-0.000001"},
   274  		{big.NewInt(-1000000000000000), 18, "-0.001"},
   275  		{big.NewInt(-1000000000000000000), 18, "-1"},
   276  		{big.NewInt(1000000000000000000), 15, "1000"},
   277  		{big.NewInt(1000000000000000000), 12, "1000000"},
   278  		{big.NewInt(1000000000000000000), 9, "1000000000"},
   279  		{big.NewInt(1000000000000000000), 6, "1000000000000"},
   280  		{big.NewInt(1000000000000000000), 3, "1000000000000000"},
   281  		{big.NewInt(1000000000000000000), 0, "1000000000000000000"},
   282  	}
   283  
   284  	for i, test := range tests {
   285  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   286  			got := w3.FromWei(test.Wei, test.Decimals)
   287  			if got != test.Want {
   288  				t.Fatalf("%q != %q", got, test.Want)
   289  			}
   290  		})
   291  	}
   292  }
   293  
   294  func TestBigMin(t *testing.T) {
   295  	tests := []struct {
   296  		A, B, Want *big.Int
   297  	}{
   298  		{big.NewInt(0), big.NewInt(0), big.NewInt(0)},
   299  		{big.NewInt(0), big.NewInt(1), big.NewInt(0)},
   300  		{big.NewInt(1), big.NewInt(0), big.NewInt(0)},
   301  	}
   302  
   303  	for i, test := range tests {
   304  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   305  			got := w3.BigMin(test.A, test.B)
   306  			if test.Want.Cmp(got) != 0 {
   307  				t.Fatalf("want: %v, got: %v", test.Want, got)
   308  			}
   309  		})
   310  	}
   311  }
   312  
   313  func TestBigMax(t *testing.T) {
   314  	tests := []struct {
   315  		A, B, Want *big.Int
   316  	}{
   317  		{big.NewInt(0), big.NewInt(0), big.NewInt(0)},
   318  		{big.NewInt(0), big.NewInt(1), big.NewInt(1)},
   319  		{big.NewInt(1), big.NewInt(0), big.NewInt(1)},
   320  	}
   321  
   322  	for i, test := range tests {
   323  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   324  			got := w3.BigMax(test.A, test.B)
   325  			if test.Want.Cmp(got) != 0 {
   326  				t.Fatalf("want: %v, got: %v", test.Want, got)
   327  			}
   328  		})
   329  	}
   330  }