satellite/{console,accountfreeze}: test freeze effects
This change adds more tests to the autofreeze chore and the freeze service according to the testplan linked in the issue below. Issue: https://github.com/storj/storj/issues/5738 Change-Id: Ib2afaa283961b2e7ef6fb6e5613ee083ac7d79eb
This commit is contained in:
parent
816c3d31ac
commit
260b71e70c
@ -98,6 +98,24 @@ type Config struct {
|
|||||||
HubSpot HubSpotConfig
|
HubSpot HubSpotConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FreezeTracker is an interface for account freeze event tracking methods.
|
||||||
|
type FreezeTracker interface {
|
||||||
|
// TrackAccountFrozen sends an account frozen event to Segment.
|
||||||
|
TrackAccountFrozen(userID uuid.UUID, email string)
|
||||||
|
|
||||||
|
// TrackAccountUnfrozen sends an account unfrozen event to Segment.
|
||||||
|
TrackAccountUnfrozen(userID uuid.UUID, email string)
|
||||||
|
|
||||||
|
// TrackAccountUnwarned sends an account unwarned event to Segment.
|
||||||
|
TrackAccountUnwarned(userID uuid.UUID, email string)
|
||||||
|
|
||||||
|
// TrackAccountFreezeWarning sends an account freeze warning event to Segment.
|
||||||
|
TrackAccountFreezeWarning(userID uuid.UUID, email string)
|
||||||
|
|
||||||
|
// TrackLargeUnpaidInvoice sends an event to Segment indicating that a user has not paid a large invoice.
|
||||||
|
TrackLargeUnpaidInvoice(invID string, userID uuid.UUID, email string)
|
||||||
|
}
|
||||||
|
|
||||||
// Service for sending analytics.
|
// Service for sending analytics.
|
||||||
//
|
//
|
||||||
// architecture: Service
|
// architecture: Service
|
||||||
|
@ -63,16 +63,16 @@ type AccountFreezeService struct {
|
|||||||
freezeEventsDB AccountFreezeEvents
|
freezeEventsDB AccountFreezeEvents
|
||||||
usersDB Users
|
usersDB Users
|
||||||
projectsDB Projects
|
projectsDB Projects
|
||||||
analytics *analytics.Service
|
tracker analytics.FreezeTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccountFreezeService creates a new account freeze service.
|
// NewAccountFreezeService creates a new account freeze service.
|
||||||
func NewAccountFreezeService(freezeEventsDB AccountFreezeEvents, usersDB Users, projectsDB Projects, analytics *analytics.Service) *AccountFreezeService {
|
func NewAccountFreezeService(freezeEventsDB AccountFreezeEvents, usersDB Users, projectsDB Projects, tracker analytics.FreezeTracker) *AccountFreezeService {
|
||||||
return &AccountFreezeService{
|
return &AccountFreezeService{
|
||||||
freezeEventsDB: freezeEventsDB,
|
freezeEventsDB: freezeEventsDB,
|
||||||
usersDB: usersDB,
|
usersDB: usersDB,
|
||||||
projectsDB: projectsDB,
|
projectsDB: projectsDB,
|
||||||
analytics: analytics,
|
tracker: tracker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.analytics.TrackAccountFrozen(userID, user.Email)
|
s.tracker.TrackAccountFrozen(userID, user.Email)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ func (s *AccountFreezeService) UnfreezeUser(ctx context.Context, userID uuid.UUI
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.analytics.TrackAccountUnfrozen(userID, user.Email)
|
s.tracker.TrackAccountUnfrozen(userID, user.Email)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ func (s *AccountFreezeService) WarnUser(ctx context.Context, userID uuid.UUID) (
|
|||||||
return ErrAccountFreeze.Wrap(err)
|
return ErrAccountFreeze.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.analytics.TrackAccountFreezeWarning(userID, user.Email)
|
s.tracker.TrackAccountFreezeWarning(userID, user.Email)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ func (s *AccountFreezeService) UnWarnUser(ctx context.Context, userID uuid.UUID)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.analytics.TrackAccountUnwarned(userID, user.Email)
|
s.tracker.TrackAccountUnwarned(userID, user.Email)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,3 +271,8 @@ func (s *AccountFreezeService) GetAll(ctx context.Context, userID uuid.UUID) (fr
|
|||||||
|
|
||||||
return freeze, warning, nil
|
return freeze, warning, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestChangeFreezeTracker changes the freeze tracker service for tests.
|
||||||
|
func (s *AccountFreezeService) TestChangeFreezeTracker(t analytics.FreezeTracker) {
|
||||||
|
s.tracker = t
|
||||||
|
}
|
||||||
|
@ -8,9 +8,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"storj.io/common/memory"
|
||||||
"storj.io/common/testcontext"
|
"storj.io/common/testcontext"
|
||||||
|
"storj.io/common/testrand"
|
||||||
"storj.io/storj/private/testplanet"
|
"storj.io/storj/private/testplanet"
|
||||||
|
"storj.io/storj/satellite"
|
||||||
"storj.io/storj/satellite/console"
|
"storj.io/storj/satellite/console"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -242,3 +246,76 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFreezeEffects(t *testing.T) {
|
||||||
|
testplanet.Run(t, testplanet.Config{
|
||||||
|
SatelliteCount: 1, StorageNodeCount: 2, UplinkCount: 2,
|
||||||
|
Reconfigure: testplanet.Reconfigure{
|
||||||
|
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||||
|
config.AccountFreeze.Enabled = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||||
|
sat := planet.Satellites[0]
|
||||||
|
usersDB := sat.DB.Console().Users()
|
||||||
|
projectsDB := sat.DB.Console().Projects()
|
||||||
|
consoleService := sat.API.Console.Service
|
||||||
|
freezeService := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, sat.API.Analytics.Service)
|
||||||
|
|
||||||
|
uplink1 := planet.Uplinks[0]
|
||||||
|
user1, _, err := consoleService.GetUserByEmailWithUnverified(ctx, uplink1.User[sat.ID()].Email)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
bucketName := "testbucket"
|
||||||
|
path := "test/path"
|
||||||
|
|
||||||
|
expectedData := testrand.Bytes(50 * memory.KiB)
|
||||||
|
|
||||||
|
shouldUploadAndDownload := func(testT *testing.T) {
|
||||||
|
// Should be able to upload because account is not warned nor frozen.
|
||||||
|
err = uplink1.Upload(ctx, sat, bucketName, path, expectedData)
|
||||||
|
require.NoError(testT, err)
|
||||||
|
|
||||||
|
// Should be able to download because account is not frozen.
|
||||||
|
data, err := uplink1.Download(ctx, sat, bucketName, path)
|
||||||
|
require.NoError(testT, err)
|
||||||
|
require.Equal(testT, expectedData, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Freeze effect on project owner", func(t *testing.T) {
|
||||||
|
shouldUploadAndDownload(t)
|
||||||
|
|
||||||
|
err = freezeService.WarnUser(ctx, user1.ID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Should be able to download because account is not frozen.
|
||||||
|
data, err := uplink1.Download(ctx, sat, bucketName, path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expectedData, data)
|
||||||
|
|
||||||
|
err = freezeService.FreezeUser(ctx, user1.ID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Should not be able to upload because account is frozen.
|
||||||
|
err = uplink1.Upload(ctx, sat, bucketName, path, expectedData)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Should not be able to download because account is frozen.
|
||||||
|
_, err = uplink1.Download(ctx, sat, bucketName, path)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Should not be able to create bucket because account is frozen.
|
||||||
|
err = uplink1.CreateBucket(ctx, sat, "anotherBucket")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Should be able to list even if frozen.
|
||||||
|
objects, err := uplink1.ListObjects(ctx, sat, bucketName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, objects, 1)
|
||||||
|
|
||||||
|
// Should be able to delete even if frozen.
|
||||||
|
err = uplink1.DeleteObject(ctx, sat, bucketName, path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -188,6 +188,11 @@ func (chore *Chore) TestSetNow(f func() time.Time) {
|
|||||||
chore.nowFn = f
|
chore.nowFn = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSetFreezeService changes the freeze service for tests.
|
||||||
|
func (chore *Chore) TestSetFreezeService(service *console.AccountFreezeService) {
|
||||||
|
chore.freezeService = service
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the chore.
|
// Close closes the chore.
|
||||||
func (chore *Chore) Close() error {
|
func (chore *Chore) Close() error {
|
||||||
chore.Loop.Close()
|
chore.Loop.Close()
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"storj.io/common/testcontext"
|
"storj.io/common/testcontext"
|
||||||
|
"storj.io/common/uuid"
|
||||||
"storj.io/storj/private/testplanet"
|
"storj.io/storj/private/testplanet"
|
||||||
"storj.io/storj/satellite"
|
"storj.io/storj/satellite"
|
||||||
"storj.io/storj/satellite/console"
|
"storj.io/storj/satellite/console"
|
||||||
@ -33,8 +34,9 @@ func TestAutoFreezeChore(t *testing.T) {
|
|||||||
customerDB := sat.Core.DB.StripeCoinPayments().Customers()
|
customerDB := sat.Core.DB.StripeCoinPayments().Customers()
|
||||||
usersDB := sat.DB.Console().Users()
|
usersDB := sat.DB.Console().Users()
|
||||||
projectsDB := sat.DB.Console().Projects()
|
projectsDB := sat.DB.Console().Projects()
|
||||||
service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, sat.API.Analytics.Service)
|
service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, newFreezeTrackerMock(t))
|
||||||
chore := sat.Core.Payments.AccountFreeze
|
chore := sat.Core.Payments.AccountFreeze
|
||||||
|
chore.TestSetFreezeService(service)
|
||||||
|
|
||||||
user, err := sat.AddUser(ctx, console.CreateUser{
|
user, err := sat.AddUser(ctx, console.CreateUser{
|
||||||
FullName: "Test User",
|
FullName: "Test User",
|
||||||
@ -49,6 +51,8 @@ func TestAutoFreezeChore(t *testing.T) {
|
|||||||
curr := string(stripe.CurrencyUSD)
|
curr := string(stripe.CurrencyUSD)
|
||||||
|
|
||||||
t.Run("No freeze event for paid invoice", func(t *testing.T) {
|
t.Run("No freeze event for paid invoice", func(t *testing.T) {
|
||||||
|
// AnalyticsMock tests that events are sent once.
|
||||||
|
service.TestChangeFreezeTracker(newFreezeTrackerMock(t))
|
||||||
item, err := stripeClient.InvoiceItems().New(&stripe.InvoiceItemParams{
|
item, err := stripeClient.InvoiceItems().New(&stripe.InvoiceItemParams{
|
||||||
Params: stripe.Params{Context: ctx},
|
Params: stripe.Params{Context: ctx},
|
||||||
Amount: &amount,
|
Amount: &amount,
|
||||||
@ -102,6 +106,8 @@ func TestAutoFreezeChore(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Freeze event for failed invoice", func(t *testing.T) {
|
t.Run("Freeze event for failed invoice", func(t *testing.T) {
|
||||||
|
// AnalyticsMock tests that events are sent once.
|
||||||
|
service.TestChangeFreezeTracker(newFreezeTrackerMock(t))
|
||||||
// reset chore clock
|
// reset chore clock
|
||||||
chore.TestSetNow(time.Now)
|
chore.TestSetNow(time.Now)
|
||||||
|
|
||||||
@ -160,3 +166,46 @@ func TestAutoFreezeChore(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type freezeTrackerMock struct {
|
||||||
|
t *testing.T
|
||||||
|
freezeCounts map[string]int
|
||||||
|
warnCounts map[string]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFreezeTrackerMock(t *testing.T) *freezeTrackerMock {
|
||||||
|
return &freezeTrackerMock{
|
||||||
|
t: t,
|
||||||
|
freezeCounts: map[string]int{},
|
||||||
|
warnCounts: map[string]int{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following functions are implemented from analytics.FreezeTracker.
|
||||||
|
// They mock/test to make sure freeze events are sent just once.
|
||||||
|
|
||||||
|
func (mock *freezeTrackerMock) TrackAccountFrozen(_ uuid.UUID, email string) {
|
||||||
|
mock.freezeCounts[email]++
|
||||||
|
// make sure this tracker has not been called already for this email.
|
||||||
|
require.Equal(mock.t, 1, mock.freezeCounts[email])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *freezeTrackerMock) TrackAccountUnfrozen(_ uuid.UUID, email string) {
|
||||||
|
mock.freezeCounts[email]--
|
||||||
|
// make sure this tracker has not been called already for this email.
|
||||||
|
require.Equal(mock.t, 0, mock.freezeCounts[email])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *freezeTrackerMock) TrackAccountUnwarned(_ uuid.UUID, email string) {
|
||||||
|
mock.warnCounts[email]--
|
||||||
|
// make sure this tracker has not been called already for this email.
|
||||||
|
require.Equal(mock.t, 0, mock.warnCounts[email])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *freezeTrackerMock) TrackAccountFreezeWarning(_ uuid.UUID, email string) {
|
||||||
|
mock.warnCounts[email]++
|
||||||
|
// make sure this tracker has not been called already for this email.
|
||||||
|
require.Equal(mock.t, 1, mock.warnCounts[email])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *freezeTrackerMock) TrackLargeUnpaidInvoice(_ string, _ uuid.UUID, _ string) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user