5f6fccc6e8
Our current endpoints bail on us, if the column data is null. Thus we need to take the intermediate step and set the default to a fixed value and reset those with the following release. It sets the default column value to our current config values of 50GB for storage and bandwidth and 100 buckets, while still enabling the field to be nullable. All 0 values are migrated to be the default as well to ensure they can keep using their projects, as with the original change, 0 actually means 0. Change-Id: I797be80ce2d2105091599dc1b3fc76f74336b66b
347 lines
11 KiB
Go
347 lines
11 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package stripecoinpayments_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"storj.io/common/memory"
|
|
"storj.io/common/testcontext"
|
|
"storj.io/common/testrand"
|
|
"storj.io/common/uuid"
|
|
"storj.io/storj/satellite"
|
|
"storj.io/storj/satellite/console"
|
|
"storj.io/storj/satellite/payments"
|
|
"storj.io/storj/satellite/payments/stripecoinpayments"
|
|
"storj.io/storj/satellite/satellitedb/satellitedbtest"
|
|
)
|
|
|
|
func TestCouponRepository(t *testing.T) {
|
|
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
|
|
couponsRepo := db.StripeCoinPayments().Coupons()
|
|
coupon := payments.Coupon{
|
|
Duration: 2,
|
|
Amount: 10,
|
|
Status: payments.CouponActive,
|
|
Description: "description",
|
|
UserID: testrand.UUID(),
|
|
}
|
|
|
|
now := time.Now().UTC()
|
|
|
|
t.Run("insert", func(t *testing.T) {
|
|
_, err := couponsRepo.Insert(ctx, coupon)
|
|
require.NoError(t, err)
|
|
|
|
coupons, err := couponsRepo.List(ctx, payments.CouponActive)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(coupons))
|
|
coupon = coupons[0]
|
|
})
|
|
|
|
t.Run("update", func(t *testing.T) {
|
|
_, err := couponsRepo.Update(ctx, coupon.ID, payments.CouponUsed)
|
|
require.NoError(t, err)
|
|
|
|
coupons, err := couponsRepo.List(ctx, payments.CouponUsed)
|
|
require.NoError(t, err)
|
|
require.Equal(t, payments.CouponUsed, coupons[0].Status)
|
|
coupon = coupons[0]
|
|
})
|
|
|
|
t.Run("get latest on empty table return stripecoinpayments.ErrNoCouponUsages", func(t *testing.T) {
|
|
_, err := couponsRepo.GetLatest(ctx, coupon.ID)
|
|
require.Error(t, err)
|
|
require.Equal(t, true, stripecoinpayments.ErrNoCouponUsages.Has(err))
|
|
})
|
|
|
|
t.Run("total on empty table returns 0", func(t *testing.T) {
|
|
total, err := couponsRepo.TotalUsage(ctx, coupon.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, int64(0), total)
|
|
})
|
|
|
|
t.Run("add usage", func(t *testing.T) {
|
|
err := couponsRepo.AddUsage(ctx, stripecoinpayments.CouponUsage{
|
|
CouponID: coupon.ID,
|
|
Amount: 1,
|
|
Period: now,
|
|
})
|
|
require.NoError(t, err)
|
|
date, err := couponsRepo.GetLatest(ctx, coupon.ID)
|
|
require.NoError(t, err)
|
|
// go and postgres has different precision. go - nanoseconds, postgres micro
|
|
require.Equal(t, date.UTC(), now.Truncate(time.Microsecond))
|
|
})
|
|
|
|
t.Run("total usage", func(t *testing.T) {
|
|
amount, err := couponsRepo.TotalUsage(ctx, coupon.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, amount, int64(1))
|
|
})
|
|
})
|
|
}
|
|
|
|
// TestPopulatePromotionalCoupons is a test for PopulatePromotionalCoupons function
|
|
// that creates coupons with predefined values for each of user (from arguments) that have a project
|
|
// and that don't have a promotional coupon yet. Also it updates limits of selected projects to 1TB.
|
|
// Because the coupon should be added to a project, we select the first project of the user.
|
|
// In this test i have next test cases:
|
|
// 1. Activated user, 2 projects, without coupon. For this case we should add new coupon to his first project.
|
|
// 2. Activated user, 1 project, without coupon.
|
|
// 3. Activated user without project. Coupon should not be added.
|
|
// 4. User with inactive account. Coupon should not be added.
|
|
// 5. Activated user with project and coupon. Coupon should not be added.
|
|
// 6. Next step - is populating coupons for all 5 users. Only 2 coupons should be added.
|
|
// 7. Creating new user with project.
|
|
// 8. Populating coupons again. For 6 users above. Only 1 new coupon should be added.
|
|
// Three new coupons total should be added by 2 runs of PopulatePromotionalCoupons method.
|
|
func TestPopulatePromotionalCoupons(t *testing.T) {
|
|
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
|
|
usersRepo := db.Console().Users()
|
|
projectsRepo := db.Console().Projects()
|
|
couponsRepo := db.StripeCoinPayments().Coupons()
|
|
usageRepo := db.ProjectAccounting()
|
|
|
|
// creating test users with different status.
|
|
|
|
// activated user with 2 project. New coupon should be added to the first project.
|
|
user1, err := usersRepo.Insert(ctx, &console.User{
|
|
ID: testrand.UUID(),
|
|
FullName: "user1",
|
|
ShortName: "",
|
|
Email: "test1@example.com",
|
|
PasswordHash: []byte("123qwe"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
user1.Status = console.Active
|
|
|
|
err = usersRepo.Update(ctx, user1)
|
|
require.NoError(t, err)
|
|
|
|
// activated user with proj. New coupon should be added.
|
|
user2, err := usersRepo.Insert(ctx, &console.User{
|
|
ID: testrand.UUID(),
|
|
FullName: "user2",
|
|
ShortName: "",
|
|
Email: "test2@example.com",
|
|
PasswordHash: []byte("123qwe"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
user2.Status = console.Active
|
|
|
|
err = usersRepo.Update(ctx, user2)
|
|
require.NoError(t, err)
|
|
|
|
// activated user without proj. New coupon should not be added.
|
|
user3, err := usersRepo.Insert(ctx, &console.User{
|
|
ID: testrand.UUID(),
|
|
FullName: "user3",
|
|
ShortName: "",
|
|
Email: "test3@example.com",
|
|
PasswordHash: []byte("123qwe"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
user3.Status = console.Active
|
|
|
|
err = usersRepo.Update(ctx, user3)
|
|
require.NoError(t, err)
|
|
|
|
// inactive user. New coupon should not be added.
|
|
user4, err := usersRepo.Insert(ctx, &console.User{
|
|
ID: testrand.UUID(),
|
|
FullName: "user4",
|
|
ShortName: "",
|
|
Email: "test4@example.com",
|
|
PasswordHash: []byte("123qwe"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// activated user with proj and coupon. New coupon should not be added.
|
|
user5, err := usersRepo.Insert(ctx, &console.User{
|
|
ID: testrand.UUID(),
|
|
FullName: "user5",
|
|
ShortName: "",
|
|
Email: "test5@example.com",
|
|
PasswordHash: []byte("123qwe"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
user5.Status = console.Active
|
|
|
|
err = usersRepo.Update(ctx, user5)
|
|
require.NoError(t, err)
|
|
|
|
// creating projects for users above.
|
|
proj1, err := projectsRepo.Insert(ctx, &console.Project{
|
|
ID: testrand.UUID(),
|
|
Name: "proj 1 of user 1",
|
|
Description: "descr 1",
|
|
OwnerID: user1.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// should not be processed as we takes only first project of the user.
|
|
proj2, err := projectsRepo.Insert(ctx, &console.Project{
|
|
ID: testrand.UUID(),
|
|
Name: "proj 2 of user 1",
|
|
Description: "descr 2",
|
|
OwnerID: user1.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
proj3, err := projectsRepo.Insert(ctx, &console.Project{
|
|
ID: testrand.UUID(),
|
|
Name: "proj 1 of user 2",
|
|
Description: "descr 3",
|
|
OwnerID: user2.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
couponID := testrand.UUID()
|
|
_, err = couponsRepo.Insert(ctx, payments.Coupon{
|
|
ID: couponID,
|
|
UserID: user5.ID,
|
|
Amount: 5500,
|
|
Duration: 2,
|
|
Description: "qw",
|
|
Type: payments.CouponTypePromotional,
|
|
Status: payments.CouponActive,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// creating new users and projects to test that multiple execution of populate method wont generate extra coupons.
|
|
user6, err := usersRepo.Insert(ctx, &console.User{
|
|
ID: testrand.UUID(),
|
|
FullName: "user6",
|
|
ShortName: "",
|
|
Email: "test6@example.com",
|
|
PasswordHash: []byte("123qwe"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
user6.Status = console.Active
|
|
|
|
err = usersRepo.Update(ctx, user6)
|
|
require.NoError(t, err)
|
|
|
|
proj5, err := projectsRepo.Insert(ctx, &console.Project{
|
|
ID: testrand.UUID(),
|
|
Name: "proj 1 of user 6",
|
|
Description: "descr 6",
|
|
OwnerID: user6.ID,
|
|
})
|
|
if err != nil {
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
t.Run("first population", func(t *testing.T) {
|
|
var usersIds = []uuid.UUID{
|
|
user1.ID,
|
|
user2.ID,
|
|
user3.ID,
|
|
user4.ID,
|
|
user5.ID,
|
|
}
|
|
err := couponsRepo.PopulatePromotionalCoupons(ctx, usersIds, 2, 5500, memory.TB)
|
|
require.NoError(t, err)
|
|
|
|
user1Coupons, err := couponsRepo.ListByUserID(ctx, user1.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user1Coupons))
|
|
|
|
proj1Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj1.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, memory.TB.Int64(), *proj1Usage)
|
|
|
|
proj2Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj2.ID)
|
|
require.NoError(t, err)
|
|
// require.Nil(t, proj2Usage)
|
|
require.Equal(t, memory.GB.Int64()*50, *proj2Usage)
|
|
|
|
user2Coupons, err := couponsRepo.ListByUserID(ctx, user2.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user2Coupons))
|
|
|
|
proj3Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj3.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, memory.TB.Int64(), *proj3Usage)
|
|
|
|
user3Coupons, err := couponsRepo.ListByUserID(ctx, user3.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(user3Coupons))
|
|
|
|
user4Coupons, err := couponsRepo.ListByUserID(ctx, user4.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(user4Coupons))
|
|
|
|
user5Coupons, err := couponsRepo.ListByUserID(ctx, user5.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user5Coupons))
|
|
require.Equal(t, "qw", user5Coupons[0].Description)
|
|
})
|
|
|
|
t.Run("second population", func(t *testing.T) {
|
|
var usersIds = []uuid.UUID{
|
|
user1.ID,
|
|
user2.ID,
|
|
user3.ID,
|
|
user4.ID,
|
|
user5.ID,
|
|
user6.ID,
|
|
}
|
|
err := couponsRepo.PopulatePromotionalCoupons(ctx, usersIds, 2, 5500, memory.TB)
|
|
require.NoError(t, err)
|
|
|
|
user1Coupons, err := couponsRepo.ListByUserID(ctx, user1.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user1Coupons))
|
|
|
|
proj1Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj1.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, memory.TB.Int64(), *proj1Usage)
|
|
|
|
proj2Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj2.ID)
|
|
require.NoError(t, err)
|
|
// require.Nil(t, proj2Usage)
|
|
require.Equal(t, memory.GB.Int64()*50, *proj2Usage)
|
|
|
|
user2Coupons, err := couponsRepo.ListByUserID(ctx, user2.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user2Coupons))
|
|
|
|
proj3Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj3.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, memory.TB.Int64(), *proj3Usage)
|
|
|
|
user3Coupons, err := couponsRepo.ListByUserID(ctx, user3.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(user3Coupons))
|
|
|
|
user4Coupons, err := couponsRepo.ListByUserID(ctx, user4.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(user4Coupons))
|
|
|
|
user5Coupons, err := couponsRepo.ListByUserID(ctx, user5.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user5Coupons))
|
|
require.Equal(t, "qw", user5Coupons[0].Description)
|
|
|
|
user6Coupons, err := couponsRepo.ListByUserID(ctx, user6.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(user6Coupons))
|
|
|
|
proj5Usage, err := usageRepo.GetProjectStorageLimit(ctx, proj5.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, memory.TB.Int64(), *proj5Usage)
|
|
})
|
|
})
|
|
}
|