From 8f30db4f6e4b2cd3c764d24f1902551f7f91f847 Mon Sep 17 00:00:00 2001 From: Abin Simon Date: Fri, 28 Jul 2023 16:13:59 +0530 Subject: [PATCH] Sanity tests for OneDrive exports (#3910) Add sanity tests for OneDrive exports (archive and non-archive exports). --- #### Does this PR need a docs update or release note? - [ ] :white_check_mark: Yes, it's included - [ ] :clock1: Yes, but in a later PR - [x] :no_entry: No #### Type of change - [ ] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [x] :robot: Supportability/Tests - [ ] :computer: CI/Deployment - [ ] :broom: Tech Debt/Cleanup #### Issue(s) * https://github.com/alcionai/corso/issues/3889 #### Test Plan - [ ] :muscle: Manual - [ ] :zap: Unit test - [x] :green_heart: E2E --- .../actions/backup-restore-test/action.yml | 72 ++++++++- src/cmd/sanity_test/common/common.go | 6 + src/cmd/sanity_test/common/utils.go | 82 ++++++++++ src/cmd/sanity_test/export/onedrive.go | 88 +++++++++++ src/cmd/sanity_test/restore/exchange.go | 12 +- src/cmd/sanity_test/restore/onedrive.go | 144 ++++++++++-------- src/cmd/sanity_test/restore/sharepoint.go | 4 +- src/cmd/sanity_test/sanity_tests.go | 45 ++++-- 8 files changed, 363 insertions(+), 90 deletions(-) create mode 100644 src/cmd/sanity_test/common/common.go create mode 100644 src/cmd/sanity_test/common/utils.go create mode 100644 src/cmd/sanity_test/export/onedrive.go diff --git a/.github/actions/backup-restore-test/action.yml b/.github/actions/backup-restore-test/action.yml index 2d161af63..56213d3e7 100644 --- a/.github/actions/backup-restore-test/action.yml +++ b/.github/actions/backup-restore-test/action.yml @@ -72,12 +72,78 @@ runs: cat /tmp/corsologs - - name: Check ${{ inputs.service }} ${{ inputs.kind }} + - name: Check restore ${{ inputs.service }} ${{ inputs.kind }} shell: bash working-directory: src env: - SANITY_RESTORE_FOLDER: ${{ steps.restore.outputs.result }} - SANITY_RESTORE_SERVICE: ${{ inputs.service }} + SANITY_TEST_KIND: restore + SANITY_TEST_FOLDER: ${{ steps.restore.outputs.result }} + SANITY_TEST_SERVICE: ${{ inputs.service }} + TEST_DATA: ${{ inputs.test-folder }} + BASE_BACKUP: ${{ inputs.base-backup }} + run: | + CORSO_LOG_FILE=${{ inputs.log-dir }}/gotest-validate-${{ inputs.service }}-${{inputs.kind }}.log + ./sanity-test + + - name: Export ${{ inputs.service }} ${{ inputs.kind }} + id: export + shell: bash + working-directory: src + if: ${{ inputs.service == 'onedrive' }} # Export only available for OneDrive + run: | + set -euo pipefail + CORSO_LOG_FILE=${{ inputs.log-dir }}/gotest-restore-${{ inputs.service }}-${{inputs.kind }}.log + ./corso export '${{ inputs.service }}' \ + /tmp/export-${{ inputs.service }}-${{inputs.kind }} \ + --no-stats \ + --hide-progress \ + ${{ inputs.export-args }} \ + --backup '${{ steps.backup.outputs.result }}' + + cat /tmp/corsologs + + - name: Check export ${{ inputs.service }} ${{ inputs.kind }} + shell: bash + working-directory: src + if: ${{ inputs.service == 'onedrive' }} + env: + SANITY_TEST_KIND: export + SANITY_TEST_FOLDER: /tmp/export-${{ inputs.service }}-${{inputs.kind }} + SANITY_TEST_SERVICE: ${{ inputs.service }} + TEST_DATA: ${{ inputs.test-folder }} + BASE_BACKUP: ${{ inputs.base-backup }} + run: | + CORSO_LOG_FILE=${{ inputs.log-dir }}/gotest-validate-${{ inputs.service }}-${{inputs.kind }}.log + ./sanity-test + + - name: Export archive ${{ inputs.service }} ${{ inputs.kind }} + id: export-archive + shell: bash + working-directory: src + if: ${{ inputs.service == 'onedrive' }} # Export only available for OneDrive + run: | + set -euo pipefail + CORSO_LOG_FILE=${{ inputs.log-dir }}/gotest-restore-${{ inputs.service }}-${{inputs.kind }}.log + ./corso export '${{ inputs.service }}' \ + /tmp/export-${{ inputs.service }}-${{inputs.kind }}-archive \ + --no-stats \ + --hide-progress \ + --archive \ + ${{ inputs.export-args }} \ + --backup '${{ steps.backup.outputs.result }}' + + unzip /tmp/export-${{ inputs.service }}-${{inputs.kind }}-archive/*.zip \ + -d /tmp/export-${{ inputs.service }}-${{inputs.kind }}-unzipped + cat /tmp/corsologs + + - name: Check archive export ${{ inputs.service }} ${{ inputs.kind }} + shell: bash + working-directory: src + if: ${{ inputs.service == 'onedrive' }} + env: + SANITY_TEST_KIND: export + SANITY_TEST_FOLDER: /tmp/export-${{ inputs.service }}-${{inputs.kind }}-unzipped + SANITY_TEST_SERVICE: ${{ inputs.service }} TEST_DATA: ${{ inputs.test-folder }} BASE_BACKUP: ${{ inputs.base-backup }} run: | diff --git a/src/cmd/sanity_test/common/common.go b/src/cmd/sanity_test/common/common.go new file mode 100644 index 000000000..344d6dc19 --- /dev/null +++ b/src/cmd/sanity_test/common/common.go @@ -0,0 +1,6 @@ +package common + +type PermissionInfo struct { + EntityID string + Roles []string +} diff --git a/src/cmd/sanity_test/common/utils.go b/src/cmd/sanity_test/common/utils.go new file mode 100644 index 000000000..e14fa86c6 --- /dev/null +++ b/src/cmd/sanity_test/common/utils.go @@ -0,0 +1,82 @@ +package common + +import ( + "context" + "errors" + "fmt" + "os" + "strings" + "time" + + "github.com/alcionai/corso/src/internal/common/dttm" + "github.com/alcionai/corso/src/pkg/logger" +) + +func Assert( + ctx context.Context, + passes func() bool, + header string, + expect, current any, +) { + if passes() { + return + } + + header = "Error: " + header + expected := fmt.Sprintf("* Expected: %+v", expect) + got := fmt.Sprintf("* Current: %+v", current) + + logger.Ctx(ctx).Info(strings.Join([]string{header, expected, got}, " ")) + + fmt.Println(header) + fmt.Println(expected) + fmt.Println(got) + + os.Exit(1) +} + +func Fatal(ctx context.Context, msg string, err error) { + logger.CtxErr(ctx, err).Error("test failure: " + msg) + fmt.Println(msg+": ", err) + os.Exit(1) +} + +func MustGetTimeFromName(ctx context.Context, name string) (time.Time, bool) { + t, err := dttm.ExtractTime(name) + if err != nil && !errors.Is(err, dttm.ErrNoTimeString) { + Fatal(ctx, "extracting time from name: "+name, err) + } + + return t, !errors.Is(err, dttm.ErrNoTimeString) +} + +func IsWithinTimeBound(ctx context.Context, bound, check time.Time, hasTime bool) bool { + if hasTime { + if bound.Before(check) { + logger.Ctx(ctx). + With("boundary_time", bound, "check_time", check). + Info("skipping restore folder: not older than time bound") + + return false + } + } + + return true +} + +func FilterSlice(sl []string, remove string) []string { + r := []string{} + + for _, s := range sl { + if !strings.EqualFold(s, remove) { + r = append(r, s) + } + } + + return r +} + +func LogAndPrint(ctx context.Context, tmpl string, vs ...any) { + logger.Ctx(ctx).Infof(tmpl, vs...) + fmt.Printf(tmpl+"\n", vs...) +} diff --git a/src/cmd/sanity_test/export/onedrive.go b/src/cmd/sanity_test/export/onedrive.go new file mode 100644 index 000000000..3d5564bcc --- /dev/null +++ b/src/cmd/sanity_test/export/onedrive.go @@ -0,0 +1,88 @@ +package export + +import ( + "context" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/alcionai/clues" + msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" + + "github.com/alcionai/corso/src/cmd/sanity_test/common" + "github.com/alcionai/corso/src/cmd/sanity_test/restore" + "github.com/alcionai/corso/src/internal/common/ptr" +) + +func CheckOneDriveExport( + ctx context.Context, + client *msgraphsdk.GraphServiceClient, + userID, folderName, dataFolder string, +) { + drive, err := client. + Users(). + ByUserId(userID). + Drive(). + Get(ctx, nil) + if err != nil { + common.Fatal(ctx, "getting the drive:", err) + } + + // map itemID -> item size + var ( + fileSizes = make(map[string]int64) + exportFileSizes = make(map[string]int64) + startTime = time.Now() + ) + + err = filepath.Walk(folderName, func(path string, info os.FileInfo, err error) error { + if err != nil { + return clues.Stack(err) + } + + if info.IsDir() { + return nil + } + + relPath, err := filepath.Rel(folderName, path) + if err != nil { + return clues.Stack(err) + } + + exportFileSizes[relPath] = info.Size() + if startTime.After(info.ModTime()) { + startTime = info.ModTime() + } + + return nil + }) + if err != nil { + fmt.Println("Error walking the path:", err) + } + + _ = restore.PopulateDriveDetails( + ctx, + client, + ptr.Val(drive.GetId()), + folderName, + dataFolder, + fileSizes, + map[string][]common.PermissionInfo{}, + startTime) + + for fileName, expected := range fileSizes { + common.LogAndPrint(ctx, "checking for file: %s", fileName) + + got := exportFileSizes[fileName] + + common.Assert( + ctx, + func() bool { return expected == got }, + fmt.Sprintf("different file size: %s", fileName), + expected, + got) + } + + fmt.Println("Success") +} diff --git a/src/cmd/sanity_test/restore/exchange.go b/src/cmd/sanity_test/restore/exchange.go index e484550de..2dc65e6e1 100644 --- a/src/cmd/sanity_test/restore/exchange.go +++ b/src/cmd/sanity_test/restore/exchange.go @@ -12,7 +12,7 @@ import ( "github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/users" - "github.com/alcionai/corso/src/cmd/sanity_test/utils" + "github.com/alcionai/corso/src/cmd/sanity_test/common" "github.com/alcionai/corso/src/internal/common/ptr" "github.com/alcionai/corso/src/pkg/filters" ) @@ -35,7 +35,7 @@ func CheckEmailRestoration( for { result, err := builder.Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting mail folders", err) + common.Fatal(ctx, "getting mail folders", err) } values := result.GetValue() @@ -79,7 +79,7 @@ func CheckEmailRestoration( ChildFolders(). Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting restore folder child folders", err) + common.Fatal(ctx, "getting restore folder child folders", err) } for _, fld := range childFolder.GetValue() { @@ -102,7 +102,7 @@ func verifyEmailData(ctx context.Context, restoreMessageCount, messageCount map[ for fldName, expected := range messageCount { got := restoreMessageCount[fldName] - utils.Assert( + common.Assert( ctx, func() bool { return expected == got }, fmt.Sprintf("Restore item counts do not match: %s", fldName), @@ -142,7 +142,7 @@ func getAllMailSubFolders( ChildFolders(). Get(ctx, options) if err != nil { - utils.Fatal(ctx, "getting mail subfolders", err) + common.Fatal(ctx, "getting mail subfolders", err) } for _, child := range childFolder.GetValue() { @@ -194,7 +194,7 @@ func checkAllSubFolder( ChildFolders(). Get(ctx, options) if err != nil { - utils.Fatal(ctx, "getting mail subfolders", err) + common.Fatal(ctx, "getting mail subfolders", err) } for _, child := range childFolder.GetValue() { diff --git a/src/cmd/sanity_test/restore/onedrive.go b/src/cmd/sanity_test/restore/onedrive.go index ca332d608..87ea424c3 100644 --- a/src/cmd/sanity_test/restore/onedrive.go +++ b/src/cmd/sanity_test/restore/onedrive.go @@ -10,7 +10,7 @@ import ( msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" "golang.org/x/exp/slices" - "github.com/alcionai/corso/src/cmd/sanity_test/utils" + "github.com/alcionai/corso/src/cmd/sanity_test/common" "github.com/alcionai/corso/src/internal/common/ptr" "github.com/alcionai/corso/src/pkg/path" ) @@ -19,11 +19,6 @@ const ( owner = "owner" ) -type permissionInfo struct { - entityID string - roles []string -} - func CheckOneDriveRestoration( ctx context.Context, client *msgraphsdk.GraphServiceClient, @@ -36,7 +31,7 @@ func CheckOneDriveRestoration( Drive(). Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting the drive:", err) + common.Fatal(ctx, "getting the drive:", err) } checkDriveRestoration( @@ -66,15 +61,58 @@ func checkDriveRestoration( // map itemID -> item size fileSizes = make(map[string]int64) // map itemID -> permission id -> []permission roles - folderPermissions = make(map[string][]permissionInfo) + folderPermissions = make(map[string][]common.PermissionInfo) restoreFile = make(map[string]int64) - restoredFolderPermissions = make(map[string][]permissionInfo) + restoredFolderPermissions = make(map[string][]common.PermissionInfo) ) - var restoreFolderID string - ctx = clues.Add(ctx, "drive_id", driveID, "drive_name", driveName) + restoreFolderID := PopulateDriveDetails( + ctx, + client, + driveID, + folderName, + dataFolder, + fileSizes, + folderPermissions, + startTime) + + getRestoredDrive(ctx, client, driveID, restoreFolderID, restoreFile, restoredFolderPermissions, startTime) + + checkRestoredDriveItemPermissions( + ctx, + service, + skipPermissionTest, + folderPermissions, + restoredFolderPermissions) + + for fileName, expected := range fileSizes { + common.LogAndPrint(ctx, "checking for file: %s", fileName) + + got := restoreFile[fileName] + + common.Assert( + ctx, + func() bool { return expected == got }, + fmt.Sprintf("different file size: %s", fileName), + expected, + got) + } + + fmt.Println("Success") +} + +func PopulateDriveDetails( + ctx context.Context, + client *msgraphsdk.GraphServiceClient, + driveID, folderName, dataFolder string, + fileSizes map[string]int64, + folderPermissions map[string][]common.PermissionInfo, + startTime time.Time, +) string { + var restoreFolderID string + response, err := client. Drives(). ByDriveId(driveID). @@ -83,7 +121,7 @@ func checkDriveRestoration( Children(). Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting drive by id", err) + common.Fatal(ctx, "getting drive by id", err) } for _, driveItem := range response.GetValue() { @@ -98,7 +136,7 @@ func checkDriveRestoration( } if itemName != dataFolder { - utils.LogAndPrint(ctx, "test data for folder: %s", dataFolder) + common.LogAndPrint(ctx, "test data for folder: %s", dataFolder) continue } @@ -114,7 +152,7 @@ func checkDriveRestoration( // currently we don't restore blank folders. // skip permission check for empty folders if ptr.Val(driveItem.GetFolder().GetChildCount()) == 0 { - utils.LogAndPrint(ctx, "skipped empty folder: %s", itemName) + common.LogAndPrint(ctx, "skipped empty folder: %s", itemName) continue } @@ -122,37 +160,15 @@ func checkDriveRestoration( getOneDriveChildFolder(ctx, client, driveID, itemID, itemName, fileSizes, folderPermissions, startTime) } - getRestoredDrive(ctx, client, driveID, restoreFolderID, restoreFile, restoredFolderPermissions, startTime) - - checkRestoredDriveItemPermissions( - ctx, - service, - skipPermissionTest, - folderPermissions, - restoredFolderPermissions) - - for fileName, expected := range fileSizes { - utils.LogAndPrint(ctx, "checking for file: %s", fileName) - - got := restoreFile[fileName] - - utils.Assert( - ctx, - func() bool { return expected == got }, - fmt.Sprintf("different file size: %s", fileName), - expected, - got) - } - - fmt.Println("Success") + return restoreFolderID } func checkRestoredDriveItemPermissions( ctx context.Context, service path.ServiceType, skip bool, - folderPermissions map[string][]permissionInfo, - restoredFolderPermissions map[string][]permissionInfo, + folderPermissions map[string][]common.PermissionInfo, + restoredFolderPermissions map[string][]common.PermissionInfo, ) { if skip { return @@ -164,12 +180,12 @@ func checkRestoredDriveItemPermissions( **/ for folderName, permissions := range folderPermissions { - utils.LogAndPrint(ctx, "checking for folder: %s", folderName) + common.LogAndPrint(ctx, "checking for folder: %s", folderName) restoreFolderPerm := restoredFolderPermissions[folderName] if len(permissions) < 1 { - utils.LogAndPrint(ctx, "no permissions found in: %s", folderName) + common.LogAndPrint(ctx, "no permissions found in: %s", folderName) continue } @@ -179,7 +195,7 @@ func checkRestoredDriveItemPermissions( permCheck = func() bool { return len(permissions) <= len(restoreFolderPerm) } } - utils.Assert( + common.Assert( ctx, permCheck, fmt.Sprintf("wrong number of restored permissions: %s", folderName), @@ -187,25 +203,25 @@ func checkRestoredDriveItemPermissions( restoreFolderPerm) for _, perm := range permissions { - eqID := func(pi permissionInfo) bool { return strings.EqualFold(pi.entityID, perm.entityID) } + eqID := func(pi common.PermissionInfo) bool { return strings.EqualFold(pi.EntityID, perm.EntityID) } i := slices.IndexFunc(restoreFolderPerm, eqID) - utils.Assert( + common.Assert( ctx, func() bool { return i >= 0 }, fmt.Sprintf("permission was restored in: %s", folderName), - perm.entityID, + perm.EntityID, restoreFolderPerm) // permissions should be sorted, so a by-index comparison works restored := restoreFolderPerm[i] - utils.Assert( + common.Assert( ctx, - func() bool { return slices.Equal(perm.roles, restored.roles) }, + func() bool { return slices.Equal(perm.Roles, restored.Roles) }, fmt.Sprintf("different roles restored: %s", folderName), - perm.roles, - restored.roles) + perm.Roles, + restored.Roles) } } } @@ -215,12 +231,12 @@ func getOneDriveChildFolder( client *msgraphsdk.GraphServiceClient, driveID, itemID, parentName string, fileSizes map[string]int64, - folderPermission map[string][]permissionInfo, + folderPermission map[string][]common.PermissionInfo, startTime time.Time, ) { response, err := client.Drives().ByDriveId(driveID).Items().ByDriveItemId(itemID).Children().Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting child folder", err) + common.Fatal(ctx, "getting child folder", err) } for _, driveItem := range response.GetValue() { @@ -230,8 +246,8 @@ func getOneDriveChildFolder( fullName = parentName + "/" + itemName ) - folderTime, hasTime := utils.MustGetTimeFromName(ctx, itemName) - if !utils.IsWithinTimeBound(ctx, startTime, folderTime, hasTime) { + folderTime, hasTime := common.MustGetTimeFromName(ctx, itemName) + if !common.IsWithinTimeBound(ctx, startTime, folderTime, hasTime) { continue } @@ -247,7 +263,7 @@ func getOneDriveChildFolder( // currently we don't restore blank folders. // skip permission check for empty folders if ptr.Val(driveItem.GetFolder().GetChildCount()) == 0 { - utils.LogAndPrint(ctx, "skipped empty folder: %s", fullName) + common.LogAndPrint(ctx, "skipped empty folder: %s", fullName) continue } @@ -262,7 +278,7 @@ func getRestoredDrive( client *msgraphsdk.GraphServiceClient, driveID, restoreFolderID string, restoreFile map[string]int64, - restoreFolder map[string][]permissionInfo, + restoreFolder map[string][]common.PermissionInfo, startTime time.Time, ) { restored, err := client. @@ -273,7 +289,7 @@ func getRestoredDrive( Children(). Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting child folder", err) + common.Fatal(ctx, "getting child folder", err) } for _, item := range restored.GetValue() { @@ -305,8 +321,8 @@ func permissionIn( ctx context.Context, client *msgraphsdk.GraphServiceClient, driveID, itemID string, -) []permissionInfo { - pi := []permissionInfo{} +) []common.PermissionInfo { + pi := []common.PermissionInfo{} pcr, err := client. Drives(). @@ -316,7 +332,7 @@ func permissionIn( Permissions(). Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting permission", err) + common.Fatal(ctx, "getting permission", err) } for _, perm := range pcr.GetValue() { @@ -326,7 +342,7 @@ func permissionIn( var ( gv2 = perm.GetGrantedToV2() - permInfo = permissionInfo{} + permInfo = common.PermissionInfo{} entityID string ) @@ -337,14 +353,14 @@ func permissionIn( entityID = ptr.Val(gv2.GetGroup().GetId()) } - roles := utils.FilterSlice(perm.GetRoles(), owner) + roles := common.FilterSlice(perm.GetRoles(), owner) for _, role := range roles { - permInfo.entityID = entityID - permInfo.roles = append(permInfo.roles, role) + permInfo.EntityID = entityID + permInfo.Roles = append(permInfo.Roles, role) } if len(roles) > 0 { - slices.Sort(permInfo.roles) + slices.Sort(permInfo.Roles) pi = append(pi, permInfo) } } diff --git a/src/cmd/sanity_test/restore/sharepoint.go b/src/cmd/sanity_test/restore/sharepoint.go index d84e28f6c..a5146d7a4 100644 --- a/src/cmd/sanity_test/restore/sharepoint.go +++ b/src/cmd/sanity_test/restore/sharepoint.go @@ -6,7 +6,7 @@ import ( msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" - "github.com/alcionai/corso/src/cmd/sanity_test/utils" + "github.com/alcionai/corso/src/cmd/sanity_test/common" "github.com/alcionai/corso/src/internal/common/ptr" "github.com/alcionai/corso/src/pkg/path" ) @@ -23,7 +23,7 @@ func CheckSharePointRestoration( Drive(). Get(ctx, nil) if err != nil { - utils.Fatal(ctx, "getting the drive:", err) + common.Fatal(ctx, "getting the drive:", err) } checkDriveRestoration( diff --git a/src/cmd/sanity_test/sanity_tests.go b/src/cmd/sanity_test/sanity_tests.go index a4d455edd..44680ab47 100644 --- a/src/cmd/sanity_test/sanity_tests.go +++ b/src/cmd/sanity_test/sanity_tests.go @@ -9,8 +9,9 @@ import ( "github.com/alcionai/clues" msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" + "github.com/alcionai/corso/src/cmd/sanity_test/common" + "github.com/alcionai/corso/src/cmd/sanity_test/export" "github.com/alcionai/corso/src/cmd/sanity_test/restore" - "github.com/alcionai/corso/src/cmd/sanity_test/utils" "github.com/alcionai/corso/src/internal/m365/graph" "github.com/alcionai/corso/src/internal/tester/tconfig" "github.com/alcionai/corso/src/pkg/logger" @@ -35,16 +36,16 @@ func main() { os.Getenv("AZURE_CLIENT_ID"), os.Getenv("AZURE_CLIENT_SECRET")) if err != nil { - utils.Fatal(ctx, "creating adapter", err) + common.Fatal(ctx, "creating adapter", err) } var ( client = msgraphsdk.NewGraphServiceClient(adapter) testUser = tconfig.GetM365UserID(ctx) testSite = tconfig.GetM365SiteID(ctx) - testService = os.Getenv("SANITY_RESTORE_SERVICE") - folder = strings.TrimSpace(os.Getenv("SANITY_RESTORE_FOLDER")) - startTime, _ = utils.MustGetTimeFromName(ctx, folder) + testKind = os.Getenv("SANITY_TEST_KIND") // restore or export (cli arg?) + testService = os.Getenv("SANITY_TEST_SERVICE") + folder = strings.TrimSpace(os.Getenv("SANITY_TEST_FOLDER")) dataFolder = os.Getenv("TEST_DATA") baseBackupFolder = os.Getenv("BASE_BACKUP") ) @@ -53,19 +54,33 @@ func main() { ctx, "resource_owner", testUser, "service", testService, - "sanity_restore_folder", folder, - "start_time", startTime.Format(time.RFC3339Nano)) + "sanity_restore_folder", folder) logger.Ctx(ctx).Info("starting sanity test check") - switch testService { - case "exchange": - restore.CheckEmailRestoration(ctx, client, testUser, folder, dataFolder, baseBackupFolder, startTime) - case "onedrive": - restore.CheckOneDriveRestoration(ctx, client, testUser, folder, dataFolder, startTime) - case "sharepoint": - restore.CheckSharePointRestoration(ctx, client, testSite, testUser, folder, dataFolder, startTime) + switch testKind { + case "restore": + startTime, _ := common.MustGetTimeFromName(ctx, folder) + clues.Add(ctx, "sanity_restore_start_time", startTime.Format(time.RFC3339)) + + switch testService { + case "exchange": + restore.CheckEmailRestoration(ctx, client, testUser, folder, dataFolder, baseBackupFolder, startTime) + case "onedrive": + restore.CheckOneDriveRestoration(ctx, client, testUser, folder, dataFolder, startTime) + case "sharepoint": + restore.CheckSharePointRestoration(ctx, client, testSite, testUser, folder, dataFolder, startTime) + default: + common.Fatal(ctx, "unknown service for restore sanity tests", nil) + } + case "export": + switch testService { + case "onedrive": + export.CheckOneDriveExport(ctx, client, testUser, folder, dataFolder) + default: + common.Fatal(ctx, "unknown service for export sanity tests", nil) + } default: - utils.Fatal(ctx, "unknown service for restore sanity tests", nil) + common.Fatal(ctx, "unknown test kind (expected restore or export)", nil) } }