Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

num_test.gno

3.48 Kb · 130 lines
  1package num
  2
  3import (
  4	"strconv"
  5	"testing"
  6
  7	"gno.land/p/nt/uassert/v0"
  8)
  9
 10const minInt64 = -9223372036854775808
 11
 12func TestDec(t *testing.T) {
 13	cases := []struct {
 14		name     string
 15		v        int64
 16		decimals int
 17		want     string
 18	}{
 19		{"whole", 2000000, 6, "2"},
 20		{"trimmed", 1234500, 6, "1.2345"},
 21		{"full", 1234567, 6, "1.234567"},
 22		{"zero", 0, 6, "0"},
 23		{"sub-unit", 100, 6, "0.0001"},
 24		{"smallest unit", 1, 6, "0.000001"},
 25		{"no decimals", 42, 0, "42"},
 26		{"negative whole", -2000000, 6, "-2"},
 27		{"negative fraction", -1500000, 6, "-1.5"},
 28		{"negative sub-unit", -100, 6, "-0.0001"},
 29		{"negative smallest unit", -1, 6, "-0.000001"},
 30		{"two decimals", 1234, 2, "12.34"},
 31		{"int64 max", 9223372036854775807, 6, "9223372036854.775807"},
 32		{"int64 min", minInt64, 6, "-9223372036854.775808"},
 33	}
 34	for _, tc := range cases {
 35		t.Run(tc.name, func(t *testing.T) {
 36			uassert.Equal(t, tc.want, Dec(tc.v, tc.decimals))
 37		})
 38	}
 39}
 40
 41func TestDecFixedKeepsWidth(t *testing.T) {
 42	cases := []struct {
 43		v    int64
 44		want string
 45	}{
 46		{2000000, "2.000000"},
 47		{1234500, "1.234500"},
 48		{0, "0.000000"},
 49		{-1, "-0.000001"},
 50	}
 51	for _, tc := range cases {
 52		uassert.Equal(t, tc.want, DecFixed(tc.v, 6))
 53	}
 54}
 55
 56// TestEveryDecimalStringParsesBack is the invariant the hand-rolled copies
 57// break: whatever comes out must be a number again. "-1." and "0.999" for a
 58// negative input both fail here, which is what the two live implementations
 59// return.
 60func TestEveryDecimalStringParsesBack(t *testing.T) {
 61	values := []int64{
 62		0, 1, -1, 100, -100, 999999, -999999, 1000000, -1000000,
 63		1234567, -1234567, 9223372036854775807, minInt64,
 64	}
 65	for _, v := range values {
 66		for _, fixed := range []bool{false, true} {
 67			got := dec(v, 6, fixed)
 68			f, err := strconv.ParseFloat(got, 64)
 69			if err != nil {
 70				t.Errorf("dec(%d, 6, %t) = %q, not a number: %v", v, fixed, got, err)
 71				continue
 72			}
 73			if (v < 0) != (f < 0) && f != 0 {
 74				t.Errorf("dec(%d, 6, %t) = %q, sign flipped", v, fixed, got)
 75			}
 76		}
 77	}
 78}
 79
 80// TestMagnitudeSurvivesTheInt64Minimum pins the one input that makes the
 81// obvious implementations fail. `-v` on the minimum is the minimum again, so a
 82// `if v < 0 { v = -v }` keeps it negative and a recursive `"-" + f(-v)` never
 83// terminates. A mainnet realm does the second.
 84func TestMagnitudeSurvivesTheInt64Minimum(t *testing.T) {
 85	neg, m := mag(minInt64)
 86	uassert.True(t, neg)
 87	uassert.Equal(t, "9223372036854775808", strconv.FormatUint(m, 10))
 88}
 89
 90func TestGNOT(t *testing.T) {
 91	uassert.Equal(t, "1.234567", GNOT(1234567))
 92	uassert.Equal(t, "1.234567 GNOT", GNOTf(1234567))
 93	uassert.Equal(t, "0 GNOT", GNOTf(0))
 94	uassert.Equal(t, "-1.5 GNOT", GNOTf(-1500000))
 95}
 96
 97func TestPct(t *testing.T) {
 98	uassert.Equal(t, "12.34%", Pct(1234))
 99	uassert.Equal(t, "1%", Pct(100))
100	uassert.Equal(t, "0.01%", Pct(1))
101	uassert.Equal(t, "0%", Pct(0))
102	uassert.Equal(t, "-12.34%", Pct(-1234))
103}
104
105func TestPad(t *testing.T) {
106	cases := []struct {
107		v     int64
108		width int
109		want  string
110	}{
111		{7, 3, "007"},
112		{123, 3, "123"},
113		{1234, 3, "1234"},
114		{0, 2, "00"},
115		{7, 0, "7"},
116		{-7, 3, "-007"},
117		{minInt64, 3, "-9223372036854775808"},
118	}
119	for _, tc := range cases {
120		uassert.Equal(t, tc.want, Pad(tc.v, tc.width))
121	}
122}
123
124func TestDecRejectsAnImpossibleScale(cur realm, t *testing.T) {
125	msg := "num: decimals out of range [0, 19]"
126	uassert.PanicsWithMessage(t, cur, msg, func() { Dec(1, -1) })
127	uassert.PanicsWithMessage(t, cur, msg, func() { Dec(1, 20) })
128	uassert.NotPanics(t, cur, func() { Dec(1, 0) })
129	uassert.NotPanics(t, cur, func() { Dec(1, 19) })
130}