diff --git a/src/pkg/selectors/onedrive.go b/src/pkg/selectors/onedrive.go new file mode 100644 index 000000000..ff4258af2 --- /dev/null +++ b/src/pkg/selectors/onedrive.go @@ -0,0 +1,112 @@ +package selectors + +// --------------------------------------------------------------------------- +// Selectors +// --------------------------------------------------------------------------- + +type ( + // onedrive provides an api for selecting + // data scopes applicable to the OneDrive service. + onedrive struct { + Selector + } + + // OneDriveBackup provides an api for selecting + // data scopes applicable to the OneDrive service, + // plus backup-specific methods. + OneDriveBackup struct { + onedrive + } +) + +// NewOneDriveBackup produces a new Selector with the service set to ServiceOneDrive. +func NewOneDriveBackup() *OneDriveBackup { + src := OneDriveBackup{ + onedrive{ + newSelector(ServiceOneDrive), + }, + } + return &src +} + +// ToOneDriveBackup transforms the generic selector into an OneDriveBackup. +// Errors if the service defined by the selector is not ServiceOneDrive. +func (s Selector) ToOneDriveBackup() (*OneDriveBackup, error) { + if s.Service != ServiceOneDrive { + return nil, badCastErr(ServiceOneDrive, s.Service) + } + src := OneDriveBackup{onedrive{s}} + return &src, nil +} + +// --------------------------------------------------------------------------- +// Scopes +// --------------------------------------------------------------------------- + +type ( + // OneDriveScope specifies the data available + // when interfacing with the OneDrive service. + OneDriveScope scope + // onedriveCategory enumerates the type of the lowest level + // of data () in a scope. + onedriveCategory int +) + +//go:generate go run golang.org/x/tools/cmd/stringer -type=onedriveCategory +const ( + OneDriveCategoryUnknown onedriveCategory = iota + // types of data identified by OneDrive + OneDriveUser +) + +// Scopes retrieves the list of onedriveScopes in the selector. +func (s *onedrive) Scopes() []OneDriveScope { + scopes := []OneDriveScope{} + for _, v := range s.Includes { + scopes = append(scopes, OneDriveScope(v)) + } + return scopes +} + +// Get returns the data category in the scope. If the scope +// contains all data types for a user, it'll return the +// OneDriveUser category. +func (s OneDriveScope) Get(cat onedriveCategory) []string { + v, ok := s[cat.String()] + if !ok { + return None() + } + return split(v) +} + +// Produces one or more onedrive user scopes. +// One scope is created per user entry. +// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] +// If any slice contains selectors.None, that slice is reduced to [selectors.None] +// If any slice is empty, it defaults to [selectors.None] +func (s *onedrive) Users(users []string) []OneDriveScope { + users = normalize(users) + scopes := []OneDriveScope{} + for _, u := range users { + userScope := OneDriveScope{ + OneDriveUser.String(): u, + } + scopes = append(scopes, userScope) + } + return scopes +} + +// nop-transform method +func nopTransform(sl []OneDriveScope) []OneDriveScope { return sl } + +func (s *onedrive) Include(scopes ...[]OneDriveScope) { + appendIncludes(&s.Selector, nopTransform, scopes...) +} + +func (s *onedrive) Exclude(scopes ...[]OneDriveScope) { + appendExcludes(&s.Selector, nopTransform, scopes...) +} + +func (s *onedrive) Filter(scopes ...[]OneDriveScope) { + appendFilters(&s.Selector, nopTransform, scopes...) +} diff --git a/src/pkg/selectors/onedrive_test.go b/src/pkg/selectors/onedrive_test.go new file mode 100644 index 000000000..e8c361471 --- /dev/null +++ b/src/pkg/selectors/onedrive_test.go @@ -0,0 +1,72 @@ +package selectors + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type OnedriveSourceSuite struct { + suite.Suite +} + +func TestOnedriveSourceSuite(t *testing.T) { + suite.Run(t, new(OnedriveSourceSuite)) +} + +func (suite *OnedriveSourceSuite) TestNewOnedriveBackup() { + t := suite.T() + ob := NewOneDriveBackup() + assert.Equal(t, ob.Service, ServiceOneDrive) + assert.NotZero(t, ob.Scopes()) +} + +func (suite *OnedriveSourceSuite) TestToOnedriveBackup() { + t := suite.T() + ob := NewOneDriveBackup() + s := ob.Selector + ob, err := s.ToOneDriveBackup() + require.NoError(t, err) + assert.Equal(t, ob.Service, ServiceOneDrive) + assert.NotZero(t, ob.Scopes()) +} + +func (suite *OnedriveSourceSuite) TestOnedriveSelector_Users() { + t := suite.T() + sel := NewOneDriveBackup() + + const ( + u1 = "u1" + u2 = "u2" + ) + userScopes := sel.Users([]string{u1, u2}) + for _, scope := range userScopes { + // Scope value is either u1 or u2 + assert.Contains(t, []string{u1, u2}, scope[OneDriveUser.String()]) + } + + // Initialize the selector Include, Exclude, Filter + sel.Exclude(userScopes) + sel.Include(userScopes) + sel.Filter(userScopes) + + table := []struct { + name string + scopesToCheck []scope + }{ + {"Include Scopes", sel.Includes}, + {"Exclude Scopes", sel.Excludes}, + {"Filter Scopes", sel.Filters}, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + require.Equal(t, 2, len(test.scopesToCheck)) + for _, scope := range test.scopesToCheck { + // Scope value is either u1 or u2 + assert.Contains(t, []string{u1, u2}, scope[OneDriveUser.String()]) + } + }) + } +} diff --git a/src/pkg/selectors/onedrivecategory_string.go b/src/pkg/selectors/onedrivecategory_string.go new file mode 100644 index 000000000..65c65158b --- /dev/null +++ b/src/pkg/selectors/onedrivecategory_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=onedriveCategory"; DO NOT EDIT. + +package selectors + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[OneDriveCategoryUnknown-0] + _ = x[OneDriveUser-1] +} + +const _onedriveCategory_name = "OneDriveCategoryUnknownOneDriveUser" + +var _onedriveCategory_index = [...]uint8{0, 23, 35} + +func (i onedriveCategory) String() string { + if i < 0 || i >= onedriveCategory(len(_onedriveCategory_index)-1) { + return "onedriveCategory(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _onedriveCategory_name[_onedriveCategory_index[i]:_onedriveCategory_index[i+1]] +} diff --git a/src/pkg/selectors/selectors.go b/src/pkg/selectors/selectors.go index 0117a6622..c2fbb06e6 100644 --- a/src/pkg/selectors/selectors.go +++ b/src/pkg/selectors/selectors.go @@ -14,6 +14,7 @@ type service int const ( ServiceUnknown service = iota // Unknown Service ServiceExchange // Exchange + ServiceOneDrive // OneDrive ) var ErrorBadSelectorCast = errors.New("wrong selector service type")