Skip to content

Commit

Permalink
[1658]: Unit tests on GetFulfillmentAssetsAmt and NewPartialFulfillment.
Browse files Browse the repository at this point in the history
  • Loading branch information
SpicyLemon committed Sep 27, 2023
1 parent 805ce18 commit d921806
Showing 1 changed file with 282 additions and 10 deletions.
292 changes: 282 additions & 10 deletions x/exchange/fulfillment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func copyOrderFulfillment(f *OrderFulfillment) *OrderFulfillment {
FeesToPay: copyCoins(f.FeesToPay),
OrderFeesLeft: copyCoins(f.OrderFeesLeft),
PriceFilledAmt: copySDKInt(f.PriceFilledAmt),
PriceUnfilledAmt: copySDKInt(f.PriceFilledAmt),
PriceUnfilledAmt: copySDKInt(f.PriceUnfilledAmt),
}
}

Expand Down Expand Up @@ -132,7 +132,7 @@ func TestNewOrderFulfillment(t *testing.T) {
{
name: "nil sub-order",
order: NewOrder(1),
expPanic: "unknown sub-order type <nil>: does not implement SubOrderI",
expPanic: nilSubTypeErr(1),
},
{
name: "ask order",
Expand Down Expand Up @@ -203,7 +203,6 @@ func TestNewOrderFulfillment(t *testing.T) {
if t.Failed() {
t.Logf(" Actual: %s", orderFulfillmentString(actual))
t.Logf("Expected: %s", orderFulfillmentString(tc.expected))

}
}()

Expand Down Expand Up @@ -947,6 +946,8 @@ func assertEqualOrderFulfillments(t *testing.T, expected, actual *OrderFulfillme
assert.Equalf(t, expected.OrderFeesLeft, actual.OrderFeesLeft, msg("OrderFulfillment.OrderFeesLeft"), args...)
assert.Equalf(t, expected.PriceFilledAmt, actual.PriceFilledAmt, msg("OrderFulfillment.PriceFilledAmt"), args...)
assert.Equalf(t, expected.PriceUnfilledAmt, actual.PriceUnfilledAmt, msg("OrderFulfillment.PriceUnfilledAmt"), args...)
t.Logf(" Actual: %s", orderFulfillmentString(actual))
t.Logf("Expected: %s", orderFulfillmentString(expected))
return false
}

Expand Down Expand Up @@ -1168,8 +1169,6 @@ func TestOrderFulfillment_Apply(t *testing.T) {
assertions.AssertErrorValue(t, err, tc.expErr, "Apply error")
if !assertEqualOrderFulfillments(t, tc.expResult, tc.receiver, "order fulfillment after .Apply") {
t.Logf("Original: %s", orderFulfillmentString(orig))
t.Logf(" Actual: %s", orderFulfillmentString(tc.receiver))
t.Logf("Expected: %s", orderFulfillmentString(tc.expResult))
}
})
}
Expand Down Expand Up @@ -1290,9 +1289,7 @@ func TestOrderFulfillment_ApplyLeftoverPrice(t *testing.T) {
}
assertions.RequirePanicEquals(t, testFunc, tc.expPanic, "ApplyLeftoverPrice")
if !assertEqualOrderFulfillments(t, tc.expFulfillment, tc.receiver, "OrderFulfillment after .ApplyLeftoverPrice") {
t.Logf("Original OrderFulfillment: %s", orderFulfillmentString(origFulfillment))
t.Logf(" Actual OrderFulfillment: %s", orderFulfillmentString(tc.receiver))
t.Logf("Expected OrderFulfillment: %s", orderFulfillmentString(tc.expFulfillment))
t.Logf("Original: %s", orderFulfillmentString(origFulfillment))
}
if !assert.Equal(t, tc.expAskSplit, tc.askSplit, "askSplit after ApplyLeftoverPrice") {
t.Logf("Original askSplit: %s", orderSplitString(origSplit))
Expand All @@ -1309,9 +1306,284 @@ func TestOrderFulfillment_ApplyLeftoverPrice(t *testing.T) {

// TODO[1658]: func TestFulfill(t *testing.T)

// TODO[1658]: func TestGetFulfillmentAssetsAmt(t *testing.T)
func TestGetFulfillmentAssetsAmt(t *testing.T) {
newAskOF := func(orderID uint64, assetsUnfilled int64, assetDenom string) *OrderFulfillment {
return &OrderFulfillment{
Order: NewOrder(orderID).WithAsk(&AskOrder{
Assets: sdk.NewInt64Coin(assetDenom, 999),
}),
AssetsUnfilledAmt: sdkmath.NewInt(assetsUnfilled),
}
}
newBidOF := func(orderID uint64, assetsUnfilled int64, assetDenom string) *OrderFulfillment {
return &OrderFulfillment{
Order: NewOrder(orderID).WithBid(&BidOrder{
Assets: sdk.NewInt64Coin(assetDenom, 999),
}),
AssetsUnfilledAmt: sdkmath.NewInt(assetsUnfilled),
}
}

cases := []struct {
name string
of1Unfilled int64
of2Unfilled int64
expAmt int64
}{
{name: "of1 zero", of1Unfilled: 0, of2Unfilled: 3, expAmt: 0},
{name: "of1 negative", of1Unfilled: -4, of2Unfilled: 3, expAmt: 0},
{name: "of2 zero", of1Unfilled: 5, of2Unfilled: 0, expAmt: 0},
{name: "of2 negative", of1Unfilled: 5, of2Unfilled: -6, expAmt: 0},
{name: "equal", of1Unfilled: 8, of2Unfilled: 8, expAmt: 8},
{name: "of1 has fewer", of1Unfilled: 9, of2Unfilled: 10, expAmt: 9},
{name: "of2 has fewer", of1Unfilled: 12, of2Unfilled: 11, expAmt: 11},
}

type testCase struct {
name string
of1 *OrderFulfillment
of2 *OrderFulfillment
expAmt sdkmath.Int
expErr string
}

tests := make([]testCase, 0, len(cases)*4)

for _, c := range cases {
newTests := []testCase{
{
name: "ask bid " + c.name,
of1: newAskOF(1, c.of1Unfilled, "one"),
of2: newBidOF(2, c.of2Unfilled, "two"),
expAmt: sdkmath.NewInt(c.expAmt),
},
{
name: "bid ask " + c.name,
of1: newBidOF(1, c.of1Unfilled, "one"),
of2: newAskOF(2, c.of2Unfilled, "two"),
expAmt: sdkmath.NewInt(c.expAmt),
},
{
name: "ask ask " + c.name,
of1: newAskOF(1, c.of1Unfilled, "one"),
of2: newAskOF(2, c.of2Unfilled, "two"),
expAmt: sdkmath.NewInt(c.expAmt),
},
{
name: "bid bid " + c.name,
of1: newBidOF(1, c.of1Unfilled, "one"),
of2: newBidOF(2, c.of2Unfilled, "two"),
expAmt: sdkmath.NewInt(c.expAmt),
},
}
if c.expAmt == 0 {
newTests[0].expErr = fmt.Sprintf("cannot fill ask order 1 having assets left \"%done\" "+
"with bid order 2 having assets left \"%dtwo\": zero or negative assets left",
c.of1Unfilled, c.of2Unfilled)
newTests[1].expErr = fmt.Sprintf("cannot fill bid order 1 having assets left \"%done\" "+
"with ask order 2 having assets left \"%dtwo\": zero or negative assets left",
c.of1Unfilled, c.of2Unfilled)
newTests[2].expErr = fmt.Sprintf("cannot fill ask order 1 having assets left \"%done\" "+
"with ask order 2 having assets left \"%dtwo\": zero or negative assets left",
c.of1Unfilled, c.of2Unfilled)
newTests[3].expErr = fmt.Sprintf("cannot fill bid order 1 having assets left \"%done\" "+
"with bid order 2 having assets left \"%dtwo\": zero or negative assets left",
c.of1Unfilled, c.of2Unfilled)
}
tests = append(tests, newTests...)
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
if len(tc.expErr) > 0 {
tc.expAmt = sdkmath.ZeroInt()
}
origOF1 := copyOrderFulfillment(tc.of1)
origOF2 := copyOrderFulfillment(tc.of2)

var amt sdkmath.Int
var err error
testFunc := func() {
amt, err = GetFulfillmentAssetsAmt(tc.of1, tc.of2)
}
require.NotPanics(t, testFunc, "GetFulfillmentAssetsAmt")
assertions.AssertErrorValue(t, err, tc.expErr, "GetFulfillmentAssetsAmt error")
assert.Equal(t, tc.expAmt, amt, "GetFulfillmentAssetsAmt amount")
assertEqualOrderFulfillments(t, origOF1, tc.of1, "of1 after GetFulfillmentAssetsAmt")
assertEqualOrderFulfillments(t, origOF2, tc.of2, "of2 after GetFulfillmentAssetsAmt")
})
}
}

