corso/src/pkg/extensions/mock_extensions.go
Abhishek Pandey 83e56ed396
Integrate extensions into drive item reader (#3750)
<!-- PR description-->

* Integrates corso extensions into onedrive/sharepoint library item backup flows.
* Also includes integration tests for OD/SP, unit tests for collections.
* Includes a small fix for `rw *backupStreamReader Close()`

Remaining things which will be covered in later PRs:
* extension tests with incremental backups
* Observability related changes for extensions

---

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

- [ ]  Yes, it's included
- [x] 🕐 Yes, but in a later PR
- [ ]  No

#### Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* internal
#### Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
2023-07-06 23:01:18 +00:00

101 lines
1.9 KiB
Go

package extensions
import (
"context"
"errors"
"hash/crc32"
"io"
"sync/atomic"
"github.com/alcionai/clues"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/logger"
)
const (
KNumBytes = "NumBytes"
KCrc32 = "Crc32"
)
var _ io.ReadCloser = &MockExtension{}
type MockExtension struct {
NumBytes int64
Crc32 uint32
Info details.ItemInfo
ExtData *details.ExtensionData
InnerRc io.ReadCloser
Ctx context.Context
FailOnRead bool
FailOnClose bool
}
func (me *MockExtension) Read(p []byte) (int, error) {
if me.FailOnRead {
return 0, clues.New("mock read error")
}
n, err := me.InnerRc.Read(p)
if err != nil && !errors.Is(err, io.EOF) {
logger.CtxErr(me.Ctx, err).Error("inner read error")
return n, clues.Stack(err)
}
atomic.AddInt64(&me.NumBytes, int64(n))
me.Crc32 = crc32.Update(me.Crc32, crc32.IEEETable, p[:n])
if errors.Is(err, io.EOF) {
me.ExtData.Data[KNumBytes] = me.NumBytes
me.ExtData.Data[KCrc32] = me.Crc32
}
return n, err
}
func (me *MockExtension) Close() error {
if me.FailOnClose {
return clues.New("mock close error")
}
err := me.InnerRc.Close()
if err != nil {
return clues.Stack(err)
}
me.ExtData.Data[KNumBytes] = me.NumBytes
me.ExtData.Data[KCrc32] = me.Crc32
logger.Ctx(me.Ctx).Infow(
"mock extension closed",
KNumBytes, me.NumBytes, KCrc32, me.Crc32)
return nil
}
type MockItemExtensionFactory struct {
FailOnFactoryCreation bool
FailOnRead bool
FailOnClose bool
}
func (m *MockItemExtensionFactory) CreateItemExtension(
ctx context.Context,
rc io.ReadCloser,
info details.ItemInfo,
extData *details.ExtensionData,
) (io.ReadCloser, error) {
if m.FailOnFactoryCreation {
return nil, clues.New("factory error")
}
return &MockExtension{
Ctx: ctx,
InnerRc: rc,
Info: info,
ExtData: extData,
FailOnRead: m.FailOnRead,
FailOnClose: m.FailOnClose,
}, nil
}