Mark collections as Deleted if not available and invalid delta (#2503)

## Description

<!-- Insert PR description-->

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

- [ ]  Yes, it's included
- [x] 🕐 Yes, but in a later PR
- [ ]  No 

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

## Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* Final entry : closes https://github.com/alcionai/corso/issues/2242

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
Abin Simon 2023-02-21 14:58:51 +05:30 committed by GitHub
parent 8b21e25a82
commit dd72c4c8f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 7 deletions

View File

@ -344,14 +344,59 @@ func (c *Collections) Get(
folderPaths[driveID] = map[string]string{} folderPaths[driveID] = map[string]string{}
maps.Copy(folderPaths[driveID], paths) maps.Copy(folderPaths[driveID], paths)
maps.Copy(excludedItems, excluded)
logger.Ctx(ctx).Infow( logger.Ctx(ctx).Infow(
"persisted metadata for drive", "persisted metadata for drive",
"num_paths_entries", "num_paths_entries",
len(paths), len(paths),
"num_deltas_entries", "num_deltas_entries",
numDeltas) numDeltas)
if !delta.Reset {
maps.Copy(excludedItems, excluded)
continue
}
// Set all folders in previous backup but not in the current
// one with state deleted
modifiedPaths := map[string]struct{}{}
for _, p := range c.CollectionMap {
modifiedPaths[p.FullPath().String()] = struct{}{}
}
for i, p := range oldPaths {
_, found := paths[i]
if found {
continue
}
_, found = modifiedPaths[p]
if found {
// Original folder was deleted and new folder with the
// same name/path was created in its place
continue
}
delete(paths, i)
prevPath, err := path.FromDataLayerPath(p, false)
if err != nil {
return nil, map[string]struct{}{},
clues.Wrap(err, "invalid previous path").WithClues(ctx).With("deleted_path", p)
}
col := NewCollection(
c.itemClient,
nil,
prevPath,
driveID,
c.service,
c.statusUpdater,
c.source,
c.ctrl,
true,
)
c.CollectionMap[i] = col
}
} }
observe.Message(ctx, observe.Safe(fmt.Sprintf("Discovered %d items to backup", c.NumItems))) observe.Message(ctx, observe.Safe(fmt.Sprintf("Discovered %d items to backup", c.NumItems)))

View File

@ -1531,6 +1531,89 @@ func (suite *OneDriveCollectionsSuite) TestGet() {
expectedDelList: map[string]struct{}{"file": {}}, expectedDelList: map[string]struct{}{"file": {}},
doNotMergeItems: false, doNotMergeItems: false,
}, },
{
name: "OneDrive_OneItemPage_InvalidPrevDelta_DeleteNonExistantFolder",
drives: []models.Driveable{drive1},
items: map[string][]deltaPagerResult{
driveID1: {
{
err: getDeltaError(),
},
{
items: []models.DriveItemable{
driveRootItem("root"),
driveItem("folder2", "folder2", driveBasePath1, "root", false, true, false),
driveItem("file", "file", driveBasePath1+"/folder2", "folder2", true, false, false),
},
deltaLink: &delta,
},
},
},
errCheck: assert.NoError,
prevFolderPaths: map[string]map[string]string{
driveID1: {
"root": rootFolderPath1,
"folder": folderPath1,
},
},
expectedCollections: map[string]map[data.CollectionState][]string{
expectedPath1(""): {data.NotMovedState: {"folder2"}},
expectedPath1("/folder"): {data.DeletedState: {}},
expectedPath1("/folder2"): {data.NewState: {"file"}},
},
expectedDeltaURLs: map[string]string{
driveID1: delta,
},
expectedFolderPaths: map[string]map[string]string{
driveID1: {
"root": rootFolderPath1,
"folder2": expectedPath1("/folder2"),
},
},
expectedDelList: map[string]struct{}{},
doNotMergeItems: true,
},
{
name: "OneDrive_OneItemPage_InvalidPrevDelta_AnotherFolderAtDeletedLocation",
drives: []models.Driveable{drive1},
items: map[string][]deltaPagerResult{
driveID1: {
{
err: getDeltaError(),
},
{
items: []models.DriveItemable{
driveRootItem("root"),
driveItem("folder2", "folder", driveBasePath1, "root", false, true, false),
driveItem("file", "file", driveBasePath1+"/folder", "folder2", true, false, false),
},
deltaLink: &delta,
},
},
},
errCheck: assert.NoError,
prevFolderPaths: map[string]map[string]string{
driveID1: {
"root": rootFolderPath1,
"folder": folderPath1,
},
},
expectedCollections: map[string]map[data.CollectionState][]string{
expectedPath1(""): {data.NotMovedState: {"folder2"}},
expectedPath1("/folder"): {data.NewState: {"file"}},
},
expectedDeltaURLs: map[string]string{
driveID1: delta,
},
expectedFolderPaths: map[string]map[string]string{
driveID1: {
"root": rootFolderPath1,
"folder2": expectedPath1("/folder"),
},
},
expectedDelList: map[string]struct{}{},
doNotMergeItems: true,
},
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
@ -1574,6 +1657,7 @@ func (suite *OneDriveCollectionsSuite) TestGet() {
c.drivePagerFunc = drivePagerFunc c.drivePagerFunc = drivePagerFunc
c.itemPagerFunc = itemPagerFunc c.itemPagerFunc = itemPagerFunc
prevDelta := "prev-delta"
mc, err := graph.MakeMetadataCollection( mc, err := graph.MakeMetadataCollection(
tenant, tenant,
user, user,
@ -1583,8 +1667,8 @@ func (suite *OneDriveCollectionsSuite) TestGet() {
graph.NewMetadataEntry( graph.NewMetadataEntry(
graph.DeltaURLsFileName, graph.DeltaURLsFileName,
map[string]string{ map[string]string{
driveID1: "prev-delta", driveID1: prevDelta,
driveID2: "prev-delta", driveID2: prevDelta,
}, },
), ),
graph.NewMetadataEntry( graph.NewMetadataEntry(
@ -1605,7 +1689,13 @@ func (suite *OneDriveCollectionsSuite) TestGet() {
} }
for _, baseCol := range cols { for _, baseCol := range cols {
folderPath := baseCol.FullPath().String() var folderPath string
if baseCol.State() != data.DeletedState {
folderPath = baseCol.FullPath().String()
} else {
folderPath = baseCol.PreviousPath().String()
}
if folderPath == metadataPath.String() { if folderPath == metadataPath.String() {
deltas, paths, err := deserializeMetadata(ctx, []data.RestoreCollection{ deltas, paths, err := deserializeMetadata(ctx, []data.RestoreCollection{
data.NotFoundRestoreCollection{Collection: baseCol}, data.NotFoundRestoreCollection{Collection: baseCol},
@ -1614,8 +1704,8 @@ func (suite *OneDriveCollectionsSuite) TestGet() {
continue continue
} }
assert.Equal(t, test.expectedDeltaURLs, deltas) assert.Equal(t, test.expectedDeltaURLs, deltas, "delta urls")
assert.Equal(t, test.expectedFolderPaths, paths) assert.Equal(t, test.expectedFolderPaths, paths, "folder paths")
continue continue
} }

View File

@ -213,6 +213,7 @@ func collectItems(
logger.Ctx(ctx).Infow("Invalid previous delta link", "link", prevDelta) logger.Ctx(ctx).Infow("Invalid previous delta link", "link", prevDelta)
invalidPrevDelta = true invalidPrevDelta = true
newPaths = map[string]string{}
pager.Reset() pager.Reset()