harden sanitree population (#5237)

Allow sanity tree checking to require multiple folder subtrees have no
errors. This allows us to ensure both the source folder subtree and
restore folder subtree are populated without issue.

---

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

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

#### Type of change

- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [x] 🤖 Supportability/Tests
- [x] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Test Plan

- [ ] 💪 Manual
- [ ]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2024-02-21 15:53:12 -08:00 committed by GitHub
parent f4dbaf60b0
commit f3fdb4a885
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 16 deletions

View File

@ -5,6 +5,7 @@ import (
"github.com/alcionai/clues" "github.com/alcionai/clues"
"github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/models"
"golang.org/x/exp/slices"
"github.com/alcionai/corso/src/cmd/sanity_test/common" "github.com/alcionai/corso/src/cmd/sanity_test/common"
"github.com/alcionai/corso/src/internal/common/ptr" "github.com/alcionai/corso/src/internal/common/ptr"
@ -20,19 +21,20 @@ const (
// this increases the chance that we'll run into a race collision with // this increases the chance that we'll run into a race collision with
// the cleanup script. Sometimes that's okay (deleting old data that // the cleanup script. Sometimes that's okay (deleting old data that
// isn't scrutinized in the test), other times it's not. We mark whether // isn't scrutinized in the test), other times it's not. We mark whether
// that's okay to do or not by specifying the folder that's being // that's okay to do or not by specifying the folders being
// scrutinized for the test. Any errors within that folder should cause // scrutinized for the test. Any errors within those folders should cause
// a fatal exit. Errors outside of that folder get ignored. // a fatal exit. Errors outside of those folders get ignored.
// //
// since we're using folder names, requireNoErrorsWithinFolderName will // since we're using folder names, mustPopulateFolders will
// work best (ie: have the fewest collisions/side-effects) if the folder // work best (ie: have the fewest collisions/side-effects) if the folder
// name is very specific. Standard sanity tests should include timestamps, // names are very specific. Standard sanity tests should include timestamps,
// which should help ensure that. Be warned if you try to use it with // which should help ensure that. Be warned if you try to use it with
// a more generic name: unintended effects could occur. // a more generic name: unintended effects could occur.
func populateSanitree( func populateSanitree(
ctx context.Context, ctx context.Context,
ac api.Client, ac api.Client,
driveID, requireNoErrorsWithinFolderName string, driveID string,
mustPopulateFolders []string,
) *common.Sanitree[models.DriveItemable, models.DriveItemable] { ) *common.Sanitree[models.DriveItemable, models.DriveItemable] {
common.Infof(ctx, "building sanitree for drive: %s", driveID) common.Infof(ctx, "building sanitree for drive: %s", driveID)
@ -56,8 +58,8 @@ func populateSanitree(
ac, ac,
driveID, driveID,
stree.Name+"/", stree.Name+"/",
requireNoErrorsWithinFolderName, mustPopulateFolders,
rootName == requireNoErrorsWithinFolderName, slices.Contains(mustPopulateFolders, rootName),
stree) stree)
return stree return stree
@ -66,7 +68,9 @@ func populateSanitree(
func recursivelyBuildTree( func recursivelyBuildTree(
ctx context.Context, ctx context.Context,
ac api.Client, ac api.Client,
driveID, location, requireNoErrorsWithinFolderName string, driveID string,
location string,
mustPopulateFolders []string,
isChildOfFolderRequiringNoErrors bool, isChildOfFolderRequiringNoErrors bool,
stree *common.Sanitree[models.DriveItemable, models.DriveItemable], stree *common.Sanitree[models.DriveItemable, models.DriveItemable],
) { ) {
@ -80,9 +84,9 @@ func recursivelyBuildTree(
common.Infof( common.Infof(
ctx, ctx,
"ignoring error getting children in directory %q because it is not within directory %q\nerror: %s\n%+v", "ignoring error getting children in directory %q because it is not within directory set %v\nerror: %s\n%+v",
location, location,
requireNoErrorsWithinFolderName, mustPopulateFolders,
err.Error(), err.Error(),
clues.ToCore(err)) clues.ToCore(err))
@ -99,11 +103,12 @@ func recursivelyBuildTree(
// currently we don't restore blank folders. // currently we don't restore blank folders.
// skip permission check for empty folders // skip permission check for empty folders
if ptr.Val(driveItem.GetFolder().GetChildCount()) == 0 { if ptr.Val(driveItem.GetFolder().GetChildCount()) == 0 {
common.Infof(ctx, "skipped empty folder: %s/%s", location, itemName) common.Infof(ctx, "skipped empty folder: %s%s", location, itemName)
continue continue
} }
cannotAllowErrors := isChildOfFolderRequiringNoErrors || itemName == requireNoErrorsWithinFolderName cannotAllowErrors := isChildOfFolderRequiringNoErrors ||
slices.Contains(mustPopulateFolders, itemName)
branch := &common.Sanitree[models.DriveItemable, models.DriveItemable]{ branch := &common.Sanitree[models.DriveItemable, models.DriveItemable]{
Parent: stree, Parent: stree,
@ -124,7 +129,7 @@ func recursivelyBuildTree(
ac, ac,
driveID, driveID,
location+branch.Name+"/", location+branch.Name+"/",
requireNoErrorsWithinFolderName, mustPopulateFolders,
cannotAllowErrors, cannotAllowErrors,
branch) branch)
} }

View File

@ -32,7 +32,7 @@ func CheckExport(
ctx, ctx,
ac, ac,
driveID, driveID,
envs.RestoreContainer) []string{envs.SourceContainer})
sourceTree, ok := root.Children[envs.SourceContainer] sourceTree, ok := root.Children[envs.SourceContainer]
common.Assert( common.Assert(

View File

@ -45,7 +45,14 @@ func CheckRestoration(
"drive_id", driveID, "drive_id", driveID,
"drive_name", driveName) "drive_name", driveName)
root := populateSanitree(ctx, ac, driveID, envs.RestoreContainer) root := populateSanitree(
ctx,
ac,
driveID,
[]string{
envs.SourceContainer,
envs.RestoreContainer,
})
sourceTree, ok := root.Children[envs.SourceContainer] sourceTree, ok := root.Children[envs.SourceContainer]
common.Assert( common.Assert(