Merge PR #1626: Increase coverage of types/
This commit is contained in:
parent
12c2c236c2
commit
93457aac33
|
@ -0,0 +1,132 @@
|
||||||
|
package types_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var invalidstrs = []string{
|
||||||
|
"",
|
||||||
|
"hello, world!",
|
||||||
|
"0xAA",
|
||||||
|
"AAA",
|
||||||
|
types.Bech32PrefixAccAddr + "AB0C",
|
||||||
|
types.Bech32PrefixAccPub + "1234",
|
||||||
|
types.Bech32PrefixValAddr + "5678",
|
||||||
|
types.Bech32PrefixValPub + "BBAB",
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMarshal(t *testing.T, original interface{}, res interface{}, marshal func() ([]byte, error), unmarshal func([]byte) error) {
|
||||||
|
bz, err := marshal()
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = unmarshal(bz)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, original, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandBech32PubkeyConsistency(t *testing.T) {
|
||||||
|
var pub ed25519.PubKeyEd25519
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
rand.Read(pub[:])
|
||||||
|
|
||||||
|
mustbech32accpub := types.MustBech32ifyAccPub(pub)
|
||||||
|
bech32accpub, err := types.Bech32ifyAccPub(pub)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, bech32accpub, mustbech32accpub)
|
||||||
|
|
||||||
|
mustbech32valpub := types.MustBech32ifyValPub(pub)
|
||||||
|
bech32valpub, err := types.Bech32ifyValPub(pub)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, bech32valpub, mustbech32valpub)
|
||||||
|
|
||||||
|
mustaccpub := types.MustGetAccPubKeyBech32(bech32accpub)
|
||||||
|
accpub, err := types.GetAccPubKeyBech32(bech32accpub)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, accpub, mustaccpub)
|
||||||
|
|
||||||
|
mustvalpub := types.MustGetValPubKeyBech32(bech32valpub)
|
||||||
|
valpub, err := types.GetValPubKeyBech32(bech32valpub)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, valpub, mustvalpub)
|
||||||
|
|
||||||
|
require.Equal(t, valpub, accpub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandBech32AccAddrConsistency(t *testing.T) {
|
||||||
|
var pub ed25519.PubKeyEd25519
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
rand.Read(pub[:])
|
||||||
|
|
||||||
|
acc := types.AccAddress(pub.Address())
|
||||||
|
res := types.AccAddress{}
|
||||||
|
|
||||||
|
testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
|
||||||
|
testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
|
||||||
|
|
||||||
|
str := acc.String()
|
||||||
|
res, err := types.AccAddressFromBech32(str)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, acc, res)
|
||||||
|
|
||||||
|
str = hex.EncodeToString(acc)
|
||||||
|
res, err = types.AccAddressFromHex(str)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, acc, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, str := range invalidstrs {
|
||||||
|
_, err := types.AccAddressFromHex(str)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
|
||||||
|
_, err = types.AccAddressFromBech32(str)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
|
||||||
|
err = (*types.AccAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
|
||||||
|
require.NotNil(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValAddr(t *testing.T) {
|
||||||
|
var pub ed25519.PubKeyEd25519
|
||||||
|
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
rand.Read(pub[:])
|
||||||
|
|
||||||
|
acc := types.ValAddress(pub.Address())
|
||||||
|
res := types.ValAddress{}
|
||||||
|
|
||||||
|
testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
|
||||||
|
testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
|
||||||
|
|
||||||
|
str := acc.String()
|
||||||
|
res, err := types.ValAddressFromBech32(str)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, acc, res)
|
||||||
|
|
||||||
|
str = hex.EncodeToString(acc)
|
||||||
|
res, err = types.ValAddressFromHex(str)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, acc, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, str := range invalidstrs {
|
||||||
|
_, err := types.ValAddressFromHex(str)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
|
||||||
|
_, err = types.ValAddressFromBech32(str)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
|
||||||
|
err = (*types.ValAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
|
||||||
|
require.NotNil(t, err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -147,6 +147,46 @@ func TestMinusCoin(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsZeroCoins(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
inputOne Coins
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{Coins{}, true},
|
||||||
|
{Coins{NewCoin("A", 0)}, true},
|
||||||
|
{Coins{NewCoin("A", 0), NewCoin("B", 0)}, true},
|
||||||
|
{Coins{NewCoin("A", 1)}, false},
|
||||||
|
{Coins{NewCoin("A", 0), NewCoin("B", 1)}, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
res := tc.inputOne.IsZero()
|
||||||
|
require.Equal(t, tc.expected, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqualCoins(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
inputOne Coins
|
||||||
|
inputTwo Coins
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{Coins{}, Coins{}, true},
|
||||||
|
{Coins{NewCoin("A", 0)}, Coins{NewCoin("A", 0)}, true},
|
||||||
|
{Coins{NewCoin("A", 0), NewCoin("B", 1)}, Coins{NewCoin("A", 0), NewCoin("B", 1)}, true},
|
||||||
|
{Coins{NewCoin("A", 0)}, Coins{NewCoin("B", 0)}, false},
|
||||||
|
{Coins{NewCoin("A", 0)}, Coins{NewCoin("A", 1)}, false},
|
||||||
|
{Coins{NewCoin("A", 0)}, Coins{NewCoin("A", 0), NewCoin("B", 1)}, false},
|
||||||
|
// TODO: is it expected behaviour? shouldn't we sort the coins before comparing them?
|
||||||
|
{Coins{NewCoin("A", 0), NewCoin("B", 1)}, Coins{NewCoin("B", 1), NewCoin("A", 0)}, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
res := tc.inputOne.IsEqual(tc.inputTwo)
|
||||||
|
require.Equal(t, tc.expected, res, "Equality is differed from expected. tc #%d, expected %b, actual %b.", tcnum, tc.expected, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCoins(t *testing.T) {
|
func TestCoins(t *testing.T) {
|
||||||
|
|
||||||
//Define the coins to be used in tests
|
//Define the coins to be used in tests
|
||||||
|
@ -160,6 +200,7 @@ func TestCoins(t *testing.T) {
|
||||||
empty := Coins{
|
empty := Coins{
|
||||||
{"GOLD", NewInt(0)},
|
{"GOLD", NewInt(0)},
|
||||||
}
|
}
|
||||||
|
null := Coins{}
|
||||||
badSort1 := Coins{
|
badSort1 := Coins{
|
||||||
{"TREE", NewInt(1)},
|
{"TREE", NewInt(1)},
|
||||||
{"GAS", NewInt(1)},
|
{"GAS", NewInt(1)},
|
||||||
|
@ -184,6 +225,7 @@ func TestCoins(t *testing.T) {
|
||||||
|
|
||||||
assert.True(t, good.IsValid(), "Coins are valid")
|
assert.True(t, good.IsValid(), "Coins are valid")
|
||||||
assert.True(t, good.IsPositive(), "Expected coins to be positive: %v", good)
|
assert.True(t, good.IsPositive(), "Expected coins to be positive: %v", good)
|
||||||
|
assert.False(t, null.IsPositive(), "Expected coins to not be positive: %v", null)
|
||||||
assert.True(t, good.IsGTE(empty), "Expected %v to be >= %v", good, empty)
|
assert.True(t, good.IsGTE(empty), "Expected %v to be >= %v", good, empty)
|
||||||
assert.False(t, neg.IsPositive(), "Expected neg coins to not be positive: %v", neg)
|
assert.False(t, neg.IsPositive(), "Expected neg coins to not be positive: %v", neg)
|
||||||
assert.Zero(t, len(sum), "Expected 0 coins")
|
assert.Zero(t, len(sum), "Expected 0 coins")
|
||||||
|
|
|
@ -98,3 +98,84 @@ func TestLogContext(t *testing.T) {
|
||||||
ctx.Logger().Error("error")
|
ctx.Logger().Error("error")
|
||||||
require.Equal(t, *logger.logs, []string{"debug", "info", "error"})
|
require.Equal(t, *logger.logs, []string{"debug", "info", "error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dummy int64
|
||||||
|
|
||||||
|
func (d dummy) Clone() interface{} {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing saving/loading primitive values to/from the context
|
||||||
|
func TestContextWithPrimitive(t *testing.T) {
|
||||||
|
ctx := types.NewContext(nil, abci.Header{}, false, log.NewNopLogger())
|
||||||
|
|
||||||
|
clonerkey := "cloner"
|
||||||
|
stringkey := "string"
|
||||||
|
int32key := "int32"
|
||||||
|
uint32key := "uint32"
|
||||||
|
uint64key := "uint64"
|
||||||
|
|
||||||
|
keys := []string{clonerkey, stringkey, int32key, uint32key, uint64key}
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
require.Nil(t, ctx.Value(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
clonerval := dummy(1)
|
||||||
|
stringval := "string"
|
||||||
|
int32val := int32(1)
|
||||||
|
uint32val := uint32(2)
|
||||||
|
uint64val := uint64(3)
|
||||||
|
|
||||||
|
ctx = ctx.
|
||||||
|
WithCloner(clonerkey, clonerval).
|
||||||
|
WithString(stringkey, stringval).
|
||||||
|
WithInt32(int32key, int32val).
|
||||||
|
WithUint32(uint32key, uint32val).
|
||||||
|
WithUint64(uint64key, uint64val)
|
||||||
|
|
||||||
|
require.Equal(t, clonerval, ctx.Value(clonerkey))
|
||||||
|
require.Equal(t, stringval, ctx.Value(stringkey))
|
||||||
|
require.Equal(t, int32val, ctx.Value(int32key))
|
||||||
|
require.Equal(t, uint32val, ctx.Value(uint32key))
|
||||||
|
require.Equal(t, uint64val, ctx.Value(uint64key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing saving/loading sdk type values to/from the context
|
||||||
|
func TestContextWithCustom(t *testing.T) {
|
||||||
|
var ctx types.Context
|
||||||
|
require.True(t, ctx.IsZero())
|
||||||
|
|
||||||
|
require.Panics(t, func() { ctx.BlockHeader() })
|
||||||
|
require.Panics(t, func() { ctx.BlockHeight() })
|
||||||
|
require.Panics(t, func() { ctx.ChainID() })
|
||||||
|
require.Panics(t, func() { ctx.TxBytes() })
|
||||||
|
require.Panics(t, func() { ctx.Logger() })
|
||||||
|
require.Panics(t, func() { ctx.SigningValidators() })
|
||||||
|
require.Panics(t, func() { ctx.GasMeter() })
|
||||||
|
|
||||||
|
header := abci.Header{}
|
||||||
|
height := int64(1)
|
||||||
|
chainid := "chainid"
|
||||||
|
ischeck := true
|
||||||
|
txbytes := []byte("txbytes")
|
||||||
|
logger := NewMockLogger()
|
||||||
|
signvals := []abci.SigningValidator{abci.SigningValidator{}}
|
||||||
|
meter := types.NewGasMeter(10000)
|
||||||
|
|
||||||
|
ctx = types.NewContext(nil, header, ischeck, logger).
|
||||||
|
WithBlockHeight(height).
|
||||||
|
WithChainID(chainid).
|
||||||
|
WithTxBytes(txbytes).
|
||||||
|
WithSigningValidators(signvals).
|
||||||
|
WithGasMeter(meter)
|
||||||
|
|
||||||
|
require.Equal(t, header, ctx.BlockHeader())
|
||||||
|
require.Equal(t, height, ctx.BlockHeight())
|
||||||
|
require.Equal(t, chainid, ctx.ChainID())
|
||||||
|
require.Equal(t, txbytes, ctx.TxBytes())
|
||||||
|
require.Equal(t, logger, ctx.Logger())
|
||||||
|
require.Equal(t, signvals, ctx.SigningValidators())
|
||||||
|
require.Equal(t, meter, ctx.GasMeter())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -65,6 +65,10 @@ const (
|
||||||
MaximumCodespace CodespaceType = 65535
|
MaximumCodespace CodespaceType = 65535
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func unknownCodeMsg(code CodeType) string {
|
||||||
|
return fmt.Sprintf("unknown code %d", code)
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Don't stringer this, we'll put better messages in later.
|
// NOTE: Don't stringer this, we'll put better messages in later.
|
||||||
// nolint: gocyclo
|
// nolint: gocyclo
|
||||||
func CodeToDefaultMsg(code CodeType) string {
|
func CodeToDefaultMsg(code CodeType) string {
|
||||||
|
@ -96,7 +100,7 @@ func CodeToDefaultMsg(code CodeType) string {
|
||||||
case CodeMemoTooLarge:
|
case CodeMemoTooLarge:
|
||||||
return "memo too large"
|
return "memo too large"
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("unknown code %d", code)
|
return unknownCodeMsg(code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -14,8 +13,13 @@ var codeTypes = []CodeType{
|
||||||
CodeUnauthorized,
|
CodeUnauthorized,
|
||||||
CodeInsufficientFunds,
|
CodeInsufficientFunds,
|
||||||
CodeUnknownRequest,
|
CodeUnknownRequest,
|
||||||
CodeUnknownAddress,
|
CodeInvalidAddress,
|
||||||
CodeInvalidPubKey,
|
CodeInvalidPubKey,
|
||||||
|
CodeUnknownAddress,
|
||||||
|
CodeInsufficientCoins,
|
||||||
|
CodeInvalidCoins,
|
||||||
|
CodeOutOfGas,
|
||||||
|
CodeMemoTooLarge,
|
||||||
}
|
}
|
||||||
|
|
||||||
type errFn func(msg string) Error
|
type errFn func(msg string) Error
|
||||||
|
@ -27,24 +31,34 @@ var errFns = []errFn{
|
||||||
ErrUnauthorized,
|
ErrUnauthorized,
|
||||||
ErrInsufficientFunds,
|
ErrInsufficientFunds,
|
||||||
ErrUnknownRequest,
|
ErrUnknownRequest,
|
||||||
ErrUnknownAddress,
|
ErrInvalidAddress,
|
||||||
ErrInvalidPubKey,
|
ErrInvalidPubKey,
|
||||||
|
ErrUnknownAddress,
|
||||||
|
ErrInsufficientCoins,
|
||||||
|
ErrInvalidCoins,
|
||||||
|
ErrOutOfGas,
|
||||||
|
ErrMemoTooLarge,
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCodeType(t *testing.T) {
|
func TestCodeType(t *testing.T) {
|
||||||
require.True(t, ABCICodeOK.IsOK())
|
require.True(t, ABCICodeOK.IsOK())
|
||||||
|
|
||||||
for _, c := range codeTypes {
|
for tcnum, c := range codeTypes {
|
||||||
msg := CodeToDefaultMsg(c)
|
msg := CodeToDefaultMsg(c)
|
||||||
require.False(t, strings.HasPrefix(msg, "Unknown code"))
|
require.NotEqual(t, unknownCodeMsg(c), msg, "Code expected to be known. tc #%d, code %d, msg %s", tcnum, c, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg := CodeToDefaultMsg(CodeOK)
|
||||||
|
require.Equal(t, unknownCodeMsg(CodeOK), msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrFn(t *testing.T) {
|
func TestErrFn(t *testing.T) {
|
||||||
for i, errFn := range errFns {
|
for i, errFn := range errFns {
|
||||||
err := errFn("")
|
err := errFn("")
|
||||||
codeType := codeTypes[i]
|
codeType := codeTypes[i]
|
||||||
require.Equal(t, err.Code(), codeType)
|
require.Equal(t, err.Code(), codeType, "Err function expected to return proper code. tc #%d", i)
|
||||||
require.Equal(t, err.Result().Code, ToABCICode(CodespaceRoot, codeType))
|
require.Equal(t, err.Result().Code, ToABCICode(CodespaceRoot, codeType), "Err function expected to return proper ABCICode. tc #%d")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require.Equal(t, ABCICodeOK, ToABCICode(CodespaceRoot, CodeOK))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGasMeter(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
limit Gas
|
||||||
|
usage []Gas
|
||||||
|
}{
|
||||||
|
{10, []Gas{1, 2, 3, 4}},
|
||||||
|
{1000, []Gas{40, 30, 20, 10, 900}},
|
||||||
|
{100000, []Gas{99999, 1}},
|
||||||
|
{100000000, []Gas{50000000, 40000000, 10000000}},
|
||||||
|
{65535, []Gas{32768, 32767}},
|
||||||
|
{65536, []Gas{32768, 32767, 1}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
meter := NewGasMeter(tc.limit)
|
||||||
|
used := int64(0)
|
||||||
|
|
||||||
|
for unum, usage := range tc.usage {
|
||||||
|
used += usage
|
||||||
|
require.NotPanics(t, func() { meter.ConsumeGas(usage, "") }, "Not exceeded limit but panicked. tc #%d, usage #%d", tcnum, unum)
|
||||||
|
require.Equal(t, used, meter.GasConsumed(), "Gas consumption not match. tc #%d, usage #%d", tcnum, unum)
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Panics(t, func() { meter.ConsumeGas(1, "") }, "Exceeded but not panicked. tc #%d", tcnum)
|
||||||
|
break
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
90
types/int.go
90
types/int.go
|
@ -4,21 +4,13 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newIntegerFromString(s string) (*big.Int, bool) {
|
func newIntegerFromString(s string) (*big.Int, bool) {
|
||||||
return new(big.Int).SetString(s, 0)
|
return new(big.Int).SetString(s, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIntegerWithDecimal(n int64, dec int) (res *big.Int) {
|
|
||||||
if dec < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(dec)), nil)
|
|
||||||
i := new(big.Int)
|
|
||||||
return i.Mul(big.NewInt(n), exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func equal(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 0 }
|
func equal(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 0 }
|
||||||
|
|
||||||
func gt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 1 }
|
func gt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 1 }
|
||||||
|
@ -37,6 +29,8 @@ func mod(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mod(i, i2) }
|
||||||
|
|
||||||
func neg(i *big.Int) *big.Int { return new(big.Int).Neg(i) }
|
func neg(i *big.Int) *big.Int { return new(big.Int).Neg(i) }
|
||||||
|
|
||||||
|
func random(i *big.Int) *big.Int { return new(big.Int).Rand(rand.New(rand.NewSource(rand.Int63())), i) }
|
||||||
|
|
||||||
func min(i *big.Int, i2 *big.Int) *big.Int {
|
func min(i *big.Int, i2 *big.Int) *big.Int {
|
||||||
if i.Cmp(i2) == 1 {
|
if i.Cmp(i2) == 1 {
|
||||||
return new(big.Int).Set(i2)
|
return new(big.Int).Set(i2)
|
||||||
|
@ -118,7 +112,13 @@ func NewIntFromString(s string) (res Int, ok bool) {
|
||||||
// NewIntWithDecimal constructs Int with decimal
|
// NewIntWithDecimal constructs Int with decimal
|
||||||
// Result value is n*10^dec
|
// Result value is n*10^dec
|
||||||
func NewIntWithDecimal(n int64, dec int) Int {
|
func NewIntWithDecimal(n int64, dec int) Int {
|
||||||
i := newIntegerWithDecimal(n, dec)
|
if dec < 0 {
|
||||||
|
panic("NewIntWithDecimal() decimal is negative")
|
||||||
|
}
|
||||||
|
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(dec)), nil)
|
||||||
|
i := new(big.Int)
|
||||||
|
i.Mul(big.NewInt(n), exp)
|
||||||
|
|
||||||
// Check overflow
|
// Check overflow
|
||||||
if i.BitLen() > 255 {
|
if i.BitLen() > 255 {
|
||||||
panic("NewIntWithDecimal() out of bound")
|
panic("NewIntWithDecimal() out of bound")
|
||||||
|
@ -141,6 +141,11 @@ func (i Int) Int64() int64 {
|
||||||
return i.i.Int64()
|
return i.i.Int64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsInt64 returns true if Int64() not panics
|
||||||
|
func (i Int) IsInt64() bool {
|
||||||
|
return i.i.IsInt64()
|
||||||
|
}
|
||||||
|
|
||||||
// IsZero returns true if Int is zero
|
// IsZero returns true if Int is zero
|
||||||
func (i Int) IsZero() bool {
|
func (i Int) IsZero() bool {
|
||||||
return i.i.Sign() == 0
|
return i.i.Sign() == 0
|
||||||
|
@ -229,6 +234,19 @@ func (i Int) DivRaw(i2 int64) Int {
|
||||||
return i.Div(NewInt(i2))
|
return i.Div(NewInt(i2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mod returns remainder after dividing with Int
|
||||||
|
func (i Int) Mod(i2 Int) Int {
|
||||||
|
if i2.Sign() == 0 {
|
||||||
|
panic("division-by-zero")
|
||||||
|
}
|
||||||
|
return Int{mod(i.i, i2.i)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModRaw returns remainder after dividing with int64
|
||||||
|
func (i Int) ModRaw(i2 int64) Int {
|
||||||
|
return i.Mod(NewInt(i2))
|
||||||
|
}
|
||||||
|
|
||||||
// Neg negates Int
|
// Neg negates Int
|
||||||
func (i Int) Neg() (res Int) {
|
func (i Int) Neg() (res Int) {
|
||||||
return Int{neg(i.i)}
|
return Int{neg(i.i)}
|
||||||
|
@ -239,10 +257,16 @@ func MinInt(i1, i2 Int) Int {
|
||||||
return Int{min(i1.BigInt(), i2.BigInt())}
|
return Int{min(i1.BigInt(), i2.BigInt())}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Human readable string
|
||||||
func (i Int) String() string {
|
func (i Int) String() string {
|
||||||
return i.i.String()
|
return i.i.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Testing purpose random Int generator
|
||||||
|
func randomInt(i Int) Int {
|
||||||
|
return NewIntFromBigInt(random(i.BigInt()))
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalAmino defines custom encoding scheme
|
// MarshalAmino defines custom encoding scheme
|
||||||
func (i Int) MarshalAmino() (string, error) {
|
func (i Int) MarshalAmino() (string, error) {
|
||||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||||
|
@ -319,8 +343,14 @@ func NewUintFromString(s string) (res Uint, ok bool) {
|
||||||
|
|
||||||
// NewUintWithDecimal constructs Uint with decimal
|
// NewUintWithDecimal constructs Uint with decimal
|
||||||
// Result value is n*10^dec
|
// Result value is n*10^dec
|
||||||
func NewUintWithDecimal(n int64, dec int) Uint {
|
func NewUintWithDecimal(n uint64, dec int) Uint {
|
||||||
i := newIntegerWithDecimal(n, dec)
|
if dec < 0 {
|
||||||
|
panic("NewUintWithDecimal() decimal is negative")
|
||||||
|
}
|
||||||
|
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(dec)), nil)
|
||||||
|
i := new(big.Int)
|
||||||
|
i.Mul(new(big.Int).SetUint64(n), exp)
|
||||||
|
|
||||||
// Check overflow
|
// Check overflow
|
||||||
if i.Sign() == -1 || i.Sign() == 1 && i.BitLen() > 256 {
|
if i.Sign() == -1 || i.Sign() == 1 && i.BitLen() > 256 {
|
||||||
panic("NewUintWithDecimal() out of bound")
|
panic("NewUintWithDecimal() out of bound")
|
||||||
|
@ -343,6 +373,11 @@ func (i Uint) Uint64() uint64 {
|
||||||
return i.i.Uint64()
|
return i.i.Uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsUint64 returns true if Uint64() not panics
|
||||||
|
func (i Uint) IsUint64() bool {
|
||||||
|
return i.i.IsUint64()
|
||||||
|
}
|
||||||
|
|
||||||
// IsZero returns true if Uint is zero
|
// IsZero returns true if Uint is zero
|
||||||
func (i Uint) IsZero() bool {
|
func (i Uint) IsZero() bool {
|
||||||
return i.i.Sign() == 0
|
return i.i.Sign() == 0
|
||||||
|
@ -378,7 +413,7 @@ func (i Uint) Add(i2 Uint) (res Uint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRaw adds int64 to Uint
|
// AddRaw adds uint64 to Uint
|
||||||
func (i Uint) AddRaw(i2 uint64) Uint {
|
func (i Uint) AddRaw(i2 uint64) Uint {
|
||||||
return i.Add(NewUint(i2))
|
return i.Add(NewUint(i2))
|
||||||
}
|
}
|
||||||
|
@ -393,7 +428,7 @@ func (i Uint) Sub(i2 Uint) (res Uint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubRaw subtracts int64 from Uint
|
// SubRaw subtracts uint64 from Uint
|
||||||
func (i Uint) SubRaw(i2 uint64) Uint {
|
func (i Uint) SubRaw(i2 uint64) Uint {
|
||||||
return i.Sub(NewUint(i2))
|
return i.Sub(NewUint(i2))
|
||||||
}
|
}
|
||||||
|
@ -412,7 +447,7 @@ func (i Uint) Mul(i2 Uint) (res Uint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulRaw multipies Uint and int64
|
// MulRaw multipies Uint and uint64
|
||||||
func (i Uint) MulRaw(i2 uint64) Uint {
|
func (i Uint) MulRaw(i2 uint64) Uint {
|
||||||
return i.Mul(NewUint(i2))
|
return i.Mul(NewUint(i2))
|
||||||
}
|
}
|
||||||
|
@ -426,16 +461,39 @@ func (i Uint) Div(i2 Uint) (res Uint) {
|
||||||
return Uint{div(i.i, i2.i)}
|
return Uint{div(i.i, i2.i)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Div divides Uint with int64
|
// Div divides Uint with uint64
|
||||||
func (i Uint) DivRaw(i2 uint64) Uint {
|
func (i Uint) DivRaw(i2 uint64) Uint {
|
||||||
return i.Div(NewUint(i2))
|
return i.Div(NewUint(i2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mod returns remainder after dividing with Uint
|
||||||
|
func (i Uint) Mod(i2 Uint) Uint {
|
||||||
|
if i2.Sign() == 0 {
|
||||||
|
panic("division-by-zero")
|
||||||
|
}
|
||||||
|
return Uint{mod(i.i, i2.i)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModRaw returns remainder after dividing with uint64
|
||||||
|
func (i Uint) ModRaw(i2 uint64) Uint {
|
||||||
|
return i.Mod(NewUint(i2))
|
||||||
|
}
|
||||||
|
|
||||||
// Return the minimum of the Uints
|
// Return the minimum of the Uints
|
||||||
func MinUint(i1, i2 Uint) Uint {
|
func MinUint(i1, i2 Uint) Uint {
|
||||||
return Uint{min(i1.BigInt(), i2.BigInt())}
|
return Uint{min(i1.BigInt(), i2.BigInt())}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Human readable string
|
||||||
|
func (i Uint) String() string {
|
||||||
|
return i.i.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing purpose random Uint generator
|
||||||
|
func randomUint(i Uint) Uint {
|
||||||
|
return NewUintFromBigInt(random(i.BigInt()))
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalAmino defines custom encoding scheme
|
// MarshalAmino defines custom encoding scheme
|
||||||
func (i Uint) MarshalAmino() (string, error) {
|
func (i Uint) MarshalAmino() (string, error) {
|
||||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -15,7 +17,7 @@ func TestFromInt64(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInt(t *testing.T) {
|
func TestIntPanic(t *testing.T) {
|
||||||
// Max Int = 2^255-1 = 5.789e+76
|
// Max Int = 2^255-1 = 5.789e+76
|
||||||
// Min Int = -(2^255-1) = -5.789e+76
|
// Min Int = -(2^255-1) = -5.789e+76
|
||||||
require.NotPanics(t, func() { NewIntWithDecimal(1, 76) })
|
require.NotPanics(t, func() { NewIntWithDecimal(1, 76) })
|
||||||
|
@ -71,7 +73,7 @@ func TestInt(t *testing.T) {
|
||||||
require.Panics(t, func() { i1.Div(NewInt(0)) })
|
require.Panics(t, func() { i1.Div(NewInt(0)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUint(t *testing.T) {
|
func TestUintPanic(t *testing.T) {
|
||||||
// Max Uint = 1.15e+77
|
// Max Uint = 1.15e+77
|
||||||
// Min Uint = 0
|
// Min Uint = 0
|
||||||
require.NotPanics(t, func() { NewUintWithDecimal(5, 76) })
|
require.NotPanics(t, func() { NewUintWithDecimal(5, 76) })
|
||||||
|
@ -109,3 +111,482 @@ func TestUint(t *testing.T) {
|
||||||
// Division-by-zero check
|
// Division-by-zero check
|
||||||
require.Panics(t, func() { i1.Div(uintmin) })
|
require.Panics(t, func() { i1.Div(uintmin) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests below uses randomness
|
||||||
|
// Since we are using *big.Int as underlying value
|
||||||
|
// and (U/)Int is immutable value(see TestImmutability(U/)Int)
|
||||||
|
// it is safe to use randomness in the tests
|
||||||
|
func TestIdentInt(t *testing.T) {
|
||||||
|
for d := 0; d < 1000; d++ {
|
||||||
|
n := rand.Int63()
|
||||||
|
i := NewInt(n)
|
||||||
|
|
||||||
|
ifromstr, ok := NewIntFromString(strconv.FormatInt(n, 10))
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
cases := []int64{
|
||||||
|
i.Int64(),
|
||||||
|
i.BigInt().Int64(),
|
||||||
|
ifromstr.Int64(),
|
||||||
|
NewIntFromBigInt(big.NewInt(n)).Int64(),
|
||||||
|
NewIntWithDecimal(n, 0).Int64(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
require.Equal(t, n, tc, "Int is modified during conversion. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func minint(i1, i2 int64) int64 {
|
||||||
|
if i1 < i2 {
|
||||||
|
return i1
|
||||||
|
}
|
||||||
|
return i2
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArithInt(t *testing.T) {
|
||||||
|
for d := 0; d < 1000; d++ {
|
||||||
|
n1 := int64(rand.Int31())
|
||||||
|
i1 := NewInt(n1)
|
||||||
|
n2 := int64(rand.Int31())
|
||||||
|
i2 := NewInt(n2)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
ires Int
|
||||||
|
nres int64
|
||||||
|
}{
|
||||||
|
{i1.Add(i2), n1 + n2},
|
||||||
|
{i1.Sub(i2), n1 - n2},
|
||||||
|
{i1.Mul(i2), n1 * n2},
|
||||||
|
{i1.Div(i2), n1 / n2},
|
||||||
|
{i1.AddRaw(n2), n1 + n2},
|
||||||
|
{i1.SubRaw(n2), n1 - n2},
|
||||||
|
{i1.MulRaw(n2), n1 * n2},
|
||||||
|
{i1.DivRaw(n2), n1 / n2},
|
||||||
|
{MinInt(i1, i2), minint(n1, n2)},
|
||||||
|
{i1.Neg(), -n1},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
require.Equal(t, tc.nres, tc.ires.Int64(), "Int arithmetic operation does not match with int64 operation. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompInt(t *testing.T) {
|
||||||
|
for d := 0; d < 1000; d++ {
|
||||||
|
n1 := int64(rand.Int31())
|
||||||
|
i1 := NewInt(n1)
|
||||||
|
n2 := int64(rand.Int31())
|
||||||
|
i2 := NewInt(n2)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
ires bool
|
||||||
|
nres bool
|
||||||
|
}{
|
||||||
|
{i1.Equal(i2), n1 == n2},
|
||||||
|
{i1.GT(i2), n1 > n2},
|
||||||
|
{i1.LT(i2), n1 < n2},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
require.Equal(t, tc.nres, tc.ires, "Int comparison operation does not match with int64 operation. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIdentUint(t *testing.T) {
|
||||||
|
for d := 0; d < 1000; d++ {
|
||||||
|
n := rand.Uint64()
|
||||||
|
i := NewUint(n)
|
||||||
|
|
||||||
|
ifromstr, ok := NewUintFromString(strconv.FormatUint(n, 10))
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
cases := []uint64{
|
||||||
|
i.Uint64(),
|
||||||
|
i.BigInt().Uint64(),
|
||||||
|
ifromstr.Uint64(),
|
||||||
|
NewUintFromBigInt(new(big.Int).SetUint64(n)).Uint64(),
|
||||||
|
NewUintWithDecimal(n, 0).Uint64(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
require.Equal(t, n, tc, "Uint is modified during conversion. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func minuint(i1, i2 uint64) uint64 {
|
||||||
|
if i1 < i2 {
|
||||||
|
return i1
|
||||||
|
}
|
||||||
|
return i2
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArithUint(t *testing.T) {
|
||||||
|
for d := 0; d < 1000; d++ {
|
||||||
|
n1 := uint64(rand.Uint32())
|
||||||
|
i1 := NewUint(n1)
|
||||||
|
n2 := uint64(rand.Uint32())
|
||||||
|
i2 := NewUint(n2)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
ires Uint
|
||||||
|
nres uint64
|
||||||
|
}{
|
||||||
|
{i1.Add(i2), n1 + n2},
|
||||||
|
{i1.Mul(i2), n1 * n2},
|
||||||
|
{i1.Div(i2), n1 / n2},
|
||||||
|
{i1.AddRaw(n2), n1 + n2},
|
||||||
|
{i1.MulRaw(n2), n1 * n2},
|
||||||
|
{i1.DivRaw(n2), n1 / n2},
|
||||||
|
{MinUint(i1, i2), minuint(n1, n2)},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
require.Equal(t, tc.nres, tc.ires.Uint64(), "Uint arithmetic operation does not match with uint64 operation. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n2 > n1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
subs := []struct {
|
||||||
|
ires Uint
|
||||||
|
nres uint64
|
||||||
|
}{
|
||||||
|
{i1.Sub(i2), n1 - n2},
|
||||||
|
{i1.SubRaw(n2), n1 - n2},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range subs {
|
||||||
|
require.Equal(t, tc.nres, tc.ires.Uint64(), "Uint subtraction does not match with uint64 operation. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompUint(t *testing.T) {
|
||||||
|
for d := 0; d < 1000; d++ {
|
||||||
|
n1 := rand.Uint64()
|
||||||
|
i1 := NewUint(n1)
|
||||||
|
n2 := rand.Uint64()
|
||||||
|
i2 := NewUint(n2)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
ires bool
|
||||||
|
nres bool
|
||||||
|
}{
|
||||||
|
{i1.Equal(i2), n1 == n2},
|
||||||
|
{i1.GT(i2), n1 > n2},
|
||||||
|
{i1.LT(i2), n1 < n2},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
require.Equal(t, tc.nres, tc.ires, "Uint comparison operation does not match with uint64 operation. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func randint() Int {
|
||||||
|
return NewInt(rand.Int63())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImmutabilityAllInt(t *testing.T) {
|
||||||
|
ops := []func(*Int){
|
||||||
|
func(i *Int) { _ = i.Add(randint()) },
|
||||||
|
func(i *Int) { _ = i.Sub(randint()) },
|
||||||
|
func(i *Int) { _ = i.Mul(randint()) },
|
||||||
|
func(i *Int) { _ = i.Div(randint()) },
|
||||||
|
func(i *Int) { _ = i.AddRaw(rand.Int63()) },
|
||||||
|
func(i *Int) { _ = i.SubRaw(rand.Int63()) },
|
||||||
|
func(i *Int) { _ = i.MulRaw(rand.Int63()) },
|
||||||
|
func(i *Int) { _ = i.DivRaw(rand.Int63()) },
|
||||||
|
func(i *Int) { _ = i.Neg() },
|
||||||
|
func(i *Int) { _ = i.IsZero() },
|
||||||
|
func(i *Int) { _ = i.Sign() },
|
||||||
|
func(i *Int) { _ = i.Equal(randint()) },
|
||||||
|
func(i *Int) { _ = i.GT(randint()) },
|
||||||
|
func(i *Int) { _ = i.LT(randint()) },
|
||||||
|
func(i *Int) { _ = i.String() },
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
n := rand.Int63()
|
||||||
|
ni := NewInt(n)
|
||||||
|
|
||||||
|
for opnum, op := range ops {
|
||||||
|
op(&ni)
|
||||||
|
|
||||||
|
require.Equal(t, n, ni.Int64(), "Int is modified by operation. tc #%d", opnum)
|
||||||
|
require.Equal(t, NewInt(n), ni, "Int is modified by operation. tc #%d", opnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type intop func(Int, *big.Int) (Int, *big.Int)
|
||||||
|
|
||||||
|
func intarith(uifn func(Int, Int) Int, bifn func(*big.Int, *big.Int, *big.Int) *big.Int) intop {
|
||||||
|
return func(ui Int, bi *big.Int) (Int, *big.Int) {
|
||||||
|
r := rand.Int63()
|
||||||
|
br := new(big.Int).SetInt64(r)
|
||||||
|
return uifn(ui, NewInt(r)), bifn(new(big.Int), bi, br)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func intarithraw(uifn func(Int, int64) Int, bifn func(*big.Int, *big.Int, *big.Int) *big.Int) intop {
|
||||||
|
return func(ui Int, bi *big.Int) (Int, *big.Int) {
|
||||||
|
r := rand.Int63()
|
||||||
|
br := new(big.Int).SetInt64(r)
|
||||||
|
return uifn(ui, r), bifn(new(big.Int), bi, br)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImmutabilityArithInt(t *testing.T) {
|
||||||
|
size := 1000
|
||||||
|
|
||||||
|
ops := []intop{
|
||||||
|
intarith(Int.Add, (*big.Int).Add),
|
||||||
|
intarith(Int.Sub, (*big.Int).Sub),
|
||||||
|
intarith(Int.Mul, (*big.Int).Mul),
|
||||||
|
intarith(Int.Div, (*big.Int).Div),
|
||||||
|
intarithraw(Int.AddRaw, (*big.Int).Add),
|
||||||
|
intarithraw(Int.SubRaw, (*big.Int).Sub),
|
||||||
|
intarithraw(Int.MulRaw, (*big.Int).Mul),
|
||||||
|
intarithraw(Int.DivRaw, (*big.Int).Div),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
uis := make([]Int, size)
|
||||||
|
bis := make([]*big.Int, size)
|
||||||
|
|
||||||
|
n := rand.Int63()
|
||||||
|
ui := NewInt(n)
|
||||||
|
bi := new(big.Int).SetInt64(n)
|
||||||
|
|
||||||
|
for j := 0; j < size; j++ {
|
||||||
|
op := ops[rand.Intn(len(ops))]
|
||||||
|
uis[j], bis[j] = op(ui, bi)
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 0; j < size; j++ {
|
||||||
|
require.Equal(t, 0, bis[j].Cmp(uis[j].BigInt()), "Int is different from *big.Int. tc #%d, Int %s, *big.Int %s", j, uis[j].String(), bis[j].String())
|
||||||
|
require.Equal(t, NewIntFromBigInt(bis[j]), uis[j], "Int is different from *big.Int. tc #%d, Int %s, *big.Int %s", j, uis[j].String(), bis[j].String())
|
||||||
|
require.True(t, uis[j].i != bis[j], "Pointer addresses are equal. tc #%d, Int %s, *big.Int %s", j, uis[j].String(), bis[j].String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestImmutabilityAllUint(t *testing.T) {
|
||||||
|
ops := []func(*Uint){
|
||||||
|
func(i *Uint) { _ = i.Add(NewUint(rand.Uint64())) },
|
||||||
|
func(i *Uint) { _ = i.Sub(NewUint(rand.Uint64() % i.Uint64())) },
|
||||||
|
func(i *Uint) { _ = i.Mul(randuint()) },
|
||||||
|
func(i *Uint) { _ = i.Div(randuint()) },
|
||||||
|
func(i *Uint) { _ = i.AddRaw(rand.Uint64()) },
|
||||||
|
func(i *Uint) { _ = i.SubRaw(rand.Uint64() % i.Uint64()) },
|
||||||
|
func(i *Uint) { _ = i.MulRaw(rand.Uint64()) },
|
||||||
|
func(i *Uint) { _ = i.DivRaw(rand.Uint64()) },
|
||||||
|
func(i *Uint) { _ = i.IsZero() },
|
||||||
|
func(i *Uint) { _ = i.Sign() },
|
||||||
|
func(i *Uint) { _ = i.Equal(randuint()) },
|
||||||
|
func(i *Uint) { _ = i.GT(randuint()) },
|
||||||
|
func(i *Uint) { _ = i.LT(randuint()) },
|
||||||
|
func(i *Uint) { _ = i.String() },
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
n := rand.Uint64()
|
||||||
|
ni := NewUint(n)
|
||||||
|
|
||||||
|
for opnum, op := range ops {
|
||||||
|
op(&ni)
|
||||||
|
|
||||||
|
require.Equal(t, n, ni.Uint64(), "Uint is modified by operation. #%d", opnum)
|
||||||
|
require.Equal(t, NewUint(n), ni, "Uint is modified by operation. #%d", opnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type uintop func(Uint, *big.Int) (Uint, *big.Int)
|
||||||
|
|
||||||
|
func uintarith(uifn func(Uint, Uint) Uint, bifn func(*big.Int, *big.Int, *big.Int) *big.Int, sub bool) uintop {
|
||||||
|
return func(ui Uint, bi *big.Int) (Uint, *big.Int) {
|
||||||
|
r := rand.Uint64()
|
||||||
|
if sub && ui.IsUint64() {
|
||||||
|
if ui.IsZero() {
|
||||||
|
return ui, bi
|
||||||
|
}
|
||||||
|
r = r % ui.Uint64()
|
||||||
|
}
|
||||||
|
ur := NewUint(r)
|
||||||
|
br := new(big.Int).SetUint64(r)
|
||||||
|
return uifn(ui, ur), bifn(new(big.Int), bi, br)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func uintarithraw(uifn func(Uint, uint64) Uint, bifn func(*big.Int, *big.Int, *big.Int) *big.Int, sub bool) uintop {
|
||||||
|
return func(ui Uint, bi *big.Int) (Uint, *big.Int) {
|
||||||
|
r := rand.Uint64()
|
||||||
|
if sub && ui.IsUint64() {
|
||||||
|
if ui.IsZero() {
|
||||||
|
return ui, bi
|
||||||
|
}
|
||||||
|
r = r % ui.Uint64()
|
||||||
|
}
|
||||||
|
br := new(big.Int).SetUint64(r)
|
||||||
|
mui := ui.ModRaw(math.MaxUint64)
|
||||||
|
mbi := new(big.Int).Mod(bi, new(big.Int).SetUint64(math.MaxUint64))
|
||||||
|
return uifn(mui, r), bifn(new(big.Int), mbi, br)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImmutabilityArithUint(t *testing.T) {
|
||||||
|
size := 1000
|
||||||
|
|
||||||
|
ops := []uintop{
|
||||||
|
uintarith(Uint.Add, (*big.Int).Add, false),
|
||||||
|
uintarith(Uint.Sub, (*big.Int).Sub, true),
|
||||||
|
uintarith(Uint.Mul, (*big.Int).Mul, false),
|
||||||
|
uintarith(Uint.Div, (*big.Int).Div, false),
|
||||||
|
uintarithraw(Uint.AddRaw, (*big.Int).Add, false),
|
||||||
|
uintarithraw(Uint.SubRaw, (*big.Int).Sub, true),
|
||||||
|
uintarithraw(Uint.MulRaw, (*big.Int).Mul, false),
|
||||||
|
uintarithraw(Uint.DivRaw, (*big.Int).Div, false),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
uis := make([]Uint, size)
|
||||||
|
bis := make([]*big.Int, size)
|
||||||
|
|
||||||
|
n := rand.Uint64()
|
||||||
|
ui := NewUint(n)
|
||||||
|
bi := new(big.Int).SetUint64(n)
|
||||||
|
|
||||||
|
for j := 0; j < size; j++ {
|
||||||
|
op := ops[rand.Intn(len(ops))]
|
||||||
|
uis[j], bis[j] = op(ui, bi)
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 0; j < size; j++ {
|
||||||
|
require.Equal(t, 0, bis[j].Cmp(uis[j].BigInt()), "Int is different from *big.Int. tc #%d, Int %s, *big.Int %s", j, uis[j].String(), bis[j].String())
|
||||||
|
require.Equal(t, NewUintFromBigInt(bis[j]), uis[j], "Int is different from *big.Int. tc #%d, Int %s, *big.Int %s", j, uis[j].String(), bis[j].String())
|
||||||
|
require.True(t, uis[j].i != bis[j], "Pointer addresses are equal. tc #%d, Int %s, *big.Int %s", j, uis[j].String(), bis[j].String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func randuint() Uint {
|
||||||
|
return NewUint(rand.Uint64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodingRandom(t *testing.T) {
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
n := rand.Int63()
|
||||||
|
ni := NewInt(n)
|
||||||
|
var ri Int
|
||||||
|
|
||||||
|
str, err := ni.MarshalAmino()
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = (&ri).UnmarshalAmino(str)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, ni, ri, "MarshalAmino * UnmarshalAmino is not identity. tc #%d, Expected %s, Actual %s", i, ni.String(), ri.String())
|
||||||
|
require.True(t, ni.i != ri.i, "Pointer addresses are equal. tc #%d", i)
|
||||||
|
|
||||||
|
bz, err := ni.MarshalJSON()
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = (&ri).UnmarshalJSON(bz)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, ni, ri, "MarshalJSON * UnmarshalJSON is not identity. tc #%d, Expected %s, Actual %s", i, ni.String(), ri.String())
|
||||||
|
require.True(t, ni.i != ri.i, "Pointer addresses are equal. tc #%d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
n := rand.Uint64()
|
||||||
|
ni := NewUint(n)
|
||||||
|
var ri Uint
|
||||||
|
|
||||||
|
str, err := ni.MarshalAmino()
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = (&ri).UnmarshalAmino(str)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, ni, ri, "MarshalAmino * UnmarshalAmino is not identity. tc #%d, Expected %s, Actual %s", i, ni.String(), ri.String())
|
||||||
|
require.True(t, ni.i != ri.i, "Pointer addresses are equal. tc #%d", i)
|
||||||
|
|
||||||
|
bz, err := ni.MarshalJSON()
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = (&ri).UnmarshalJSON(bz)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, ni, ri, "MarshalJSON * UnmarshalJSON is not identity. tc #%d, Expected %s, Actual %s", i, ni.String(), ri.String())
|
||||||
|
require.True(t, ni.i != ri.i, "Pointer addresses are equal. tc #%d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodingTableInt(t *testing.T) {
|
||||||
|
var i Int
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
i Int
|
||||||
|
bz []byte
|
||||||
|
str string
|
||||||
|
}{
|
||||||
|
{NewInt(0), []byte("\"0\""), "0"},
|
||||||
|
{NewInt(100), []byte("\"100\""), "100"},
|
||||||
|
{NewInt(51842), []byte("\"51842\""), "51842"},
|
||||||
|
{NewInt(19513368), []byte("\"19513368\""), "19513368"},
|
||||||
|
{NewInt(999999999999), []byte("\"999999999999\""), "999999999999"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
bz, err := tc.i.MarshalJSON()
|
||||||
|
require.Nil(t, err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.bz, bz, "Marshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
err = (&i).UnmarshalJSON(bz)
|
||||||
|
require.Nil(t, err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.i, i, "Unmarshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
|
||||||
|
str, err := tc.i.MarshalAmino()
|
||||||
|
require.Nil(t, err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.str, str, "Marshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
err = (&i).UnmarshalAmino(str)
|
||||||
|
require.Nil(t, err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.i, i, "Unmarshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodingTableUint(t *testing.T) {
|
||||||
|
var i Uint
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
i Uint
|
||||||
|
bz []byte
|
||||||
|
str string
|
||||||
|
}{
|
||||||
|
{NewUint(0), []byte("\"0\""), "0"},
|
||||||
|
{NewUint(100), []byte("\"100\""), "100"},
|
||||||
|
{NewUint(51842), []byte("\"51842\""), "51842"},
|
||||||
|
{NewUint(19513368), []byte("\"19513368\""), "19513368"},
|
||||||
|
{NewUint(999999999999), []byte("\"999999999999\""), "999999999999"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tcnum, tc := range cases {
|
||||||
|
bz, err := tc.i.MarshalJSON()
|
||||||
|
require.Nil(t, err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.bz, bz, "Marshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
err = (&i).UnmarshalJSON(bz)
|
||||||
|
require.Nil(t, err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.i, i, "Unmarshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
|
||||||
|
str, err := tc.i.MarshalAmino()
|
||||||
|
require.Nil(t, err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.str, str, "Marshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
err = (&i).UnmarshalAmino(str)
|
||||||
|
require.Nil(t, err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
||||||
|
require.Equal(t, tc.i, i, "Unmarshaled value is different from expected. tc #%d", tcnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,18 @@ func defaultComponents(key sdk.StoreKey) (sdk.Context, *wire.Codec) {
|
||||||
return ctx, cdc
|
return ctx, cdc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewLinear(t *testing.T) {
|
||||||
|
cdc := wire.NewCodec()
|
||||||
|
require.NotPanics(t, func() { NewLinear(cdc, nil, nil) })
|
||||||
|
require.NotPanics(t, func() { NewLinear(cdc, nil, DefaultLinearKeys()) })
|
||||||
|
require.NotPanics(t, func() { NewLinear(cdc, nil, &LinearKeys{[]byte{0xAA}, []byte{0xBB}, []byte{0xCC}}) })
|
||||||
|
|
||||||
|
require.Panics(t, func() { NewLinear(cdc, nil, &LinearKeys{nil, nil, nil}) })
|
||||||
|
require.Panics(t, func() { NewLinear(cdc, nil, &LinearKeys{[]byte{0xAA}, nil, nil}) })
|
||||||
|
require.Panics(t, func() { NewLinear(cdc, nil, &LinearKeys{nil, []byte{0xBB}, nil}) })
|
||||||
|
require.Panics(t, func() { NewLinear(cdc, nil, &LinearKeys{nil, nil, []byte{0xCC}}) })
|
||||||
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestList(t *testing.T) {
|
||||||
key := sdk.NewKVStoreKey("test")
|
key := sdk.NewKVStoreKey("test")
|
||||||
ctx, cdc := defaultComponents(key)
|
ctx, cdc := defaultComponents(key)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
wire "github.com/cosmos/cosmos-sdk/wire"
|
wire "github.com/cosmos/cosmos-sdk/wire"
|
||||||
|
@ -317,3 +318,85 @@ func TestStringOverflow(t *testing.T) {
|
||||||
rat3.String(),
|
rat3.String(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests below uses randomness
|
||||||
|
// Since we are using *big.Rat as underlying value
|
||||||
|
// and (U/)Int is immutable value(see TestImmutability(U/)Int)
|
||||||
|
// it is safe to use randomness in the tests
|
||||||
|
func TestArithRat(t *testing.T) {
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
n1 := NewInt(int64(rand.Int31()))
|
||||||
|
d1 := NewInt(int64(rand.Int31()))
|
||||||
|
rat1 := NewRatFromInt(n1, d1)
|
||||||
|
|
||||||
|
n2 := NewInt(int64(rand.Int31()))
|
||||||
|
d2 := NewInt(int64(rand.Int31()))
|
||||||
|
rat2 := NewRatFromInt(n2, d2)
|
||||||
|
|
||||||
|
n1d2 := n1.Mul(d2)
|
||||||
|
n2d1 := n2.Mul(d1)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
nres Int
|
||||||
|
dres Int
|
||||||
|
rres Rat
|
||||||
|
}{
|
||||||
|
{n1d2.Add(n2d1), d1.Mul(d2), rat1.Add(rat2)},
|
||||||
|
{n1d2.Sub(n2d1), d1.Mul(d2), rat1.Sub(rat2)},
|
||||||
|
{n1.Mul(n2), d1.Mul(d2), rat1.Mul(rat2)},
|
||||||
|
{n1d2, n2d1, rat1.Quo(rat2)},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
require.Equal(t, NewRatFromInt(tc.nres, tc.dres), tc.rres)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompRat(t *testing.T) {
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
n1 := NewInt(int64(rand.Int31()))
|
||||||
|
d1 := NewInt(int64(rand.Int31()))
|
||||||
|
rat1 := NewRatFromInt(n1, d1)
|
||||||
|
|
||||||
|
n2 := NewInt(int64(rand.Int31()))
|
||||||
|
d2 := NewInt(int64(rand.Int31()))
|
||||||
|
rat2 := NewRatFromInt(n2, d2)
|
||||||
|
|
||||||
|
n1d2 := n1.Mul(d2)
|
||||||
|
n2d1 := n2.Mul(d1)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
ires bool
|
||||||
|
rres bool
|
||||||
|
}{
|
||||||
|
{n1d2.Equal(n2d1), rat1.Equal(rat2)},
|
||||||
|
{n1d2.GT(n2d1), rat1.GT(rat2)},
|
||||||
|
{n1d2.LT(n2d1), rat1.LT(rat2)},
|
||||||
|
{n1d2.GT(n2d1) || n1d2.Equal(n2d1), rat1.GTE(rat2)},
|
||||||
|
{n1d2.LT(n2d1) || n1d2.Equal(n2d1), rat1.LTE(rat2)},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
require.Equal(t, tc.ires, tc.rres)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImmutabilityRat(t *testing.T) {
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
n := int64(rand.Int31())
|
||||||
|
r := NewRat(n)
|
||||||
|
z := ZeroRat()
|
||||||
|
o := OneRat()
|
||||||
|
|
||||||
|
r.Add(z)
|
||||||
|
r.Sub(z)
|
||||||
|
r.Mul(o)
|
||||||
|
r.Quo(o)
|
||||||
|
|
||||||
|
require.Equal(t, n, r.RoundInt64())
|
||||||
|
require.True(t, NewRat(n).Equal(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResult(t *testing.T) {
|
||||||
|
var res Result
|
||||||
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
|
res.Data = []byte("data")
|
||||||
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
|
res.Code = ABCICodeType(1)
|
||||||
|
require.False(t, res.IsOK())
|
||||||
|
}
|
|
@ -25,3 +25,15 @@ func TestPrefixEndBytes(t *testing.T) {
|
||||||
require.Equal(t, test.expected, end)
|
require.Equal(t, test.expected, end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommitID(t *testing.T) {
|
||||||
|
var empty CommitID
|
||||||
|
require.True(t, empty.IsZero())
|
||||||
|
|
||||||
|
var nonempty CommitID
|
||||||
|
nonempty = CommitID{
|
||||||
|
Version: 1,
|
||||||
|
Hash: []byte("testhash"),
|
||||||
|
}
|
||||||
|
require.False(t, nonempty.IsZero())
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ func TestAppendTags(t *testing.T) {
|
||||||
b := NewTags("b", []byte("2"))
|
b := NewTags("b", []byte("2"))
|
||||||
c := a.AppendTags(b)
|
c := a.AppendTags(b)
|
||||||
require.Equal(t, c, Tags{MakeTag("a", []byte("1")), MakeTag("b", []byte("2"))})
|
require.Equal(t, c, Tags{MakeTag("a", []byte("1")), MakeTag("b", []byte("2"))})
|
||||||
|
require.Equal(t, c, Tags{MakeTag("a", []byte("1"))}.AppendTag("b", []byte("2")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmptyTags(t *testing.T) {
|
func TestEmptyTags(t *testing.T) {
|
||||||
|
@ -21,4 +22,14 @@ func TestEmptyTags(t *testing.T) {
|
||||||
func TestNewTags(t *testing.T) {
|
func TestNewTags(t *testing.T) {
|
||||||
b := NewTags("a", []byte("1"))
|
b := NewTags("a", []byte("1"))
|
||||||
require.Equal(t, b, Tags{MakeTag("a", []byte("1"))})
|
require.Equal(t, b, Tags{MakeTag("a", []byte("1"))})
|
||||||
|
|
||||||
|
require.Panics(t, func() { NewTags("a", []byte("1"), "b") })
|
||||||
|
require.Panics(t, func() { NewTags("a", 1) })
|
||||||
|
require.Panics(t, func() { NewTags(1, 1) })
|
||||||
|
require.Panics(t, func() { NewTags(true, false) })
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVPairTags(t *testing.T) {
|
||||||
|
a := NewTags("a", []byte("1"))
|
||||||
|
require.Equal(t, a, Tags(a.ToKVPairs()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,15 @@ func TestSortJSON(t *testing.T) {
|
||||||
|
|
||||||
for tcIndex, tc := range cases {
|
for tcIndex, tc := range cases {
|
||||||
got, err := SortJSON([]byte(tc.unsortedJSON))
|
got, err := SortJSON([]byte(tc.unsortedJSON))
|
||||||
if tc.wantErr != (err != nil) {
|
if tc.wantErr {
|
||||||
t.Fatalf("got %t, want: %t, tc #%d, err=%s", err != nil, tc.wantErr, tcIndex, err)
|
require.NotNil(t, err, "tc #%d", tcIndex)
|
||||||
|
require.Panics(t, func() { MustSortJSON([]byte(tc.unsortedJSON)) })
|
||||||
|
} else {
|
||||||
|
require.Nil(t, err, "tc #%d, err=%s", tcIndex, err)
|
||||||
|
require.NotPanics(t, func() { MustSortJSON([]byte(tc.unsortedJSON)) })
|
||||||
|
require.Equal(t, got, MustSortJSON([]byte(tc.unsortedJSON)))
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(t, string(got), tc.want)
|
require.Equal(t, string(got), tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue