Compare commits
1 Commits
main
...
upn_remova
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdc9145f61 |
@ -8,7 +8,6 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/version"
|
"github.com/alcionai/corso/src/internal/version"
|
||||||
"github.com/alcionai/corso/src/pkg/backup/identity"
|
|
||||||
"github.com/alcionai/corso/src/pkg/logger"
|
"github.com/alcionai/corso/src/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,11 +22,6 @@ type BackupBases interface {
|
|||||||
ClearMergeBases()
|
ClearMergeBases()
|
||||||
AssistBases() []ManifestEntry
|
AssistBases() []ManifestEntry
|
||||||
ClearAssistBases()
|
ClearAssistBases()
|
||||||
MergeBackupBases(
|
|
||||||
ctx context.Context,
|
|
||||||
other BackupBases,
|
|
||||||
reasonToKey func(identity.Reasoner) string,
|
|
||||||
) BackupBases
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type backupBases struct {
|
type backupBases struct {
|
||||||
@ -111,119 +105,6 @@ func (bb *backupBases) ClearAssistBases() {
|
|||||||
bb.assistBases = nil
|
bb.assistBases = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MergeBackupBases reduces the two BackupBases into a single BackupBase.
|
|
||||||
// Assumes the passed in BackupBases represents a prior backup version (across
|
|
||||||
// some migration that disrupts lookup), and that the BackupBases used to call
|
|
||||||
// this function contains the current version.
|
|
||||||
//
|
|
||||||
// reasonToKey should be a function that, given a Reasoner, will produce some
|
|
||||||
// string that represents Reasoner in the context of the merge operation. For
|
|
||||||
// example, to merge BackupBases across a ProtectedResource migration, the
|
|
||||||
// Reasoner's service and category can be used as the key.
|
|
||||||
//
|
|
||||||
// Selection priority, for each reason key generated by reasonsToKey, follows
|
|
||||||
// these rules:
|
|
||||||
// 1. If the called BackupBases has an entry for a given reason, ignore the
|
|
||||||
// other BackupBases matching that reason.
|
|
||||||
// 2. If the called BackupBases has only AssistBases, look for a matching
|
|
||||||
// MergeBase manifest in the other BackupBases.
|
|
||||||
// 3. If the called BackupBases has no entry for a reason, look for a matching
|
|
||||||
// MergeBase in the other BackupBases.
|
|
||||||
func (bb *backupBases) MergeBackupBases(
|
|
||||||
ctx context.Context,
|
|
||||||
other BackupBases,
|
|
||||||
reasonToKey func(reason identity.Reasoner) string,
|
|
||||||
) BackupBases {
|
|
||||||
if other == nil || (len(other.MergeBases()) == 0 && len(other.AssistBases()) == 0) {
|
|
||||||
return bb
|
|
||||||
}
|
|
||||||
|
|
||||||
if bb == nil || (len(bb.MergeBases()) == 0 && len(bb.AssistBases()) == 0) {
|
|
||||||
return other
|
|
||||||
}
|
|
||||||
|
|
||||||
toMerge := map[string]struct{}{}
|
|
||||||
assist := map[string]struct{}{}
|
|
||||||
|
|
||||||
// Track the bases in bb.
|
|
||||||
for _, m := range bb.mergeBases {
|
|
||||||
for _, r := range m.Reasons {
|
|
||||||
k := reasonToKey(r)
|
|
||||||
|
|
||||||
toMerge[k] = struct{}{}
|
|
||||||
assist[k] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range bb.assistBases {
|
|
||||||
for _, r := range m.Reasons {
|
|
||||||
k := reasonToKey(r)
|
|
||||||
assist[k] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var toAdd []ManifestEntry
|
|
||||||
|
|
||||||
// Calculate the set of mergeBases to pull from other into this one.
|
|
||||||
for _, m := range other.MergeBases() {
|
|
||||||
useReasons := []identity.Reasoner{}
|
|
||||||
|
|
||||||
for _, r := range m.Reasons {
|
|
||||||
k := reasonToKey(r)
|
|
||||||
if _, ok := toMerge[k]; ok {
|
|
||||||
// Assume other contains prior manifest versions.
|
|
||||||
// We don't want to stack a prior version incomplete onto
|
|
||||||
// a current version's complete snapshot.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
useReasons = append(useReasons, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(useReasons) > 0 {
|
|
||||||
m.Reasons = useReasons
|
|
||||||
toAdd = append(toAdd, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res := &backupBases{
|
|
||||||
backups: bb.Backups(),
|
|
||||||
mergeBases: bb.MergeBases(),
|
|
||||||
assistBases: bb.AssistBases(),
|
|
||||||
// Note that assistBackups are a new feature and don't exist
|
|
||||||
// in prior versions where we were using UPN based reasons i.e.
|
|
||||||
// other won't have any assistBackups.
|
|
||||||
assistBackups: bb.AssistBackups(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new mergeBases and backups.
|
|
||||||
for _, man := range toAdd {
|
|
||||||
// Will get empty string if not found which is fine, it'll fail one of the
|
|
||||||
// other checks.
|
|
||||||
bID, _ := man.GetTag(TagBackupID)
|
|
||||||
|
|
||||||
bup, ok := getBackupByID(other.Backups(), bID)
|
|
||||||
if !ok {
|
|
||||||
logger.Ctx(ctx).Infow(
|
|
||||||
"not unioning snapshot missing backup",
|
|
||||||
"other_manifest_id", man.ID,
|
|
||||||
"other_backup_id", bID)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
bup.Reasons = man.Reasons
|
|
||||||
|
|
||||||
res.backups = append(res.backups, bup)
|
|
||||||
res.mergeBases = append(res.mergeBases, man)
|
|
||||||
// TODO(pandeyabs): Remove this once we remove overlap between
|
|
||||||
// between merge and assist bases as part of #3943.
|
|
||||||
res.assistBases = append(res.assistBases, man)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func findNonUniqueManifests(
|
func findNonUniqueManifests(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
manifests []ManifestEntry,
|
manifests []ManifestEntry,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package kopia
|
package kopia
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kopia/kopia/repo/manifest"
|
"github.com/kopia/kopia/repo/manifest"
|
||||||
@ -203,279 +202,6 @@ func (suite *BackupBasesUnitSuite) TestClearAssistBases() {
|
|||||||
assert.Empty(suite.T(), bb.AssistBases())
|
assert.Empty(suite.T(), bb.AssistBases())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *BackupBasesUnitSuite) TestMergeBackupBases() {
|
|
||||||
ro := "resource_owner"
|
|
||||||
|
|
||||||
type testInput struct {
|
|
||||||
id int
|
|
||||||
cat []path.CategoryType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a function so tests can modify things without messing with each other.
|
|
||||||
makeBackupBases := func(mergeInputs []testInput, assistInputs []testInput) *backupBases {
|
|
||||||
res := &backupBases{}
|
|
||||||
|
|
||||||
for _, i := range mergeInputs {
|
|
||||||
baseID := fmt.Sprintf("id%d", i.id)
|
|
||||||
reasons := make([]identity.Reasoner, 0, len(i.cat))
|
|
||||||
|
|
||||||
for _, c := range i.cat {
|
|
||||||
reasons = append(reasons, NewReason("", ro, path.ExchangeService, c))
|
|
||||||
}
|
|
||||||
|
|
||||||
m := makeManifest(baseID, "", "b"+baseID, reasons...)
|
|
||||||
res.assistBases = append(res.assistBases, m)
|
|
||||||
|
|
||||||
b := BackupEntry{
|
|
||||||
Backup: &backup.Backup{
|
|
||||||
BaseModel: model.BaseModel{ID: model.StableID("b" + baseID)},
|
|
||||||
SnapshotID: baseID,
|
|
||||||
StreamStoreID: "ss" + baseID,
|
|
||||||
},
|
|
||||||
Reasons: reasons,
|
|
||||||
}
|
|
||||||
|
|
||||||
res.backups = append(res.backups, b)
|
|
||||||
res.mergeBases = append(res.mergeBases, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, i := range assistInputs {
|
|
||||||
baseID := fmt.Sprintf("id%d", i.id)
|
|
||||||
|
|
||||||
reasons := make([]identity.Reasoner, 0, len(i.cat))
|
|
||||||
|
|
||||||
for _, c := range i.cat {
|
|
||||||
reasons = append(reasons, NewReason("", ro, path.ExchangeService, c))
|
|
||||||
}
|
|
||||||
|
|
||||||
m := makeManifest(baseID, "", "a"+baseID, reasons...)
|
|
||||||
|
|
||||||
b := BackupEntry{
|
|
||||||
Backup: &backup.Backup{
|
|
||||||
BaseModel: model.BaseModel{
|
|
||||||
ID: model.StableID("a" + baseID),
|
|
||||||
Tags: map[string]string{model.BackupTypeTag: model.AssistBackup},
|
|
||||||
},
|
|
||||||
SnapshotID: baseID,
|
|
||||||
StreamStoreID: "ss" + baseID,
|
|
||||||
},
|
|
||||||
Reasons: reasons,
|
|
||||||
}
|
|
||||||
|
|
||||||
res.assistBackups = append(res.assistBackups, b)
|
|
||||||
res.assistBases = append(res.assistBases, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
table := []struct {
|
|
||||||
name string
|
|
||||||
merge []testInput
|
|
||||||
assist []testInput
|
|
||||||
otherMerge []testInput
|
|
||||||
otherAssist []testInput
|
|
||||||
expect func() *backupBases
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Other Empty",
|
|
||||||
merge: []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
},
|
|
||||||
assist: []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
},
|
|
||||||
expect: func() *backupBases {
|
|
||||||
bs := makeBackupBases([]testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
}, []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
})
|
|
||||||
|
|
||||||
return bs
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "current Empty",
|
|
||||||
otherMerge: []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
},
|
|
||||||
otherAssist: []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
},
|
|
||||||
expect: func() *backupBases {
|
|
||||||
bs := makeBackupBases([]testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
}, []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
})
|
|
||||||
|
|
||||||
return bs
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Other overlaps merge and assist",
|
|
||||||
merge: []testInput{
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
assist: []testInput{
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
otherMerge: []testInput{
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
otherAssist: []testInput{
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expect: func() *backupBases {
|
|
||||||
bs := makeBackupBases([]testInput{
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
}, []testInput{
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return bs
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Other overlaps merge",
|
|
||||||
merge: []testInput{
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
otherMerge: []testInput{
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expect: func() *backupBases {
|
|
||||||
bs := makeBackupBases([]testInput{
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
}, nil)
|
|
||||||
|
|
||||||
return bs
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Current assist overlaps with Other merge",
|
|
||||||
assist: []testInput{
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
otherMerge: []testInput{
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
otherAssist: []testInput{
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
expect: func() *backupBases {
|
|
||||||
bs := makeBackupBases([]testInput{
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
}, []testInput{
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return bs
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Other Disjoint",
|
|
||||||
merge: []testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
otherMerge: []testInput{
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
cat: []path.CategoryType{path.ContactsCategory},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expect: func() *backupBases {
|
|
||||||
bs := makeBackupBases([]testInput{
|
|
||||||
{cat: []path.CategoryType{path.EmailCategory}},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
cat: []path.CategoryType{path.EmailCategory},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
cat: []path.CategoryType{path.ContactsCategory},
|
|
||||||
},
|
|
||||||
}, nil)
|
|
||||||
|
|
||||||
return bs
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range table {
|
|
||||||
suite.Run(test.name, func() {
|
|
||||||
t := suite.T()
|
|
||||||
|
|
||||||
bb := makeBackupBases(test.merge, test.assist)
|
|
||||||
other := makeBackupBases(test.otherMerge, test.otherAssist)
|
|
||||||
expected := test.expect()
|
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
got := bb.MergeBackupBases(
|
|
||||||
ctx,
|
|
||||||
other,
|
|
||||||
func(r identity.Reasoner) string {
|
|
||||||
return r.Service().String() + r.Category().String()
|
|
||||||
})
|
|
||||||
AssertBackupBasesEqual(t, expected, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *BackupBasesUnitSuite) TestFixupAndVerify() {
|
func (suite *BackupBasesUnitSuite) TestFixupAndVerify() {
|
||||||
ro := "resource_owner"
|
ro := "resource_owner"
|
||||||
|
|
||||||
|
|||||||
@ -333,11 +333,6 @@ func (op *BackupOperation) do(
|
|||||||
return nil, clues.Wrap(err, "getting reasons")
|
return nil, clues.Wrap(err, "getting reasons")
|
||||||
}
|
}
|
||||||
|
|
||||||
fallbackReasons, err := makeFallbackReasons(op.account.ID(), op.Selectors)
|
|
||||||
if err != nil {
|
|
||||||
return nil, clues.Wrap(err, "getting fallback reasons")
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Ctx(ctx).With(
|
logger.Ctx(ctx).With(
|
||||||
"control_options", op.Options,
|
"control_options", op.Options,
|
||||||
"selectors", op.Selectors).
|
"selectors", op.Selectors).
|
||||||
@ -355,7 +350,7 @@ func (op *BackupOperation) do(
|
|||||||
ctx,
|
ctx,
|
||||||
kbf,
|
kbf,
|
||||||
op.kopia,
|
op.kopia,
|
||||||
reasons, fallbackReasons,
|
reasons,
|
||||||
op.account.ID(),
|
op.account.ID(),
|
||||||
op.incremental,
|
op.incremental,
|
||||||
op.disableAssistBackup)
|
op.disableAssistBackup)
|
||||||
@ -430,16 +425,6 @@ func (op *BackupOperation) do(
|
|||||||
return deets, nil
|
return deets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeFallbackReasons(tenant string, sel selectors.Selector) ([]identity.Reasoner, error) {
|
|
||||||
if sel.PathService() != path.SharePointService &&
|
|
||||||
sel.DiscreteOwner != sel.DiscreteOwnerName {
|
|
||||||
return sel.Reasons(tenant, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// return nil for fallback reasons since a nil value will no-op.
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// checker to see if conditions are correct for incremental backup behavior such as
|
// checker to see if conditions are correct for incremental backup behavior such as
|
||||||
// retrieving metadata like delta tokens and previous paths.
|
// retrieving metadata like delta tokens and previous paths.
|
||||||
func useIncrementalBackup(sel selectors.Selector, opts control.Options) bool {
|
func useIncrementalBackup(sel selectors.Selector, opts control.Options) bool {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ func produceManifestsAndMetadata(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
bf inject.BaseFinder,
|
bf inject.BaseFinder,
|
||||||
rp inject.RestoreProducer,
|
rp inject.RestoreProducer,
|
||||||
reasons, fallbackReasons []identity.Reasoner,
|
reasons []identity.Reasoner,
|
||||||
tenantID string,
|
tenantID string,
|
||||||
getMetadata, dropAssistBases bool,
|
getMetadata, dropAssistBases bool,
|
||||||
) (kopia.BackupBases, []data.RestoreCollection, bool, error) {
|
) (kopia.BackupBases, []data.RestoreCollection, bool, error) {
|
||||||
@ -29,7 +29,6 @@ func produceManifestsAndMetadata(
|
|||||||
bf,
|
bf,
|
||||||
rp,
|
rp,
|
||||||
reasons,
|
reasons,
|
||||||
fallbackReasons,
|
|
||||||
tenantID,
|
tenantID,
|
||||||
getMetadata)
|
getMetadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,7 +56,7 @@ func getManifestsAndMetadata(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
bf inject.BaseFinder,
|
bf inject.BaseFinder,
|
||||||
rp inject.RestoreProducer,
|
rp inject.RestoreProducer,
|
||||||
reasons, fallbackReasons []identity.Reasoner,
|
reasons []identity.Reasoner,
|
||||||
tenantID string,
|
tenantID string,
|
||||||
getMetadata bool,
|
getMetadata bool,
|
||||||
) (kopia.BackupBases, []data.RestoreCollection, bool, error) {
|
) (kopia.BackupBases, []data.RestoreCollection, bool, error) {
|
||||||
@ -68,24 +67,6 @@ func getManifestsAndMetadata(
|
|||||||
)
|
)
|
||||||
|
|
||||||
bb := bf.FindBases(ctx, reasons, tags)
|
bb := bf.FindBases(ctx, reasons, tags)
|
||||||
// TODO(ashmrtn): Only fetch these if we haven't already covered all the
|
|
||||||
// reasons for this backup.
|
|
||||||
fbb := bf.FindBases(ctx, fallbackReasons, tags)
|
|
||||||
|
|
||||||
// one of three cases can occur when retrieving backups across reason migrations:
|
|
||||||
// 1. the current reasons don't match any manifests, and we use the fallback to
|
|
||||||
// look up the previous reason version.
|
|
||||||
// 2. the current reasons only contain an incomplete manifest, and the fallback
|
|
||||||
// can find a complete manifest.
|
|
||||||
// 3. the current reasons contain all the necessary manifests.
|
|
||||||
// Note: This is not relevant for assist backups, since they are newly introduced
|
|
||||||
// and they don't exist with fallback reasons.
|
|
||||||
bb = bb.MergeBackupBases(
|
|
||||||
ctx,
|
|
||||||
fbb,
|
|
||||||
func(r identity.Reasoner) string {
|
|
||||||
return r.Service().String() + r.Category().String()
|
|
||||||
})
|
|
||||||
|
|
||||||
if !getMetadata {
|
if !getMetadata {
|
||||||
return bb, nil, false, nil
|
return bb, nil, false, nil
|
||||||
|
|||||||
@ -12,9 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/data"
|
"github.com/alcionai/corso/src/internal/data"
|
||||||
"github.com/alcionai/corso/src/internal/kopia"
|
"github.com/alcionai/corso/src/internal/kopia"
|
||||||
"github.com/alcionai/corso/src/internal/model"
|
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
"github.com/alcionai/corso/src/pkg/backup"
|
|
||||||
"github.com/alcionai/corso/src/pkg/backup/identity"
|
"github.com/alcionai/corso/src/pkg/backup/identity"
|
||||||
"github.com/alcionai/corso/src/pkg/fault"
|
"github.com/alcionai/corso/src/pkg/fault"
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
@ -482,7 +480,7 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
|
|||||||
ctx,
|
ctx,
|
||||||
test.bf,
|
test.bf,
|
||||||
&test.rp,
|
&test.rp,
|
||||||
test.reasons, nil,
|
test.reasons,
|
||||||
tid,
|
tid,
|
||||||
test.getMeta,
|
test.getMeta,
|
||||||
test.dropAssist)
|
test.dropAssist)
|
||||||
@ -532,499 +530,3 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata_FallbackReasons() {
|
|
||||||
const (
|
|
||||||
ro = "resourceowner"
|
|
||||||
fbro = "fb_resourceowner"
|
|
||||||
tid = "tenantid"
|
|
||||||
did = "detailsid"
|
|
||||||
)
|
|
||||||
|
|
||||||
makeMan := func(ro, id, incmpl string, cats ...path.CategoryType) kopia.ManifestEntry {
|
|
||||||
return kopia.ManifestEntry{
|
|
||||||
Manifest: &snapshot.Manifest{
|
|
||||||
ID: manifest.ID(id),
|
|
||||||
IncompleteReason: incmpl,
|
|
||||||
Tags: map[string]string{"tag:" + kopia.TagBackupID: id + "bup"},
|
|
||||||
},
|
|
||||||
Reasons: buildReasons(ro, path.ExchangeService, cats...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
makeBackup := func(ro, snapID string, cats ...path.CategoryType) kopia.BackupEntry {
|
|
||||||
return kopia.BackupEntry{
|
|
||||||
Backup: &backup.Backup{
|
|
||||||
BaseModel: model.BaseModel{
|
|
||||||
ID: model.StableID(snapID + "bup"),
|
|
||||||
},
|
|
||||||
SnapshotID: snapID,
|
|
||||||
StreamStoreID: snapID + "store",
|
|
||||||
},
|
|
||||||
Reasons: buildReasons(ro, path.ExchangeService, cats...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emailReason := kopia.NewReason(
|
|
||||||
"",
|
|
||||||
ro,
|
|
||||||
path.ExchangeService,
|
|
||||||
path.EmailCategory)
|
|
||||||
|
|
||||||
fbEmailReason := kopia.NewReason(
|
|
||||||
"",
|
|
||||||
fbro,
|
|
||||||
path.ExchangeService,
|
|
||||||
path.EmailCategory)
|
|
||||||
|
|
||||||
table := []struct {
|
|
||||||
name string
|
|
||||||
bf *mockBackupFinder
|
|
||||||
rp mockRestoreProducer
|
|
||||||
reasons []identity.Reasoner
|
|
||||||
fallbackReasons []identity.Reasoner
|
|
||||||
getMeta bool
|
|
||||||
dropAssist bool
|
|
||||||
assertErr assert.ErrorAssertionFunc
|
|
||||||
assertB assert.BoolAssertionFunc
|
|
||||||
expectDCS []mockColl
|
|
||||||
expectMans kopia.BackupBases
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "don't get metadata, only fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: false,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.False,
|
|
||||||
expectDCS: nil,
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "only fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "fb_id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "only fallbacks, no assist",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
dropAssist: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "fb_id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
).
|
|
||||||
ClearMockAssistBases(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "complete mans and fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id1"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "incomplete mans and fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(fbro, "fb_id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id2"}}},
|
|
||||||
"fb_id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id2"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: nil,
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "complete and incomplete mans and fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
).WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
).WithAssistBases(
|
|
||||||
makeMan(fbro, "fb_id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id1"}}},
|
|
||||||
"id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id2"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
"fb_id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id2"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
).WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "incomplete mans and complete fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id2"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "fb_id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
).WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "incomplete mans and complete fallbacks, no assist bases",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(ro, "id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id2"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
dropAssist: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "fb_id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory),
|
|
||||||
).
|
|
||||||
ClearMockAssistBases(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "complete mans and incomplete fallbacks",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithAssistBases(
|
|
||||||
makeMan(fbro, "fb_id2", "checkpoint", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id1"}}},
|
|
||||||
"fb_id2": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id2"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{fbEmailReason},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "complete mans and complete fallbacks, multiple reasons",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory, path.ContactsCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory, path.ContactsCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory, path.ContactsCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id1"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{
|
|
||||||
emailReason,
|
|
||||||
kopia.NewReason("", ro, path.ExchangeService, path.ContactsCategory),
|
|
||||||
},
|
|
||||||
fallbackReasons: []identity.Reasoner{
|
|
||||||
fbEmailReason,
|
|
||||||
kopia.NewReason("", fbro, path.ExchangeService, path.ContactsCategory),
|
|
||||||
},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory, path.ContactsCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "complete mans and complete fallbacks, distinct reasons",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.ContactsCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.ContactsCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id1"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{emailReason},
|
|
||||||
fallbackReasons: []identity.Reasoner{
|
|
||||||
kopia.NewReason("", fbro, path.ExchangeService, path.ContactsCategory),
|
|
||||||
},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "id1"}, {id: "fb_id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
makeMan(fbro, "fb_id1", "", path.ContactsCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.ContactsCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "complete mans and complete fallbacks, fallback has superset of reasons",
|
|
||||||
bf: &mockBackupFinder{
|
|
||||||
data: map[string]kopia.BackupBases{
|
|
||||||
ro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
),
|
|
||||||
fbro: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(fbro, "fb_id1", "", path.EmailCategory, path.ContactsCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.EmailCategory, path.ContactsCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rp: mockRestoreProducer{
|
|
||||||
collsByID: map[string][]data.RestoreCollection{
|
|
||||||
"id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "id1"}}},
|
|
||||||
"fb_id1": {data.NoFetchRestoreCollection{Collection: mockColl{id: "fb_id1"}}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reasons: []identity.Reasoner{
|
|
||||||
emailReason,
|
|
||||||
kopia.NewReason("", ro, path.ExchangeService, path.ContactsCategory),
|
|
||||||
},
|
|
||||||
fallbackReasons: []identity.Reasoner{
|
|
||||||
fbEmailReason,
|
|
||||||
kopia.NewReason("", fbro, path.ExchangeService, path.ContactsCategory),
|
|
||||||
},
|
|
||||||
getMeta: true,
|
|
||||||
assertErr: assert.NoError,
|
|
||||||
assertB: assert.True,
|
|
||||||
expectDCS: []mockColl{{id: "id1"}, {id: "fb_id1"}},
|
|
||||||
expectMans: kopia.NewMockBackupBases().WithMergeBases(
|
|
||||||
makeMan(ro, "id1", "", path.EmailCategory),
|
|
||||||
makeMan(fbro, "fb_id1", "", path.ContactsCategory),
|
|
||||||
).WithBackups(
|
|
||||||
makeBackup(fbro, "fb_id1", path.ContactsCategory),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range table {
|
|
||||||
suite.Run(test.name, func() {
|
|
||||||
t := suite.T()
|
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
mans, dcs, b, err := produceManifestsAndMetadata(
|
|
||||||
ctx,
|
|
||||||
test.bf,
|
|
||||||
&test.rp,
|
|
||||||
test.reasons, test.fallbackReasons,
|
|
||||||
tid,
|
|
||||||
test.getMeta,
|
|
||||||
test.dropAssist)
|
|
||||||
test.assertErr(t, err, clues.ToCore(err))
|
|
||||||
test.assertB(t, b)
|
|
||||||
|
|
||||||
kopia.AssertBackupBasesEqual(t, test.expectMans, mans)
|
|
||||||
|
|
||||||
expect, got := []string{}, []string{}
|
|
||||||
|
|
||||||
for _, dc := range test.expectDCS {
|
|
||||||
expect = append(expect, dc.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, dc := range dcs {
|
|
||||||
if !assert.IsTypef(
|
|
||||||
t,
|
|
||||||
data.NoFetchRestoreCollection{},
|
|
||||||
dc,
|
|
||||||
"unexpected type returned [%T]",
|
|
||||||
dc,
|
|
||||||
) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp := dc.(data.NoFetchRestoreCollection)
|
|
||||||
|
|
||||||
if !assert.IsTypef(
|
|
||||||
t,
|
|
||||||
mockColl{},
|
|
||||||
tmp.Collection,
|
|
||||||
"unexpected type returned [%T]",
|
|
||||||
tmp.Collection,
|
|
||||||
) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mc := tmp.Collection.(mockColl)
|
|
||||||
got = append(got, mc.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.ElementsMatch(t, expect, got, "expected collections are present")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user