diff --git a/src/internal/connector/graph_connector_helper_test.go b/src/internal/connector/graph_connector_helper_test.go index 48f6d5f7e..d0ce306fe 100644 --- a/src/internal/connector/graph_connector_helper_test.go +++ b/src/internal/connector/graph_connector_helper_test.go @@ -22,6 +22,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/tester" + "github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/path" @@ -147,6 +148,16 @@ func testElementsMatch[T any]( ) } +type configInfo struct { + acct account.Account + opts control.Options + resource resource + service path.ServiceType + tenant string + resourceOwners []string + dest control.RestoreDestination +} + type itemInfo struct { // lookupKey is a string that can be used to find this data from a set of // other data in the same collection. This key should be something that will @@ -185,6 +196,8 @@ type restoreBackupInfoMultiVersion struct { collectionsLatest []colInfo collectionsPrevious []colInfo resource resource + backupVersion int + countMeta bool } func attachmentEqual( @@ -730,7 +743,6 @@ func compareOneDriveItem( return } - assert.Equal(t, len(expectedMeta.Permissions), len(itemMeta.Permissions), "number of permissions after restore") testElementsMatch(t, expectedMeta.Permissions, itemMeta.Permissions, permissionEqual) } @@ -999,6 +1011,7 @@ func collectionsForInfo( tenant, user string, dest control.RestoreDestination, allInfo []colInfo, + backupVersion int, ) (int, int, []data.RestoreCollection, map[string]map[string][]byte) { collections := make([]data.RestoreCollection, 0, len(allInfo)) expectedData := make(map[string]map[string][]byte, len(allInfo)) @@ -1031,7 +1044,7 @@ func collectionsForInfo( baseExpected[info.items[i].lookupKey] = info.items[i].data // We do not count metadata files against item count - if service != path.OneDriveService || + if backupVersion == 0 || service != path.OneDriveService || (service == path.OneDriveService && strings.HasSuffix(info.items[i].name, onedrive.DataFileSuffix)) { totalItems++ @@ -1054,55 +1067,6 @@ func collectionsForInfo( return totalItems, kopiaEntries, collections, expectedData } -func collectionsForInfoVersion0( - t *testing.T, - service path.ServiceType, - tenant, user string, - dest control.RestoreDestination, - allInfo []colInfo, -) (int, int, []data.RestoreCollection, map[string]map[string][]byte) { - collections := make([]data.RestoreCollection, 0, len(allInfo)) - expectedData := make(map[string]map[string][]byte, len(allInfo)) - totalItems := 0 - kopiaEntries := 0 - - for _, info := range allInfo { - pth := mustToDataLayerPath( - t, - service, - tenant, - user, - info.category, - info.pathElements, - false, - ) - c := mockconnector.NewMockExchangeCollection(pth, pth, len(info.items)) - baseDestPath := backupOutputPathFromRestore(t, dest, pth) - - baseExpected := expectedData[baseDestPath.String()] - if baseExpected == nil { - expectedData[baseDestPath.String()] = make(map[string][]byte, len(info.items)) - baseExpected = expectedData[baseDestPath.String()] - } - - for i := 0; i < len(info.items); i++ { - c.Names[i] = info.items[i].name - c.Data[i] = info.items[i].data - - baseExpected[info.items[i].lookupKey] = info.items[i].data - } - - collections = append(collections, data.NotFoundRestoreCollection{ - Collection: c, - }) - totalItems += len(info.items) - kopiaEntries += len(info.items) - } - - return totalItems, kopiaEntries, collections, expectedData -} - -//nolint:deadcode func getSelectorWith( t *testing.T, service path.ServiceType, diff --git a/src/internal/connector/graph_connector_onedrive_test.go b/src/internal/connector/graph_connector_onedrive_test.go new file mode 100644 index 000000000..1614c59a8 --- /dev/null +++ b/src/internal/connector/graph_connector_onedrive_test.go @@ -0,0 +1,670 @@ +package connector + +import ( + "encoding/base64" + "encoding/json" + "strings" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/alcionai/corso/src/internal/connector/graph" + "github.com/alcionai/corso/src/internal/connector/onedrive" + "github.com/alcionai/corso/src/internal/tester" + "github.com/alcionai/corso/src/pkg/account" + "github.com/alcionai/corso/src/pkg/control" + "github.com/alcionai/corso/src/pkg/path" +) + +func getTestMetaJSON(t *testing.T, user string, roles []string) []byte { + id := base64.StdEncoding.EncodeToString([]byte(user + strings.Join(roles, "+"))) + testMeta := onedrive.Metadata{Permissions: []onedrive.UserPermission{ + {ID: id, Roles: roles, Email: user}, + }} + + testMetaJSON, err := json.Marshal(testMeta) + if err != nil { + t.Fatal("unable to marshall test permissions", err) + } + + return testMetaJSON +} + +func onedriveItemWithData(name string, itemData []byte) itemInfo { + return itemInfo{ + name: name, + data: itemData, + lookupKey: name, + } +} + +func onedriveFileWithMetadata(baseName string, fileData, metadata []byte) []itemInfo { + return []itemInfo{ + onedriveItemWithData(baseName+onedrive.DataFileSuffix, fileData), + onedriveItemWithData(baseName+onedrive.MetaFileSuffix, metadata), + } +} + +type GraphConnectorOneDriveIntegrationSuite struct { + suite.Suite + connector *GraphConnector + user string + secondaryUser string + acct account.Account +} + +func TestGraphConnectorOneDriveIntegrationSuite(t *testing.T) { + tester.RunOnAny( + t, + tester.CorsoCITests, + tester.CorsoGraphConnectorTests, + tester.CorsoGraphConnectorExchangeTests) + + suite.Run(t, new(GraphConnectorOneDriveIntegrationSuite)) +} + +func (suite *GraphConnectorOneDriveIntegrationSuite) SetupSuite() { + ctx, flush := tester.NewContext() + defer flush() + + tester.MustGetEnvSets(suite.T(), tester.M365AcctCredEnvs) + + suite.connector = loadConnector(ctx, suite.T(), graph.HTTPClient(graph.NoTimeout()), Users) + suite.user = tester.M365UserID(suite.T()) + suite.secondaryUser = tester.SecondaryM365UserID(suite.T()) + suite.acct = tester.NewM365Account(suite.T()) + + tester.LogTimeOfTest(suite.T()) +} + +var ( + fileEmptyPerms = onedriveItemWithData( + "test-file.txt"+onedrive.MetaFileSuffix, + []byte("{}"), + ) + + fileAEmptyPerms = []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.DataFileSuffix, + []byte(strings.Repeat("a", 33)), + ), + fileEmptyPerms, + } + + fileBEmptyPerms = []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.DataFileSuffix, + []byte(strings.Repeat("b", 65)), + ), + fileEmptyPerms, + } + + fileCEmptyPerms = []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.DataFileSuffix, + []byte(strings.Repeat("c", 129)), + ), + fileEmptyPerms, + } + + fileDEmptyPerms = []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.DataFileSuffix, + []byte(strings.Repeat("d", 257)), + ), + fileEmptyPerms, + } + + fileEEmptyPerms = []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.DataFileSuffix, + []byte(strings.Repeat("e", 257)), + ), + fileEmptyPerms, + } + + folderAEmptyPerms = []itemInfo{ + onedriveItemWithData("folder-a"+onedrive.DirMetaFileSuffix, []byte("{}")), + } + + folderBEmptyPerms = []itemInfo{ + onedriveItemWithData("b"+onedrive.DirMetaFileSuffix, []byte("{}")), + } +) + +func withItems(items ...[]itemInfo) []itemInfo { + res := []itemInfo{} + for _, i := range items { + res = append(res, i...) + } + + return res +} + +func (suite *GraphConnectorOneDriveIntegrationSuite) TestRestoreAndBackup() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + table := []restoreBackupInfo{ + { + name: "OneDriveFoldersAndFilesWithMetadata", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: withItems( + onedriveFileWithMetadata( + "test-file.txt", + []byte(strings.Repeat("a", 33)), + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + ), + []itemInfo{onedriveItemWithData( + "b"+onedrive.DirMetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + )}, + ), + auxItems: []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.MetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + ), + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: onedriveFileWithMetadata( + "test-file.txt", + []byte(strings.Repeat("e", 66)), + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + ), + auxItems: []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.MetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + ), + }, + }, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTest( + t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} + +func (suite *GraphConnectorOneDriveIntegrationSuite) TestRestoreAndBackup_Versions() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + collectionsLatest := []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: withItems( + fileAEmptyPerms, + folderAEmptyPerms, + folderBEmptyPerms, + ), + auxItems: []itemInfo{fileEmptyPerms}, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + }, + category: path.FilesCategory, + items: withItems(fileBEmptyPerms, folderBEmptyPerms), + auxItems: []itemInfo{fileEmptyPerms}, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + }, + category: path.FilesCategory, + items: withItems(fileCEmptyPerms, folderAEmptyPerms), + auxItems: []itemInfo{fileEmptyPerms}, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + "folder-a", + }, + category: path.FilesCategory, + items: fileDEmptyPerms, + auxItems: []itemInfo{fileEmptyPerms}, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: fileEEmptyPerms, + auxItems: []itemInfo{fileEmptyPerms}, + }, + } + + table := []restoreBackupInfoMultiVersion{ + { + name: "OneDriveMultipleFoldersAndFiles_Version0", + service: path.OneDriveService, + resource: Users, + backupVersion: 0, // The OG version ;) + countMeta: true, + + collectionsPrevious: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + onedriveItemWithData( + "test-file.txt", + []byte(strings.Repeat("a", 33)), + ), + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + }, + category: path.FilesCategory, + items: []itemInfo{ + onedriveItemWithData( + "test-file.txt", + []byte(strings.Repeat("b", 65)), + ), + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + onedriveItemWithData( + "test-file.txt", + []byte(strings.Repeat("c", 129)), + ), + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + "folder-a", + }, + category: path.FilesCategory, + items: []itemInfo{ + onedriveItemWithData( + "test-file.txt", + []byte(strings.Repeat("d", 257)), + ), + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + onedriveItemWithData( + "test-file.txt", + []byte(strings.Repeat("e", 257)), + ), + }, + }, + }, + + collectionsLatest: collectionsLatest, + }, + + { + name: "OneDriveMultipleFoldersAndFiles_Version1", + service: path.OneDriveService, + resource: Users, + backupVersion: 1, + countMeta: false, + collectionsPrevious: collectionsLatest, + collectionsLatest: collectionsLatest, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTestVersions( + t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} + +func (suite *GraphConnectorOneDriveIntegrationSuite) TestPermissionsRestoreAndBackup() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + var ( + fileAWritePerms = onedriveFileWithMetadata( + "test-file.txt", + []byte(strings.Repeat("a", 33)), + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + ) + + fileEReadPerms = onedriveFileWithMetadata( + "test-file.txt", + []byte(strings.Repeat("e", 66)), + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + ) + + folderBReadPerms = []itemInfo{onedriveItemWithData( + "b"+onedrive.DirMetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + )} + + fileWritePerms = onedriveItemWithData( + "test-file.txt"+onedrive.MetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + ) + + fileReadPerms = onedriveItemWithData( + "test-file.txt"+onedrive.MetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + ) + ) + + table := []restoreBackupInfo{ + { + name: "FilePermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: fileAWritePerms, + auxItems: []itemInfo{fileWritePerms}, + }, + }, + }, + + { + name: "FileInsideFolderPermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: withItems(fileAEmptyPerms, folderBEmptyPerms), + auxItems: []itemInfo{fileEmptyPerms}, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: fileEReadPerms, + auxItems: []itemInfo{fileReadPerms}, + }, + }, + }, + + { + name: "FileAndFolderPermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: withItems(fileAWritePerms, folderBReadPerms), + auxItems: []itemInfo{fileWritePerms}, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: fileEReadPerms, + auxItems: []itemInfo{fileReadPerms}, + }, + }, + }, + + { + name: "FileAndFolderSeparatePermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: folderBReadPerms, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: fileAWritePerms, + auxItems: []itemInfo{fileWritePerms}, + }, + }, + }, + + { + name: "FolderAndNoChildPermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: folderBReadPerms, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: fileEEmptyPerms, + auxItems: []itemInfo{fileEmptyPerms}, + }, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTest(t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} + +func (suite *GraphConnectorOneDriveIntegrationSuite) TestPermissionsBackupAndNoRestore() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + table := []restoreBackupInfo{ + { + name: "FilePermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: onedriveFileWithMetadata( + "test-file.txt", + []byte(strings.Repeat("a", 33)), + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + ), + auxItems: []itemInfo{ + onedriveItemWithData( + "test-file.txt"+onedrive.MetaFileSuffix, + getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + ), + }, + }, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTest( + t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} diff --git a/src/internal/connector/graph_connector_test.go b/src/internal/connector/graph_connector_test.go index c5122becd..f263d0f42 100644 --- a/src/internal/connector/graph_connector_test.go +++ b/src/internal/connector/graph_connector_test.go @@ -2,9 +2,6 @@ package connector import ( "context" - "encoding/base64" - "encoding/json" - "strings" "testing" "time" @@ -17,7 +14,6 @@ import ( "github.com/alcionai/corso/src/internal/connector/discovery/api" "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/mockconnector" - "github.com/alcionai/corso/src/internal/connector/onedrive" "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/tester" @@ -368,34 +364,30 @@ func mustGetDefaultDriveID( return *d.GetId() } -func runRestoreBackupTest( +func getCollectionsAndExpected( t *testing.T, - acct account.Account, - test restoreBackupInfo, - tenant string, - resourceOwners []string, - opts control.Options, -) { + config configInfo, + testCollections []colInfo, + backupVersion int, +) (int, int, []data.RestoreCollection, map[string]map[string][]byte) { + t.Helper() + var ( collections []data.RestoreCollection expectedData = map[string]map[string][]byte{} totalItems = 0 totalKopiaItems = 0 - // Get a dest per test so they're independent. - dest = tester.DefaultTestRestoreDestination() ) - ctx, flush := tester.NewContext() - defer flush() - - for _, owner := range resourceOwners { + for _, owner := range config.resourceOwners { numItems, kopiaItems, ownerCollections, userExpectedData := collectionsForInfo( t, - test.service, - tenant, + config.service, + config.tenant, owner, - dest, - test.collections, + config.dest, + testCollections, + backupVersion, ) collections = append(collections, ownerCollections...) @@ -405,22 +397,33 @@ func runRestoreBackupTest( maps.Copy(expectedData, userExpectedData) } + return totalItems, totalKopiaItems, collections, expectedData +} + +func runRestore( + t *testing.T, + ctx context.Context, //revive:disable-line:context-as-argument + config configInfo, + backupVersion int, + collections []data.RestoreCollection, + numRestoreItems int, +) { t.Logf( "Restoring collections to %s for resourceOwners(s) %v\n", - dest.ContainerName, - resourceOwners) + config.dest.ContainerName, + config.resourceOwners) start := time.Now() - restoreGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) - restoreSel := getSelectorWith(t, test.service, resourceOwners, true) + restoreGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), config.resource) + restoreSel := getSelectorWith(t, config.service, config.resourceOwners, true) deets, err := restoreGC.RestoreDataCollections( ctx, - backup.Version, - acct, + backupVersion, + config.acct, restoreSel, - dest, - opts, + config.dest, + config.opts, collections, fault.New(true)) require.NoError(t, err) @@ -431,36 +434,48 @@ func runRestoreBackupTest( assert.NoError(t, status.Err, "restored status.Err") assert.Zero(t, status.ErrorCount, "restored status.ErrorCount") - assert.Equal(t, totalItems, status.ObjectCount, "restored status.ObjectCount") - assert.Equal(t, totalItems, status.Successful, "restored status.Successful") + assert.Equal(t, numRestoreItems, status.ObjectCount, "restored status.ObjectCount") + assert.Equal(t, numRestoreItems, status.Successful, "restored status.Successful") assert.Len( t, deets.Entries, - totalItems, + numRestoreItems, "details entries contains same item count as total successful items restored") t.Logf("Restore complete in %v\n", runTime) +} + +func runBackupAndCompare( + t *testing.T, + ctx context.Context, //revive:disable-line:context-as-argument + config configInfo, + expectedData map[string]map[string][]byte, + totalItems int, + totalKopiaItems int, + inputCollections []colInfo, +) { + t.Helper() // Run a backup and compare its output with what we put in. - cats := make(map[path.CategoryType]struct{}, len(test.collections)) - for _, c := range test.collections { + cats := make(map[path.CategoryType]struct{}, len(inputCollections)) + for _, c := range inputCollections { cats[c.category] = struct{}{} } - expectedDests := make([]destAndCats, 0, len(resourceOwners)) - for _, ro := range resourceOwners { + expectedDests := make([]destAndCats, 0, len(config.resourceOwners)) + for _, ro := range config.resourceOwners { expectedDests = append(expectedDests, destAndCats{ resourceOwner: ro, - dest: dest.ContainerName, + dest: config.dest.ContainerName, cats: cats, }) } - backupGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) - backupSel := backupSelectorForExpected(t, test.service, expectedDests) + backupGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), config.resource) + backupSel := backupSelectorForExpected(t, config.service, expectedDests) t.Logf("Selective backup of %s\n", backupSel) - start = time.Now() + start := time.Now() dcs, excludes, err := backupGC.DataCollections( ctx, backupSel, @@ -478,9 +493,9 @@ func runRestoreBackupTest( // Pull the data prior to waiting for the status as otherwise it will // deadlock. - skipped := checkCollections(t, totalKopiaItems, expectedData, dcs, opts.RestorePermissions) + skipped := checkCollections(t, totalKopiaItems, expectedData, dcs, config.opts.RestorePermissions) - status = backupGC.AwaitStatus() + status := backupGC.AwaitStatus() assert.NoError(t, status.Err, "backup status.Err") assert.Zero(t, status.ErrorCount, "backup status.ErrorCount") @@ -490,10 +505,55 @@ func runRestoreBackupTest( "backup status.Successful; wanted %d items + %d skipped", totalItems, skipped) } -// runRestoreBackupTestVersion0 restores with data from an older +func runRestoreBackupTest( + t *testing.T, + acct account.Account, + test restoreBackupInfo, + tenant string, + resourceOwners []string, + opts control.Options, +) { + ctx, flush := tester.NewContext() + defer flush() + + config := configInfo{ + acct: acct, + opts: opts, + resource: test.resource, + service: test.service, + tenant: tenant, + resourceOwners: resourceOwners, + dest: tester.DefaultTestRestoreDestination(), + } + + totalItems, totalKopiaItems, collections, expectedData := getCollectionsAndExpected( + t, + config, + test.collections, + backup.Version) + + runRestore( + t, + ctx, + config, + backup.Version, + collections, + totalItems) + + runBackupAndCompare( + t, + ctx, + config, + expectedData, + totalItems, + totalKopiaItems, + test.collections) +} + +// runRestoreBackupTestVersions restores with data from an older // version of the backup and check the restored data against the // something that would be in the form of a newer backup. -func runRestoreBackupTestVersion0( +func runRestoreBackupTestVersions( t *testing.T, acct account.Account, test restoreBackupInfoMultiVersion, @@ -501,147 +561,54 @@ func runRestoreBackupTestVersion0( resourceOwners []string, opts control.Options, ) { - var ( - collections []data.RestoreCollection - expectedData = map[string]map[string][]byte{} - totalItems = 0 - totalKopiaItems = 0 - // Get a dest per test so they're independent. - dest = tester.DefaultTestRestoreDestination() - ) - ctx, flush := tester.NewContext() defer flush() - for _, owner := range resourceOwners { - _, _, ownerCollections, _ := collectionsForInfoVersion0( - t, - test.service, - tenant, - owner, - dest, - test.collectionsPrevious, - ) - - collections = append(collections, ownerCollections...) + config := configInfo{ + acct: acct, + opts: opts, + resource: test.resource, + service: test.service, + tenant: tenant, + resourceOwners: resourceOwners, + dest: tester.DefaultTestRestoreDestination(), } - t.Logf( - "Restoring collections to %s for resourceOwners(s) %v\n", - dest.ContainerName, - resourceOwners, - ) + totalItems, _, collections, _ := getCollectionsAndExpected( + t, + config, + test.collectionsPrevious, + test.backupVersion) - start := time.Now() - - restoreGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) - restoreSel := getSelectorWith(t, test.service, resourceOwners, true) - deets, err := restoreGC.RestoreDataCollections( + runRestore( + t, ctx, - 0, // The OG version ;) - acct, - restoreSel, - dest, - opts, + config, + test.backupVersion, collections, - fault.New(true)) - require.NoError(t, err) - assert.NotNil(t, deets) + totalItems) - assert.NotNil(t, restoreGC.AwaitStatus()) + // Get expected output for new version. + totalItems, totalKopiaItems, _, expectedData := getCollectionsAndExpected( + t, + config, + test.collectionsLatest, + backup.Version) - runTime := time.Since(start) - - t.Logf("Restore complete in %v\n", runTime) - - // Run a backup and compare its output with what we put in. - for _, owner := range resourceOwners { - numItems, kopiaItems, _, userExpectedData := collectionsForInfo( - t, - test.service, - tenant, - owner, - dest, - test.collectionsLatest, - ) - - totalItems += numItems - totalKopiaItems += kopiaItems - - maps.Copy(expectedData, userExpectedData) - } - - cats := make(map[path.CategoryType]struct{}, len(test.collectionsLatest)) - for _, c := range test.collectionsLatest { - cats[c.category] = struct{}{} - } - - expectedDests := make([]destAndCats, 0, len(resourceOwners)) - for _, ro := range resourceOwners { - expectedDests = append(expectedDests, destAndCats{ - resourceOwner: ro, - dest: dest.ContainerName, - cats: cats, - }) - } - - backupGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) - backupSel := backupSelectorForExpected(t, test.service, expectedDests) - - start = time.Now() - dcs, excludes, err := backupGC.DataCollections( + runBackupAndCompare( + t, ctx, - backupSel, - nil, - control.Options{ - RestorePermissions: true, - ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, - }, - fault.New(true)) - require.NoError(t, err) - // No excludes yet because this isn't an incremental backup. - assert.Empty(t, excludes) - - t.Logf("Backup enumeration complete in %v\n", time.Since(start)) - - // Pull the data prior to waiting for the status as otherwise it will - // deadlock. - skipped := checkCollections(t, totalKopiaItems, expectedData, dcs, opts.RestorePermissions) - - status := backupGC.AwaitStatus() - assert.Equal(t, totalItems+skipped, status.ObjectCount, "status.ObjectCount") - assert.Equal(t, totalItems+skipped, status.Successful, "status.Successful") -} - -func getTestMetaJSON(t *testing.T, user string, roles []string) []byte { - id := base64.StdEncoding.EncodeToString([]byte(user + strings.Join(roles, "+"))) - testMeta := onedrive.Metadata{Permissions: []onedrive.UserPermission{ - {ID: id, Roles: roles, Email: user}, - }} - - testMetaJSON, err := json.Marshal(testMeta) - if err != nil { - t.Fatal("unable to marshall test permissions", err) - } - - return testMetaJSON + config, + expectedData, + totalItems, + totalKopiaItems, + test.collectionsLatest) } func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { bodyText := "This email has some text. However, all the text is on the same line." subjectText := "Test message for restore" - ctx, flush := tester.NewContext() - defer flush() - - // Get the default drive ID for the test user. - driveID := mustGetDefaultDriveID( - suite.T(), - ctx, - suite.connector.Service, - suite.user, - ) - table := []restoreBackupInfo{ { name: "EmailsWithAttachments", @@ -858,242 +825,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { // }, // }, // }, - { - name: "OneDriveMultipleFoldersAndFiles", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "folder-a" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("b", 65)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("c", 129)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "folder-a" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - "b", - "folder-a", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("d", 257)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 257)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - { - name: "OneDriveFoldersAndFilesWithMetadata", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 66)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, } for _, test := range table { @@ -1113,293 +844,6 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { } } -func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackupVersion0() { - ctx, flush := tester.NewContext() - defer flush() - - // Get the default drive ID for the test user. - driveID := mustGetDefaultDriveID( - suite.T(), - ctx, - suite.connector.Service, - suite.user, - ) - - table := []restoreBackupInfoMultiVersion{ - { - name: "OneDriveMultipleFoldersAndFiles", - service: path.OneDriveService, - resource: Users, - - collectionsPrevious: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt", - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt", - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt", - data: []byte(strings.Repeat("b", 65)), - lookupKey: "test-file.txt", - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt", - data: []byte(strings.Repeat("c", 129)), - lookupKey: "test-file.txt", - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - "b", - "folder-a", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt", - data: []byte(strings.Repeat("d", 257)), - lookupKey: "test-file.txt", - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt", - data: []byte(strings.Repeat("e", 257)), - lookupKey: "test-file.txt", - }, - }, - }, - }, - - collectionsLatest: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "folder-a" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("b", 65)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("c", 129)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "folder-a" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "folder-a", - "b", - "folder-a", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("d", 257)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 257)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - } - - for _, test := range table { - suite.T().Run(test.name, func(t *testing.T) { - runRestoreBackupTestVersion0( - t, - suite.acct, - test, - suite.connector.tenant, - []string{suite.user}, - control.Options{ - RestorePermissions: true, - ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, - }, - ) - }) - } -} - func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames() { table := []restoreBackupInfo{ { @@ -1489,6 +933,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames suite.user, dest, []colInfo{collection}, + backup.Version, ) allItems += totalItems @@ -1562,375 +1007,6 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames } } -func (suite *GraphConnectorIntegrationSuite) TestPermissionsRestoreAndBackup() { - ctx, flush := tester.NewContext() - defer flush() - - // Get the default drive ID for the test user. - driveID := mustGetDefaultDriveID( - suite.T(), - ctx, - suite.connector.Service, - suite.user, - ) - - table := []restoreBackupInfo{ - { - name: "FilePermissionsRestore", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - - { - name: "FileInsideFolderPermissionsRestore", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: []byte("{}"), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 66)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - - { - name: "FileAndFolderPermissionsResote", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - { - name: "b" + onedrive.DirMetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 66)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - - { - name: "FileAndFolderSeparatePermissionsResote", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "b" + onedrive.DirMetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 66)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - - { - name: "FolderAndNoChildPermissionsResote", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "b" + onedrive.DirMetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), - lookupKey: "b" + onedrive.DirMetaFileSuffix, - }, - }, - }, - { - pathElements: []string{ - "drives", - driveID, - "root:", - "b", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("e", 66)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: []byte("{}"), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - } - - for _, test := range table { - suite.T().Run(test.name, func(t *testing.T) { - runRestoreBackupTest(t, - suite.acct, - test, - suite.connector.tenant, - []string{suite.user}, - control.Options{ - RestorePermissions: true, - ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, - }, - ) - }) - } -} - -func (suite *GraphConnectorIntegrationSuite) TestPermissionsBackupAndNoRestore() { - ctx, flush := tester.NewContext() - defer flush() - - // Get the default drive ID for the test user. - driveID := mustGetDefaultDriveID( - suite.T(), - ctx, - suite.connector.Service, - suite.user, - ) - - table := []restoreBackupInfo{ - { - name: "FilePermissionsRestore", - service: path.OneDriveService, - resource: Users, - collections: []colInfo{ - { - pathElements: []string{ - "drives", - driveID, - "root:", - }, - category: path.FilesCategory, - items: []itemInfo{ - { - name: "test-file.txt" + onedrive.DataFileSuffix, - data: []byte(strings.Repeat("a", 33)), - lookupKey: "test-file.txt" + onedrive.DataFileSuffix, - }, - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - auxItems: []itemInfo{ - { - name: "test-file.txt" + onedrive.MetaFileSuffix, - data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), - lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, - }, - }, - }, - }, - }, - } - - for _, test := range table { - suite.T().Run(test.name, func(t *testing.T) { - runRestoreBackupTest( - t, - suite.acct, - test, - suite.connector.tenant, - []string{suite.user}, - control.Options{ - RestorePermissions: true, - ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, - }, - ) - }) - } -} - // TODO: this should only be run during smoke tests, not part of the standard CI. // That's why it's set aside instead of being included in the other test set. func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup_largeMailAttachment() {