From 640dfcf9679ce564724f41bc843411e5c54ba18c Mon Sep 17 00:00:00 2001 From: Keepers <104464746+ryanfkeepers@users.noreply.github.com> Date: Tue, 2 Aug 2022 13:13:23 -0600 Subject: [PATCH] derive test userID from test config (#465) In order to both maintain control of test env data, as well as ensure open-source users are able to run the integration tests on personal account data, the test user must be derived from the test configuration, rather than hardcoded within the tests. --- .../connector/graph_connector_test.go | 16 ++++++---- .../mockconnector/mock_data_collection.go | 8 ++++- src/internal/operations/backup_test.go | 5 ++-- src/internal/operations/restore_test.go | 12 ++++---- src/internal/tester/account.go | 2 +- src/internal/tester/config.go | 29 ++++++++++++++++++- src/internal/tester/users.go | 18 ++++++++++++ 7 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 src/internal/tester/users.go diff --git a/src/internal/connector/graph_connector_test.go b/src/internal/connector/graph_connector_test.go index 9a8974ed3..925ef6faa 100644 --- a/src/internal/connector/graph_connector_test.go +++ b/src/internal/connector/graph_connector_test.go @@ -61,8 +61,10 @@ func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_setTenantUsers() } func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_ExchangeDataCollection() { + userID, err := tester.M365UserID() + require.NoError(suite.T(), err) sel := selectors.NewExchangeBackup() - sel.Include(sel.Users([]string{"lidiah@8qzvrj.onmicrosoft.com"})) + sel.Include(sel.Users([]string{userID})) collectionList, err := suite.connector.ExchangeDataCollection(context.Background(), sel.Selector) assert.NotNil(suite.T(), collectionList, "collection list") assert.Nil(suite.T(), err) @@ -102,13 +104,14 @@ func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_restoreMessages( // TestGraphConnector_CreateAndDeleteFolder ensures msgraph application has the ability // to create and remove folders within the tenant func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_CreateAndDeleteFolder() { - user := "lidiah@8qzvrj.onmicrosoft.com" + userID, err := tester.M365UserID() + require.NoError(suite.T(), err) now := time.Now() folderName := "TestFolder: " + common.FormatSimpleDateTime(now) - aFolder, err := exchange.CreateMailFolder(&suite.connector.graphService, user, folderName) + aFolder, err := exchange.CreateMailFolder(&suite.connector.graphService, userID, folderName) assert.NoError(suite.T(), err, support.ConnectorStackErrorTrace(err)) if aFolder != nil { - err = exchange.DeleteMailFolder(&suite.connector.graphService, user, *aFolder.GetId()) + err = exchange.DeleteMailFolder(&suite.connector.graphService, userID, *aFolder.GetId()) assert.NoError(suite.T(), err) } } @@ -116,9 +119,10 @@ func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_CreateAndDeleteF // TestGraphConnector_GetMailFolderID verifies the ability to retrieve folder ID of folders // at the top level of the file tree func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_GetMailFolderID() { - user := "lidiah@8qzvrj.onmicrosoft.com" + userID, err := tester.M365UserID() + require.NoError(suite.T(), err) folderName := "Inbox" - folderID, err := exchange.GetMailFolderID(&suite.connector.graphService, folderName, user) + folderID, err := exchange.GetMailFolderID(&suite.connector.graphService, folderName, userID) assert.NoError(suite.T(), err) assert.NotNil(suite.T(), folderID) } diff --git a/src/internal/connector/mockconnector/mock_data_collection.go b/src/internal/connector/mockconnector/mock_data_collection.go index 2c46d80bc..ac44a5383 100644 --- a/src/internal/connector/mockconnector/mock_data_collection.go +++ b/src/internal/connector/mockconnector/mock_data_collection.go @@ -9,6 +9,7 @@ import ( "github.com/alcionai/corso/internal/common" "github.com/alcionai/corso/internal/data" + "github.com/alcionai/corso/internal/tester" "github.com/alcionai/corso/pkg/backup/details" ) @@ -88,8 +89,13 @@ func (med *MockExchangeData) Info() details.ItemInfo { // Contents verified as working with sample data from kiota-serialization-json-go v0.5.5 func getMockMessageBytes(subject string) []byte { + userID, err := tester.M365UserID() + if err != nil { + userID = "lidiah@8qzvrj.onmicrosoft.com" + } + message := "{\n \"@odata.etag\": \"W/\\\"CQAAABYAAAB8wYc0thTTTYl3RpEYIUq+AAAZ0f0I\\\"\",\n \"id\": \"AAMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOABGAAAAAAAPvVwUramXT7jlSGpVU8_7BwB8wYc0thTTTYl3RpEYIUq_AAAAAAEMAAB8wYc0thTTTYl3RpEYIUq_AAAZ3wG3AAA=\",\n \"createdDateTime\": \"2022-04-08T18:08:02Z\",\n \"lastModifiedDateTime\": \"2022-05-17T13:46:55Z\",\n \"changeKey\": \"CQAAABYAAAB8wYc0thTTTYl3RpEYIUq+AAAZ0f0I\",\n \"categories\": [],\n \"receivedDateTime\": \"2022-04-08T18:08:02Z\",\n \"sentDateTime\": \"2022-04-08T18:07:53Z\",\n \"hasAttachments\": false,\n \"internetMessageId\": \"\",\n \"subject\": \"" + - subject + " " + common.FormatSimpleDateTime(time.Now()) + " Different\",\n \"bodyPreview\": \"Who is coming to next week's party? I cannot imagine it is July soon\",\n \"importance\": \"normal\",\n \"parentFolderId\": \"AQMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4ADVkZWQwNmNlMTgALgAAAw_9XBStqZdPuOVIalVTz7sBAHzBhzS2FNNNiXdGkRghSr4AAAIBDAAAAA==\",\n \"conversationId\": \"AAQkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOAAQAI7SSzmEPaRJsY-TWIALn1g=\",\n \"conversationIndex\": \"AQHYS3N3jtJLOYQ9pEmxj9NYgAufWA==\",\n \"isDeliveryReceiptRequested\": null,\n \"isReadReceiptRequested\": false,\n \"isRead\": true,\n \"isDraft\": false,\n \"webLink\": \"https://outlook.office365.com/owa/?ItemID=AAMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOABGAAAAAAAPvVwUramXT7jlSGpVU8%2B7BwB8wYc0thTTTYl3RpEYIUq%2BAAAAAAEMAAB8wYc0thTTTYl3RpEYIUq%2BAAAZ3wG3AAA%3D&exvsurl=1&viewmodel=ReadMessageItem\",\n \"inferenceClassification\": \"focused\",\n \"body\": {\n \"contentType\": \"html\",\n \"content\": \"

I've been going through with the changing of messages. It shouldn't have the same calls, right? Call Me?

 

We want to be able to send multiple messages and we want to be able to respond and do other things that make sense for our users. In this case. Let’s consider a Mailbox

\"\n },\n \"sender\": {\n \"emailAddress\": {\n \"name\": \"Lidia Holloway\",\n \"address\": \"lidiah@8qzvrj.onmicrosoft.com\"\n }\n },\n \"from\": {\n \"emailAddress\": {\n \"name\": \"Lidia Holloway\",\n \"address\": \"lidiah@8qzvrj.onmicrosoft.com\"\n }\n },\n \"toRecipients\": [\n {\n \"emailAddress\": {\n \"name\": \"Dustin Abbot\",\n \"address\": \"dustina@8qzvrj.onmicrosoft.com\"\n }\n }\n ],\n \"ccRecipients\": [],\n \"bccRecipients\": [],\n \"replyTo\": [],\n \"flag\": {\n \"flagStatus\": \"notFlagged\"\n }\n}\n" + subject + " " + common.FormatSimpleDateTime(time.Now()) + " Different\",\n \"bodyPreview\": \"Who is coming to next week's party? I cannot imagine it is July soon\",\n \"importance\": \"normal\",\n \"parentFolderId\": \"AQMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4ADVkZWQwNmNlMTgALgAAAw_9XBStqZdPuOVIalVTz7sBAHzBhzS2FNNNiXdGkRghSr4AAAIBDAAAAA==\",\n \"conversationId\": \"AAQkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOAAQAI7SSzmEPaRJsY-TWIALn1g=\",\n \"conversationIndex\": \"AQHYS3N3jtJLOYQ9pEmxj9NYgAufWA==\",\n \"isDeliveryReceiptRequested\": null,\n \"isReadReceiptRequested\": false,\n \"isRead\": true,\n \"isDraft\": false,\n \"webLink\": \"https://outlook.office365.com/owa/?ItemID=AAMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOABGAAAAAAAPvVwUramXT7jlSGpVU8%2B7BwB8wYc0thTTTYl3RpEYIUq%2BAAAAAAEMAAB8wYc0thTTTYl3RpEYIUq%2BAAAZ3wG3AAA%3D&exvsurl=1&viewmodel=ReadMessageItem\",\n \"inferenceClassification\": \"focused\",\n \"body\": {\n \"contentType\": \"html\",\n \"content\": \"

I've been going through with the changing of messages. It shouldn't have the same calls, right? Call Me?

 

We want to be able to send multiple messages and we want to be able to respond and do other things that make sense for our users. In this case. Let’s consider a Mailbox

\"\n },\n \"sender\": {\n \"emailAddress\": {\n \"name\": \"Lidia Holloway\",\n \"address\": \"" + userID + "\"\n }\n },\n \"from\": {\n \"emailAddress\": {\n \"name\": \"Lidia Holloway\",\n \"address\": \"lidiah@8qzvrj.onmicrosoft.com\"\n }\n },\n \"toRecipients\": [\n {\n \"emailAddress\": {\n \"name\": \"Dustin Abbot\",\n \"address\": \"dustina@8qzvrj.onmicrosoft.com\"\n }\n }\n ],\n \"ccRecipients\": [],\n \"bccRecipients\": [],\n \"replyTo\": [],\n \"flag\": {\n \"flagStatus\": \"notFlagged\"\n }\n}\n" return []byte(message) } diff --git a/src/internal/operations/backup_test.go b/src/internal/operations/backup_test.go index 48b78ea27..6cac6a641 100644 --- a/src/internal/operations/backup_test.go +++ b/src/internal/operations/backup_test.go @@ -131,7 +131,8 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run() { t := suite.T() ctx := context.Background() - m365User := "lidiah@8qzvrj.onmicrosoft.com" + m365UserID, err := tester.M365UserID() + require.NoError(suite.T(), err) acct, err := tester.NewM365Account() require.NoError(t, err) @@ -157,7 +158,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run() { sw := store.NewKopiaStore(ms) sel := selectors.NewExchangeBackup() - sel.Include(sel.Users([]string{m365User})) + sel.Include(sel.Users([]string{m365UserID})) bo, err := NewBackupOperation( ctx, diff --git a/src/internal/operations/restore_test.go b/src/internal/operations/restore_test.go index 401e1f687..6c6ff82ed 100644 --- a/src/internal/operations/restore_test.go +++ b/src/internal/operations/restore_test.go @@ -129,7 +129,8 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() { t := suite.T() ctx := context.Background() - m365User := "lidiah@8qzvrj.onmicrosoft.com" + m365UserID, err := tester.M365UserID() + require.NoError(suite.T(), err) acct, err := tester.NewM365Account() require.NoError(t, err) @@ -152,7 +153,7 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() { sw := store.NewKopiaStore(ms) bsel := selectors.NewExchangeBackup() - bsel.Include(bsel.Users([]string{m365User})) + bsel.Include(bsel.Users([]string{m365UserID})) bo, err := NewBackupOperation( ctx, @@ -166,7 +167,7 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() { require.NotEmpty(t, bo.Results.BackupID) rsel := selectors.NewExchangeRestore() - rsel.Include(rsel.Users([]string{m365User})) + rsel.Include(rsel.Users([]string{m365UserID})) ro, err := NewRestoreOperation( ctx, @@ -192,7 +193,8 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run_ErrorNoResults() { t := suite.T() ctx := context.Background() - m365User := "lidiah@8qzvrj.onmicrosoft.com" + m365UserID, err := tester.M365UserID() + require.NoError(suite.T(), err) acct, err := tester.NewM365Account() require.NoError(t, err) @@ -215,7 +217,7 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run_ErrorNoResults() { sw := store.NewKopiaStore(ms) bsel := selectors.NewExchangeBackup() - bsel.Include(bsel.Users([]string{m365User})) + bsel.Include(bsel.Users([]string{m365UserID})) bo, err := NewBackupOperation( ctx, diff --git a/src/internal/tester/account.go b/src/internal/tester/account.go index 33568502c..380876c86 100644 --- a/src/internal/tester/account.go +++ b/src/internal/tester/account.go @@ -16,7 +16,7 @@ var M365AcctCredEnvs = []string{ func NewM365Account() (account.Account, error) { cfg, err := readTestConfig() if err != nil { - return account.Account{}, errors.Wrap(err, "configuring m365 account from test file") + return account.Account{}, errors.Wrap(err, "configuring m365 account from test configuration") } return account.NewAccount( diff --git a/src/internal/tester/config.go b/src/internal/tester/config.go index 110afe3ce..f2104fd75 100644 --- a/src/internal/tester/config.go +++ b/src/internal/tester/config.go @@ -18,8 +18,29 @@ const ( // M365 config testCfgTenantID = "tenantid" + testCfgUserID = "m365userid" ) +// test specific env vars +const ( + EnvCorsoM365TestUserID = "CORSO_M356_TEST_USER_ID" +) + +// global to hold the test config results. +var testConfig map[string]string + +// call this instead of returning testConfig directly. +func cloneTestConfig() map[string]string { + if testConfig == nil { + return map[string]string{} + } + clone := map[string]string{} + for k, v := range testConfig { + clone[k] = v + } + return clone +} + func newTestViper() (*viper.Viper, error) { vpr := viper.New() @@ -48,6 +69,10 @@ func newTestViper() (*viper.Viper, error) { // local integration test controls. Populates values with // defaults where standard. func readTestConfig() (map[string]string, error) { + if testConfig != nil { + return cloneTestConfig(), nil + } + vpr, err := newTestViper() if err != nil { return nil, err @@ -66,8 +91,10 @@ func readTestConfig() (map[string]string, error) { fallbackTo(testEnv, testCfgEndpoint, vpr.GetString(testCfgEndpoint), "s3.amazonaws.com") fallbackTo(testEnv, testCfgPrefix, vpr.GetString(testCfgPrefix)) fallbackTo(testEnv, testCfgTenantID, os.Getenv(account.TenantID), vpr.GetString(testCfgTenantID)) + fallbackTo(testEnv, testCfgUserID, os.Getenv(EnvCorsoM365TestUserID), vpr.GetString(testCfgTenantID), "lidiah@8qzvrj.onmicrosoft.com") - return testEnv, nil + testConfig = testEnv + return cloneTestConfig(), nil } // writes the first non-zero valued string to the map at the key. diff --git a/src/internal/tester/users.go b/src/internal/tester/users.go new file mode 100644 index 000000000..23f81c022 --- /dev/null +++ b/src/internal/tester/users.go @@ -0,0 +1,18 @@ +package tester + +import ( + "github.com/pkg/errors" +) + +// M365UserID returns an userID string representing the m365UserID described +// by either the env var CORSO_M356_TEST_USER_ID, the corso_test.toml config +// file or the default value (in that order of priority). The default is a +// last-attempt fallback that will only work on alcion's testing org. +func M365UserID() (string, error) { + cfg, err := readTestConfig() + if err != nil { + return "", errors.Wrap(err, "retrieving m365 user id from test configuration") + } + + return cfg[testCfgUserID], nil +}