remove builder.toServicePath from paths (#5028)

path.Build produces the same result with more standard and centralized behavior.

---

#### Does this PR need a docs update or release note?

- [x]  No

#### Type of change

- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #4025

#### Test Plan

- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Keepers 2024-01-16 09:42:49 -07:00 committed by GitHub
parent ec35ea9b62
commit 6e50d5216e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 320 additions and 139 deletions

View File

@ -180,9 +180,13 @@ func (suite *CollectionUnitSuite) TestCollection() {
readItems = []data.Item{}
)
pb := path.Builder{}.Append(path.Split("drive/driveID1/root:/dir1/dir2/dir3")...)
folderPath, err := pb.ToDataLayerOneDrivePath("tenant", "owner", false)
folderPath, err := path.Build(
"tenant",
"owner",
path.OneDriveService,
path.FilesCategory,
false,
path.Split("drive/driveID1/root:/dir1/dir2/dir3")...)
require.NoError(t, err, clues.ToCore(err))
mbh := defaultOneDriveBH("a-user")
@ -314,8 +318,13 @@ func (suite *CollectionUnitSuite) TestCollectionReadError() {
wg.Add(1)
pb := path.Builder{}.Append(path.Split("drive/driveID1/root:/folderPath")...)
folderPath, err := pb.ToDataLayerOneDrivePath("a-tenant", "a-user", false)
folderPath, err := path.Build(
"a-tenant",
"a-user",
path.OneDriveService,
path.FilesCategory,
false,
path.Split("drive/driveID1/root:/folderPath")...)
require.NoError(t, err, clues.ToCore(err))
mbh := defaultOneDriveBH("a-user")
@ -393,8 +402,13 @@ func (suite *CollectionUnitSuite) TestCollectionReadUnauthorizedErrorRetry() {
true,
false)
pb := path.Builder{}.Append(path.Split("drive/driveID1/root:/folderPath")...)
folderPath, err := pb.ToDataLayerOneDrivePath("a-tenant", "a-user", false)
folderPath, err := path.Build(
"a-tenant",
"a-user",
path.OneDriveService,
path.FilesCategory,
false,
path.Split("drive/driveID1/root:/folderPath")...)
require.NoError(t, err)
mbh := defaultOneDriveBH("a-user")
@ -454,8 +468,13 @@ func (suite *CollectionUnitSuite) TestCollectionPermissionBackupLatestModTime()
wg.Add(1)
pb := path.Builder{}.Append(path.Split("drive/driveID1/root:/folderPath")...)
folderPath, err := pb.ToDataLayerOneDrivePath("a-tenant", "a-user", false)
folderPath, err := path.Build(
"a-tenant",
"a-user",
path.OneDriveService,
path.FilesCategory,
false,
path.Split("drive/driveID1/root:/folderPath")...)
require.NoError(t, err, clues.ToCore(err))
mbh := defaultOneDriveBH("a-user")
@ -844,10 +863,15 @@ func (suite *CollectionUnitSuite) TestItemExtensions() {
wg = sync.WaitGroup{}
now = time.Now()
readData = []byte("hello world!")
pb = path.Builder{}.Append(path.Split("drive/driveID1/root:/folderPath")...)
)
folderPath, err := pb.ToDataLayerOneDrivePath("a-tenant", "a-user", false)
folderPath, err := path.Build(
"a-tenant",
"a-user",
path.OneDriveService,
path.FilesCategory,
false,
path.Split("drive/driveID1/root:/folderPath")...)
require.NoError(t, err, clues.ToCore(err))
table := []struct {

View File

@ -18,6 +18,7 @@ import (
"github.com/alcionai/corso/src/pkg/count"
countTD "github.com/alcionai/corso/src/pkg/count/testdata"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/services/m365/api/pagers"
"github.com/alcionai/corso/src/pkg/services/m365/custom"
)
@ -2306,8 +2307,13 @@ func (suite *CollectionsTreeUnitSuite) TestCollections_AddFolderToTree() {
func (suite *CollectionsTreeUnitSuite) TestCollections_MakeFolderCollectionPath() {
d := drive()
basePath, err := odConsts.DriveFolderPrefixBuilder(d.id).
ToDataLayerOneDrivePath(tenant, user, false)
basePath, err := path.Build(
tenant,
user,
path.OneDriveService,
path.FilesCategory,
false,
odConsts.DriveFolderPrefixBuilder(d.id).Elements()...)
require.NoError(suite.T(), err, clues.ToCore(err))
folderPath, err := basePath.Append(false, folderName())

View File

@ -881,11 +881,23 @@ func (h mockBackupHandler[T]) GetItemPermission(
type canonPather func(*path.Builder, string, string) (path.Path, error)
var defaultOneDriveCanonPather = func(pb *path.Builder, tID, ro string) (path.Path, error) {
return pb.ToDataLayerOneDrivePath(tID, ro, false)
return path.Build(
tID,
ro,
path.OneDriveService,
path.FilesCategory,
false,
pb.Elements()...)
}
var defaultSharePointCanonPather = func(pb *path.Builder, tID, ro string) (path.Path, error) {
return pb.ToDataLayerSharePointPath(tID, ro, path.LibrariesCategory, false)
return path.Build(
tID,
ro,
path.SharePointService,
path.LibrariesCategory,
false,
pb.Elements()...)
}
type (

View File

@ -215,7 +215,13 @@ func (suite *RestoreUnitSuite) TestRestoreItem_collisionHandling() {
caches.collisionKeyToItemID = test.collisionKeys
dpp, err := dpb.ToDataLayerOneDrivePath("t", "u", false)
dpp, err := path.Build(
"t",
"u",
path.OneDriveService,
path.FilesCategory,
false,
dpb.Elements()...)
require.NoError(t, err)
dp, err := path.ToDrivePath(dpp)

View File

@ -131,7 +131,13 @@ func (h userDriveBackupHandler) CanonicalPath(
folders *path.Builder,
tenantID string,
) (path.Path, error) {
return folders.ToDataLayerOneDrivePath(tenantID, h.userID, false)
return path.Build(
tenantID,
h.userID,
path.OneDriveService,
path.FilesCategory,
false,
folders.Elements()...)
}
func (h userDriveBackupHandler) ServiceCat() (path.ServiceType, path.CategoryType) {

View File

@ -432,11 +432,13 @@ func includeContainer(
loc = loc.Append(ptr.Val(c.GetDisplayName()))
}
dirPath, err := pb.ToDataLayerExchangePathForCategory(
dirPath, err := path.Build(
qp.TenantID,
qp.ProtectedResource.ID(),
path.ExchangeService,
category,
false)
false,
pb.Elements()...)
// Containers without a path (e.g. Root mail folder) always err here.
if err != nil {
return nil, nil, false
@ -445,11 +447,13 @@ func includeContainer(
directory = dirPath.Folder(false)
if loc != nil {
locPath, err = loc.ToDataLayerExchangePathForCategory(
locPath, err = path.Build(
qp.TenantID,
qp.ProtectedResource.ID(),
path.ExchangeService,
category,
false)
false,
loc.Elements()...)
// Containers without a path (e.g. Root mail folder) always err here.
if err != nil {
return nil, nil, false

View File

@ -323,7 +323,13 @@ func (suite *ExportUnitSuite) TestExportRestoreCollections() {
}
)
p, err := dpb.ToDataLayerOneDrivePath("t", "u", false)
p, err := path.Build(
"t",
"u",
path.OneDriveService,
path.FilesCategory,
false,
dpb.Elements()...)
assert.NoError(t, err, "build path")
dcs := []data.RestoreCollection{

View File

@ -235,11 +235,23 @@ func (h BackupHandler[T]) GetItemPermission(
type canonPather func(*path.Builder, string, string) (path.Path, error)
var defaultOneDriveCanonPather = func(pb *path.Builder, tID, ro string) (path.Path, error) {
return pb.ToDataLayerOneDrivePath(tID, ro, false)
return path.Build(
tID,
ro,
path.OneDriveService,
path.FilesCategory,
false,
pb.Elements()...)
}
var defaultSharePointCanonPather = func(pb *path.Builder, tID, ro string) (path.Path, error) {
return pb.ToDataLayerSharePointPath(tID, ro, path.LibrariesCategory, false)
return path.Build(
tID,
ro,
path.SharePointService,
path.LibrariesCategory,
false,
pb.Elements()...)
}
type (

View File

@ -8,6 +8,7 @@ import (
"github.com/alcionai/clues"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/data"
@ -90,7 +91,13 @@ func (suite *ExportUnitSuite) TestExportRestoreCollections() {
},
},
getCollPath: func(t *testing.T) path.Path {
p, err := dpb.ToDataLayerSharePointPath("t", "u", path.LibrariesCategory, false)
p, err := path.Build(
"t",
"u",
path.SharePointService,
path.LibrariesCategory,
false,
dpb.Elements()...)
assert.NoError(t, err, "build path")
return p
@ -119,7 +126,13 @@ func (suite *ExportUnitSuite) TestExportRestoreCollections() {
},
},
getCollPath: func(t *testing.T) path.Path {
p, err := dpb.ToDataLayerSharePointPath("t", "u", path.LibrariesCategory, false)
p, err := path.Build(
"t",
"u",
path.SharePointService,
path.LibrariesCategory,
false,
dpb.Elements()...)
assert.NoError(t, err, "build path")
return p
@ -148,9 +161,13 @@ func (suite *ExportUnitSuite) TestExportRestoreCollections() {
},
},
getCollPath: func(t *testing.T) path.Path {
p, err := path.Elements{"listid1"}.
Builder().
ToDataLayerSharePointListPath("t", "u", path.ListsCategory, false)
p, err := path.Build(
"t",
"u",
path.SharePointService,
path.ListsCategory,
false,
"listid1")
assert.NoError(t, err, "build path")
return p
@ -198,9 +215,8 @@ func (suite *ExportUnitSuite) TestExportRestoreCollections() {
dcs,
stats,
fault.New(true))
assert.NoError(t, err, "export collections error")
require.NoError(t, err, "export collections error")
assert.Len(t, ecs, 1, "num of collections")
assert.Equal(t, test.expectedPath, ecs[0].BasePath(), "base dir")
fitems := []export.Item{}

View File

@ -2,7 +2,6 @@ package m365
import (
"context"
"fmt"
"testing"
"time"
@ -306,19 +305,7 @@ func ToDataLayerPath(
err error
)
switch service {
case path.ExchangeService:
p, err = pb.ToDataLayerExchangePathForCategory(tenant, resourceOwner, category, isItem)
case path.OneDriveService:
p, err = pb.ToDataLayerOneDrivePath(tenant, resourceOwner, isItem)
case path.SharePointService:
p, err = pb.ToDataLayerSharePointPath(tenant, resourceOwner, category, isItem)
case path.GroupsService:
p, err = pb.ToDataLayerPath(tenant, resourceOwner, service, category, false)
default:
err = clues.New(fmt.Sprintf("unknown service: %s", service))
}
p, err = pb.ToDataLayerPath(tenant, resourceOwner, service, category, isItem)
require.NoError(t, err, clues.ToCore(err))
return p

View File

@ -53,9 +53,10 @@ func locFromRepo(rr path.Path, isItem bool) *path.Builder {
loc = loc.Append(strings.TrimSuffix(e, folderSuffix))
}
if rr.Service() == path.GroupsService {
switch rr.Service() {
case path.GroupsService:
loc = loc.PopFront().PopFront().PopFront()
} else if rr.Service() == path.OneDriveService || rr.Category() == path.LibrariesCategory || rr.Category() == path.ListsCategory {
case path.OneDriveService, path.SharePointService:
loc = loc.PopFront()
}
@ -126,9 +127,6 @@ func (p repoRefAndLocRef) locationAsRepoRef() path.Path {
}
func mustPathRep(ref string, isItem, isSharepointList bool) repoRefAndLocRef {
var rr path.Path
var err error
res := repoRefAndLocRef{}
tmp := mustParsePath(ref, isItem, isSharepointList)
@ -144,21 +142,13 @@ func mustPathRep(ref string, isItem, isSharepointList bool) repoRefAndLocRef {
rrPB = rrPB.Append(tmp.Item() + fileSuffix)
}
if isSharepointList {
rr, err = rrPB.ToDataLayerSharePointListPath(
tmp.Tenant(),
tmp.ProtectedResource(),
tmp.Category(),
isItem)
} else {
rr, err = rrPB.ToDataLayerPath(
tmp.Tenant(),
tmp.ProtectedResource(),
tmp.Service(),
tmp.Category(),
isItem)
}
rr, err := path.BuildOrPrefix(
tmp.Tenant(),
tmp.ProtectedResource(),
tmp.Service(),
tmp.Category(),
isItem,
rrPB.Elements()...)
if err != nil {
panic(err)
}

View File

@ -332,57 +332,6 @@ func (pb Builder) ToDataLayerPath(
}, nil
}
func (pb Builder) ToDataLayerExchangePathForCategory(
tenant, resource string,
category CategoryType,
isItem bool,
) (Path, error) {
return pb.ToDataLayerPath(tenant, resource, ExchangeService, category, isItem)
}
func (pb Builder) ToDataLayerOneDrivePath(
tenant, resource string,
isItem bool,
) (Path, error) {
return pb.ToDataLayerPath(tenant, resource, OneDriveService, FilesCategory, isItem)
}
func (pb Builder) ToDataLayerSharePointPath(
tenant, site string,
category CategoryType,
isItem bool,
) (Path, error) {
return pb.ToDataLayerPath(tenant, site, SharePointService, category, isItem)
}
func (pb Builder) ToDataLayerSharePointListPath(
tenant, site string,
category CategoryType,
isItem bool,
) (Path, error) {
if err := ValidateServiceAndCategory(SharePointService, category); err != nil {
return nil, err
}
if err := verifyInputValues(tenant, site); err != nil {
return nil, err
}
prefixItems := []string{
tenant,
SharePointService.String(),
site,
category.String(),
}
return &dataLayerResourcePath{
Builder: *pb.withPrefix(prefixItems...),
service: SharePointService,
category: category,
hasItem: isItem,
}, nil
}
// ---------------------------------------------------------------------------
// Stringers and PII Concealer Compliance
// ---------------------------------------------------------------------------

View File

@ -276,7 +276,7 @@ func (suite *BuilderUnitSuite) TestFolder() {
p: func(t *testing.T) Path {
p, err := Builder{}.
Append("a", "b", "c").
ToDataLayerExchangePathForCategory("t", "u", EmailCategory, false)
ToDataLayerPath("t", "u", ExchangeService, EmailCategory, false)
require.NoError(t, err, clues.ToCore(err))
return p
@ -289,7 +289,7 @@ func (suite *BuilderUnitSuite) TestFolder() {
p: func(t *testing.T) Path {
p, err := Builder{}.
Append("a", "b", "c").
ToDataLayerExchangePathForCategory("t", "u", EmailCategory, false)
ToDataLayerPath("t", "u", ExchangeService, EmailCategory, false)
require.NoError(t, err, clues.ToCore(err))
return p
@ -303,7 +303,7 @@ func (suite *BuilderUnitSuite) TestFolder() {
p: func(t *testing.T) Path {
p, err := Builder{}.
Append("a/", "b", "c").
ToDataLayerExchangePathForCategory("t", "u", EmailCategory, false)
ToDataLayerPath("t", "u", ExchangeService, EmailCategory, false)
require.NoError(t, err, clues.ToCore(err))
return p
@ -316,7 +316,7 @@ func (suite *BuilderUnitSuite) TestFolder() {
p: func(t *testing.T) Path {
p, err := Builder{}.
Append("a/", "b", "c").
ToDataLayerExchangePathForCategory("t", "u", EmailCategory, false)
ToDataLayerPath("t", "u", ExchangeService, EmailCategory, false)
require.NoError(t, err, clues.ToCore(err))
return p

View File

@ -164,6 +164,40 @@ func BuildMetadata(
hasItem)
}
// BuildOrPrefix is the same as Build, but allows for 0-len folders
// (ie: only builds the prefix).
func BuildOrPrefix(
tenant, resourceOwner string,
service ServiceType,
category CategoryType,
hasItem bool,
elements ...string,
) (Path, error) {
pb := Builder{}
if err := ValidateServiceAndCategory(service, category); err != nil {
return nil, err
}
if err := verifyInputValues(tenant, resourceOwner); err != nil {
return nil, err
}
prefixItems := append(Elements{
tenant,
service.String(),
resourceOwner,
category.String(),
}, elements...)
return &dataLayerResourcePath{
Builder: *pb.withPrefix(prefixItems...),
service: service,
category: category,
hasItem: hasItem,
}, nil
}
func BuildPrefix(
tenant, resourceOwner string,
s ServiceType,

View File

@ -446,6 +446,82 @@ func (suite *PathUnitSuite) TestPrefixOrPathFromDataLayerPath() {
assert.Error(t, err)
}
func (suite *PathUnitSuite) TestBuildOrPrefix() {
table := []struct {
name string
service ServiceType
category CategoryType
tenant string
owner string
folders []string
expect string
expectErr require.ErrorAssertionFunc
}{
{
name: "ok, empty elements",
service: ExchangeService,
category: ContactsCategory,
tenant: "t",
owner: "ro",
folders: []string{},
expect: join([]string{"t", ExchangeService.String(), "ro", ContactsCategory.String()}),
expectErr: require.NoError,
},
{
name: "ok, non-empty elements",
service: ExchangeService,
category: ContactsCategory,
tenant: "t",
owner: "ro",
folders: []string{"foo"},
expect: join([]string{"t", ExchangeService.String(), "ro", ContactsCategory.String(), "foo"}),
expectErr: require.NoError,
},
{
name: "bad category",
service: ExchangeService,
category: FilesCategory,
tenant: "t",
owner: "ro",
expectErr: require.Error,
},
{
name: "bad tenant",
service: ExchangeService,
category: ContactsCategory,
tenant: "",
owner: "ro",
expectErr: require.Error,
},
{
name: "bad owner",
service: ExchangeService,
category: ContactsCategory,
tenant: "t",
owner: "",
expectErr: require.Error,
},
}
for _, test := range table {
suite.Run(test.name, func() {
t := suite.T()
r, err := BuildOrPrefix(test.tenant, test.owner, test.service, test.category, false, test.folders...)
test.expectErr(t, err, clues.ToCore(err))
if r == nil {
return
}
assert.Equal(t, test.expect, r.String())
assert.NotPanics(t, func() {
r.Folders()
r.Item()
}, "runs Folders() and Item()")
})
}
}
func (suite *PathUnitSuite) TestBuildPrefix() {
table := []struct {
name string

View File

@ -80,49 +80,91 @@ var (
service: path.ExchangeService,
category: path.EmailCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerExchangePathForCategory(tenant, resource, path.EmailCategory, isItem)
return path.Build(
tenant,
resource,
path.ExchangeService,
path.EmailCategory,
isItem,
pb.Elements()...)
},
},
{
service: path.ExchangeService,
category: path.ContactsCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerExchangePathForCategory(tenant, resource, path.ContactsCategory, isItem)
return path.Build(
tenant,
resource,
path.ExchangeService,
path.ContactsCategory,
isItem,
pb.Elements()...)
},
},
{
service: path.ExchangeService,
category: path.EventsCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerExchangePathForCategory(tenant, resource, path.EventsCategory, isItem)
return path.Build(
tenant,
resource,
path.ExchangeService,
path.EventsCategory,
isItem,
pb.Elements()...)
},
},
{
service: path.OneDriveService,
category: path.FilesCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerOneDrivePath(tenant, resource, isItem)
return path.Build(
tenant,
resource,
path.OneDriveService,
path.FilesCategory,
isItem,
pb.Elements()...)
},
},
{
service: path.SharePointService,
category: path.LibrariesCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerSharePointPath(tenant, resource, path.LibrariesCategory, isItem)
return path.Build(
tenant,
resource,
path.SharePointService,
path.LibrariesCategory,
isItem,
pb.Elements()...)
},
},
{
service: path.SharePointService,
category: path.ListsCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerSharePointPath(tenant, resource, path.ListsCategory, isItem)
return path.Build(
tenant,
resource,
path.SharePointService,
path.ListsCategory,
isItem,
pb.Elements()...)
},
},
{
service: path.SharePointService,
category: path.PagesCategory,
pathFunc: func(pb *path.Builder, tenant, resource string, isItem bool) (path.Path, error) {
return pb.ToDataLayerSharePointPath(tenant, resource, path.PagesCategory, isItem)
return path.Build(
tenant,
resource,
path.SharePointService,
path.PagesCategory,
isItem,
pb.Elements()...)
},
},
}
@ -196,12 +238,13 @@ func (suite *DataLayerResourcePath) TestPopFront() {
suite.Run(m.name, func() {
t := suite.T()
pb := path.Builder{}.Append(rest...)
p, err := pb.ToDataLayerExchangePathForCategory(
p, err := path.Build(
testTenant,
testResource,
path.ExchangeService,
path.EmailCategory,
m.isItem)
m.isItem,
rest...)
require.NoError(t, err, clues.ToCore(err))
b := p.PopFront()
@ -220,12 +263,13 @@ func (suite *DataLayerResourcePath) TestDir() {
for _, m := range modes {
suite.Run(m.name, func() {
pb := path.Builder{}.Append(rest...)
p, err := pb.ToDataLayerExchangePathForCategory(
p, err := path.Build(
testTenant,
testResource,
path.ExchangeService,
path.EmailCategory,
m.isItem)
m.isItem,
rest...)
require.NoError(suite.T(), err, clues.ToCore(err))
for i := 1; i <= len(rest); i++ {
@ -391,11 +435,13 @@ func (suite *DataLayerResourcePath) TestToExchangePathForCategory() {
suite.Run(test.category.String(), func() {
t := suite.T()
p, err := b.ToDataLayerExchangePathForCategory(
p, err := path.Build(
testTenant,
testResource,
path.ExchangeService,
test.category,
m.isItem)
m.isItem,
b.Elements()...)
test.check(t, err, clues.ToCore(err))
if err != nil {
@ -430,11 +476,13 @@ func (suite *PopulatedDataLayerResourcePath) SetupSuite() {
base := path.Builder{}.Append(rest...)
for _, t := range []bool{true, false} {
p, err := base.ToDataLayerExchangePathForCategory(
p, err := path.Build(
testTenant,
testResource,
path.ExchangeService,
path.EmailCategory,
t)
t,
base.Elements()...)
require.NoError(suite.T(), err, clues.ToCore(err))
suite.paths[t] = p
@ -613,8 +661,13 @@ func (suite *PopulatedDataLayerResourcePath) TestUpdateParent() {
}
buildPath := func(t *testing.T, pth string, isItem bool) path.Path {
pathBuilder := path.Builder{}.Append(strings.Split(pth, "/")...)
item, err := pathBuilder.ToDataLayerOneDrivePath("tenant", "resource", isItem)
item, err := path.Build(
"tenant",
"resource",
path.OneDriveService,
path.FilesCategory,
isItem,
strings.Split(pth, "/")...)
require.NoError(t, err, "err building path")
return item