328 lines
9.0 KiB
Go
328 lines
9.0 KiB
Go
package operations
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/alcionai/corso/src/internal/connector/exchange"
|
|
"github.com/alcionai/corso/src/internal/connector/support"
|
|
"github.com/alcionai/corso/src/internal/events"
|
|
evmock "github.com/alcionai/corso/src/internal/events/mock"
|
|
"github.com/alcionai/corso/src/internal/kopia"
|
|
"github.com/alcionai/corso/src/internal/tester"
|
|
"github.com/alcionai/corso/src/pkg/account"
|
|
"github.com/alcionai/corso/src/pkg/control"
|
|
"github.com/alcionai/corso/src/pkg/selectors"
|
|
"github.com/alcionai/corso/src/pkg/store"
|
|
)
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// unit
|
|
// ---------------------------------------------------------------------------
|
|
|
|
type BackupOpSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func TestBackupOpSuite(t *testing.T) {
|
|
suite.Run(t, new(BackupOpSuite))
|
|
}
|
|
|
|
func (suite *BackupOpSuite) TestBackupOperation_PersistResults() {
|
|
ctx, flush := tester.NewContext()
|
|
defer flush()
|
|
|
|
var (
|
|
kw = &kopia.Wrapper{}
|
|
sw = &store.Wrapper{}
|
|
acct = account.Account{}
|
|
now = time.Now()
|
|
)
|
|
|
|
table := []struct {
|
|
expectStatus opStatus
|
|
expectErr assert.ErrorAssertionFunc
|
|
stats backupStats
|
|
}{
|
|
{
|
|
expectStatus: Completed,
|
|
expectErr: assert.NoError,
|
|
stats: backupStats{
|
|
started: true,
|
|
resourceCount: 1,
|
|
k: &kopia.BackupStats{
|
|
TotalFileCount: 1,
|
|
TotalHashedBytes: 1,
|
|
TotalUploadedBytes: 1,
|
|
},
|
|
gc: &support.ConnectorOperationStatus{
|
|
Successful: 1,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
expectStatus: Failed,
|
|
expectErr: assert.Error,
|
|
stats: backupStats{
|
|
started: false,
|
|
k: &kopia.BackupStats{},
|
|
gc: &support.ConnectorOperationStatus{},
|
|
},
|
|
},
|
|
{
|
|
expectStatus: NoData,
|
|
expectErr: assert.NoError,
|
|
stats: backupStats{
|
|
started: true,
|
|
k: &kopia.BackupStats{},
|
|
gc: &support.ConnectorOperationStatus{},
|
|
},
|
|
},
|
|
}
|
|
for _, test := range table {
|
|
suite.T().Run(test.expectStatus.String(), func(t *testing.T) {
|
|
op, err := NewBackupOperation(
|
|
ctx,
|
|
control.Options{},
|
|
kw,
|
|
sw,
|
|
acct,
|
|
selectors.Selector{},
|
|
evmock.NewBus())
|
|
require.NoError(t, err)
|
|
test.expectErr(t, op.persistResults(now, &test.stats))
|
|
|
|
assert.Equal(t, test.expectStatus.String(), op.Status.String(), "status")
|
|
assert.Equal(t, test.stats.gc.Successful, op.Results.ItemsRead, "items read")
|
|
assert.Equal(t, test.stats.readErr, op.Results.ReadErrors, "read errors")
|
|
assert.Equal(t, test.stats.k.TotalFileCount, op.Results.ItemsWritten, "items written")
|
|
assert.Equal(t, test.stats.k.TotalHashedBytes, op.Results.BytesRead, "bytes read")
|
|
assert.Equal(t, test.stats.k.TotalUploadedBytes, op.Results.BytesUploaded, "bytes written")
|
|
assert.Equal(t, test.stats.resourceCount, op.Results.ResourceOwners, "resource owners")
|
|
assert.Equal(t, test.stats.writeErr, op.Results.WriteErrors, "write errors")
|
|
assert.Equal(t, now, op.Results.StartedAt, "started at")
|
|
assert.Less(t, now, op.Results.CompletedAt, "completed at")
|
|
})
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// integration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
type BackupOpIntegrationSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func TestBackupOpIntegrationSuite(t *testing.T) {
|
|
if err := tester.RunOnAny(
|
|
tester.CorsoCITests,
|
|
tester.CorsoOperationTests,
|
|
); err != nil {
|
|
t.Skip(err)
|
|
}
|
|
|
|
suite.Run(t, new(BackupOpIntegrationSuite))
|
|
}
|
|
|
|
func (suite *BackupOpIntegrationSuite) SetupSuite() {
|
|
_, err := tester.GetRequiredEnvSls(
|
|
tester.AWSStorageCredEnvs,
|
|
tester.M365AcctCredEnvs)
|
|
require.NoError(suite.T(), err)
|
|
}
|
|
|
|
func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() {
|
|
kw := &kopia.Wrapper{}
|
|
sw := &store.Wrapper{}
|
|
acct := tester.NewM365Account(suite.T())
|
|
|
|
table := []struct {
|
|
name string
|
|
opts control.Options
|
|
kw *kopia.Wrapper
|
|
sw *store.Wrapper
|
|
acct account.Account
|
|
targets []string
|
|
errCheck assert.ErrorAssertionFunc
|
|
}{
|
|
{"good", control.Options{}, kw, sw, acct, nil, assert.NoError},
|
|
{"missing kopia", control.Options{}, nil, sw, acct, nil, assert.Error},
|
|
{"missing modelstore", control.Options{}, kw, nil, acct, nil, assert.Error},
|
|
}
|
|
for _, test := range table {
|
|
suite.T().Run(test.name, func(t *testing.T) {
|
|
ctx, flush := tester.NewContext()
|
|
defer flush()
|
|
|
|
_, err := NewBackupOperation(
|
|
ctx,
|
|
test.opts,
|
|
test.kw,
|
|
test.sw,
|
|
test.acct,
|
|
selectors.Selector{},
|
|
evmock.NewBus())
|
|
test.errCheck(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestBackup_Run ensures that Integration Testing works
|
|
// for the following scopes: Contacts, Events, and Mail
|
|
func (suite *BackupOpIntegrationSuite) TestBackup_Run() {
|
|
ctx, flush := tester.NewContext()
|
|
defer flush()
|
|
|
|
m365UserID := tester.M365UserID(suite.T())
|
|
acct := tester.NewM365Account(suite.T())
|
|
|
|
tests := []struct {
|
|
name string
|
|
selectFunc func() *selectors.Selector
|
|
}{
|
|
{
|
|
name: "Integration Exchange.Mail",
|
|
selectFunc: func() *selectors.Selector {
|
|
sel := selectors.NewExchangeBackup()
|
|
sel.Include(sel.MailFolders([]string{m365UserID}, []string{exchange.DefaultMailFolder}))
|
|
return &sel.Selector
|
|
},
|
|
},
|
|
{
|
|
name: "Integration Exchange.Contacts",
|
|
selectFunc: func() *selectors.Selector {
|
|
sel := selectors.NewExchangeBackup()
|
|
sel.Include(sel.ContactFolders([]string{m365UserID}, []string{exchange.DefaultContactFolder}))
|
|
return &sel.Selector
|
|
},
|
|
},
|
|
{
|
|
name: "Integration Exchange.Events",
|
|
selectFunc: func() *selectors.Selector {
|
|
sel := selectors.NewExchangeBackup()
|
|
sel.Include(sel.EventCalendars([]string{m365UserID}, []string{exchange.DefaultCalendar}))
|
|
return &sel.Selector
|
|
},
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
suite.T().Run(test.name, func(t *testing.T) {
|
|
// need to initialize the repository before we can test connecting to it.
|
|
st := tester.NewPrefixedS3Storage(t)
|
|
k := kopia.NewConn(st)
|
|
require.NoError(t, k.Initialize(ctx))
|
|
|
|
// kopiaRef comes with a count of 1 and Wrapper bumps it again so safe
|
|
// to close here.
|
|
defer k.Close(ctx)
|
|
|
|
kw, err := kopia.NewWrapper(k)
|
|
require.NoError(t, err)
|
|
defer kw.Close(ctx)
|
|
|
|
ms, err := kopia.NewModelStore(k)
|
|
require.NoError(t, err)
|
|
defer ms.Close(ctx)
|
|
|
|
mb := evmock.NewBus()
|
|
|
|
sw := store.NewKopiaStore(ms)
|
|
selected := test.selectFunc()
|
|
bo, err := NewBackupOperation(
|
|
ctx,
|
|
control.Options{},
|
|
kw,
|
|
sw,
|
|
acct,
|
|
*selected,
|
|
mb)
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, bo.Run(ctx))
|
|
require.NotEmpty(t, bo.Results)
|
|
require.NotEmpty(t, bo.Results.BackupID)
|
|
assert.Equalf(t, Completed, bo.Status, "backup status %s is not Completed", bo.Status)
|
|
assert.Less(t, 0, bo.Results.ItemsRead)
|
|
assert.Less(t, 0, bo.Results.ItemsWritten)
|
|
assert.Less(t, int64(0), bo.Results.BytesRead, "bytes read")
|
|
assert.Less(t, int64(0), bo.Results.BytesUploaded, "bytes uploaded")
|
|
assert.Equal(t, 1, bo.Results.ResourceOwners)
|
|
assert.NoError(t, bo.Results.ReadErrors)
|
|
assert.NoError(t, bo.Results.WriteErrors)
|
|
assert.Equal(t, 1, mb.TimesCalled[events.BackupStart], "backup-start events")
|
|
assert.Equal(t, 1, mb.TimesCalled[events.BackupEnd], "backup-end events")
|
|
assert.Equal(t,
|
|
mb.CalledWith[events.BackupStart][0][events.BackupID],
|
|
bo.Results.BackupID, "backupID pre-declaration")
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *BackupOpIntegrationSuite) TestBackupOneDrive_Run() {
|
|
ctx, flush := tester.NewContext()
|
|
defer flush()
|
|
|
|
t := suite.T()
|
|
|
|
m365UserID := tester.M365UserID(t)
|
|
acct := tester.NewM365Account(t)
|
|
|
|
// need to initialize the repository before we can test connecting to it.
|
|
st := tester.NewPrefixedS3Storage(t)
|
|
|
|
k := kopia.NewConn(st)
|
|
require.NoError(t, k.Initialize(ctx))
|
|
|
|
// kopiaRef comes with a count of 1 and Wrapper bumps it again so safe
|
|
// to close here.
|
|
defer k.Close(ctx)
|
|
|
|
kw, err := kopia.NewWrapper(k)
|
|
require.NoError(t, err)
|
|
|
|
defer kw.Close(ctx)
|
|
|
|
ms, err := kopia.NewModelStore(k)
|
|
require.NoError(t, err)
|
|
|
|
defer ms.Close(ctx)
|
|
|
|
sw := store.NewKopiaStore(ms)
|
|
|
|
mb := evmock.NewBus()
|
|
|
|
sel := selectors.NewOneDriveBackup()
|
|
sel.Include(sel.Users([]string{m365UserID}))
|
|
|
|
bo, err := NewBackupOperation(
|
|
ctx,
|
|
control.Options{},
|
|
kw,
|
|
sw,
|
|
acct,
|
|
sel.Selector,
|
|
mb)
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, bo.Run(ctx))
|
|
require.NotEmpty(t, bo.Results)
|
|
require.NotEmpty(t, bo.Results.BackupID)
|
|
assert.Equalf(t, Completed, bo.Status, "backup status %s is not Completed", bo.Status)
|
|
assert.Equal(t, bo.Results.ItemsRead, bo.Results.ItemsWritten)
|
|
assert.Less(t, int64(0), bo.Results.BytesRead, "bytes read")
|
|
assert.Less(t, int64(0), bo.Results.BytesUploaded, "bytes uploaded")
|
|
assert.Equal(t, 1, bo.Results.ResourceOwners)
|
|
assert.NoError(t, bo.Results.ReadErrors)
|
|
assert.NoError(t, bo.Results.WriteErrors)
|
|
assert.Equal(t, 1, mb.TimesCalled[events.BackupStart], "backup-start events")
|
|
assert.Equal(t, 1, mb.TimesCalled[events.BackupEnd], "backup-end events")
|
|
assert.Equal(t,
|
|
mb.CalledWith[events.BackupStart][0][events.BackupID],
|
|
bo.Results.BackupID, "backupID pre-declaration")
|
|
}
|