Exchange multiuser restore and backup tests (#1195)

## Description

Basic smoke tests to ensure multi-user restore and backup work properly. Will need updated to add OneDrive tests later on once the OneDrive test pattern is merged

## 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
* #1186 

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-10-24 11:36:26 -07:00 committed by GitHub
parent 7c027564c1
commit 14bd16f978
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -469,6 +470,89 @@ func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() {
} }
} }
func runRestoreBackupTest(
t *testing.T,
test restoreBackupInfo,
tenant string,
users []string,
) {
var (
collections []data.Collection
expectedData = map[string]map[string][]byte{}
totalItems = 0
// Get a dest per test so they're independent.
dest = tester.DefaultTestRestoreDestination()
)
ctx, flush := tester.NewContext()
defer flush()
for _, user := range users {
numItems, userCollections, userExpectedData := collectionsForInfo(
t,
test.service,
tenant,
user,
dest,
test.collections,
)
collections = append(collections, userCollections...)
totalItems += numItems
for k, v := range userExpectedData {
expectedData[k] = v
}
}
t.Logf(
"Restoring collections to %s for user(s) %v\n",
dest.ContainerName,
users,
)
start := time.Now()
restoreGC := loadConnector(ctx, t)
restoreSel := getSelectorWith(test.service)
deets, err := restoreGC.RestoreDataCollections(ctx, restoreSel, dest, collections)
require.NoError(t, err)
assert.NotNil(t, deets)
status := restoreGC.AwaitStatus()
runTime := time.Now().Sub(start)
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful")
assert.Len(
t,
deets.Entries,
totalItems,
"details entries contains same item count as total successful items restored")
t.Logf("Restore complete in %v\n", runTime)
// Run a backup and compare its output with what we put in.
backupGC := loadConnector(ctx, t)
backupSel := backupSelectorForExpected(t, expectedData)
t.Logf("Selective backup of %s\n", backupSel)
start = time.Now()
dcs, err := backupGC.DataCollections(ctx, backupSel)
require.NoError(t, err)
t.Logf("Backup enumeration complete in %v\n", time.Now().Sub(start))
// Pull the data prior to waiting for the status as otherwise it will
// deadlock.
checkCollections(t, totalItems, expectedData, dcs)
status = backupGC.AwaitStatus()
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful")
}
func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
bodyText := "This email has some text. However, all the text is on the same line." bodyText := "This email has some text. However, all the text is on the same line."
subjectText := "Test message for restore" subjectText := "Test message for restore"
@ -689,56 +773,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
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) {
ctx, flush := tester.NewContext() runRestoreBackupTest(t, test, suite.connector.tenant, []string{suite.user})
defer flush()
// Get a dest per test so they're independent.
dest := tester.DefaultTestRestoreDestination()
totalItems, collections, expectedData := collectionsForInfo(
t,
test.service,
suite.connector.tenant,
suite.user,
dest,
test.collections,
)
t.Logf("Restoring collections to %s\n", dest.ContainerName)
restoreGC := loadConnector(ctx, t)
restoreSel := getSelectorWith(test.service)
deets, err := restoreGC.RestoreDataCollections(ctx, restoreSel, dest, collections)
require.NoError(t, err)
assert.NotNil(t, deets)
status := restoreGC.AwaitStatus()
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful")
assert.Equal(
t, totalItems, len(deets.Entries),
"details entries contains same item count as total successful items restored")
t.Logf("Restore complete\n")
// Run a backup and compare its output with what we put in.
backupGC := loadConnector(ctx, t)
backupSel := backupSelectorForExpected(t, expectedData)
t.Logf("Selective backup of %s\n", backupSel)
dcs, err := backupGC.DataCollections(ctx, backupSel)
require.NoError(t, err)
t.Logf("Backup enumeration complete\n")
// Pull the data prior to waiting for the status as otherwise it will
// deadlock.
checkCollections(t, totalItems, expectedData, dcs)
status = backupGC.AwaitStatus()
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful")
}) })
} }
} }
@ -876,3 +911,113 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
}) })
} }
} }
func (suite *GraphConnectorIntegrationSuite) TestMultiuserRestoreAndBackup() {
bodyText := "This email has some text. However, all the text is on the same line."
subjectText := "Test message for restore"
users := []string{
suite.user,
tester.SecondaryM365UserID(suite.T()),
}
table := []restoreBackupInfo{
{
name: "Email",
service: path.ExchangeService,
collections: []colInfo{
{
pathElements: []string{"Inbox"},
category: path.EmailCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockMessageWithBodyBytes(
subjectText+"-1",
bodyText+" 1.",
bodyText+" 1.",
),
lookupKey: subjectText + "-1",
},
},
},
{
pathElements: []string{"Archive"},
category: path.EmailCategory,
items: []itemInfo{
{
name: "someencodeditemID2",
data: mockconnector.GetMockMessageWithBodyBytes(
subjectText+"-2",
bodyText+" 2.",
bodyText+" 2.",
),
lookupKey: subjectText + "-2",
},
},
},
},
},
{
name: "Contacts",
service: path.ExchangeService,
collections: []colInfo{
{
pathElements: []string{"Work"},
category: path.ContactsCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockContactBytes("Ghimley"),
lookupKey: "Ghimley",
},
},
},
{
pathElements: []string{"Personal"},
category: path.ContactsCategory,
items: []itemInfo{
{
name: "someencodeditemID2",
data: mockconnector.GetMockContactBytes("Irgot"),
lookupKey: "Irgot",
},
},
},
},
},
{
name: "Events",
service: path.ExchangeService,
collections: []colInfo{
{
pathElements: []string{"Work"},
category: path.EventsCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockEventWithSubjectBytes("Ghimley"),
lookupKey: "Ghimley",
},
},
},
{
pathElements: []string{"Personal"},
category: path.EventsCategory,
items: []itemInfo{
{
name: "someencodeditemID2",
data: mockconnector.GetMockEventWithSubjectBytes("Irgot"),
lookupKey: "Irgot",
},
},
},
},
},
}
for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) {
runRestoreBackupTest(t, test, suite.connector.tenant, users)
})
}
}