Add OneDrive path base structs (#833)

* Constants for OneDrive stuff

* Tests and constructor for OneDrive paths

* Populate onedrive path struct in data collection (#835)

* Helper function to make path structs for onedrive

* Use path struct in onedrive data collection

Does not change the external API at all, just the internals of how
FullPath functions and what is stored for the path.

* Wire up making data collections with path struct

Requires addition of tenant as input to Collections().

* Fixup onedrive Collections tests

* Wire up call to onedrive.NewCollections()

Just requires adding the tenant ID to the call.
This commit is contained in:
ashmrtn 2022-09-13 14:48:03 -07:00 committed by GitHub
parent 1d39d911ca
commit 0e6ae32fc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 228 additions and 64 deletions

View File

@ -463,7 +463,12 @@ func (gc *GraphConnector) OneDriveDataCollections(
for _, user := range scope.Get(selectors.OneDriveUser) { for _, user := range scope.Get(selectors.OneDriveUser) {
logger.Ctx(ctx).With("user", user).Debug("Creating OneDrive collections") logger.Ctx(ctx).With("user", user).Debug("Creating OneDrive collections")
odcs, err := onedrive.NewCollections(user, &gc.graphService, gc.UpdateStatus).Get(ctx) odcs, err := onedrive.NewCollections(
gc.credentials.TenantID,
user,
&gc.graphService,
gc.UpdateStatus,
).Get(ctx)
if err != nil { if err != nil {
return nil, support.WrapAndAppend(user, err, errs) return nil, support.WrapAndAppend(user, err, errs)
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/connector/support"
"github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/path"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/logger" "github.com/alcionai/corso/src/pkg/logger"
) )
@ -30,7 +31,7 @@ type Collection struct {
data chan data.Stream data chan data.Stream
// folderPath indicates what level in the hierarchy this collection // folderPath indicates what level in the hierarchy this collection
// represents // represents
folderPath string folderPath path.Path
// M365 IDs of file items within this collection // M365 IDs of file items within this collection
driveItemIDs []string driveItemIDs []string
// M365 ID of the drive this collection was created from // M365 ID of the drive this collection was created from
@ -48,7 +49,10 @@ type itemReaderFunc func(
) (name string, itemData io.ReadCloser, err error) ) (name string, itemData io.ReadCloser, err error)
// NewCollection creates a Collection // NewCollection creates a Collection
func NewCollection(folderPath, driveID string, service graph.Service, func NewCollection(
folderPath path.Path,
driveID string,
service graph.Service,
statusUpdater support.StatusUpdater, statusUpdater support.StatusUpdater,
) *Collection { ) *Collection {
c := &Collection{ c := &Collection{
@ -77,10 +81,9 @@ func (oc *Collection) Items() <-chan data.Stream {
} }
func (oc *Collection) FullPath() []string { func (oc *Collection) FullPath() []string {
path := oc.folderPath // TODO(ashmrtn): Update this when data.Collection.FullPath has support for
// Remove leading `/` if any so that Split // path.Path.
// doesn't return a "" return strings.Split(oc.folderPath.String(), "/")
return strings.Split(strings.TrimPrefix(path, "/"), "/")
} }
// Item represents a single item retrieved from OneDrive // Item represents a single item retrieved from OneDrive
@ -125,7 +128,7 @@ func (oc *Collection) populateItems(ctx context.Context) {
info: &details.OneDriveInfo{ info: &details.OneDriveInfo{
ItemType: details.OneDriveItem, ItemType: details.OneDriveItem,
ItemName: itemName, ItemName: itemName,
ParentPath: oc.folderPath, ParentPath: oc.folderPath.String(),
}, },
} }
} }

View File

@ -5,6 +5,7 @@ import (
"context" "context"
"errors" "errors"
"io" "io"
"strings"
"sync" "sync"
"testing" "testing"
@ -54,12 +55,20 @@ func (suite *OneDriveCollectionSuite) testStatusUpdater(
} }
func (suite *OneDriveCollectionSuite) TestOneDriveCollection() { func (suite *OneDriveCollectionSuite) TestOneDriveCollection() {
t := suite.T()
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
collStatus := support.ConnectorOperationStatus{} collStatus := support.ConnectorOperationStatus{}
folderPath := "dir1/dir2/dir3"
folderPath, err := getCanonicalPath("dir1/dir2/dir3", "a-tenant", "a-user")
require.NoError(t, err)
coll := NewCollection(folderPath, "fakeDriveID", suite, suite.testStatusUpdater(&wg, &collStatus)) coll := NewCollection(folderPath, "fakeDriveID", suite, suite.testStatusUpdater(&wg, &collStatus))
require.NotNil(suite.T(), coll) require.NotNil(t, coll)
assert.Equal(suite.T(), []string{"dir1", "dir2", "dir3"}, coll.FullPath()) assert.Equal(
t,
strings.Split(folderPath.String(), "/"),
coll.FullPath(),
)
testItemID := "fakeItemID" testItemID := "fakeItemID"
testItemName := "itemName" testItemName := "itemName"
@ -80,31 +89,35 @@ func (suite *OneDriveCollectionSuite) TestOneDriveCollection() {
} }
wg.Wait() wg.Wait()
// Expect only 1 item // Expect only 1 item
require.Len(suite.T(), readItems, 1) require.Len(t, readItems, 1)
require.Equal(suite.T(), 1, collStatus.ObjectCount) require.Equal(t, 1, collStatus.ObjectCount)
require.Equal(suite.T(), 1, collStatus.Successful) require.Equal(t, 1, collStatus.Successful)
// Validate item info and data // Validate item info and data
readItem := readItems[0] readItem := readItems[0]
readItemInfo := readItem.(data.StreamInfo) readItemInfo := readItem.(data.StreamInfo)
assert.Equal(suite.T(), testItemID, readItem.UUID()) assert.Equal(t, testItemID, readItem.UUID())
readData, err := io.ReadAll(readItem.ToReader()) readData, err := io.ReadAll(readItem.ToReader())
require.NoError(suite.T(), err) require.NoError(t, err)
assert.Equal(suite.T(), testItemData, readData) assert.Equal(t, testItemData, readData)
require.NotNil(suite.T(), readItemInfo.Info()) require.NotNil(t, readItemInfo.Info())
require.NotNil(suite.T(), readItemInfo.Info().OneDrive) require.NotNil(t, readItemInfo.Info().OneDrive)
assert.Equal(suite.T(), testItemName, readItemInfo.Info().OneDrive.ItemName) assert.Equal(t, testItemName, readItemInfo.Info().OneDrive.ItemName)
assert.Equal(suite.T(), folderPath, readItemInfo.Info().OneDrive.ParentPath) assert.Equal(t, folderPath.String(), readItemInfo.Info().OneDrive.ParentPath)
} }
func (suite *OneDriveCollectionSuite) TestOneDriveCollectionReadError() { func (suite *OneDriveCollectionSuite) TestOneDriveCollectionReadError() {
t := suite.T()
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
collStatus := support.ConnectorOperationStatus{} collStatus := support.ConnectorOperationStatus{}
wg.Add(1) wg.Add(1)
coll := NewCollection("folderPath", "fakeDriveID", suite, suite.testStatusUpdater(&wg, &collStatus)) folderPath, err := getCanonicalPath("folderPath", "a-tenant", "a-user")
require.NoError(t, err)
coll := NewCollection(folderPath, "fakeDriveID", suite, suite.testStatusUpdater(&wg, &collStatus))
coll.Add("testItemID") coll.Add("testItemID")
readError := errors.New("Test error") readError := errors.New("Test error")
@ -116,6 +129,6 @@ func (suite *OneDriveCollectionSuite) TestOneDriveCollectionReadError() {
coll.Items() coll.Items()
wg.Wait() wg.Wait()
// Expect no items // Expect no items
require.Equal(suite.T(), 1, collStatus.ObjectCount) require.Equal(t, 1, collStatus.ObjectCount)
require.Equal(suite.T(), 0, collStatus.Successful) require.Equal(t, 0, collStatus.Successful)
} }

View File

@ -2,7 +2,8 @@ package onedrive
import ( import (
"context" "context"
"path" stdpath "path"
"strings"
"github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -10,11 +11,13 @@ import (
"github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/connector/support"
"github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/path"
) )
// Collections is used to retrieve OneDrive data for a // Collections is used to retrieve OneDrive data for a
// specified user // specified user
type Collections struct { type Collections struct {
tenant string
user string user string
// collectionMap allows lookup of the data.Collection // collectionMap allows lookup of the data.Collection
// for a OneDrive folder // for a OneDrive folder
@ -30,11 +33,13 @@ type Collections struct {
} }
func NewCollections( func NewCollections(
tenant string,
user string, user string,
service graph.Service, service graph.Service,
statusUpdater support.StatusUpdater, statusUpdater support.StatusUpdater,
) *Collections { ) *Collections {
return &Collections{ return &Collections{
tenant: tenant,
user: user, user: user,
collectionMap: map[string]data.Collection{}, collectionMap: map[string]data.Collection{},
service: service, service: service,
@ -66,6 +71,17 @@ func (c *Collections) Get(ctx context.Context) ([]data.Collection, error) {
return collections, nil return collections, nil
} }
func getCanonicalPath(p, tenant, user string) (path.Path, error) {
pathBuilder := path.Builder{}.Append(strings.Split(p, "/")...)
res, err := pathBuilder.ToDataLayerOneDrivePath(tenant, user, false)
if err != nil {
return nil, errors.Wrap(err, "converting to canonical path")
}
return res, nil
}
// updateCollections initializes and adds the provided OneDrive items to Collections // updateCollections initializes and adds the provided OneDrive items to Collections
// A new collection is created for every OneDrive folder (or package) // A new collection is created for every OneDrive folder (or package)
func (c *Collections) updateCollections(ctx context.Context, driveID string, items []models.DriveItemable) error { func (c *Collections) updateCollections(ctx context.Context, driveID string, items []models.DriveItemable) error {
@ -81,22 +97,52 @@ func (c *Collections) updateCollections(ctx context.Context, driveID string, ite
if item.GetParentReference() == nil || item.GetParentReference().GetPath() == nil { if item.GetParentReference() == nil || item.GetParentReference().GetPath() == nil {
return errors.Errorf("item does not have a parent reference. item name : %s", *item.GetName()) return errors.Errorf("item does not have a parent reference. item name : %s", *item.GetName())
} }
// Create a collection for the parent of this item // Create a collection for the parent of this item
collectionPath := *item.GetParentReference().GetPath() collectionPath, err := getCanonicalPath(
if _, found := c.collectionMap[collectionPath]; !found { *item.GetParentReference().GetPath(),
c.collectionMap[collectionPath] = NewCollection(collectionPath, driveID, c.service, c.statusUpdater) c.tenant,
c.user,
)
if err != nil {
return err
}
if _, found := c.collectionMap[collectionPath.String()]; !found {
c.collectionMap[collectionPath.String()] = NewCollection(
collectionPath,
driveID,
c.service,
c.statusUpdater,
)
} }
switch { switch {
case item.GetFolder() != nil, item.GetPackage() != nil: case item.GetFolder() != nil, item.GetPackage() != nil:
// For folders and packages we also create a collection to represent those // For folders and packages we also create a collection to represent those
// TODO: This is where we might create a "special file" to represent these in the backup repository // TODO: This is where we might create a "special file" to represent these in the backup repository
// e.g. a ".folderMetadataFile" // e.g. a ".folderMetadataFile"
itemPath := path.Join(*item.GetParentReference().GetPath(), *item.GetName()) itemPath, err := getCanonicalPath(
if _, found := c.collectionMap[itemPath]; !found { stdpath.Join(
c.collectionMap[itemPath] = NewCollection(itemPath, driveID, c.service, c.statusUpdater) *item.GetParentReference().GetPath(),
*item.GetName(),
),
c.tenant,
c.user,
)
if err != nil {
return err
}
if _, found := c.collectionMap[itemPath.String()]; !found {
c.collectionMap[itemPath.String()] = NewCollection(
itemPath,
driveID,
c.service,
c.statusUpdater,
)
} }
case item.GetFile() != nil: case item.GetFile() != nil:
collection := c.collectionMap[collectionPath].(*Collection) collection := c.collectionMap[collectionPath.String()].(*Collection)
collection.Add(*item.GetId()) collection.Add(*item.GetId())
default: default:
return errors.Errorf("item type not supported. item name : %s", *item.GetName()) return errors.Errorf("item type not supported. item name : %s", *item.GetName())

View File

@ -7,9 +7,23 @@ import (
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
"github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
) )
func expectedPathAsSlice(t *testing.T, tenant, user string, rest ...string) []string {
res := make([]string, 0, len(rest))
for _, r := range rest {
p, err := getCanonicalPath(r, tenant, user)
require.NoError(t, err)
res = append(res, p.String())
}
return res
}
type OneDriveCollectionsSuite struct { type OneDriveCollectionsSuite struct {
suite.Suite suite.Suite
} }
@ -19,6 +33,8 @@ func TestOneDriveCollectionsSuite(t *testing.T) {
} }
func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { func (suite *OneDriveCollectionsSuite) TestUpdateCollections() {
tenant := "tenant"
user := "user"
tests := []struct { tests := []struct {
testCase string testCase string
items []models.DriveItemable items []models.DriveItemable
@ -42,7 +58,12 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() {
driveItem("file", "/root", true, false, false), driveItem("file", "/root", true, false, false),
}, },
expect: assert.NoError, expect: assert.NoError,
expectedCollectionPaths: []string{"/root"}, expectedCollectionPaths: expectedPathAsSlice(
suite.T(),
tenant,
user,
"root",
),
expectedItemCount: 1, expectedItemCount: 1,
expectedFileCount: 1, expectedFileCount: 1,
}, },
@ -52,7 +73,13 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() {
driveItem("folder", "/root", false, true, false), driveItem("folder", "/root", false, true, false),
}, },
expect: assert.NoError, expect: assert.NoError,
expectedCollectionPaths: []string{"/root", "/root/folder"}, expectedCollectionPaths: expectedPathAsSlice(
suite.T(),
tenant,
user,
"/root",
"/root/folder",
),
expectedItemCount: 1, expectedItemCount: 1,
expectedFolderCount: 1, expectedFolderCount: 1,
}, },
@ -62,7 +89,13 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() {
driveItem("package", "/root", false, false, true), driveItem("package", "/root", false, false, true),
}, },
expect: assert.NoError, expect: assert.NoError,
expectedCollectionPaths: []string{"/root", "/root/package"}, expectedCollectionPaths: expectedPathAsSlice(
suite.T(),
tenant,
user,
"/root",
"/root/package",
),
expectedItemCount: 1, expectedItemCount: 1,
expectedPackageCount: 1, expectedPackageCount: 1,
}, },
@ -76,7 +109,14 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() {
driveItem("fileInPackage", "/root/package", true, false, false), driveItem("fileInPackage", "/root/package", true, false, false),
}, },
expect: assert.NoError, expect: assert.NoError,
expectedCollectionPaths: []string{"/root", "/root/folder", "/root/package"}, expectedCollectionPaths: expectedPathAsSlice(
suite.T(),
tenant,
user,
"/root",
"/root/folder",
"/root/package",
),
expectedItemCount: 5, expectedItemCount: 5,
expectedFileCount: 3, expectedFileCount: 3,
expectedFolderCount: 1, expectedFolderCount: 1,
@ -85,7 +125,7 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() {
} }
for _, tt := range tests { for _, tt := range tests {
suite.T().Run(tt.testCase, func(t *testing.T) { suite.T().Run(tt.testCase, func(t *testing.T) {
c := NewCollections("user", &MockGraphService{}, nil) c := NewCollections(tenant, user, &MockGraphService{}, nil)
err := c.updateCollections(context.Background(), "driveID", tt.items) err := c.updateCollections(context.Background(), "driveID", tt.items)
tt.expect(t, err) tt.expect(t, err)
assert.Equal(t, len(tt.expectedCollectionPaths), len(c.collectionMap)) assert.Equal(t, len(tt.expectedCollectionPaths), len(c.collectionMap))

View File

@ -12,11 +12,12 @@ func _() {
_ = x[EmailCategory-1] _ = x[EmailCategory-1]
_ = x[ContactsCategory-2] _ = x[ContactsCategory-2]
_ = x[EventsCategory-3] _ = x[EventsCategory-3]
_ = x[FilesCategory-4]
} }
const _CategoryType_name = "UnknownCategoryemailcontactsevents" const _CategoryType_name = "UnknownCategoryemailcontactseventsfiles"
var _CategoryType_index = [...]uint8{0, 15, 20, 28, 34} var _CategoryType_index = [...]uint8{0, 15, 20, 28, 34, 39}
func (i CategoryType) String() string { func (i CategoryType) String() string {
if i < 0 || i >= CategoryType(len(_CategoryType_index)-1) { if i < 0 || i >= CategoryType(len(_CategoryType_index)-1) {

View File

@ -241,6 +241,27 @@ func (pb Builder) ToDataLayerExchangePathForCategory(
}, nil }, nil
} }
func (pb Builder) ToDataLayerOneDrivePath(
tenant, user string,
isItem bool,
) (Path, error) {
if err := pb.verifyPrefix(tenant, user); err != nil {
return nil, err
}
return &dataLayerResourcePath{
Builder: *pb.withPrefix(
tenant,
OneDriveService.String(),
user,
FilesCategory.String(),
),
service: OneDriveService,
category: FilesCategory,
hasItem: isItem,
}, nil
}
// FromDataLayerPath parses the escaped path p, validates the elements in p // FromDataLayerPath parses the escaped path p, validates the elements in p
// match a resource-specific path format, and returns a Path struct for that // match a resource-specific path format, and returns a Path struct for that
// resource-specific type. If p does not match any resource-specific paths or // resource-specific type. If p does not match any resource-specific paths or

View File

@ -12,12 +12,15 @@ type ServiceType int
const ( const (
UnknownService ServiceType = iota UnknownService ServiceType = iota
ExchangeService // exchange ExchangeService // exchange
OneDriveService // onedrive
) )
func toServiceType(service string) ServiceType { func toServiceType(service string) ServiceType {
switch service { switch service {
case ExchangeService.String(): case ExchangeService.String():
return ExchangeService return ExchangeService
case OneDriveService.String():
return OneDriveService
default: default:
return UnknownService return UnknownService
} }
@ -33,6 +36,7 @@ const (
EmailCategory // email EmailCategory // email
ContactsCategory // contacts ContactsCategory // contacts
EventsCategory // events EventsCategory // events
FilesCategory // files
) )
func ToCategoryType(category string) CategoryType { func ToCategoryType(category string) CategoryType {
@ -43,6 +47,8 @@ func ToCategoryType(category string) CategoryType {
return ContactsCategory return ContactsCategory
case EventsCategory.String(): case EventsCategory.String():
return EventsCategory return EventsCategory
case FilesCategory.String():
return FilesCategory
default: default:
return UnknownCategory return UnknownCategory
} }
@ -55,6 +61,9 @@ var serviceCategories = map[ServiceType]map[CategoryType]struct{}{
ContactsCategory: {}, ContactsCategory: {},
EventsCategory: {}, EventsCategory: {},
}, },
OneDriveService: {
FilesCategory: {},
},
} }
func validateServiceAndCategoryStrings(s, c string) (ServiceType, CategoryType, error) { func validateServiceAndCategoryStrings(s, c string) (ServiceType, CategoryType, error) {

View File

@ -68,22 +68,39 @@ var (
}, },
} }
// Set of acceptable service/category mixtures for exchange. // Set of acceptable service/category mixtures.
exchangeServiceCategories = []struct { serviceCategories = []struct {
service path.ServiceType service path.ServiceType
category path.CategoryType category path.CategoryType
pathFunc func(pb *path.Builder, tenant, user string, isItem bool) (path.Path, error)
}{ }{
{ {
service: path.ExchangeService, service: path.ExchangeService,
category: path.EmailCategory, category: path.EmailCategory,
pathFunc: func(pb *path.Builder, tenant, user string, isItem bool) (path.Path, error) {
return pb.ToDataLayerExchangePathForCategory(tenant, user, path.EmailCategory, isItem)
},
}, },
{ {
service: path.ExchangeService, service: path.ExchangeService,
category: path.ContactsCategory, category: path.ContactsCategory,
pathFunc: func(pb *path.Builder, tenant, user string, isItem bool) (path.Path, error) {
return pb.ToDataLayerExchangePathForCategory(tenant, user, path.ContactsCategory, isItem)
},
}, },
{ {
service: path.ExchangeService, service: path.ExchangeService,
category: path.EventsCategory, category: path.EventsCategory,
pathFunc: func(pb *path.Builder, tenant, user string, isItem bool) (path.Path, error) {
return pb.ToDataLayerExchangePathForCategory(tenant, user, path.EventsCategory, isItem)
},
},
{
service: path.OneDriveService,
category: path.FilesCategory,
pathFunc: func(pb *path.Builder, tenant, user string, isItem bool) (path.Path, error) {
return pb.ToDataLayerOneDrivePath(tenant, user, isItem)
},
}, },
} }
) )
@ -97,7 +114,7 @@ func TestDataLayerResourcePath(t *testing.T) {
} }
func (suite *DataLayerResourcePath) TestMissingInfoErrors() { func (suite *DataLayerResourcePath) TestMissingInfoErrors() {
for _, types := range exchangeServiceCategories { for _, types := range serviceCategories {
suite.T().Run(types.service.String()+types.category.String(), func(t1 *testing.T) { suite.T().Run(types.service.String()+types.category.String(), func(t1 *testing.T) {
for _, m := range modes { for _, m := range modes {
t1.Run(m.name, func(t2 *testing.T) { t1.Run(m.name, func(t2 *testing.T) {
@ -105,10 +122,10 @@ func (suite *DataLayerResourcePath) TestMissingInfoErrors() {
t2.Run(test.name, func(t *testing.T) { t2.Run(test.name, func(t *testing.T) {
b := path.Builder{}.Append(test.rest...) b := path.Builder{}.Append(test.rest...)
_, err := b.ToDataLayerExchangePathForCategory( _, err := types.pathFunc(
b,
test.tenant, test.tenant,
test.user, test.user,
types.category,
m.isItem, m.isItem,
) )
assert.Error(t, err) assert.Error(t, err)
@ -124,12 +141,12 @@ func (suite *DataLayerResourcePath) TestMailItemNoFolder() {
item := "item" item := "item"
b := path.Builder{}.Append(item) b := path.Builder{}.Append(item)
for _, types := range exchangeServiceCategories { for _, types := range serviceCategories {
suite.T().Run(types.service.String()+types.category.String(), func(t *testing.T) { suite.T().Run(types.service.String()+types.category.String(), func(t *testing.T) {
p, err := b.ToDataLayerExchangePathForCategory( p, err := types.pathFunc(
b,
testTenant, testTenant,
testUser, testUser,
types.category,
true, true,
) )
require.NoError(t, err) require.NoError(t, err)

View File

@ -97,6 +97,14 @@ func (suite *ServiceCategoryUnitSuite) TestValidateServiceAndCategory() {
expectedCategory: EventsCategory, expectedCategory: EventsCategory,
check: assert.NoError, check: assert.NoError,
}, },
{
name: "OneDriveFiles",
service: OneDriveService.String(),
category: FilesCategory.String(),
expectedService: OneDriveService,
expectedCategory: FilesCategory,
check: assert.NoError,
},
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {

View File

@ -10,11 +10,12 @@ func _() {
var x [1]struct{} var x [1]struct{}
_ = x[UnknownService-0] _ = x[UnknownService-0]
_ = x[ExchangeService-1] _ = x[ExchangeService-1]
_ = x[OneDriveService-2]
} }
const _ServiceType_name = "UnknownServiceexchange" const _ServiceType_name = "UnknownServiceexchangeonedrive"
var _ServiceType_index = [...]uint8{0, 14, 22} var _ServiceType_index = [...]uint8{0, 14, 22, 30}
func (i ServiceType) String() string { func (i ServiceType) String() string {
if i < 0 || i >= ServiceType(len(_ServiceType_index)-1) { if i < 0 || i >= ServiceType(len(_ServiceType_index)-1) {