implement load tests (#937)

## Description

Adds the load test func calls and asserts for
both exchange and onedrive.

## Type of change

- [x] 🤖 Test

## Issue(s)

* #902

## Test Plan

- [x] 💚 E2E
This commit is contained in:
Keepers 2022-09-26 18:21:30 -06:00 committed by GitHub
parent 7d1cf2ce5b
commit e061ce7c73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 191 additions and 60 deletions

View File

@ -9,53 +9,54 @@ permissions:
id-token: write id-token: write
contents: read contents: read
Load-Tests: jobs:
environment: Testing Load-Tests:
runs-on: ubuntu-latest environment: Testing
defaults: runs-on: ubuntu-latest
run: defaults:
working-directory: src run:
steps: working-directory: src
- uses: actions/checkout@v3 steps:
- uses: actions/checkout@v3
- name: Setup Golang with cache - name: Setup Golang with cache
uses: magnetikonline/action-golang-cache@v3 uses: magnetikonline/action-golang-cache@v3
with: with:
go-version-file: src/go.mod go-version-file: src/go.mod
# Install gotestfmt # Install gotestfmt
- name: Set up gotestfmt - name: Set up gotestfmt
run: go install github.com/haveyoudebuggedit/gotestfmt/v2/cmd/gotestfmt@latest run: go install github.com/haveyoudebuggedit/gotestfmt/v2/cmd/gotestfmt@latest
# AWS creds # AWS creds
- name: Configure AWS credentials from Test account - name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v1 uses: aws-actions/configure-aws-credentials@v1
with: with:
role-to-assume: arn:aws:iam::951767375776:role/corso-testing-role role-to-assume: arn:aws:iam::951767375776:role/corso-testing-role
role-session-name: integration-testing role-session-name: integration-testing
aws-region: us-east-1 aws-region: us-east-1
# run the tests # run the tests
- name: Integration Tests - name: Integration Tests
env: env:
CORSO_LOAD_TESTS: true CORSO_LOAD_TESTS: true
CLIENT_ID: ${{ secrets.CLIENT_ID }} CLIENT_ID: ${{ secrets.CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }} CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }}
TENANT_ID: ${{ secrets.TENANT_ID }} TENANT_ID: ${{ secrets.TENANT_ID }}
run: | run: |
set -euo pipefail set -euo pipefail
go test \ go test \
-json \ -json \
-v \ -v \
-count=1 \ -count=1 \
--timeout 12h \ --timeout 12h \
./... 2>&1 | tee /tmp/gotest.log | gotestfmt -hide successful-tests ./... 2>&1 | tee /tmp/gotest.log | gotestfmt -hide successful-tests
# Upload the original go test log as an artifact for later review. # Upload the original go test log as an artifact for later review.
- name: Upload test log - name: Upload test log
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: test-log name: test-log
path: /tmp/gotest.log path: /tmp/gotest.log
if-no-files-found: error if-no-files-found: error

View File

