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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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}