Patch and test some edge cases for deserializing OneDrive metadata (#2341)

## Description

Currently no folder path entry is stored for the root folder. This leads to not having a folders map but having a valid delta token if all items are in the root of the drive.

Update the code to add at least an empty folders map entry so we don't think we have missing metadata. Add tests to check for these edge cases.

Long-term we may want to add a folder entry for the root folder. Whether we do or not may depend on how we decide to set the state field for that collection.

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

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

## Type of change

- [ ] 🌻 Feature
- [x] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

## Issue(s)

* #2122 

## Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2023-02-01 10:57:38 -08:00 committed by GitHub
parent 1594a86c22
commit 24c918e99c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 8 deletions

View File

@ -180,7 +180,15 @@ func deserializeMetadata(
// Go through and remove partial results (i.e. path mapping but no delta URL
// or vice-versa).
for k := range prevDeltas {
for k, v := range prevDeltas {
// Remove entries with an empty delta token as it's not useful.
if len(v) == 0 {
delete(prevDeltas, k)
delete(prevFolders, k)
}
// Remove entries without a folders map as we can't tell kopia the
// hierarchy changes.
if _, ok := prevFolders[k]; !ok {
delete(prevDeltas, k)
}
@ -287,17 +295,21 @@ func (c *Collections) Get(
return nil, nil, err
}
// It's alright to have an empty folders map (i.e. no folders found) but not
// an empty delta token. This is because when deserializing the metadata we
// remove entries for which there is no corresponding delta token/folder. If
// we leave empty delta tokens then we may end up setting the State field
// for collections when not actually getting delta results.
if len(delta) > 0 {
deltaURLs[driveID] = delta
}
if len(paths) > 0 {
folderPaths[driveID] = map[string]string{}
for id, p := range paths {
folderPaths[driveID][id] = p
}
}
// Avoid the edge case where there's no paths but we do have a valid delta
// token. We can accomplish this by adding an empty paths map for this
// drive. If we don't have this then the next backup won't use the delta
// token because it thinks the folder paths weren't persisted.
folderPaths[driveID] = map[string]string{}
maps.Copy(folderPaths[driveID], paths)
maps.Copy(excludedItems, excluded)
}

View File

@ -711,6 +711,60 @@ func (suite *OneDriveCollectionsSuite) TestDeserializeMetadata() {
expectedPaths: map[string]map[string]string{},
errCheck: assert.NoError,
},
{
// An empty path map but valid delta results in metadata being returned
// since it's possible to have a drive with no folders other than the
// root.
name: "EmptyPaths",
cols: []func() []graph.MetadataCollectionEntry{
func() []graph.MetadataCollectionEntry {
return []graph.MetadataCollectionEntry{
graph.NewMetadataEntry(
graph.DeltaURLsFileName,
map[string]string{driveID1: deltaURL1},
),
graph.NewMetadataEntry(
graph.PreviousPathFileName,
map[string]map[string]string{
driveID1: {},
},
),
}
},
},
expectedDeltas: map[string]string{driveID1: deltaURL1},
expectedPaths: map[string]map[string]string{driveID1: {}},
errCheck: assert.NoError,
},
{
// An empty delta map but valid path results in no metadata for that drive
// being returned since the path map is only useful if we have a valid
// delta.
name: "EmptyDeltas",
cols: []func() []graph.MetadataCollectionEntry{
func() []graph.MetadataCollectionEntry {
return []graph.MetadataCollectionEntry{
graph.NewMetadataEntry(
graph.DeltaURLsFileName,
map[string]string{
driveID1: "",
},
),
graph.NewMetadataEntry(
graph.PreviousPathFileName,
map[string]map[string]string{
driveID1: {
folderID1: path1,
},
},
),
}
},
},
expectedDeltas: map[string]string{},
expectedPaths: map[string]map[string]string{},
errCheck: assert.NoError,
},
{
name: "SuccessTwoDrivesTwoCollections",
cols: []func() []graph.MetadataCollectionEntry{