@ -4,14 +4,17 @@ import (
"context" "context"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/operations"
"github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/internal/tester"
"github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/logger" "github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/repository" "github.com/alcionai/corso/src/pkg/repository"
"github.com/alcionai/corso/src/pkg/selectors"
"github.com/alcionai/corso/src/pkg/storage" "github.com/alcionai/corso/src/pkg/storage"
) )
@ -38,6 +41,98 @@ func initM365Repo(t *testing.T) (
return ctx, repo, ac, st return ctx, repo, ac, st
} }
//revive:disable:context-as-argument
func runBackupLoadTest(
t *testing.T,
ctx context.Context,
b *operations.BackupOperation,
name string,
) {
//revive:enable:context-as-argument
t.Run("backup_"+name, func(t *testing.T) {
require.NoError(t, b.Run(ctx), "running backup")
require.NotEmpty(t, b.Results, "has results after run")
assert.NotEmpty(t, b.Results.BackupID, "has an ID after run")
assert.Equal(t, b.Status, operations.Completed, "backup status")
assert.Less(t, 0, b.Results.ItemsRead, "items read")
assert.Less(t, 0, b.Results.ItemsWritten, "items written")
assert.Less(t, int64(0), b.Results.BytesUploaded, "bytes uploaded")
assert.Less(t, 0, b.Results.ResourceOwners, "resource owners")
assert.Zero(t, b.Results.ReadErrors, "read errors")
assert.Zero(t, b.Results.WriteErrors, "write errors")
})
}
//revive:disable:context-as-argument
func runBackupListLoadTest(
t *testing.T,
ctx context.Context,
r repository.Repository,
name, expectID string,
) {
//revive:enable:context-as-argument
t.Run("backup_list_"+name, func(t *testing.T) {
bs, err := r.Backups(ctx)
require.NoError(t, err, "retrieving backups")
require.Less(t, 0, len(bs), "at least one backup is recorded")
var found bool
for _, b := range bs {
bid := b.ID
assert.NotEmpty(t, bid, "iterating backup ids")
if string(bid) == expectID {
found = true
}
}
assert.True(t, found, "expected backup id "+expectID+" found in backups")
})
}
//revive:disable:context-as-argument
func runBackupDetailsLoadTest(
t *testing.T,
ctx context.Context,
r repository.Repository,
name, backupID string,
) {
//revive:enable:context-as-argument
require.NotEmpty(t, backupID, "backup ID to retrieve deails")
t.Run("backup_details_"+name, func(t *testing.T) {
ds, b, err := r.BackupDetails(ctx, backupID)
require.NoError(t, err, "retrieving details in backup "+backupID)
require.NotNil(t, ds, "backup details")
require.NotNil(t, b, "backup")
assert.Equal(t, b.ItemsWritten, len(ds.Entries))
})
}
//revive:disable:context-as-argument
func runRestoreLoadTest(
t *testing.T,
ctx context.Context,
r operations.RestoreOperation,
name string,
expectItemCount int,
) {
//revive:enable:context-as-argument
t.Run("restore_"+name, func(t *testing.T) {
t.Skip("skipping restore handling while investigating performance")
require.NoError(t, r.Run(ctx), "running restore")
require.NotEmpty(t, r.Results, "has results after run")
assert.Equal(t, r.Status, operations.Completed, "restore status")
assert.Less(t, 0, r.Results.ItemsRead, "items read")
assert.Less(t, 0, r.Results.ItemsWritten, "items written")
assert.Less(t, 0, r.Results.ResourceOwners, "resource owners")
assert.Zero(t, r.Results.ReadErrors, "read errors")
assert.Zero(t, r.Results.WriteErrors, "write errors")
assert.Equal(t, expectItemCount, r.Results.ItemsWritten, "backup and restore wrote the same count of items")
})
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Exchange // Exchange
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -76,20 +171,39 @@ func (suite *RepositoryLoadTestExchangeSuite) TeardownTest() {
} }
func (suite *RepositoryLoadTestExchangeSuite) TestExchange() { func (suite *RepositoryLoadTestExchangeSuite) TestExchange() {
// var ( var (
// t = suite.T() t = suite.T()
// ctx = context.Background() ctx = context.Background()
// ) r = suite.repo
service = "exchange"
)
// t.parallel() t.Parallel()
m356User := tester.M365UserID(t)
// backup // backup
bsel := selectors.NewExchangeBackup()
bsel.Include(bsel.Users([]string{m356User}))
// bsel.Include(bsel.Users(selectors.Any()))
// list b, err := r.NewBackup(ctx, bsel.Selector)
require.NoError(t, err)
// details runBackupLoadTest(t, ctx, &b, service)
bid := string(b.Results.BackupID)
runBackupListLoadTest(t, ctx, r, service, bid)
runBackupDetailsLoadTest(t, ctx, r, service, bid)
// restore // restore
rsel, err := bsel.ToExchangeRestore()
require.NoError(t, err)
rst, err := r.NewRestore(ctx, bid, rsel.Selector)
require.NoError(t, err)
runRestoreLoadTest(t, ctx, rst, service, b.Results.ItemsWritten)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -129,19 +243,35 @@ func (suite *RepositoryLoadTestOneDriveSuite) TeardownTest() {
logger.Flush(suite.ctx) logger.Flush(suite.ctx)
} }
func (suite *RepositoryLoadTestOneDriveSuite) TestExchange() { func (suite *RepositoryLoadTestOneDriveSuite) TestOneDrive() {
// var ( var (
// t = suite.T() t = suite.T()
// ctx = context.Background() ctx = context.Background()
// ) r = suite.repo
service = "one_drive"
)
// t.parallel() t.Parallel()
// backup // backup
bsel := selectors.NewOneDriveBackup()
bsel.Include(bsel.Users(selectors.Any()))
// list b, err := r.NewBackup(ctx, bsel.Selector)
require.NoError(t, err)
// details runBackupLoadTest(t, ctx, &b, service)
bid := string(b.Results.BackupID)
runBackupListLoadTest(t, ctx, r, service, bid)
runBackupDetailsLoadTest(t, ctx, r, service, bid)
// restore // restore
rsel, err := bsel.ToOneDriveRestore()
require.NoError(t, err)
rst, err := r.NewRestore(ctx, bid, rsel.Selector)
require.NoError(t, err)
runRestoreLoadTest(t, ctx, rst, service, b.Results.ItemsWritten)
} }