Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(common): add docs for testutil and increase test coverage #1527

Merged
merged 49 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2ed7490
test(inflation): types coverage
Unique-Divine Jul 24, 2023
efac0d8
feat(wasm): no op handler + tests with updated shifter.wasm
Unique-Divine Jul 25, 2023
773dee4
Merge branch 'master' into realu/test-inflation
Unique-Divine Jul 25, 2023
2e7192a
linter
Unique-Divine Jul 25, 2023
b774c48
refactor: make it possible to use the encoding config without the app
Unique-Divine Jul 25, 2023
aa92edd
deps: remove usage of cosmossdk.io/depinject since it doesn't work ou…
Unique-Divine Jul 25, 2023
d263ffb
changelog
Unique-Divine Jul 25, 2023
8a01ec1
small refactor for better var names
Unique-Divine Jul 25, 2023
68c47ad
refactor: remove unused fn
Unique-Divine Jul 25, 2023
2aa65ed
refactor(simapp): simapp fns are not used outside the simapp dir or t…
Unique-Divine Jul 26, 2023
392d080
test(inflation): param set pairs
Unique-Divine Jul 26, 2023
e793851
test(inflation): test getters in params.go
Unique-Divine Jul 26, 2023
062dbfc
Merge branch 'realu/test-inflation' into realu/test-inflation-2
Unique-Divine Jul 26, 2023
d526b2a
linter
Unique-Divine Jul 26, 2023
dc5559c
test(inflation): run the suite
Unique-Divine Jul 26, 2023
7fb10e6
Squashed commit of the following:
Unique-Divine Jul 26, 2023
e4c1600
test(common): EnsureNibiruPrefix
Unique-Divine Jul 26, 2023
c19917b
test(sudo): remove unused fns and increase coverage
Unique-Divine Jul 26, 2023
bc33367
test(spot): wait another block for concurrency issue
Unique-Divine Jul 26, 2023
743652a
test(spot): wait another block for concurrency issue
Unique-Divine Jul 26, 2023
4e550a0
test(inflation): cover last few grpc queries
Unique-Divine Jul 26, 2023
378ace5
Merge branch 'realu/test-inflation' into realu/test-sudo
Unique-Divine Jul 26, 2023
7a47d59
ci: add concurrency statements to workflows
Unique-Divine Jul 26, 2023
53d2d16
Merge branch 'realu/test-inflation' into realu/test-sudo
Unique-Divine Jul 26, 2023
7780cc8
test(perp/cli): use the same server between runs for gen_market_test
Unique-Divine Jul 26, 2023
253cb65
refactor: make registration aspect of the encoding config constructor…
Unique-Divine Jul 26, 2023
eaefe17
Merge branch 'master' into realu/test-inflation
Unique-Divine Jul 26, 2023
2362461
(test.mk): add a test-coverage-integration command
Unique-Divine Jul 26, 2023
85933c4
Merge branch 'realu/test-inflation' into realu/test-sudo
Unique-Divine Jul 26, 2023
c7d0d26
Merge branch 'realu/test-sudo' into realu/test-determinism
Unique-Divine Jul 26, 2023
4327565
fix(ci): mistake in scheduling
Unique-Divine Jul 26, 2023
1aa88ae
refactor(testutil): organise network files
Unique-Divine Jul 26, 2023
be071ea
Merge branch 'master' into realu/test-determinism
Unique-Divine Jul 26, 2023
4e2c15b
refactor: DRY improvments for genesis cli tets
Unique-Divine Jul 26, 2023
3bf66d6
test(common): document and test BankersRound
Unique-Divine Jul 27, 2023
9659a54
fix(amm.go): small bug in ComputeSqrtDepth
Unique-Divine Jul 27, 2023
182786c
docs(testutil/cli): documentation for the Network and Validator structs
Unique-Divine Jul 27, 2023
35f04f5
Merge branch 'master' into realu/test-determinism
Unique-Divine Jul 27, 2023
bfb88d8
test(common): address utils test
Unique-Divine Jul 27, 2023
9395e79
changelog + linter
Unique-Divine Jul 27, 2023
0b5e87f
test(common): remove unused code + more tests
Unique-Divine Jul 28, 2023
0a56cd2
simplify the 'with' functions
Unique-Divine Aug 1, 2023
d7ea816
fix finicky tests
Unique-Divine Aug 1, 2023
582f274
Merge branch 'master' into realu/test-determinism
Unique-Divine Aug 1, 2023
cac831f
test(testutil): remove unused code + add tests
Unique-Divine Aug 2, 2023
28191fe
test(testutil): more tests + better var names
Unique-Divine Aug 2, 2023
c313b59
refactor: ExecTx -> Network.ExecTxCmd
Unique-Divine Aug 2, 2023
b0022cd
Merge branch 'master' into realu/test-determinism
Unique-Divine Aug 2, 2023
19a33bd
test,refactor: make getters to use in place of the 'PrintMnemonic' func
Unique-Divine Aug 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1520](https://github.com/NibiruChain/nibiru/pull/1520) - feat(wasm): no op handler + tests with updated contracts
* [#1521](https://github.com/NibiruChain/nibiru/pull/1521) - test(sudo): increase unit test coverage
* [#1523](https://github.com/NibiruChain/nibiru/pull/1523) - chore: bump cosmos-sdk to v0.47.4
* [#1527](https://github.com/NibiruChain/nibiru/pull/1527) - test(common): add docs for testutil and increase test coverage
* [#1536](https://github.com/NibiruChain/nibiru/pull/1536) - test(perp): add more tests to perp module and cli
* [#1533](https://github.com/NibiruChain/nibiru/pull/1533) - feat(perp): add differential fields to PositionChangedEvent

Expand Down Expand Up @@ -633,4 +634,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Testing

* [#695](https://github.com/NibiruChain/nibiru/pull/695) Add `OpenPosition` integration tests.
* [#692](https://github.com/NibiruChain/nibiru/pull/692) Add test coverage for Perp MsgServer methods.
* [#692](https://github.com/NibiruChain/nibiru/pull/692) Add test coverage for Perp MsgServer methods.
19 changes: 19 additions & 0 deletions x/common/address_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package common_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/NibiruChain/nibiru/x/common"
"github.com/NibiruChain/nibiru/x/common/testutil"
)

func TestAddress(t *testing.T) {
require.NotPanics(t, func() {
_, addrs := testutil.PrivKeyAddressPairs(5)
strs := common.AddrsToStrings(addrs...)
addrsOut := common.StringsToAddrs(strs...)
require.EqualValues(t, addrs, addrsOut)
})
}
36 changes: 3 additions & 33 deletions x/common/asset/pair.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,49 +149,19 @@ func (pairKeyEncoder) Decode(b []byte) (int, Pair) {
return i, MustNewPair(s)
}

//-----------------------------------------------------------------------------
Copy link
Member Author

@Unique-Divine Unique-Divine Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Searched with the LSP and and found that this type alias was largely unused, so I removed some of the dead code.

// Pairs

// Pairs is a set of Pair, one per pair.
type Pairs []Pair

// News constructs a new asset pair set. A panic will occur if one of
// MustNewPairs constructs a new asset pair set. A panic will occur if one of
// the provided pair names is invalid.
func News(pairStrings ...string) (pairs Pairs) {
func MustNewPairs(pairStrings ...string) (pairs []Pair) {
for _, pairString := range pairStrings {
pairs = append(pairs, MustNewPair(pairString))
}
return pairs
}

// Contains checks if a token pair is contained within 'Pairs'
func (haystack Pairs) Contains(needle Pair) bool {
for _, p := range haystack {
if p.Equal(needle) {
return true
}
}
return false
}

func (pairs Pairs) Strings() []string {
func PairsToStrings(pairs []Pair) []string {
pairsStrings := []string{}
for _, pair := range pairs {
pairsStrings = append(pairsStrings, pair.String())
}
return pairsStrings
}

func (pairs Pairs) Validate() error {
seenPairs := make(map[string]bool)
for _, pair := range pairs {
if seenPairs[pair.String()] {
return fmt.Errorf("duplicate pair %s", pair.String())
}
if err := pair.Validate(); err != nil {
return err
}
seenPairs[pair.String()] = true
}
return nil
}
103 changes: 90 additions & 13 deletions x/common/asset/pair_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package asset
package asset_test

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/NibiruChain/nibiru/app/codec"
"github.com/NibiruChain/nibiru/x/common/asset"
"github.com/NibiruChain/nibiru/x/common/denoms"
)

Expand All @@ -20,17 +23,17 @@ func TestTryNewPair(t *testing.T) {
{
"only one token",
denoms.NIBI,
ErrInvalidTokenPair,
asset.ErrInvalidTokenPair,
},
{
"more than 2 tokens",
fmt.Sprintf("%s:%s:%s", denoms.NIBI, denoms.NUSD, denoms.USDC),
ErrInvalidTokenPair,
asset.ErrInvalidTokenPair,
},
{
"different separator",
fmt.Sprintf("%s,%s", denoms.NIBI, denoms.NUSD),
ErrInvalidTokenPair,
asset.ErrInvalidTokenPair,
},
{
"correct pair",
Expand All @@ -57,7 +60,7 @@ func TestTryNewPair(t *testing.T) {
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
_, err := TryNewPair(tc.tokenStr)
_, err := asset.TryNewPair(tc.tokenStr)
if tc.err != nil {
require.ErrorContains(t, err, tc.err.Error())
} else {
Expand All @@ -68,17 +71,17 @@ func TestTryNewPair(t *testing.T) {
}

func TestGetDenoms(t *testing.T) {
pair := MustNewPair("uatom:unibi")
pair := asset.MustNewPair("uatom:unibi")

require.Equal(t, "uatom", pair.BaseDenom())
require.Equal(t, "unibi", pair.QuoteDenom())
}

func TestEquals(t *testing.T) {
pair := MustNewPair("abc:xyz")
matchingOther := MustNewPair("abc:xyz")
mismatchToken1 := MustNewPair("abc:abc")
inversePair := MustNewPair("xyz:abc")
pair := asset.MustNewPair("abc:xyz")
matchingOther := asset.MustNewPair("abc:xyz")
mismatchToken1 := asset.MustNewPair("abc:abc")
inversePair := asset.MustNewPair("xyz:abc")

require.True(t, pair.Equal(matchingOther))
require.False(t, pair.Equal(inversePair))
Expand All @@ -87,17 +90,91 @@ func TestEquals(t *testing.T) {

func TestMustNewAssetPair(t *testing.T) {
require.Panics(t, func() {
MustNewPair("aaa:bbb:ccc")
asset.MustNewPair("aaa:bbb:ccc")
})

require.NotPanics(t, func() {
MustNewPair("aaa:bbb")
asset.MustNewPair("aaa:bbb")
})
}

func TestInverse(t *testing.T) {
pair := MustNewPair("abc:xyz")
pair := asset.MustNewPair("abc:xyz")
inverse := pair.Inverse()
require.Equal(t, "xyz", inverse.BaseDenom())
require.Equal(t, "abc", inverse.QuoteDenom())
}

func TestMarshalJSON(t *testing.T) {
cdc := codec.MakeEncodingConfig()

testCases := []struct {
name string
input asset.Pair
strOutput string
}{
{name: "happy-0", input: asset.Pair("abc:xyz"), strOutput: "\"abc:xyz\""},
{name: "happy-1", input: asset.Pair("abc:xyz:foo"), strOutput: "\"abc:xyz:foo\""},
{name: "happy-2", input: asset.Pair("abc"), strOutput: "\"abc\""},
{name: "empty", input: asset.Pair(""), strOutput: "\"\""},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// MarshalJSON with codec.LegacyAmino
jsonBz, err := cdc.Amino.MarshalJSON(tc.input)
require.NoError(t, err)
require.Equal(t, tc.strOutput, string(jsonBz))

// MarshalJSON on custom type
jsonBzCustom, err := tc.input.MarshalJSON()
require.NoError(t, err)
require.Equal(t, jsonBzCustom, jsonBz)

// UnmarshalJSON with codec.LegacyAmino
newPair := new(asset.Pair)
require.NoError(t, cdc.Amino.UnmarshalJSON(jsonBz, newPair))
require.Equal(t, tc.input, *newPair)

// UnmarshalJSON on custom type
newNewPair := new(asset.Pair)
*newNewPair = tc.input
require.NoError(t, newNewPair.UnmarshalJSON(jsonBz))

// Marshal and Unmarshal (to bytes) test
bz, err := tc.input.Marshal()
require.NoError(t, err)
newNewNewPair := new(asset.Pair)
require.NoError(t, newNewNewPair.Unmarshal(bz))
require.Equal(t, tc.input, *newNewNewPair)
})
}
}

func TestPairsUtils(t *testing.T) {
testCases := []struct {
pairStrs []string
expectPanic bool
}{
{pairStrs: []string{"eth:usd", "btc:usd", "atom:usd"}, expectPanic: false},
{pairStrs: []string{"eth:usd", "", "abc"}, expectPanic: true},
{pairStrs: []string{"eth:usd:ftt", "btc:usd"}, expectPanic: true},
}

var panicTestFn func(t require.TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{})

for idx, tc := range testCases {
t.Run(fmt.Sprint(idx), func(t *testing.T) {
if tc.expectPanic {
panicTestFn = require.Panics
} else {
panicTestFn = require.NotPanics
}
panicTestFn(t, func() {
pairs := asset.MustNewPairs(tc.pairStrs...)
newPairStrs := asset.PairsToStrings(pairs)
require.Equal(t, tc.pairStrs, newPairStrs)
})
})
}
}
44 changes: 33 additions & 11 deletions x/common/dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the code more descriptive here and added tests for it. Since the Sqrt is used in x/perp, it's important to make sure these functions don't panic.

const (
// number of decimal places
Precision = 18
PrecisionExponent = 18

// bits required to represent the above precision
// Ceiling[Log2[10^Precision - 1]]
Expand All @@ -25,9 +25,11 @@
)

var (
precisionReuse = new(big.Int).Exp(big.NewInt(10), big.NewInt(Precision), nil)
fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2))
oneInt = big.NewInt(1)
// precisionInt: 10 ** PrecisionExponent
precisionInt = new(big.Int).Exp(big.NewInt(10), big.NewInt(PrecisionExponent), nil)
// halfPrecisionInt: (10 ** PrecisionExponent) / 2
halfPrecisionInt = new(big.Int).Quo(precisionInt, big.NewInt(2))
oneInt = big.NewInt(1)
)

// MustSqrtDec computes the square root of the input decimal using its
Expand Down Expand Up @@ -119,8 +121,9 @@
// |_____: / | $$$ |
// |________|

// Remove a Precision amount of rightmost digits and perform bankers rounding
// on the remainder (gaussian rounding) on the digits which have been removed.
// ChopPrecisionAndRound: Remove a Precision amount of rightmost digits and
// perform bankers rounding on the remainder (gaussian rounding) on the digits
// which have been removed.
//
// Mutates the input. Use the non-mutative version if that is undesired
func ChopPrecisionAndRound(d *big.Int) *big.Int {
Expand All @@ -133,20 +136,39 @@
return d
}

// get the truncated quotient and remainder
// Divide out the 'precisionInt', which truncates to a quotient and remainder.
quo, rem := d, big.NewInt(0)
quo, rem = quo.QuoRem(d, precisionReuse, rem)
quo, rem = quo.QuoRem(d, precisionInt, rem)

Check warning on line 141 in x/common/dec.go

View check run for this annotation

Codecov / codecov/patch

x/common/dec.go#L141

Added line #L141 was not covered by tests

if rem.Sign() == 0 { // remainder is zero
return BankersRound(quo, rem, halfPrecisionInt)

Check warning on line 143 in x/common/dec.go

View check run for this annotation

Codecov / codecov/patch

x/common/dec.go#L143

Added line #L143 was not covered by tests
}

// BankersRound: Banker's rounding is a method commonly used in banking and
// accounting to reduce roudning bias when processing large volumes of rounded
// numbers.
//
// 1. If the remainder < half precision, round down
// 2. If the remainder > half precision, round up
// 3. If remainder == half precision, round to the nearest even number
//
// The name comes from the idea that it provides egalitarian rounding that
// doesn't consistently favor one party over another (e.g. always rounding up).
// With this method, rounding errors tend to cancel out rather than
// accumulating in one direction.
func BankersRound(quo, rem, halfPrecision *big.Int) *big.Int {
// Zero remainder after dividing precision means => no rounding is needed.
if rem.Sign() == 0 {
return quo
}

switch rem.Cmp(fivePrecision) {
// Nonzero remainder after dividing precision means => do banker's rounding
switch rem.Cmp(halfPrecision) {
case -1:
return quo
case 1:
return quo.Add(quo, oneInt)
default: // bankers rounding must take place
default:
// default case: bankers rounding must take place
// always round to an even number
if quo.Bit(0) == 0 {
return quo
Expand Down
Loading
Loading