package selectors import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/path" ) type OneDriveSelectorSuite struct { suite.Suite } func TestOneDriveSelectorSuite(t *testing.T) { suite.Run(t, new(OneDriveSelectorSuite)) } func (suite *OneDriveSelectorSuite) TestNewOneDriveBackup() { t := suite.T() ob := NewOneDriveBackup(Any()) assert.Equal(t, ob.Service, ServiceOneDrive) assert.NotZero(t, ob.Scopes()) } func (suite *OneDriveSelectorSuite) TestToOneDriveBackup() { t := suite.T() ob := NewOneDriveBackup(Any()) s := ob.Selector ob, err := s.ToOneDriveBackup() require.NoError(t, err) assert.Equal(t, ob.Service, ServiceOneDrive) assert.NotZero(t, ob.Scopes()) } func (suite *OneDriveSelectorSuite) TestOneDriveSelector_AllData() { t := suite.T() var ( users = []string{"u1", "u2"} sel = NewOneDriveBackup(users) allScopes = sel.AllData() ) assert.ElementsMatch(t, users, sel.DiscreteResourceOwners()) // Initialize the selector Include, Exclude, Filter sel.Exclude(allScopes) sel.Include(allScopes) sel.Filter(allScopes) table := []struct { name string scopesToCheck []scope }{ {"Include Scopes", sel.Includes}, {"Exclude Scopes", sel.Excludes}, {"Filter Scopes", sel.Filters}, } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { require.Len(t, test.scopesToCheck, 1) for _, scope := range test.scopesToCheck { scopeMustHave( t, OneDriveScope(scope), map[categorizer]string{ OneDriveItem: AnyTgt, OneDriveFolder: AnyTgt, }, ) } }) } } func (suite *OneDriveSelectorSuite) TestOneDriveSelector_Include_AllData() { t := suite.T() const ( u1 = "u1" u2 = "u2" ) var ( users = []string{u1, u2} sel = NewOneDriveBackup(users) allScopes = sel.AllData() ) sel.Include(allScopes) scopes := sel.Includes require.Len(t, scopes, 1) for _, sc := range scopes { scopeMustHave( t, OneDriveScope(sc), map[categorizer]string{ OneDriveItem: AnyTgt, OneDriveFolder: AnyTgt, }, ) } } func (suite *OneDriveSelectorSuite) TestOneDriveSelector_Exclude_AllData() { t := suite.T() const ( u1 = "u1" u2 = "u2" ) var ( users = []string{u1, u2} sel = NewOneDriveBackup(users) allScopes = sel.AllData() ) sel.Exclude(allScopes) scopes := sel.Excludes require.Len(t, scopes, 1) for _, sc := range scopes { scopeMustHave( t, OneDriveScope(sc), map[categorizer]string{ OneDriveItem: AnyTgt, OneDriveFolder: AnyTgt, }, ) } } func (suite *OneDriveSelectorSuite) TestNewOneDriveRestore() { t := suite.T() or := NewOneDriveRestore(Any()) assert.Equal(t, or.Service, ServiceOneDrive) assert.NotZero(t, or.Scopes()) } func (suite *OneDriveSelectorSuite) TestToOneDriveRestore() { t := suite.T() eb := NewOneDriveRestore(Any()) s := eb.Selector or, err := s.ToOneDriveRestore() require.NoError(t, err) assert.Equal(t, or.Service, ServiceOneDrive) assert.NotZero(t, or.Scopes()) } func (suite *OneDriveSelectorSuite) TestOneDriveRestore_Reduce() { var ( file = stubRepoRef(path.OneDriveService, path.FilesCategory, "uid", "drive/driveID/root:/folderA/folderB", "file") file2 = stubRepoRef(path.OneDriveService, path.FilesCategory, "uid", "drive/driveID/root:/folderA/folderC", "file2") file3 = stubRepoRef(path.OneDriveService, path.FilesCategory, "uid", "drive/driveID/root:/folderD/folderE", "file3") ) deets := &details.Details{ DetailsModel: details.DetailsModel{ Entries: []details.DetailsEntry{ { RepoRef: file, ItemInfo: details.ItemInfo{ OneDrive: &details.OneDriveInfo{ ItemType: details.OneDriveItem, }, }, }, { RepoRef: file2, ItemInfo: details.ItemInfo{ OneDrive: &details.OneDriveInfo{ ItemType: details.OneDriveItem, }, }, }, { RepoRef: file3, ItemInfo: details.ItemInfo{ OneDrive: &details.OneDriveInfo{ ItemType: details.OneDriveItem, }, }, }, }, }, } arr := func(s ...string) []string { return s } table := []struct { name string deets *details.Details makeSelector func() *OneDriveRestore expect []string }{ { "all", deets, func() *OneDriveRestore { odr := NewOneDriveRestore(Any()) odr.Include(odr.AllData()) return odr }, arr(file, file2, file3), }, { "only match file", deets, func() *OneDriveRestore { odr := NewOneDriveRestore(Any()) odr.Include(odr.Items(Any(), []string{"file2"})) return odr }, arr(file2), }, { "only match folder", deets, func() *OneDriveRestore { odr := NewOneDriveRestore([]string{"uid"}) odr.Include(odr.Folders([]string{"folderA/folderB", "folderA/folderC"})) return odr }, arr(file, file2), }, } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { ctx, flush := tester.NewContext() defer flush() sel := test.makeSelector() results := sel.Reduce(ctx, test.deets) paths := results.Paths() assert.Equal(t, test.expect, paths) }) } } func (suite *OneDriveSelectorSuite) TestOneDriveCategory_PathValues() { t := suite.T() pathBuilder := path.Builder{}.Append("drive", "driveID", "root:", "dir1", "dir2", "file") filePath, err := pathBuilder.ToDataLayerOneDrivePath("tenant", "user", true) require.NoError(t, err) expected := map[categorizer]string{ OneDriveFolder: "dir1/dir2", OneDriveItem: "file", } assert.Equal(t, expected, OneDriveItem.pathValues(filePath)) } func (suite *OneDriveSelectorSuite) TestOneDriveScope_MatchesInfo() { ods := NewOneDriveRestore(Any()) var ( epoch = time.Time{} now = time.Now() future = now.Add(1 * time.Minute) ) itemInfo := details.ItemInfo{ OneDrive: &details.OneDriveInfo{ ItemType: details.OneDriveItem, ParentPath: "folder1/folder2", ItemName: "file1", Size: 10, Owner: "user@email.com", Created: now, Modified: now, }, } table := []struct { name string scope []OneDriveScope expect assert.BoolAssertionFunc }{ {"file create after the epoch", ods.CreatedAfter(common.FormatTime(epoch)), assert.True}, {"file create after now", ods.CreatedAfter(common.FormatTime(now)), assert.False}, {"file create after later", ods.CreatedAfter(common.FormatTime(future)), assert.False}, {"file create before future", ods.CreatedBefore(common.FormatTime(future)), assert.True}, {"file create before now", ods.CreatedBefore(common.FormatTime(now)), assert.False}, {"file create before epoch", ods.CreatedBefore(common.FormatTime(now)), assert.False}, {"file modified after the epoch", ods.ModifiedAfter(common.FormatTime(epoch)), assert.True}, {"file modified after now", ods.ModifiedAfter(common.FormatTime(now)), assert.False}, {"file modified after later", ods.ModifiedAfter(common.FormatTime(future)), assert.False}, {"file modified before future", ods.ModifiedBefore(common.FormatTime(future)), assert.True}, {"file modified before now", ods.ModifiedBefore(common.FormatTime(now)), assert.False}, {"file modified before epoch", ods.ModifiedBefore(common.FormatTime(now)), assert.False}, } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { scopes := setScopesToDefault(test.scope) for _, scope := range scopes { test.expect(t, scope.matchesInfo(itemInfo)) } }) } } func (suite *OneDriveSelectorSuite) TestCategory_PathType() { table := []struct { cat oneDriveCategory pathType path.CategoryType }{ {OneDriveCategoryUnknown, path.UnknownCategory}, {OneDriveUser, path.UnknownCategory}, {OneDriveItem, path.FilesCategory}, {OneDriveFolder, path.FilesCategory}, {FileFilterCreatedAfter, path.FilesCategory}, {FileFilterCreatedBefore, path.FilesCategory}, {FileFilterModifiedAfter, path.FilesCategory}, {FileFilterModifiedBefore, path.FilesCategory}, } for _, test := range table { suite.T().Run(test.cat.String(), func(t *testing.T) { assert.Equal(t, test.pathType, test.cat.PathType()) }) } }