From 9a5b3099c8710b2eb384283692a7e292f88ba87a Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 13:50:03 -0700 Subject: [PATCH 01/23] Beginning pulling enginetest logic out into reusable methods with a new harness type --- .../sqle/enginetest/dolt_engine_test.go | 9 +++-- .../doltcore/sqle/enginetest/dolt_harness.go | 35 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 024d1e4ddf4..69c5db8a702 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -120,21 +120,24 @@ func TestSingleQuery(t *testing.T) { } func TestSchemaOverrides(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunSchemaOverridesTest(t, harness) +} + +func RunSchemaOverridesTest(t *testing.T, harness DoltEnginetestHarness) { tcc := &testCommitClock{} cleanup := installTestCommitClock(tcc) defer cleanup() for _, script := range SchemaOverrideTests { sql.RunWithNowFunc(tcc.Now, func() error { - harness := newDoltHarness(t) + harness = harness.NewHarness(t) harness.Setup(setup.MydbData) engine, err := harness.NewEngine(t) if err != nil { panic(err) } - // engine.EngineAnalyzer().Debug = true - // engine.EngineAnalyzer().Verbose = true enginetest.TestScriptWithEngine(t, engine, harness, script) return nil diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 7c3635f03f8..02a574378a6 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -61,15 +61,28 @@ type DoltHarness struct { setupTestProcedures bool } -var _ enginetest.Harness = (*DoltHarness)(nil) -var _ enginetest.SkippingHarness = (*DoltHarness)(nil) -var _ enginetest.ClientHarness = (*DoltHarness)(nil) -var _ enginetest.IndexHarness = (*DoltHarness)(nil) -var _ enginetest.VersionedDBHarness = (*DoltHarness)(nil) -var _ enginetest.ForeignKeyHarness = (*DoltHarness)(nil) -var _ enginetest.KeylessTableHarness = (*DoltHarness)(nil) -var _ enginetest.ReadOnlyDatabaseHarness = (*DoltHarness)(nil) -var _ enginetest.ValidatingHarness = (*DoltHarness)(nil) +func (d *DoltHarness) NewHarness(t *testing.T) DoltEnginetestHarness { + return newDoltHarness(t) +} + +type DoltEnginetestHarness interface { + enginetest.Harness + enginetest.SkippingHarness + enginetest.ClientHarness + enginetest.IndexHarness + enginetest.VersionedDBHarness + enginetest.ForeignKeyHarness + enginetest.KeylessTableHarness + enginetest.ReadOnlyDatabaseHarness + enginetest.ValidatingHarness + + // NewHarness returns a new harness of the same type + NewHarness(t *testing.T) DoltEnginetestHarness +} + +var _ DoltEnginetestHarness = &DoltHarness{} + +// Next: define an interface that can be shared with doltgres // newDoltHarness creates a new harness for testing Dolt, using an in-memory filesystem and an in-memory blob store. func newDoltHarness(t *testing.T) *DoltHarness { @@ -82,6 +95,10 @@ func newDoltHarness(t *testing.T) *DoltHarness { return dh } +func newDoltEnginetestHarness(t *testing.T) DoltEnginetestHarness { + return newDoltHarness(t) +} + // newDoltHarnessForLocalFilesystem creates a new harness for testing Dolt, using // the local filesystem for all storage, instead of in-memory versions. This setup // is useful for testing functionality that requires a real filesystem. From 606d42e7dae399bd7217d1d7c5df87b3d471caa7 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 13:54:13 -0700 Subject: [PATCH 02/23] Added Close method, more tests migrated --- .../sqle/enginetest/dolt_engine_test.go | 19 ++++++++++++++----- .../doltcore/sqle/enginetest/dolt_harness.go | 5 ++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 69c5db8a702..a28449f6024 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -180,9 +180,14 @@ func newUpdateResult(matched, updated int) gmstypes.OkResult { } func TestAutoIncrementTrackerLockMode(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunAutoIncrementTrackerLockModeTest(t, harness) +} + +func RunAutoIncrementTrackerLockModeTest(t *testing.T, harness DoltEnginetestHarness) { for _, lockMode := range []int64{0, 1, 2} { t.Run(fmt.Sprintf("lock mode %d", lockMode), func(t *testing.T) { - testAutoIncrementTrackerWithLockMode(t, lockMode) + testAutoIncrementTrackerWithLockMode(t, harness, lockMode) }) } } @@ -190,8 +195,7 @@ func TestAutoIncrementTrackerLockMode(t *testing.T) { // testAutoIncrementTrackerWithLockMode tests that interleaved inserts don't cause deadlocks, regardless of the value of innodb_autoinc_lock_mode. // In a real use case, these interleaved operations would be happening in different sessions on different threads. // In order to make the test behave predictably, we manually interleave the two iterators. -func testAutoIncrementTrackerWithLockMode(t *testing.T, lockMode int64) { - +func testAutoIncrementTrackerWithLockMode(t *testing.T, harness DoltEnginetestHarness, lockMode int64) { err := sql.SystemVariables.AssignValues(map[string]interface{}{"innodb_autoinc_lock_mode": lockMode}) require.NoError(t, err) @@ -205,7 +209,7 @@ func testAutoIncrementTrackerWithLockMode(t *testing.T, lockMode int64) { "CREATE VIEW sequence5bit AS SELECT b1.v + 2*b2.v + 4*b3.v + 8*b4.v + 16*b5.v AS v from bin b1, bin b2, bin b3, bin b4, bin b5;", }} - harness := newDoltHarness(t) + harness = harness.NewHarness(t) defer harness.Close() harness.Setup(setup.MydbData, setupScripts) e := mustNewEngine(t, harness) @@ -533,8 +537,13 @@ func TestSingleScriptPrepared(t *testing.T) { } func TestVersionedQueries(t *testing.T) { - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) defer h.Close() + + RunVersionedQueriesTest(t, h) +} + +func RunVersionedQueriesTest(t *testing.T, h DoltEnginetestHarness) { h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) e, err := h.NewEngine(t) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 02a574378a6..44644398815 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -76,8 +76,11 @@ type DoltEnginetestHarness interface { enginetest.ReadOnlyDatabaseHarness enginetest.ValidatingHarness - // NewHarness returns a new harness of the same type + // NewHarness returns a new uninitialized harness of the same type NewHarness(t *testing.T) DoltEnginetestHarness + + // Close closes the harness, freeing up any resources it may have allocated + Close() } var _ DoltEnginetestHarness = &DoltHarness{} From af71998d099287604b69963c2aa7c95994cdc7b9 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 14:13:42 -0700 Subject: [PATCH 03/23] more conversion --- .../doltcore/sqle/enginetest/dolt_engine_test.go | 12 ++++++++---- .../doltcore/sqle/enginetest/dolt_harness.go | 14 +++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index a28449f6024..6d3e30ce67c 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -569,6 +569,11 @@ func TestAnsiQuotesSqlModePrepared(t *testing.T) { // Tests of choosing the correct execution plan independent of result correctness. Mostly useful for confirming that // the right indexes are being used for joining tables. func TestQueryPlans(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunQueryTestPlans(t, harness) +} + +func RunQueryTestPlans(t *testing.T, harness DoltEnginetestHarness) { // Dolt supports partial keys, so the index matched is different for some plans // TODO: Fix these differences by implementing partial key matching in the memory tables, or the engine itself skipped := []string{ @@ -582,8 +587,7 @@ func TestQueryPlans(t *testing.T) { } // Parallelism introduces Exchange nodes into the query plans, so disable. // TODO: exchange nodes should really only be part of the explain plan under certain debug settings - harness := newDoltHarness(t).WithSkippedQueries(skipped) - harness.configureStats = true + harness = harness.NewHarness(t).WithSkippedQueries(skipped).WithConfigureStats(true) if !types.IsFormat_DOLT(types.Format_Default) { // only new format supports reverse IndexTableAccess reverseIndexSkip := []string{ @@ -738,7 +742,7 @@ func TestIgnoreIntoWithDuplicateUniqueKeyKeylessPrepared(t *testing.T) { } func TestInsertIntoErrors(t *testing.T) { - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) defer h.Close() h = h.WithSkippedQueries([]string{ "create table bad (vb varbinary(65535))", @@ -2942,7 +2946,7 @@ func TestInsertIgnoreScriptsPrepared(t *testing.T) { func TestInsertErrorScriptsPrepared(t *testing.T) { skipPreparedTests(t) - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) defer h.Close() h = h.WithSkippedQueries([]string{ "create table bad (vb varbinary(65535))", diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 44644398815..1ef215a05f2 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -61,6 +61,12 @@ type DoltHarness struct { setupTestProcedures bool } +func (d *DoltHarness) WithConfigureStats(configureStats bool) DoltEnginetestHarness { + nd := *d + nd.configureStats = configureStats + return &nd +} + func (d *DoltHarness) NewHarness(t *testing.T) DoltEnginetestHarness { return newDoltHarness(t) } @@ -79,6 +85,12 @@ type DoltEnginetestHarness interface { // NewHarness returns a new uninitialized harness of the same type NewHarness(t *testing.T) DoltEnginetestHarness + // WithSkippedQueries returns a copy of the harness with the given queries skipped + WithSkippedQueries(skipped []string) DoltEnginetestHarness + + // WithConfigureStats returns a copy of the harness with the given configureStats value + WithConfigureStats(configureStats bool) DoltEnginetestHarness + // Close closes the harness, freeing up any resources it may have allocated Close() } @@ -306,7 +318,7 @@ func (d *DoltHarness) WithParallelism(parallelism int) *DoltHarness { } // WithSkippedQueries returns a copy of the harness with the given queries skipped -func (d *DoltHarness) WithSkippedQueries(queries []string) *DoltHarness { +func (d *DoltHarness) WithSkippedQueries(queries []string) DoltEnginetestHarness { nd := *d nd.skippedQueries = append(d.skippedQueries, queries...) return &nd From 5b7779e6a4e2b7b1f11639dcc89ddfc58099403e Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 14:33:45 -0700 Subject: [PATCH 04/23] more interface conversions --- .../sqle/enginetest/dolt_engine_test.go | 20 +++++++++---------- .../doltcore/sqle/enginetest/dolt_harness.go | 13 +++++++++--- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 6d3e30ce67c..7c802f5780e 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -612,8 +612,7 @@ func RunQueryTestPlans(t *testing.T, harness DoltEnginetestHarness) { } func TestIntegrationQueryPlans(t *testing.T) { - harness := newDoltHarness(t) - harness.configureStats = true + harness := newDoltEnginetestHarness(t).WithConfigureStats(true) defer harness.Close() enginetest.TestIntegrationPlans(t, harness) } @@ -623,7 +622,11 @@ func TestDoltDiffQueryPlans(t *testing.T) { t.Skip("only new format support system table indexing") } - harness := newDoltHarness(t).WithParallelism(2) // want Exchange nodes + harness := newDoltEnginetestHarness(t).WithParallelism(2) // want Exchange nodes + RunDoltDiffQueryPlansTest(t, harness) +} + +func RunDoltDiffQueryPlansTest(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() harness.Setup(setup.SimpleSetup...) e, err := harness.NewEngine(t) @@ -2209,10 +2212,9 @@ func TestBrokenSystemTableQueries(t *testing.T) { func TestHistorySystemTable(t *testing.T) { harness := newDoltHarness(t).WithParallelism(2) - defer harness.Close() - harness.Setup(setup.MydbData) for _, test := range HistorySystemTableScriptTests { - harness.engine = nil + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) t.Run(test.Name, func(t *testing.T) { enginetest.TestScript(t, harness, test) }) @@ -2220,11 +2222,9 @@ func TestHistorySystemTable(t *testing.T) { } func TestHistorySystemTablePrepared(t *testing.T) { - harness := newDoltHarness(t).WithParallelism(2) - defer harness.Close() - harness.Setup(setup.MydbData) for _, test := range HistorySystemTableScriptTests { - harness.engine = nil + harness := newDoltHarness(t).WithParallelism(2) + harness.Setup(setup.MydbData) t.Run(test.Name, func(t *testing.T) { enginetest.TestScriptPrepared(t, harness, test) }) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 1ef215a05f2..b40d38d0f7b 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -88,11 +88,18 @@ type DoltEnginetestHarness interface { // WithSkippedQueries returns a copy of the harness with the given queries skipped WithSkippedQueries(skipped []string) DoltEnginetestHarness + // WithParallelism returns a copy of the harness with parallelism set to the given number of threads + WithParallelism(parallelism int) DoltEnginetestHarness + // WithConfigureStats returns a copy of the harness with the given configureStats value WithConfigureStats(configureStats bool) DoltEnginetestHarness - + + // SkipSetupCommit configures to harness to skip the commit after setup scripts are run + SkipSetupCommit() + // Close closes the harness, freeing up any resources it may have allocated - Close() + Close() + } var _ DoltEnginetestHarness = &DoltHarness{} @@ -311,7 +318,7 @@ func filterStatsOnlyQueries(scripts []setup.SetupScript) []setup.SetupScript { // WithParallelism returns a copy of the harness with parallelism set to the given number of threads. A value of 0 or // less means to use the system parallelism settings. -func (d *DoltHarness) WithParallelism(parallelism int) *DoltHarness { +func (d *DoltHarness) WithParallelism(parallelism int) DoltEnginetestHarness { nd := *d nd.parallelism = parallelism return &nd From b1b67fbed8f6e3b4b392e844afe4d4092bc17cb4 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 15:33:51 -0700 Subject: [PATCH 05/23] More refactoring --- .../sqle/enginetest/dolt_engine_test.go | 60 +++++++++++++++---- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 7c802f5780e..3c77fb8b332 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -639,9 +639,14 @@ func RunDoltDiffQueryPlansTest(t *testing.T, harness DoltEnginetestHarness) { } func TestBranchPlans(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunBranchPlanTests(t, harness) +} + +func RunBranchPlanTests(t *testing.T, harness DoltEnginetestHarness) { for _, script := range BranchPlanTests { t.Run(script.Name, func(t *testing.T) { - harness := newDoltHarness(t) + harness = harness.NewHarness(t) defer harness.Close() e := mustNewEngine(t, harness) @@ -667,15 +672,19 @@ func TestQueryErrors(t *testing.T) { } func TestInfoSchema(t *testing.T) { - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) + RunInfoSchemaTests(t, h) +} + +func RunInfoSchemaTests(t *testing.T, h DoltEnginetestHarness) { defer h.Close() enginetest.TestInfoSchema(t, h) for _, script := range DoltInfoSchemaScripts { func() { - harness := newDoltHarness(t) - defer harness.Close() - enginetest.TestScript(t, harness, script) + h = h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) }() } } @@ -746,22 +755,32 @@ func TestIgnoreIntoWithDuplicateUniqueKeyKeylessPrepared(t *testing.T) { func TestInsertIntoErrors(t *testing.T) { h := newDoltEnginetestHarness(t) - defer h.Close() + RunInsertIntoErrorsTest(t, h) +} + +func RunInsertIntoErrorsTest(t *testing.T, h DoltEnginetestHarness) { h = h.WithSkippedQueries([]string{ "create table bad (vb varbinary(65535))", "insert into bad values (repeat('0', 65536))", }) + defer h.Close() enginetest.TestInsertIntoErrors(t, h) } func TestGeneratedColumns(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunGeneratedColumnTests(t, harness) +} + +func RunGeneratedColumnTests(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() enginetest.TestGeneratedColumns(t, // virtual indexes are failing for certain lookups on this test - newDoltHarness(t).WithSkippedQueries([]string{"create table t (pk int primary key, col1 int as (pk + 1));"})) + harness.WithSkippedQueries([]string{"create table t (pk int primary key, col1 int as (pk + 1));"})) for _, script := range GeneratedColumnMergeTestScripts { func() { - h := newDoltHarness(t) + h := harness.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -964,8 +983,7 @@ func TestJoinPlanning(t *testing.T) { if types.IsFormat_LD(types.Format_Default) { t.Skip("DOLT_LD keyless indexes are not sorted") } - h := newDoltHarness(t) - h.configureStats = true + h := newDoltEnginetestHarness(t).WithConfigureStats(true) defer h.Close() enginetest.TestJoinPlanning(t, h) } @@ -1044,9 +1062,14 @@ func TestRowLimit(t *testing.T) { } func TestBranchDdl(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunBranchDdlTest(t, h) +} + +func RunBranchDdlTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DdlBranchTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1054,9 +1077,14 @@ func TestBranchDdl(t *testing.T) { } func TestBranchDdlPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunBranchDdlTestPrepared(t, h) +} + +func RunBranchDdlTestPrepared(t *testing.T, h DoltEnginetestHarness) { for _, script := range DdlBranchTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, script) }() @@ -1133,6 +1161,10 @@ func TestIndexes(t *testing.T) { func TestIndexPrefix(t *testing.T) { skipOldFormat(t) harness := newDoltHarness(t) + RunIndexPrefixTest(t, harness) +} + +func RunIndexPrefixTest(t *testing.T, harness *DoltHarness) { defer harness.Close() enginetest.TestIndexPrefix(t, harness) for _, script := range DoltIndexPrefixScripts { @@ -1144,6 +1176,10 @@ func TestBigBlobs(t *testing.T) { skipOldFormat(t) h := newDoltHarness(t) + RunBigBlobsTest(t, h) +} + +func RunBigBlobsTest(t *testing.T, h *DoltHarness) { defer h.Close() h.Setup(setup.MydbData, setup.BlobData) for _, tt := range BigBlobQueries { From 9ab68be215f65e5bdb419bbab4ebcc6ef64907e4 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 15:41:30 -0700 Subject: [PATCH 06/23] More refactoring --- .../sqle/enginetest/dolt_engine_test.go | 18 ++++++++++++++---- .../doltcore/sqle/enginetest/dolt_harness.go | 2 -- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 3c77fb8b332..96f0cec681d 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1188,8 +1188,13 @@ func RunBigBlobsTest(t *testing.T, h *DoltHarness) { } func TestDropDatabase(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDropEngineTest(t, h) +} + +func RunDropEngineTest(t *testing.T, h DoltEnginetestHarness) { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, queries.ScriptTest{ Name: "Drop database engine tests for Dolt only", @@ -1223,7 +1228,7 @@ func TestDropDatabase(t *testing.T) { }() t.Skip("Dolt doesn't yet support dropping the primary database, which these tests do") - h := newDoltHarness(t) + h = h.NewHarness(t) defer h.Close() enginetest.TestDropDatabase(t, h) } @@ -1247,6 +1252,11 @@ func TestForeignKeys(t *testing.T) { } func TestForeignKeyBranches(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunForeignKeyBranchesTest(t, h) +} + +func RunForeignKeyBranchesTest(t *testing.T, h DoltEnginetestHarness) { setupPrefix := []string{ "call dolt_branch('b1')", "use mydb/b1", @@ -1259,7 +1269,7 @@ func TestForeignKeyBranches(t *testing.T) { } for _, script := range queries.ForeignKeyTests { // New harness for every script because we create branches - h := newDoltHarness(t) + h := h.NewHarness(t) h.Setup(setup.MydbData, setup.Parent_childData) modifiedScript := script modifiedScript.SetUpScript = append(setupPrefix, modifiedScript.SetUpScript...) @@ -1269,7 +1279,7 @@ func TestForeignKeyBranches(t *testing.T) { for _, script := range ForeignKeyBranchTests { // New harness for every script because we create branches - h := newDoltHarness(t) + h := h.NewHarness(t) h.Setup(setup.MydbData, setup.Parent_childData) enginetest.TestScript(t, h, script) } diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index b40d38d0f7b..eeb1d680bf0 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -104,8 +104,6 @@ type DoltEnginetestHarness interface { var _ DoltEnginetestHarness = &DoltHarness{} -// Next: define an interface that can be shared with doltgres - // newDoltHarness creates a new harness for testing Dolt, using an in-memory filesystem and an in-memory blob store. func newDoltHarness(t *testing.T) *DoltHarness { dh := &DoltHarness{ From fcf7450881d7744b0082ddbb68664de6581a382a Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 15:49:10 -0700 Subject: [PATCH 07/23] More refactoring --- .../sqle/enginetest/dolt_engine_test.go | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 96f0cec681d..00d80b022ac 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1286,6 +1286,11 @@ func RunForeignKeyBranchesTest(t *testing.T, h DoltEnginetestHarness) { } func TestForeignKeyBranchesPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunForeignKeyBranchesPreparedTest(t, h) +} + +func RunForeignKeyBranchesPreparedTest(t *testing.T, h DoltEnginetestHarness) { setupPrefix := []string{ "call dolt_branch('b1')", "use mydb/b1", @@ -1298,7 +1303,7 @@ func TestForeignKeyBranchesPrepared(t *testing.T) { } for _, script := range queries.ForeignKeyTests { // New harness for every script because we create branches - h := newDoltHarness(t) + h := h.NewHarness(t) h.Setup(setup.MydbData, setup.Parent_childData) modifiedScript := script modifiedScript.SetUpScript = append(setupPrefix, modifiedScript.SetUpScript...) @@ -1308,7 +1313,7 @@ func TestForeignKeyBranchesPrepared(t *testing.T) { for _, script := range ForeignKeyBranchTests { // New harness for every script because we create branches - h := newDoltHarness(t) + h := h.NewHarness(t) h.Setup(setup.MydbData, setup.Parent_childData) enginetest.TestScriptPrepared(t, h, script) } @@ -1369,9 +1374,14 @@ func TestViews(t *testing.T) { } func TestBranchViews(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunBranchViewsTest(t, h) +} + +func RunBranchViewsTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range ViewBranchTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1379,9 +1389,14 @@ func TestBranchViews(t *testing.T) { } func TestBranchViewsPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunBranchViewsPreparedTest(t, h) +} + +func RunBranchViewsPreparedTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range ViewBranchTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, script) }() @@ -1389,7 +1404,11 @@ func TestBranchViewsPrepared(t *testing.T) { } func TestVersionedViews(t *testing.T) { - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) + RunVersionedViewsTest(t, h) +} + +func RunVersionedViewsTest(t *testing.T, h DoltEnginetestHarness) { defer h.Close() h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) From 7cd8a29cd6665b7898303aa705ccfa23f3577c3f Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 16:14:19 -0700 Subject: [PATCH 08/23] More refactoring --- .../sqle/enginetest/dolt_engine_test.go | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 00d80b022ac..0d68993f906 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1491,7 +1491,11 @@ func TestAlterTable(t *testing.T) { } func TestVariables(t *testing.T) { - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) + RunVariableTest(t, h) +} + +func RunVariableTest(t *testing.T, h DoltEnginetestHarness) { defer h.Close() enginetest.TestVariables(t, h) for _, script := range DoltSystemVariables { @@ -1539,6 +1543,7 @@ func TestJsonScripts(t *testing.T) { skippedTests := []string{ "round-trip into table", // The current Dolt JSON format does not preserve decimals and unsigneds in JSON. } + // TODO: fix this, use a skipping harness enginetest.TestJsonScripts(t, h, skippedTests) } @@ -1555,24 +1560,33 @@ func TestRollbackTriggers(t *testing.T) { } func TestStoredProcedures(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunStoredProceduresTest(t, h) +} + +func RunStoredProceduresTest(t *testing.T, h DoltEnginetestHarness) { tests := make([]queries.ScriptTest, 0, len(queries.ProcedureLogicTests)) for _, test := range queries.ProcedureLogicTests { - //TODO: this passes locally but SOMETIMES fails tests on GitHub, no clue why + // TODO: this passes locally but SOMETIMES fails tests on GitHub, no clue why if test.Name != "ITERATE and LEAVE loops" { tests = append(tests, test) } } queries.ProcedureLogicTests = tests - h := newDoltHarness(t) defer h.Close() enginetest.TestStoredProcedures(t, h) } func TestDoltStoredProcedures(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltStoredProceduresTest(t, h) +} + +func RunDoltStoredProceduresTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltProcedureTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1580,9 +1594,14 @@ func TestDoltStoredProcedures(t *testing.T) { } func TestDoltStoredProceduresPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltStoredProceduresPreparedTest(t, h) +} + +func RunDoltStoredProceduresPreparedTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltProcedureTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, script) }() From fc546fca6c66dc29ca3b874043148173c9022fb0 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 16:49:28 -0700 Subject: [PATCH 09/23] more refactoring --- .../sqle/enginetest/dolt_engine_test.go | 65 +++++++++++++++---- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 0d68993f906..c85db030d48 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1615,9 +1615,14 @@ func TestEvents(t *testing.T) { } func TestCallAsOf(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunCallAsOfTest(t, h) +} + +func RunCallAsOfTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltCallAsOf { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1625,8 +1630,12 @@ func TestCallAsOf(t *testing.T) { } func TestLargeJsonObjects(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunLargeJsonObjectsTest(t, harness) +} + +func RunLargeJsonObjectsTest(t *testing.T, harness DoltEnginetestHarness) { SkipByDefaultInCI(t) - harness := newDoltHarness(t) defer harness.Close() for _, script := range LargeJsonObjectScriptTests { enginetest.TestScript(t, harness, script) @@ -1640,37 +1649,42 @@ func SkipByDefaultInCI(t *testing.T) { } func TestTransactions(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunTransactionTests(t, h) +} + +func RunTransactionTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range queries.TransactionTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() } for _, script := range DoltTransactionTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() } for _, script := range DoltStoredProcedureTransactionTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() } for _, script := range DoltConflictHandlingTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() } for _, script := range DoltConstraintViolationTransactionTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() @@ -1678,9 +1692,14 @@ func TestTransactions(t *testing.T) { } func TestBranchTransactions(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunBranchTransactionTest(t, h) +} + +func RunBranchTransactionTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range BranchIsolationTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() @@ -1688,9 +1707,14 @@ func TestBranchTransactions(t *testing.T) { } func TestMultiDbTransactions(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunMultiDbTransactionsTest(t, h) +} + +func RunMultiDbTransactionsTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range MultiDbTransactionTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1698,7 +1722,7 @@ func TestMultiDbTransactions(t *testing.T) { for _, script := range MultiDbSavepointTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestTransactionScript(t, h, script) }() @@ -1706,9 +1730,14 @@ func TestMultiDbTransactions(t *testing.T) { } func TestMultiDbTransactionsPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunMultiDbTransactionsPreparedTest(t, h) +} + +func RunMultiDbTransactionsPreparedTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range MultiDbTransactionTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, script) }() @@ -1722,9 +1751,14 @@ func TestConcurrentTransactions(t *testing.T) { } func TestDoltScripts(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunDoltScriptsTest(t, harness) +} + +func RunDoltScriptsTest(t *testing.T, harness DoltEnginetestHarness) { for _, script := range DoltScripts { go func() { - harness := newDoltHarness(t) + harness := harness.NewHarness(t) defer harness.Close() enginetest.TestScript(t, harness, script) }() @@ -1732,8 +1766,13 @@ func TestDoltScripts(t *testing.T) { } func TestDoltTempTableScripts(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunDoltTempTableScripts(t, harness) +} + +func RunDoltTempTableScripts(t *testing.T, harness DoltEnginetestHarness) { for _, script := range DoltTempTableScripts { - harness := newDoltHarness(t) + harness := harness.NewHarness(t) enginetest.TestScript(t, harness, script) harness.Close() } From 1d2f02624e9ac54bd90138b0f628f86819b1b735 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 17:07:30 -0700 Subject: [PATCH 10/23] more interface changes --- .../sqle/enginetest/dolt_engine_test.go | 28 +++++++++++++------ .../doltcore/sqle/enginetest/dolt_harness.go | 7 +++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index c85db030d48..c4e508a8952 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1779,9 +1779,14 @@ func RunDoltTempTableScripts(t *testing.T, harness DoltEnginetestHarness) { } func TestDoltRevisionDbScripts(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltRevisionDbScriptsTest(t, h) +} + +func RunDoltRevisionDbScriptsTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltRevisionDbScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1789,12 +1794,12 @@ func TestDoltRevisionDbScripts(t *testing.T) { // Testing a commit-qualified database revision spec requires // a little extra work to get the generated commit hash - harness := newDoltHarness(t) - defer harness.Close() - e, err := harness.NewEngine(t) + h = h.NewHarness(t) + defer h.Close() + e, err := h.NewEngine(t) require.NoError(t, err) defer e.Close() - ctx := harness.NewContext() + ctx := h.NewContext() setupScripts := []setup.SetupScript{ {"create table t01 (pk int primary key, c1 int)"}, @@ -1805,10 +1810,10 @@ func TestDoltRevisionDbScripts(t *testing.T) { {"insert into t01 values (3, 3);"}, {"call dolt_commit('-am', 'adding another row to table t01 on main');"}, } - _, err = enginetest.RunSetupScripts(ctx, harness.engine, setupScripts, true) + _, err = enginetest.RunSetupScripts(ctx, h.Engine(), setupScripts, true) require.NoError(t, err) - _, iter, err := harness.engine.Query(ctx, "select hashof('HEAD~2');") + _, iter, err := h.Engine().Query(ctx, "select hashof('HEAD~2');") require.NoError(t, err) rows, err := sql.RowIterToRows(ctx, iter) require.NoError(t, err) @@ -1875,13 +1880,18 @@ func TestDoltRevisionDbScripts(t *testing.T) { }, } - enginetest.TestScript(t, harness, scriptTest) + enginetest.TestScript(t, h, scriptTest) } func TestDoltRevisionDbScriptsPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltRevisionDbScriptsPreparedTest(t, h) +} + +func RunDoltRevisionDbScriptsPreparedTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltRevisionDbScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, script) }() diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index eeb1d680bf0..1fcac7890c1 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -100,6 +100,9 @@ type DoltEnginetestHarness interface { // Close closes the harness, freeing up any resources it may have allocated Close() + + Engine() *gms.Engine + } var _ DoltEnginetestHarness = &DoltHarness{} @@ -329,6 +332,10 @@ func (d *DoltHarness) WithSkippedQueries(queries []string) DoltEnginetestHarness return &nd } +func (d *DoltHarness) Engine() *gms.Engine { + return d.engine +} + // SkipQueryTest returns whether to skip a query func (d *DoltHarness) SkipQueryTest(query string) bool { lowerQuery := strings.ToLower(query) From 35750353b42555012eadc0a97f05f400bfdd6f9c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 17:51:24 -0700 Subject: [PATCH 11/23] More --- .../sqle/enginetest/dolt_engine_test.go | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index c4e508a8952..caaf82a0ece 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1899,7 +1899,11 @@ func RunDoltRevisionDbScriptsPreparedTest(t *testing.T, h DoltEnginetestHarness) } func TestDoltDdlScripts(t *testing.T) { - harness := newDoltHarness(t) + harness := newDoltEnginetestHarness(t) + RunDoltDdlScripts(t, harness) +} + +func RunDoltDdlScripts(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() harness.Setup() @@ -1950,9 +1954,14 @@ func TestDescribeTableAsOf(t *testing.T) { } func TestShowCreateTable(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunShowCreateTableTests(t, h) +} + +func RunShowCreateTableTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range ShowCreateTableScriptTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -1960,9 +1969,14 @@ func TestShowCreateTable(t *testing.T) { } func TestShowCreateTablePrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunShowCreateTablePreparedTests(t, h) +} + +func RunShowCreateTablePreparedTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range ShowCreateTableScriptTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, script) }() @@ -1983,11 +1997,16 @@ func TestViewsWithAsOfPrepared(t *testing.T) { } func TestDoltMerge(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltMergeTests(t, h) +} + +func RunDoltMergeTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range MergeScripts { // harness can't reset effectively when there are new commits / branches created, so use a new harness for // each script func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() h.Setup(setup.MydbData) enginetest.TestScript(t, h, script) @@ -1996,11 +2015,16 @@ func TestDoltMerge(t *testing.T) { } func TestDoltRebase(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltRebaseTests(t, h) +} + +func RunDoltRebaseTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltRebaseScriptTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() - h.skipSetupCommit = true + h.SkipSetupCommit() enginetest.TestScript(t, h, script) }() } @@ -2009,11 +2033,16 @@ func TestDoltRebase(t *testing.T) { } func TestDoltRebasePrepared(t *testing.T) { + h := newDoltHarness(t) + RunDoltRebasePreparedTests(t, h) +} + +func RunDoltRebasePreparedTests(t *testing.T, h *DoltHarness) { for _, script := range DoltRebaseScriptTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() - h.skipSetupCommit = true + h.SkipSetupCommit() enginetest.TestScriptPrepared(t, h, script) }() } From f0a5265af2e933a6d9ad512daa18a955461f0762 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 18:01:57 -0700 Subject: [PATCH 12/23] More --- .../sqle/enginetest/dolt_engine_test.go | 84 ++++++++++++++----- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index caaf82a0ece..81831f56c91 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2014,6 +2014,23 @@ func RunDoltMergeTests(t *testing.T, h DoltEnginetestHarness) { } } +func TestDoltMergePrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltMergePreparedTests(t, h) +} + +func RunDoltMergePreparedTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range MergeScripts { + // harness can't reset effectively when there are new commits / branches created, so use a new harness for + // each script + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + func TestDoltRebase(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRebaseTests(t, h) @@ -2048,23 +2065,16 @@ func RunDoltRebasePreparedTests(t *testing.T, h *DoltHarness) { } } -func TestDoltMergePrepared(t *testing.T) { - for _, script := range MergeScripts { - // harness can't reset effectively when there are new commits / branches created, so use a new harness for - // each script - func() { - h := newDoltHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } +func TestDoltRevert(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltRevertTests(t, h) } -func TestDoltRevert(t *testing.T) { +func RunDoltRevertTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range RevertScripts { // harness can't reset effectively. Use a new harness for each script func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2072,21 +2082,31 @@ func TestDoltRevert(t *testing.T) { } func TestDoltRevertPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltRevertPreparedTests(t, h) +} + +func RunDoltRevertPreparedTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range RevertScripts { // harness can't reset effectively. Use a new harness for each script func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() - enginetest.TestScriptPrepared(t, h, script) + enginetest.TestScript(t, h, script) }() } } func TestDoltAutoIncrement(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltAutoIncrementTests(t, h) +} + +func RunDoltAutoIncrementTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltAutoIncrementTests { // doing commits on different branches is antagonistic to engine reuse, use a new engine on each script func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2094,20 +2114,30 @@ func TestDoltAutoIncrement(t *testing.T) { } func TestDoltAutoIncrementPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltAutoIncrementPreparedTests(t, h) +} + +func RunDoltAutoIncrementPreparedTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltAutoIncrementTests { // doing commits on different branches is antagonistic to engine reuse, use a new engine on each script func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() - enginetest.TestScriptPrepared(t, h, script) + enginetest.TestScript(t, h, script) }() } } func TestDoltConflictsTableNameTable(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltConflictsTableNameTableTests(t, h) +} + +func RunDoltConflictsTableNameTableTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltConflictTableNameTableTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2116,7 +2146,7 @@ func TestDoltConflictsTableNameTable(t *testing.T) { if types.IsFormat_DOLT(types.Format_Default) { for _, script := range Dolt1ConflictTableNameTableTests { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2126,12 +2156,17 @@ func TestDoltConflictsTableNameTable(t *testing.T) { // tests new format behavior for keyless merges that create CVs and conflicts func TestKeylessDoltMergeCVsAndConflicts(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunKelyessDoltMergeCVsAndConflictsTests(t, h) +} + +func RunKelyessDoltMergeCVsAndConflictsTests(t *testing.T, h DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip() } for _, script := range KeylessMergeCVsAndConflictsScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2140,15 +2175,20 @@ func TestKeylessDoltMergeCVsAndConflicts(t *testing.T) { // eventually this will be part of TestDoltMerge func TestDoltMergeArtifacts(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltMergeArtifacts(t, h) +} + +func RunDoltMergeArtifacts(t *testing.T, h DoltEnginetestHarness) { for _, script := range MergeArtifactsScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() } for _, script := range SchemaConflictScripts { - h := newDoltHarness(t) + h := h.NewHarness(t) enginetest.TestScript(t, h, script) h.Close() } From ecace5504a7e1ed82c1c8ef95c4f0e4abbb2d7d8 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 18:09:16 -0700 Subject: [PATCH 13/23] More new interfaces --- .../sqle/enginetest/dolt_engine_test.go | 55 +++++++++++++++---- .../doltcore/sqle/enginetest/dolt_harness.go | 7 +++ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 81831f56c91..fb191c1ef84 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2210,10 +2210,15 @@ func TestOldFormatMergeConflictsAndCVs(t *testing.T) { } func TestDoltReset(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltResetTest(t, h) +} + +func RunDoltResetTest(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltReset { // dolt versioning conflicts with reset harness -- use new harness every time func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2232,15 +2237,20 @@ func TestDoltGC(t *testing.T) { } func TestDoltCheckout(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltCheckoutTests(t, h) +} + +func RunDoltCheckoutTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltCheckoutScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() } - h := newDoltHarness(t) + h = h.NewHarness(t) defer h.Close() engine, err := h.NewEngine(t) require.NoError(t, err) @@ -2253,15 +2263,20 @@ func TestDoltCheckout(t *testing.T) { } func TestDoltCheckoutPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltCheckoutPreparedTests(t, h) +} + +func RunDoltCheckoutPreparedTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltCheckoutScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() - enginetest.TestScriptPrepared(t, h, script) + enginetest.TestScript(t, h, script) }() } - h := newDoltHarness(t) + h = h.NewHarness(t) defer h.Close() engine, err := h.NewEngine(t) require.NoError(t, err) @@ -2274,9 +2289,14 @@ func TestDoltCheckoutPrepared(t *testing.T) { } func TestDoltBranch(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltBranchTests(t, h) +} + +func RunDoltBranchTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltBranchScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2284,9 +2304,14 @@ func TestDoltBranch(t *testing.T) { } func TestDoltTag(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltTagTests(t, h) +} + +func RunDoltTagTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltTagTestScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2294,9 +2319,14 @@ func TestDoltTag(t *testing.T) { } func TestDoltRemote(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltRemoteTests(t, h) +} + +func RunDoltRemoteTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltRemoteTestScripts { func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, script) }() @@ -2304,7 +2334,12 @@ func TestDoltRemote(t *testing.T) { } func TestDoltUndrop(t *testing.T) { - h := newDoltHarnessForLocalFilesystem(t) + h := newDoltEnginetestHarness(t) + RunDoltUndropTests(t, h) +} + +func RunDoltUndropTests(t *testing.T, h DoltEnginetestHarness) { + h.UseLocalFileSystem() defer h.Close() for _, script := range DoltUndropTestScripts { enginetest.TestScript(t, h, script) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 1fcac7890c1..6845172eba5 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -61,6 +61,10 @@ type DoltHarness struct { setupTestProcedures bool } +func (d *DoltHarness) UseLocalFileSystem() { + d.useLocalFilesystem = true +} + func (d *DoltHarness) WithConfigureStats(configureStats bool) DoltEnginetestHarness { nd := *d nd.configureStats = configureStats @@ -96,6 +100,9 @@ type DoltEnginetestHarness interface { // SkipSetupCommit configures to harness to skip the commit after setup scripts are run SkipSetupCommit() + + // UseLocalFileSystem configures the harness to use the local filesystem for all storage, instead of in-memory versions + UseLocalFileSystem() // Close closes the harness, freeing up any resources it may have allocated Close() From 8c8b24fd2dbbc1a3dd4df8fbafab0e2b03369187 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 18:16:35 -0700 Subject: [PATCH 14/23] More --- .../sqle/enginetest/dolt_engine_test.go | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index fb191c1ef84..530ddcb347c 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2448,7 +2448,11 @@ func TestBrokenSystemTableQueries(t *testing.T) { } func TestHistorySystemTable(t *testing.T) { - harness := newDoltHarness(t).WithParallelism(2) + harness := newDoltEnginetestHarness(t).WithParallelism(2) + RunHistorySystemTableTests(t, harness) +} + +func RunHistorySystemTableTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range HistorySystemTableScriptTests { harness = harness.NewHarness(t) harness.Setup(setup.MydbData) @@ -2459,8 +2463,13 @@ func TestHistorySystemTable(t *testing.T) { } func TestHistorySystemTablePrepared(t *testing.T) { + harness := newDoltEnginetestHarness(t).WithParallelism(2) + RunHistorySystemTableTestsPrepared(t, harness) +} + +func RunHistorySystemTableTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range HistorySystemTableScriptTests { - harness := newDoltHarness(t).WithParallelism(2) + harness = harness.NewHarness(t) harness.Setup(setup.MydbData) t.Run(test.Name, func(t *testing.T) { enginetest.TestScriptPrepared(t, harness, test) @@ -2482,9 +2491,14 @@ func TestBrokenHistorySystemTablePrepared(t *testing.T) { } func TestUnscopedDiffSystemTable(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunUnscopedDiffSystemTableTests(t, h) +} + +func RunUnscopedDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { for _, test := range UnscopedDiffSystemTableScriptTests { t.Run(test.Name, func(t *testing.T) { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, test) }) @@ -2492,9 +2506,14 @@ func TestUnscopedDiffSystemTable(t *testing.T) { } func TestUnscopedDiffSystemTablePrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunUnscopedDiffSystemTableTestsPrepared(t, h) +} + +func RunUnscopedDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { for _, test := range UnscopedDiffSystemTableScriptTests { t.Run(test.Name, func(t *testing.T) { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, test) }) @@ -2502,23 +2521,33 @@ func TestUnscopedDiffSystemTablePrepared(t *testing.T) { } func TestColumnDiffSystemTable(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunColumnDiffSystemTableTests(t, h) +} + +func RunColumnDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("correct behavior of dolt_column_diff only guaranteed on new format") } for _, test := range ColumnDiffSystemTableScriptTests { t.Run(test.Name, func(t *testing.T) { - enginetest.TestScript(t, newDoltHarness(t), test) + enginetest.TestScript(t, h.NewHarness(t), test) }) } } func TestColumnDiffSystemTablePrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunColumnDiffSystemTableTestsPrepared(t, h) +} + +func RunColumnDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("correct behavior of dolt_column_diff only guaranteed on new format") } for _, test := range ColumnDiffSystemTableScriptTests { t.Run(test.Name, func(t *testing.T) { - enginetest.TestScriptPrepared(t, newDoltHarness(t), test) + enginetest.TestScriptPrepared(t, h.NewHarness(t), test) }) } } From 4342d91e3ef5dde5abfa22ee7b39b006b6162ac9 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 18:23:31 -0700 Subject: [PATCH 15/23] more --- .../sqle/enginetest/dolt_engine_test.go | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 530ddcb347c..834fd688712 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2553,14 +2553,18 @@ func RunColumnDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness } func TestStatBranchTests(t *testing.T) { - harness := newDoltHarness(t) + harness := newDoltEnginetestHarness(t) + RunStatBranchTests(t, harness) +} + +func RunStatBranchTests(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() - harness.Setup(setup.MydbData) - harness.configureStats = true for _, test := range StatBranchTests { t.Run(test.Name, func(t *testing.T) { // reset engine so provider statistics are clean - harness.engine = nil + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + harness = harness.WithConfigureStats(true) e := mustNewEngine(t, harness) defer e.Close() enginetest.TestScriptWithEngine(t, e, harness, test) @@ -2569,15 +2573,18 @@ func TestStatBranchTests(t *testing.T) { } func TestStatsFunctions(t *testing.T) { - harness := newDoltHarness(t) + harness := newDoltEnginetestHarness(t) + RunStatsFunctionsTest(t, harness) +} + +func RunStatsFunctionsTest(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() - harness.Setup(setup.MydbData) - harness.configureStats = true - harness.skipSetupCommit = true for _, test := range StatProcTests { t.Run(test.Name, func(t *testing.T) { // reset engine so provider statistics are clean - harness.engine = nil + harness = harness.NewHarness(t).WithConfigureStats(true) + harness.Setup(setup.MydbData) + harness.SkipSetupCommit() e := mustNewEngine(t, harness) defer e.Close() enginetest.TestScriptWithEngine(t, e, harness, test) @@ -2586,24 +2593,32 @@ func TestStatsFunctions(t *testing.T) { } func TestDiffTableFunction(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDiffTableFunctionTests(t, harness) +} + +func RunDiffTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DiffTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } } func TestDiffTableFunctionPrepared(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDiffTableFunctionTestsPrepared(t, harness) +} + +func RunDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DiffTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } From eaaf8170b511ed026cb0d658005ed4ab30d864ab Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 17 Jun 2024 18:32:05 -0700 Subject: [PATCH 16/23] Tedium --- .../sqle/enginetest/dolt_engine_test.go | 64 +++++++++++++------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 834fd688712..89293d7e557 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2625,10 +2625,14 @@ func RunDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarne } func TestDiffStatTableFunction(t *testing.T) { - harness := newDoltHarness(t) - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDiffStatTableFunctionTests(t, harness) +} + +func RunDiffStatTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DiffStatTableFunctionScriptTests { - harness.engine = nil + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) t.Run(test.Name, func(t *testing.T) { enginetest.TestScript(t, harness, test) }) @@ -2636,10 +2640,14 @@ func TestDiffStatTableFunction(t *testing.T) { } func TestDiffStatTableFunctionPrepared(t *testing.T) { - harness := newDoltHarness(t) - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDiffStatTableFunctionTestsPrepared(t, harness) +} + +func RunDiffStatTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DiffStatTableFunctionScriptTests { - harness.engine = nil + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) t.Run(test.Name, func(t *testing.T) { enginetest.TestScriptPrepared(t, harness, test) }) @@ -2647,46 +2655,62 @@ func TestDiffStatTableFunctionPrepared(t *testing.T) { } func TestDiffSummaryTableFunction(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDiffSummaryTableFunctionTests(t, harness) +} + +func RunDiffSummaryTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DiffSummaryTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } } func TestDiffSummaryTableFunctionPrepared(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDiffSummaryTableFunctionTestsPrepared(t, harness) +} + +func RunDiffSummaryTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DiffSummaryTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } } func TestPatchTableFunction(t *testing.T) { - harness := newDoltHarness(t) - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDoltPatchTableFunctionTests(t, harness) +} + +func RunDoltPatchTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range PatchTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } } func TestPatchTableFunctionPrepared(t *testing.T) { - harness := newDoltHarness(t) - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDoltPatchTableFunctionTestsPrepared(t, harness) +} + +func RunDoltPatchTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range PatchTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } From 292aaf2c198b4fdf620936719616f6f24d9e4f03 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 18 Jun 2024 12:04:38 -0700 Subject: [PATCH 17/23] more refactoring --- .../sqle/enginetest/dolt_engine_test.go | 122 ++++++++++++------ 1 file changed, 80 insertions(+), 42 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 89293d7e557..d90e0450636 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2717,26 +2717,34 @@ func RunDoltPatchTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetest } func TestLogTableFunction(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunLogTableFunctionTests(t, harness) +} + +func RunLogTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range LogTableFunctionScriptTests { - harness.engine = nil - harness.skipSetupCommit = true t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + harness.SkipSetupCommit() enginetest.TestScript(t, harness, test) }) } } func TestLogTableFunctionPrepared(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunLogTableFunctionTestsPrepared(t, harness) +} + +func RunLogTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range LogTableFunctionScriptTests { - harness.engine = nil - harness.skipSetupCommit = true t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + harness.SkipSetupCommit() enginetest.TestScriptPrepared(t, harness, test) }) } @@ -2761,49 +2769,62 @@ func TestDoltReflogPrepared(t *testing.T) { } func TestCommitDiffSystemTable(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunCommitDiffSystemTableTests(t, harness) +} + +func RunCommitDiffSystemTableTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range CommitDiffSystemTableScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } } func TestCommitDiffSystemTablePrepared(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunCommitDiffSystemTableTestsPrepared(t, harness) +} + +func RunCommitDiffSystemTableTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range CommitDiffSystemTableScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } } func TestDiffSystemTable(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltDiffSystemTableTests(t, h) +} + +func RunDoltDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("only new format support system table indexing") } - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) for _, test := range DiffSystemTableScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { - enginetest.TestScript(t, harness, test) + h = h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScript(t, h, test) }) } if types.IsFormat_DOLT(types.Format_Default) { for _, test := range Dolt1DiffSystemTableScripts { func() { - h := newDoltHarness(t) + h = h.NewHarness(t) defer h.Close() + h.Setup(setup.MydbData) enginetest.TestScript(t, h, test) }() } @@ -2811,25 +2832,30 @@ func TestDiffSystemTable(t *testing.T) { } func TestDiffSystemTablePrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltDiffSystemTableTestsPrepared(t, h) +} + +func RunDoltDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("only new format support system table indexing") } - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) for _, test := range DiffSystemTableScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { - enginetest.TestScriptPrepared(t, harness, test) + h = h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, h, test) }) } if types.IsFormat_DOLT(types.Format_Default) { for _, test := range Dolt1DiffSystemTableScripts { func() { - h := newDoltHarness(t) + h = h.NewHarness(t) defer h.Close() + h.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, h, test) }() } @@ -2837,36 +2863,48 @@ func TestDiffSystemTablePrepared(t *testing.T) { } func TestSchemaDiffTableFunction(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunSchemaDiffTableFunctionTests(t, harness) +} + +func RunSchemaDiffTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range SchemaDiffTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } } func TestSchemaDiffTableFunctionPrepared(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunSchemaDiffTableFunctionTestsPrepared(t, harness) +} + +func RunSchemaDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range SchemaDiffTableFunctionScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } } func TestDoltDatabaseCollationDiffs(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunDoltDatabaseCollationDiffsTests(t, harness) +} + +func RunDoltDatabaseCollationDiffsTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range DoltDatabaseCollationScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } From 202a94bb66717ecccc51ba5672a6a476384f0a18 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 18 Jun 2024 13:04:36 -0700 Subject: [PATCH 18/23] Another new interface --- .../sqle/enginetest/dolt_engine_test.go | 195 ++++++++++++------ .../doltcore/sqle/enginetest/dolt_harness.go | 6 +- 2 files changed, 137 insertions(+), 64 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index d90e0450636..ddbea176e31 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2911,12 +2911,16 @@ func RunDoltDatabaseCollationDiffsTests(t *testing.T, harness DoltEnginetestHarn } func TestQueryDiff(t *testing.T) { - harness := newDoltHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunQueryDiffTests(t, harness) +} + +func RunQueryDiffTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range QueryDiffTableScriptTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } @@ -2938,12 +2942,17 @@ var biasedCosters = []memo.Coster{ } func TestSystemTableIndexes(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunSystemTableIndexesTests(t, harness) +} + +func RunSystemTableIndexesTests(t *testing.T, harness DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("only new format support system table indexing") } for _, stt := range SystemTableIndexTests { - harness := newDoltHarness(t).WithParallelism(2) + harness = harness.NewHarness(t).WithParallelism(2) defer harness.Close() harness.SkipSetupCommit() e := mustNewEngine(t, harness) @@ -2981,12 +2990,17 @@ func TestSystemTableIndexes(t *testing.T) { } func TestSystemTableIndexesPrepared(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunSystemTableIndexesTestsPrepared(t, harness) +} + +func RunSystemTableIndexesTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("only new format support system table indexing") } for _, stt := range SystemTableIndexTests { - harness := newDoltHarness(t).WithParallelism(2) + harness = harness.NewHarness(t).WithParallelism(2) defer harness.Close() harness.SkipSetupCommit() e := mustNewEngine(t, harness) @@ -3013,22 +3027,30 @@ func TestSystemTableIndexesPrepared(t *testing.T) { } func TestSystemTableFunctionIndexes(t *testing.T) { - harness := newDoltHarness(t) - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunSystemTableFunctionIndexesTests(t, harness) +} + +func RunSystemTableFunctionIndexesTests(t *testing.T, harness DoltEnginetestHarness) { for _, test := range SystemTableFunctionIndexTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) enginetest.TestScript(t, harness, test) }) } } func TestSystemTableFunctionIndexesPrepared(t *testing.T) { - harness := newDoltHarness(t) - harness.Setup(setup.MydbData) + harness := newDoltEnginetestHarness(t) + RunSystemTableFunctionIndexesTestsPrepared(t, harness) +} + +func RunSystemTableFunctionIndexesTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, test := range SystemTableFunctionIndexTests { - harness.engine = nil t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) enginetest.TestScriptPrepared(t, harness, test) }) } @@ -3047,9 +3069,12 @@ func TestAddDropPks(t *testing.T) { } func TestAddAutoIncrementColumn(t *testing.T) { - h := newDoltHarness(t) - defer h.Close() + h := newDoltEnginetestHarness(t) + RunAddAutoIncrementColumnTests(t, h) +} +func RunAddAutoIncrementColumnTests(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() for _, script := range queries.AlterTableAddAutoIncrementScripts { enginetest.TestScript(t, h, script) } @@ -3086,23 +3111,37 @@ func TestTypesOverWire(t *testing.T) { } func TestDoltCherryPick(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunDoltCherryPickTests(t, harness) +} + +func RunDoltCherryPickTests(t *testing.T, harness DoltEnginetestHarness) { for _, script := range DoltCherryPickTests { - harness := newDoltHarness(t) + harness = harness.NewHarness(t) enginetest.TestScript(t, harness, script) harness.Close() } } func TestDoltCherryPickPrepared(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunDoltCherryPickTestsPrepared(t, harness) +} + +func RunDoltCherryPickTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { for _, script := range DoltCherryPickTests { - harness := newDoltHarness(t) + harness = harness.NewHarness(t) enginetest.TestScriptPrepared(t, harness, script) harness.Close() } } func TestDoltCommit(t *testing.T) { - harness := newDoltHarness(t) + harness := newDoltEnginetestHarness(t) + RunDoltCommitTests(t, harness) +} + +func RunDoltCommitTests(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() for _, script := range DoltCommitTests { enginetest.TestScript(t, harness, script) @@ -3110,7 +3149,11 @@ func TestDoltCommit(t *testing.T) { } func TestDoltCommitPrepared(t *testing.T) { - harness := newDoltHarness(t) + harness := newDoltEnginetestHarness(t) + RunDoltCommitTestsPrepared(t, harness) +} + +func RunDoltCommitTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() for _, script := range DoltCommitTests { enginetest.TestScriptPrepared(t, harness, script) @@ -3124,24 +3167,32 @@ func TestQueriesPrepared(t *testing.T) { } func TestStatsHistograms(t *testing.T) { - h := newDoltHarness(t) - defer h.Close() - h.configureStats = true + h := newDoltEnginetestHarness(t) + RunStatsHistogramTests(t, h) +} + +func RunStatsHistogramTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltHistogramTests { - h.engine = nil - enginetest.TestScript(t, h, script) + func() { + h = h.NewHarness(t).WithConfigureStats(true) + defer h.Close() + enginetest.TestScript(t, h, script) + }() } } // TestStatsIO force a provider reload in-between setup and assertions that // forces a round trip of the statistics table before inspecting values. func TestStatsIO(t *testing.T) { - h := newDoltHarness(t) - h.configureStats = true - defer h.Close() + h := newDoltEnginetestHarness(t) + RunStatsIOTests(t, h) +} + +func RunStatsIOTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range append(DoltStatsIOTests, DoltHistogramTests...) { - h.engine = nil func() { + h = h.NewHarness(t).WithConfigureStats(true) + defer h.Close() e := mustNewEngine(t, h) if enginetest.IsServerEngine(e) { return @@ -3153,12 +3204,16 @@ func TestStatsIO(t *testing.T) { } func TestJoinStats(t *testing.T) { - // these are sensitive to cardinality estimates, - // particularly the join-filter tests that trade-off - // smallest table first vs smallest join first - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) + RunJoinStatsTests(t, h) +} + +// these are sensitive to cardinality estimates, +// particularly the join-filter tests that trade-off +// smallest table first vs smallest join first +func RunJoinStatsTests(t *testing.T, h DoltEnginetestHarness) { defer h.Close() - h.configureStats = true + h = h.WithConfigureStats(true) enginetest.TestJoinStats(t, h) } @@ -3177,17 +3232,26 @@ func TestSpatialQueriesPrepared(t *testing.T) { } func TestPreparedStatistics(t *testing.T) { - h := newDoltHarness(t) - defer h.Close() - h.configureStats = true + h := newDoltEnginetestHarness(t) + RunPreparedStatisticsTests(t, h) +} + +func RunPreparedStatisticsTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltHistogramTests { - h.engine = nil - enginetest.TestScriptPrepared(t, h, script) + func() { + h := h.NewHarness(t).WithConfigureStats(true) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() } } func TestVersionedQueriesPrepared(t *testing.T) { - h := newDoltHarness(t) + h := newDoltEnginetestHarness(t) + RunVersionedQueriesPreparedTests(t, h) +} + +func RunVersionedQueriesPreparedTests(t *testing.T, h DoltEnginetestHarness) { defer h.Close() h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) @@ -3370,8 +3434,13 @@ func TestDatabaseCollationWire(t *testing.T) { } func TestAddDropPrimaryKeys(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunAddDropPrimaryKeysTests(t, harness) +} + +func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { t.Run("adding and dropping primary keys does not result in duplicate NOT NULL constraints", func(t *testing.T) { - harness := newDoltHarness(t) + harness = harness.NewHarness(t) defer harness.Close() addPkScript := queries.ScriptTest{ Name: "add primary keys", @@ -3392,11 +3461,11 @@ func TestAddDropPrimaryKeys(t *testing.T) { Query: "show create table test", Expected: []sql.Row{ {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `c1_idx` (`c1`)\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `c1_idx` (`c1`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, }, }, }, @@ -3405,8 +3474,8 @@ func TestAddDropPrimaryKeys(t *testing.T) { enginetest.TestScript(t, harness, addPkScript) // make sure there is only one NOT NULL constraint after all those mutations - ctx := sql.NewContext(context.Background(), sql.WithSession(harness.session)) - ws, err := harness.session.WorkingSet(ctx, "mydb") + ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) + ws, err := harness.Session().WorkingSet(ctx, "mydb") require.NoError(t, err) table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) @@ -3426,7 +3495,7 @@ func TestAddDropPrimaryKeys(t *testing.T) { }) t.Run("Add primary key to table with index", func(t *testing.T) { - harness := newDoltHarness(t) + harness := harness.NewHarness(t) defer harness.Close() script := queries.ScriptTest{ Name: "add primary keys to table with index", @@ -3442,12 +3511,12 @@ func TestAddDropPrimaryKeys(t *testing.T) { Query: "show create table test", Expected: []sql.Row{ {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `c1_idx` (`c1`),\n" + - " CONSTRAINT `test_check` CHECK ((`c1` > 0))\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `c1_idx` (`c1`),\n" + + " CONSTRAINT `test_check` CHECK ((`c1` > 0))\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, }, }, { @@ -3461,8 +3530,8 @@ func TestAddDropPrimaryKeys(t *testing.T) { } enginetest.TestScript(t, harness, script) - ctx := sql.NewContext(context.Background(), sql.WithSession(harness.session)) - ws, err := harness.session.WorkingSet(ctx, "mydb") + ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) + ws, err := harness.Session().WorkingSet(ctx, "mydb") require.NoError(t, err) table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) @@ -3481,7 +3550,7 @@ func TestAddDropPrimaryKeys(t *testing.T) { }) t.Run("Add primary key when one more cells contain NULL", func(t *testing.T) { - harness := newDoltHarness(t) + harness := harness.NewHarness(t) defer harness.Close() script := queries.ScriptTest{ Name: "Add primary key when one more cells contain NULL", @@ -3504,7 +3573,7 @@ func TestAddDropPrimaryKeys(t *testing.T) { }) t.Run("Drop primary key from table with index", func(t *testing.T) { - harness := newDoltHarness(t) + harness := harness.NewHarness(t) defer harness.Close() script := queries.ScriptTest{ Name: "Drop primary key from table with index", @@ -3519,10 +3588,10 @@ func TestAddDropPrimaryKeys(t *testing.T) { Query: "show create table test", Expected: []sql.Row{ {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " KEY `c1_idx` (`c1`)\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " KEY `c1_idx` (`c1`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, }, }, { @@ -3537,8 +3606,8 @@ func TestAddDropPrimaryKeys(t *testing.T) { enginetest.TestScript(t, harness, script) - ctx := sql.NewContext(context.Background(), sql.WithSession(harness.session)) - ws, err := harness.session.WorkingSet(ctx, "mydb") + ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) + ws, err := harness.Session().WorkingSet(ctx, "mydb") require.NoError(t, err) table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 6845172eba5..3251254d180 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -65,6 +65,10 @@ func (d *DoltHarness) UseLocalFileSystem() { d.useLocalFilesystem = true } +func (d *DoltHarness) Session() *dsess.DoltSession { + return d.session +} + func (d *DoltHarness) WithConfigureStats(configureStats bool) DoltEnginetestHarness { nd := *d nd.configureStats = configureStats @@ -106,10 +110,10 @@ type DoltEnginetestHarness interface { // Close closes the harness, freeing up any resources it may have allocated Close() - Engine() *gms.Engine + Session() *dsess.DoltSession } var _ DoltEnginetestHarness = &DoltHarness{} From 871e48776d597c5da1abc4cbe4215d2b882b41fc Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 18 Jun 2024 13:12:08 -0700 Subject: [PATCH 19/23] Last conversions --- .../sqle/enginetest/dolt_engine_test.go | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index ddbea176e31..a8e15b5b796 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -3627,9 +3627,14 @@ func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { } func TestDoltVerifyConstraints(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunDoltVerifyConstraintsTests(t, harness) +} + +func RunDoltVerifyConstraintsTests(t *testing.T, harness DoltEnginetestHarness) { for _, script := range DoltVerifyConstraintsTestScripts { func() { - harness := newDoltHarness(t) + harness = harness.NewHarness(t) defer harness.Close() enginetest.TestScript(t, harness, script) }() @@ -3637,6 +3642,11 @@ func TestDoltVerifyConstraints(t *testing.T) { } func TestDoltStorageFormat(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunDoltStorageFormatTests(t, h) +} + +func RunDoltStorageFormatTests(t *testing.T, h DoltEnginetestHarness) { var expectedFormatString string if types.IsFormat_DOLT(types.Format_Default) { expectedFormatString = "NEW ( __DOLT__ )" @@ -3652,7 +3662,6 @@ func TestDoltStorageFormat(t *testing.T) { }, }, } - h := newDoltHarness(t) defer h.Close() enginetest.TestScript(t, h, script) } @@ -3670,6 +3679,12 @@ func TestDoltStorageFormatPrepared(t *testing.T) { } func TestThreeWayMergeWithSchemaChangeScripts(t *testing.T) { + h := newDoltEnginetestHarness(t) + + RunThreeWayMergeWithSchemaChangeScripts(t, h) +} + +func RunThreeWayMergeWithSchemaChangeScripts(t *testing.T, h DoltEnginetestHarness) { skipOldFormat(t) runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", false) runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", false) @@ -3684,7 +3699,7 @@ func TestThreeWayMergeWithSchemaChangeScripts(t *testing.T) { for _, script := range SchemaChangeTestsTypeChanges { // run in a func() so we can cleanly defer closing the harness func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScript(t, h, convertMergeScriptTest(script, false)) }() @@ -3693,28 +3708,33 @@ func TestThreeWayMergeWithSchemaChangeScripts(t *testing.T) { } func TestThreeWayMergeWithSchemaChangeScriptsPrepared(t *testing.T) { + h := newDoltEnginetestHarness(t) + + RunThreeWayMergeWithSchemaChangeScriptsPrepared(t, h) +} + +func RunThreeWayMergeWithSchemaChangeScriptsPrepared(t *testing.T, h DoltEnginetestHarness) { skipOldFormat(t) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", true) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", true) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsCollations, "collation changes", true) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsConstraints, "constraint changes", true) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsSchemaConflicts, "schema conflicts", true) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsGeneratedColumns, "generated columns", true) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForJsonConflicts, "json merge", true) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsCollations, "collation changes", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsConstraints, "constraint changes", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsSchemaConflicts, "schema conflicts", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsGeneratedColumns, "generated columns", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForJsonConflicts, "json merge", false) // Run non-symmetric schema merge tests in just one direction t.Run("type changes", func(t *testing.T) { for _, script := range SchemaChangeTestsTypeChanges { // run in a func() so we can cleanly defer closing the harness func() { - h := newDoltHarness(t) + h := h.NewHarness(t) defer h.Close() enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, false)) }() } }) } - // If CREATE DATABASE has an error within the DatabaseProvider, it should not // leave behind intermediate filesystem state. func TestCreateDatabaseErrorCleansUp(t *testing.T) { From a39de0f04109f45c22088eca4a5c09d94d407d43 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 18 Jun 2024 16:00:15 -0700 Subject: [PATCH 20/23] Moved exported methods out of test file --- .../sqle/enginetest/dolt_engine_test.go | 1913 +--------------- .../sqle/enginetest/dolt_engine_tests.go | 1920 +++++++++++++++++ .../sqle/enginetest/dolt_server_test.go | 657 ------ .../sqle/enginetest/dolt_server_tests.go | 683 ++++++ 4 files changed, 2617 insertions(+), 2556 deletions(-) create mode 100755 go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go create mode 100755 go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index a8e15b5b796..442db42e290 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -17,7 +17,6 @@ package enginetest import ( "context" "fmt" - "io" "os" "runtime" "sync" @@ -27,47 +26,26 @@ import ( "github.com/dolthub/go-mysql-server/enginetest" "github.com/dolthub/go-mysql-server/enginetest/queries" "github.com/dolthub/go-mysql-server/enginetest/scriptgen/setup" - "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" - "github.com/dolthub/go-mysql-server/sql/memo" "github.com/dolthub/go-mysql-server/sql/mysql_db" "github.com/dolthub/go-mysql-server/sql/plan" - "github.com/dolthub/go-mysql-server/sql/transform" gmstypes "github.com/dolthub/go-mysql-server/sql/types" - "github.com/dolthub/vitess/go/mysql" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" "github.com/dolthub/dolt/go/libraries/doltcore/env" - "github.com/dolthub/dolt/go/libraries/doltcore/schema" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/statspro" "github.com/dolthub/dolt/go/libraries/utils/config" - "github.com/dolthub/dolt/go/store/datas" "github.com/dolthub/dolt/go/store/types" ) -var skipPrepared bool - // SkipPreparedsCount is used by the "ci-check-repo CI workflow // as a reminder to consider prepareds when adding a new // enginetest suite. const SkipPreparedsCount = 83 -const skipPreparedFlag = "DOLT_SKIP_PREPARED_ENGINETESTS" - -func init() { - sqle.MinRowsPerPartition = 8 - sqle.MaxRowsPerPartition = 1024 - - if v := os.Getenv(skipPreparedFlag); v != "" { - skipPrepared = true - } -} - func TestQueries(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -124,27 +102,6 @@ func TestSchemaOverrides(t *testing.T) { RunSchemaOverridesTest(t, harness) } -func RunSchemaOverridesTest(t *testing.T, harness DoltEnginetestHarness) { - tcc := &testCommitClock{} - cleanup := installTestCommitClock(tcc) - defer cleanup() - - for _, script := range SchemaOverrideTests { - sql.RunWithNowFunc(tcc.Now, func() error { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - - engine, err := harness.NewEngine(t) - if err != nil { - panic(err) - } - - enginetest.TestScriptWithEngine(t, engine, harness, script) - return nil - }) - } -} - // Convenience test for debugging a single query. Unskip and set to the desired query. func TestSingleScript(t *testing.T) { t.Skip() @@ -184,124 +141,6 @@ func TestAutoIncrementTrackerLockMode(t *testing.T) { RunAutoIncrementTrackerLockModeTest(t, harness) } -func RunAutoIncrementTrackerLockModeTest(t *testing.T, harness DoltEnginetestHarness) { - for _, lockMode := range []int64{0, 1, 2} { - t.Run(fmt.Sprintf("lock mode %d", lockMode), func(t *testing.T) { - testAutoIncrementTrackerWithLockMode(t, harness, lockMode) - }) - } -} - -// testAutoIncrementTrackerWithLockMode tests that interleaved inserts don't cause deadlocks, regardless of the value of innodb_autoinc_lock_mode. -// In a real use case, these interleaved operations would be happening in different sessions on different threads. -// In order to make the test behave predictably, we manually interleave the two iterators. -func testAutoIncrementTrackerWithLockMode(t *testing.T, harness DoltEnginetestHarness, lockMode int64) { - err := sql.SystemVariables.AssignValues(map[string]interface{}{"innodb_autoinc_lock_mode": lockMode}) - require.NoError(t, err) - - setupScripts := []setup.SetupScript{[]string{ - "CREATE TABLE test1 (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,c0 int,index t1_c_index (c0));", - "CREATE TABLE test2 (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,c0 int,index t2_c_index (c0));", - "CREATE TABLE timestamps (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT, t int);", - "CREATE TRIGGER t1 AFTER INSERT ON test1 FOR EACH ROW INSERT INTO timestamps VALUES (0, 1);", - "CREATE TRIGGER t2 AFTER INSERT ON test2 FOR EACH ROW INSERT INTO timestamps VALUES (0, 2);", - "CREATE VIEW bin AS SELECT 0 AS v UNION ALL SELECT 1;", - "CREATE VIEW sequence5bit AS SELECT b1.v + 2*b2.v + 4*b3.v + 8*b4.v + 16*b5.v AS v from bin b1, bin b2, bin b3, bin b4, bin b5;", - }} - - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData, setupScripts) - e := mustNewEngine(t, harness) - - defer e.Close() - ctx := enginetest.NewContext(harness) - - // Confirm that the system variable was correctly set. - _, iter, err := e.Query(ctx, "select @@innodb_autoinc_lock_mode") - require.NoError(t, err) - rows, err := sql.RowIterToRows(ctx, iter) - require.NoError(t, err) - assert.Equal(t, rows, []sql.Row{{lockMode}}) - - // Ordinarily QueryEngine.query manages transactions. - // Since we can't use that for this test, we manually start a new transaction. - ts := ctx.Session.(sql.TransactionSession) - tx, err := ts.StartTransaction(ctx, sql.ReadWrite) - require.NoError(t, err) - ctx.SetTransaction(tx) - - getTriggerIter := func(query string) sql.RowIter { - root, err := e.AnalyzeQuery(ctx, query) - require.NoError(t, err) - - var triggerNode *plan.TriggerExecutor - transform.Node(root, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { - if triggerNode != nil { - return n, transform.SameTree, nil - } - if t, ok := n.(*plan.TriggerExecutor); ok { - triggerNode = t - } - return n, transform.NewTree, nil - }) - iter, err := e.EngineAnalyzer().ExecBuilder.Build(ctx, triggerNode, nil) - require.NoError(t, err) - return iter - } - - iter1 := getTriggerIter("INSERT INTO test1 (c0) select v from sequence5bit;") - iter2 := getTriggerIter("INSERT INTO test2 (c0) select v from sequence5bit;") - - // Alternate the iterators until they're exhausted. - var err1 error - var err2 error - for err1 != io.EOF || err2 != io.EOF { - if err1 != io.EOF { - var row1 sql.Row - require.NoError(t, err1) - row1, err1 = iter1.Next(ctx) - _ = row1 - } - if err2 != io.EOF { - require.NoError(t, err2) - _, err2 = iter2.Next(ctx) - } - } - err = iter1.Close(ctx) - require.NoError(t, err) - err = iter2.Close(ctx) - require.NoError(t, err) - - dsess.DSessFromSess(ctx.Session).CommitTransaction(ctx, ctx.GetTransaction()) - - // Verify that the inserts are seen by the engine. - { - _, iter, err := e.Query(ctx, "select count(*) from timestamps") - require.NoError(t, err) - rows, err := sql.RowIterToRows(ctx, iter) - require.NoError(t, err) - assert.Equal(t, rows, []sql.Row{{int64(64)}}) - } - - // Verify that the insert operations are actually interleaved by inspecting the order that values were added to `timestamps` - { - _, iter, err := e.Query(ctx, "select (select min(pk) from timestamps where t = 1) < (select max(pk) from timestamps where t = 2)") - require.NoError(t, err) - rows, err := sql.RowIterToRows(ctx, iter) - require.NoError(t, err) - assert.Equal(t, rows, []sql.Row{{true}}) - } - - { - _, iter, err := e.Query(ctx, "select (select min(pk) from timestamps where t = 2) < (select max(pk) from timestamps where t = 1)") - require.NoError(t, err) - rows, err := sql.RowIterToRows(ctx, iter) - require.NoError(t, err) - assert.Equal(t, rows, []sql.Row{{true}}) - } -} - // Convenience test for debugging a single query. Unskip and set to the desired query. func TestSingleMergeScript(t *testing.T) { t.Skip() @@ -543,21 +382,6 @@ func TestVersionedQueries(t *testing.T) { RunVersionedQueriesTest(t, h) } -func RunVersionedQueriesTest(t *testing.T, h DoltEnginetestHarness) { - h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) - - e, err := h.NewEngine(t) - require.NoError(t, err) - - for _, tt := range queries.VersionedQueries { - enginetest.TestQueryWithEngine(t, h, e, tt) - } - - for _, tt := range queries.VersionedScripts { - enginetest.TestScriptWithEngine(t, e, h, tt) - } -} - func TestAnsiQuotesSqlMode(t *testing.T) { enginetest.TestAnsiQuotesSqlMode(t, newDoltHarness(t)) } @@ -573,44 +397,6 @@ func TestQueryPlans(t *testing.T) { RunQueryTestPlans(t, harness) } -func RunQueryTestPlans(t *testing.T, harness DoltEnginetestHarness) { - // Dolt supports partial keys, so the index matched is different for some plans - // TODO: Fix these differences by implementing partial key matching in the memory tables, or the engine itself - skipped := []string{ - "SELECT pk,pk1,pk2 FROM one_pk LEFT JOIN two_pk ON pk=pk1", - "SELECT pk,pk1,pk2 FROM one_pk JOIN two_pk ON pk=pk1", - "SELECT one_pk.c5,pk1,pk2 FROM one_pk JOIN two_pk ON pk=pk1 ORDER BY 1,2,3", - "SELECT opk.c5,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON opk.pk=tpk.pk1 ORDER BY 1,2,3", - "SELECT opk.c5,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON pk=pk1 ORDER BY 1,2,3", - "SELECT pk,pk1,pk2 FROM one_pk LEFT JOIN two_pk ON pk=pk1 ORDER BY 1,2,3", - "SELECT pk,pk1,pk2 FROM one_pk t1, two_pk t2 WHERE pk=1 AND pk2=1 AND pk1=1 ORDER BY 1,2", - } - // Parallelism introduces Exchange nodes into the query plans, so disable. - // TODO: exchange nodes should really only be part of the explain plan under certain debug settings - harness = harness.NewHarness(t).WithSkippedQueries(skipped).WithConfigureStats(true) - if !types.IsFormat_DOLT(types.Format_Default) { - // only new format supports reverse IndexTableAccess - reverseIndexSkip := []string{ - "SELECT * FROM one_pk ORDER BY pk", - "SELECT * FROM two_pk ORDER BY pk1, pk2", - "SELECT * FROM two_pk ORDER BY pk1", - "SELECT pk1 AS one, pk2 AS two FROM two_pk ORDER BY pk1, pk2", - "SELECT pk1 AS one, pk2 AS two FROM two_pk ORDER BY one, two", - "SELECT i FROM (SELECT i FROM mytable ORDER BY i DESC LIMIT 1) sq WHERE i = 3", - "SELECT i FROM (SELECT i FROM (SELECT i FROM mytable ORDER BY DES LIMIT 1) sql1)sql2 WHERE i = 3", - "SELECT s,i FROM mytable order by i DESC", - "SELECT s,i FROM mytable as a order by i DESC", - "SELECT pk1, pk2 FROM two_pk order by pk1 asc, pk2 asc", - "SELECT pk1, pk2 FROM two_pk order by pk1 desc, pk2 desc", - "SELECT i FROM (SELECT i FROM (SELECT i FROM mytable ORDER BY i DESC LIMIT 1) sq1) sq2 WHERE i = 3", - } - harness = harness.WithSkippedQueries(reverseIndexSkip) - } - - defer harness.Close() - enginetest.TestQueryPlans(t, harness, queries.PlanTests) -} - func TestIntegrationQueryPlans(t *testing.T) { harness := newDoltEnginetestHarness(t).WithConfigureStats(true) defer harness.Close() @@ -626,45 +412,11 @@ func TestDoltDiffQueryPlans(t *testing.T) { RunDoltDiffQueryPlansTest(t, harness) } -func RunDoltDiffQueryPlansTest(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - harness.Setup(setup.SimpleSetup...) - e, err := harness.NewEngine(t) - require.NoError(t, err) - defer e.Close() - - for _, tt := range append(DoltDiffPlanTests, DoltCommitPlanTests...) { - enginetest.TestQueryPlanWithName(t, tt.Query, harness, e, tt.Query, tt.ExpectedPlan, sql.DescribeOptions{}) - } -} - func TestBranchPlans(t *testing.T) { harness := newDoltEnginetestHarness(t) RunBranchPlanTests(t, harness) } -func RunBranchPlanTests(t *testing.T, harness DoltEnginetestHarness) { - for _, script := range BranchPlanTests { - t.Run(script.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - - e := mustNewEngine(t, harness) - defer e.Close() - - for _, statement := range script.SetUpScript { - ctx := enginetest.NewContext(harness).WithQuery(statement) - enginetest.RunQueryWithContext(t, e, harness, ctx, statement) - } - for _, tt := range script.Queries { - t.Run(tt.Query, func(t *testing.T) { - TestIndexedAccess(t, e, harness, tt.Query, tt.Index) - }) - } - }) - } -} - func TestQueryErrors(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -676,19 +428,6 @@ func TestInfoSchema(t *testing.T) { RunInfoSchemaTests(t, h) } -func RunInfoSchemaTests(t *testing.T, h DoltEnginetestHarness) { - defer h.Close() - enginetest.TestInfoSchema(t, h) - - for _, script := range DoltInfoSchemaScripts { - func() { - h = h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestColumnAliases(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -758,35 +497,11 @@ func TestInsertIntoErrors(t *testing.T) { RunInsertIntoErrorsTest(t, h) } -func RunInsertIntoErrorsTest(t *testing.T, h DoltEnginetestHarness) { - h = h.WithSkippedQueries([]string{ - "create table bad (vb varbinary(65535))", - "insert into bad values (repeat('0', 65536))", - }) - defer h.Close() - enginetest.TestInsertIntoErrors(t, h) -} - func TestGeneratedColumns(t *testing.T) { harness := newDoltEnginetestHarness(t) RunGeneratedColumnTests(t, harness) } -func RunGeneratedColumnTests(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - enginetest.TestGeneratedColumns(t, - // virtual indexes are failing for certain lookups on this test - harness.WithSkippedQueries([]string{"create table t (pk int primary key, col1 int as (pk + 1));"})) - - for _, script := range GeneratedColumnMergeTestScripts { - func() { - h := harness.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestGeneratedColumnPlans(t *testing.T) { enginetest.TestGeneratedColumnPlans(t, newDoltHarness(t)) } @@ -1066,31 +781,11 @@ func TestBranchDdl(t *testing.T) { RunBranchDdlTest(t, h) } -func RunBranchDdlTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DdlBranchTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestBranchDdlPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunBranchDdlTestPrepared(t, h) } -func RunBranchDdlTestPrepared(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DdlBranchTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestPkOrdinalsDDL(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -1164,14 +859,6 @@ func TestIndexPrefix(t *testing.T) { RunIndexPrefixTest(t, harness) } -func RunIndexPrefixTest(t *testing.T, harness *DoltHarness) { - defer harness.Close() - enginetest.TestIndexPrefix(t, harness) - for _, script := range DoltIndexPrefixScripts { - enginetest.TestScript(t, harness, script) - } -} - func TestBigBlobs(t *testing.T) { skipOldFormat(t) @@ -1179,60 +866,11 @@ func TestBigBlobs(t *testing.T) { RunBigBlobsTest(t, h) } -func RunBigBlobsTest(t *testing.T, h *DoltHarness) { - defer h.Close() - h.Setup(setup.MydbData, setup.BlobData) - for _, tt := range BigBlobQueries { - enginetest.RunWriteQueryTest(t, h, tt) - } -} - func TestDropDatabase(t *testing.T) { h := newDoltEnginetestHarness(t) RunDropEngineTest(t, h) } -func RunDropEngineTest(t *testing.T, h DoltEnginetestHarness) { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, queries.ScriptTest{ - Name: "Drop database engine tests for Dolt only", - SetUpScript: []string{ - "CREATE DATABASE Test1db", - "CREATE DATABASE TEST2db", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "DROP DATABASE TeSt2DB", - Expected: []sql.Row{{gmstypes.OkResult{RowsAffected: 1}}}, - }, - { - Query: "USE test2db", - ExpectedErr: sql.ErrDatabaseNotFound, - }, - { - Query: "USE TEST1DB", - Expected: []sql.Row{}, - }, - { - Query: "DROP DATABASE IF EXISTS test1DB", - Expected: []sql.Row{{gmstypes.OkResult{RowsAffected: 1}}}, - }, - { - Query: "USE Test1db", - ExpectedErr: sql.ErrDatabaseNotFound, - }, - }, - }) - }() - - t.Skip("Dolt doesn't yet support dropping the primary database, which these tests do") - h = h.NewHarness(t) - defer h.Close() - enginetest.TestDropDatabase(t, h) -} - func TestCreateForeignKeys(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -1256,69 +894,11 @@ func TestForeignKeyBranches(t *testing.T) { RunForeignKeyBranchesTest(t, h) } -func RunForeignKeyBranchesTest(t *testing.T, h DoltEnginetestHarness) { - setupPrefix := []string{ - "call dolt_branch('b1')", - "use mydb/b1", - } - assertionsPrefix := []queries.ScriptTestAssertion{ - { - Query: "use mydb/b1", - SkipResultsCheck: true, - }, - } - for _, script := range queries.ForeignKeyTests { - // New harness for every script because we create branches - h := h.NewHarness(t) - h.Setup(setup.MydbData, setup.Parent_childData) - modifiedScript := script - modifiedScript.SetUpScript = append(setupPrefix, modifiedScript.SetUpScript...) - modifiedScript.Assertions = append(assertionsPrefix, modifiedScript.Assertions...) - enginetest.TestScript(t, h, modifiedScript) - } - - for _, script := range ForeignKeyBranchTests { - // New harness for every script because we create branches - h := h.NewHarness(t) - h.Setup(setup.MydbData, setup.Parent_childData) - enginetest.TestScript(t, h, script) - } -} - func TestForeignKeyBranchesPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunForeignKeyBranchesPreparedTest(t, h) } -func RunForeignKeyBranchesPreparedTest(t *testing.T, h DoltEnginetestHarness) { - setupPrefix := []string{ - "call dolt_branch('b1')", - "use mydb/b1", - } - assertionsPrefix := []queries.ScriptTestAssertion{ - { - Query: "use mydb/b1", - SkipResultsCheck: true, - }, - } - for _, script := range queries.ForeignKeyTests { - // New harness for every script because we create branches - h := h.NewHarness(t) - h.Setup(setup.MydbData, setup.Parent_childData) - modifiedScript := script - modifiedScript.SetUpScript = append(setupPrefix, modifiedScript.SetUpScript...) - modifiedScript.Assertions = append(assertionsPrefix, modifiedScript.Assertions...) - enginetest.TestScriptPrepared(t, h, modifiedScript) - } - - for _, script := range ForeignKeyBranchTests { - // New harness for every script because we create branches - h := h.NewHarness(t) - h.Setup(setup.MydbData, setup.Parent_childData) - enginetest.TestScriptPrepared(t, h, script) - } -} - func TestFulltextIndexes(t *testing.T) { if !types.IsFormat_DOLT(types.Format_Default) { t.Skip("FULLTEXT is not supported on the old format") @@ -1378,51 +958,16 @@ func TestBranchViews(t *testing.T) { RunBranchViewsTest(t, h) } -func RunBranchViewsTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range ViewBranchTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestBranchViewsPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunBranchViewsPreparedTest(t, h) } -func RunBranchViewsPreparedTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range ViewBranchTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestVersionedViews(t *testing.T) { h := newDoltEnginetestHarness(t) RunVersionedViewsTest(t, h) } -func RunVersionedViewsTest(t *testing.T, h DoltEnginetestHarness) { - defer h.Close() - h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) - - e, err := h.NewEngine(t) - require.NoError(t, err) - - for _, testCase := range queries.VersionedViewTests { - t.Run(testCase.Query, func(t *testing.T) { - ctx := enginetest.NewContext(h) - enginetest.TestQueryWithContext(t, ctx, e, h, testCase.Query, testCase.Expected, testCase.ExpectedColumns, nil) - }) - } -} - func TestWindowFunctions(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -1495,14 +1040,6 @@ func TestVariables(t *testing.T) { RunVariableTest(t, h) } -func RunVariableTest(t *testing.T, h DoltEnginetestHarness) { - defer h.Close() - enginetest.TestVariables(t, h) - for _, script := range DoltSystemVariables { - enginetest.TestScript(t, h, script) - } -} - func TestVariableErrors(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -1564,50 +1101,16 @@ func TestStoredProcedures(t *testing.T) { RunStoredProceduresTest(t, h) } -func RunStoredProceduresTest(t *testing.T, h DoltEnginetestHarness) { - tests := make([]queries.ScriptTest, 0, len(queries.ProcedureLogicTests)) - for _, test := range queries.ProcedureLogicTests { - // TODO: this passes locally but SOMETIMES fails tests on GitHub, no clue why - if test.Name != "ITERATE and LEAVE loops" { - tests = append(tests, test) - } - } - queries.ProcedureLogicTests = tests - - defer h.Close() - enginetest.TestStoredProcedures(t, h) -} - func TestDoltStoredProcedures(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltStoredProceduresTest(t, h) } -func RunDoltStoredProceduresTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltProcedureTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltStoredProceduresPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltStoredProceduresPreparedTest(t, h) } -func RunDoltStoredProceduresPreparedTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltProcedureTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestEvents(t *testing.T) { doltHarness := newDoltHarness(t) defer doltHarness.Close() @@ -1619,114 +1122,24 @@ func TestCallAsOf(t *testing.T) { RunCallAsOfTest(t, h) } -func RunCallAsOfTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltCallAsOf { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestLargeJsonObjects(t *testing.T) { harness := newDoltEnginetestHarness(t) RunLargeJsonObjectsTest(t, harness) } -func RunLargeJsonObjectsTest(t *testing.T, harness DoltEnginetestHarness) { - SkipByDefaultInCI(t) - defer harness.Close() - for _, script := range LargeJsonObjectScriptTests { - enginetest.TestScript(t, harness, script) - } +func TestTransactions(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunTransactionTests(t, h) } -func SkipByDefaultInCI(t *testing.T) { - if os.Getenv("CI") != "" && os.Getenv("DOLT_TEST_RUN_NON_RACE_TESTS") == "" { - t.Skip() - } +func TestBranchTransactions(t *testing.T) { + h := newDoltEnginetestHarness(t) + RunBranchTransactionTest(t, h) } -func TestTransactions(t *testing.T) { +func TestMultiDbTransactions(t *testing.T) { h := newDoltEnginetestHarness(t) - RunTransactionTests(t, h) -} - -func RunTransactionTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range queries.TransactionTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } - for _, script := range DoltTransactionTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } - for _, script := range DoltStoredProcedureTransactionTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } - for _, script := range DoltConflictHandlingTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } - for _, script := range DoltConstraintViolationTransactionTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } -} - -func TestBranchTransactions(t *testing.T) { - h := newDoltEnginetestHarness(t) - RunBranchTransactionTest(t, h) -} - -func RunBranchTransactionTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range BranchIsolationTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } -} - -func TestMultiDbTransactions(t *testing.T) { - h := newDoltEnginetestHarness(t) - RunMultiDbTransactionsTest(t, h) -} - -func RunMultiDbTransactionsTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range MultiDbTransactionTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - - for _, script := range MultiDbSavepointTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestTransactionScript(t, h, script) - }() - } + RunMultiDbTransactionsTest(t, h) } func TestMultiDbTransactionsPrepared(t *testing.T) { @@ -1734,16 +1147,6 @@ func TestMultiDbTransactionsPrepared(t *testing.T) { RunMultiDbTransactionsPreparedTest(t, h) } -func RunMultiDbTransactionsPreparedTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range MultiDbTransactionTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestConcurrentTransactions(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -1755,192 +1158,26 @@ func TestDoltScripts(t *testing.T) { RunDoltScriptsTest(t, harness) } -func RunDoltScriptsTest(t *testing.T, harness DoltEnginetestHarness) { - for _, script := range DoltScripts { - go func() { - harness := harness.NewHarness(t) - defer harness.Close() - enginetest.TestScript(t, harness, script) - }() - } -} - func TestDoltTempTableScripts(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltTempTableScripts(t, harness) } -func RunDoltTempTableScripts(t *testing.T, harness DoltEnginetestHarness) { - for _, script := range DoltTempTableScripts { - harness := harness.NewHarness(t) - enginetest.TestScript(t, harness, script) - harness.Close() - } -} - func TestDoltRevisionDbScripts(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRevisionDbScriptsTest(t, h) } -func RunDoltRevisionDbScriptsTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltRevisionDbScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - - // Testing a commit-qualified database revision spec requires - // a little extra work to get the generated commit hash - h = h.NewHarness(t) - defer h.Close() - e, err := h.NewEngine(t) - require.NoError(t, err) - defer e.Close() - ctx := h.NewContext() - - setupScripts := []setup.SetupScript{ - {"create table t01 (pk int primary key, c1 int)"}, - {"call dolt_add('.');"}, - {"call dolt_commit('-am', 'creating table t01 on main');"}, - {"insert into t01 values (1, 1), (2, 2);"}, - {"call dolt_commit('-am', 'adding rows to table t01 on main');"}, - {"insert into t01 values (3, 3);"}, - {"call dolt_commit('-am', 'adding another row to table t01 on main');"}, - } - _, err = enginetest.RunSetupScripts(ctx, h.Engine(), setupScripts, true) - require.NoError(t, err) - - _, iter, err := h.Engine().Query(ctx, "select hashof('HEAD~2');") - require.NoError(t, err) - rows, err := sql.RowIterToRows(ctx, iter) - require.NoError(t, err) - assert.Equal(t, 1, len(rows)) - commithash := rows[0][0].(string) - - scriptTest := queries.ScriptTest{ - Name: "database revision specs: commit-qualified revision spec", - Assertions: []queries.ScriptTestAssertion{ - { - Query: "show databases;", - Expected: []sql.Row{{"mydb"}, {"information_schema"}, {"mysql"}}, - }, - { - Query: "use mydb/" + commithash, - Expected: []sql.Row{}, - }, - { - Query: "select active_branch();", - Expected: []sql.Row{ - {nil}, - }, - }, - { - Query: "select database();", - Expected: []sql.Row{{"mydb/" + commithash}}, - }, - { - Query: "show databases;", - Expected: []sql.Row{{"mydb"}, {"mydb/" + commithash}, {"information_schema"}, {"mysql"}}, - }, - { - Query: "select * from t01", - Expected: []sql.Row{}, - }, - { - Query: "call dolt_reset();", - ExpectedErrStr: "unable to reset HEAD in read-only databases", - }, - { - Query: "call dolt_checkout('main');", - Expected: []sql.Row{{0, "Switched to branch 'main'"}}, - }, - { - Query: "select database();", - Expected: []sql.Row{{"mydb"}}, - }, - { - Query: "select active_branch();", - Expected: []sql.Row{{"main"}}, - }, - { - Query: "use mydb;", - Expected: []sql.Row{}, - }, - { - Query: "select database();", - Expected: []sql.Row{{"mydb"}}, - }, - { - Query: "show databases;", - Expected: []sql.Row{{"mydb"}, {"information_schema"}, {"mysql"}}, - }, - }, - } - - enginetest.TestScript(t, h, scriptTest) -} - func TestDoltRevisionDbScriptsPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRevisionDbScriptsPreparedTest(t, h) } -func RunDoltRevisionDbScriptsPreparedTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltRevisionDbScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestDoltDdlScripts(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltDdlScripts(t, harness) } -func RunDoltDdlScripts(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - harness.Setup() - - for _, script := range ModifyAndChangeColumnScripts { - e, err := harness.NewEngine(t) - require.NoError(t, err) - enginetest.TestScriptWithEngine(t, e, harness, script) - } - - for _, script := range ModifyColumnTypeScripts { - e, err := harness.NewEngine(t) - require.NoError(t, err) - enginetest.TestScriptWithEngine(t, e, harness, script) - } - - for _, script := range DropColumnScripts { - e, err := harness.NewEngine(t) - require.NoError(t, err) - enginetest.TestScriptWithEngine(t, e, harness, script) - } - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("not fixing unique index on keyless tables for old format") - } - for _, script := range AddIndexScripts { - e, err := harness.NewEngine(t) - require.NoError(t, err) - enginetest.TestScriptWithEngine(t, e, harness, script) - } - - // TODO: these scripts should be general enough to go in GMS - for _, script := range AddDropPrimaryKeysScripts { - e, err := harness.NewEngine(t) - require.NoError(t, err) - enginetest.TestScriptWithEngine(t, e, harness, script) - } -} - func TestBrokenDdlScripts(t *testing.T) { for _, script := range BrokenDDLScripts { t.Skip(script.Name) @@ -1958,31 +1195,11 @@ func TestShowCreateTable(t *testing.T) { RunShowCreateTableTests(t, h) } -func RunShowCreateTableTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range ShowCreateTableScriptTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestShowCreateTablePrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunShowCreateTablePreparedTests(t, h) } -func RunShowCreateTablePreparedTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range ShowCreateTableScriptTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestViewsWithAsOf(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -2001,199 +1218,58 @@ func TestDoltMerge(t *testing.T) { RunDoltMergeTests(t, h) } -func RunDoltMergeTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range MergeScripts { - // harness can't reset effectively when there are new commits / branches created, so use a new harness for - // each script - func() { - h := h.NewHarness(t) - defer h.Close() - h.Setup(setup.MydbData) - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltMergePrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltMergePreparedTests(t, h) } -func RunDoltMergePreparedTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range MergeScripts { - // harness can't reset effectively when there are new commits / branches created, so use a new harness for - // each script - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestDoltRebase(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRebaseTests(t, h) } -func RunDoltRebaseTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltRebaseScriptTests { - func() { - h := h.NewHarness(t) - defer h.Close() - h.SkipSetupCommit() - enginetest.TestScript(t, h, script) - }() - } - - testMultiSessionScriptTests(t, DoltRebaseMultiSessionScriptTests) -} - func TestDoltRebasePrepared(t *testing.T) { h := newDoltHarness(t) RunDoltRebasePreparedTests(t, h) } -func RunDoltRebasePreparedTests(t *testing.T, h *DoltHarness) { - for _, script := range DoltRebaseScriptTests { - func() { - h := h.NewHarness(t) - defer h.Close() - h.SkipSetupCommit() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestDoltRevert(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRevertTests(t, h) } -func RunDoltRevertTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range RevertScripts { - // harness can't reset effectively. Use a new harness for each script - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltRevertPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRevertPreparedTests(t, h) } -func RunDoltRevertPreparedTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range RevertScripts { - // harness can't reset effectively. Use a new harness for each script - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltAutoIncrement(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltAutoIncrementTests(t, h) } -func RunDoltAutoIncrementTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltAutoIncrementTests { - // doing commits on different branches is antagonistic to engine reuse, use a new engine on each script - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltAutoIncrementPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltAutoIncrementPreparedTests(t, h) } -func RunDoltAutoIncrementPreparedTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltAutoIncrementTests { - // doing commits on different branches is antagonistic to engine reuse, use a new engine on each script - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltConflictsTableNameTable(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltConflictsTableNameTableTests(t, h) } -func RunDoltConflictsTableNameTableTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltConflictTableNameTableTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - - if types.IsFormat_DOLT(types.Format_Default) { - for _, script := range Dolt1ConflictTableNameTableTests { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - } -} - // tests new format behavior for keyless merges that create CVs and conflicts func TestKeylessDoltMergeCVsAndConflicts(t *testing.T) { h := newDoltEnginetestHarness(t) RunKelyessDoltMergeCVsAndConflictsTests(t, h) } -func RunKelyessDoltMergeCVsAndConflictsTests(t *testing.T, h DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip() - } - for _, script := range KeylessMergeCVsAndConflictsScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - // eventually this will be part of TestDoltMerge func TestDoltMergeArtifacts(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltMergeArtifacts(t, h) } -func RunDoltMergeArtifacts(t *testing.T, h DoltEnginetestHarness) { - for _, script := range MergeArtifactsScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - for _, script := range SchemaConflictScripts { - h := h.NewHarness(t) - enginetest.TestScript(t, h, script) - h.Close() - } -} - // these tests are temporary while there is a difference between the old format // and new format merge behaviors. func TestOldFormatMergeConflictsAndCVs(t *testing.T) { @@ -2214,17 +1290,6 @@ func TestDoltReset(t *testing.T) { RunDoltResetTest(t, h) } -func RunDoltResetTest(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltReset { - // dolt versioning conflicts with reset harness -- use new harness every time - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltGC(t *testing.T) { t.SkipNow() for _, script := range DoltGC { @@ -2241,132 +1306,31 @@ func TestDoltCheckout(t *testing.T) { RunDoltCheckoutTests(t, h) } -func RunDoltCheckoutTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltCheckoutScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - - h = h.NewHarness(t) - defer h.Close() - engine, err := h.NewEngine(t) - require.NoError(t, err) - readOnlyEngine, err := h.NewReadOnlyEngine(engine.EngineAnalyzer().Catalog.DbProvider) - require.NoError(t, err) - - for _, script := range DoltCheckoutReadOnlyScripts { - enginetest.TestScriptWithEngine(t, readOnlyEngine, h, script) - } -} - func TestDoltCheckoutPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltCheckoutPreparedTests(t, h) } -func RunDoltCheckoutPreparedTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltCheckoutScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } - - h = h.NewHarness(t) - defer h.Close() - engine, err := h.NewEngine(t) - require.NoError(t, err) - readOnlyEngine, err := h.NewReadOnlyEngine(engine.EngineAnalyzer().Catalog.DbProvider) - require.NoError(t, err) - - for _, script := range DoltCheckoutReadOnlyScripts { - enginetest.TestScriptWithEnginePrepared(t, readOnlyEngine, h, script) - } -} - func TestDoltBranch(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltBranchTests(t, h) } -func RunDoltBranchTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltBranchScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltTag(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltTagTests(t, h) } -func RunDoltTagTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltTagTestScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltRemote(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltRemoteTests(t, h) } -func RunDoltRemoteTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltRemoteTestScripts { - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - func TestDoltUndrop(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltUndropTests(t, h) } -func RunDoltUndropTests(t *testing.T, h DoltEnginetestHarness) { - h.UseLocalFileSystem() - defer h.Close() - for _, script := range DoltUndropTestScripts { - enginetest.TestScript(t, h, script) - } -} - -type testCommitClock struct { - unixNano int64 -} - -func (tcc *testCommitClock) Now() time.Time { - now := time.Unix(0, tcc.unixNano) - tcc.unixNano += int64(time.Hour) - return now -} - -func installTestCommitClock(tcc *testCommitClock) func() { - oldNowFunc := datas.CommitterDate - oldCommitLoc := datas.CommitLoc - datas.CommitterDate = tcc.Now - datas.CommitLoc = time.UTC - return func() { - datas.CommitterDate = oldNowFunc - datas.CommitLoc = oldCommitLoc - } -} - // TestSingleTransactionScript is a convenience method for debugging a single transaction test. Unskip and set to the // desired test. func TestSingleTransactionScript(t *testing.T) { @@ -2452,31 +1416,11 @@ func TestHistorySystemTable(t *testing.T) { RunHistorySystemTableTests(t, harness) } -func RunHistorySystemTableTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range HistorySystemTableScriptTests { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - t.Run(test.Name, func(t *testing.T) { - enginetest.TestScript(t, harness, test) - }) - } -} - func TestHistorySystemTablePrepared(t *testing.T) { harness := newDoltEnginetestHarness(t).WithParallelism(2) RunHistorySystemTableTestsPrepared(t, harness) } -func RunHistorySystemTableTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range HistorySystemTableScriptTests { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - t.Run(test.Name, func(t *testing.T) { - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestBrokenHistorySystemTablePrepared(t *testing.T) { t.Skip() harness := newDoltHarness(t) @@ -2495,261 +1439,81 @@ func TestUnscopedDiffSystemTable(t *testing.T) { RunUnscopedDiffSystemTableTests(t, h) } -func RunUnscopedDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { - for _, test := range UnscopedDiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, test) - }) - } -} - func TestUnscopedDiffSystemTablePrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunUnscopedDiffSystemTableTestsPrepared(t, h) } -func RunUnscopedDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { - for _, test := range UnscopedDiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, test) - }) - } -} - func TestColumnDiffSystemTable(t *testing.T) { h := newDoltEnginetestHarness(t) RunColumnDiffSystemTableTests(t, h) } -func RunColumnDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("correct behavior of dolt_column_diff only guaranteed on new format") - } - for _, test := range ColumnDiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - enginetest.TestScript(t, h.NewHarness(t), test) - }) - } -} - func TestColumnDiffSystemTablePrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunColumnDiffSystemTableTestsPrepared(t, h) } -func RunColumnDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("correct behavior of dolt_column_diff only guaranteed on new format") - } - for _, test := range ColumnDiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - enginetest.TestScriptPrepared(t, h.NewHarness(t), test) - }) - } -} - func TestStatBranchTests(t *testing.T) { harness := newDoltEnginetestHarness(t) RunStatBranchTests(t, harness) } -func RunStatBranchTests(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - for _, test := range StatBranchTests { - t.Run(test.Name, func(t *testing.T) { - // reset engine so provider statistics are clean - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - harness = harness.WithConfigureStats(true) - e := mustNewEngine(t, harness) - defer e.Close() - enginetest.TestScriptWithEngine(t, e, harness, test) - }) - } -} - func TestStatsFunctions(t *testing.T) { harness := newDoltEnginetestHarness(t) RunStatsFunctionsTest(t, harness) } -func RunStatsFunctionsTest(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - for _, test := range StatProcTests { - t.Run(test.Name, func(t *testing.T) { - // reset engine so provider statistics are clean - harness = harness.NewHarness(t).WithConfigureStats(true) - harness.Setup(setup.MydbData) - harness.SkipSetupCommit() - e := mustNewEngine(t, harness) - defer e.Close() - enginetest.TestScriptWithEngine(t, e, harness, test) - }) - } -} - func TestDiffTableFunction(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDiffTableFunctionTests(t, harness) } -func RunDiffTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DiffTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - func TestDiffTableFunctionPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDiffTableFunctionTestsPrepared(t, harness) } -func RunDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DiffTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestDiffStatTableFunction(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDiffStatTableFunctionTests(t, harness) } -func RunDiffStatTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DiffStatTableFunctionScriptTests { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - t.Run(test.Name, func(t *testing.T) { - enginetest.TestScript(t, harness, test) - }) - } -} - func TestDiffStatTableFunctionPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDiffStatTableFunctionTestsPrepared(t, harness) } -func RunDiffStatTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DiffStatTableFunctionScriptTests { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - t.Run(test.Name, func(t *testing.T) { - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestDiffSummaryTableFunction(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDiffSummaryTableFunctionTests(t, harness) } -func RunDiffSummaryTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DiffSummaryTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - func TestDiffSummaryTableFunctionPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDiffSummaryTableFunctionTestsPrepared(t, harness) } -func RunDiffSummaryTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DiffSummaryTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestPatchTableFunction(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltPatchTableFunctionTests(t, harness) } -func RunDoltPatchTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range PatchTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - func TestPatchTableFunctionPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltPatchTableFunctionTestsPrepared(t, harness) } -func RunDoltPatchTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range PatchTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestLogTableFunction(t *testing.T) { harness := newDoltEnginetestHarness(t) RunLogTableFunctionTests(t, harness) } -func RunLogTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range LogTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - harness.SkipSetupCommit() - enginetest.TestScript(t, harness, test) - }) - } -} - func TestLogTableFunctionPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunLogTableFunctionTestsPrepared(t, harness) } -func RunLogTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range LogTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - harness.SkipSetupCommit() - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestDoltReflog(t *testing.T) { for _, script := range DoltReflogTestScripts { h := newDoltHarnessForLocalFilesystem(t) @@ -2773,125 +1537,29 @@ func TestCommitDiffSystemTable(t *testing.T) { RunCommitDiffSystemTableTests(t, harness) } -func RunCommitDiffSystemTableTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range CommitDiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - func TestCommitDiffSystemTablePrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunCommitDiffSystemTableTestsPrepared(t, harness) } -func RunCommitDiffSystemTableTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range CommitDiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestDiffSystemTable(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltDiffSystemTableTests(t, h) } -func RunDoltDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("only new format support system table indexing") - } - - for _, test := range DiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - h = h.NewHarness(t) - defer h.Close() - h.Setup(setup.MydbData) - enginetest.TestScript(t, h, test) - }) - } - - if types.IsFormat_DOLT(types.Format_Default) { - for _, test := range Dolt1DiffSystemTableScripts { - func() { - h = h.NewHarness(t) - defer h.Close() - h.Setup(setup.MydbData) - enginetest.TestScript(t, h, test) - }() - } - } -} - func TestDiffSystemTablePrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltDiffSystemTableTestsPrepared(t, h) } -func RunDoltDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("only new format support system table indexing") - } - - for _, test := range DiffSystemTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - h = h.NewHarness(t) - defer h.Close() - h.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, h, test) - }) - } - - if types.IsFormat_DOLT(types.Format_Default) { - for _, test := range Dolt1DiffSystemTableScripts { - func() { - h = h.NewHarness(t) - defer h.Close() - h.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, h, test) - }() - } - } -} - -func TestSchemaDiffTableFunction(t *testing.T) { - harness := newDoltEnginetestHarness(t) - RunSchemaDiffTableFunctionTests(t, harness) -} - -func RunSchemaDiffTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range SchemaDiffTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - -func TestSchemaDiffTableFunctionPrepared(t *testing.T) { +func TestSchemaDiffTableFunction(t *testing.T) { harness := newDoltEnginetestHarness(t) - RunSchemaDiffTableFunctionTestsPrepared(t, harness) + RunSchemaDiffTableFunctionTests(t, harness) } -func RunSchemaDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range SchemaDiffTableFunctionScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } +func TestSchemaDiffTableFunctionPrepared(t *testing.T) { + harness := newDoltEnginetestHarness(t) + RunSchemaDiffTableFunctionTestsPrepared(t, harness) } func TestDoltDatabaseCollationDiffs(t *testing.T) { @@ -2899,163 +1567,31 @@ func TestDoltDatabaseCollationDiffs(t *testing.T) { RunDoltDatabaseCollationDiffsTests(t, harness) } -func RunDoltDatabaseCollationDiffsTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range DoltDatabaseCollationScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestQueryDiff(t *testing.T) { harness := newDoltEnginetestHarness(t) RunQueryDiffTests(t, harness) } -func RunQueryDiffTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range QueryDiffTableScriptTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - -func mustNewEngine(t *testing.T, h enginetest.Harness) enginetest.QueryEngine { - e, err := h.NewEngine(t) - if err != nil { - require.NoError(t, err) - } - return e -} - -var biasedCosters = []memo.Coster{ - memo.NewInnerBiasedCoster(), - memo.NewLookupBiasedCoster(), - memo.NewHashBiasedCoster(), - memo.NewMergeBiasedCoster(), -} - func TestSystemTableIndexes(t *testing.T) { harness := newDoltEnginetestHarness(t) RunSystemTableIndexesTests(t, harness) } -func RunSystemTableIndexesTests(t *testing.T, harness DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("only new format support system table indexing") - } - - for _, stt := range SystemTableIndexTests { - harness = harness.NewHarness(t).WithParallelism(2) - defer harness.Close() - harness.SkipSetupCommit() - e := mustNewEngine(t, harness) - defer e.Close() - e.EngineAnalyzer().Coster = memo.NewMergeBiasedCoster() - - ctx := enginetest.NewContext(harness) - for _, q := range stt.setup { - enginetest.RunQueryWithContext(t, e, harness, ctx, q) - } - - for i, c := range []string{"inner", "lookup", "hash", "merge"} { - e.EngineAnalyzer().Coster = biasedCosters[i] - for _, tt := range stt.queries { - if tt.query == "select count(*) from dolt_blame_xy" && c == "inner" { - // todo we either need join hints to work inside the blame view - // and force the window relation to be primary, or we need the - // blame view's timestamp columns to be specific enough to not - // overlap during testing. - t.Skip("the blame table is unstable as secondary table in join with exchange node") - } - t.Run(fmt.Sprintf("%s(%s): %s", stt.name, c, tt.query), func(t *testing.T) { - if tt.skip { - t.Skip() - } - - ctx = ctx.WithQuery(tt.query) - if tt.exp != nil { - enginetest.TestQueryWithContext(t, ctx, e, harness, tt.query, tt.exp, nil, nil) - } - }) - } - } - } -} - func TestSystemTableIndexesPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunSystemTableIndexesTestsPrepared(t, harness) } -func RunSystemTableIndexesTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip("only new format support system table indexing") - } - - for _, stt := range SystemTableIndexTests { - harness = harness.NewHarness(t).WithParallelism(2) - defer harness.Close() - harness.SkipSetupCommit() - e := mustNewEngine(t, harness) - defer e.Close() - - ctx := enginetest.NewContext(harness) - for _, q := range stt.setup { - enginetest.RunQueryWithContext(t, e, harness, ctx, q) - } - - for _, tt := range stt.queries { - t.Run(fmt.Sprintf("%s: %s", stt.name, tt.query), func(t *testing.T) { - if tt.skip { - t.Skip() - } - - ctx = ctx.WithQuery(tt.query) - if tt.exp != nil { - enginetest.TestPreparedQueryWithContext(t, ctx, e, harness, tt.query, tt.exp, nil, nil, false) - } - }) - } - } -} - func TestSystemTableFunctionIndexes(t *testing.T) { harness := newDoltEnginetestHarness(t) RunSystemTableFunctionIndexesTests(t, harness) } -func RunSystemTableFunctionIndexesTests(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range SystemTableFunctionIndexTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - enginetest.TestScript(t, harness, test) - }) - } -} - func TestSystemTableFunctionIndexesPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunSystemTableFunctionIndexesTestsPrepared(t, harness) } -func RunSystemTableFunctionIndexesTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, test := range SystemTableFunctionIndexTests { - t.Run(test.Name, func(t *testing.T) { - harness = harness.NewHarness(t) - harness.Setup(setup.MydbData) - enginetest.TestScriptPrepared(t, harness, test) - }) - } -} - func TestReadOnlyDatabases(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -3073,13 +1609,6 @@ func TestAddAutoIncrementColumn(t *testing.T) { RunAddAutoIncrementColumnTests(t, h) } -func RunAddAutoIncrementColumnTests(t *testing.T, h DoltEnginetestHarness) { - defer h.Close() - for _, script := range queries.AlterTableAddAutoIncrementScripts { - enginetest.TestScript(t, h, script) - } -} - func TestNullRanges(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -3115,51 +1644,21 @@ func TestDoltCherryPick(t *testing.T) { RunDoltCherryPickTests(t, harness) } -func RunDoltCherryPickTests(t *testing.T, harness DoltEnginetestHarness) { - for _, script := range DoltCherryPickTests { - harness = harness.NewHarness(t) - enginetest.TestScript(t, harness, script) - harness.Close() - } -} - func TestDoltCherryPickPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltCherryPickTestsPrepared(t, harness) } -func RunDoltCherryPickTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - for _, script := range DoltCherryPickTests { - harness = harness.NewHarness(t) - enginetest.TestScriptPrepared(t, harness, script) - harness.Close() - } -} - func TestDoltCommit(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltCommitTests(t, harness) } -func RunDoltCommitTests(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - for _, script := range DoltCommitTests { - enginetest.TestScript(t, harness, script) - } -} - func TestDoltCommitPrepared(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltCommitTestsPrepared(t, harness) } -func RunDoltCommitTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { - defer harness.Close() - for _, script := range DoltCommitTests { - enginetest.TestScriptPrepared(t, harness, script) - } -} - func TestQueriesPrepared(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -3171,16 +1670,6 @@ func TestStatsHistograms(t *testing.T) { RunStatsHistogramTests(t, h) } -func RunStatsHistogramTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltHistogramTests { - func() { - h = h.NewHarness(t).WithConfigureStats(true) - defer h.Close() - enginetest.TestScript(t, h, script) - }() - } -} - // TestStatsIO force a provider reload in-between setup and assertions that // forces a round trip of the statistics table before inspecting values. func TestStatsIO(t *testing.T) { @@ -3188,35 +1677,11 @@ func TestStatsIO(t *testing.T) { RunStatsIOTests(t, h) } -func RunStatsIOTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range append(DoltStatsIOTests, DoltHistogramTests...) { - func() { - h = h.NewHarness(t).WithConfigureStats(true) - defer h.Close() - e := mustNewEngine(t, h) - if enginetest.IsServerEngine(e) { - return - } - defer e.Close() - TestProviderReloadScriptWithEngine(t, e, h, script) - }() - } -} - func TestJoinStats(t *testing.T) { h := newDoltEnginetestHarness(t) RunJoinStatsTests(t, h) } -// these are sensitive to cardinality estimates, -// particularly the join-filter tests that trade-off -// smallest table first vs smallest join first -func RunJoinStatsTests(t *testing.T, h DoltEnginetestHarness) { - defer h.Close() - h = h.WithConfigureStats(true) - enginetest.TestJoinStats(t, h) -} - func TestStatisticIndexes(t *testing.T) { h := newDoltHarness(t) defer h.Close() @@ -3236,37 +1701,11 @@ func TestPreparedStatistics(t *testing.T) { RunPreparedStatisticsTests(t, h) } -func RunPreparedStatisticsTests(t *testing.T, h DoltEnginetestHarness) { - for _, script := range DoltHistogramTests { - func() { - h := h.NewHarness(t).WithConfigureStats(true) - defer h.Close() - enginetest.TestScriptPrepared(t, h, script) - }() - } -} - func TestVersionedQueriesPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunVersionedQueriesPreparedTests(t, h) } -func RunVersionedQueriesPreparedTests(t *testing.T, h DoltEnginetestHarness) { - defer h.Close() - h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) - - e, err := h.NewEngine(t) - require.NoError(t, err) - - for _, tt := range queries.VersionedQueries { - enginetest.TestPreparedQueryWithEngine(t, h, e, tt) - } - - for _, tt := range queries.VersionedScripts { - enginetest.TestScriptWithEnginePrepared(t, e, h, tt) - } -} - func TestInfoSchemaPrepared(t *testing.T) { skipPreparedTests(t) h := newDoltHarness(t) @@ -3438,234 +1877,16 @@ func TestAddDropPrimaryKeys(t *testing.T) { RunAddDropPrimaryKeysTests(t, harness) } -func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { - t.Run("adding and dropping primary keys does not result in duplicate NOT NULL constraints", func(t *testing.T) { - harness = harness.NewHarness(t) - defer harness.Close() - addPkScript := queries.ScriptTest{ - Name: "add primary keys", - SetUpScript: []string{ - "create table test (id int not null, c1 int);", - "create index c1_idx on test(c1)", - "insert into test values (1,1),(2,2)", - "ALTER TABLE test ADD PRIMARY KEY(id)", - "ALTER TABLE test DROP PRIMARY KEY", - "ALTER TABLE test ADD PRIMARY KEY(id)", - "ALTER TABLE test DROP PRIMARY KEY", - "ALTER TABLE test ADD PRIMARY KEY(id)", - "ALTER TABLE test DROP PRIMARY KEY", - "ALTER TABLE test ADD PRIMARY KEY(id)", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "show create table test", - Expected: []sql.Row{ - {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `c1_idx` (`c1`)\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, - }, - }, - }, - } - - enginetest.TestScript(t, harness, addPkScript) - - // make sure there is only one NOT NULL constraint after all those mutations - ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) - ws, err := harness.Session().WorkingSet(ctx, "mydb") - require.NoError(t, err) - - table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) - require.NoError(t, err) - require.True(t, ok) - - sch, err := table.GetSchema(ctx) - for _, col := range sch.GetAllCols().GetColumns() { - count := 0 - for _, cc := range col.Constraints { - if cc.GetConstraintType() == schema.NotNullConstraintType { - count++ - } - } - require.Less(t, count, 2) - } - }) - - t.Run("Add primary key to table with index", func(t *testing.T) { - harness := harness.NewHarness(t) - defer harness.Close() - script := queries.ScriptTest{ - Name: "add primary keys to table with index", - SetUpScript: []string{ - "create table test (id int not null, c1 int);", - "create index c1_idx on test(c1)", - "insert into test values (1,1),(2,2)", - "ALTER TABLE test ADD constraint test_check CHECK (c1 > 0)", - "ALTER TABLE test ADD PRIMARY KEY(id)", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "show create table test", - Expected: []sql.Row{ - {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `c1_idx` (`c1`),\n" + - " CONSTRAINT `test_check` CHECK ((`c1` > 0))\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, - }, - }, - { - Query: "select * from test order by id", - Expected: []sql.Row{ - {1, 1}, - {2, 2}, - }, - }, - }, - } - enginetest.TestScript(t, harness, script) - - ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) - ws, err := harness.Session().WorkingSet(ctx, "mydb") - require.NoError(t, err) - - table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) - require.NoError(t, err) - require.True(t, ok) - - // Assert the new index map is not empty - newRows, err := table.GetIndexRowData(ctx, "c1_idx") - require.NoError(t, err) - empty, err := newRows.Empty() - require.NoError(t, err) - assert.False(t, empty) - count, err := newRows.Count() - require.NoError(t, err) - assert.Equal(t, count, uint64(2)) - }) - - t.Run("Add primary key when one more cells contain NULL", func(t *testing.T) { - harness := harness.NewHarness(t) - defer harness.Close() - script := queries.ScriptTest{ - Name: "Add primary key when one more cells contain NULL", - SetUpScript: []string{ - "create table test (id int not null, c1 int);", - "create index c1_idx on test(c1)", - "insert into test values (1,1),(2,2)", - "ALTER TABLE test ADD PRIMARY KEY (c1)", - "ALTER TABLE test ADD COLUMN (c2 INT NULL)", - "ALTER TABLE test DROP PRIMARY KEY", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "ALTER TABLE test ADD PRIMARY KEY (id, c1, c2)", - ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull, - }, - }, - } - enginetest.TestScript(t, harness, script) - }) - - t.Run("Drop primary key from table with index", func(t *testing.T) { - harness := harness.NewHarness(t) - defer harness.Close() - script := queries.ScriptTest{ - Name: "Drop primary key from table with index", - SetUpScript: []string{ - "create table test (id int not null primary key, c1 int);", - "create index c1_idx on test(c1)", - "insert into test values (1,1),(2,2)", - "ALTER TABLE test DROP PRIMARY KEY", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "show create table test", - Expected: []sql.Row{ - {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " KEY `c1_idx` (`c1`)\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, - }, - }, - { - Query: "select * from test order by id", - Expected: []sql.Row{ - {1, 1}, - {2, 2}, - }, - }, - }, - } - - enginetest.TestScript(t, harness, script) - - ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) - ws, err := harness.Session().WorkingSet(ctx, "mydb") - require.NoError(t, err) - - table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) - require.NoError(t, err) - require.True(t, ok) - - // Assert the index map is not empty - newIdx, err := table.GetIndexRowData(ctx, "c1_idx") - assert.NoError(t, err) - empty, err := newIdx.Empty() - require.NoError(t, err) - assert.False(t, empty) - count, err := newIdx.Count() - require.NoError(t, err) - assert.Equal(t, count, uint64(2)) - }) -} - func TestDoltVerifyConstraints(t *testing.T) { harness := newDoltEnginetestHarness(t) RunDoltVerifyConstraintsTests(t, harness) } -func RunDoltVerifyConstraintsTests(t *testing.T, harness DoltEnginetestHarness) { - for _, script := range DoltVerifyConstraintsTestScripts { - func() { - harness = harness.NewHarness(t) - defer harness.Close() - enginetest.TestScript(t, harness, script) - }() - } -} - func TestDoltStorageFormat(t *testing.T) { h := newDoltEnginetestHarness(t) RunDoltStorageFormatTests(t, h) } -func RunDoltStorageFormatTests(t *testing.T, h DoltEnginetestHarness) { - var expectedFormatString string - if types.IsFormat_DOLT(types.Format_Default) { - expectedFormatString = "NEW ( __DOLT__ )" - } else { - expectedFormatString = fmt.Sprintf("OLD ( %s )", types.Format_Default.VersionString()) - } - script := queries.ScriptTest{ - Name: "dolt storage format function works", - Assertions: []queries.ScriptTestAssertion{ - { - Query: "select dolt_storage_format()", - Expected: []sql.Row{{expectedFormatString}}, - }, - }, - } - defer h.Close() - enginetest.TestScript(t, h, script) -} - func TestDoltStorageFormatPrepared(t *testing.T) { var expectedFormatString string if types.IsFormat_DOLT(types.Format_Default) { @@ -3684,57 +1905,12 @@ func TestThreeWayMergeWithSchemaChangeScripts(t *testing.T) { RunThreeWayMergeWithSchemaChangeScripts(t, h) } -func RunThreeWayMergeWithSchemaChangeScripts(t *testing.T, h DoltEnginetestHarness) { - skipOldFormat(t) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsCollations, "collation changes", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsConstraints, "constraint changes", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsSchemaConflicts, "schema conflicts", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsGeneratedColumns, "generated columns", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForJsonConflicts, "json merge", false) - - // Run non-symmetric schema merge tests in just one direction - t.Run("type changes", func(t *testing.T) { - for _, script := range SchemaChangeTestsTypeChanges { - // run in a func() so we can cleanly defer closing the harness - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScript(t, h, convertMergeScriptTest(script, false)) - }() - } - }) -} - func TestThreeWayMergeWithSchemaChangeScriptsPrepared(t *testing.T) { h := newDoltEnginetestHarness(t) RunThreeWayMergeWithSchemaChangeScriptsPrepared(t, h) } -func RunThreeWayMergeWithSchemaChangeScriptsPrepared(t *testing.T, h DoltEnginetestHarness) { - skipOldFormat(t) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsCollations, "collation changes", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsConstraints, "constraint changes", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsSchemaConflicts, "schema conflicts", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsGeneratedColumns, "generated columns", false) - runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForJsonConflicts, "json merge", false) - - // Run non-symmetric schema merge tests in just one direction - t.Run("type changes", func(t *testing.T) { - for _, script := range SchemaChangeTestsTypeChanges { - // run in a func() so we can cleanly defer closing the harness - func() { - h := h.NewHarness(t) - defer h.Close() - enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, false)) - }() - } - }) -} // If CREATE DATABASE has an error within the DatabaseProvider, it should not // leave behind intermediate filesystem state. func TestCreateDatabaseErrorCleansUp(t *testing.T) { @@ -3872,65 +2048,4 @@ func TestStatsAutoRefreshConcurrency(t *testing.T) { wg.Wait() } -} - -// runMergeScriptTestsInBothDirections creates a new test run, named |name|, and runs the specified merge |tests| -// in both directions (right to left merge, and left to right merge). If -// |runAsPrepared| is true then the test scripts will be run using the prepared -// statement test code. -func runMergeScriptTestsInBothDirections(t *testing.T, tests []MergeScriptTest, name string, runAsPrepared bool) { - t.Run(name, func(t *testing.T) { - t.Run("right to left merges", func(t *testing.T) { - for _, script := range tests { - // run in a func() so we can cleanly defer closing the harness - func() { - h := newDoltHarness(t) - defer h.Close() - if runAsPrepared { - enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, false)) - } else { - enginetest.TestScript(t, h, convertMergeScriptTest(script, false)) - } - }() - } - }) - t.Run("left to right merges", func(t *testing.T) { - for _, script := range tests { - func() { - h := newDoltHarness(t) - defer h.Close() - if runAsPrepared { - enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, true)) - } else { - enginetest.TestScript(t, h, convertMergeScriptTest(script, true)) - } - }() - } - }) - }) -} - -var newFormatSkippedScripts = []string{ - // Different query plans - "Partial indexes are used and return the expected result", - "Multiple indexes on the same columns in a different order", -} - -func skipOldFormat(t *testing.T) { - if !types.IsFormat_DOLT(types.Format_Default) { - t.Skip() - } -} - -func skipPreparedTests(t *testing.T) { - if skipPrepared { - t.Skip("skip prepared") - } -} - -func newSessionBuilder(harness *DoltHarness) server.SessionBuilder { - return func(ctx context.Context, conn *mysql.Conn, host string) (sql.Session, error) { - newCtx := harness.NewSession() - return newCtx.Session, nil - } -} +} \ No newline at end of file diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go new file mode 100755 index 00000000000..f41d6442837 --- /dev/null +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go @@ -0,0 +1,1920 @@ +// Copyright 2024 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package enginetest + +import ( + "context" + "fmt" + "io" + "os" + "testing" + "time" + + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" + "github.com/dolthub/dolt/go/libraries/doltcore/schema" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" + "github.com/dolthub/dolt/go/store/datas" + "github.com/dolthub/dolt/go/store/types" + "github.com/dolthub/go-mysql-server/enginetest" + "github.com/dolthub/go-mysql-server/enginetest/queries" + "github.com/dolthub/go-mysql-server/enginetest/scriptgen/setup" + "github.com/dolthub/go-mysql-server/server" + "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/memo" + "github.com/dolthub/go-mysql-server/sql/plan" + "github.com/dolthub/go-mysql-server/sql/transform" + gmstypes "github.com/dolthub/go-mysql-server/sql/types" + "github.com/dolthub/vitess/go/mysql" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const skipPreparedFlag = "DOLT_SKIP_PREPARED_ENGINETESTS" + +var skipPrepared bool + +func init() { + sqle.MinRowsPerPartition = 8 + sqle.MaxRowsPerPartition = 1024 + + if v := os.Getenv(skipPreparedFlag); v != "" { + skipPrepared = true + } +} + +func RunSchemaOverridesTest(t *testing.T, harness DoltEnginetestHarness) { + tcc := &testCommitClock{} + cleanup := installTestCommitClock(tcc) + defer cleanup() + + for _, script := range SchemaOverrideTests { + sql.RunWithNowFunc(tcc.Now, func() error { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + + engine, err := harness.NewEngine(t) + if err != nil { + panic(err) + } + + enginetest.TestScriptWithEngine(t, engine, harness, script) + return nil + }) + } +} + +type testCommitClock struct { + unixNano int64 +} + +func (tcc *testCommitClock) Now() time.Time { + now := time.Unix(0, tcc.unixNano) + tcc.unixNano += int64(time.Hour) + return now +} + +func installTestCommitClock(tcc *testCommitClock) func() { + oldNowFunc := datas.CommitterDate + oldCommitLoc := datas.CommitLoc + datas.CommitterDate = tcc.Now + datas.CommitLoc = time.UTC + return func() { + datas.CommitterDate = oldNowFunc + datas.CommitLoc = oldCommitLoc + } +} + +func RunAutoIncrementTrackerLockModeTest(t *testing.T, harness DoltEnginetestHarness) { + for _, lockMode := range []int64{0, 1, 2} { + t.Run(fmt.Sprintf("lock mode %d", lockMode), func(t *testing.T) { + testAutoIncrementTrackerWithLockMode(t, harness, lockMode) + }) + } +} + +// testAutoIncrementTrackerWithLockMode tests that interleaved inserts don't cause deadlocks, regardless of the value of innodb_autoinc_lock_mode. +// In a real use case, these interleaved operations would be happening in different sessions on different threads. +// In order to make the test behave predictably, we manually interleave the two iterators. +func testAutoIncrementTrackerWithLockMode(t *testing.T, harness DoltEnginetestHarness, lockMode int64) { + err := sql.SystemVariables.AssignValues(map[string]interface{}{"innodb_autoinc_lock_mode": lockMode}) + require.NoError(t, err) + + setupScripts := []setup.SetupScript{[]string{ + "CREATE TABLE test1 (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,c0 int,index t1_c_index (c0));", + "CREATE TABLE test2 (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,c0 int,index t2_c_index (c0));", + "CREATE TABLE timestamps (pk int NOT NULL PRIMARY KEY AUTO_INCREMENT, t int);", + "CREATE TRIGGER t1 AFTER INSERT ON test1 FOR EACH ROW INSERT INTO timestamps VALUES (0, 1);", + "CREATE TRIGGER t2 AFTER INSERT ON test2 FOR EACH ROW INSERT INTO timestamps VALUES (0, 2);", + "CREATE VIEW bin AS SELECT 0 AS v UNION ALL SELECT 1;", + "CREATE VIEW sequence5bit AS SELECT b1.v + 2*b2.v + 4*b3.v + 8*b4.v + 16*b5.v AS v from bin b1, bin b2, bin b3, bin b4, bin b5;", + }} + + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData, setupScripts) + e := mustNewEngine(t, harness) + + defer e.Close() + ctx := enginetest.NewContext(harness) + + // Confirm that the system variable was correctly set. + _, iter, err := e.Query(ctx, "select @@innodb_autoinc_lock_mode") + require.NoError(t, err) + rows, err := sql.RowIterToRows(ctx, iter) + require.NoError(t, err) + assert.Equal(t, rows, []sql.Row{{lockMode}}) + + // Ordinarily QueryEngine.query manages transactions. + // Since we can't use that for this test, we manually start a new transaction. + ts := ctx.Session.(sql.TransactionSession) + tx, err := ts.StartTransaction(ctx, sql.ReadWrite) + require.NoError(t, err) + ctx.SetTransaction(tx) + + getTriggerIter := func(query string) sql.RowIter { + root, err := e.AnalyzeQuery(ctx, query) + require.NoError(t, err) + + var triggerNode *plan.TriggerExecutor + transform.Node(root, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { + if triggerNode != nil { + return n, transform.SameTree, nil + } + if t, ok := n.(*plan.TriggerExecutor); ok { + triggerNode = t + } + return n, transform.NewTree, nil + }) + iter, err := e.EngineAnalyzer().ExecBuilder.Build(ctx, triggerNode, nil) + require.NoError(t, err) + return iter + } + + iter1 := getTriggerIter("INSERT INTO test1 (c0) select v from sequence5bit;") + iter2 := getTriggerIter("INSERT INTO test2 (c0) select v from sequence5bit;") + + // Alternate the iterators until they're exhausted. + var err1 error + var err2 error + for err1 != io.EOF || err2 != io.EOF { + if err1 != io.EOF { + var row1 sql.Row + require.NoError(t, err1) + row1, err1 = iter1.Next(ctx) + _ = row1 + } + if err2 != io.EOF { + require.NoError(t, err2) + _, err2 = iter2.Next(ctx) + } + } + err = iter1.Close(ctx) + require.NoError(t, err) + err = iter2.Close(ctx) + require.NoError(t, err) + + dsess.DSessFromSess(ctx.Session).CommitTransaction(ctx, ctx.GetTransaction()) + + // Verify that the inserts are seen by the engine. + { + _, iter, err := e.Query(ctx, "select count(*) from timestamps") + require.NoError(t, err) + rows, err := sql.RowIterToRows(ctx, iter) + require.NoError(t, err) + assert.Equal(t, rows, []sql.Row{{int64(64)}}) + } + + // Verify that the insert operations are actually interleaved by inspecting the order that values were added to `timestamps` + { + _, iter, err := e.Query(ctx, "select (select min(pk) from timestamps where t = 1) < (select max(pk) from timestamps where t = 2)") + require.NoError(t, err) + rows, err := sql.RowIterToRows(ctx, iter) + require.NoError(t, err) + assert.Equal(t, rows, []sql.Row{{true}}) + } + + { + _, iter, err := e.Query(ctx, "select (select min(pk) from timestamps where t = 2) < (select max(pk) from timestamps where t = 1)") + require.NoError(t, err) + rows, err := sql.RowIterToRows(ctx, iter) + require.NoError(t, err) + assert.Equal(t, rows, []sql.Row{{true}}) + } +} + +func RunVersionedQueriesTest(t *testing.T, h DoltEnginetestHarness) { + h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) + + e, err := h.NewEngine(t) + require.NoError(t, err) + + for _, tt := range queries.VersionedQueries { + enginetest.TestQueryWithEngine(t, h, e, tt) + } + + for _, tt := range queries.VersionedScripts { + enginetest.TestScriptWithEngine(t, e, h, tt) + } +} + +func RunQueryTestPlans(t *testing.T, harness DoltEnginetestHarness) { + // Dolt supports partial keys, so the index matched is different for some plans + // TODO: Fix these differences by implementing partial key matching in the memory tables, or the engine itself + skipped := []string{ + "SELECT pk,pk1,pk2 FROM one_pk LEFT JOIN two_pk ON pk=pk1", + "SELECT pk,pk1,pk2 FROM one_pk JOIN two_pk ON pk=pk1", + "SELECT one_pk.c5,pk1,pk2 FROM one_pk JOIN two_pk ON pk=pk1 ORDER BY 1,2,3", + "SELECT opk.c5,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON opk.pk=tpk.pk1 ORDER BY 1,2,3", + "SELECT opk.c5,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON pk=pk1 ORDER BY 1,2,3", + "SELECT pk,pk1,pk2 FROM one_pk LEFT JOIN two_pk ON pk=pk1 ORDER BY 1,2,3", + "SELECT pk,pk1,pk2 FROM one_pk t1, two_pk t2 WHERE pk=1 AND pk2=1 AND pk1=1 ORDER BY 1,2", + } + // Parallelism introduces Exchange nodes into the query plans, so disable. + // TODO: exchange nodes should really only be part of the explain plan under certain debug settings + harness = harness.NewHarness(t).WithSkippedQueries(skipped).WithConfigureStats(true) + if !types.IsFormat_DOLT(types.Format_Default) { + // only new format supports reverse IndexTableAccess + reverseIndexSkip := []string{ + "SELECT * FROM one_pk ORDER BY pk", + "SELECT * FROM two_pk ORDER BY pk1, pk2", + "SELECT * FROM two_pk ORDER BY pk1", + "SELECT pk1 AS one, pk2 AS two FROM two_pk ORDER BY pk1, pk2", + "SELECT pk1 AS one, pk2 AS two FROM two_pk ORDER BY one, two", + "SELECT i FROM (SELECT i FROM mytable ORDER BY i DESC LIMIT 1) sq WHERE i = 3", + "SELECT i FROM (SELECT i FROM (SELECT i FROM mytable ORDER BY DES LIMIT 1) sql1)sql2 WHERE i = 3", + "SELECT s,i FROM mytable order by i DESC", + "SELECT s,i FROM mytable as a order by i DESC", + "SELECT pk1, pk2 FROM two_pk order by pk1 asc, pk2 asc", + "SELECT pk1, pk2 FROM two_pk order by pk1 desc, pk2 desc", + "SELECT i FROM (SELECT i FROM (SELECT i FROM mytable ORDER BY i DESC LIMIT 1) sq1) sq2 WHERE i = 3", + } + harness = harness.WithSkippedQueries(reverseIndexSkip) + } + + defer harness.Close() + enginetest.TestQueryPlans(t, harness, queries.PlanTests) +} + +func RunDoltDiffQueryPlansTest(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + harness.Setup(setup.SimpleSetup...) + e, err := harness.NewEngine(t) + require.NoError(t, err) + defer e.Close() + + for _, tt := range append(DoltDiffPlanTests, DoltCommitPlanTests...) { + enginetest.TestQueryPlanWithName(t, tt.Query, harness, e, tt.Query, tt.ExpectedPlan, sql.DescribeOptions{}) + } +} + +func RunBranchPlanTests(t *testing.T, harness DoltEnginetestHarness) { + for _, script := range BranchPlanTests { + t.Run(script.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + + e := mustNewEngine(t, harness) + defer e.Close() + + for _, statement := range script.SetUpScript { + ctx := enginetest.NewContext(harness).WithQuery(statement) + enginetest.RunQueryWithContext(t, e, harness, ctx, statement) + } + for _, tt := range script.Queries { + t.Run(tt.Query, func(t *testing.T) { + TestIndexedAccess(t, e, harness, tt.Query, tt.Index) + }) + } + }) + } +} + +func RunInfoSchemaTests(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() + enginetest.TestInfoSchema(t, h) + + for _, script := range DoltInfoSchemaScripts { + func() { + h = h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunInsertIntoErrorsTest(t *testing.T, h DoltEnginetestHarness) { + h = h.WithSkippedQueries([]string{ + "create table bad (vb varbinary(65535))", + "insert into bad values (repeat('0', 65536))", + }) + defer h.Close() + enginetest.TestInsertIntoErrors(t, h) +} + +func RunGeneratedColumnTests(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + enginetest.TestGeneratedColumns(t, + // virtual indexes are failing for certain lookups on this test + harness.WithSkippedQueries([]string{"create table t (pk int primary key, col1 int as (pk + 1));"})) + + for _, script := range GeneratedColumnMergeTestScripts { + func() { + h := harness.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunBranchDdlTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DdlBranchTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunBranchDdlTestPrepared(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DdlBranchTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunIndexPrefixTest(t *testing.T, harness *DoltHarness) { + defer harness.Close() + enginetest.TestIndexPrefix(t, harness) + for _, script := range DoltIndexPrefixScripts { + enginetest.TestScript(t, harness, script) + } +} + +func RunBigBlobsTest(t *testing.T, h *DoltHarness) { + defer h.Close() + h.Setup(setup.MydbData, setup.BlobData) + for _, tt := range BigBlobQueries { + enginetest.RunWriteQueryTest(t, h, tt) + } +} + +func RunDropEngineTest(t *testing.T, h DoltEnginetestHarness) { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, queries.ScriptTest{ + Name: "Drop database engine tests for Dolt only", + SetUpScript: []string{ + "CREATE DATABASE Test1db", + "CREATE DATABASE TEST2db", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "DROP DATABASE TeSt2DB", + Expected: []sql.Row{{gmstypes.OkResult{RowsAffected: 1}}}, + }, + { + Query: "USE test2db", + ExpectedErr: sql.ErrDatabaseNotFound, + }, + { + Query: "USE TEST1DB", + Expected: []sql.Row{}, + }, + { + Query: "DROP DATABASE IF EXISTS test1DB", + Expected: []sql.Row{{gmstypes.OkResult{RowsAffected: 1}}}, + }, + { + Query: "USE Test1db", + ExpectedErr: sql.ErrDatabaseNotFound, + }, + }, + }) + }() + + t.Skip("Dolt doesn't yet support dropping the primary database, which these tests do") + h = h.NewHarness(t) + defer h.Close() + enginetest.TestDropDatabase(t, h) +} + +func RunForeignKeyBranchesTest(t *testing.T, h DoltEnginetestHarness) { + setupPrefix := []string{ + "call dolt_branch('b1')", + "use mydb/b1", + } + assertionsPrefix := []queries.ScriptTestAssertion{ + { + Query: "use mydb/b1", + SkipResultsCheck: true, + }, + } + for _, script := range queries.ForeignKeyTests { + // New harness for every script because we create branches + h := h.NewHarness(t) + h.Setup(setup.MydbData, setup.Parent_childData) + modifiedScript := script + modifiedScript.SetUpScript = append(setupPrefix, modifiedScript.SetUpScript...) + modifiedScript.Assertions = append(assertionsPrefix, modifiedScript.Assertions...) + enginetest.TestScript(t, h, modifiedScript) + } + + for _, script := range ForeignKeyBranchTests { + // New harness for every script because we create branches + h := h.NewHarness(t) + h.Setup(setup.MydbData, setup.Parent_childData) + enginetest.TestScript(t, h, script) + } +} + +func RunForeignKeyBranchesPreparedTest(t *testing.T, h DoltEnginetestHarness) { + setupPrefix := []string{ + "call dolt_branch('b1')", + "use mydb/b1", + } + assertionsPrefix := []queries.ScriptTestAssertion{ + { + Query: "use mydb/b1", + SkipResultsCheck: true, + }, + } + for _, script := range queries.ForeignKeyTests { + // New harness for every script because we create branches + h := h.NewHarness(t) + h.Setup(setup.MydbData, setup.Parent_childData) + modifiedScript := script + modifiedScript.SetUpScript = append(setupPrefix, modifiedScript.SetUpScript...) + modifiedScript.Assertions = append(assertionsPrefix, modifiedScript.Assertions...) + enginetest.TestScriptPrepared(t, h, modifiedScript) + } + + for _, script := range ForeignKeyBranchTests { + // New harness for every script because we create branches + h := h.NewHarness(t) + h.Setup(setup.MydbData, setup.Parent_childData) + enginetest.TestScriptPrepared(t, h, script) + } +} + +func RunBranchViewsTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range ViewBranchTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunBranchViewsPreparedTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range ViewBranchTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunVersionedViewsTest(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() + h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) + + e, err := h.NewEngine(t) + require.NoError(t, err) + + for _, testCase := range queries.VersionedViewTests { + t.Run(testCase.Query, func(t *testing.T) { + ctx := enginetest.NewContext(h) + enginetest.TestQueryWithContext(t, ctx, e, h, testCase.Query, testCase.Expected, testCase.ExpectedColumns, nil) + }) + } +} + +func RunVariableTest(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() + enginetest.TestVariables(t, h) + for _, script := range DoltSystemVariables { + enginetest.TestScript(t, h, script) + } +} + +func RunStoredProceduresTest(t *testing.T, h DoltEnginetestHarness) { + tests := make([]queries.ScriptTest, 0, len(queries.ProcedureLogicTests)) + for _, test := range queries.ProcedureLogicTests { + // TODO: this passes locally but SOMETIMES fails tests on GitHub, no clue why + if test.Name != "ITERATE and LEAVE loops" { + tests = append(tests, test) + } + } + queries.ProcedureLogicTests = tests + + defer h.Close() + enginetest.TestStoredProcedures(t, h) +} + +func RunDoltStoredProceduresTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltProcedureTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltStoredProceduresPreparedTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltProcedureTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunCallAsOfTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltCallAsOf { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunLargeJsonObjectsTest(t *testing.T, harness DoltEnginetestHarness) { + SkipByDefaultInCI(t) + defer harness.Close() + for _, script := range LargeJsonObjectScriptTests { + enginetest.TestScript(t, harness, script) + } +} + +func RunTransactionTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range queries.TransactionTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } + for _, script := range DoltTransactionTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } + for _, script := range DoltStoredProcedureTransactionTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } + for _, script := range DoltConflictHandlingTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } + for _, script := range DoltConstraintViolationTransactionTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } +} + +func RunBranchTransactionTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range BranchIsolationTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } +} + +func RunMultiDbTransactionsTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range MultiDbTransactionTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + + for _, script := range MultiDbSavepointTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestTransactionScript(t, h, script) + }() + } +} + +func RunMultiDbTransactionsPreparedTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range MultiDbTransactionTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunDoltScriptsTest(t *testing.T, harness DoltEnginetestHarness) { + for _, script := range DoltScripts { + go func() { + harness := harness.NewHarness(t) + defer harness.Close() + enginetest.TestScript(t, harness, script) + }() + } +} + +func RunDoltTempTableScripts(t *testing.T, harness DoltEnginetestHarness) { + for _, script := range DoltTempTableScripts { + harness := harness.NewHarness(t) + enginetest.TestScript(t, harness, script) + harness.Close() + } +} + +func RunDoltRevisionDbScriptsTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltRevisionDbScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + + // Testing a commit-qualified database revision spec requires + // a little extra work to get the generated commit hash + h = h.NewHarness(t) + defer h.Close() + e, err := h.NewEngine(t) + require.NoError(t, err) + defer e.Close() + ctx := h.NewContext() + + setupScripts := []setup.SetupScript{ + {"create table t01 (pk int primary key, c1 int)"}, + {"call dolt_add('.');"}, + {"call dolt_commit('-am', 'creating table t01 on main');"}, + {"insert into t01 values (1, 1), (2, 2);"}, + {"call dolt_commit('-am', 'adding rows to table t01 on main');"}, + {"insert into t01 values (3, 3);"}, + {"call dolt_commit('-am', 'adding another row to table t01 on main');"}, + } + _, err = enginetest.RunSetupScripts(ctx, h.Engine(), setupScripts, true) + require.NoError(t, err) + + _, iter, err := h.Engine().Query(ctx, "select hashof('HEAD~2');") + require.NoError(t, err) + rows, err := sql.RowIterToRows(ctx, iter) + require.NoError(t, err) + assert.Equal(t, 1, len(rows)) + commithash := rows[0][0].(string) + + scriptTest := queries.ScriptTest{ + Name: "database revision specs: commit-qualified revision spec", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "show databases;", + Expected: []sql.Row{{"mydb"}, {"information_schema"}, {"mysql"}}, + }, + { + Query: "use mydb/" + commithash, + Expected: []sql.Row{}, + }, + { + Query: "select active_branch();", + Expected: []sql.Row{ + {nil}, + }, + }, + { + Query: "select database();", + Expected: []sql.Row{{"mydb/" + commithash}}, + }, + { + Query: "show databases;", + Expected: []sql.Row{{"mydb"}, {"mydb/" + commithash}, {"information_schema"}, {"mysql"}}, + }, + { + Query: "select * from t01", + Expected: []sql.Row{}, + }, + { + Query: "call dolt_reset();", + ExpectedErrStr: "unable to reset HEAD in read-only databases", + }, + { + Query: "call dolt_checkout('main');", + Expected: []sql.Row{{0, "Switched to branch 'main'"}}, + }, + { + Query: "select database();", + Expected: []sql.Row{{"mydb"}}, + }, + { + Query: "select active_branch();", + Expected: []sql.Row{{"main"}}, + }, + { + Query: "use mydb;", + Expected: []sql.Row{}, + }, + { + Query: "select database();", + Expected: []sql.Row{{"mydb"}}, + }, + { + Query: "show databases;", + Expected: []sql.Row{{"mydb"}, {"information_schema"}, {"mysql"}}, + }, + }, + } + + enginetest.TestScript(t, h, scriptTest) +} + +func RunDoltRevisionDbScriptsPreparedTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltRevisionDbScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunDoltDdlScripts(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + harness.Setup() + + for _, script := range ModifyAndChangeColumnScripts { + e, err := harness.NewEngine(t) + require.NoError(t, err) + enginetest.TestScriptWithEngine(t, e, harness, script) + } + + for _, script := range ModifyColumnTypeScripts { + e, err := harness.NewEngine(t) + require.NoError(t, err) + enginetest.TestScriptWithEngine(t, e, harness, script) + } + + for _, script := range DropColumnScripts { + e, err := harness.NewEngine(t) + require.NoError(t, err) + enginetest.TestScriptWithEngine(t, e, harness, script) + } + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("not fixing unique index on keyless tables for old format") + } + for _, script := range AddIndexScripts { + e, err := harness.NewEngine(t) + require.NoError(t, err) + enginetest.TestScriptWithEngine(t, e, harness, script) + } + + // TODO: these scripts should be general enough to go in GMS + for _, script := range AddDropPrimaryKeysScripts { + e, err := harness.NewEngine(t) + require.NoError(t, err) + enginetest.TestScriptWithEngine(t, e, harness, script) + } +} + +func RunShowCreateTableTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range ShowCreateTableScriptTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunShowCreateTablePreparedTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range ShowCreateTableScriptTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunDoltMergeTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range MergeScripts { + // harness can't reset effectively when there are new commits / branches created, so use a new harness for + // each script + func() { + h := h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltMergePreparedTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range MergeScripts { + // harness can't reset effectively when there are new commits / branches created, so use a new harness for + // each script + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunDoltRebaseTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltRebaseScriptTests { + func() { + h := h.NewHarness(t) + defer h.Close() + h.SkipSetupCommit() + enginetest.TestScript(t, h, script) + }() + } + + testMultiSessionScriptTests(t, DoltRebaseMultiSessionScriptTests) +} + +func RunDoltRebasePreparedTests(t *testing.T, h *DoltHarness) { + for _, script := range DoltRebaseScriptTests { + func() { + h := h.NewHarness(t) + defer h.Close() + h.SkipSetupCommit() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunDoltRevertTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range RevertScripts { + // harness can't reset effectively. Use a new harness for each script + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltRevertPreparedTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range RevertScripts { + // harness can't reset effectively. Use a new harness for each script + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltAutoIncrementTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltAutoIncrementTests { + // doing commits on different branches is antagonistic to engine reuse, use a new engine on each script + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltAutoIncrementPreparedTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltAutoIncrementTests { + // doing commits on different branches is antagonistic to engine reuse, use a new engine on each script + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltConflictsTableNameTableTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltConflictTableNameTableTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + + if types.IsFormat_DOLT(types.Format_Default) { + for _, script := range Dolt1ConflictTableNameTableTests { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + } +} + +func RunKelyessDoltMergeCVsAndConflictsTests(t *testing.T, h DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip() + } + for _, script := range KeylessMergeCVsAndConflictsScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltMergeArtifacts(t *testing.T, h DoltEnginetestHarness) { + for _, script := range MergeArtifactsScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + for _, script := range SchemaConflictScripts { + h := h.NewHarness(t) + enginetest.TestScript(t, h, script) + h.Close() + } +} + +func RunDoltResetTest(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltReset { + // dolt versioning conflicts with reset harness -- use new harness every time + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltCheckoutTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltCheckoutScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + + h = h.NewHarness(t) + defer h.Close() + engine, err := h.NewEngine(t) + require.NoError(t, err) + readOnlyEngine, err := h.NewReadOnlyEngine(engine.EngineAnalyzer().Catalog.DbProvider) + require.NoError(t, err) + + for _, script := range DoltCheckoutReadOnlyScripts { + enginetest.TestScriptWithEngine(t, readOnlyEngine, h, script) + } +} + +func RunDoltCheckoutPreparedTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltCheckoutScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } + + h = h.NewHarness(t) + defer h.Close() + engine, err := h.NewEngine(t) + require.NoError(t, err) + readOnlyEngine, err := h.NewReadOnlyEngine(engine.EngineAnalyzer().Catalog.DbProvider) + require.NoError(t, err) + + for _, script := range DoltCheckoutReadOnlyScripts { + enginetest.TestScriptWithEnginePrepared(t, readOnlyEngine, h, script) + } +} + +func RunDoltBranchTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltBranchScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltTagTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltTagTestScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltRemoteTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltRemoteTestScripts { + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunDoltUndropTests(t *testing.T, h DoltEnginetestHarness) { + h.UseLocalFileSystem() + defer h.Close() + for _, script := range DoltUndropTestScripts { + enginetest.TestScript(t, h, script) + } +} + +func RunHistorySystemTableTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range HistorySystemTableScriptTests { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + t.Run(test.Name, func(t *testing.T) { + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunHistorySystemTableTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range HistorySystemTableScriptTests { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + t.Run(test.Name, func(t *testing.T) { + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunUnscopedDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { + for _, test := range UnscopedDiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, test) + }) + } +} + +func RunUnscopedDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { + for _, test := range UnscopedDiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, test) + }) + } +} + +func RunColumnDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("correct behavior of dolt_column_diff only guaranteed on new format") + } + for _, test := range ColumnDiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + enginetest.TestScript(t, h.NewHarness(t), test) + }) + } +} + +func RunColumnDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("correct behavior of dolt_column_diff only guaranteed on new format") + } + for _, test := range ColumnDiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + enginetest.TestScriptPrepared(t, h.NewHarness(t), test) + }) + } +} + +func RunStatBranchTests(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + for _, test := range StatBranchTests { + t.Run(test.Name, func(t *testing.T) { + // reset engine so provider statistics are clean + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + harness = harness.WithConfigureStats(true) + e := mustNewEngine(t, harness) + defer e.Close() + enginetest.TestScriptWithEngine(t, e, harness, test) + }) + } +} + +func mustNewEngine(t *testing.T, h enginetest.Harness) enginetest.QueryEngine { + e, err := h.NewEngine(t) + if err != nil { + require.NoError(t, err) + } + return e +} + +func RunStatsFunctionsTest(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + for _, test := range StatProcTests { + t.Run(test.Name, func(t *testing.T) { + // reset engine so provider statistics are clean + harness = harness.NewHarness(t).WithConfigureStats(true) + harness.Setup(setup.MydbData) + harness.SkipSetupCommit() + e := mustNewEngine(t, harness) + defer e.Close() + enginetest.TestScriptWithEngine(t, e, harness, test) + }) + } +} + +func RunDiffTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DiffTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DiffTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunDiffStatTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DiffStatTableFunctionScriptTests { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + t.Run(test.Name, func(t *testing.T) { + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunDiffStatTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DiffStatTableFunctionScriptTests { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + t.Run(test.Name, func(t *testing.T) { + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunDiffSummaryTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DiffSummaryTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunDiffSummaryTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DiffSummaryTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunDoltPatchTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range PatchTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunDoltPatchTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range PatchTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunLogTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range LogTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + harness.SkipSetupCommit() + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunLogTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range LogTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + harness.SkipSetupCommit() + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunCommitDiffSystemTableTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range CommitDiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunCommitDiffSystemTableTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range CommitDiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunDoltDiffSystemTableTests(t *testing.T, h DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("only new format support system table indexing") + } + + for _, test := range DiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + h = h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScript(t, h, test) + }) + } + + if types.IsFormat_DOLT(types.Format_Default) { + for _, test := range Dolt1DiffSystemTableScripts { + func() { + h = h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScript(t, h, test) + }() + } + } +} + +func RunDoltDiffSystemTableTestsPrepared(t *testing.T, h DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("only new format support system table indexing") + } + + for _, test := range DiffSystemTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + h = h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, h, test) + }) + } + + if types.IsFormat_DOLT(types.Format_Default) { + for _, test := range Dolt1DiffSystemTableScripts { + func() { + h = h.NewHarness(t) + defer h.Close() + h.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, h, test) + }() + } + } +} + +func RunSchemaDiffTableFunctionTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range SchemaDiffTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunSchemaDiffTableFunctionTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range SchemaDiffTableFunctionScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunDoltDatabaseCollationDiffsTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range DoltDatabaseCollationScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunQueryDiffTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range QueryDiffTableScriptTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunSystemTableIndexesTests(t *testing.T, harness DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("only new format support system table indexing") + } + + for _, stt := range SystemTableIndexTests { + harness = harness.NewHarness(t).WithParallelism(2) + defer harness.Close() + harness.SkipSetupCommit() + e := mustNewEngine(t, harness) + defer e.Close() + e.EngineAnalyzer().Coster = memo.NewMergeBiasedCoster() + + ctx := enginetest.NewContext(harness) + for _, q := range stt.setup { + enginetest.RunQueryWithContext(t, e, harness, ctx, q) + } + + for i, c := range []string{"inner", "lookup", "hash", "merge"} { + e.EngineAnalyzer().Coster = biasedCosters[i] + for _, tt := range stt.queries { + if tt.query == "select count(*) from dolt_blame_xy" && c == "inner" { + // todo we either need join hints to work inside the blame view + // and force the window relation to be primary, or we need the + // blame view's timestamp columns to be specific enough to not + // overlap during testing. + t.Skip("the blame table is unstable as secondary table in join with exchange node") + } + t.Run(fmt.Sprintf("%s(%s): %s", stt.name, c, tt.query), func(t *testing.T) { + if tt.skip { + t.Skip() + } + + ctx = ctx.WithQuery(tt.query) + if tt.exp != nil { + enginetest.TestQueryWithContext(t, ctx, e, harness, tt.query, tt.exp, nil, nil) + } + }) + } + } + } +} + +var biasedCosters = []memo.Coster{ + memo.NewInnerBiasedCoster(), + memo.NewLookupBiasedCoster(), + memo.NewHashBiasedCoster(), + memo.NewMergeBiasedCoster(), +} + +func RunSystemTableIndexesTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip("only new format support system table indexing") + } + + for _, stt := range SystemTableIndexTests { + harness = harness.NewHarness(t).WithParallelism(2) + defer harness.Close() + harness.SkipSetupCommit() + e := mustNewEngine(t, harness) + defer e.Close() + + ctx := enginetest.NewContext(harness) + for _, q := range stt.setup { + enginetest.RunQueryWithContext(t, e, harness, ctx, q) + } + + for _, tt := range stt.queries { + t.Run(fmt.Sprintf("%s: %s", stt.name, tt.query), func(t *testing.T) { + if tt.skip { + t.Skip() + } + + ctx = ctx.WithQuery(tt.query) + if tt.exp != nil { + enginetest.TestPreparedQueryWithContext(t, ctx, e, harness, tt.query, tt.exp, nil, nil, false) + } + }) + } + } +} + +func RunSystemTableFunctionIndexesTests(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range SystemTableFunctionIndexTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + enginetest.TestScript(t, harness, test) + }) + } +} + +func RunSystemTableFunctionIndexesTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, test := range SystemTableFunctionIndexTests { + t.Run(test.Name, func(t *testing.T) { + harness = harness.NewHarness(t) + harness.Setup(setup.MydbData) + enginetest.TestScriptPrepared(t, harness, test) + }) + } +} + +func RunAddAutoIncrementColumnTests(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() + for _, script := range queries.AlterTableAddAutoIncrementScripts { + enginetest.TestScript(t, h, script) + } +} + +func RunDoltCherryPickTests(t *testing.T, harness DoltEnginetestHarness) { + for _, script := range DoltCherryPickTests { + harness = harness.NewHarness(t) + enginetest.TestScript(t, harness, script) + harness.Close() + } +} + +func RunDoltCherryPickTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + for _, script := range DoltCherryPickTests { + harness = harness.NewHarness(t) + enginetest.TestScriptPrepared(t, harness, script) + harness.Close() + } +} + +func RunDoltCommitTests(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + for _, script := range DoltCommitTests { + enginetest.TestScript(t, harness, script) + } +} + +func RunDoltCommitTestsPrepared(t *testing.T, harness DoltEnginetestHarness) { + defer harness.Close() + for _, script := range DoltCommitTests { + enginetest.TestScriptPrepared(t, harness, script) + } +} + +func RunStatsHistogramTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltHistogramTests { + func() { + h = h.NewHarness(t).WithConfigureStats(true) + defer h.Close() + enginetest.TestScript(t, h, script) + }() + } +} + +func RunStatsIOTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range append(DoltStatsIOTests, DoltHistogramTests...) { + func() { + h = h.NewHarness(t).WithConfigureStats(true) + defer h.Close() + e := mustNewEngine(t, h) + if enginetest.IsServerEngine(e) { + return + } + defer e.Close() + TestProviderReloadScriptWithEngine(t, e, h, script) + }() + } +} + +// these are sensitive to cardinality estimates, +// particularly the join-filter tests that trade-off +// smallest table first vs smallest join first +func RunJoinStatsTests(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() + h = h.WithConfigureStats(true) + enginetest.TestJoinStats(t, h) +} + +func RunPreparedStatisticsTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltHistogramTests { + func() { + h := h.NewHarness(t).WithConfigureStats(true) + defer h.Close() + enginetest.TestScriptPrepared(t, h, script) + }() + } +} + +func RunVersionedQueriesPreparedTests(t *testing.T, h DoltEnginetestHarness) { + defer h.Close() + h.Setup(setup.MydbData, []setup.SetupScript{VersionedQuerySetup, VersionedQueryViews}) + + e, err := h.NewEngine(t) + require.NoError(t, err) + + for _, tt := range queries.VersionedQueries { + enginetest.TestPreparedQueryWithEngine(t, h, e, tt) + } + + for _, tt := range queries.VersionedScripts { + enginetest.TestScriptWithEnginePrepared(t, e, h, tt) + } +} + +func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { + t.Run("adding and dropping primary keys does not result in duplicate NOT NULL constraints", func(t *testing.T) { + harness = harness.NewHarness(t) + defer harness.Close() + addPkScript := queries.ScriptTest{ + Name: "add primary keys", + SetUpScript: []string{ + "create table test (id int not null, c1 int);", + "create index c1_idx on test(c1)", + "insert into test values (1,1),(2,2)", + "ALTER TABLE test ADD PRIMARY KEY(id)", + "ALTER TABLE test DROP PRIMARY KEY", + "ALTER TABLE test ADD PRIMARY KEY(id)", + "ALTER TABLE test DROP PRIMARY KEY", + "ALTER TABLE test ADD PRIMARY KEY(id)", + "ALTER TABLE test DROP PRIMARY KEY", + "ALTER TABLE test ADD PRIMARY KEY(id)", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "show create table test", + Expected: []sql.Row{ + {"test", "CREATE TABLE `test` (\n" + + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `c1_idx` (`c1`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + }, + }, + }, + } + + enginetest.TestScript(t, harness, addPkScript) + + // make sure there is only one NOT NULL constraint after all those mutations + ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) + ws, err := harness.Session().WorkingSet(ctx, "mydb") + require.NoError(t, err) + + table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) + require.NoError(t, err) + require.True(t, ok) + + sch, err := table.GetSchema(ctx) + for _, col := range sch.GetAllCols().GetColumns() { + count := 0 + for _, cc := range col.Constraints { + if cc.GetConstraintType() == schema.NotNullConstraintType { + count++ + } + } + require.Less(t, count, 2) + } + }) + + t.Run("Add primary key to table with index", func(t *testing.T) { + harness := harness.NewHarness(t) + defer harness.Close() + script := queries.ScriptTest{ + Name: "add primary keys to table with index", + SetUpScript: []string{ + "create table test (id int not null, c1 int);", + "create index c1_idx on test(c1)", + "insert into test values (1,1),(2,2)", + "ALTER TABLE test ADD constraint test_check CHECK (c1 > 0)", + "ALTER TABLE test ADD PRIMARY KEY(id)", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "show create table test", + Expected: []sql.Row{ + {"test", "CREATE TABLE `test` (\n" + + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `c1_idx` (`c1`),\n" + + " CONSTRAINT `test_check` CHECK ((`c1` > 0))\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + }, + }, + { + Query: "select * from test order by id", + Expected: []sql.Row{ + {1, 1}, + {2, 2}, + }, + }, + }, + } + enginetest.TestScript(t, harness, script) + + ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) + ws, err := harness.Session().WorkingSet(ctx, "mydb") + require.NoError(t, err) + + table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) + require.NoError(t, err) + require.True(t, ok) + + // Assert the new index map is not empty + newRows, err := table.GetIndexRowData(ctx, "c1_idx") + require.NoError(t, err) + empty, err := newRows.Empty() + require.NoError(t, err) + assert.False(t, empty) + count, err := newRows.Count() + require.NoError(t, err) + assert.Equal(t, count, uint64(2)) + }) + + t.Run("Add primary key when one more cells contain NULL", func(t *testing.T) { + harness := harness.NewHarness(t) + defer harness.Close() + script := queries.ScriptTest{ + Name: "Add primary key when one more cells contain NULL", + SetUpScript: []string{ + "create table test (id int not null, c1 int);", + "create index c1_idx on test(c1)", + "insert into test values (1,1),(2,2)", + "ALTER TABLE test ADD PRIMARY KEY (c1)", + "ALTER TABLE test ADD COLUMN (c2 INT NULL)", + "ALTER TABLE test DROP PRIMARY KEY", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "ALTER TABLE test ADD PRIMARY KEY (id, c1, c2)", + ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull, + }, + }, + } + enginetest.TestScript(t, harness, script) + }) + + t.Run("Drop primary key from table with index", func(t *testing.T) { + harness := harness.NewHarness(t) + defer harness.Close() + script := queries.ScriptTest{ + Name: "Drop primary key from table with index", + SetUpScript: []string{ + "create table test (id int not null primary key, c1 int);", + "create index c1_idx on test(c1)", + "insert into test values (1,1),(2,2)", + "ALTER TABLE test DROP PRIMARY KEY", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "show create table test", + Expected: []sql.Row{ + {"test", "CREATE TABLE `test` (\n" + + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " KEY `c1_idx` (`c1`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + }, + }, + { + Query: "select * from test order by id", + Expected: []sql.Row{ + {1, 1}, + {2, 2}, + }, + }, + }, + } + + enginetest.TestScript(t, harness, script) + + ctx := sql.NewContext(context.Background(), sql.WithSession(harness.Session())) + ws, err := harness.Session().WorkingSet(ctx, "mydb") + require.NoError(t, err) + + table, ok, err := ws.WorkingRoot().GetTable(ctx, doltdb.TableName{Name: "test"}) + require.NoError(t, err) + require.True(t, ok) + + // Assert the index map is not empty + newIdx, err := table.GetIndexRowData(ctx, "c1_idx") + assert.NoError(t, err) + empty, err := newIdx.Empty() + require.NoError(t, err) + assert.False(t, empty) + count, err := newIdx.Count() + require.NoError(t, err) + assert.Equal(t, count, uint64(2)) + }) +} + +func RunDoltVerifyConstraintsTests(t *testing.T, harness DoltEnginetestHarness) { + for _, script := range DoltVerifyConstraintsTestScripts { + func() { + harness = harness.NewHarness(t) + defer harness.Close() + enginetest.TestScript(t, harness, script) + }() + } +} + +func RunDoltStorageFormatTests(t *testing.T, h DoltEnginetestHarness) { + var expectedFormatString string + if types.IsFormat_DOLT(types.Format_Default) { + expectedFormatString = "NEW ( __DOLT__ )" + } else { + expectedFormatString = fmt.Sprintf("OLD ( %s )", types.Format_Default.VersionString()) + } + script := queries.ScriptTest{ + Name: "dolt storage format function works", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "select dolt_storage_format()", + Expected: []sql.Row{{expectedFormatString}}, + }, + }, + } + defer h.Close() + enginetest.TestScript(t, h, script) +} + +func RunThreeWayMergeWithSchemaChangeScripts(t *testing.T, h DoltEnginetestHarness) { + skipOldFormat(t) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsCollations, "collation changes", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsConstraints, "constraint changes", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsSchemaConflicts, "schema conflicts", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsGeneratedColumns, "generated columns", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForJsonConflicts, "json merge", false) + + // Run non-symmetric schema merge tests in just one direction + t.Run("type changes", func(t *testing.T) { + for _, script := range SchemaChangeTestsTypeChanges { + // run in a func() so we can cleanly defer closing the harness + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScript(t, h, convertMergeScriptTest(script, false)) + }() + } + }) +} + +func RunThreeWayMergeWithSchemaChangeScriptsPrepared(t *testing.T, h DoltEnginetestHarness) { + skipOldFormat(t) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsBasicCases, "basic cases", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForDataConflicts, "data conflicts", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsCollations, "collation changes", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsConstraints, "constraint changes", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsSchemaConflicts, "schema conflicts", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsGeneratedColumns, "generated columns", false) + runMergeScriptTestsInBothDirections(t, SchemaChangeTestsForJsonConflicts, "json merge", false) + + // Run non-symmetric schema merge tests in just one direction + t.Run("type changes", func(t *testing.T) { + for _, script := range SchemaChangeTestsTypeChanges { + // run in a func() so we can cleanly defer closing the harness + func() { + h := h.NewHarness(t) + defer h.Close() + enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, false)) + }() + } + }) +} + +// runMergeScriptTestsInBothDirections creates a new test run, named |name|, and runs the specified merge |tests| +// in both directions (right to left merge, and left to right merge). If +// |runAsPrepared| is true then the test scripts will be run using the prepared +// statement test code. +func runMergeScriptTestsInBothDirections(t *testing.T, tests []MergeScriptTest, name string, runAsPrepared bool) { + t.Run(name, func(t *testing.T) { + t.Run("right to left merges", func(t *testing.T) { + for _, script := range tests { + // run in a func() so we can cleanly defer closing the harness + func() { + h := newDoltHarness(t) + defer h.Close() + if runAsPrepared { + enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, false)) + } else { + enginetest.TestScript(t, h, convertMergeScriptTest(script, false)) + } + }() + } + }) + t.Run("left to right merges", func(t *testing.T) { + for _, script := range tests { + func() { + h := newDoltHarness(t) + defer h.Close() + if runAsPrepared { + enginetest.TestScriptPrepared(t, h, convertMergeScriptTest(script, true)) + } else { + enginetest.TestScript(t, h, convertMergeScriptTest(script, true)) + } + }() + } + }) + }) +} + +func SkipByDefaultInCI(t *testing.T) { + if os.Getenv("CI") != "" && os.Getenv("DOLT_TEST_RUN_NON_RACE_TESTS") == "" { + t.Skip() + } +} + +var newFormatSkippedScripts = []string{ + // Different query plans + "Partial indexes are used and return the expected result", + "Multiple indexes on the same columns in a different order", +} + +func skipOldFormat(t *testing.T) { + if !types.IsFormat_DOLT(types.Format_Default) { + t.Skip() + } +} + +func skipPreparedTests(t *testing.T) { + if skipPrepared { + t.Skip("skip prepared") + } +} + +func newSessionBuilder(harness *DoltHarness) server.SessionBuilder { + return func(ctx context.Context, conn *mysql.Conn, host string) (sql.Session, error) { + newCtx := harness.NewSession() + return newCtx.Session, nil + } +} diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_server_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_server_test.go index ca95d7a0cef..d3b9d216661 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_server_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_server_test.go @@ -15,465 +15,17 @@ package enginetest import ( - "context" - gosql "database/sql" - "math/rand" "runtime" "strings" "testing" - "time" - "github.com/dolthub/go-mysql-server/enginetest/queries" "github.com/dolthub/go-mysql-server/sql" - "github.com/gocraft/dbr/v2" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver" - "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" - "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/servercfg" - "github.com/dolthub/dolt/go/libraries/utils/svcs" ) -// DoltBranchMultiSessionScriptTests contain tests that need to be run in a multi-session server environment -// in order to fully test branch deletion and renaming logic. -var DoltBranchMultiSessionScriptTests = []queries.ScriptTest{ - { - Name: "Test multi-session behavior for deleting branches", - SetUpScript: []string{ - "call dolt_branch('branch1');", - "call dolt_branch('branch2');", - "call dolt_branch('branch3');", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ CALL DOLT_CHECKOUT('branch1');", - Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, - }, - { - Query: "/* client a */ select active_branch();", - Expected: []sql.Row{{"branch1"}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch1');", - ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", - }, - { - Query: "/* client a */ CALL DOLT_CHECKOUT('branch2');", - Expected: []sql.Row{{0, "Switched to branch 'branch2'"}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch1');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch2');", - ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-df', 'branch2');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch3');", - Expected: []sql.Row{{0}}, - }, - }, - }, - { - Name: "Test multi-session behavior for renaming branches", - SetUpScript: []string{ - "call dolt_branch('branch1');", - "call dolt_branch('branch2');", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ CALL DOLT_CHECKOUT('branch1');", - Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, - }, - { - Query: "/* client a */ select active_branch();", - Expected: []sql.Row{{"branch1"}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-m', 'branch1', 'movedBranch1');", - ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-mf', 'branch1', 'movedBranch1');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-m', 'branch2', 'movedBranch2');", - Expected: []sql.Row{{0}}, - }, - }, - }, - { - Name: "Test branch deletion when clients are using a branch-qualified database", - SetUpScript: []string{ - "call dolt_branch('branch1');", - "call dolt_branch('branch2');", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ use dolt/branch1;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ SELECT DATABASE(), ACTIVE_BRANCH();", - Expected: []sql.Row{{"dolt/branch1", "branch1"}}, - }, - { - Query: "/* client b */ use dolt/branch2;", - Expected: []sql.Row{}, - }, - { - Query: "/* client b */ SELECT DATABASE(), ACTIVE_BRANCH();", - Expected: []sql.Row{{"dolt/branch2", "branch2"}}, - }, - { - Query: "/* client a */ SHOW DATABASES;", - Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, - }, - { - Query: "/* client a */ CALL DOLT_BRANCH('-d', 'branch2');", - ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", - }, - { - Query: "/* client a */ CALL DOLT_BRANCH('-df', 'branch2');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client a */ SHOW DATABASES;", - Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, - }, - { - Query: "/* client a */ SELECT DATABASE(), ACTIVE_BRANCH();", - Expected: []sql.Row{{"dolt/branch1", "branch1"}}, - }, - { - // Call a stored procedure since this searches across all databases and will - // fail if a branch-qualified database exists for a missing branch. - Query: "/* client a */ CALL DOLT_BRANCH('branch3');", - Expected: []sql.Row{{0}}, - }, - }, - }, - { - Name: "Test branch renaming when clients are using a branch-qualified database", - SetUpScript: []string{ - "call dolt_branch('branch1');", - "call dolt_branch('branch2');", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ use dolt/branch1;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ SELECT DATABASE(), ACTIVE_BRANCH();", - Expected: []sql.Row{{"dolt/branch1", "branch1"}}, - }, - { - Query: "/* client b */ use dolt/branch2;", - Expected: []sql.Row{}, - }, - { - Query: "/* client b */ SELECT DATABASE(), ACTIVE_BRANCH();", - Expected: []sql.Row{{"dolt/branch2", "branch2"}}, - }, - { - Query: "/* client a */ SHOW DATABASES;", - Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, - }, - { - Query: "/* client a */ CALL DOLT_BRANCH('-m', 'branch2', 'newName');", - ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", - }, - { - Query: "/* client a */ CALL DOLT_BRANCH('-mf', 'branch2', 'newName');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client a */ SHOW DATABASES;", - Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, - }, - { - // Call a stored procedure since this searches across all databases and will - // fail if a branch-qualified database exists for a missing branch. - Query: "/* client a */ CALL DOLT_BRANCH('branch3');", - Expected: []sql.Row{{0}}, - }, - }, - }, - { - Name: "Test multi-session behavior for force deleting active branch with autocommit on", - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ SET @@autocommit=1;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ CALL DOLT_CHECKOUT('-b', 'branch1');", - Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, - }, - { - Query: "/* client a */ select active_branch();", - Expected: []sql.Row{{"branch1"}}, - }, - { - Query: "/* client b */ select active_branch();", - Expected: []sql.Row{{"main"}}, - }, - { - Query: "/* client b */ select name from dolt_branches order by name;", - Expected: []sql.Row{{"branch1"}, {"main"}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-D', 'branch1');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client b */ select name from dolt_branches;", - Expected: []sql.Row{{"main"}}, - }, - { - Query: "/* client a */ select name from dolt_branches;", - ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", - }, - { - Query: "/* client a */ CALL DOLT_CHECKOUT('main');", - ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", - }, - { - Query: "/* client a */ USE dolt/main;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ select active_branch();", - Expected: []sql.Row{{"main"}}, - }, - }, - }, - { - Name: "Test multi-session behavior for force deleting active branch with autocommit off", - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ SET @@autocommit=0;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ CALL DOLT_CHECKOUT('-b', 'branch1');", - Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, - }, - { - Query: "/* client a */ select active_branch();", - Expected: []sql.Row{{"branch1"}}, - }, - { - Query: "/* client b */ select active_branch();", - Expected: []sql.Row{{"main"}}, - }, - { - Query: "/* client b */ select name from dolt_branches order by name;", - Expected: []sql.Row{{"branch1"}, {"main"}}, - }, - { - Query: "/* client b */ CALL DOLT_BRANCH('-D', 'branch1');", - Expected: []sql.Row{{0}}, - }, - { - Query: "/* client b */ select name from dolt_branches;", - Expected: []sql.Row{{"main"}}, - }, - { - Query: "/* client a */ select name from dolt_branches;", - ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", - }, - { - // TODO: this could be handled better, not the best experience. Maybe kill the session? - Query: "/* client a */ CALL DOLT_CHECKOUT('main');", - ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", - }, - { - Query: "/* client a */ USE dolt/main;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ select active_branch();", - Expected: []sql.Row{{"main"}}, - }, - }, - }, -} - -// DropDatabaseMultiSessionScriptTests test that when dropping a database, other sessions are properly updated -// and don't get left with old state that causes incorrect results. -// Note: this test needs to be run against a real Dolt sql-server, and not just with our transaction test scripts, -// because the transaction tests currently have a different behavior for session management and don't emulate prod. -var DropDatabaseMultiSessionScriptTests = []queries.ScriptTest{ - { - Name: "Test multi-session behavior for dropping databases", - SetUpScript: []string{ - "create database db01;", - "create table db01.t01 (pk int primary key);", - "insert into db01.t01 values (101), (202), (303);", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ use db01;", - Expected: []sql.Row{}, - }, - { - Query: "/* client b */ use db01;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ show tables;", - Expected: []sql.Row{{"t01"}}, - }, - { - Query: "/* client b */ show tables;", - Expected: []sql.Row{{"t01"}}, - }, - { - Query: "/* client a */ drop database db01;", - Expected: []sql.Row{}, - }, - { - // TODO: This test runner doesn't currently support asserting against null values - Query: "/* client a */ select database() is NULL;", - Expected: []sql.Row{{1}}, - }, - { - Query: "/* client a */ show databases like 'db01';", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ create database db01;", - Expected: []sql.Row{}, - }, - { - Query: "/* client b */ select database();", - Expected: []sql.Row{{"db01"}}, - }, - { - Query: "/* client b */ show tables;", - Expected: []sql.Row{}, - }, - }, - }, - { - Name: "Test multi-session behavior for dropping databases with a revision db", - SetUpScript: []string{ - "create database db01;", - "use db01;", - "create table db01.t01 (pk int primary key);", - "insert into db01.t01 values (101), (202), (303);", - "call dolt_commit('-Am', 'commit on main');", - "call dolt_checkout('-b', 'branch1');", - "insert into db01.t01 values (1001), (2002), (3003);", - "call dolt_commit('-Am', 'commit on branch1');", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "/* client a */ use db01;", - Expected: []sql.Row{}, - }, - { - Query: "/* client b */ use `db01/branch1`;", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ show tables;", - Expected: []sql.Row{{"t01"}}, - }, - { - Query: "/* client b */ show tables;", - Expected: []sql.Row{{"t01"}}, - }, - { - Query: "/* client a */ drop database db01;", - Expected: []sql.Row{}, - }, - { - // TODO: This test runner doesn't currently support asserting against null values - Query: "/* client a */ select database() is NULL;", - Expected: []sql.Row{{1}}, - }, - { - Query: "/* client a */ show databases like 'db01';", - Expected: []sql.Row{}, - }, - { - Query: "/* client a */ create database db01;", - Expected: []sql.Row{}, - }, - { - Query: "/* client b */ select database();", - Expected: []sql.Row{{"db01/branch1"}}, - }, - { - Query: "/* client b */ show tables;", - ExpectedErrStr: "Error 1049 (HY000): database not found: db01/branch1", - }, - }, - }, -} - -var PersistVariableTests = []queries.ScriptTest{ - { - Name: "set persisted variables with on and off", - SetUpScript: []string{ - "set @@persist.dolt_skip_replication_errors = on;", - "set @@persist.dolt_read_replica_force_pull = off;", - }, - }, - { - Name: "retrieve persisted variables", - Assertions: []queries.ScriptTestAssertion{ - { - Query: "select @@dolt_skip_replication_errors", - Expected: []sql.Row{ - {1}, - }, - }, - { - Query: "select @@dolt_read_replica_force_pull", - Expected: []sql.Row{ - {0}, - }, - }, - }, - }, - { - Name: "set persisted variables with 1 and 0", - SetUpScript: []string{ - "set @@persist.dolt_skip_replication_errors = 0;", - "set @@persist.dolt_read_replica_force_pull = 1;", - }, - }, - { - Name: "retrieve persisted variables", - Assertions: []queries.ScriptTestAssertion{ - { - Query: "select @@dolt_skip_replication_errors", - Expected: []sql.Row{ - {0}, - }, - }, - { - Query: "select @@dolt_read_replica_force_pull", - Expected: []sql.Row{ - {1}, - }, - }, - }, - }, -} - // TestDoltMultiSessionBehavior runs tests that exercise multi-session logic on a running SQL server. Statements // are sent through the server, from out of process, instead of directly to the in-process engine API. func TestDoltMultiSessionBehavior(t *testing.T) { @@ -491,215 +43,6 @@ func TestPersistVariable(t *testing.T) { testSerialSessionScriptTests(t, PersistVariableTests) } -func testMultiSessionScriptTests(t *testing.T, tests []queries.ScriptTest) { - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - dEnv, sc, serverConfig := startServer(t, true, "", "") - err := sc.WaitForStart() - require.NoError(t, err) - defer dEnv.DoltDB.Close() - - conn1, sess1 := newConnection(t, serverConfig) - conn2, sess2 := newConnection(t, serverConfig) - - t.Run(test.Name, func(t *testing.T) { - for _, setupStatement := range test.SetUpScript { - _, err := sess1.Exec(setupStatement) - require.NoError(t, err) - } - - for _, assertion := range test.Assertions { - t.Run(assertion.Query, func(t *testing.T) { - var activeSession *dbr.Session - if strings.Contains(strings.ToLower(assertion.Query), "/* client a */") { - activeSession = sess1 - } else if strings.Contains(strings.ToLower(assertion.Query), "/* client b */") { - activeSession = sess2 - } else { - require.Fail(t, "unsupported client specification: "+assertion.Query) - } - - rows, err := activeSession.Query(assertion.Query) - - if len(assertion.ExpectedErrStr) > 0 { - require.EqualError(t, err, assertion.ExpectedErrStr) - } else if assertion.ExpectedErr != nil { - require.True(t, assertion.ExpectedErr.Is(err), "expected error %v, got %v", assertion.ExpectedErr, err) - } else if assertion.Expected != nil { - require.NoError(t, err) - assertResultsEqual(t, assertion.Expected, rows) - } else if assertion.SkipResultsCheck { - // no-op - } else { - t.Fatalf("unsupported ScriptTestAssertion property: %v", assertion) - } - if rows != nil { - require.NoError(t, rows.Close()) - } - }) - } - }) - - require.NoError(t, conn1.Close()) - require.NoError(t, conn2.Close()) - - sc.Stop() - err = sc.WaitForStop() - require.NoError(t, err) - }) - } -} - -// testSerialSessionScriptTests creates an environment, then for each script starts a server and runs assertions, -// stopping the server in between scripts. Unlike other script test executors, scripts may influence later scripts in -// the block. -func testSerialSessionScriptTests(t *testing.T, tests []queries.ScriptTest) { - dEnv := dtestutils.CreateTestEnv() - serverConfig := sqlserver.DefaultCommandLineServerConfig() - rand.Seed(time.Now().UnixNano()) - port := 15403 + rand.Intn(25) - serverConfig = serverConfig.WithPort(port) - defer dEnv.DoltDB.Close() - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - sc, serverConfig := startServerOnEnv(t, serverConfig, dEnv) - err := sc.WaitForStart() - require.NoError(t, err) - - conn1, sess1 := newConnection(t, serverConfig) - - t.Run(test.Name, func(t *testing.T) { - for _, setupStatement := range test.SetUpScript { - _, err := sess1.Exec(setupStatement) - require.NoError(t, err) - } - - for _, assertion := range test.Assertions { - t.Run(assertion.Query, func(t *testing.T) { - activeSession := sess1 - rows, err := activeSession.Query(assertion.Query) - - if len(assertion.ExpectedErrStr) > 0 { - require.EqualError(t, err, assertion.ExpectedErrStr) - } else if assertion.ExpectedErr != nil { - require.True(t, assertion.ExpectedErr.Is(err), "expected error %v, got %v", assertion.ExpectedErr, err) - } else if assertion.Expected != nil { - require.NoError(t, err) - assertResultsEqual(t, assertion.Expected, rows) - } else { - require.Fail(t, "unsupported ScriptTestAssertion property: %v", assertion) - } - if rows != nil { - require.NoError(t, rows.Close()) - } - }) - } - }) - - require.NoError(t, conn1.Close()) - - sc.Stop() - err = sc.WaitForStop() - require.NoError(t, err) - }) - } -} - -func makeDestinationSlice(t *testing.T, columnTypes []*gosql.ColumnType) []interface{} { - dest := make([]any, len(columnTypes)) - for i, columnType := range columnTypes { - switch strings.ToLower(columnType.DatabaseTypeName()) { - case "int", "tinyint", "bigint": - var integer int - dest[i] = &integer - case "text": - var s string - dest[i] = &s - default: - require.Fail(t, "unsupported type: "+columnType.DatabaseTypeName()) - } - } - - return dest -} - -func assertResultsEqual(t *testing.T, expected []sql.Row, rows *gosql.Rows) { - columnTypes, err := rows.ColumnTypes() - assert.NoError(t, err) - dest := makeDestinationSlice(t, columnTypes) - - for _, expectedRow := range expected { - ok := rows.Next() - if !ok { - assert.Fail(t, "Fewer results than expected") - } - err := rows.Scan(dest...) - assert.NoError(t, err) - assert.Equal(t, len(expectedRow), len(dest), - "Different number of columns returned than expected") - - for j, expectedValue := range expectedRow { - switch strings.ToUpper(columnTypes[j].DatabaseTypeName()) { - case "TEXT": - actualValue, ok := dest[j].(*string) - assert.True(t, ok) - assert.Equal(t, expectedValue, *actualValue) - case "INT", "TINYINT", "BIGINT": - actualValue, ok := dest[j].(*int) - assert.True(t, ok) - assert.Equal(t, expectedValue, *actualValue) - default: - assert.Fail(t, "Unsupported datatype: %s", columnTypes[j].DatabaseTypeName()) - } - } - } - - if rows.Next() { - assert.Fail(t, "More results than expected") - } -} - -// startServer will start sql-server with given host, unix socket file path and whether to use specific port, which is defined randomly. -func startServer(t *testing.T, withPort bool, host string, unixSocketPath string) (*env.DoltEnv, *svcs.Controller, servercfg.ServerConfig) { - dEnv := dtestutils.CreateTestEnv() - serverConfig := sqlserver.DefaultCommandLineServerConfig() - if withPort { - rand.Seed(time.Now().UnixNano()) - port := 15403 + rand.Intn(25) - serverConfig = serverConfig.WithPort(port) - } - if host != "" { - serverConfig = serverConfig.WithHost(host) - } - if unixSocketPath != "" { - serverConfig = serverConfig.WithSocket(unixSocketPath) - } - - onEnv, config := startServerOnEnv(t, serverConfig, dEnv) - return dEnv, onEnv, config -} - -func startServerOnEnv(t *testing.T, serverConfig servercfg.ServerConfig, dEnv *env.DoltEnv) (*svcs.Controller, servercfg.ServerConfig) { - sc := svcs.NewController() - go func() { - _, _ = sqlserver.Serve(context.Background(), "0.0.0", serverConfig, sc, dEnv) - }() - err := sc.WaitForStart() - require.NoError(t, err) - - return sc, serverConfig -} - -// newConnection takes sqlserver.serverConfig and opens a connection, and will return that connection with a new session -func newConnection(t *testing.T, serverConfig servercfg.ServerConfig) (*dbr.Connection, *dbr.Session) { - const dbName = "dolt" - conn, err := dbr.Open("mysql", servercfg.ConnectionString(serverConfig, dbName), nil) - require.NoError(t, err) - sess := conn.NewSession(nil) - return conn, sess -} - func TestDoltServerRunningUnixSocket(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("unix sockets not supported on Windows") diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go new file mode 100755 index 00000000000..a15d9896a8b --- /dev/null +++ b/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go @@ -0,0 +1,683 @@ +// Copyright 2024 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package enginetest + +import ( + "context" + gosql "database/sql" + "math/rand" + "strings" + "testing" + "time" + + "github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver" + "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" + "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/servercfg" + "github.com/dolthub/dolt/go/libraries/utils/svcs" + "github.com/dolthub/go-mysql-server/enginetest/queries" + "github.com/dolthub/go-mysql-server/sql" + "github.com/gocraft/dbr/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// DoltBranchMultiSessionScriptTests contain tests that need to be run in a multi-session server environment +// in order to fully test branch deletion and renaming logic. +var DoltBranchMultiSessionScriptTests = []queries.ScriptTest{ + { + Name: "Test multi-session behavior for deleting branches", + SetUpScript: []string{ + "call dolt_branch('branch1');", + "call dolt_branch('branch2');", + "call dolt_branch('branch3');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ CALL DOLT_CHECKOUT('branch1');", + Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, + }, + { + Query: "/* client a */ select active_branch();", + Expected: []sql.Row{{"branch1"}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch1');", + ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", + }, + { + Query: "/* client a */ CALL DOLT_CHECKOUT('branch2');", + Expected: []sql.Row{{0, "Switched to branch 'branch2'"}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch1');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch2');", + ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-df', 'branch2');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-d', 'branch3');", + Expected: []sql.Row{{0}}, + }, + }, + }, + { + Name: "Test multi-session behavior for renaming branches", + SetUpScript: []string{ + "call dolt_branch('branch1');", + "call dolt_branch('branch2');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ CALL DOLT_CHECKOUT('branch1');", + Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, + }, + { + Query: "/* client a */ select active_branch();", + Expected: []sql.Row{{"branch1"}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-m', 'branch1', 'movedBranch1');", + ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-mf', 'branch1', 'movedBranch1');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-m', 'branch2', 'movedBranch2');", + Expected: []sql.Row{{0}}, + }, + }, + }, + { + Name: "Test branch deletion when clients are using a branch-qualified database", + SetUpScript: []string{ + "call dolt_branch('branch1');", + "call dolt_branch('branch2');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ use dolt/branch1;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ SELECT DATABASE(), ACTIVE_BRANCH();", + Expected: []sql.Row{{"dolt/branch1", "branch1"}}, + }, + { + Query: "/* client b */ use dolt/branch2;", + Expected: []sql.Row{}, + }, + { + Query: "/* client b */ SELECT DATABASE(), ACTIVE_BRANCH();", + Expected: []sql.Row{{"dolt/branch2", "branch2"}}, + }, + { + Query: "/* client a */ SHOW DATABASES;", + Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, + }, + { + Query: "/* client a */ CALL DOLT_BRANCH('-d', 'branch2');", + ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", + }, + { + Query: "/* client a */ CALL DOLT_BRANCH('-df', 'branch2');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client a */ SHOW DATABASES;", + Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, + }, + { + Query: "/* client a */ SELECT DATABASE(), ACTIVE_BRANCH();", + Expected: []sql.Row{{"dolt/branch1", "branch1"}}, + }, + { + // Call a stored procedure since this searches across all databases and will + // fail if a branch-qualified database exists for a missing branch. + Query: "/* client a */ CALL DOLT_BRANCH('branch3');", + Expected: []sql.Row{{0}}, + }, + }, + }, + { + Name: "Test branch renaming when clients are using a branch-qualified database", + SetUpScript: []string{ + "call dolt_branch('branch1');", + "call dolt_branch('branch2');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ use dolt/branch1;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ SELECT DATABASE(), ACTIVE_BRANCH();", + Expected: []sql.Row{{"dolt/branch1", "branch1"}}, + }, + { + Query: "/* client b */ use dolt/branch2;", + Expected: []sql.Row{}, + }, + { + Query: "/* client b */ SELECT DATABASE(), ACTIVE_BRANCH();", + Expected: []sql.Row{{"dolt/branch2", "branch2"}}, + }, + { + Query: "/* client a */ SHOW DATABASES;", + Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, + }, + { + Query: "/* client a */ CALL DOLT_BRANCH('-m', 'branch2', 'newName');", + ExpectedErrStr: "Error 1105 (HY000): unsafe to delete or rename branches in use in other sessions; use --force to force the change", + }, + { + Query: "/* client a */ CALL DOLT_BRANCH('-mf', 'branch2', 'newName');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client a */ SHOW DATABASES;", + Expected: []sql.Row{{"dolt"}, {"dolt/branch1"}, {"information_schema"}, {"mysql"}}, + }, + { + // Call a stored procedure since this searches across all databases and will + // fail if a branch-qualified database exists for a missing branch. + Query: "/* client a */ CALL DOLT_BRANCH('branch3');", + Expected: []sql.Row{{0}}, + }, + }, + }, + { + Name: "Test multi-session behavior for force deleting active branch with autocommit on", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ SET @@autocommit=1;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ CALL DOLT_CHECKOUT('-b', 'branch1');", + Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, + }, + { + Query: "/* client a */ select active_branch();", + Expected: []sql.Row{{"branch1"}}, + }, + { + Query: "/* client b */ select active_branch();", + Expected: []sql.Row{{"main"}}, + }, + { + Query: "/* client b */ select name from dolt_branches order by name;", + Expected: []sql.Row{{"branch1"}, {"main"}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-D', 'branch1');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client b */ select name from dolt_branches;", + Expected: []sql.Row{{"main"}}, + }, + { + Query: "/* client a */ select name from dolt_branches;", + ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", + }, + { + Query: "/* client a */ CALL DOLT_CHECKOUT('main');", + ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", + }, + { + Query: "/* client a */ USE dolt/main;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ select active_branch();", + Expected: []sql.Row{{"main"}}, + }, + }, + }, + { + Name: "Test multi-session behavior for force deleting active branch with autocommit off", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ SET @@autocommit=0;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ CALL DOLT_CHECKOUT('-b', 'branch1');", + Expected: []sql.Row{{0, "Switched to branch 'branch1'"}}, + }, + { + Query: "/* client a */ select active_branch();", + Expected: []sql.Row{{"branch1"}}, + }, + { + Query: "/* client b */ select active_branch();", + Expected: []sql.Row{{"main"}}, + }, + { + Query: "/* client b */ select name from dolt_branches order by name;", + Expected: []sql.Row{{"branch1"}, {"main"}}, + }, + { + Query: "/* client b */ CALL DOLT_BRANCH('-D', 'branch1');", + Expected: []sql.Row{{0}}, + }, + { + Query: "/* client b */ select name from dolt_branches;", + Expected: []sql.Row{{"main"}}, + }, + { + Query: "/* client a */ select name from dolt_branches;", + ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", + }, + { + // TODO: this could be handled better, not the best experience. Maybe kill the session? + Query: "/* client a */ CALL DOLT_CHECKOUT('main');", + ExpectedErrStr: "Error 1049 (HY000): database not found: dolt/branch1", + }, + { + Query: "/* client a */ USE dolt/main;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ select active_branch();", + Expected: []sql.Row{{"main"}}, + }, + }, + }, +} + +// DropDatabaseMultiSessionScriptTests test that when dropping a database, other sessions are properly updated +// and don't get left with old state that causes incorrect results. +// Note: this test needs to be run against a real Dolt sql-server, and not just with our transaction test scripts, +// because the transaction tests currently have a different behavior for session management and don't emulate prod. +var DropDatabaseMultiSessionScriptTests = []queries.ScriptTest{ + { + Name: "Test multi-session behavior for dropping databases", + SetUpScript: []string{ + "create database db01;", + "create table db01.t01 (pk int primary key);", + "insert into db01.t01 values (101), (202), (303);", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ use db01;", + Expected: []sql.Row{}, + }, + { + Query: "/* client b */ use db01;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ show tables;", + Expected: []sql.Row{{"t01"}}, + }, + { + Query: "/* client b */ show tables;", + Expected: []sql.Row{{"t01"}}, + }, + { + Query: "/* client a */ drop database db01;", + Expected: []sql.Row{}, + }, + { + // TODO: This test runner doesn't currently support asserting against null values + Query: "/* client a */ select database() is NULL;", + Expected: []sql.Row{{1}}, + }, + { + Query: "/* client a */ show databases like 'db01';", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ create database db01;", + Expected: []sql.Row{}, + }, + { + Query: "/* client b */ select database();", + Expected: []sql.Row{{"db01"}}, + }, + { + Query: "/* client b */ show tables;", + Expected: []sql.Row{}, + }, + }, + }, + { + Name: "Test multi-session behavior for dropping databases with a revision db", + SetUpScript: []string{ + "create database db01;", + "use db01;", + "create table db01.t01 (pk int primary key);", + "insert into db01.t01 values (101), (202), (303);", + "call dolt_commit('-Am', 'commit on main');", + "call dolt_checkout('-b', 'branch1');", + "insert into db01.t01 values (1001), (2002), (3003);", + "call dolt_commit('-Am', 'commit on branch1');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "/* client a */ use db01;", + Expected: []sql.Row{}, + }, + { + Query: "/* client b */ use `db01/branch1`;", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ show tables;", + Expected: []sql.Row{{"t01"}}, + }, + { + Query: "/* client b */ show tables;", + Expected: []sql.Row{{"t01"}}, + }, + { + Query: "/* client a */ drop database db01;", + Expected: []sql.Row{}, + }, + { + // TODO: This test runner doesn't currently support asserting against null values + Query: "/* client a */ select database() is NULL;", + Expected: []sql.Row{{1}}, + }, + { + Query: "/* client a */ show databases like 'db01';", + Expected: []sql.Row{}, + }, + { + Query: "/* client a */ create database db01;", + Expected: []sql.Row{}, + }, + { + Query: "/* client b */ select database();", + Expected: []sql.Row{{"db01/branch1"}}, + }, + { + Query: "/* client b */ show tables;", + ExpectedErrStr: "Error 1049 (HY000): database not found: db01/branch1", + }, + }, + }, +} + +var PersistVariableTests = []queries.ScriptTest{ + { + Name: "set persisted variables with on and off", + SetUpScript: []string{ + "set @@persist.dolt_skip_replication_errors = on;", + "set @@persist.dolt_read_replica_force_pull = off;", + }, + }, + { + Name: "retrieve persisted variables", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "select @@dolt_skip_replication_errors", + Expected: []sql.Row{ + {1}, + }, + }, + { + Query: "select @@dolt_read_replica_force_pull", + Expected: []sql.Row{ + {0}, + }, + }, + }, + }, + { + Name: "set persisted variables with 1 and 0", + SetUpScript: []string{ + "set @@persist.dolt_skip_replication_errors = 0;", + "set @@persist.dolt_read_replica_force_pull = 1;", + }, + }, + { + Name: "retrieve persisted variables", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "select @@dolt_skip_replication_errors", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "select @@dolt_read_replica_force_pull", + Expected: []sql.Row{ + {1}, + }, + }, + }, + }, +} + +// testSerialSessionScriptTests creates an environment, then for each script starts a server and runs assertions, +// stopping the server in between scripts. Unlike other script test executors, scripts may influence later scripts in +// the block. +func testSerialSessionScriptTests(t *testing.T, tests []queries.ScriptTest) { + dEnv := dtestutils.CreateTestEnv() + serverConfig := sqlserver.DefaultCommandLineServerConfig() + rand.Seed(time.Now().UnixNano()) + port := 15403 + rand.Intn(25) + serverConfig = serverConfig.WithPort(port) + defer dEnv.DoltDB.Close() + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + sc, serverConfig := startServerOnEnv(t, serverConfig, dEnv) + err := sc.WaitForStart() + require.NoError(t, err) + + conn1, sess1 := newConnection(t, serverConfig) + + t.Run(test.Name, func(t *testing.T) { + for _, setupStatement := range test.SetUpScript { + _, err := sess1.Exec(setupStatement) + require.NoError(t, err) + } + + for _, assertion := range test.Assertions { + t.Run(assertion.Query, func(t *testing.T) { + activeSession := sess1 + rows, err := activeSession.Query(assertion.Query) + + if len(assertion.ExpectedErrStr) > 0 { + require.EqualError(t, err, assertion.ExpectedErrStr) + } else if assertion.ExpectedErr != nil { + require.True(t, assertion.ExpectedErr.Is(err), "expected error %v, got %v", assertion.ExpectedErr, err) + } else if assertion.Expected != nil { + require.NoError(t, err) + assertResultsEqual(t, assertion.Expected, rows) + } else { + require.Fail(t, "unsupported ScriptTestAssertion property: %v", assertion) + } + if rows != nil { + require.NoError(t, rows.Close()) + } + }) + } + }) + + require.NoError(t, conn1.Close()) + + sc.Stop() + err = sc.WaitForStop() + require.NoError(t, err) + }) + } +} + +func makeDestinationSlice(t *testing.T, columnTypes []*gosql.ColumnType) []interface{} { + dest := make([]any, len(columnTypes)) + for i, columnType := range columnTypes { + switch strings.ToLower(columnType.DatabaseTypeName()) { + case "int", "tinyint", "bigint": + var integer int + dest[i] = &integer + case "text": + var s string + dest[i] = &s + default: + require.Fail(t, "unsupported type: "+columnType.DatabaseTypeName()) + } + } + + return dest +} + +func startServerOnEnv(t *testing.T, serverConfig servercfg.ServerConfig, dEnv *env.DoltEnv) (*svcs.Controller, servercfg.ServerConfig) { + sc := svcs.NewController() + go func() { + _, _ = sqlserver.Serve(context.Background(), "0.0.0", serverConfig, sc, dEnv) + }() + err := sc.WaitForStart() + require.NoError(t, err) + + return sc, serverConfig +} + +// newConnection takes sqlserver.serverConfig and opens a connection, and will return that connection with a new session +func newConnection(t *testing.T, serverConfig servercfg.ServerConfig) (*dbr.Connection, *dbr.Session) { + const dbName = "dolt" + conn, err := dbr.Open("mysql", servercfg.ConnectionString(serverConfig, dbName), nil) + require.NoError(t, err) + sess := conn.NewSession(nil) + return conn, sess +} + +// startServer will start sql-server with given host, unix socket file path and whether to use specific port, which is defined randomly. +func startServer(t *testing.T, withPort bool, host string, unixSocketPath string) (*env.DoltEnv, *svcs.Controller, servercfg.ServerConfig) { + dEnv := dtestutils.CreateTestEnv() + serverConfig := sqlserver.DefaultCommandLineServerConfig() + if withPort { + rand.Seed(time.Now().UnixNano()) + port := 15403 + rand.Intn(25) + serverConfig = serverConfig.WithPort(port) + } + if host != "" { + serverConfig = serverConfig.WithHost(host) + } + if unixSocketPath != "" { + serverConfig = serverConfig.WithSocket(unixSocketPath) + } + + onEnv, config := startServerOnEnv(t, serverConfig, dEnv) + return dEnv, onEnv, config +} + +func assertResultsEqual(t *testing.T, expected []sql.Row, rows *gosql.Rows) { + columnTypes, err := rows.ColumnTypes() + assert.NoError(t, err) + dest := makeDestinationSlice(t, columnTypes) + + for _, expectedRow := range expected { + ok := rows.Next() + if !ok { + assert.Fail(t, "Fewer results than expected") + } + err := rows.Scan(dest...) + assert.NoError(t, err) + assert.Equal(t, len(expectedRow), len(dest), + "Different number of columns returned than expected") + + for j, expectedValue := range expectedRow { + switch strings.ToUpper(columnTypes[j].DatabaseTypeName()) { + case "TEXT": + actualValue, ok := dest[j].(*string) + assert.True(t, ok) + assert.Equal(t, expectedValue, *actualValue) + case "INT", "TINYINT", "BIGINT": + actualValue, ok := dest[j].(*int) + assert.True(t, ok) + assert.Equal(t, expectedValue, *actualValue) + default: + assert.Fail(t, "Unsupported datatype: %s", columnTypes[j].DatabaseTypeName()) + } + } + } + + if rows.Next() { + assert.Fail(t, "More results than expected") + } +} + +func testMultiSessionScriptTests(t *testing.T, tests []queries.ScriptTest) { + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + dEnv, sc, serverConfig := startServer(t, true, "", "") + err := sc.WaitForStart() + require.NoError(t, err) + defer dEnv.DoltDB.Close() + + conn1, sess1 := newConnection(t, serverConfig) + conn2, sess2 := newConnection(t, serverConfig) + + t.Run(test.Name, func(t *testing.T) { + for _, setupStatement := range test.SetUpScript { + _, err := sess1.Exec(setupStatement) + require.NoError(t, err) + } + + for _, assertion := range test.Assertions { + t.Run(assertion.Query, func(t *testing.T) { + var activeSession *dbr.Session + if strings.Contains(strings.ToLower(assertion.Query), "/* client a */") { + activeSession = sess1 + } else if strings.Contains(strings.ToLower(assertion.Query), "/* client b */") { + activeSession = sess2 + } else { + require.Fail(t, "unsupported client specification: "+assertion.Query) + } + + rows, err := activeSession.Query(assertion.Query) + + if len(assertion.ExpectedErrStr) > 0 { + require.EqualError(t, err, assertion.ExpectedErrStr) + } else if assertion.ExpectedErr != nil { + require.True(t, assertion.ExpectedErr.Is(err), "expected error %v, got %v", assertion.ExpectedErr, err) + } else if assertion.Expected != nil { + require.NoError(t, err) + assertResultsEqual(t, assertion.Expected, rows) + } else if assertion.SkipResultsCheck { + // no-op + } else { + t.Fatalf("unsupported ScriptTestAssertion property: %v", assertion) + } + if rows != nil { + require.NoError(t, rows.Close()) + } + }) + } + }) + + require.NoError(t, conn1.Close()) + require.NoError(t, conn2.Close()) + + sc.Stop() + err = sc.WaitForStop() + require.NoError(t, err) + }) + } +} + From c791d70c1af60bba6c677ee23f961a8856f41f5a Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 21 Jun 2024 11:05:10 -0700 Subject: [PATCH 21/23] Couple more method moves --- .../sqle/enginetest/dolt_engine_test.go | 16 +++------ .../sqle/enginetest/dolt_engine_tests.go | 33 +++++++++++++++++-- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 442db42e290..976eb18b095 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -1515,21 +1515,13 @@ func TestLogTableFunctionPrepared(t *testing.T) { } func TestDoltReflog(t *testing.T) { - for _, script := range DoltReflogTestScripts { - h := newDoltHarnessForLocalFilesystem(t) - h.SkipSetupCommit() - enginetest.TestScript(t, h, script) - h.Close() - } + h := newDoltEnginetestHarness(t) + RunDoltReflogTests(t, h) } func TestDoltReflogPrepared(t *testing.T) { - for _, script := range DoltReflogTestScripts { - h := newDoltHarnessForLocalFilesystem(t) - h.SkipSetupCommit() - enginetest.TestScriptPrepared(t, h, script) - h.Close() - } + h := newDoltEnginetestHarness(t) + RunDoltReflogTestsPrepared(t, h) } func TestCommitDiffSystemTable(t *testing.T) { diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go index f41d6442837..9829512999e 100755 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go @@ -359,7 +359,7 @@ func RunBranchDdlTestPrepared(t *testing.T, h DoltEnginetestHarness) { } } -func RunIndexPrefixTest(t *testing.T, harness *DoltHarness) { +func RunIndexPrefixTest(t *testing.T, harness DoltEnginetestHarness) { defer harness.Close() enginetest.TestIndexPrefix(t, harness) for _, script := range DoltIndexPrefixScripts { @@ -367,7 +367,7 @@ func RunIndexPrefixTest(t *testing.T, harness *DoltHarness) { } } -func RunBigBlobsTest(t *testing.T, h *DoltHarness) { +func RunBigBlobsTest(t *testing.T, h DoltEnginetestHarness) { defer h.Close() h.Setup(setup.MydbData, setup.BlobData) for _, tt := range BigBlobQueries { @@ -869,7 +869,7 @@ func RunDoltRebaseTests(t *testing.T, h DoltEnginetestHarness) { testMultiSessionScriptTests(t, DoltRebaseMultiSessionScriptTests) } -func RunDoltRebasePreparedTests(t *testing.T, h *DoltHarness) { +func RunDoltRebasePreparedTests(t *testing.T, h DoltEnginetestHarness) { for _, script := range DoltRebaseScriptTests { func() { h := h.NewHarness(t) @@ -1918,3 +1918,30 @@ func newSessionBuilder(harness *DoltHarness) server.SessionBuilder { return newCtx.Session, nil } } + +func RunDoltReflogTests(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltReflogTestScripts { + func() { + h = h.NewHarness(t) + defer h.Close() + h.UseLocalFileSystem() + h.SkipSetupCommit() + enginetest.TestScript(t, h, script) + h.Close() + }() + } +} + +func RunDoltReflogTestsPrepared(t *testing.T, h DoltEnginetestHarness) { + for _, script := range DoltReflogTestScripts { + func() { + h = h.NewHarness(t) + defer h.Close() + h.UseLocalFileSystem() + h.SkipSetupCommit() + enginetest.TestScriptPrepared(t, h, script) + h.Close() + }() + } +} + From bfae6a5bad6d18d240f94af45da0eba9e89f49a9 Mon Sep 17 00:00:00 2001 From: zachmu Date: Fri, 21 Jun 2024 18:16:33 +0000 Subject: [PATCH 22/23] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- .../sqle/enginetest/dolt_engine_test.go | 2 +- .../sqle/enginetest/dolt_engine_tests.go | 44 +++++++++---------- .../doltcore/sqle/enginetest/dolt_harness.go | 12 ++--- .../sqle/enginetest/dolt_server_tests.go | 12 ++--- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 84b9cf9e293..45cdc1eae15 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2046,4 +2046,4 @@ func TestStatsAutoRefreshConcurrency(t *testing.T) { wg.Wait() } -} \ No newline at end of file +} diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go index 9829512999e..eb0b30e1af2 100755 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go @@ -22,12 +22,6 @@ import ( "testing" "time" - "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" - "github.com/dolthub/dolt/go/libraries/doltcore/schema" - "github.com/dolthub/dolt/go/libraries/doltcore/sqle" - "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" - "github.com/dolthub/dolt/go/store/datas" - "github.com/dolthub/dolt/go/store/types" "github.com/dolthub/go-mysql-server/enginetest" "github.com/dolthub/go-mysql-server/enginetest/queries" "github.com/dolthub/go-mysql-server/enginetest/scriptgen/setup" @@ -40,6 +34,13 @@ import ( "github.com/dolthub/vitess/go/mysql" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" + "github.com/dolthub/dolt/go/libraries/doltcore/schema" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" + "github.com/dolthub/dolt/go/store/datas" + "github.com/dolthub/dolt/go/store/types" ) const skipPreparedFlag = "DOLT_SKIP_PREPARED_ENGINETESTS" @@ -1611,11 +1612,11 @@ func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { Query: "show create table test", Expected: []sql.Row{ {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `c1_idx` (`c1`)\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `c1_idx` (`c1`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, }, }, }, @@ -1661,12 +1662,12 @@ func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { Query: "show create table test", Expected: []sql.Row{ {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " PRIMARY KEY (`id`),\n" + - " KEY `c1_idx` (`c1`),\n" + - " CONSTRAINT `test_check` CHECK ((`c1` > 0))\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `c1_idx` (`c1`),\n" + + " CONSTRAINT `test_check` CHECK ((`c1` > 0))\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, }, }, { @@ -1738,10 +1739,10 @@ func RunAddDropPrimaryKeysTests(t *testing.T, harness DoltEnginetestHarness) { Query: "show create table test", Expected: []sql.Row{ {"test", "CREATE TABLE `test` (\n" + - " `id` int NOT NULL,\n" + - " `c1` int,\n" + - " KEY `c1_idx` (`c1`)\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, + " `id` int NOT NULL,\n" + + " `c1` int,\n" + + " KEY `c1_idx` (`c1`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, }, }, { @@ -1944,4 +1945,3 @@ func RunDoltReflogTestsPrepared(t *testing.T, h DoltEnginetestHarness) { }() } } - diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 3251254d180..09ec1a106c7 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -89,28 +89,28 @@ type DoltEnginetestHarness interface { enginetest.KeylessTableHarness enginetest.ReadOnlyDatabaseHarness enginetest.ValidatingHarness - + // NewHarness returns a new uninitialized harness of the same type NewHarness(t *testing.T) DoltEnginetestHarness - + // WithSkippedQueries returns a copy of the harness with the given queries skipped WithSkippedQueries(skipped []string) DoltEnginetestHarness - + // WithParallelism returns a copy of the harness with parallelism set to the given number of threads WithParallelism(parallelism int) DoltEnginetestHarness - + // WithConfigureStats returns a copy of the harness with the given configureStats value WithConfigureStats(configureStats bool) DoltEnginetestHarness // SkipSetupCommit configures to harness to skip the commit after setup scripts are run SkipSetupCommit() - + // UseLocalFileSystem configures the harness to use the local filesystem for all storage, instead of in-memory versions UseLocalFileSystem() // Close closes the harness, freeing up any resources it may have allocated Close() - + Engine() *gms.Engine Session() *dsess.DoltSession diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go index a15d9896a8b..fffa257cdf2 100755 --- a/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_server_tests.go @@ -22,16 +22,17 @@ import ( "testing" "time" - "github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver" - "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" - "github.com/dolthub/dolt/go/libraries/doltcore/env" - "github.com/dolthub/dolt/go/libraries/doltcore/servercfg" - "github.com/dolthub/dolt/go/libraries/utils/svcs" "github.com/dolthub/go-mysql-server/enginetest/queries" "github.com/dolthub/go-mysql-server/sql" "github.com/gocraft/dbr/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/dolthub/dolt/go/cmd/dolt/commands/sqlserver" + "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" + "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/servercfg" + "github.com/dolthub/dolt/go/libraries/utils/svcs" ) // DoltBranchMultiSessionScriptTests contain tests that need to be run in a multi-session server environment @@ -680,4 +681,3 @@ func testMultiSessionScriptTests(t *testing.T, tests []queries.ScriptTest) { }) } } - From b68ac3d0d433ea1462648499df1e76d3182b014b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 21 Jun 2024 13:36:22 -0700 Subject: [PATCH 23/23] Fixed double close error --- go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go index 9829512999e..4e10c1e0a48 100755 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_tests.go @@ -1927,7 +1927,6 @@ func RunDoltReflogTests(t *testing.T, h DoltEnginetestHarness) { h.UseLocalFileSystem() h.SkipSetupCommit() enginetest.TestScript(t, h, script) - h.Close() }() } } @@ -1940,7 +1939,6 @@ func RunDoltReflogTestsPrepared(t *testing.T, h DoltEnginetestHarness) { h.UseLocalFileSystem() h.SkipSetupCommit() enginetest.TestScriptPrepared(t, h, script) - h.Close() }() } }