blob: 1b435e5ca433059e1c7fd5d222bdcf58a10878fa [file] [log] [blame]
package migration
import (
"context"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.skia.org/infra/perf/go/clustering2"
"go.skia.org/infra/perf/go/dataframe"
"go.skia.org/infra/perf/go/regression"
"go.skia.org/infra/perf/go/regression/sqlregression2store"
"go.skia.org/infra/perf/go/regression/sqlregressionstore"
"go.skia.org/infra/perf/go/sql/sqltest"
"go.skia.org/infra/perf/go/stepfit"
"go.skia.org/infra/perf/go/types"
"go.skia.org/infra/perf/go/ui/frame"
)
func setup(t *testing.T) (context.Context, *RegressionMigrator, *sqlregressionstore.SQLRegressionStore, *sqlregression2store.SQLRegression2Store) {
ctx := context.Background()
db := sqltest.NewSpannerDBForTests(t, "regstore")
migrator, _ := New(ctx, db)
legacyStore, _ := sqlregressionstore.New(db)
newStore, _ := sqlregression2store.New(db, nil)
return ctx, migrator, legacyStore, newStore
}
func createLegacyRegressions(ctx context.Context, count int, commitNumber types.CommitNumber, alertID string, legacyStore *sqlregressionstore.SQLRegressionStore) {
df := &frame.FrameResponse{
DataFrame: &dataframe.DataFrame{
Header: []*dataframe.ColumnHeader{
{Offset: 1},
{Offset: 2},
{Offset: 3},
},
},
}
clusterSummary := &clustering2.ClusterSummary{
StepFit: &stepfit.StepFit{
TurningPoint: 1,
},
Timestamp: time.Now(),
Centroid: []float32{1.0, 5.0, 5.0},
}
for i := 0; i < count; i++ {
_, _, _ = legacyStore.SetHigh(ctx, commitNumber, alertID, df, clusterSummary)
}
}
func assertRegressions(t *testing.T, legacy *regression.Regression, new *regression.Regression) {
assert.Equal(t, legacy.Frame, new.Frame)
assert.Equal(t, legacy.High, new.High)
}
func TestMigrate_Single_Success(t *testing.T) {
ctx, migrator, legacyStore, newStore := setup(t)
commitNumber := types.CommitNumber(1)
alertID := "123"
createLegacyRegressions(ctx, 1, commitNumber, alertID, legacyStore)
err := migrator.migrateRegressions(ctx, 1)
assert.Nil(t, err)
regressionsMap, err := newStore.Range(ctx, commitNumber, commitNumber)
assert.Nil(t, err)
assert.NotNil(t, regressionsMap)
regressionsForCommit := regressionsMap[commitNumber]
newRegression := regressionsForCommit.ByAlertID[alertID]
assert.NotNil(t, newRegression)
legacyRegressionsMap, _ := legacyStore.Range(ctx, commitNumber, commitNumber)
legacyRegression := legacyRegressionsMap[commitNumber].ByAlertID[alertID]
// Compare the legacy values.
assertRegressions(t, legacyRegression, newRegression)
// Assert the new values specific to the regression2 schema
assert.Equal(t, alertID, strconv.Itoa(int(newRegression.AlertId)))
assert.Equal(t, commitNumber, newRegression.CommitNumber)
assert.NotEmpty(t, newRegression.Id)
// Ensure that no more legacy regressions are remaining to migrate.
remainingRegressions, _ := legacyStore.GetRegressionsToMigrate(ctx, 1)
assert.Equal(t, 0, len(remainingRegressions))
}
func TestMigrate_Multiple_Success(t *testing.T) {
ctx, migrator, legacyStore, newStore := setup(t)
alertID := "123"
// Create 10 regressions for different commits
for i := 1; i <= 10; i++ {
commitNumber := types.CommitNumber(i)
createLegacyRegressions(ctx, 1, commitNumber, alertID, legacyStore)
}
// Now let's migrate them in a batch of 10
err := migrator.migrateRegressions(ctx, 10)
assert.Nil(t, err)
regressionsMap, err := newStore.Range(ctx, 1, 10)
assert.Nil(t, err)
assert.NotNil(t, regressionsMap)
assert.Equal(t, 10, len(regressionsMap))
legacyRegressionsMap, _ := legacyStore.Range(ctx, 1, 10)
assert.Equal(t, 10, len(legacyRegressionsMap))
for i := 1; i <= 10; i++ {
commitNumber := types.CommitNumber(i)
newRegression := regressionsMap[commitNumber].ByAlertID[alertID]
oldRegression := legacyRegressionsMap[commitNumber].ByAlertID[alertID]
assertRegressions(t, oldRegression, newRegression)
assert.Equal(t, alertID, strconv.Itoa(int(newRegression.AlertId)))
assert.Equal(t, commitNumber, newRegression.CommitNumber)
assert.NotEmpty(t, newRegression.Id)
}
}
func TestMigrate_Partial_Success(t *testing.T) {
ctx, migrator, legacyStore, newStore := setup(t)
alertID := "123"
// Create 10 regressions for different commits
for i := 1; i <= 10; i++ {
commitNumber := types.CommitNumber(i)
createLegacyRegressions(ctx, 1, commitNumber, alertID, legacyStore)
}
// Now let's migrate some of them in a batch of 5.
migrationCount := 5
err := migrator.migrateRegressions(ctx, migrationCount)
assert.Nil(t, err)
regressionsMap, err := newStore.Range(ctx, 1, 10)
assert.Nil(t, err)
assert.NotNil(t, regressionsMap)
assert.Equal(t, migrationCount, len(regressionsMap))
legacyRegressionsMap, _ := legacyStore.Range(ctx, 1, 10)
assert.Equal(t, 10, len(legacyRegressionsMap))
for commitNumber := range regressionsMap {
newRegression := regressionsMap[commitNumber].ByAlertID[alertID]
oldRegression := legacyRegressionsMap[commitNumber].ByAlertID[alertID]
assertRegressions(t, oldRegression, newRegression)
assert.Equal(t, alertID, strconv.Itoa(int(newRegression.AlertId)))
assert.Equal(t, commitNumber, newRegression.CommitNumber)
assert.NotEmpty(t, newRegression.Id)
}
// Ensure that there are 5 regressions remaining.
remainingLegacyRegressions, _ := legacyStore.GetRegressionsToMigrate(ctx, 10)
assert.Equal(t, 5, len(remainingLegacyRegressions))
}
func TestMigrate_MultipleBatches_Success(t *testing.T) {
ctx, migrator, legacyStore, newStore := setup(t)
alertID := "123"
totalCount := 10
// Create 10 regressions for different commits
for i := 1; i <= totalCount; i++ {
commitNumber := types.CommitNumber(i)
createLegacyRegressions(ctx, 1, commitNumber, alertID, legacyStore)
}
// Now let's migrate some of them in a batch of 7.
migrationCount := 7
err := migrator.migrateRegressions(ctx, migrationCount)
assert.Nil(t, err)
regressionsMap, err := newStore.Range(ctx, 1, 10)
assert.Nil(t, err)
assert.NotNil(t, regressionsMap)
assert.Equal(t, migrationCount, len(regressionsMap))
legacyRegressionsMap, _ := legacyStore.Range(ctx, 1, 10)
assert.Equal(t, 10, len(legacyRegressionsMap))
for commitNumber := range regressionsMap {
newRegression := regressionsMap[commitNumber].ByAlertID[alertID]
oldRegression := legacyRegressionsMap[commitNumber].ByAlertID[alertID]
assertRegressions(t, oldRegression, newRegression)
assert.Equal(t, alertID, strconv.Itoa(int(newRegression.AlertId)))
assert.Equal(t, commitNumber, newRegression.CommitNumber)
assert.NotEmpty(t, newRegression.Id)
}
// Ensure that the no of remaining regressions is correct.
remainingLegacyRegressions, _ := legacyStore.GetRegressionsToMigrate(ctx, totalCount)
assert.Equal(t, totalCount-migrationCount, len(remainingLegacyRegressions))
// Now run another batch.
err = migrator.migrateRegressions(ctx, migrationCount)
assert.Nil(t, err)
// Ensure that the no regressions are remaining.
remainingLegacyRegressions, _ = legacyStore.GetRegressionsToMigrate(ctx, totalCount)
assert.Equal(t, 0, len(remainingLegacyRegressions))
}
func Test_Migrate_Prev_Migrated_Regression(t *testing.T) {
ctx, migrator, legacyStore, newStore := setup(t)
alertID := "123"
commitNumber := types.CommitNumber(222)
createLegacyRegressions(ctx, 1, commitNumber, alertID, legacyStore)
// Lets migrate this regression first.
err := migrator.migrateRegressions(ctx, 1)
assert.Nil(t, err)
// Get the regression from the new store.
regressionsMap, _ := newStore.Range(ctx, commitNumber, commitNumber)
regressionsForCommit := regressionsMap[commitNumber]
newRegression := regressionsForCommit.ByAlertID[alertID]
// Now update the regression in the legacy store. This should mark the
// legacy regressions as available to migrate.
_ = legacyStore.TriageHigh(ctx, commitNumber, alertID, regression.TriageStatus{
Status: regression.Positive,
Message: "Updating the legacy regression.",
})
regressionsToMigrate, err := legacyStore.GetRegressionsToMigrate(ctx, 1)
assert.Nil(t, err)
assert.Equal(t, 1, len(regressionsToMigrate))
assert.NotEmpty(t, regressionsToMigrate[0].Id)
// Ensure that the legacy regression has the same id as the newly created one.
assert.Equal(t, newRegression.Id, regressionsToMigrate[0].Id)
// Run migration again.
err = migrator.migrateRegressions(ctx, 1)
assert.Nil(t, err)
// Get the regression from the new store.
regressionsMap, _ = newStore.Range(ctx, commitNumber, commitNumber)
regressionsForCommit = regressionsMap[commitNumber]
newRegression = regressionsForCommit.ByAlertID[alertID]
assert.NotNil(t, newRegression.HighStatus)
}
func Test_Migrate_Mixed_Regression(t *testing.T) {
ctx, migrator, legacyStore, newStore := setup(t)
alertID := "123"
commitNumber := types.CommitNumber(222)
df := &frame.FrameResponse{
DataFrame: &dataframe.DataFrame{
Header: []*dataframe.ColumnHeader{
{Offset: 1},
{Offset: 2},
{Offset: 3},
},
},
}
clusterSummary := &clustering2.ClusterSummary{
StepFit: &stepfit.StepFit{
TurningPoint: 1,
},
Timestamp: time.Now(),
Centroid: []float32{1.0, 5.0, 5.0},
}
// Set both high and low values to create a mixed regression
_, _, _ = legacyStore.SetHigh(ctx, commitNumber, alertID, df, clusterSummary)
_, _, _ = legacyStore.SetLow(ctx, commitNumber, alertID, df, clusterSummary)
err := migrator.migrateRegressions(ctx, 1)
assert.Nil(t, err)
// Get the regression from the new store.
regressionsMap, _ := newStore.Range(ctx, commitNumber, commitNumber)
regressionsForCommit := regressionsMap[commitNumber]
newRegression := regressionsForCommit.ByAlertID[alertID]
assert.NotNil(t, newRegression.High)
assert.NotNil(t, newRegression.Low)
}