Move BaseCollection to different package (#4322)
Prep for use in other packages. Removed tests were covered by other code --- #### Does this PR need a docs update or release note? - [ ] ✅ Yes, it's included - [ ] 🕐 Yes, but in a later PR - [x] ⛔ No #### Type of change - [ ] 🌻 Feature - [ ] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Supportability/Tests - [ ] 💻 CI/Deployment - [x] 🧹 Tech Debt/Cleanup #### Issue(s) * #4319 #### Test Plan - [ ] 💪 Manual - [x] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
c1ec3c6648
commit
f767b67eca
@ -9,6 +9,7 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
|
||||
@ -70,3 +71,84 @@ func (suite *CollectionSuite) TestStateOf() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *CollectionSuite) TestNewBaseCollection() {
|
||||
fooP, err := path.Build("t", "u", path.ExchangeService, path.EmailCategory, false, "foo")
|
||||
require.NoError(suite.T(), err, clues.ToCore(err))
|
||||
barP, err := path.Build("t", "u", path.ExchangeService, path.EmailCategory, false, "bar")
|
||||
require.NoError(suite.T(), err, clues.ToCore(err))
|
||||
preP, err := path.Build("_t", "_u", path.ExchangeService, path.EmailCategory, false, "foo")
|
||||
require.NoError(suite.T(), err, clues.ToCore(err))
|
||||
|
||||
loc := path.Builder{}.Append("foo")
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
current path.Path
|
||||
previous path.Path
|
||||
doNotMerge bool
|
||||
|
||||
expectCurrent path.Path
|
||||
expectPrev path.Path
|
||||
expectState CollectionState
|
||||
expectDoNotMerge bool
|
||||
}{
|
||||
{
|
||||
name: "NotMoved DoNotMerge",
|
||||
current: fooP,
|
||||
previous: fooP,
|
||||
doNotMerge: true,
|
||||
expectCurrent: fooP,
|
||||
expectPrev: fooP,
|
||||
expectState: NotMovedState,
|
||||
expectDoNotMerge: true,
|
||||
},
|
||||
{
|
||||
name: "Moved",
|
||||
current: fooP,
|
||||
previous: barP,
|
||||
expectCurrent: fooP,
|
||||
expectPrev: barP,
|
||||
expectState: MovedState,
|
||||
},
|
||||
{
|
||||
name: "PrefixMoved",
|
||||
current: fooP,
|
||||
previous: preP,
|
||||
expectCurrent: fooP,
|
||||
expectPrev: preP,
|
||||
expectState: MovedState,
|
||||
},
|
||||
{
|
||||
name: "New",
|
||||
current: fooP,
|
||||
expectCurrent: fooP,
|
||||
expectState: NewState,
|
||||
},
|
||||
{
|
||||
name: "Deleted",
|
||||
previous: fooP,
|
||||
expectPrev: fooP,
|
||||
expectState: DeletedState,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
t := suite.T()
|
||||
|
||||
b := NewBaseCollection(
|
||||
test.current,
|
||||
test.previous,
|
||||
loc,
|
||||
control.Options{},
|
||||
test.doNotMerge)
|
||||
|
||||
assert.Equal(t, test.expectCurrent, b.FullPath(), "full path")
|
||||
assert.Equal(t, test.expectPrev, b.PreviousPath(), "previous path")
|
||||
assert.Equal(t, loc, b.LocationPath(), "location path")
|
||||
assert.Equal(t, test.expectState, b.State(), "state")
|
||||
assert.Equal(t, test.expectDoNotMerge, b.DoNotMergeItems(), "do not merge")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
|
||||
@ -51,3 +52,76 @@ func StateOf(prev, curr path.Path) CollectionState {
|
||||
|
||||
return NotMovedState
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// BaseCollection
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
func NewBaseCollection(
|
||||
curr, prev path.Path,
|
||||
location *path.Builder,
|
||||
ctrlOpts control.Options,
|
||||
doNotMergeItems bool,
|
||||
) BaseCollection {
|
||||
return BaseCollection{
|
||||
opts: ctrlOpts,
|
||||
doNotMergeItems: doNotMergeItems,
|
||||
fullPath: curr,
|
||||
locationPath: location,
|
||||
prevPath: prev,
|
||||
state: StateOf(prev, curr),
|
||||
}
|
||||
}
|
||||
|
||||
// BaseCollection contains basic functionality like returning path, location,
|
||||
// and state information. It can be embedded in other implementations to provide
|
||||
// this functionality.
|
||||
//
|
||||
// Functionality like how items are fetched is left to the embedding struct.
|
||||
type BaseCollection struct {
|
||||
opts control.Options
|
||||
|
||||
// FullPath is the current hierarchical path used by this collection.
|
||||
fullPath path.Path
|
||||
|
||||
// PrevPath is the previous hierarchical path used by this collection.
|
||||
// It may be the same as fullPath, if the folder was not renamed or
|
||||
// moved. It will be empty on its first retrieval.
|
||||
prevPath path.Path
|
||||
|
||||
// LocationPath contains the path with human-readable display names.
|
||||
// IE: "/Inbox/Important" instead of "/abcdxyz123/algha=lgkhal=t"
|
||||
locationPath *path.Builder
|
||||
|
||||
state CollectionState
|
||||
|
||||
// doNotMergeItems should only be true if the old delta token expired.
|
||||
doNotMergeItems bool
|
||||
}
|
||||
|
||||
// FullPath returns the BaseCollection's fullPath []string
|
||||
func (col *BaseCollection) FullPath() path.Path {
|
||||
return col.fullPath
|
||||
}
|
||||
|
||||
// LocationPath produces the BaseCollection's full path, but with display names
|
||||
// instead of IDs in the folders. Only populated for Calendars.
|
||||
func (col *BaseCollection) LocationPath() *path.Builder {
|
||||
return col.locationPath
|
||||
}
|
||||
|
||||
func (col BaseCollection) PreviousPath() path.Path {
|
||||
return col.prevPath
|
||||
}
|
||||
|
||||
func (col BaseCollection) State() CollectionState {
|
||||
return col.state
|
||||
}
|
||||
|
||||
func (col BaseCollection) DoNotMergeItems() bool {
|
||||
return col.doNotMergeItems
|
||||
}
|
||||
|
||||
func (col BaseCollection) Opts() control.Options {
|
||||
return col.opts
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ func populateCollections(
|
||||
}
|
||||
|
||||
edc := NewCollection(
|
||||
NewBaseCollection(
|
||||
data.NewBaseCollection(
|
||||
currPath,
|
||||
prevPath,
|
||||
locPath,
|
||||
@ -242,7 +242,7 @@ func populateCollections(
|
||||
}
|
||||
|
||||
edc := NewCollection(
|
||||
NewBaseCollection(
|
||||
data.NewBaseCollection(
|
||||
nil, // marks the collection as deleted
|
||||
prevPath,
|
||||
nil, // tombstones don't need a location
|
||||
|
||||
@ -20,7 +20,6 @@ import (
|
||||
"github.com/alcionai/corso/src/internal/m365/support"
|
||||
"github.com/alcionai/corso/src/internal/observe"
|
||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/logger"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
@ -38,71 +37,6 @@ const (
|
||||
numberOfRetries = 4
|
||||
)
|
||||
|
||||
func NewBaseCollection(
|
||||
curr, prev path.Path,
|
||||
location *path.Builder,
|
||||
ctrlOpts control.Options,
|
||||
doNotMergeItems bool,
|
||||
) baseCollection {
|
||||
return baseCollection{
|
||||
ctrl: ctrlOpts,
|
||||
doNotMergeItems: doNotMergeItems,
|
||||
fullPath: curr,
|
||||
locationPath: location,
|
||||
prevPath: prev,
|
||||
state: data.StateOf(prev, curr),
|
||||
}
|
||||
}
|
||||
|
||||
// baseCollection contains basic functionality like returning path, location,
|
||||
// and state information. It can be embedded in other implementations to provide
|
||||
// this functionality.
|
||||
//
|
||||
// Functionality like how items are fetched is left to the embedding struct.
|
||||
type baseCollection struct {
|
||||
ctrl control.Options
|
||||
|
||||
// FullPath is the current hierarchical path used by this collection.
|
||||
fullPath path.Path
|
||||
|
||||
// PrevPath is the previous hierarchical path used by this collection.
|
||||
// It may be the same as fullPath, if the folder was not renamed or
|
||||
// moved. It will be empty on its first retrieval.
|
||||
prevPath path.Path
|
||||
|
||||
// LocationPath contains the path with human-readable display names.
|
||||
// IE: "/Inbox/Important" instead of "/abcdxyz123/algha=lgkhal=t"
|
||||
locationPath *path.Builder
|
||||
|
||||
state data.CollectionState
|
||||
|
||||
// doNotMergeItems should only be true if the old delta token expired.
|
||||
doNotMergeItems bool
|
||||
}
|
||||
|
||||
// FullPath returns the baseCollection's fullPath []string
|
||||
func (col *baseCollection) FullPath() path.Path {
|
||||
return col.fullPath
|
||||
}
|
||||
|
||||
// LocationPath produces the baseCollection's full path, but with display names
|
||||
// instead of IDs in the folders. Only populated for Calendars.
|
||||
func (col *baseCollection) LocationPath() *path.Builder {
|
||||
return col.locationPath
|
||||
}
|
||||
|
||||
func (col baseCollection) PreviousPath() path.Path {
|
||||
return col.prevPath
|
||||
}
|
||||
|
||||
func (col baseCollection) State() data.CollectionState {
|
||||
return col.state
|
||||
}
|
||||
|
||||
func (col baseCollection) DoNotMergeItems() bool {
|
||||
return col.doNotMergeItems
|
||||
}
|
||||
|
||||
// updateStatus is a utility function used to send the status update through
|
||||
// the channel.
|
||||
func updateStatus(
|
||||
@ -173,7 +107,7 @@ func getItemAndInfo(
|
||||
// If both are populated, then state is either moved (if they differ),
|
||||
// or notMoved (if they match).
|
||||
func NewCollection(
|
||||
bc baseCollection,
|
||||
bc data.BaseCollection,
|
||||
user string,
|
||||
items itemGetterSerializer,
|
||||
origAdded map[string]time.Time,
|
||||
@ -199,7 +133,7 @@ func NewCollection(
|
||||
|
||||
if !validModTimes {
|
||||
return &prefetchCollection{
|
||||
baseCollection: bc,
|
||||
BaseCollection: bc,
|
||||
user: user,
|
||||
added: added,
|
||||
removed: removed,
|
||||
@ -209,7 +143,7 @@ func NewCollection(
|
||||
}
|
||||
|
||||
return &lazyFetchCollection{
|
||||
baseCollection: bc,
|
||||
BaseCollection: bc,
|
||||
user: user,
|
||||
added: added,
|
||||
removed: removed,
|
||||
@ -221,7 +155,7 @@ func NewCollection(
|
||||
// prefetchCollection implements the interface from data.BackupCollection
|
||||
// Structure holds data for an Exchange application for a single user
|
||||
type prefetchCollection struct {
|
||||
baseCollection
|
||||
data.BaseCollection
|
||||
|
||||
user string
|
||||
|
||||
@ -283,7 +217,7 @@ func (col *prefetchCollection) streamItems(
|
||||
defer close(colProgress)
|
||||
}
|
||||
|
||||
semaphoreCh := make(chan struct{}, col.ctrl.Parallelism.ItemFetch)
|
||||
semaphoreCh := make(chan struct{}, col.Opts().Parallelism.ItemFetch)
|
||||
defer close(semaphoreCh)
|
||||
|
||||
// delete all removed items
|
||||
@ -331,7 +265,7 @@ func (col *prefetchCollection) streamItems(
|
||||
col.getter,
|
||||
user,
|
||||
id,
|
||||
col.ctrl.ToggleFeatures.ExchangeImmutableIDs,
|
||||
col.Opts().ToggleFeatures.ExchangeImmutableIDs,
|
||||
parentPath)
|
||||
if err != nil {
|
||||
// Don't report errors for deleted items as there's no way for us to
|
||||
@ -380,7 +314,7 @@ func (col *prefetchCollection) streamItems(
|
||||
// information (path and mod time) is handed to kopia. Total bytes across all
|
||||
// items is not tracked.
|
||||
type lazyFetchCollection struct {
|
||||
baseCollection
|
||||
data.BaseCollection
|
||||
|
||||
user string
|
||||
|
||||
@ -474,7 +408,7 @@ func (col *lazyFetchCollection) streamItems(
|
||||
id: id,
|
||||
getter: col.getter,
|
||||
modTime: modTime,
|
||||
immutableIDs: col.ctrl.ToggleFeatures.ExchangeImmutableIDs,
|
||||
immutableIDs: col.Opts().ToggleFeatures.ExchangeImmutableIDs,
|
||||
parentPath: parentPath,
|
||||
errs: errs,
|
||||
}
|
||||
|
||||
@ -63,32 +63,6 @@ func (suite *CollectionUnitSuite) TestReader_Empty() {
|
||||
assert.NoError(t, err, clues.ToCore(err))
|
||||
}
|
||||
|
||||
func (suite *CollectionUnitSuite) TestCollection_NewCollection() {
|
||||
t := suite.T()
|
||||
tenant := "a-tenant"
|
||||
user := "a-user"
|
||||
folder := "a-folder"
|
||||
name := "User"
|
||||
|
||||
fullPath, err := path.Build(
|
||||
tenant,
|
||||
user,
|
||||
path.ExchangeService,
|
||||
path.EmailCategory,
|
||||
false,
|
||||
folder)
|
||||
require.NoError(t, err, clues.ToCore(err))
|
||||
|
||||
edc := prefetchCollection{
|
||||
baseCollection: baseCollection{
|
||||
fullPath: fullPath,
|
||||
},
|
||||
user: name,
|
||||
}
|
||||
assert.Equal(t, name, edc.user)
|
||||
assert.Equal(t, fullPath, edc.FullPath())
|
||||
}
|
||||
|
||||
func (suite *CollectionUnitSuite) TestNewCollection_state() {
|
||||
type collectionTypes struct {
|
||||
name string
|
||||
@ -153,7 +127,7 @@ func (suite *CollectionUnitSuite) TestNewCollection_state() {
|
||||
t := suite.T()
|
||||
|
||||
c := NewCollection(
|
||||
NewBaseCollection(
|
||||
data.NewBaseCollection(
|
||||
test.curr,
|
||||
test.prev,
|
||||
test.loc,
|
||||
@ -296,7 +270,7 @@ func (suite *CollectionUnitSuite) TestPrefetchCollection_Items() {
|
||||
defer flush()
|
||||
|
||||
col := NewCollection(
|
||||
NewBaseCollection(
|
||||
data.NewBaseCollection(
|
||||
fullPath,
|
||||
nil,
|
||||
locPath.ToBuilder(),
|
||||
@ -434,7 +408,7 @@ func (suite *CollectionUnitSuite) TestLazyFetchCollection_Items_LazyFetch() {
|
||||
defer mlg.check(t, test.expectReads)
|
||||
|
||||
col := NewCollection(
|
||||
NewBaseCollection(
|
||||
data.NewBaseCollection(
|
||||
fullPath,
|
||||
nil,
|
||||
locPath.ToBuilder(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user