Mark folder updated when an updated item is added (#1987)

## Description

If an item is updated, update the folder entries it belongs to. 

Also contains a minor refactor - unexport `FolderEntry` to `folderEntry`

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

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

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🐹 Trivial/Minor

## Issue(s)

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

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
Vaibhav Kamra 2022-12-29 15:41:04 -08:00 committed by GitHub
parent 5fec5ccd11
commit ad691148fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 219 additions and 122 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Folder entries in backup details now indicate whether an item in the hierarchy was updated
- Incremental backup support for Exchange ([#1777](https://github.com/alcionai/corso/issues/1777)). This is currently enabled by specifying the `--enable-incrementals` - Incremental backup support for Exchange ([#1777](https://github.com/alcionai/corso/issues/1777)). This is currently enabled by specifying the `--enable-incrementals`
with the `backup create` command. This functionality will be enabled by default in an upcoming release. with the `backup create` command. This functionality will be enabled by default in an upcoming release.
- Folder entries in backup details now include size and modified time for the hierarchy ([#1896](https://github.com/alcionai/corso/issues/1896)) - Folder entries in backup details now include size and modified time for the hierarchy ([#1896](https://github.com/alcionai/corso/issues/1896))

View File

@ -184,7 +184,11 @@ func (cp *corsoProgress) FinishedFile(relativePath string, err error) {
) )
folders := details.FolderEntriesForPath(parent) folders := details.FolderEntriesForPath(parent)
cp.deets.AddFoldersForItem(folders, *d.info) cp.deets.AddFoldersForItem(
folders,
*d.info,
true, // itemUpdated = true
)
} }
// Kopia interface function used as a callback when kopia finishes hashing a file. // Kopia interface function used as a callback when kopia finishes hashing a file.

View File

@ -515,18 +515,20 @@ func mergeDetails(
) )
} }
// TODO(ashmrtn): This may need updated if we start using this merge
// strategry for items that were cached in kopia.
itemUpdated := newPath.String() != rr.String()
deets.Add( deets.Add(
newPath.String(), newPath.String(),
newPath.ShortRef(), newPath.ShortRef(),
newPath.ToBuilder().Dir().ShortRef(), newPath.ToBuilder().Dir().ShortRef(),
// TODO(ashmrtn): This may need updated if we start using this merge itemUpdated,
// strategry for items that were cached in kopia.
newPath.String() != rr.String(),
item, item,
) )
folders := details.FolderEntriesForPath(newPath.ToBuilder().Dir()) folders := details.FolderEntriesForPath(newPath.ToBuilder().Dir())
deets.AddFoldersForItem(folders, item) deets.AddFoldersForItem(folders, item, itemUpdated)
// Track how many entries we added so that we know if we got them all when // Track how many entries we added so that we know if we got them all when
// we're done. // we're done.

View File

