GC: Backup: Events: Filter Calendars with Scope (#900)
## Description Feature branch enabling filtering based upon `selectors.ExchangeScope` <!-- Insert PR description--> ## Type of change <!--- Please check the type of change your PR introduces: ---> - [x] 🌻 Feature ## Issue(s) <!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. --> *closes #810<issue> ## Test Plan - [x] ⚡ Unit test
This commit is contained in:
parent
679b32697b
commit
06d2a389d9
@ -58,12 +58,7 @@ func (suite *ExchangeIteratorSuite) TestDescendable() {
|
||||
}
|
||||
|
||||
func loadService(t *testing.T) *exchangeService {
|
||||
_, err := tester.GetRequiredEnvVars(tester.M365AcctCredEnvs...)
|
||||
require.NoError(t, err)
|
||||
|
||||
a := tester.NewM365Account(t)
|
||||
require.NoError(t, err)
|
||||
|
||||
m365, err := a.M365Config()
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -145,7 +140,7 @@ func (suite *ExchangeIteratorSuite) TestIterativeFunctions() {
|
||||
}, {
|
||||
name: "Folder Iterative Check Mail",
|
||||
queryFunction: GetAllFolderNamesForUser,
|
||||
iterativeFunction: IterateFilterFolderDirectoriesForCollections,
|
||||
iterativeFunction: IterateFilterContainersForCollections,
|
||||
scope: mailScope,
|
||||
transformer: models.CreateMailFolderCollectionResponseFromDiscriminatorValue,
|
||||
folderNames: map[string]struct{}{
|
||||
@ -156,7 +151,7 @@ func (suite *ExchangeIteratorSuite) TestIterativeFunctions() {
|
||||
}, {
|
||||
name: "Folder Iterative Check Contacts",
|
||||
queryFunction: GetAllContactFolderNamesForUser,
|
||||
iterativeFunction: IterateFilterFolderDirectoriesForCollections,
|
||||
iterativeFunction: IterateFilterContainersForCollections,
|
||||
scope: contactScope,
|
||||
transformer: models.CreateContactFolderCollectionResponseFromDiscriminatorValue,
|
||||
},
|
||||
|
||||
@ -5,9 +5,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
)
|
||||
|
||||
type ServiceFunctionsIntegrationSuite struct {
|
||||
@ -77,6 +80,7 @@ func (suite *ServiceFunctionsIntegrationSuite) TestGetAllCalendars() {
|
||||
|
||||
func (suite *ServiceFunctionsIntegrationSuite) TestGetAllContactFolders() {
|
||||
gs := loadService(suite.T())
|
||||
user := tester.M365UserID(suite.T())
|
||||
ctx := context.Background()
|
||||
|
||||
table := []struct {
|
||||
@ -86,14 +90,14 @@ func (suite *ServiceFunctionsIntegrationSuite) TestGetAllContactFolders() {
|
||||
}{
|
||||
{
|
||||
name: "plain lookup",
|
||||
user: suite.m365UserID,
|
||||
user: user,
|
||||
expectCount: assert.Greater,
|
||||
expectErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "root folder",
|
||||
contains: "Contact",
|
||||
user: suite.m365UserID,
|
||||
user: user,
|
||||
expectCount: assert.Greater,
|
||||
expectErr: assert.NoError,
|
||||
},
|
||||
@ -106,7 +110,7 @@ func (suite *ServiceFunctionsIntegrationSuite) TestGetAllContactFolders() {
|
||||
{
|
||||
name: "nonsense matcher",
|
||||
contains: "∂ç∂ç∂√≈∂ƒß∂ç√ßç√≈ç√ß∂ƒçß√ß≈∂ƒßç√",
|
||||
user: suite.m365UserID,
|
||||
user: user,
|
||||
expectCount: assert.Equal,
|
||||
expectErr: assert.NoError,
|
||||
},
|
||||
@ -164,3 +168,83 @@ func (suite *ServiceFunctionsIntegrationSuite) TestGetAllMailFolders() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ServiceFunctionsIntegrationSuite) TestCollectContainers() {
|
||||
ctx := context.Background()
|
||||
failFast := false
|
||||
containerCount := 1
|
||||
t := suite.T()
|
||||
user := tester.M365UserID(t)
|
||||
a := tester.NewM365Account(t)
|
||||
credentials, err := a.M365Config()
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
name, contains string
|
||||
getScope func() selectors.ExchangeScope
|
||||
expectedCount assert.ComparisonAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "All Events",
|
||||
contains: "Birthdays",
|
||||
expectedCount: assert.Greater,
|
||||
getScope: func() selectors.ExchangeScope {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.EventCalendars([]string{user}, selectors.Any()))
|
||||
|
||||
scopes := sel.Scopes()
|
||||
assert.Equal(t, len(scopes), 1)
|
||||
|
||||
return scopes[0]
|
||||
},
|
||||
}, {
|
||||
name: "Default Calendar",
|
||||
contains: DefaultCalendar,
|
||||
expectedCount: assert.Equal,
|
||||
getScope: func() selectors.ExchangeScope {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.EventCalendars([]string{user}, []string{DefaultCalendar}))
|
||||
|
||||
scopes := sel.Scopes()
|
||||
assert.Equal(t, len(scopes), 1)
|
||||
|
||||
return scopes[0]
|
||||
},
|
||||
}, {
|
||||
name: "Default Mail",
|
||||
contains: DefaultMailFolder,
|
||||
expectedCount: assert.Equal,
|
||||
getScope: func() selectors.ExchangeScope {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.MailFolders([]string{user}, []string{DefaultMailFolder}))
|
||||
|
||||
scopes := sel.Scopes()
|
||||
assert.Equal(t, len(scopes), 1)
|
||||
|
||||
return scopes[0]
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
qp := graph.QueryParams{
|
||||
User: user,
|
||||
Scope: test.getScope(),
|
||||
FailFast: failFast,
|
||||
Credentials: credentials,
|
||||
}
|
||||
collections := make(map[string]*Collection)
|
||||
err := CollectFolders(ctx, qp, collections, nil)
|
||||
assert.NoError(t, err)
|
||||
test.expectedCount(t, len(collections), containerCount)
|
||||
|
||||
keys := make([]string, 0, len(collections))
|
||||
for k := range collections {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
t.Logf("Collections Made: %v\n", keys)
|
||||
assert.Contains(t, keys, test.contains)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package exchange
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
@ -117,6 +118,9 @@ func IterateSelectAllDescendablesForCollections(
|
||||
// utility function for iterating through events
|
||||
// and storing events in collections based on
|
||||
// the calendarID which originates from M365.
|
||||
// @param pageItem is a CalendarCollectionResponse possessing two populated fields:
|
||||
// - id - M365 ID
|
||||
// - Name - Calendar Name
|
||||
func IterateSelectAllEventsFromCalendars(
|
||||
ctx context.Context,
|
||||
qp graph.QueryParams,
|
||||
@ -124,83 +128,62 @@ func IterateSelectAllEventsFromCalendars(
|
||||
collections map[string]*Collection,
|
||||
statusUpdater support.StatusUpdater,
|
||||
) func(any) bool {
|
||||
var (
|
||||
isEnabled bool
|
||||
service graph.Service
|
||||
)
|
||||
|
||||
return func(pageItem any) bool {
|
||||
if pageItem == nil {
|
||||
return true
|
||||
if !isEnabled {
|
||||
// Create Collections based on qp.Scope
|
||||
err := CollectFolders(ctx, qp, collections, statusUpdater)
|
||||
if err != nil {
|
||||
errUpdater(
|
||||
qp.User,
|
||||
errors.Wrap(err, support.ConnectorStackErrorTrace(err)),
|
||||
)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
service, err = createService(qp.Credentials, qp.FailFast)
|
||||
if err != nil {
|
||||
errUpdater(qp.User, err)
|
||||
return false
|
||||
}
|
||||
|
||||
isEnabled = true
|
||||
}
|
||||
|
||||
shell, ok := pageItem.(models.Calendarable)
|
||||
pageItem = CreateCalendarDisplayable(pageItem)
|
||||
|
||||
calendar, ok := pageItem.(displayable)
|
||||
if !ok {
|
||||
errUpdater(qp.User, errors.New("casting pageItem to models.Calendarable"))
|
||||
errUpdater(
|
||||
qp.User,
|
||||
fmt.Errorf("unable to parse pageItem into CalendarDisplayable: %T", pageItem),
|
||||
)
|
||||
}
|
||||
|
||||
if calendar.GetDisplayName() == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
service, err := createService(qp.Credentials, qp.FailFast)
|
||||
collection, ok := collections[*calendar.GetDisplayName()]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
eventIDs, err := ReturnEventIDsFromCalendar(ctx, service, qp.User, *calendar.GetId())
|
||||
if err != nil {
|
||||
errUpdater(
|
||||
qp.User,
|
||||
errors.Wrap(err, "creating service for IterateSelectAllEventsFromCalendars"))
|
||||
errors.Wrap(err, support.ConnectorStackErrorTrace(err)))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
eventResponseable, err := service.Client().
|
||||
UsersById(qp.User).
|
||||
CalendarsById(*shell.GetId()).
|
||||
Events().Get(ctx, nil)
|
||||
if err != nil {
|
||||
errUpdater(qp.User, err)
|
||||
}
|
||||
|
||||
directory := shell.GetName()
|
||||
owner := shell.GetOwner()
|
||||
|
||||
// Conditional Guard Checks
|
||||
if eventResponseable == nil ||
|
||||
directory == nil ||
|
||||
owner == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
eventables := eventResponseable.GetValue()
|
||||
// Clause is true when Calendar has does not have any events
|
||||
if eventables == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if _, ok := collections[*directory]; !ok {
|
||||
service, err := createService(qp.Credentials, qp.FailFast)
|
||||
if err != nil {
|
||||
errUpdater(qp.User, err)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
dirPath, err := path.Builder{}.Append(*directory).ToDataLayerExchangePathForCategory(
|
||||
qp.Credentials.TenantID,
|
||||
qp.User,
|
||||
path.EventsCategory,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
// we should never hit this error
|
||||
errUpdater("converting to resource path", err)
|
||||
return true
|
||||
}
|
||||
|
||||
edc := NewCollection(
|
||||
qp.User,
|
||||
dirPath,
|
||||
events,
|
||||
service,
|
||||
statusUpdater,
|
||||
)
|
||||
collections[*directory] = &edc
|
||||
}
|
||||
|
||||
for _, event := range eventables {
|
||||
collections[*directory].AddJob(*event.GetId())
|
||||
}
|
||||
collection.jobs = append(collection.jobs, eventIDs...)
|
||||
|
||||
return true
|
||||
}
|
||||
@ -216,7 +199,11 @@ func IterateAndFilterDescendablesForCollections(
|
||||
collections map[string]*Collection,
|
||||
statusUpdater support.StatusUpdater,
|
||||
) func(any) bool {
|
||||
var isFilterSet bool
|
||||
var (
|
||||
isFilterSet bool
|
||||
resolver graph.ContainerResolver
|
||||
cache map[string]string
|
||||
)
|
||||
|
||||
return func(descendItem any) bool {
|
||||
if !isFilterSet {
|
||||
@ -230,6 +217,13 @@ func IterateAndFilterDescendablesForCollections(
|
||||
errUpdater(qp.User, err)
|
||||
return false
|
||||
}
|
||||
// Caches folder directories
|
||||
cache = make(map[string]string, 0)
|
||||
|
||||
resolver, err = maybeGetAndPopulateFolderResolver(ctx, qp, path.EmailCategory)
|
||||
if err != nil {
|
||||
errUpdater("getting folder resolver for category "+path.EmailCategory.String(), err)
|
||||
}
|
||||
|
||||
isFilterSet = true
|
||||
}
|
||||
@ -240,7 +234,20 @@ func IterateAndFilterDescendablesForCollections(
|
||||
return true
|
||||
}
|
||||
// Saving only messages for the created directories
|
||||
directory := *message.GetParentFolderId()
|
||||
folderID := *message.GetParentFolderId()
|
||||
|
||||
directory, ok := cache[folderID]
|
||||
if !ok {
|
||||
result := translateIDToDirectory(ctx, qp, resolver, folderID)
|
||||
if result == "" {
|
||||
errUpdater(qp.User,
|
||||
errors.New("getCollectionPath experienced error during translateID"))
|
||||
}
|
||||
|
||||
cache[folderID] = result
|
||||
directory = result
|
||||
}
|
||||
|
||||
if _, ok = collections[directory]; !ok {
|
||||
return true
|
||||
}
|
||||
@ -251,7 +258,65 @@ func IterateAndFilterDescendablesForCollections(
|
||||
}
|
||||
}
|
||||
|
||||
func IterateFilterFolderDirectoriesForCollections(
|
||||
func translateIDToDirectory(
|
||||
ctx context.Context,
|
||||
qp graph.QueryParams,
|
||||
resolver graph.ContainerResolver,
|
||||
directoryID string,
|
||||
) string {
|
||||
fullPath, err := getCollectionPath(ctx, qp, resolver, directoryID, path.EmailCategory)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fullPath.Folder()
|
||||
}
|
||||
|
||||
func getCategoryAndValidation(es selectors.ExchangeScope) (
|
||||
optionIdentifier,
|
||||
path.CategoryType,
|
||||
func(namePtr *string) bool,
|
||||
) {
|
||||
var (
|
||||
option = scopeToOptionIdentifier(es)
|
||||
category path.CategoryType
|
||||
validate func(namePtr *string) bool
|
||||
)
|
||||
|
||||
switch option {
|
||||
case messages:
|
||||
category = path.EmailCategory
|
||||
validate = func(namePtr *string) bool {
|
||||
if namePtr == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return !es.Matches(selectors.ExchangeMailFolder, *namePtr)
|
||||
}
|
||||
case contacts:
|
||||
category = path.ContactsCategory
|
||||
validate = func(namePtr *string) bool {
|
||||
if namePtr == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return !es.Matches(selectors.ExchangeContactFolder, *namePtr)
|
||||
}
|
||||
case events:
|
||||
category = path.EventsCategory
|
||||
validate = func(namePtr *string) bool {
|
||||
if namePtr == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return !es.Matches(selectors.ExchangeEventCalendar, *namePtr)
|
||||
}
|
||||
}
|
||||
|
||||
return option, category, validate
|
||||
}
|
||||
|
||||
func IterateFilterContainersForCollections(
|
||||
ctx context.Context,
|
||||
qp graph.QueryParams,
|
||||
errUpdater func(string, error),
|
||||
@ -265,30 +330,12 @@ func IterateFilterFolderDirectoriesForCollections(
|
||||
err error
|
||||
option optionIdentifier
|
||||
category path.CategoryType
|
||||
validate func(string) bool
|
||||
validate func(*string) bool
|
||||
)
|
||||
|
||||
return func(folderItem any) bool {
|
||||
folder, ok := folderItem.(displayable)
|
||||
if !ok {
|
||||
errUpdater(qp.User, errors.New("casting folderItem to displayable"))
|
||||
return true
|
||||
}
|
||||
|
||||
if !isSet {
|
||||
option = scopeToOptionIdentifier(qp.Scope)
|
||||
switch option {
|
||||
case messages:
|
||||
category = path.EmailCategory
|
||||
validate = func(name string) bool {
|
||||
return !qp.Scope.Matches(selectors.ExchangeMailFolder, name)
|
||||
}
|
||||
case contacts:
|
||||
category = path.ContactsCategory
|
||||
validate = func(name string) bool {
|
||||
return !qp.Scope.Matches(selectors.ExchangeContactFolder, name)
|
||||
}
|
||||
}
|
||||
option, category, validate = getCategoryAndValidation(qp.Scope)
|
||||
|
||||
resolver, err = maybeGetAndPopulateFolderResolver(ctx, qp, category)
|
||||
if err != nil {
|
||||
@ -298,19 +345,27 @@ func IterateFilterFolderDirectoriesForCollections(
|
||||
isSet = true
|
||||
}
|
||||
|
||||
// Continue to iterate if folder name is empty
|
||||
if folder.GetDisplayName() == nil {
|
||||
if option == events {
|
||||
folderItem = CreateCalendarDisplayable(folderItem)
|
||||
}
|
||||
|
||||
folder, ok := folderItem.(displayable)
|
||||
if !ok {
|
||||
errUpdater(qp.User,
|
||||
fmt.Errorf("unable to convert input of %T for category: %s", folderItem, category.String()),
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if validate(*folder.GetDisplayName()) {
|
||||
if validate(folder.GetDisplayName()) {
|
||||
return true
|
||||
}
|
||||
|
||||
if option == contacts {
|
||||
collectPath = *folder.GetDisplayName()
|
||||
} else {
|
||||
if option == messages {
|
||||
collectPath = *folder.GetId()
|
||||
} else {
|
||||
collectPath = *folder.GetDisplayName()
|
||||
}
|
||||
|
||||
dirPath, err := getCollectionPath(
|
||||
@ -345,7 +400,7 @@ func IterateFilterFolderDirectoriesForCollections(
|
||||
service,
|
||||
statusUpdater,
|
||||
)
|
||||
collections[*folder.GetId()] = &temp
|
||||
collections[*folder.GetDisplayName()] = &temp
|
||||
|
||||
return true
|
||||
}
|
||||
@ -565,3 +620,53 @@ func ReturnContactIDsFromDirectory(ctx context.Context, gs graph.Service, user,
|
||||
|
||||
return stringArray, nil
|
||||
}
|
||||
|
||||
// ReturnEventIDsFromCalendar returns a list of all M365IDs of events of the targeted Calendar.
|
||||
func ReturnEventIDsFromCalendar(
|
||||
ctx context.Context,
|
||||
gs graph.Service,
|
||||
user, calendarID string,
|
||||
) ([]string, error) {
|
||||
ids := []string{}
|
||||
|
||||
response, err := gs.Client().
|
||||
UsersById(user).
|
||||
CalendarsById(calendarID).
|
||||
Events().Get(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageIterator, err := msgraphgocore.NewPageIterator(
|
||||
response,
|
||||
gs.Adapter(),
|
||||
models.CreateEventCollectionResponseFromDiscriminatorValue,
|
||||
)
|
||||
|
||||
callbackFunc := func(pageItem any) bool {
|
||||
entry, ok := pageItem.(models.Eventable)
|
||||
if !ok {
|
||||
err = errors.New("casting pageItem to models.Eventable")
|
||||
return false
|
||||
}
|
||||
|
||||
ids = append(ids, *entry.GetId())
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if iterateErr := pageIterator.Iterate(ctx, callbackFunc); iterateErr != nil {
|
||||
return nil,
|
||||
errors.Wrap(iterateErr, support.ConnectorStackErrorTrace(err))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
@ -122,6 +122,8 @@ func RetrieveMessageDataForUser(ctx context.Context, gs graph.Service, user, m36
|
||||
return gs.Client().UsersById(user).MessagesById(m365ID).Get(ctx, nil)
|
||||
}
|
||||
|
||||
// CollectFolders is a utility function for creating Collections based off parameters found
|
||||
// in the ExchangeScope found in the graph.QueryParams
|
||||
func CollectFolders(
|
||||
ctx context.Context,
|
||||
qp graph.QueryParams,
|
||||
@ -149,6 +151,9 @@ func CollectFolders(
|
||||
case contacts:
|
||||
query = GetAllContactFolderNamesForUser
|
||||
transformer = models.CreateContactFolderCollectionResponseFromDiscriminatorValue
|
||||
case events:
|
||||
query = GetAllCalendarNamesForUser
|
||||
transformer = models.CreateCalendarCollectionResponseFromDiscriminatorValue
|
||||
default:
|
||||
return fmt.Errorf("unsupported option %s used in CollectFolders", option)
|
||||
}
|
||||
@ -176,7 +181,7 @@ func CollectFolders(
|
||||
err = support.WrapAndAppend(id, e, err)
|
||||
}
|
||||
|
||||
callbackFunc := IterateFilterFolderDirectoriesForCollections(
|
||||
callbackFunc := IterateFilterContainersForCollections(
|
||||
ctx,
|
||||
qp,
|
||||
errUpdater,
|
||||
|
||||
@ -3,7 +3,6 @@ package connector
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -14,7 +13,6 @@ import (
|
||||
"github.com/alcionai/corso/src/internal/common"
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange"
|
||||
"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/selectors"
|
||||
)
|
||||
@ -85,36 +83,54 @@ func (suite *GraphConnectorIntegrationSuite) TestSetTenantUsers() {
|
||||
// - events
|
||||
func (suite *GraphConnectorIntegrationSuite) TestExchangeDataCollection() {
|
||||
ctx := context.Background()
|
||||
t := suite.T()
|
||||
connector := loadConnector(ctx, t)
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.Users([]string{suite.user}))
|
||||
collectionList, err := connector.ExchangeDataCollection(context.Background(), sel.Selector)
|
||||
assert.NotNil(t, collectionList, "collection list")
|
||||
assert.NoError(t, err)
|
||||
assert.Zero(t, connector.status.ObjectCount)
|
||||
assert.Zero(t, connector.status.FolderCount)
|
||||
assert.Zero(t, connector.status.Successful)
|
||||
connector := loadConnector(ctx, suite.T())
|
||||
tests := []struct {
|
||||
name string
|
||||
getSelector func(t *testing.T) selectors.Selector
|
||||
}{
|
||||
{
|
||||
name: suite.user + " Email",
|
||||
getSelector: func(t *testing.T) selectors.Selector {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.MailFolders([]string{suite.user}, []string{exchange.DefaultMailFolder}))
|
||||
|
||||
streams := make(map[string]<-chan data.Stream)
|
||||
// Verify Items() call returns an iterable channel(e.g. a channel that has been closed)
|
||||
for _, collection := range collectionList {
|
||||
temp := collection.Items()
|
||||
testName := collection.FullPath().ResourceOwner()
|
||||
streams[testName] = temp
|
||||
return sel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: suite.user + " Contacts",
|
||||
getSelector: func(t *testing.T) selectors.Selector {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.ContactFolders([]string{suite.user}, []string{exchange.DefaultContactFolder}))
|
||||
|
||||
return sel.Selector
|
||||
},
|
||||
},
|
||||
{
|
||||
name: suite.user + " Events",
|
||||
getSelector: func(t *testing.T) selectors.Selector {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.EventCalendars([]string{suite.user}, []string{exchange.DefaultCalendar}))
|
||||
|
||||
return sel.Selector
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
status := connector.AwaitStatus()
|
||||
assert.NotZero(t, status.Successful)
|
||||
|
||||
for name, channel := range streams {
|
||||
suite.T().Run(name, func(t *testing.T) {
|
||||
t.Logf("Test: %s\t Items: %d", name, len(channel))
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
collection, err := connector.ExchangeDataCollection(ctx, test.getSelector(t))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(collection), 1)
|
||||
channel := collection[0].Items()
|
||||
for object := range channel {
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := buf.ReadFrom(object.ToReader())
|
||||
assert.NoError(t, err, "received a buf.Read error")
|
||||
}
|
||||
status := connector.AwaitStatus()
|
||||
assert.NotZero(t, status.Successful)
|
||||
t.Log(status.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -127,7 +143,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMailSerializationRegression() {
|
||||
t := suite.T()
|
||||
connector := loadConnector(ctx, t)
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.MailFolders([]string{suite.user}, []string{"Inbox"}))
|
||||
sel.Include(sel.MailFolders([]string{suite.user}, []string{exchange.DefaultMailFolder}))
|
||||
eb, err := sel.ToExchangeBackup()
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -162,27 +178,40 @@ func (suite *GraphConnectorIntegrationSuite) TestMailSerializationRegression() {
|
||||
// and to store contact within Collection. Downloaded contacts are run through
|
||||
// a regression test to ensure that downloaded items can be uploaded.
|
||||
func (suite *GraphConnectorIntegrationSuite) TestContactSerializationRegression() {
|
||||
ctx := context.Background()
|
||||
t := suite.T()
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.ContactFolders([]string{suite.user}, selectors.Any()))
|
||||
eb, err := sel.ToExchangeBackup()
|
||||
require.NoError(t, err)
|
||||
connector := loadConnector(context.Background(), suite.T())
|
||||
|
||||
scopes := eb.Scopes()
|
||||
connector := loadConnector(ctx, t)
|
||||
tests := []struct {
|
||||
name string
|
||||
getCollection func(t *testing.T) []*exchange.Collection
|
||||
}{
|
||||
{
|
||||
name: "Default Contact Folder",
|
||||
getCollection: func(t *testing.T) []*exchange.Collection {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.ContactFolders([]string{suite.user}, []string{exchange.DefaultContactFolder}))
|
||||
eb, err := sel.ToExchangeBackup()
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.Len(scopes, 1)
|
||||
contactsOnly := scopes[0]
|
||||
collections, err := connector.createCollections(context.Background(), contactsOnly)
|
||||
assert.NoError(t, err)
|
||||
scopes := eb.Scopes()
|
||||
|
||||
number := 0
|
||||
suite.Len(scopes, 1)
|
||||
contactsOnly := scopes[0]
|
||||
collections, err := connector.createCollections(context.Background(), contactsOnly)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, edc := range collections {
|
||||
testName := fmt.Sprintf("%s_ContactFolder_%d", edc.FullPath().ResourceOwner(), number)
|
||||
suite.T().Run(testName, func(t *testing.T) {
|
||||
return collections
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
edcs := test.getCollection(t)
|
||||
assert.Equal(t, len(edcs), 1)
|
||||
edc := edcs[0]
|
||||
assert.Equal(t, edc.FullPath().Folder(), exchange.DefaultContactFolder)
|
||||
streamChannel := edc.Items()
|
||||
count := 0
|
||||
for stream := range streamChannel {
|
||||
buf := &bytes.Buffer{}
|
||||
read, err := buf.ReadFrom(stream.ToReader())
|
||||
@ -190,52 +219,80 @@ func (suite *GraphConnectorIntegrationSuite) TestContactSerializationRegression(
|
||||
assert.NotZero(t, read)
|
||||
contact, err := support.CreateContactFromBytes(buf.Bytes())
|
||||
assert.NotNil(t, contact)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, err, "error on converting contact bytes: "+string(buf.Bytes()))
|
||||
count++
|
||||
}
|
||||
number++
|
||||
assert.NotZero(t, count)
|
||||
|
||||
status := connector.AwaitStatus()
|
||||
suite.NotNil(status)
|
||||
suite.Equal(status.ObjectCount, status.Successful)
|
||||
})
|
||||
}
|
||||
|
||||
status := connector.AwaitStatus()
|
||||
suite.NotNil(status)
|
||||
suite.Equal(status.ObjectCount, status.Successful)
|
||||
}
|
||||
|
||||
// TestEventsSerializationRegression ensures functionality of createCollections
|
||||
// to be able to successfully query, download and restore event objects
|
||||
func (suite *GraphConnectorIntegrationSuite) TestEventsSerializationRegression() {
|
||||
ctx := context.Background()
|
||||
t := suite.T()
|
||||
connector := loadConnector(ctx, t)
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.EventCalendars([]string{suite.user}, selectors.Any()))
|
||||
scopes := sel.Scopes()
|
||||
suite.Equal(len(scopes), 1)
|
||||
collections, err := connector.createCollections(context.Background(), scopes[0])
|
||||
require.NoError(t, err)
|
||||
connector := loadConnector(context.Background(), suite.T())
|
||||
|
||||
for _, edc := range collections {
|
||||
streamChannel := edc.Items()
|
||||
number := 0
|
||||
tests := []struct {
|
||||
name, expected string
|
||||
getCollection func(t *testing.T) []*exchange.Collection
|
||||
}{
|
||||
{
|
||||
name: "Default Event Calendar",
|
||||
expected: exchange.DefaultCalendar,
|
||||
getCollection: func(t *testing.T) []*exchange.Collection {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.EventCalendars([]string{suite.user}, []string{exchange.DefaultCalendar}))
|
||||
scopes := sel.Scopes()
|
||||
suite.Equal(len(scopes), 1)
|
||||
collections, err := connector.createCollections(context.Background(), scopes[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
for stream := range streamChannel {
|
||||
testName := fmt.Sprintf("%s_Event_%d", edc.FullPath().ResourceOwner(), number)
|
||||
suite.T().Run(testName, func(t *testing.T) {
|
||||
return collections
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Birthday Calendar",
|
||||
expected: "Birthdays",
|
||||
getCollection: func(t *testing.T) []*exchange.Collection {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.EventCalendars([]string{suite.user}, []string{"Birthdays"}))
|
||||
scopes := sel.Scopes()
|
||||
suite.Equal(len(scopes), 1)
|
||||
collections, err := connector.createCollections(context.Background(), scopes[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
return collections
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
collections := test.getCollection(t)
|
||||
require.Equal(t, len(collections), 1)
|
||||
edc := collections[0]
|
||||
assert.Equal(t, edc.FullPath().Folder(), test.expected)
|
||||
streamChannel := edc.Items()
|
||||
|
||||
for stream := range streamChannel {
|
||||
buf := &bytes.Buffer{}
|
||||
read, err := buf.ReadFrom(stream.ToReader())
|
||||
assert.NoError(t, err)
|
||||
assert.NotZero(t, read)
|
||||
event, err := support.CreateEventFromBytes(buf.Bytes())
|
||||
assert.NotNil(t, event)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
assert.NoError(t, err, "experienced error parsing event bytes: "+string(buf.Bytes()))
|
||||
}
|
||||
|
||||
status := connector.AwaitStatus()
|
||||
suite.NotNil(status)
|
||||
suite.Equal(status.ObjectCount, status.Successful)
|
||||
status := connector.AwaitStatus()
|
||||
suite.NotNil(status)
|
||||
suite.Equal(status.ObjectCount, status.Successful)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestAccessOfInboxAllUsers verifies that GraphConnector can
|
||||
@ -249,7 +306,7 @@ func (suite *GraphConnectorIntegrationSuite) TestAccessOfInboxAllUsers() {
|
||||
t := suite.T()
|
||||
connector := loadConnector(ctx, t)
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.MailFolders(selectors.Any(), []string{"Inbox"}))
|
||||
sel.Include(sel.MailFolders(selectors.Any(), []string{exchange.DefaultMailFolder}))
|
||||
scopes := sel.DiscreteScopes(connector.GetUsers())
|
||||
|
||||
for _, scope := range scopes {
|
||||
|
||||
@ -102,7 +102,6 @@ func (suite *ItemIntegrationSuite) TestItemReader() {
|
||||
)
|
||||
|
||||
// Read data for the file
|
||||
|
||||
name, itemData, err := driveItemReader(ctx, suite, driveID, driveItemID)
|
||||
require.NoError(suite.T(), err)
|
||||
require.NotEmpty(suite.T(), name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user