corso/src/internal/operations/restore_test.go
Keepers 7c62939c85
update GC's restore to use AwaitStatus (#451)
GC's restore funcs update their status field differently than
the backup funcs.  This brings the behavior in line.
2022-07-29 21:09:15 +00:00

245 lines
6.4 KiB
Go

package operations
import (
"context"
"testing"
"time"
multierror "github.com/hashicorp/go-multierror"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/alcionai/corso/internal/connector/exchange"
"github.com/alcionai/corso/internal/connector/support"
"github.com/alcionai/corso/internal/data"
"github.com/alcionai/corso/internal/kopia"
ctesting "github.com/alcionai/corso/internal/testing"
"github.com/alcionai/corso/pkg/account"
"github.com/alcionai/corso/pkg/control"
"github.com/alcionai/corso/pkg/selectors"
"github.com/alcionai/corso/pkg/store"
)
// ---------------------------------------------------------------------------
// unit
// ---------------------------------------------------------------------------
type RestoreOpSuite struct {
suite.Suite
}
func TestRestoreOpSuite(t *testing.T) {
suite.Run(t, new(RestoreOpSuite))
}
// TODO: after modelStore integration is added, mock the store and/or
// move this to an integration test.
func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() {
t := suite.T()
ctx := context.Background()
var (
kw = &kopia.Wrapper{}
sw = &store.Wrapper{}
acct = account.Account{}
now = time.Now()
stats = restoreStats{
readErr: multierror.Append(nil, assert.AnError),
writeErr: assert.AnError,
cs: []data.Collection{&exchange.Collection{}},
gc: &support.ConnectorOperationStatus{
ObjectCount: 1,
},
}
)
op, err := NewRestoreOperation(ctx, control.Options{}, kw, sw, acct, "foo", selectors.Selector{})
require.NoError(t, err)
op.persistResults(now, &stats)
assert.Equal(t, op.Status, Failed, "status")
assert.Equal(t, op.Results.ItemsRead, len(stats.cs), "items read")
assert.Equal(t, op.Results.ReadErrors, stats.readErr, "read errors")
assert.Equal(t, op.Results.ItemsWritten, stats.gc.Successful, "items written")
assert.Equal(t, op.Results.WriteErrors, stats.writeErr, "write errors")
assert.Equal(t, op.Results.StartedAt, now, "started at")
assert.Less(t, now, op.Results.CompletedAt, "completed at")
}
// ---------------------------------------------------------------------------
// integration
// ---------------------------------------------------------------------------
type RestoreOpIntegrationSuite struct {
suite.Suite
}
func TestRestoreOpIntegrationSuite(t *testing.T) {
if err := ctesting.RunOnAny(
ctesting.CorsoCITests,
ctesting.CorsoOperationTests,
); err != nil {
t.Skip(err)
}
suite.Run(t, new(RestoreOpIntegrationSuite))
}
func (suite *RestoreOpIntegrationSuite) SetupSuite() {
_, err := ctesting.GetRequiredEnvVars(ctesting.M365AcctCredEnvs...)
require.NoError(suite.T(), err)
}
func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() {
kw := &kopia.Wrapper{}
sw := &store.Wrapper{}
acct, err := ctesting.NewM365Account()
require.NoError(suite.T(), err)
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) {
_, err := NewRestoreOperation(
context.Background(),
test.opts,
test.kw,
test.sw,
test.acct,
"backup-id",
selectors.Selector{})
test.errCheck(t, err)
})
}
}
func (suite *RestoreOpIntegrationSuite) TestRestore_Run() {
t := suite.T()
ctx := context.Background()
m365User := "lidiah@8qzvrj.onmicrosoft.com"
acct, err := ctesting.NewM365Account()
require.NoError(t, err)
// need to initialize the repository before we can test connecting to it.
st, err := ctesting.NewPrefixedS3Storage(t)
require.NoError(t, err)
k := kopia.NewConn(st)
require.NoError(t, k.Initialize(ctx))
defer k.Close(ctx)
w, err := kopia.NewWrapper(k)
require.NoError(t, err)
defer w.Close(ctx)
ms, err := kopia.NewModelStore(k)
require.NoError(t, err)
defer ms.Close(ctx)
sw := store.NewKopiaStore(ms)
bsel := selectors.NewExchangeBackup()
bsel.Include(bsel.Users([]string{m365User}))
bo, err := NewBackupOperation(
ctx,
control.Options{},
w,
sw,
acct,
bsel.Selector)
require.NoError(t, err)
require.NoError(t, bo.Run(ctx))
require.NotEmpty(t, bo.Results.BackupID)
rsel := selectors.NewExchangeRestore()
rsel.Include(rsel.Users([]string{m365User}))
ro, err := NewRestoreOperation(
ctx,
control.Options{},
w,
sw,
acct,
bo.Results.BackupID,
rsel.Selector)
require.NoError(t, err)
require.NoError(t, ro.Run(ctx), "restoreOp.Run()")
require.NotEmpty(t, ro.Results, "restoreOp results")
assert.Equal(t, ro.Status, Successful, "restoreOp status")
assert.Greater(t, ro.Results.ItemsRead, 0, "restore items read")
assert.Greater(t, ro.Results.ItemsWritten, 0, "restored items written")
assert.Zero(t, ro.Results.ReadErrors, "errors while reading restore data")
assert.Zero(t, ro.Results.WriteErrors, "errors while writing restore data")
assert.Equal(t, bo.Results.ItemsWritten, ro.Results.ItemsWritten, "backup and restore wrote the same num of items")
}
func (suite *RestoreOpIntegrationSuite) TestRestore_Run_ErrorNoResults() {
t := suite.T()
ctx := context.Background()
m365User := "lidiah@8qzvrj.onmicrosoft.com"
acct, err := ctesting.NewM365Account()
require.NoError(t, err)
// need to initialize the repository before we can test connecting to it.
st, err := ctesting.NewPrefixedS3Storage(t)
require.NoError(t, err)
k := kopia.NewConn(st)
require.NoError(t, k.Initialize(ctx))
defer k.Close(ctx)
w, err := kopia.NewWrapper(k)
require.NoError(t, err)
defer w.Close(ctx)
ms, err := kopia.NewModelStore(k)
require.NoError(t, err)
defer ms.Close(ctx)
sw := store.NewKopiaStore(ms)
bsel := selectors.NewExchangeBackup()
bsel.Include(bsel.Users([]string{m365User}))
bo, err := NewBackupOperation(
ctx,
control.Options{},
w,
sw,
acct,
bsel.Selector)
require.NoError(t, err)
require.NoError(t, bo.Run(ctx))
require.NotEmpty(t, bo.Results.BackupID)
rsel := selectors.NewExchangeRestore()
rsel.Include(rsel.Users(selectors.None()))
ro, err := NewRestoreOperation(
ctx,
control.Options{},
w,
sw,
acct,
bo.Results.BackupID,
rsel.Selector)
require.NoError(t, err)
require.Error(t, ro.Run(ctx), "restoreOp.Run() should have 0 results")
}