corso/src/internal/operations/helpers_test.go
Keepers f2bf0ee685
introduce fail-after-recovery option (#3005)
While fail-fast and best-effort make for good
categories at the extreme ends of error handling, 
we keep finding outselves wanting to operate
in a middle ground.  This change introduces a new
error handling category: FailAfterRecovery.  This
option tells corso to complete as much of its
process as it can, even if it recovers from errors.
But at the end of processing, if it recovered from
any errors, an error is returned for the operation.

This behavior is the new failure handling default,
instead of failFast.

---

#### Does this PR need a docs update or release note?

- [x]  No

#### Type of change

- [x] 🌻 Feature

#### Test Plan

- [x] 💪 Manual
- [x]  Unit test
2023-04-01 00:43:52 +00:00

103 lines
2.2 KiB
Go

package operations
import (
"testing"
"github.com/stretchr/testify/assert"
"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/fault"
)
type HelpersUnitSuite struct {
tester.Suite
}
func TestHelpersUnitSuite(t *testing.T) {
suite.Run(t, &HelpersUnitSuite{Suite: tester.NewUnitSuite(t)})
}
func (suite *HelpersUnitSuite) TestFinalizeErrorHandling() {
table := []struct {
name string
errs func() *fault.Bus
opts control.Options
expectErr assert.ErrorAssertionFunc
}{
{
name: "no errors",
errs: func() *fault.Bus {
return fault.New(false)
},
opts: control.Options{
FailureHandling: control.FailAfterRecovery,
},
expectErr: assert.NoError,
},
{
name: "already failed",
errs: func() *fault.Bus {
fn := fault.New(false)
fn.Fail(assert.AnError)
return fn
},
opts: control.Options{
FailureHandling: control.FailAfterRecovery,
},
expectErr: assert.Error,
},
{
name: "best effort",
errs: func() *fault.Bus {
fn := fault.New(false)
fn.AddRecoverable(assert.AnError)
return fn
},
opts: control.Options{
FailureHandling: control.BestEffort,
},
expectErr: assert.NoError,
},
{
name: "recoverable errors produce hard fail",
errs: func() *fault.Bus {
fn := fault.New(false)
fn.AddRecoverable(assert.AnError)
return fn
},
opts: control.Options{
FailureHandling: control.FailAfterRecovery,
},
expectErr: assert.Error,
},
{
name: "multiple recoverable errors produce hard fail",
errs: func() *fault.Bus {
fn := fault.New(false)
fn.AddRecoverable(assert.AnError)
fn.AddRecoverable(assert.AnError)
fn.AddRecoverable(assert.AnError)
return fn
},
opts: control.Options{
FailureHandling: control.FailAfterRecovery,
},
expectErr: assert.Error,
},
}
for _, test := range table {
suite.Run(test.name, func() {
ctx, flush := tester.NewContext()
defer flush()
t := suite.T()
errs := test.errs()
finalizeErrorHandling(ctx, test.opts, errs, "test")
test.expectErr(t, errs.Failure())
})
}
}