add happy-path incremental tests to operations (#1973)

## Description

Add a simple happy-path integration test to
operations backups.  This test only attemps to
assert the most basic expectations: that
incrementals are runnable, and that they involve
less data than the initial backup.

## Does this PR need a docs update or release note?

- [x]  No 

## Type of change

- [x] 🤖 Test

## Issue(s)

* #1966

## Test Plan

- [x] 💚 E2E
This commit is contained in:
Keepers 2022-12-28 14:13:20 -07:00 committed by GitHub
parent 0e6fce7d1e
commit 673ee10752
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -27,12 +27,17 @@ import (
// helpers // helpers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// prepNewBackupOp generates all clients required to run a backup operation,
// returning both a backup operation created with those clients, as well as
// the clients themselves.
//
//revive:disable:context-as-argument //revive:disable:context-as-argument
func prepNewBackupOp( func prepNewBackupOp(
t *testing.T, t *testing.T,
ctx context.Context, ctx context.Context,
bus events.Eventer, bus events.Eventer,
sel selectors.Selector, sel selectors.Selector,
featureFlags control.FeatureFlags,
) (BackupOperation, account.Account, *kopia.Wrapper, *kopia.ModelStore, func()) { ) (BackupOperation, account.Account, *kopia.Wrapper, *kopia.ModelStore, func()) {
//revive:enable:context-as-argument //revive:enable:context-as-argument
acct := tester.NewM365Account(t) acct := tester.NewM365Account(t)
@ -70,22 +75,43 @@ func prepNewBackupOp(
ms.Close(ctx) ms.Close(ctx)
} }
sw := store.NewKopiaStore(ms) bo := newBackupOp(t, ctx, kw, ms, acct, sel, bus, featureFlags, closer)
bo, err := NewBackupOperation( return bo, acct, kw, ms, closer
ctx, }
control.Options{},
kw, // newBackupOp accepts the clients required to compose a backup operation, plus
sw, // any other metadata, and uses them to generate a new backup operation. This
acct, // allows backup chains to utilize the same temp directory and configuration
sel, // details.
bus) //
//revive:disable:context-as-argument
func newBackupOp(
t *testing.T,
ctx context.Context,
kw *kopia.Wrapper,
ms *kopia.ModelStore,
acct account.Account,
sel selectors.Selector,
bus events.Eventer,
featureFlags control.FeatureFlags,
closer func(),
) BackupOperation {
//revive:enable:context-as-argument
var (
sw = store.NewKopiaStore(ms)
opts = control.Options{}
)
opts.EnabledFeatures = featureFlags
bo, err := NewBackupOperation(ctx, opts, kw, sw, acct, sel, bus)
if !assert.NoError(t, err) { if !assert.NoError(t, err) {
closer() closer()
t.FailNow() t.FailNow()
} }
return bo, acct, kw, ms, closer return bo
} }
//revive:disable:context-as-argument //revive:disable:context-as-argument
@ -97,23 +123,23 @@ func runAndCheckBackup(
) { ) {
//revive:enable:context-as-argument //revive:enable:context-as-argument
require.NoError(t, bo.Run(ctx)) require.NoError(t, bo.Run(ctx))
require.NotEmpty(t, bo.Results) require.NotEmpty(t, bo.Results, "the backup had non-zero results")
require.NotEmpty(t, bo.Results.BackupID) require.NotEmpty(t, bo.Results.BackupID, "the backup generated an ID")
require.Equalf( require.Equalf(
t, t,
Completed, Completed,
bo.Status, bo.Status,
"backup status %s is not Completed", "backup status should be Completed, got %s",
bo.Status, bo.Status,
) )
require.Less(t, 0, bo.Results.ItemsWritten) require.Less(t, 0, bo.Results.ItemsWritten)
assert.Less(t, 0, bo.Results.ItemsRead) assert.Less(t, 0, bo.Results.ItemsRead, "count of items read")
assert.Less(t, int64(0), bo.Results.BytesRead, "bytes read") assert.Less(t, int64(0), bo.Results.BytesRead, "bytes read")
assert.Less(t, int64(0), bo.Results.BytesUploaded, "bytes uploaded") assert.Less(t, int64(0), bo.Results.BytesUploaded, "bytes uploaded")
assert.Equal(t, 1, bo.Results.ResourceOwners) assert.Equal(t, 1, bo.Results.ResourceOwners, "count of resource owners")
assert.NoError(t, bo.Results.ReadErrors) assert.NoError(t, bo.Results.ReadErrors, "errors reading data")
assert.NoError(t, bo.Results.WriteErrors) assert.NoError(t, bo.Results.WriteErrors, "errors writing data")
assert.Equal(t, 1, mb.TimesCalled[events.BackupStart], "backup-start events") 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, 1, mb.TimesCalled[events.BackupEnd], "backup-end events")
assert.Equal(t, assert.Equal(t,
@ -355,19 +381,19 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchange() {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
var ( var (
mb = evmock.NewBus() mb = evmock.NewBus()
sel = test.selector() sel = test.selector().Selector
bo, acct, kw, ms, closer = prepNewBackupOp(t, ctx, mb, sel.Selector) ffs = control.FeatureFlags{ExchangeIncrementals: test.runIncremental}
) )
bo, acct, kw, ms, closer := prepNewBackupOp(t, ctx, mb, sel, ffs)
defer closer() defer closer()
runAndCheckBackup(t, ctx, &bo, mb)
checkBackupIsInManifests(t, ctx, kw, &bo, sel.Selector, test.resourceOwner, test.category)
m365, err := acct.M365Config() m365, err := acct.M365Config()
require.NoError(t, err) require.NoError(t, err)
// run the tests
runAndCheckBackup(t, ctx, &bo, mb)
checkBackupIsInManifests(t, ctx, kw, &bo, sel, test.resourceOwner, test.category)
checkMetadataFilesExist( checkMetadataFilesExist(
t, t,
ctx, ctx,
@ -380,6 +406,47 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchange() {
test.category, test.category,
test.metadataFiles, test.metadataFiles,
) )
if !test.runIncremental {
return
}
// Basic, happy path incremental test. No changes are dictated or expected.
// This only tests that an incremental backup is runnable at all, and that it
// produces fewer results than the last backup.
var (
incMB = evmock.NewBus()
incBO = newBackupOp(t, ctx, kw, ms, acct, sel, incMB, ffs, closer)
)
runAndCheckBackup(t, ctx, &incBO, incMB)
checkBackupIsInManifests(t, ctx, kw, &incBO, sel, test.resourceOwner, test.category)
checkMetadataFilesExist(
t,
ctx,
incBO.Results.BackupID,
kw,
ms,
m365.AzureTenantID,
test.resourceOwner,
path.ExchangeService,
test.category,
test.metadataFiles,
)
// do some additional checks to ensure the incremental dealt with fewer items.
assert.Greater(t, bo.Results.ItemsWritten, incBO.Results.ItemsWritten, "incremental items written")
assert.Greater(t, bo.Results.ItemsRead, incBO.Results.ItemsRead, "incremental items read")
assert.Greater(t, bo.Results.BytesRead, incBO.Results.BytesRead, "incremental bytes read")
assert.Greater(t, bo.Results.BytesUploaded, incBO.Results.BytesUploaded, "incremental bytes uploaded")
assert.Equal(t, bo.Results.ResourceOwners, incBO.Results.ResourceOwners, "incremental backup resource owner")
assert.NoError(t, incBO.Results.ReadErrors, "incremental read errors")
assert.NoError(t, incBO.Results.WriteErrors, "incremental write errors")
assert.Equal(t, 1, incMB.TimesCalled[events.BackupStart], "incremental backup-start events")
assert.Equal(t, 1, incMB.TimesCalled[events.BackupEnd], "incremental backup-end events")
assert.Equal(t,
incMB.CalledWith[events.BackupStart][0][events.BackupID],
incBO.Results.BackupID, "incremental backupID pre-declaration")
}) })
} }
} }
@ -397,7 +464,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_oneDrive() {
sel.Include(sel.Users([]string{m365UserID})) sel.Include(sel.Users([]string{m365UserID}))
bo, _, _, _, closer := prepNewBackupOp(t, ctx, mb, sel.Selector) bo, _, _, _, closer := prepNewBackupOp(t, ctx, mb, sel.Selector, control.FeatureFlags{})
defer closer() defer closer()
runAndCheckBackup(t, ctx, &bo, mb) runAndCheckBackup(t, ctx, &bo, mb)
@ -415,7 +482,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_sharePoint() {
sel.Include(sel.Sites([]string{suite.site})) sel.Include(sel.Sites([]string{suite.site}))
bo, _, _, _, closer := prepNewBackupOp(t, ctx, mb, sel.Selector) bo, _, _, _, closer := prepNewBackupOp(t, ctx, mb, sel.Selector, control.FeatureFlags{})
defer closer() defer closer()
runAndCheckBackup(t, ctx, &bo, mb) runAndCheckBackup(t, ctx, &bo, mb)