Test helper functions for selector creation (#1163)
## Description Mostly path manipulations here to allow creating selectors for a backup and paths for the output of a backup given some information about the input. Capable of working for OneDrive and Exchange. ## Type of change <!--- Please check the type of change your PR introduces: ---> - [x] 🌻 Feature - [ ] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Test - [ ] 💻 CI/Deployment - [ ] 🐹 Trivial/Minor ## Issue(s) * #913 ## Test Plan <!-- How will this be tested prior to merging.--> - [ ] 💪 Manual - [x] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
42b9b133af
commit
29015df8ef
@ -660,6 +660,151 @@ func checkCollections(
|
||||
assert.Equal(t, expectedItems, gotItems, "expected items")
|
||||
}
|
||||
|
||||
func mustParsePath(t *testing.T, p string, isItem bool) path.Path {
|
||||
res, err := path.FromDataLayerPath(p, isItem)
|
||||
require.NoError(t, err)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func makeExchangeBackupSel(
|
||||
t *testing.T,
|
||||
expected map[string]map[string][]byte,
|
||||
) selectors.Selector {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
toInclude := [][]selectors.ExchangeScope{}
|
||||
|
||||
for p := range expected {
|
||||
pth := mustParsePath(t, p, false)
|
||||
require.Equal(t, path.ExchangeService.String(), pth.Service().String())
|
||||
|
||||
switch pth.Category() {
|
||||
case path.EmailCategory:
|
||||
toInclude = append(toInclude, sel.MailFolders(
|
||||
[]string{pth.ResourceOwner()},
|
||||
[]string{backupInputFromPath(pth).String()},
|
||||
))
|
||||
case path.ContactsCategory:
|
||||
toInclude = append(toInclude, sel.ContactFolders(
|
||||
[]string{pth.ResourceOwner()},
|
||||
[]string{backupInputFromPath(pth).String()},
|
||||
))
|
||||
case path.EventsCategory:
|
||||
toInclude = append(toInclude, sel.EventCalendars(
|
||||
[]string{pth.ResourceOwner()},
|
||||
[]string{backupInputFromPath(pth).String()},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
sel.Include(toInclude...)
|
||||
|
||||
return sel.Selector
|
||||
}
|
||||
|
||||
func makeOneDriveBackupSel(
|
||||
t *testing.T,
|
||||
expected map[string]map[string][]byte,
|
||||
) selectors.Selector {
|
||||
sel := selectors.NewOneDriveBackup()
|
||||
toInclude := [][]selectors.OneDriveScope{}
|
||||
|
||||
for p := range expected {
|
||||
pth := mustParsePath(t, p, false)
|
||||
require.Equal(t, path.OneDriveService.String(), pth.Service().String())
|
||||
|
||||
toInclude = append(toInclude, sel.Folders(
|
||||
[]string{pth.ResourceOwner()},
|
||||
[]string{backupInputFromPath(pth).String()},
|
||||
))
|
||||
}
|
||||
|
||||
sel.Include(toInclude...)
|
||||
|
||||
return sel.Selector
|
||||
}
|
||||
|
||||
// backupSelectorForExpected creates a selector that can be used to backup the
|
||||
// given items in expected based on the item paths. Fails the test if items from
|
||||
// multiple services are in expected.
|
||||
func backupSelectorForExpected(
|
||||
t *testing.T,
|
||||
expected map[string]map[string][]byte,
|
||||
) selectors.Selector {
|
||||
require.NotEmpty(t, expected)
|
||||
|
||||
// Sadly need to get the first item to figure out what sort of selector we
|
||||
// need.
|
||||
for p := range expected {
|
||||
pth := mustParsePath(t, p, false)
|
||||
|
||||
switch pth.Service() {
|
||||
case path.ExchangeService:
|
||||
return makeExchangeBackupSel(t, expected)
|
||||
case path.OneDriveService:
|
||||
return makeOneDriveBackupSel(t, expected)
|
||||
default:
|
||||
assert.FailNowf(t, "bad serivce type %s", pth.Service().String())
|
||||
}
|
||||
}
|
||||
|
||||
// Fix compile error about no return. Should not reach here.
|
||||
return selectors.Selector{}
|
||||
}
|
||||
|
||||
// backupInputFromPath returns a path.Builder with the path that a call to Backup
|
||||
// can use to backup the given items.
|
||||
func backupInputFromPath(
|
||||
inputPath path.Path,
|
||||
) *path.Builder {
|
||||
startIdx := 0
|
||||
|
||||
if inputPath.Service() == path.OneDriveService {
|
||||
// OneDrive has folders that are trimmed off in the app that are present in
|
||||
// Corso.
|
||||
startIdx = 3
|
||||
}
|
||||
|
||||
return path.Builder{}.Append(inputPath.Folders()[startIdx:]...)
|
||||
}
|
||||
|
||||
// backupOutputPathFromRestore returns a path.Path denoting the location in
|
||||
// kopia the data will be placed at. The location is a data-type specific
|
||||
// combination of the location the data was recently restored to and where the
|
||||
// data was originally in the hierarchy.
|
||||
func backupOutputPathFromRestore(
|
||||
t *testing.T,
|
||||
restoreDest control.RestoreDestination,
|
||||
inputPath path.Path,
|
||||
) path.Path {
|
||||
base := []string{restoreDest.ContainerName}
|
||||
|
||||
// OneDrive has leading information like the drive ID.
|
||||
if inputPath.Service() == path.OneDriveService {
|
||||
folders := inputPath.Folders()
|
||||
base = append(append([]string{}, folders[:3]...), restoreDest.ContainerName)
|
||||
|
||||
if len(folders) > 3 {
|
||||
base = append(base, folders[3:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ashmrtn): Uncomment when exchange mail supports restoring to subfolders.
|
||||
// if inputPath.Service == path.ExchangeService && inputPath.Category() == path.EmailCategory {
|
||||
// base = append(base, inputPath.Folders()...)
|
||||
// }
|
||||
|
||||
return mustToDataLayerPath(
|
||||
t,
|
||||
inputPath.Service(),
|
||||
inputPath.Tenant(),
|
||||
inputPath.ResourceOwner(),
|
||||
inputPath.Category(),
|
||||
base,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
func collectionsForInfo(
|
||||
t *testing.T,
|
||||
service path.ServiceType,
|
||||
@ -682,19 +827,7 @@ func collectionsForInfo(
|
||||
false,
|
||||
)
|
||||
c := mockconnector.NewMockExchangeCollection(pth, len(info.items))
|
||||
|
||||
// TODO(ashmrtn): This will need expanded/broken up by service/category
|
||||
// depending on how restore for that service/category places data back in
|
||||
// M365.
|
||||
baseDestPath := mustToDataLayerPath(
|
||||
t,
|
||||
service,
|
||||
tenant,
|
||||
user,
|
||||
info.category,
|
||||
[]string{dest.ContainerName},
|
||||
false,
|
||||
)
|
||||
baseDestPath := backupOutputPathFromRestore(t, dest, pth)
|
||||
|
||||
baseExpected := expectedData[baseDestPath.String()]
|
||||
if baseExpected == nil {
|
||||
|
||||
@ -457,7 +457,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
name string
|
||||
service path.ServiceType
|
||||
collections []colInfo
|
||||
backupSelFunc func(dest control.RestoreDestination, backupUser string) selectors.Selector
|
||||
expectedRestoreFolders int
|
||||
}{
|
||||
{
|
||||
@ -486,17 +485,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO(ashmrtn): Generalize this once we know the path transforms that
|
||||
// occur during restore.
|
||||
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
backupSel.Include(backupSel.MailFolders(
|
||||
[]string{backupUser},
|
||||
[]string{dest.ContainerName},
|
||||
))
|
||||
|
||||
return backupSel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MultipleEmailsSingleFolder",
|
||||
@ -534,17 +522,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO(ashmrtn): Generalize this once we know the path transforms that
|
||||
// occur during restore.
|
||||
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
backupSel.Include(backupSel.MailFolders(
|
||||
[]string{backupUser},
|
||||
[]string{dest.ContainerName},
|
||||
))
|
||||
|
||||
return backupSel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MultipleContactsSingleFolder",
|
||||
@ -573,17 +550,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO(ashmrtn): Generalize this once we know the path transforms that
|
||||
// occur during restore.
|
||||
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
backupSel.Include(backupSel.ContactFolders(
|
||||
[]string{backupUser},
|
||||
[]string{dest.ContainerName},
|
||||
))
|
||||
|
||||
return backupSel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MultipleContactsMutlipleFolders",
|
||||
@ -628,17 +594,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO(ashmrtn): Generalize this once we know the path transforms that
|
||||
// occur during restore.
|
||||
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
backupSel.Include(backupSel.ContactFolders(
|
||||
[]string{backupUser},
|
||||
[]string{dest.ContainerName},
|
||||
))
|
||||
|
||||
return backupSel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MultipleEventsSingleCalendar",
|
||||
@ -667,17 +622,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO(ashmrtn): Generalize this once we know the path transforms that
|
||||
// occur during restore.
|
||||
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
backupSel.Include(backupSel.EventCalendars(
|
||||
[]string{backupUser},
|
||||
[]string{dest.ContainerName},
|
||||
))
|
||||
|
||||
return backupSel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MultipleEventsMultipleCalendars",
|
||||
@ -722,17 +666,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO(ashmrtn): Generalize this once we know the path transforms that
|
||||
// occur during restore.
|
||||
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
backupSel.Include(backupSel.EventCalendars(
|
||||
[]string{backupUser},
|
||||
[]string{dest.ContainerName},
|
||||
))
|
||||
|
||||
return backupSel.Selector
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -774,7 +707,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
||||
// Run a backup and compare its output with what we put in.
|
||||
|
||||
backupGC := loadConnector(ctx, t)
|
||||
backupSel := test.backupSelFunc(dest, suite.user)
|
||||
backupSel := backupSelectorForExpected(t, expectedData)
|
||||
t.Logf("Selective backup of %s\n", backupSel)
|
||||
|
||||
dcs, err := backupGC.DataCollections(ctx, backupSel)
|
||||
@ -800,41 +733,6 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
|
||||
bodyText := "This email has some text. However, all the text is on the same line."
|
||||
subjectText := "Test message for restore"
|
||||
|
||||
// TODO(ashmrtn): Update if we start mixing categories during backup/restore.
|
||||
backupSelFunc := func(
|
||||
dests []control.RestoreDestination,
|
||||
category path.CategoryType,
|
||||
backupUser string,
|
||||
) selectors.Selector {
|
||||
destNames := make([]string, 0, len(dests))
|
||||
|
||||
for _, d := range dests {
|
||||
destNames = append(destNames, d.ContainerName)
|
||||
}
|
||||
|
||||
backupSel := selectors.NewExchangeBackup()
|
||||
|
||||
switch category {
|
||||
case path.EmailCategory:
|
||||
backupSel.Include(backupSel.MailFolders(
|
||||
[]string{backupUser},
|
||||
destNames,
|
||||
))
|
||||
case path.ContactsCategory:
|
||||
backupSel.Include(backupSel.ContactFolders(
|
||||
[]string{backupUser},
|
||||
destNames,
|
||||
))
|
||||
case path.EventsCategory:
|
||||
backupSel.Include(backupSel.EventCalendars(
|
||||
[]string{backupUser},
|
||||
destNames,
|
||||
))
|
||||
}
|
||||
|
||||
return backupSel.Selector
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
service path.ServiceType
|
||||
@ -994,7 +892,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
|
||||
// Run a backup and compare its output with what we put in.
|
||||
|
||||
backupGC := loadConnector(ctx, t)
|
||||
backupSel := backupSelFunc(dests, test.category, suite.user)
|
||||
backupSel := backupSelectorForExpected(t, allExpectedData)
|
||||
t.Logf("Selective backup of %s\n", backupSel)
|
||||
|
||||
dcs, err := backupGC.DataCollections(ctx, backupSel)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user