func TestNewPartialFulfillment(t *testing.T) {
sdkNewInt64CoinP := func(denom string, amt int64) *sdk.Coin {
rv := sdk.NewInt64Coin(denom, amt)
return &rv
}

tests := []struct {
name string
f *OrderFulfillment
exp *PartialFulfillment
expPanic string
}{
{
name: "ask order fees left",
f: &OrderFulfillment{
Order: NewOrder(54).WithAsk(&AskOrder{
MarketId: 12,
Seller: "the seller",
Assets: sdk.NewInt64Coin("apple", 1234),
Price: sdk.NewInt64Coin("pear", 9876),
SellerSettlementFlatFee: sdkNewInt64CoinP("fig", 55),
AllowPartial: true,
}),
AssetsFilledAmt: sdkmath.NewInt(234),
AssetsUnfilledAmt: sdkmath.NewInt(1000),
PriceAppliedAmt: sdkmath.NewInt(10000),
PriceLeftAmt: sdkmath.NewInt(-124),
OrderFeesLeft: sdk.NewCoins(sdk.NewInt64Coin("fig", 50)),
PriceFilledAmt: sdkmath.NewInt(876),
PriceUnfilledAmt: sdkmath.NewInt(9000),
},
exp: &PartialFulfillment{
NewOrder: NewOrder(54).WithAsk(&AskOrder{
MarketId: 12,
Seller: "the seller",
Assets: sdk.NewInt64Coin("apple", 1000),
Price: sdk.NewInt64Coin("pear", 9000),
SellerSettlementFlatFee: sdkNewInt64CoinP("fig", 50),
AllowPartial: true,
}),
AssetsFilled: sdk.NewInt64Coin("apple", 234),
PriceFilled: sdk.NewInt64Coin("pear", 876),
},
},
{
name: "ask order no fees left",
f: &OrderFulfillment{
Order: NewOrder(54).WithAsk(&AskOrder{
MarketId: 12,
Seller: "the seller",
Assets: sdk.NewInt64Coin("apple", 1234),
Price: sdk.NewInt64Coin("pear", 9876),
SellerSettlementFlatFee: sdkNewInt64CoinP("fig", 55),
AllowPartial: false,
}),
AssetsFilledAmt: sdkmath.NewInt(234),
AssetsUnfilledAmt: sdkmath.NewInt(1000),
PriceAppliedAmt: sdkmath.NewInt(10000),
PriceLeftAmt: sdkmath.NewInt(-124),
OrderFeesLeft: nil,
PriceFilledAmt: sdkmath.NewInt(876),
PriceUnfilledAmt: sdkmath.NewInt(9000),
},
exp: &PartialFulfillment{
NewOrder: NewOrder(54).WithAsk(&AskOrder{
MarketId: 12,
Seller: "the seller",
Assets: sdk.NewInt64Coin("apple", 1000),
Price: sdk.NewInt64Coin("pear", 9000),
SellerSettlementFlatFee: nil,
AllowPartial: false,
}),
AssetsFilled: sdk.NewInt64Coin("apple", 234),
PriceFilled: sdk.NewInt64Coin("pear", 876),
},
expPanic: "",
},
{
name: "ask order multiple fees left",
f: &OrderFulfillment{
Order: NewOrder(54).WithAsk(&AskOrder{
MarketId: 12,
Seller: "the seller",
Assets: sdk.NewInt64Coin("apple", 1234),
Price: sdk.NewInt64Coin("pear", 9876),
SellerSettlementFlatFee: sdkNewInt64CoinP("fig", 55),
AllowPartial: true,
}),
AssetsFilledAmt: sdkmath.NewInt(234),
AssetsUnfilledAmt: sdkmath.NewInt(1000),
PriceAppliedAmt: sdkmath.NewInt(10000),
PriceLeftAmt: sdkmath.NewInt(-124),
OrderFeesLeft: sdk.NewCoins(sdk.NewInt64Coin("fig", 50), sdk.NewInt64Coin("grape", 1)),
PriceFilledAmt: sdkmath.NewInt(876),
PriceUnfilledAmt: sdkmath.NewInt(9000),
},
expPanic: "partially filled ask order 54 somehow has multiple denoms in fees left \"50fig,1grape\"",
},
{
name: "bid order",
f: &OrderFulfillment{
Order: NewOrder(54).WithBid(&BidOrder{
MarketId: 12,
Buyer: "the buyer",
Assets: sdk.NewInt64Coin("apple", 1234),
Price: sdk.NewInt64Coin("pear", 9876),
BuyerSettlementFees: sdk.NewCoins(sdk.NewInt64Coin("fig", 55), sdk.NewInt64Coin("grape", 12)),
AllowPartial: true,
}),
AssetsFilledAmt: sdkmath.NewInt(234),
AssetsUnfilledAmt: sdkmath.NewInt(1000),
PriceAppliedAmt: sdkmath.NewInt(9875),
PriceLeftAmt: sdkmath.NewInt(1),
OrderFeesLeft: sdk.NewCoins(sdk.NewInt64Coin("fig", 50)),
PriceFilledAmt: sdkmath.NewInt(876),
PriceUnfilledAmt: sdkmath.NewInt(9000),
},
exp: &PartialFulfillment{
NewOrder: NewOrder(54).WithBid(&BidOrder{
MarketId: 12,
Buyer: "the buyer",
Assets: sdk.NewInt64Coin("apple", 1000),
Price: sdk.NewInt64Coin("pear", 9000),
BuyerSettlementFees: sdk.NewCoins(sdk.NewInt64Coin("fig", 50)),
AllowPartial: true,
}),
AssetsFilled: sdk.NewInt64Coin("apple", 234),
PriceFilled: sdk.NewInt64Coin("pear", 876),
},
},
{
name: "nil order type",
f: &OrderFulfillment{
Order: NewOrder(57),
AssetsFilledAmt: sdkmath.NewInt(5),
PriceFilledAmt: sdkmath.NewInt(6),
},
expPanic: nilSubTypeErr(57),
},
{
name: "unknown order type",
f: &OrderFulfillment{
Order: &Order{OrderId: 58, Order: &unknownOrderType{}},
AssetsFilledAmt: sdkmath.NewInt(5),
PriceFilledAmt: sdkmath.NewInt(6),
},
expPanic: unknownSubTypeErr(58),
},
// I don't feel like creating a 3rd order type that implements SubOrderI which would be needed in order to
// have a test case reach the final "order %d has unknown type %q" panic at the end of the func.
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
origF := copyOrderFulfillment(tc.f)

// TODO[1658]: func TestNewPartialFulfillment(t *testing.T)
var actual *PartialFulfillment
testFunc := func() {
actual = NewPartialFulfillment(tc.f)
}
assertions.RequirePanicEquals(t, testFunc, tc.expPanic, "NewPartialFulfillment")
if !assert.Equal(t, tc.exp, actual, "NewPartialFulfillment result") {
t.Logf(" Actual: %s", partialFulfillmentString(actual))
t.Logf("Expected: %s", partialFulfillmentString(tc.exp))
}
assertEqualOrderFulfillments(t, origF, tc.f, "OrderFulfillment after NewPartialFulfillment")
})
}
}

// TODO[1658]: func TestBuildFulfillments(t *testing.T)

Expand Down

0 comments on commit d921806

Please sign in to comment.