@ -14,10 +14,11 @@ import (
"github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/path"
) )
type FolderEntry struct { type folderEntry struct {
RepoRef string RepoRef string
ShortRef string ShortRef string
ParentRef string ParentRef string
Updated bool
Info ItemInfo Info ItemInfo
} }
@ -106,7 +107,7 @@ func (dm DetailsModel) Items() []*DetailsEntry {
type Builder struct { type Builder struct {
d Details d Details
mu sync.Mutex `json:"-"` mu sync.Mutex `json:"-"`
knownFolders map[string]FolderEntry `json:"-"` knownFolders map[string]folderEntry `json:"-"`
} }
func (b *Builder) Add(repoRef, shortRef, parentRef string, updated bool, info ItemInfo) { func (b *Builder) Add(repoRef, shortRef, parentRef string, updated bool, info ItemInfo) {
@ -130,13 +131,13 @@ func (b *Builder) Details() *Details {
// TODO(ashmrtn): If we never need to pre-populate the modified time of a folder // TODO(ashmrtn): If we never need to pre-populate the modified time of a folder
// we should just merge this with AddFoldersForItem, have Add call // we should just merge this with AddFoldersForItem, have Add call
// AddFoldersForItem, and unexport AddFoldersForItem. // AddFoldersForItem, and unexport AddFoldersForItem.
func FolderEntriesForPath(parent *path.Builder) []FolderEntry { func FolderEntriesForPath(parent *path.Builder) []folderEntry {
folders := []FolderEntry{} folders := []folderEntry{}
for len(parent.Elements()) > 0 { for len(parent.Elements()) > 0 {
nextParent := parent.Dir() nextParent := parent.Dir()
folders = append(folders, FolderEntry{ folders = append(folders, folderEntry{
RepoRef: parent.String(), RepoRef: parent.String(),
ShortRef: parent.ShortRef(), ShortRef: parent.ShortRef(),
ParentRef: nextParent.ShortRef(), ParentRef: nextParent.ShortRef(),
@ -156,12 +157,12 @@ func FolderEntriesForPath(parent *path.Builder) []FolderEntry {
// AddFoldersForItem adds entries for the given folders. It skips adding entries that // AddFoldersForItem adds entries for the given folders. It skips adding entries that
// have been added by previous calls. // have been added by previous calls.
func (b *Builder) AddFoldersForItem(folders []FolderEntry, itemInfo ItemInfo) { func (b *Builder) AddFoldersForItem(folders []folderEntry, itemInfo ItemInfo, updated bool) {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
if b.knownFolders == nil { if b.knownFolders == nil {
b.knownFolders = map[string]FolderEntry{} b.knownFolders = map[string]folderEntry{}
} }
for _, folder := range folders { for _, folder := range folders {
@ -180,6 +181,12 @@ func (b *Builder) AddFoldersForItem(folders []FolderEntry, itemInfo ItemInfo) {
folder.Info.Folder.Modified = itemModified folder.Info.Folder.Modified = itemModified
} }
// If the item being added was "updated" - propagate that to the
// folder entries
if updated {
folder.Updated = true
}
b.knownFolders[folder.ShortRef] = folder b.knownFolders[folder.ShortRef] = folder
} }
} }
@ -206,12 +213,13 @@ func (d *Details) add(repoRef, shortRef, parentRef string, updated bool, info It
} }
// addFolder adds an entry for the given folder. // addFolder adds an entry for the given folder.
func (d *Details) addFolder(folder FolderEntry) { func (d *Details) addFolder(folder folderEntry) {
d.Entries = append(d.Entries, DetailsEntry{ d.Entries = append(d.Entries, DetailsEntry{
RepoRef: folder.RepoRef, RepoRef: folder.RepoRef,
ShortRef: folder.ShortRef, ShortRef: folder.ShortRef,
ParentRef: folder.ParentRef, ParentRef: folder.ParentRef,
ItemInfo: folder.Info, ItemInfo: folder.Info,
Updated: folder.Updated,
}) })
} }

View File

@ -1,4 +1,4 @@
package details_test package details
import ( import (
"testing" "testing"
@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/path"
) )
@ -33,13 +32,13 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
table := []struct { table := []struct {
name string name string
entry details.DetailsEntry entry DetailsEntry
expectHs []string expectHs []string
expectVs []string expectVs []string
}{ }{
{ {
name: "no info", name: "no info",
entry: details.DetailsEntry{ entry: DetailsEntry{
RepoRef: "reporef", RepoRef: "reporef",
ShortRef: "deadbeef", ShortRef: "deadbeef",
}, },
@ -48,12 +47,12 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
}, },
{ {
name: "exchange event info", name: "exchange event info",
entry: details.DetailsEntry{ entry: DetailsEntry{
RepoRef: "reporef", RepoRef: "reporef",
ShortRef: "deadbeef", ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{ ItemInfo: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeEvent, ItemType: ExchangeEvent,
EventStart: now, EventStart: now,
EventEnd: now, EventEnd: now,
Organizer: "organizer", Organizer: "organizer",
@ -67,12 +66,12 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
}, },
{ {
name: "exchange contact info", name: "exchange contact info",
entry: details.DetailsEntry{ entry: DetailsEntry{
RepoRef: "reporef", RepoRef: "reporef",
ShortRef: "deadbeef", ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{ ItemInfo: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeContact, ItemType: ExchangeContact,
ContactName: "contactName", ContactName: "contactName",
}, },
}, },
@ -82,12 +81,12 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
}, },
{ {
name: "exchange mail info", name: "exchange mail info",
entry: details.DetailsEntry{ entry: DetailsEntry{
RepoRef: "reporef", RepoRef: "reporef",
ShortRef: "deadbeef", ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{ ItemInfo: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeMail, ItemType: ExchangeMail,
Sender: "sender", Sender: "sender",
Subject: "subject", Subject: "subject",
Received: now, Received: now,
@ -99,11 +98,11 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
}, },
{ {
name: "sharepoint info", name: "sharepoint info",
entry: details.DetailsEntry{ entry: DetailsEntry{
RepoRef: "reporef", RepoRef: "reporef",
ShortRef: "deadbeef", ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{ ItemInfo: ItemInfo{
SharePoint: &details.SharePointInfo{ SharePoint: &SharePointInfo{
ItemName: "itemName", ItemName: "itemName",
ParentPath: "parentPath", ParentPath: "parentPath",
Size: 1000, Size: 1000,
@ -118,11 +117,11 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
}, },
{ {
name: "oneDrive info", name: "oneDrive info",
entry: details.DetailsEntry{ entry: DetailsEntry{
RepoRef: "reporef", RepoRef: "reporef",
ShortRef: "deadbeef", ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{ ItemInfo: ItemInfo{
OneDrive: &details.OneDriveInfo{ OneDrive: &OneDriveInfo{
ItemName: "itemName", ItemName: "itemName",
ParentPath: "parentPath", ParentPath: "parentPath",
Size: 1000, Size: 1000,
@ -149,7 +148,7 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
var pathItemsTable = []struct { var pathItemsTable = []struct {
name string name string
ents []details.DetailsEntry ents []DetailsEntry
expectRefs []string expectRefs []string
}{ }{
{ {
@ -159,14 +158,14 @@ var pathItemsTable = []struct {
}, },
{ {
name: "single entry", name: "single entry",
ents: []details.DetailsEntry{ ents: []DetailsEntry{
{RepoRef: "abcde"}, {RepoRef: "abcde"},
}, },
expectRefs: []string{"abcde"}, expectRefs: []string{"abcde"},
}, },
{ {
name: "multiple entries", name: "multiple entries",
ents: []details.DetailsEntry{ ents: []DetailsEntry{
{RepoRef: "abcde"}, {RepoRef: "abcde"},
{RepoRef: "12345"}, {RepoRef: "12345"},
}, },
@ -174,13 +173,13 @@ var pathItemsTable = []struct {
}, },
{ {
name: "multiple entries with folder", name: "multiple entries with folder",
ents: []details.DetailsEntry{ ents: []DetailsEntry{
{RepoRef: "abcde"}, {RepoRef: "abcde"},
{RepoRef: "12345"}, {RepoRef: "12345"},
{ {
RepoRef: "deadbeef", RepoRef: "deadbeef",
ItemInfo: details.ItemInfo{ ItemInfo: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
DisplayName: "test folder", DisplayName: "test folder",
}, },
}, },
@ -193,8 +192,8 @@ var pathItemsTable = []struct {
func (suite *DetailsUnitSuite) TestDetailsModel_Path() { func (suite *DetailsUnitSuite) TestDetailsModel_Path() {
for _, test := range pathItemsTable { for _, test := range pathItemsTable {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
d := details.Details{ d := Details{
DetailsModel: details.DetailsModel{ DetailsModel: DetailsModel{
Entries: test.ents, Entries: test.ents,
}, },
} }
@ -206,8 +205,8 @@ func (suite *DetailsUnitSuite) TestDetailsModel_Path() {
func (suite *DetailsUnitSuite) TestDetailsModel_Items() { func (suite *DetailsUnitSuite) TestDetailsModel_Items() {
for _, test := range pathItemsTable { for _, test := range pathItemsTable {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
d := details.Details{ d := Details{
DetailsModel: details.DetailsModel{ DetailsModel: DetailsModel{
Entries: test.ents, Entries: test.ents,
}, },
} }
@ -227,8 +226,8 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
folderTimeOlderThanItem := time.Date(2022, 9, 21, 10, 0, 0, 0, time.UTC) folderTimeOlderThanItem := time.Date(2022, 9, 21, 10, 0, 0, 0, time.UTC)
folderTimeNewerThanItem := time.Date(2022, 11, 21, 10, 0, 0, 0, time.UTC) folderTimeNewerThanItem := time.Date(2022, 11, 21, 10, 0, 0, 0, time.UTC)
itemInfo := details.ItemInfo{ itemInfo := ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
@ -236,19 +235,19 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
table := []struct { table := []struct {
name string name string
folders []details.FolderEntry folders []folderEntry
expectedShortRefs []string expectedShortRefs []string
expectedFolderInfo map[string]details.FolderInfo expectedFolderInfo map[string]FolderInfo
}{ }{
{ {
name: "MultipleFolders", name: "MultipleFolders",
folders: []details.FolderEntry{ folders: []folderEntry{
{ {
RepoRef: "rr1", RepoRef: "rr1",
ShortRef: "sr1", ShortRef: "sr1",
ParentRef: "pr1", ParentRef: "pr1",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
Modified: folderTimeOlderThanItem, Modified: folderTimeOlderThanItem,
}, },
}, },
@ -257,28 +256,28 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
RepoRef: "rr2", RepoRef: "rr2",
ShortRef: "sr2", ShortRef: "sr2",
ParentRef: "pr2", ParentRef: "pr2",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
Modified: folderTimeNewerThanItem, Modified: folderTimeNewerThanItem,
}, },
}, },
}, },
}, },
expectedShortRefs: []string{"sr1", "sr2"}, expectedShortRefs: []string{"sr1", "sr2"},
expectedFolderInfo: map[string]details.FolderInfo{ expectedFolderInfo: map[string]FolderInfo{
"sr1": {Size: 20, Modified: itemTime}, "sr1": {Size: 20, Modified: itemTime},
"sr2": {Size: 20, Modified: folderTimeNewerThanItem}, "sr2": {Size: 20, Modified: folderTimeNewerThanItem},
}, },
}, },
{ {
name: "MultipleFoldersWithRepeats", name: "MultipleFoldersWithRepeats",
folders: []details.FolderEntry{ folders: []folderEntry{
{ {
RepoRef: "rr1", RepoRef: "rr1",
ShortRef: "sr1", ShortRef: "sr1",
ParentRef: "pr1", ParentRef: "pr1",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
Modified: folderTimeOlderThanItem, Modified: folderTimeOlderThanItem,
}, },
}, },
@ -287,8 +286,8 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
RepoRef: "rr2", RepoRef: "rr2",
ShortRef: "sr2", ShortRef: "sr2",
ParentRef: "pr2", ParentRef: "pr2",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
Modified: folderTimeOlderThanItem, Modified: folderTimeOlderThanItem,
}, },
}, },
@ -297,8 +296,8 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
RepoRef: "rr1", RepoRef: "rr1",
ShortRef: "sr1", ShortRef: "sr1",
ParentRef: "pr1", ParentRef: "pr1",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
Modified: folderTimeOlderThanItem, Modified: folderTimeOlderThanItem,
}, },
}, },
@ -307,15 +306,15 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
RepoRef: "rr3", RepoRef: "rr3",
ShortRef: "sr3", ShortRef: "sr3",
ParentRef: "pr3", ParentRef: "pr3",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{ Folder: &FolderInfo{
Modified: folderTimeNewerThanItem, Modified: folderTimeNewerThanItem,
}, },
}, },
}, },
}, },
expectedShortRefs: []string{"sr1", "sr2", "sr3"}, expectedShortRefs: []string{"sr1", "sr2", "sr3"},
expectedFolderInfo: map[string]details.FolderInfo{ expectedFolderInfo: map[string]FolderInfo{
// Two items were added // Two items were added
"sr1": {Size: 40, Modified: itemTime}, "sr1": {Size: 40, Modified: itemTime},
"sr2": {Size: 20, Modified: itemTime}, "sr2": {Size: 20, Modified: itemTime},
@ -325,8 +324,8 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
builder := details.Builder{} builder := Builder{}
builder.AddFoldersForItem(test.folders, itemInfo) builder.AddFoldersForItem(test.folders, itemInfo, true)
deets := builder.Details() deets := builder.Details()
assert.Len(t, deets.Entries, len(test.expectedShortRefs)) assert.Len(t, deets.Entries, len(test.expectedShortRefs))
@ -339,49 +338,132 @@ func (suite *DetailsUnitSuite) TestDetails_AddFolders() {
} }
} }
func (suite *DetailsUnitSuite) TestDetails_AddFoldersUpdate() {
itemInfo := ItemInfo{
Exchange: &ExchangeInfo{},
}
table := []struct {
name string
folders []folderEntry
itemUpdated bool
expectedFolderUpdatedValue map[string]bool
}{
{
name: "ItemNotUpdated_NoChange",
folders: []folderEntry{
{
RepoRef: "rr1",
ShortRef: "sr1",
ParentRef: "pr1",
Info: ItemInfo{
Folder: &FolderInfo{},
},
Updated: true,
},
{
RepoRef: "rr2",
ShortRef: "sr2",
ParentRef: "pr2",
Info: ItemInfo{
Folder: &FolderInfo{},
},
},
},
itemUpdated: false,
expectedFolderUpdatedValue: map[string]bool{
"sr1": true,
"sr2": false,
},
},
{
name: "ItemUpdated",
folders: []folderEntry{
{
RepoRef: "rr1",
ShortRef: "sr1",
ParentRef: "pr1",
Info: ItemInfo{
Folder: &FolderInfo{},
},
},
{
RepoRef: "rr2",
ShortRef: "sr2",
ParentRef: "pr2",
Info: ItemInfo{
Folder: &FolderInfo{},
},
},
},
itemUpdated: true,
expectedFolderUpdatedValue: map[string]bool{
"sr1": true,
"sr2": true,
},
},
}
for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) {
builder := Builder{}
builder.AddFoldersForItem(test.folders, itemInfo, test.itemUpdated)
deets := builder.Details()
assert.Len(t, deets.Entries, len(test.expectedFolderUpdatedValue))
for _, e := range deets.Entries {
assert.Equalf(
t,
test.expectedFolderUpdatedValue[e.ShortRef],
e.Updated, "%s updated value incorrect",
e.ShortRef)
}
})
}
}
func (suite *DetailsUnitSuite) TestDetails_AddFoldersDifferentServices() { func (suite *DetailsUnitSuite) TestDetails_AddFoldersDifferentServices() {
itemTime := time.Date(2022, 10, 21, 10, 0, 0, 0, time.UTC) itemTime := time.Date(2022, 10, 21, 10, 0, 0, 0, time.UTC)
table := []struct { table := []struct {
name string name string
item details.ItemInfo item ItemInfo
expectedFolderInfo details.FolderInfo expectedFolderInfo FolderInfo
}{ }{
{ {
name: "Exchange", name: "Exchange",
item: details.ItemInfo{ item: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
}, },
expectedFolderInfo: details.FolderInfo{ expectedFolderInfo: FolderInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
}, },
{ {
name: "OneDrive", name: "OneDrive",
item: details.ItemInfo{ item: ItemInfo{
OneDrive: &details.OneDriveInfo{ OneDrive: &OneDriveInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
}, },
expectedFolderInfo: details.FolderInfo{ expectedFolderInfo: FolderInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
}, },
{ {
name: "SharePoint", name: "SharePoint",
item: details.ItemInfo{ item: ItemInfo{
SharePoint: &details.SharePointInfo{ SharePoint: &SharePointInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
}, },
expectedFolderInfo: details.FolderInfo{ expectedFolderInfo: FolderInfo{
Size: 20, Size: 20,
Modified: itemTime, Modified: itemTime,
}, },
@ -389,17 +471,17 @@ func (suite *DetailsUnitSuite) TestDetails_AddFoldersDifferentServices() {
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
folderEntry := details.FolderEntry{ folder := folderEntry{
RepoRef: "rr1", RepoRef: "rr1",
ShortRef: "sr1", ShortRef: "sr1",
ParentRef: "pr1", ParentRef: "pr1",
Info: details.ItemInfo{ Info: ItemInfo{
Folder: &details.FolderInfo{}, Folder: &FolderInfo{},
}, },
} }
builder := details.Builder{} builder := Builder{}
builder.AddFoldersForItem([]details.FolderEntry{folderEntry}, test.item) builder.AddFoldersForItem([]folderEntry{folder}, test.item, true)
deets := builder.Details() deets := builder.Details()
require.Len(t, deets.Entries, 1) require.Len(t, deets.Entries, 1)
@ -469,92 +551,92 @@ func (suite *DetailsUnitSuite) TestUpdateItem() {
table := []struct { table := []struct {
name string name string
input details.ItemInfo input ItemInfo
newPath path.Path newPath path.Path
errCheck assert.ErrorAssertionFunc errCheck assert.ErrorAssertionFunc
expectedItem details.ItemInfo expectedItem ItemInfo
}{ }{
{ {
name: "ExchangeEventNoChange", name: "ExchangeEventNoChange",
input: details.ItemInfo{ input: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeEvent, ItemType: ExchangeEvent,
}, },
}, },
errCheck: assert.NoError, errCheck: assert.NoError,
expectedItem: details.ItemInfo{ expectedItem: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeEvent, ItemType: ExchangeEvent,
}, },
}, },
}, },
{ {
name: "ExchangeContactNoChange", name: "ExchangeContactNoChange",
input: details.ItemInfo{ input: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeContact, ItemType: ExchangeContact,
}, },
}, },
errCheck: assert.NoError, errCheck: assert.NoError,
expectedItem: details.ItemInfo{ expectedItem: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeContact, ItemType: ExchangeContact,
}, },
}, },
}, },
{ {
name: "ExchangeMailNoChange", name: "ExchangeMailNoChange",
input: details.ItemInfo{ input: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeMail, ItemType: ExchangeMail,
}, },
}, },
errCheck: assert.NoError, errCheck: assert.NoError,
expectedItem: details.ItemInfo{ expectedItem: ItemInfo{
Exchange: &details.ExchangeInfo{ Exchange: &ExchangeInfo{
ItemType: details.ExchangeMail, ItemType: ExchangeMail,
}, },
}, },
}, },
{ {
name: "OneDrive", name: "OneDrive",
input: details.ItemInfo{ input: ItemInfo{
OneDrive: &details.OneDriveInfo{ OneDrive: &OneDriveInfo{
ItemType: details.OneDriveItem, ItemType: OneDriveItem,
ParentPath: folder1, ParentPath: folder1,
}, },
}, },
newPath: newOneDrivePath, newPath: newOneDrivePath,
errCheck: assert.NoError, errCheck: assert.NoError,
expectedItem: details.ItemInfo{ expectedItem: ItemInfo{
OneDrive: &details.OneDriveInfo{ OneDrive: &OneDriveInfo{
ItemType: details.OneDriveItem, ItemType: OneDriveItem,
ParentPath: folder2, ParentPath: folder2,
}, },
}, },
}, },
{ {
name: "SharePoint", name: "SharePoint",
input: details.ItemInfo{ input: ItemInfo{
SharePoint: &details.SharePointInfo{ SharePoint: &SharePointInfo{
ItemType: details.SharePointItem, ItemType: SharePointItem,
ParentPath: folder1, ParentPath: folder1,
}, },
}, },
newPath: newOneDrivePath, newPath: newOneDrivePath,
errCheck: assert.NoError, errCheck: assert.NoError,
expectedItem: details.ItemInfo{ expectedItem: ItemInfo{
SharePoint: &details.SharePointInfo{ SharePoint: &SharePointInfo{
ItemType: details.SharePointItem, ItemType: SharePointItem,
ParentPath: folder2, ParentPath: folder2,
}, },
}, },
}, },
{ {
name: "OneDriveBadPath", name: "OneDriveBadPath",
input: details.ItemInfo{ input: ItemInfo{
OneDrive: &details.OneDriveInfo{ OneDrive: &OneDriveInfo{
ItemType: details.OneDriveItem, ItemType: OneDriveItem,
ParentPath: folder1, ParentPath: folder1,
}, },
}, },
@ -563,9 +645,9 @@ func (suite *DetailsUnitSuite) TestUpdateItem() {
}, },
{ {
name: "SharePointBadPath", name: "SharePointBadPath",
input: details.ItemInfo{ input: ItemInfo{
SharePoint: &details.SharePointInfo{ SharePoint: &SharePointInfo{
ItemType: details.SharePointItem, ItemType: SharePointItem,
ParentPath: folder1, ParentPath: folder1,
}, },
}, },
@ -577,7 +659,7 @@ func (suite *DetailsUnitSuite) TestUpdateItem() {
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
item := test.input item := test.input
err := details.UpdateItem(&item, test.newPath) err := UpdateItem(&item, test.newPath)
test.errCheck(t, err) test.errCheck(t, err)
if err != nil { if err != nil {