cosmos-sdk/types/rational_test.go

275 lines
8.3 KiB
Go
Raw Normal View History

2018-02-20 03:31:37 -08:00
package types
import (
"encoding/json"
"math/big"
"testing"
2018-02-23 05:13:55 -08:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2018-02-20 03:31:37 -08:00
)
func TestNew(t *testing.T) {
2018-02-23 05:13:55 -08:00
assert.Equal(t, NewRat(1), NewRat(1, 1))
assert.Equal(t, NewRat(100), NewRat(100, 1))
assert.Equal(t, NewRat(-1), NewRat(-1, 1))
assert.Equal(t, NewRat(-100), NewRat(-100, 1))
assert.Equal(t, NewRat(0), NewRat(0, 1))
2018-02-20 03:31:37 -08:00
// do not allow for more than 2 variables
2018-02-23 05:13:55 -08:00
assert.Panics(t, func() { NewRat(1, 1, 1) })
2018-02-20 03:31:37 -08:00
}
func TestNewFromDecimal(t *testing.T) {
tests := []struct {
decimalStr string
expErr bool
exp Rat
}{
2018-02-23 05:13:55 -08:00
{"0", false, NewRat(0)},
{"1", false, NewRat(1)},
{"1.1", false, NewRat(11, 10)},
{"0.75", false, NewRat(3, 4)},
{"0.8", false, NewRat(4, 5)},
{"0.11111", false, NewRat(11111, 100000)},
2018-02-20 03:31:37 -08:00
{".", true, Rat{}},
{".0", true, Rat{}},
{"1.", true, Rat{}},
{"foobar", true, Rat{}},
{"0.foobar", true, Rat{}},
{"0.foobar.", true, Rat{}},
}
for _, tc := range tests {
2018-02-23 05:13:55 -08:00
res, err := NewRatFromDecimal(tc.decimalStr)
2018-02-20 03:31:37 -08:00
if tc.expErr {
2018-02-23 05:13:55 -08:00
assert.NotNil(t, err, tc.decimalStr)
2018-02-20 03:31:37 -08:00
} else {
2018-02-23 05:13:55 -08:00
assert.Nil(t, err)
assert.True(t, res.Equal(tc.exp))
2018-02-20 03:31:37 -08:00
}
// negative tc
2018-02-23 05:13:55 -08:00
res, err = NewRatFromDecimal("-" + tc.decimalStr)
2018-02-20 03:31:37 -08:00
if tc.expErr {
2018-02-23 05:13:55 -08:00
assert.NotNil(t, err, tc.decimalStr)
2018-02-20 03:31:37 -08:00
} else {
2018-02-23 05:13:55 -08:00
assert.Nil(t, err)
assert.True(t, res.Equal(tc.exp.Mul(NewRat(-1))))
2018-02-20 03:31:37 -08:00
}
}
}
func TestEqualities(t *testing.T) {
tests := []struct {
r1, r2 Rat
gt, lt, eq bool
}{
2018-02-23 05:13:55 -08:00
{NewRat(0), NewRat(0), false, false, true},
{NewRat(0, 100), NewRat(0, 10000), false, false, true},
{NewRat(100), NewRat(100), false, false, true},
{NewRat(-100), NewRat(-100), false, false, true},
{NewRat(-100, -1), NewRat(100), false, false, true},
{NewRat(-1, 1), NewRat(1, -1), false, false, true},
{NewRat(1, -1), NewRat(-1, 1), false, false, true},
{NewRat(3, 7), NewRat(3, 7), false, false, true},
{NewRat(0), NewRat(3, 7), false, true, false},
{NewRat(0), NewRat(100), false, true, false},
{NewRat(-1), NewRat(3, 7), false, true, false},
{NewRat(-1), NewRat(100), false, true, false},
{NewRat(1, 7), NewRat(100), false, true, false},
{NewRat(1, 7), NewRat(3, 7), false, true, false},
{NewRat(-3, 7), NewRat(-1, 7), false, true, false},
{NewRat(3, 7), NewRat(0), true, false, false},
{NewRat(100), NewRat(0), true, false, false},
{NewRat(3, 7), NewRat(-1), true, false, false},
{NewRat(100), NewRat(-1), true, false, false},
{NewRat(100), NewRat(1, 7), true, false, false},
{NewRat(3, 7), NewRat(1, 7), true, false, false},
{NewRat(-1, 7), NewRat(-3, 7), true, false, false},
2018-02-20 03:31:37 -08:00
}
for _, tc := range tests {
2018-02-23 05:13:55 -08:00
assert.Equal(t, tc.gt, tc.r1.GT(tc.r2))
assert.Equal(t, tc.lt, tc.r1.LT(tc.r2))
assert.Equal(t, tc.eq, tc.r1.Equal(tc.r2))
2018-02-20 03:31:37 -08:00
}
}
func TestArithmatic(t *testing.T) {
tests := []struct {
r1, r2 Rat
resMul, resDiv, resAdd, resSub Rat
}{
2018-02-23 05:13:55 -08:00
// r1 r2 MUL DIV ADD SUB
{NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0)},
{NewRat(1), NewRat(0), NewRat(0), NewRat(0), NewRat(1), NewRat(1)},
{NewRat(0), NewRat(1), NewRat(0), NewRat(0), NewRat(1), NewRat(-1)},
{NewRat(0), NewRat(-1), NewRat(0), NewRat(0), NewRat(-1), NewRat(1)},
{NewRat(-1), NewRat(0), NewRat(0), NewRat(0), NewRat(-1), NewRat(-1)},
{NewRat(1), NewRat(1), NewRat(1), NewRat(1), NewRat(2), NewRat(0)},
{NewRat(-1), NewRat(-1), NewRat(1), NewRat(1), NewRat(-2), NewRat(0)},
{NewRat(1), NewRat(-1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(2)},
{NewRat(-1), NewRat(1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(-2)},
{NewRat(3), NewRat(7), NewRat(21), NewRat(3, 7), NewRat(10), NewRat(-4)},
{NewRat(2), NewRat(4), NewRat(8), NewRat(1, 2), NewRat(6), NewRat(-2)},
{NewRat(100), NewRat(100), NewRat(10000), NewRat(1), NewRat(200), NewRat(0)},
{NewRat(3, 2), NewRat(3, 2), NewRat(9, 4), NewRat(1), NewRat(3), NewRat(0)},
{NewRat(3, 7), NewRat(7, 3), NewRat(1), NewRat(9, 49), NewRat(58, 21), NewRat(-40, 21)},
{NewRat(1, 21), NewRat(11, 5), NewRat(11, 105), NewRat(5, 231), NewRat(236, 105), NewRat(-226, 105)},
{NewRat(-21), NewRat(3, 7), NewRat(-9), NewRat(-49), NewRat(-144, 7), NewRat(-150, 7)},
{NewRat(100), NewRat(1, 7), NewRat(100, 7), NewRat(700), NewRat(701, 7), NewRat(699, 7)},
2018-02-20 03:31:37 -08:00
}
for _, tc := range tests {
2018-02-23 05:13:55 -08:00
assert.True(t, tc.resMul.Equal(tc.r1.Mul(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())
assert.True(t, tc.resAdd.Equal(tc.r1.Add(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())
assert.True(t, tc.resSub.Equal(tc.r1.Sub(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())
2018-02-20 03:31:37 -08:00
if tc.r2.Num() == 0 { // panic for divide by zero
2018-02-23 05:13:55 -08:00
assert.Panics(t, func() { tc.r1.Quo(tc.r2) })
2018-02-20 03:31:37 -08:00
} else {
2018-02-23 05:13:55 -08:00
assert.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())
2018-02-20 03:31:37 -08:00
}
}
}
func TestEvaluate(t *testing.T) {
tests := []struct {
r1 Rat
res int64
}{
2018-02-23 05:13:55 -08:00
{NewRat(0), 0},
{NewRat(1), 1},
{NewRat(1, 4), 0},
{NewRat(1, 2), 0},
{NewRat(3, 4), 1},
{NewRat(5, 6), 1},
{NewRat(3, 2), 2},
{NewRat(5, 2), 2},
{NewRat(6, 11), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even
{NewRat(17, 11), 2}, // 1.545
{NewRat(5, 11), 0},
{NewRat(16, 11), 1},
{NewRat(113, 12), 9},
2018-02-20 03:31:37 -08:00
}
for _, tc := range tests {
2018-02-23 05:13:55 -08:00
assert.Equal(t, tc.res, tc.r1.Evaluate(), "%v", tc.r1)
assert.Equal(t, tc.res*-1, tc.r1.Mul(NewRat(-1)).Evaluate(), "%v", tc.r1.Mul(NewRat(-1)))
2018-02-20 03:31:37 -08:00
}
}
func TestRound(t *testing.T) {
many3 := "333333333333333333333333333333333333333333333"
many7 := "777777777777777777777777777777777777777777777"
big3, worked := new(big.Int).SetString(many3, 10)
2018-02-23 05:13:55 -08:00
require.True(t, worked)
2018-02-20 03:31:37 -08:00
big7, worked := new(big.Int).SetString(many7, 10)
2018-02-23 05:13:55 -08:00
require.True(t, worked)
2018-02-20 03:31:37 -08:00
tests := []struct {
r1, res Rat
precFactor int64
}{
2018-02-23 05:13:55 -08:00
{NewRat(333, 777), NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(4285714286, 10000000000), 10000000000},
{NewRat(1, 2), NewRat(1, 2), 1000},
2018-02-20 03:31:37 -08:00
}
for _, tc := range tests {
2018-02-23 05:13:55 -08:00
assert.Equal(t, tc.res, tc.r1.Round(tc.precFactor), "%v", tc.r1)
negR1, negRes := tc.r1.Mul(NewRat(-1)), tc.res.Mul(NewRat(-1))
assert.Equal(t, negRes, negR1.Round(tc.precFactor), "%v", negR1)
2018-02-20 03:31:37 -08:00
}
}
func TestZeroSerializationJSON(t *testing.T) {
var r Rat
err := json.Unmarshal([]byte("{\"numerator\":0,\"denominator\":1}"), &r)
2018-02-23 05:13:55 -08:00
assert.Nil(t, err)
2018-02-20 03:31:37 -08:00
err = json.Unmarshal([]byte("{\"numerator\":0,\"denominator\":0}"), &r)
2018-02-23 05:13:55 -08:00
assert.NotNil(t, err)
2018-02-20 03:31:37 -08:00
err = json.Unmarshal([]byte("{\"numerator\":1,\"denominator\":0}"), &r)
2018-02-23 05:13:55 -08:00
assert.NotNil(t, err)
2018-02-20 03:31:37 -08:00
err = json.Unmarshal([]byte("{}"), &r)
2018-02-23 05:13:55 -08:00
assert.NotNil(t, err)
2018-02-20 03:31:37 -08:00
}
func TestSerializationJSON(t *testing.T) {
2018-02-23 05:13:55 -08:00
r := NewRat(1, 3)
2018-02-20 03:31:37 -08:00
rMarshal, err := json.Marshal(r)
2018-02-23 05:13:55 -08:00
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
var rUnmarshal Rat
err = json.Unmarshal(rMarshal, &rUnmarshal)
2018-02-23 05:13:55 -08:00
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
assert.True(t, r.Equal(rUnmarshal), "original: %v, unmarshalled: %v", r, rUnmarshal)
2018-02-20 03:31:37 -08:00
}
func TestSerializationGoWire(t *testing.T) {
2018-02-23 05:13:55 -08:00
r := NewRat(1, 3)
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
rMarshal, err := ratCdc.MarshalJSON(r)
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
var rUnmarshal Rat
2018-02-23 05:13:55 -08:00
err = ratCdc.UnmarshalJSON(rMarshal, &rUnmarshal)
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
assert.True(t, r.Equal(rUnmarshal), "original: %v, unmarshalled: %v", r, rUnmarshal)
2018-02-20 03:31:37 -08:00
}
type testEmbedStruct struct {
Field1 string `json:"f1"`
Field2 int `json:"f2"`
Field3 Rat `json:"f3"`
}
func TestEmbeddedStructSerializationGoWire(t *testing.T) {
2018-02-23 05:13:55 -08:00
r := testEmbedStruct{"foo", 10, NewRat(1, 3)}
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
rMarshal, err := ratCdc.MarshalJSON(r)
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
var rUnmarshal testEmbedStruct
2018-02-23 05:13:55 -08:00
err = ratCdc.UnmarshalJSON(rMarshal, &rUnmarshal)
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
assert.Equal(t, r.Field1, rUnmarshal.Field1)
assert.Equal(t, r.Field2, rUnmarshal.Field2)
assert.True(t, r.Field3.Equal(rUnmarshal.Field3), "original: %v, unmarshalled: %v", r, rUnmarshal)
2018-02-20 03:31:37 -08:00
}
type testEmbedInterface struct {
Field1 string `json:"f1"`
Field2 int `json:"f2"`
Field3 Rational `json:"f3"`
}
func TestEmbeddedInterfaceSerializationGoWire(t *testing.T) {
2018-02-23 05:13:55 -08:00
r := testEmbedInterface{"foo", 10, NewRat(1, 3)}
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
rMarshal, err := ratCdc.MarshalJSON(r)
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
var rUnmarshal testEmbedInterface
2018-02-23 05:13:55 -08:00
err = ratCdc.UnmarshalJSON(rMarshal, &rUnmarshal)
require.Nil(t, err)
2018-02-20 03:31:37 -08:00
2018-02-23 05:13:55 -08:00
assert.Equal(t, r.Field1, rUnmarshal.Field1)
assert.Equal(t, r.Field2, rUnmarshal.Field2)
assert.True(t, r.Field3.Equal(rUnmarshal.Field3), "original: %v, unmarshalled: %v", r, rUnmarshal)
2018-02-20 03:31:37 -08:00
}