Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Improve change detector performance #1433

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/data_format_changes/i1186-change-detctor-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Modify change detector setup flow

This is not a breaking (production code) change.

This does however change the way the change detector sets up the target branch in a way that is incompatible with the current develop, this file is required to allow the CI to pass (including comparing develop vs master).
91 changes: 42 additions & 49 deletions tests/integration/change_detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ import (
"context"
"fmt"
"io/fs"
"math/rand"
"os"
"os/exec"
"path"
"runtime"
"strings"
"testing"

"github.com/sourcenetwork/defradb/client"
"time"
)

var skip bool

func IsDetectingDbChanges() bool {
return DetectDbChanges
}
Expand All @@ -33,6 +35,10 @@ func DetectDbChangesPreTestChecks(
t *testing.T,
collectionNames []string,
) bool {
if skip {
t.SkipNow()
}

if previousTestCaseTestName == t.Name() {
// The database format changer currently only supports running the first test
// case, if a second case is detected we return early
Expand Down Expand Up @@ -64,10 +70,21 @@ func detectDbChangesInit(repository string, targetBranch string) {
return
}

tempDir := os.TempDir()
defraTempDir := path.Join(os.TempDir(), "defradb")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick:

Suggested change
defraTempDir := path.Join(os.TempDir(), "defradb")
defradbTempDir := path.Join(os.TempDir(), "defradb")

changeDetectorTempDir := path.Join(defraTempDir, "tests", "changeDetector")

latestTargetCommitHash := getLatestCommit(repository, targetBranch)
detectDbChangesCodeDir = path.Join(tempDir, "defra", latestTargetCommitHash, "code")
detectDbChangesCodeDir = path.Join(changeDetectorTempDir, "code", latestTargetCommitHash)
rand.Seed(time.Now().Unix())
randNumber := rand.Int()
dbsDir := path.Join(changeDetectorTempDir, "dbs", fmt.Sprint(randNumber))

testPackagePath, isIntegrationTest := getTestPackagePath()
if !isIntegrationTest {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: When would that not be an integration test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bench suite uses this, and there might be other references too.

skip = true
return
}
rootDatabaseDir = path.Join(dbsDir, strings.ReplaceAll(testPackagePath, "/", "_"))

_, err := os.Stat(detectDbChangesCodeDir)
// Warning - there is a race condition here, where if running multiple packages in
Expand Down Expand Up @@ -110,22 +127,12 @@ func detectDbChangesInit(repository string, targetBranch string) {
}

areDatabaseFormatChangesDocumented = checkIfDatabaseFormatChangesAreDocumented()
}

func SetupDatabaseUsingTargetBranch(
ctx context.Context,
t *testing.T,
collectionNames []string,
) client.DB {
currentTestPackage, err := os.Getwd()
if err != nil {
panic(err)
if areDatabaseFormatChangesDocumented {
// Dont bother doing anything if the changes are documented
return
}

targetTestPackage := detectDbChangesCodeDir + "/tests/integration/" + strings.Split(
currentTestPackage,
"/tests/integration/",
)[1]
targetTestPackage := detectDbChangesCodeDir + "/tests/integration/" + testPackagePath

// If we are checking for database changes, and we are not seting up the database,
// then we must be in the main test process, and need to create a new process
Expand All @@ -135,55 +142,41 @@ func SetupDatabaseUsingTargetBranch(
"go",
"test",
"./...",
"--run",
fmt.Sprintf("^%s$", t.Name()),
"-v",
)

path := t.TempDir()

goTestCmd.Dir = targetTestPackage
goTestCmd.Env = os.Environ()
goTestCmd.Env = append(
goTestCmd.Env,
setupOnlyEnvName+"=true",
fileBadgerPathEnvName+"="+path,
rootDBFilePathEnvName+"="+rootDatabaseDir,
)
out, err := goTestCmd.Output()

if err != nil {
// If file is not found - this must be a new test and
// doesn't exist in the target branch, so we pass it
// because the child process tries to run the test, but
// if it doesnt find it, the parent test should pass (not panic).
if strings.Contains(err.Error(), ": no such file or directory") {
t.SkipNow()
} else {
// Only log the output if there is an error different from above,
// logging child test runs confuses the go test runner making it
// think there are no tests in the parent run (it will still
// run everything though)!
log.ErrorE(ctx, string(out), err)
panic(err)
}
log.ErrorE(context.TODO(), string(out), err)
panic(err)
}
}

refreshedDb, err := newBadgerFileDB(ctx, t, path)
// getTestPackagePath returns the path to the package currently under test, relative
// to `./tests/integration/`. Will return an empty string and false if the tests
// are not within that directory.
func getTestPackagePath() (string, bool) {
currentTestPackage, err := os.Getwd()
if err != nil {
panic(err)
}

_, err = refreshedDb.GetCollectionByName(ctx, collectionNames[0])
if err != nil {
if err.Error() == "datastore: key not found" {
// If collection is not found - this must be a new test and
// doesn't exist in the target branch, so we pass it
t.SkipNow()
} else {
panic(err)
}
splitPath := strings.Split(
currentTestPackage,
"/tests/integration/",
)

if len(splitPath) != 2 {
return "", false
}
return refreshedDb
return splitPath[1], true
}

func checkIfDatabaseFormatChangesAreDocumented() bool {
Expand Down
44 changes: 14 additions & 30 deletions tests/integration/explain/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,38 +154,22 @@ func ExecuteExplainRequestTestCase(
log.Info(ctx, explainTest.Description, logging.NewKV("Database", dbi.name))

if testUtils.DetectDbChanges {
if testUtils.SetupOnly {
setupDatabase(
ctx,
t,
dbi,
schema,
collectionNames,
explainTest.Description,
explainTest.ExpectedError,
explainTest.Docs,
immutable.None[map[int]map[int][]string](),
)
dbi.db.Close(ctx)
return
}

dbi.db.Close(ctx)
db = testUtils.SetupDatabaseUsingTargetBranch(ctx, t, collectionNames)
} else {
setupDatabase(
ctx,
t,
dbi,
schema,
collectionNames,
explainTest.Description,
explainTest.ExpectedError,
explainTest.Docs,
immutable.None[map[int]map[int][]string](),
)
t.SkipNow()
return
}

setupDatabase(
ctx,
t,
dbi,
schema,
collectionNames,
explainTest.Description,
explainTest.ExpectedError,
explainTest.Docs,
immutable.None[map[int]map[int][]string](),
)

result := db.ExecRequest(ctx, explainTest.Request)
if assertExplainRequestResults(
ctx,
Expand Down
27 changes: 13 additions & 14 deletions tests/integration/utils2.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"context"
"fmt"
"os"
"path"
"reflect"
"strings"
"syscall"
Expand All @@ -39,6 +40,7 @@ const (
memoryBadgerEnvName = "DEFRA_BADGER_MEMORY"
fileBadgerEnvName = "DEFRA_BADGER_FILE"
fileBadgerPathEnvName = "DEFRA_BADGER_FILE_PATH"
rootDBFilePathEnvName = "DEFRA_TEST_ROOT"
inMemoryEnvName = "DEFRA_IN_MEMORY"
setupOnlyEnvName = "DEFRA_SETUP_ONLY"
detectDbChangesEnvName = "DEFRA_DETECT_DATABASE_CHANGES"
Expand Down Expand Up @@ -78,6 +80,7 @@ var (
const subscriptionTimeout = 1 * time.Second

var databaseDir string
var rootDatabaseDir string

/*
If this is set to true the integration test suite will instead of its normal profile do
Expand Down Expand Up @@ -111,6 +114,7 @@ func init() {
badgerFileValue, _ := os.LookupEnv(fileBadgerEnvName)
badgerInMemoryValue, _ := os.LookupEnv(memoryBadgerEnvName)
databaseDir, _ = os.LookupEnv(fileBadgerPathEnvName)
rootDatabaseDir, _ = os.LookupEnv(rootDBFilePathEnvName)
detectDbChangesValue, _ := os.LookupEnv(detectDbChangesEnvName)
inMemoryStoreValue, _ := os.LookupEnv(inMemoryEnvName)
repositoryValue, repositorySpecified := os.LookupEnv(repositoryEnvName)
Expand Down Expand Up @@ -195,14 +199,16 @@ func NewInMemoryDB(ctx context.Context) (client.DB, error) {
}

func NewBadgerFileDB(ctx context.Context, t testing.TB) (client.DB, error) {
var path string
if databaseDir == "" {
path = t.TempDir()
var dbPath string
if databaseDir != "" {
dbPath = databaseDir
} else if rootDatabaseDir != "" {
dbPath = path.Join(rootDatabaseDir, t.Name())
} else {
path = databaseDir
dbPath = t.TempDir()
}

return newBadgerFileDB(ctx, t, path)
return newBadgerFileDB(ctx, t, dbPath)
}

func newBadgerFileDB(ctx context.Context, t testing.TB, path string) (client.DB, error) {
Expand Down Expand Up @@ -571,15 +577,8 @@ func getStartingNodes(

// If nodes have not been explicitly configured via actions, setup a default one.
if !hasExplicitNode {
var db client.DB
if DetectDbChanges && !SetupOnly {
// Setup the database using the target branch, and then refresh the current instance
db = SetupDatabaseUsingTargetBranch(ctx, t, collectionNames)
} else {
var err error
db, err = GetDatabase(ctx, t, dbt)
require.Nil(t, err)
}
db, err := GetDatabase(ctx, t, dbt)
require.Nil(t, err)

return []*node.Node{
{
Expand Down