just a QoL shorthand to match the Build func. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🧹 Tech Debt/Cleanup #### Test Plan - [x] ⚡ Unit test - [=x] 💚 E2E
682 lines
16 KiB
Go
682 lines
16 KiB
Go
package path_test
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"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/tester"
|
|
"github.com/alcionai/corso/src/pkg/path"
|
|
)
|
|
|
|
const (
|
|
testTenant = "aTenant"
|
|
testUser = "aUser"
|
|
)
|
|
|
|
var (
|
|
// Purposely doesn't have characters that need escaping so it can be easily
|
|
// computed using strings.Join().
|
|
rest = []string{"some", "folder", "path", "with", "possible", "item"}
|
|
|
|
missingInfo = []struct {
|
|
name string
|
|
tenant string
|
|
user string
|
|
rest []string
|
|
}{
|
|
{
|
|
name: "NoTenant",
|
|
tenant: "",
|
|
user: testUser,
|
|
rest: rest,
|
|
},
|
|
{
|
|
name: "NoResourceOwner",
|
|
tenant: testTenant,
|
|
user: "",
|
|
rest: rest,
|
|
},
|
|
{
|
|
name: "NoFolderOrItem",
|
|
tenant: testTenant,
|
|
user: testUser,
|
|
rest: nil,
|
|
},
|
|
}
|
|
|
|
modes = []struct {
|
|
name string
|
|
isItem bool
|
|
expectedFolders []string
|
|
expectedItem string
|
|
}{
|
|
{
|
|
name: "Folder",
|
|
isItem: false,
|
|
expectedFolders: rest,
|
|
expectedItem: "",
|
|
},
|
|
{
|
|
name: "Item",
|
|
isItem: true,
|
|
expectedFolders: rest[:len(rest)-1],
|
|
expectedItem: rest[len(rest)-1],
|
|
},
|
|
}
|
|
|
|
// Set of acceptable service/category mixtures.
|
|
serviceCategories = []struct {
|
|
service path.ServiceType
|
|
category path.CategoryType
|
|
pathFunc func(pb *path.Builder, tenant, user string, isItem bool) (path.Path, error)
|
|
}{
|
|
{
|
|
service: path.ExchangeService,
|
|
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,
|
|
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,
|
|
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)
|
|
},
|
|
},
|
|
{
|
|
service: path.SharePointService,
|
|
category: path.LibrariesCategory,
|
|
pathFunc: func(pb *path.Builder, tenant, site string, isItem bool) (path.Path, error) {
|
|
return pb.ToDataLayerSharePointPath(tenant, site, path.LibrariesCategory, isItem)
|
|
},
|
|
},
|
|
{
|
|
service: path.SharePointService,
|
|
category: path.ListsCategory,
|
|
pathFunc: func(pb *path.Builder, tenant, site string, isItem bool) (path.Path, error) {
|
|
return pb.ToDataLayerSharePointPath(tenant, site, path.ListsCategory, isItem)
|
|
},
|
|
},
|
|
{
|
|
service: path.SharePointService,
|
|
category: path.PagesCategory,
|
|
pathFunc: func(pb *path.Builder, tenant, site string, isItem bool) (path.Path, error) {
|
|
return pb.ToDataLayerSharePointPath(tenant, site, path.PagesCategory, isItem)
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
type DataLayerResourcePath struct {
|
|
tester.Suite
|
|
}
|
|
|
|
func TestDataLayerResourcePath(t *testing.T) {
|
|
suite.Run(t, &DataLayerResourcePath{Suite: tester.NewUnitSuite(t)})
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) SetupSuite() {
|
|
clues.SetHasher(clues.NoHash())
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) TestMissingInfoErrors() {
|
|
for _, types := range serviceCategories {
|
|
suite.Run(types.service.String()+types.category.String(), func() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
for _, test := range missingInfo {
|
|
suite.Run(test.name, func() {
|
|
t := suite.T()
|
|
|
|
b := path.Builder{}.Append(test.rest...)
|
|
|
|
_, err := types.pathFunc(
|
|
b,
|
|
test.tenant,
|
|
test.user,
|
|
m.isItem,
|
|
)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) TestMailItemNoFolder() {
|
|
item := "item"
|
|
b := path.Builder{}.Append(item)
|
|
|
|
for _, types := range serviceCategories {
|
|
suite.Run(types.service.String()+types.category.String(), func() {
|
|
t := suite.T()
|
|
|
|
p, err := types.pathFunc(
|
|
b,
|
|
testTenant,
|
|
testUser,
|
|
true,
|
|
)
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
assert.Empty(t, p.Folder(false))
|
|
assert.Empty(t, p.Folders())
|
|
assert.Equal(t, item, p.Item())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) TestPopFront() {
|
|
expected := path.Builder{}.Append(append(
|
|
[]string{path.ExchangeService.String(), testUser, path.EmailCategory.String()},
|
|
rest...,
|
|
)...)
|
|
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
pb := path.Builder{}.Append(rest...)
|
|
p, err := pb.ToDataLayerExchangePathForCategory(
|
|
testTenant,
|
|
testUser,
|
|
path.EmailCategory,
|
|
m.isItem,
|
|
)
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
b := p.PopFront()
|
|
assert.Equal(t, expected.String(), b.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) TestDir() {
|
|
elements := []string{
|
|
testTenant,
|
|
path.ExchangeService.String(),
|
|
testUser,
|
|
path.EmailCategory.String(),
|
|
}
|
|
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
pb := path.Builder{}.Append(rest...)
|
|
p, err := pb.ToDataLayerExchangePathForCategory(
|
|
testTenant,
|
|
testUser,
|
|
path.EmailCategory,
|
|
m.isItem,
|
|
)
|
|
require.NoError(suite.T(), err, clues.ToCore(err))
|
|
|
|
for i := 1; i <= len(rest); i++ {
|
|
suite.Run(fmt.Sprintf("%v", i), func() {
|
|
t := suite.T()
|
|
|
|
p, err = p.Dir()
|
|
require.NoError(t, err, clues.ToCore(err))
|
|
|
|
expected := path.Builder{}.Append(elements...).Append(rest[:len(rest)-i]...)
|
|
assert.Equal(t, expected.String(), p.String())
|
|
assert.Empty(t, p.Item())
|
|
})
|
|
}
|
|
|
|
suite.Run("All", func() {
|
|
p, err = p.Dir()
|
|
assert.Error(suite.T(), err)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
|
tenant := "a-tenant"
|
|
user := "a-user"
|
|
table := []struct {
|
|
name string
|
|
service path.ServiceType
|
|
category path.CategoryType
|
|
postfix []string
|
|
expectedService path.ServiceType
|
|
check assert.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
name: "NoPostfixPasses",
|
|
service: path.ExchangeService,
|
|
category: path.EmailCategory,
|
|
expectedService: path.ExchangeMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "PostfixPasses",
|
|
service: path.ExchangeService,
|
|
category: path.EmailCategory,
|
|
postfix: []string{"a", "b"},
|
|
expectedService: path.ExchangeMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "Fails",
|
|
service: path.ExchangeService,
|
|
category: path.FilesCategory,
|
|
check: assert.Error,
|
|
},
|
|
{
|
|
name: "Exchange Contacts",
|
|
service: path.ExchangeService,
|
|
category: path.ContactsCategory,
|
|
expectedService: path.ExchangeMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "Exchange Events",
|
|
service: path.ExchangeService,
|
|
category: path.EventsCategory,
|
|
expectedService: path.ExchangeMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "OneDrive Files",
|
|
service: path.OneDriveService,
|
|
category: path.FilesCategory,
|
|
expectedService: path.OneDriveMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "SharePoint Libraries",
|
|
service: path.SharePointService,
|
|
category: path.LibrariesCategory,
|
|
expectedService: path.SharePointMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "SharePoint Lists",
|
|
service: path.SharePointService,
|
|
category: path.ListsCategory,
|
|
expectedService: path.SharePointMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "SharePoint Pages",
|
|
service: path.SharePointService,
|
|
category: path.PagesCategory,
|
|
expectedService: path.SharePointMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
name: "Groups Libraries",
|
|
service: path.GroupsService,
|
|
category: path.LibrariesCategory,
|
|
expectedService: path.GroupsMetadataService,
|
|
check: assert.NoError,
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
suite.Run(strings.Join([]string{
|
|
test.name,
|
|
test.service.String(),
|
|
test.category.String(),
|
|
}, "_"), func() {
|
|
t := suite.T()
|
|
p, err := path.BuildMetadata(
|
|
tenant,
|
|
user,
|
|
test.service,
|
|
test.category,
|
|
false,
|
|
test.postfix...)
|
|
test.check(t, err, clues.ToCore(err))
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
assert.Equal(t, test.expectedService, p.Service())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *DataLayerResourcePath) TestToExchangePathForCategory() {
|
|
b := path.Builder{}.Append(rest...)
|
|
table := []struct {
|
|
category path.CategoryType
|
|
check assert.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
category: path.UnknownCategory,
|
|
check: assert.Error,
|
|
},
|
|
{
|
|
category: path.CategoryType(-1),
|
|
check: assert.Error,
|
|
},
|
|
{
|
|
category: path.EmailCategory,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
category: path.ContactsCategory,
|
|
check: assert.NoError,
|
|
},
|
|
{
|
|
category: path.EventsCategory,
|
|
check: assert.NoError,
|
|
},
|
|
}
|
|
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
for _, test := range table {
|
|
suite.Run(test.category.String(), func() {
|
|
t := suite.T()
|
|
|
|
p, err := b.ToDataLayerExchangePathForCategory(
|
|
testTenant,
|
|
testUser,
|
|
test.category,
|
|
m.isItem)
|
|
test.check(t, err, clues.ToCore(err))
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
assert.Equal(t, testTenant, p.Tenant())
|
|
assert.Equal(t, path.ExchangeService, p.Service())
|
|
assert.Equal(t, test.category, p.Category())
|
|
assert.Equal(t, testUser, p.ResourceOwner())
|
|
assert.Equal(t, strings.Join(m.expectedFolders, "/"), p.Folder(false))
|
|
assert.Equal(t, path.Elements(m.expectedFolders), p.Folders())
|
|
assert.Equal(t, m.expectedItem, p.Item())
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
type PopulatedDataLayerResourcePath struct {
|
|
tester.Suite
|
|
// Bool value is whether the path is an item path or a folder path.
|
|
paths map[bool]path.Path
|
|
}
|
|
|
|
func TestPopulatedDataLayerResourcePath(t *testing.T) {
|
|
suite.Run(t, &PopulatedDataLayerResourcePath{Suite: tester.NewUnitSuite(t)})
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) SetupSuite() {
|
|
suite.paths = make(map[bool]path.Path, 2)
|
|
base := path.Builder{}.Append(rest...)
|
|
|
|
for _, t := range []bool{true, false} {
|
|
p, err := base.ToDataLayerExchangePathForCategory(
|
|
testTenant,
|
|
testUser,
|
|
path.EmailCategory,
|
|
t,
|
|
)
|
|
require.NoError(suite.T(), err, clues.ToCore(err))
|
|
|
|
suite.paths[t] = p
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestTenant() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(t, testTenant, suite.paths[m.isItem].Tenant())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestService() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(t, path.ExchangeService, suite.paths[m.isItem].Service())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestCategory() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(t, path.EmailCategory, suite.paths[m.isItem].Category())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestResourceOwner() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(t, testUser, suite.paths[m.isItem].ResourceOwner())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestFolder() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(
|
|
t,
|
|
strings.Join(m.expectedFolders, "/"),
|
|
suite.paths[m.isItem].Folder(false),
|
|
)
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestFolders() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(t, path.Elements(m.expectedFolders), suite.paths[m.isItem].Folders())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestItem() {
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
t := suite.T()
|
|
|
|
assert.Equal(t, m.expectedItem, suite.paths[m.isItem].Item())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestAppend() {
|
|
newElement := "someElement"
|
|
isItem := []struct {
|
|
name string
|
|
hasItem bool
|
|
// Used if the starting path is a folder.
|
|
expectedFolder string
|
|
expectedItem string
|
|
}{
|
|
{
|
|
name: "Item",
|
|
hasItem: true,
|
|
expectedFolder: strings.Join(rest, "/"),
|
|
expectedItem: newElement,
|
|
},
|
|
{
|
|
name: "Directory",
|
|
hasItem: false,
|
|
expectedFolder: strings.Join(
|
|
append(append([]string{}, rest...), newElement),
|
|
"/",
|
|
),
|
|
expectedItem: "",
|
|
},
|
|
}
|
|
|
|
for _, m := range modes {
|
|
suite.Run(m.name, func() {
|
|
for _, test := range isItem {
|
|
suite.Run(test.name, func() {
|
|
t := suite.T()
|
|
|
|
newPath, err := suite.paths[m.isItem].Append(test.hasItem, newElement)
|
|
|
|
// Items don't allow appending.
|
|
if m.isItem {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
|
|
assert.Equal(t, test.expectedFolder, newPath.Folder(false))
|
|
assert.Equal(t, test.expectedItem, newPath.Item())
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestUpdateParent() {
|
|
cases := []struct {
|
|
name string
|
|
item string
|
|
prev string
|
|
cur string
|
|
expected string
|
|
updated bool
|
|
}{
|
|
{
|
|
name: "basic",
|
|
item: "folder/item",
|
|
prev: "folder",
|
|
cur: "new-folder",
|
|
expected: "new-folder/item",
|
|
updated: true,
|
|
},
|
|
{
|
|
name: "long path",
|
|
item: "folder/folder1/folder2/item",
|
|
prev: "folder/folder1",
|
|
cur: "new-folder/new-folder1",
|
|
expected: "new-folder/new-folder1/folder2/item",
|
|
updated: true,
|
|
},
|
|
{
|
|
name: "change to shorter path",
|
|
item: "folder/folder1/folder2/item",
|
|
prev: "folder/folder1/folder2",
|
|
cur: "new-folder",
|
|
expected: "new-folder/item",
|
|
updated: true,
|
|
},
|
|
{
|
|
name: "change to longer path",
|
|
item: "folder/item",
|
|
prev: "folder",
|
|
cur: "folder/folder1/folder2/folder3",
|
|
expected: "folder/folder1/folder2/folder3/item",
|
|
updated: true,
|
|
},
|
|
{
|
|
name: "not parent",
|
|
item: "folder/folder1/folder2/item",
|
|
prev: "folder1",
|
|
cur: "new-folder1",
|
|
expected: "dummy",
|
|
updated: false,
|
|
},
|
|
}
|
|
|
|
buildPath := func(t *testing.T, pth string, isItem bool) path.Path {
|
|
pathBuilder := path.Builder{}.Append(strings.Split(pth, "/")...)
|
|
item, err := pathBuilder.ToDataLayerOneDrivePath("tenant", "user", isItem)
|
|
require.NoError(t, err, "err building path")
|
|
|
|
return item
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
suite.Run(tc.name, func() {
|
|
t := suite.T()
|
|
|
|
item := buildPath(t, tc.item, true)
|
|
prev := buildPath(t, tc.prev, false)
|
|
cur := buildPath(t, tc.cur, false)
|
|
expected := buildPath(t, tc.expected, true)
|
|
|
|
updated := item.UpdateParent(prev, cur)
|
|
assert.Equal(t, tc.updated, updated, "path updated")
|
|
if tc.updated {
|
|
assert.Equal(t, expected, item, "modified path")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *PopulatedDataLayerResourcePath) TestUpdateParent_NoopsNils() {
|
|
oldPB := path.Builder{}.Append("hello", "world")
|
|
newPB := path.Builder{}.Append("hola", "mundo")
|
|
// So we can get a new copy for each test.
|
|
testPBElems := []string{"bar", "baz"}
|
|
|
|
table := []struct {
|
|
name string
|
|
oldPB *path.Builder
|
|
newPB *path.Builder
|
|
}{
|
|
{
|
|
name: "Nil Prev",
|
|
newPB: newPB,
|
|
},
|
|
{
|
|
name: "Nil New",
|
|
oldPB: oldPB,
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
suite.Run(test.name, func() {
|
|
t := suite.T()
|
|
|
|
base := oldPB.Append(testPBElems...)
|
|
expected := base.String()
|
|
|
|
assert.False(t, base.UpdateParent(test.oldPB, test.newPB))
|
|
assert.Equal(t, expected, base.String())
|
|
})
|
|
}
|
|
}
|