From 62c8f8c6eaae07ec1dff982bb0f656f43d392274 Mon Sep 17 00:00:00 2001 From: ashmrtn Date: Thu, 22 Dec 2022 18:04:14 -0800 Subject: [PATCH] Update details merge function for details Builder and new location of folder population (#1926) ## Description Folder population now done when merging items in BackupOp. Also add more tests to make sure folders are actually populated properly in Details ## Does this PR need a docs update or release note? - [ ] :white_check_mark: Yes, it's included - [ ] :clock1: Yes, but in a later PR - [x] :no_entry: No ## Type of change - [x] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [ ] :robot: Test - [ ] :computer: CI/Deployment - [ ] :hamster: Trivial/Minor ## Issue(s) * #1800 ## Test Plan - [ ] :muscle: Manual - [x] :zap: Unit test - [ ] :green_heart: E2E --- src/internal/operations/backup.go | 3 + src/internal/operations/backup_test.go | 123 ++++++++++++++++++++++++- src/pkg/backup/details/details.go | 1 + 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index d57e93e01..790e6dd8a 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -498,6 +498,9 @@ func mergeDetails( item, ) + folders := details.FolderEntriesForPath(newPath.ToBuilder().Dir()) + deets.AddFoldersForItem(folders, item) + // Track how many entries we added so that we know if we got them all when // we're done. addedEntries++ diff --git a/src/internal/operations/backup_test.go b/src/internal/operations/backup_test.go index 2bf03b9c2..36d4f8a79 100644 --- a/src/internal/operations/backup_test.go +++ b/src/internal/operations/backup_test.go @@ -619,7 +619,7 @@ func makeManifest(backupID model.StableID, incompleteReason string) *snapshot.Ma } } -func (suite *BackupOpSuite) TestBackupOperation_MergeBackupDetails() { +func (suite *BackupOpSuite) TestBackupOperation_MergeBackupDetails_AddsItems() { var ( tenant = "a-tenant" ro = "a-user" @@ -1118,6 +1118,127 @@ func (suite *BackupOpSuite) TestBackupOperation_MergeBackupDetails() { } } +func makeFolderEntry( + pb *path.Builder, + size int64, + modTime time.Time, +) *details.DetailsEntry { + return &details.DetailsEntry{ + RepoRef: pb.String(), + ShortRef: pb.ShortRef(), + ParentRef: pb.Dir().ShortRef(), + ItemInfo: details.ItemInfo{ + Folder: &details.FolderInfo{ + ItemType: details.FolderItem, + DisplayName: pb.Elements()[len(pb.Elements())-1], + Modified: modTime, + Size: size, + }, + }, + } +} + +func (suite *BackupOpSuite) TestBackupOperation_MergeBackupDetails_AddsFolders() { + var ( + t = suite.T() + + tenant = "a-tenant" + ro = "a-user" + + pathElems = []string{ + tenant, + path.ExchangeService.String(), + ro, + path.EmailCategory.String(), + "work", + "item1", + } + + itemPath1 = makePath( + t, + pathElems, + true, + ) + + backup1 = backup.Backup{ + BaseModel: model.BaseModel{ + ID: "bid1", + }, + DetailsID: "did1", + } + + pathReason1 = kopia.Reason{ + ResourceOwner: itemPath1.ResourceOwner(), + Service: itemPath1.Service(), + Category: itemPath1.Category(), + } + + inputToMerge = map[string]path.Path{ + itemPath1.ShortRef(): itemPath1, + } + + inputMans = []*kopia.ManifestEntry{ + { + Manifest: makeManifest(backup1.ID, ""), + Reasons: []kopia.Reason{ + pathReason1, + }, + }, + } + + populatedModels = map[model.StableID]backup.Backup{ + backup1.ID: backup1, + } + + itemSize = 42 + itemDetails = makeDetailsEntry(t, itemPath1, itemSize, false) + + populatedDetails = map[string]*details.Details{ + backup1.DetailsID: { + DetailsModel: details.DetailsModel{ + Entries: []details.DetailsEntry{ + *itemDetails, + }, + }, + }, + } + + expectedEntries = []details.DetailsEntry{ + *itemDetails, + } + ) + + itemDetails.Exchange.Modified = time.Now() + + for i := 1; i < len(pathElems); i++ { + expectedEntries = append(expectedEntries, *makeFolderEntry( + path.Builder{}.Append(pathElems[:i]...), + int64(itemSize), + itemDetails.Exchange.Modified, + )) + } + + ctx, flush := tester.NewContext() + defer flush() + + mdr := mockDetailsReader{entries: populatedDetails} + w := &store.Wrapper{Storer: mockBackupStorer{entries: populatedModels}} + + deets := details.Builder{} + + err := mergeDetails( + ctx, + w, + mdr, + inputMans, + inputToMerge, + &deets, + ) + + assert.NoError(t, err) + assert.ElementsMatch(t, expectedEntries, deets.Details().Entries) +} + // --------------------------------------------------------------------------- // integration // --------------------------------------------------------------------------- diff --git a/src/pkg/backup/details/details.go b/src/pkg/backup/details/details.go index 6c0fc2e95..21f392c98 100644 --- a/src/pkg/backup/details/details.go +++ b/src/pkg/backup/details/details.go @@ -142,6 +142,7 @@ func FolderEntriesForPath(parent *path.Builder) []FolderEntry { ParentRef: nextParent.ShortRef(), Info: ItemInfo{ Folder: &FolderInfo{ + ItemType: FolderItem, DisplayName: parent.Elements()[len(parent.Elements())-1], }, },