diff --git a/src/pkg/err/err.go b/src/pkg/err/err.go new file mode 100644 index 000000000..8cb2a3df8 --- /dev/null +++ b/src/pkg/err/err.go @@ -0,0 +1,45 @@ +package err + +import ( + "errors" + + "github.com/alcionai/corso/src/internal/connector/graph" + "github.com/alcionai/corso/src/pkg/repository" +) + +// expose enums, rather than errors, for Is checks. The enum should +// map to a specific internal error that can be used for the actual +// errors.Is comparison. +type errEnum string + +const ( + RepoAlreadyExists errEnum = "repository-already-exists" + BackupNotFound errEnum = "backup-not-found" + ServiceNotEnabled errEnum = "service-not-enabled" +) + +// map of enums to errors. We might want to re-use an enum for multiple +// internal errors (ex: "ServiceNotEnabled" may exist in both graph and +// non-graph producers). +var internalToExternal = map[errEnum][]error{ + RepoAlreadyExists: {repository.ErrorRepoAlreadyExists}, + BackupNotFound: {repository.ErrorBackupNotFound}, + ServiceNotEnabled: {graph.ErrServiceNotEnabled}, +} + +// Is checks if the provided error contains an internal error that matches +// the public error category. +func Is(err error, enum errEnum) bool { + esl, ok := internalToExternal[enum] + if !ok { + return false + } + + for _, e := range esl { + if errors.Is(err, e) { + return true + } + } + + return false +} diff --git a/src/pkg/err/err_test.go b/src/pkg/err/err_test.go new file mode 100644 index 000000000..9b3758c76 --- /dev/null +++ b/src/pkg/err/err_test.go @@ -0,0 +1,37 @@ +package err + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + + "github.com/alcionai/corso/src/internal/connector/graph" + "github.com/alcionai/corso/src/internal/tester" + "github.com/alcionai/corso/src/pkg/repository" +) + +type ErrUnitSuite struct { + tester.Suite +} + +func TestErrUnitSuite(t *testing.T) { + suite.Run(t, &ErrUnitSuite{Suite: tester.NewUnitSuite(t)}) +} + +func (suite *ErrUnitSuite) TestIs() { + table := []struct { + is errEnum + input error + }{ + {RepoAlreadyExists, repository.ErrorRepoAlreadyExists}, + {BackupNotFound, repository.ErrorBackupNotFound}, + {ServiceNotEnabled, graph.ErrServiceNotEnabled}, + } + for _, test := range table { + suite.Run(string(test.is), func() { + assert.True(suite.T(), Is(test.input, test.is)) + assert.False(suite.T(), Is(assert.AnError, test.is)) + }) + } +}