github.com/cosmos/cosmos-sdk@v0.50.10/x/group/internal/math/dec_test.go (about) 1 package math 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 "pgregory.net/rapid" 9 ) 10 11 func TestDec(t *testing.T) { 12 // Property tests 13 t.Run("TestNewDecFromInt64", rapid.MakeCheck(testDecInt64)) 14 15 // Properties about addition 16 t.Run("TestAddLeftIdentity", rapid.MakeCheck(testAddLeftIdentity)) 17 t.Run("TestAddRightIdentity", rapid.MakeCheck(testAddRightIdentity)) 18 t.Run("TestAddCommutative", rapid.MakeCheck(testAddCommutative)) 19 t.Run("TestAddAssociative", rapid.MakeCheck(testAddAssociative)) 20 21 // Properties about subtraction 22 t.Run("TestSubRightIdentity", rapid.MakeCheck(testSubRightIdentity)) 23 t.Run("TestSubZero", rapid.MakeCheck(testSubZero)) 24 25 // Properties combining operations 26 t.Run("TestSubAdd", rapid.MakeCheck(testSubAdd)) 27 t.Run("TestAddSub", rapid.MakeCheck(testAddSub)) 28 29 // Properties about comparison and equality 30 t.Run("TestCmpInverse", rapid.MakeCheck(testCmpInverse)) 31 t.Run("TestEqualCommutative", rapid.MakeCheck(testEqualCommutative)) 32 33 // Properties about tests on a single Dec 34 t.Run("TestIsNegative", rapid.MakeCheck(testIsNegative)) 35 36 // Unit tests 37 zero := Dec{} 38 one := NewDecFromInt64(1) 39 two := NewDecFromInt64(2) 40 three := NewDecFromInt64(3) 41 four := NewDecFromInt64(4) 42 five := NewDecFromInt64(5) 43 minusOne := NewDecFromInt64(-1) 44 45 onePointOneFive, err := NewDecFromString("1.15") 46 require.NoError(t, err) 47 twoPointThreeFour, err := NewDecFromString("2.34") 48 require.NoError(t, err) 49 threePointFourNine, err := NewDecFromString("3.49") 50 require.NoError(t, err) 51 onePointFourNine, err := NewDecFromString("1.49") 52 require.NoError(t, err) 53 minusFivePointZero, err := NewDecFromString("-5.0") 54 require.NoError(t, err) 55 _, err = NewDecFromString("inf") 56 require.Error(t, err) 57 _, err = NewDecFromString("Infinite") 58 require.Error(t, err) 59 _, err = NewDecFromString("foo") 60 require.Error(t, err) 61 _, err = NewDecFromString("NaN") 62 require.Error(t, err) 63 64 res, err := two.Add(zero) 65 require.NoError(t, err) 66 require.True(t, res.Equal(two)) 67 68 res, err = five.Sub(two) 69 require.NoError(t, err) 70 require.True(t, res.Equal(three)) 71 72 res, err = onePointOneFive.Add(twoPointThreeFour) 73 require.NoError(t, err) 74 require.True(t, res.Equal(threePointFourNine)) 75 76 res, err = threePointFourNine.Sub(two) 77 require.NoError(t, err) 78 require.True(t, res.Equal(onePointFourNine)) 79 80 res, err = minusOne.Sub(four) 81 require.NoError(t, err) 82 require.True(t, res.Equal(minusFivePointZero)) 83 84 _, err = four.Quo(zero) 85 require.Error(t, err) 86 87 res, err = four.Quo(two) 88 require.NoError(t, err) 89 require.True(t, res.Equal(two)) 90 91 require.False(t, zero.IsNegative()) 92 require.False(t, one.IsNegative()) 93 require.True(t, minusOne.IsNegative()) 94 } 95 96 var genDec *rapid.Generator[Dec] = rapid.Custom(func(t *rapid.T) Dec { 97 f := rapid.Float64().Draw(t, "f") 98 dec, err := NewDecFromString(fmt.Sprintf("%g", f)) 99 require.NoError(t, err) 100 return dec 101 }) 102 103 // A Dec value and the float used to create it 104 type floatAndDec struct { 105 float float64 106 dec Dec 107 } 108 109 // Generate a Dec value along with the float used to create it 110 var genFloatAndDec *rapid.Generator[floatAndDec] = rapid.Custom(func(t *rapid.T) floatAndDec { 111 f := rapid.Float64().Draw(t, "f") 112 dec, err := NewDecFromString(fmt.Sprintf("%g", f)) 113 require.NoError(t, err) 114 return floatAndDec{f, dec} 115 }) 116 117 // Property: n == NewDecFromInt64(n).Int64() 118 func testDecInt64(t *rapid.T) { 119 nIn := rapid.Int64().Draw(t, "n") 120 nOut, err := NewDecFromInt64(nIn).Int64() 121 122 require.NoError(t, err) 123 require.Equal(t, nIn, nOut) 124 } 125 126 // Property: 0 + a == a 127 func testAddLeftIdentity(t *rapid.T) { 128 a := genDec.Draw(t, "a") 129 zero := NewDecFromInt64(0) 130 131 b, err := zero.Add(a) 132 require.NoError(t, err) 133 134 require.True(t, a.Equal(b)) 135 } 136 137 // Property: a + 0 == a 138 func testAddRightIdentity(t *rapid.T) { 139 a := genDec.Draw(t, "a") 140 zero := NewDecFromInt64(0) 141 142 b, err := a.Add(zero) 143 require.NoError(t, err) 144 145 require.True(t, a.Equal(b)) 146 } 147 148 // Property: a + b == b + a 149 func testAddCommutative(t *rapid.T) { 150 a := genDec.Draw(t, "a") 151 b := genDec.Draw(t, "b") 152 153 c, err := a.Add(b) 154 require.NoError(t, err) 155 156 d, err := b.Add(a) 157 require.NoError(t, err) 158 159 require.True(t, c.Equal(d)) 160 } 161 162 // Property: (a + b) + c == a + (b + c) 163 func testAddAssociative(t *rapid.T) { 164 a := genDec.Draw(t, "a") 165 b := genDec.Draw(t, "b") 166 c := genDec.Draw(t, "c") 167 168 // (a + b) + c 169 d, err := a.Add(b) 170 require.NoError(t, err) 171 172 e, err := d.Add(c) 173 require.NoError(t, err) 174 175 // a + (b + c) 176 f, err := b.Add(c) 177 require.NoError(t, err) 178 179 g, err := a.Add(f) 180 require.NoError(t, err) 181 182 require.True(t, e.Equal(g)) 183 } 184 185 // Property: a - 0 == a 186 func testSubRightIdentity(t *rapid.T) { 187 a := genDec.Draw(t, "a") 188 zero := NewDecFromInt64(0) 189 190 b, err := a.Sub(zero) 191 require.NoError(t, err) 192 193 require.True(t, a.Equal(b)) 194 } 195 196 // Property: a - a == 0 197 func testSubZero(t *rapid.T) { 198 a := genDec.Draw(t, "a") 199 zero := NewDecFromInt64(0) 200 201 b, err := a.Sub(a) 202 require.NoError(t, err) 203 204 require.True(t, b.Equal(zero)) 205 } 206 207 // Property: (a - b) + b == a 208 func testSubAdd(t *rapid.T) { 209 a := genDec.Draw(t, "a") 210 b := genDec.Draw(t, "b") 211 212 c, err := a.Sub(b) 213 require.NoError(t, err) 214 215 d, err := c.Add(b) 216 require.NoError(t, err) 217 218 require.True(t, a.Equal(d)) 219 } 220 221 // Property: (a + b) - b == a 222 func testAddSub(t *rapid.T) { 223 a := genDec.Draw(t, "a") 224 b := genDec.Draw(t, "b") 225 226 c, err := a.Add(b) 227 require.NoError(t, err) 228 229 d, err := c.Sub(b) 230 require.NoError(t, err) 231 232 require.True(t, a.Equal(d)) 233 } 234 235 // Property: Cmp(a, b) == -Cmp(b, a) 236 func testCmpInverse(t *rapid.T) { 237 a := genDec.Draw(t, "a") 238 b := genDec.Draw(t, "b") 239 240 require.Equal(t, a.Cmp(b), -b.Cmp(a)) 241 } 242 243 // Property: Equal(a, b) == Equal(b, a) 244 func testEqualCommutative(t *rapid.T) { 245 a := genDec.Draw(t, "a") 246 b := genDec.Draw(t, "b") 247 248 require.Equal(t, a.Equal(b), b.Equal(a)) 249 } 250 251 // Property: isNegative(f) == isNegative(NewDecFromString(f.String())) 252 func testIsNegative(t *rapid.T) { 253 floatAndDec := genFloatAndDec.Draw(t, "floatAndDec") 254 f, dec := floatAndDec.float, floatAndDec.dec 255 256 require.Equal(t, f < 0, dec.IsNegative()) 257 }