From acf1837e77995bdadba1e42c88b430c97fd13e58 Mon Sep 17 00:00:00 2001 From: ashmrtn Date: Tue, 20 Sep 2022 10:15:46 -0700 Subject: [PATCH] 909 path folders (#910) ## Description Adds function call to the path package that returns the folder elements present in a path after the path prefix. This is safer than using `strings.Split()` because some paths may have `/` characters in elements. ## Type of change - [x] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [ ] :robot: Test - [ ] :computer: CI/Deployment - [ ] :hamster: Trivial/Minor ## Issue(s) * closes #909 ## Test Plan - [ ] :muscle: Manual - [x] :zap: Unit test - [ ] :green_heart: E2E --- src/internal/connector/onedrive/restore.go | 3 +- src/internal/path/path.go | 1 + src/internal/path/resource_path.go | 27 +++++++++++--- src/internal/path/resource_path_test.go | 43 +++++++++++++++------- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/internal/connector/onedrive/restore.go b/src/internal/connector/onedrive/restore.go index 475129f7d..394a9550e 100644 --- a/src/internal/connector/onedrive/restore.go +++ b/src/internal/connector/onedrive/restore.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "strings" "github.com/pkg/errors" @@ -35,7 +34,7 @@ type drivePath struct { } func toOneDrivePath(p path.Path) (*drivePath, error) { - folders := strings.Split(p.Folder(), "/") + folders := p.Folders() // Must be at least `drives//root:` if len(folders) < 3 { diff --git a/src/internal/path/path.go b/src/internal/path/path.go index 2c0b0d3e2..83f00b1fb 100644 --- a/src/internal/path/path.go +++ b/src/internal/path/path.go @@ -70,6 +70,7 @@ type Path interface { Tenant() string ResourceOwner() string Folder() string + Folders() []string Item() string // PopFront returns a Builder object with the first element (left-side) // removed. As the resulting set of elements is no longer a valid resource diff --git a/src/internal/path/resource_path.go b/src/internal/path/resource_path.go index e9194a638..66575f59b 100644 --- a/src/internal/path/resource_path.go +++ b/src/internal/path/resource_path.go @@ -141,20 +141,37 @@ func (rp dataLayerResourcePath) ResourceOwner() string { return rp.Builder.elements[2] } -// Folder returns the folder segment embedded in the dataLayerResourcePath. -func (rp dataLayerResourcePath) Folder() string { +func (rp dataLayerResourcePath) lastFolderIdx() int { endIdx := len(rp.Builder.elements) - if endIdx == 4 { - return "" - } if rp.hasItem { endIdx-- } + return endIdx +} + +// Folder returns the folder segment embedded in the dataLayerResourcePath. +func (rp dataLayerResourcePath) Folder() string { + endIdx := rp.lastFolderIdx() + if endIdx == 4 { + return "" + } + return rp.Builder.join(4, endIdx) } +// Folders returns the individual folder elements embedded in the +// dataLayerResourcePath. +func (rp dataLayerResourcePath) Folders() []string { + endIdx := rp.lastFolderIdx() + if endIdx == 4 { + return nil + } + + return append([]string{}, rp.elements[4:endIdx]...) +} + // Item returns the item embedded in the dataLayerResourcePath if the path // refers to an item. func (rp dataLayerResourcePath) Item() string { diff --git a/src/internal/path/resource_path_test.go b/src/internal/path/resource_path_test.go index 1941c98de..1062d87d0 100644 --- a/src/internal/path/resource_path_test.go +++ b/src/internal/path/resource_path_test.go @@ -49,22 +49,22 @@ var ( } modes = []struct { - name string - isItem bool - expectedFolder string - expectedItem string + name string + isItem bool + expectedFolders []string + expectedItem string }{ { - name: "Folder", - isItem: false, - expectedFolder: strings.Join(rest, "/"), - expectedItem: "", + name: "Folder", + isItem: false, + expectedFolders: rest, + expectedItem: "", }, { - name: "Item", - isItem: true, - expectedFolder: strings.Join(rest[0:len(rest)-1], "/"), - expectedItem: rest[len(rest)-1], + name: "Item", + isItem: true, + expectedFolders: rest[:len(rest)-1], + expectedItem: rest[len(rest)-1], }, } @@ -152,6 +152,7 @@ func (suite *DataLayerResourcePath) TestMailItemNoFolder() { require.NoError(t, err) assert.Empty(t, p.Folder()) + assert.Empty(t, p.Folders()) assert.Equal(t, item, p.Item()) }) } @@ -206,6 +207,7 @@ func (suite *DataLayerResourcePath) TestDir() { expected := path.Builder{}.Append(elements...).Append(rest[:len(rest)-i]...) assert.Equal(t, expected.String(), p.String()) + assert.Empty(t, p.Item()) }) } @@ -266,7 +268,8 @@ func (suite *DataLayerResourcePath) TestToExchangePathForCategory() { assert.Equal(t, path.ExchangeService, p.Service()) assert.Equal(t, test.category, p.Category()) assert.Equal(t, testUser, p.ResourceOwner()) - assert.Equal(t, m.expectedFolder, p.Folder()) + assert.Equal(t, strings.Join(m.expectedFolders, "/"), p.Folder()) + assert.Equal(t, m.expectedFolders, p.Folders()) assert.Equal(t, m.expectedItem, p.Item()) }) } @@ -336,7 +339,19 @@ func (suite *PopulatedDataLayerResourcePath) TestResourceOwner() { func (suite *PopulatedDataLayerResourcePath) TestFolder() { for _, m := range modes { suite.T().Run(m.name, func(t *testing.T) { - assert.Equal(t, m.expectedFolder, suite.paths[m.isItem].Folder()) + assert.Equal( + t, + strings.Join(m.expectedFolders, "/"), + suite.paths[m.isItem].Folder(), + ) + }) + } +} + +func (suite *PopulatedDataLayerResourcePath) TestFolders() { + for _, m := range modes { + suite.T().Run(m.name, func(t *testing.T) { + assert.Equal(t, m.expectedFolders, suite.paths[m.isItem].Folders()) }) } }