add3034b43
Users with a partner package plan should be unable to replace their plan's coupon. This change enforces this behavior by rejecting coupon application attempts from users that meet this criteria. Change-Id: I6383d19f2c7fbd9e1a2826473b2f867ea8a8ea3e
244 lines
5.9 KiB
Go
244 lines
5.9 KiB
Go
// Copyright (C) 2022 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package paymentsconfig_test
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"storj.io/storj/satellite/payments"
|
|
"storj.io/storj/satellite/payments/paymentsconfig"
|
|
)
|
|
|
|
func TestProjectUsagePriceOverrides(t *testing.T) {
|
|
type Prices map[string]payments.ProjectUsagePriceModel
|
|
|
|
cases := []struct {
|
|
testID string
|
|
configValue string
|
|
expectedModel Prices
|
|
}{
|
|
{
|
|
testID: "empty",
|
|
configValue: "",
|
|
expectedModel: Prices{},
|
|
}, {
|
|
testID: "missing prices",
|
|
configValue: "partner",
|
|
}, {
|
|
testID: "missing partner",
|
|
configValue: ":1,2,3",
|
|
}, {
|
|
testID: "too few prices",
|
|
configValue: "partner:1",
|
|
}, {
|
|
testID: "single price override",
|
|
configValue: "partner:1,2,3",
|
|
expectedModel: Prices{
|
|
// Shift is to change the precision from TB dollars to MB cents
|
|
"partner": payments.ProjectUsagePriceModel{
|
|
StorageMBMonthCents: decimal.NewFromInt(1).Shift(-4),
|
|
EgressMBCents: decimal.NewFromInt(2).Shift(-4),
|
|
SegmentMonthCents: decimal.NewFromInt(3).Shift(2),
|
|
},
|
|
},
|
|
}, {
|
|
testID: "too many prices",
|
|
configValue: "partner:1,2,3,4",
|
|
}, {
|
|
testID: "invalid decimal",
|
|
configValue: "partner:0.0.1,2,3",
|
|
}, {
|
|
testID: "multiple price overrides",
|
|
configValue: "partner1:1,2,3;partner2:4,5,6",
|
|
expectedModel: Prices{
|
|
"partner1": payments.ProjectUsagePriceModel{
|
|
StorageMBMonthCents: decimal.NewFromInt(1).Shift(-4),
|
|
EgressMBCents: decimal.NewFromInt(2).Shift(-4),
|
|
SegmentMonthCents: decimal.NewFromInt(3).Shift(2),
|
|
},
|
|
"partner2": payments.ProjectUsagePriceModel{
|
|
StorageMBMonthCents: decimal.NewFromInt(4).Shift(-4),
|
|
EgressMBCents: decimal.NewFromInt(5).Shift(-4),
|
|
SegmentMonthCents: decimal.NewFromInt(6).Shift(2),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
c := c
|
|
t.Run(c.testID, func(t *testing.T) {
|
|
price := &paymentsconfig.ProjectUsagePriceOverrides{}
|
|
err := price.Set(c.configValue)
|
|
if c.expectedModel == nil {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
|
|
strParts := strings.Split(price.String(), ";")
|
|
sort.Strings(strParts)
|
|
require.Equal(t, c.configValue, strings.Join(strParts, ";"))
|
|
|
|
models, err := price.ToModels()
|
|
require.NoError(t, err)
|
|
require.Len(t, models, len(c.expectedModel))
|
|
for partner, price := range c.expectedModel {
|
|
model := models[partner]
|
|
require.Contains(t, models, partner)
|
|
require.Equal(t, price.StorageMBMonthCents, model.StorageMBMonthCents)
|
|
require.Equal(t, price.EgressMBCents, model.EgressMBCents)
|
|
require.Equal(t, price.SegmentMonthCents, model.SegmentMonthCents)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPackagePlans(t *testing.T) {
|
|
type packages map[string]payments.PackagePlan
|
|
|
|
cases := []struct {
|
|
testID string
|
|
configValue string
|
|
expectedPackagePlans packages
|
|
}{
|
|
{
|
|
testID: "empty",
|
|
configValue: "",
|
|
expectedPackagePlans: packages{},
|
|
},
|
|
{
|
|
testID: "missing couponID and price",
|
|
configValue: "partner",
|
|
},
|
|
{
|
|
testID: "missing partner",
|
|
configValue: ":abc123,100",
|
|
}, {
|
|
testID: "empty coupon ID",
|
|
configValue: "partner:,1",
|
|
}, {
|
|
testID: "empty price",
|
|
configValue: "partner:abc123,",
|
|
},
|
|
{
|
|
testID: "too few values",
|
|
configValue: "partner:abc123",
|
|
},
|
|
{
|
|
testID: "too many values",
|
|
configValue: "partner:abc123,100,200",
|
|
},
|
|
{
|
|
testID: "single package plan",
|
|
configValue: "partner1:abc123,100",
|
|
expectedPackagePlans: packages{
|
|
"partner1": payments.PackagePlan{
|
|
CouponID: "abc123",
|
|
Price: 100,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
testID: "multiple package plans",
|
|
configValue: "partner1:abc123,100;partner2:321bca,200",
|
|
expectedPackagePlans: packages{
|
|
"partner1": payments.PackagePlan{
|
|
CouponID: "abc123",
|
|
Price: 100,
|
|
},
|
|
"partner2": payments.PackagePlan{
|
|
CouponID: "321bca",
|
|
Price: 200,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
c := c
|
|
t.Run(c.testID, func(t *testing.T) {
|
|
packagePlans := paymentsconfig.PackagePlans{}
|
|
err := packagePlans.Set(c.configValue)
|
|
if c.expectedPackagePlans == nil {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
|
|
strParts := strings.Split(packagePlans.String(), ";")
|
|
sort.Strings(strParts)
|
|
require.Equal(t, c.configValue, strings.Join(strParts, ";"))
|
|
|
|
for k, v := range c.expectedPackagePlans {
|
|
p, err := packagePlans.Get([]byte(k))
|
|
require.NoError(t, err)
|
|
require.Equal(t, v, p)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPackagePlansGet(t *testing.T) {
|
|
partner := "partnerName1"
|
|
coupon := "abc123"
|
|
price := int64(100)
|
|
configStr := fmt.Sprintf("%s:%s,%d", partner, coupon, price)
|
|
|
|
packagePlans := paymentsconfig.PackagePlans{}
|
|
require.NoError(t, packagePlans.Set(configStr))
|
|
|
|
cases := []struct {
|
|
testID string
|
|
userAgent []byte
|
|
shouldPass bool
|
|
}{
|
|
{
|
|
testID: "user agent matches partner",
|
|
userAgent: []byte(partner),
|
|
shouldPass: true,
|
|
},
|
|
{
|
|
testID: "partner is first entry of user agent",
|
|
userAgent: []byte(partner + "/0.1.2"),
|
|
shouldPass: true,
|
|
},
|
|
{
|
|
testID: "partner is not first entry of user agent",
|
|
userAgent: []byte("app2/1.2.3 " + partner + "/1.2.3"),
|
|
shouldPass: true,
|
|
},
|
|
{
|
|
testID: "partner is a prefix of user agent, but not equal",
|
|
userAgent: []byte("partnerName12/1.2.3"),
|
|
shouldPass: false,
|
|
},
|
|
{
|
|
testID: "partner does not exist in user agent",
|
|
userAgent: []byte("partnerName2/1.2.3"),
|
|
shouldPass: false,
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.testID, func(t *testing.T) {
|
|
p, err := packagePlans.Get(c.userAgent)
|
|
if c.shouldPass {
|
|
require.NoError(t, err)
|
|
require.Equal(t, coupon, p.CouponID)
|
|
require.Equal(t, price, p.Price)
|
|
} else {
|
|
require.Error(t, err)
|
|
require.Empty(t, p)
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|