Consolidate/move OneDrive GraphConnector tests (#2487)

## Description

Now that we're also testing permissions behavior the OneDrive tests have gotten kind of large. This PR consolidates some of the code for tests and moves the OneDrive tests to their own file

It also sets things up so it's easier to add tests for different backup layouts in the future

Viewing by commit may make reviews easier

## 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
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [x] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

## Issue(s)

* #2447

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2023-02-14 13:27:25 -08:00 committed by GitHub
parent 570ce85656
commit 28fcafe3b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 821 additions and 1111 deletions

View File

@ -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,

View File

@ -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},
},
)
})
}
}

File diff suppressed because it is too large Load Diff