Restore tests for contacts (#989)

## Description

Test restoring a single contacts folder and multiple contacts folders. This tests that items from different folders can be restored, but not that items from multiple folders can be backed up (because the restore colocates into a single folder)

## Type of change

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

## Issue(s)

* #913 

merge after
* #986 

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-09-29 17:32:28 -07:00 committed by GitHub
parent 1a188ce657
commit 0cba7a402c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 222 additions and 46 deletions

View File

@ -160,6 +160,90 @@ func checkMessage(
assert.Equal(t, expected.GetUniqueBody(), got.GetUniqueBody(), "UniqueBody") assert.Equal(t, expected.GetUniqueBody(), got.GetUniqueBody(), "UniqueBody")
} }
func checkContact(
t *testing.T,
expected models.Contactable,
got models.Contactable,
) {
emptyOrEqual(t, expected.GetAssistantName(), got.GetAssistantName(), "AssistantName")
emptyOrEqual(t, expected.GetBirthday(), got.GetBirthday(), "Birthday")
assert.Equal(t, expected.GetBusinessAddress(), got.GetBusinessAddress())
emptyOrEqual(t, expected.GetBusinessHomePage(), got.GetBusinessHomePage(), "BusinessHomePage")
assert.Equal(t, expected.GetBusinessPhones(), got.GetBusinessPhones())
assert.Equal(t, expected.GetCategories(), got.GetCategories())
// Skip ChangeKey as it's tied to this specific instance of the item.
assert.Equal(t, expected.GetChildren(), got.GetChildren())
emptyOrEqual(t, expected.GetCompanyName(), got.GetCompanyName(), "CompanyName")
// Skip CreatedDateTime as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetDepartment(), got.GetDepartment(), "Department")
emptyOrEqual(t, expected.GetDisplayName(), got.GetDisplayName(), "DisplayName")
assert.Equal(t, expected.GetEmailAddresses(), got.GetEmailAddresses())
emptyOrEqual(t, expected.GetFileAs(), got.GetFileAs(), "FileAs")
emptyOrEqual(t, expected.GetGeneration(), got.GetGeneration(), "Generation")
emptyOrEqual(t, expected.GetGivenName(), got.GetGivenName(), "GivenName")
assert.Equal(t, expected.GetHomeAddress(), got.GetHomeAddress())
assert.Equal(t, expected.GetHomePhones(), got.GetHomePhones())
// Skip CreatedDateTime as it's tied to this specific instance of the item.
assert.Equal(t, expected.GetImAddresses(), got.GetImAddresses())
emptyOrEqual(t, expected.GetInitials(), got.GetInitials(), "Initials")
emptyOrEqual(t, expected.GetJobTitle(), got.GetJobTitle(), "JobTitle")
// Skip CreatedDateTime as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetManager(), got.GetManager(), "Manager")
emptyOrEqual(t, expected.GetMiddleName(), got.GetMiddleName(), "MiddleName")
emptyOrEqual(t, expected.GetMobilePhone(), got.GetMobilePhone(), "MobilePhone")
emptyOrEqual(t, expected.GetNickName(), got.GetNickName(), "NickName")
emptyOrEqual(t, expected.GetOfficeLocation(), got.GetOfficeLocation(), "OfficeLocation")
assert.Equal(t, expected.GetOtherAddress(), got.GetOtherAddress())
// Skip ParentFolderId as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetPersonalNotes(), got.GetPersonalNotes(), "PersonalNotes")
assert.Equal(t, expected.GetPhoto(), got.GetPhoto())
emptyOrEqual(t, expected.GetProfession(), got.GetProfession(), "Profession")
emptyOrEqual(t, expected.GetSpouseName(), got.GetSpouseName(), "SpouseName")
emptyOrEqual(t, expected.GetSurname(), got.GetSurname(), "Surname")
emptyOrEqual(t, expected.GetTitle(), got.GetTitle(), "Title")
emptyOrEqual(t, expected.GetYomiCompanyName(), got.GetYomiCompanyName(), "YomiCompanyName")
emptyOrEqual(t, expected.GetYomiGivenName(), got.GetYomiGivenName(), "YomiGivenName")
emptyOrEqual(t, expected.GetYomiSurname(), got.GetYomiSurname(), "YomiSurname")
}
func compareExchangeEmail( func compareExchangeEmail(
t *testing.T, t *testing.T,
expected map[string][]byte, expected map[string][]byte,
@ -186,6 +270,32 @@ func compareExchangeEmail(
checkMessage(t, expectedMessage, itemMessage) checkMessage(t, expectedMessage, itemMessage)
} }
func compareExchangeContact(
t *testing.T,
expected map[string][]byte,
item data.Stream,
) {
itemData, err := io.ReadAll(item.ToReader())
if !assert.NoError(t, err, "reading collection item: %s", item.UUID()) {
return
}
itemContact, err := support.CreateContactFromBytes(itemData)
if !assert.NoError(t, err, "deserializing backed up contact") {
return
}
expectedBytes, ok := expected[*itemContact.GetMiddleName()]
if !assert.True(t, ok, "unexpected item with middle name %q", *itemContact.GetMiddleName()) {
return
}
expectedContact, err := support.CreateContactFromBytes(expectedBytes)
assert.NoError(t, err, "deserializing source contact")
checkContact(t, expectedContact, itemContact)
}
func compareItem( func compareItem(
t *testing.T, t *testing.T,
expected map[string][]byte, expected map[string][]byte,
@ -198,6 +308,8 @@ func compareItem(
switch category { switch category {
case path.EmailCategory: case path.EmailCategory:
compareExchangeEmail(t, expected, item) compareExchangeEmail(t, expected, item)
case path.ContactsCategory:
compareExchangeContact(t, expected, item)
default: default:
assert.FailNowf(t, "unexpected Exchange category: %s", category.String()) assert.FailNowf(t, "unexpected Exchange category: %s", category.String())
} }
@ -295,13 +407,17 @@ func collectionsForInfo(
false, false,
) )
expectedData[baseDestPath.String()] = make(map[string][]byte, len(info.items)) baseExpected := expectedData[baseDestPath.String()]
if baseExpected == nil {
expectedData[baseDestPath.String()] = make(map[string][]byte, len(info.items))
baseExpected = expectedData[baseDestPath.String()]
}
for i := 0; i < len(info.items); i++ { for i := 0; i < len(info.items); i++ {
c.Names[i] = info.items[i].name c.Names[i] = info.items[i].name
c.Data[i] = info.items[i].data c.Data[i] = info.items[i].data
expectedData[baseDestPath.String()][info.items[i].lookupKey] = info.items[i].data baseExpected[info.items[i].lookupKey] = info.items[i].data
} }
collections = append(collections, c) collections = append(collections, c)

View File

@ -367,42 +367,6 @@ func (suite *GraphConnectorIntegrationSuite) TestCreateAndDeleteCalendar() {
} }
} }
// TODO(ashmrtn): Merge this with the below once we get comparison logic for
// contacts.
func (suite *GraphConnectorIntegrationSuite) TestRestoreContact() {
t := suite.T()
sel := selectors.NewExchangeRestore()
fullpath, err := path.Builder{}.Append("testing").
ToDataLayerExchangePathForCategory(
suite.connector.tenant,
suite.user,
path.ContactsCategory,
false,
)
require.NoError(t, err)
aPath, err := path.Builder{}.Append("validator").ToDataLayerExchangePathForCategory(
suite.connector.tenant,
suite.user,
path.ContactsCategory,
false,
)
require.NoError(t, err)
dcs := mockconnector.NewMockContactCollection(fullpath, 3)
two := mockconnector.NewMockContactCollection(aPath, 2)
collections := []data.Collection{dcs, two}
ctx := context.Background()
connector := loadConnector(ctx, suite.T())
dest := control.DefaultRestoreDestination(common.SimpleDateTimeFormat)
err = connector.RestoreDataCollections(ctx, sel.Selector, dest, collections)
assert.NoError(suite.T(), err)
value := connector.AwaitStatus()
assert.Equal(t, value.FolderCount, 1)
suite.T().Log(value.String())
}
func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() { func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() {
dest := control.DefaultRestoreDestination(common.SimpleDateTimeFormatOneDrive) dest := control.DefaultRestoreDestination(common.SimpleDateTimeFormatOneDrive)
table := []struct { table := []struct {
@ -460,14 +424,16 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
subjectText := "Test message for restore" subjectText := "Test message for restore"
table := []struct { table := []struct {
name string name string
service path.ServiceType service path.ServiceType
collections []colInfo collections []colInfo
backupSelFunc func(dest control.RestoreDestination, backupUser string) selectors.Selector backupSelFunc func(dest control.RestoreDestination, backupUser string) selectors.Selector
expectedRestoreFolders int
}{ }{
{ {
name: "MultipleEmailsSingleFolder", name: "MultipleEmailsSingleFolder",
service: path.ExchangeService, service: path.ExchangeService,
expectedRestoreFolders: 1,
collections: []colInfo{ collections: []colInfo{
{ {
pathElements: []string{"Inbox"}, pathElements: []string{"Inbox"},
@ -509,6 +475,100 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
[]string{dest.ContainerName}, []string{dest.ContainerName},
)) ))
return backupSel.Selector
},
},
{
name: "MultipleContactsSingleFolder",
service: path.ExchangeService,
expectedRestoreFolders: 1,
collections: []colInfo{
{
pathElements: []string{"Contacts"},
category: path.ContactsCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockContactBytes("Ghimley"),
lookupKey: "Ghimley",
},
{
name: "someencodeditemID2",
data: mockconnector.GetMockContactBytes("Irgot"),
lookupKey: "Irgot",
},
{
name: "someencodeditemID3",
data: mockconnector.GetMockContactBytes("Jannes"),
lookupKey: "Jannes",
},
},
},
},
// TODO(ashmrtn): Generalize this once we know the path transforms that
// occur during restore.
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
backupSel := selectors.NewExchangeBackup()
backupSel.Include(backupSel.ContactFolders(
[]string{backupUser},
[]string{dest.ContainerName},
))
return backupSel.Selector
},
},
{
name: "MultipleContactsMutlipleFolders",
service: path.ExchangeService,
expectedRestoreFolders: 1,
collections: []colInfo{
{
pathElements: []string{"Work"},
category: path.ContactsCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockContactBytes("Ghimley"),
lookupKey: "Ghimley",
},
{
name: "someencodeditemID2",
data: mockconnector.GetMockContactBytes("Irgot"),
lookupKey: "Irgot",
},
{
name: "someencodeditemID3",
data: mockconnector.GetMockContactBytes("Jannes"),
lookupKey: "Jannes",
},
},
},
{
pathElements: []string{"Personal"},
category: path.ContactsCategory,
items: []itemInfo{
{
name: "someencodeditemID4",
data: mockconnector.GetMockContactBytes("Argon"),
lookupKey: "Argon",
},
{
name: "someencodeditemID5",
data: mockconnector.GetMockContactBytes("Bernard"),
lookupKey: "Bernard",
},
},
},
},
// TODO(ashmrtn): Generalize this once we know the path transforms that
// occur during restore.
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
backupSel := selectors.NewExchangeBackup()
backupSel.Include(backupSel.ContactFolders(
[]string{backupUser},
[]string{dest.ContainerName},
))
return backupSel.Selector return backupSel.Selector
}, },
}, },
@ -537,7 +597,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
require.NoError(t, err) require.NoError(t, err)
status := restoreGC.AwaitStatus() status := restoreGC.AwaitStatus()
assert.Equal(t, len(test.collections), status.FolderCount, "status.FolderCount") assert.Equal(t, test.expectedRestoreFolders, status.FolderCount, "status.FolderCount")
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount") assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful") assert.Equal(t, totalItems, status.Successful, "status.Successful")
@ -559,7 +619,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
checkCollections(t, totalItems, expectedData, dcs) checkCollections(t, totalItems, expectedData, dcs)
status = backupGC.AwaitStatus() status = backupGC.AwaitStatus()
assert.Equal(t, len(test.collections), status.FolderCount, "status.FolderCount") assert.Equal(t, test.expectedRestoreFolders, status.FolderCount, "status.FolderCount")
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount") assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful") assert.Equal(t, totalItems, status.Successful, "status.Successful")
}) })