diff --git a/.gitignore b/.gitignore index 881e89890cc..1676eb498d0 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,4 @@ report # plan test output /go/vt/vtgate/planbuilder/testdata/plan_test* +/go/vt/vtgate/planbuilder/testdata/expected diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index 8d339eb52ee..381983cb0ee 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -28,6 +28,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/suite" + "github.com/nsf/jsondiff" "github.com/stretchr/testify/require" @@ -47,23 +49,40 @@ import ( "vitess.io/vitess/go/vt/vtgate/vindexes" ) -func makeTestOutput(t *testing.T) string { - testOutputTempDir := utils.MakeTestOutput(t, "testdata", "plan_test") +var expectedDir = "testdata/expected" + +func getTestExpectationDir() string { + return filepath.Clean(expectedDir) +} + +type planTestSuite struct { + suite.Suite + outputDir string +} - return testOutputTempDir +func (s *planTestSuite) SetupSuite() { + dir := getTestExpectationDir() + err := os.RemoveAll(dir) + require.NoError(s.T(), err) + err = os.Mkdir(dir, 0755) + require.NoError(s.T(), err) + s.outputDir = dir } -func TestPlan(t *testing.T) { - defer utils.EnsureNoLeaks(t) +func TestPlanTestSuite(t *testing.T) { + suite.Run(t, new(planTestSuite)) +} + +func (s *planTestSuite) TestPlan() { + defer utils.EnsureNoLeaks(s.T()) vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), TabletType_: topodatapb.TabletType_PRIMARY, SysVarEnabled: true, TestBuilder: TestBuilder, Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - addPKs(t, vschemaWrapper.V, "user", []string{"user", "music"}) + s.addPKs(vschemaWrapper.V, "user", []string{"user", "music"}) // You will notice that some tests expect user.Id instead of user.id. // This is because we now pre-create vindex columns in the symbol @@ -71,55 +90,53 @@ func TestPlan(t *testing.T) { // the column is named as Id. This is to make sure that // column names are case-preserved, but treated as // case-insensitive even if they come from the vschema. - testFile(t, "aggr_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "dml_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "from_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "filter_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "postprocess_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "select_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "symtab_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "unsupported_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "unknown_schema_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "vindex_func_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "wireup_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "memory_sort_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "use_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "set_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "union_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "large_union_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "transaction_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "lock_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "large_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "ddl_cases_no_default_keyspace.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "flush_cases_no_default_keyspace.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "show_cases_no_default_keyspace.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "stream_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "info_schema80_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "reference_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "vexplain_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "misc_cases.json", testOutputTempDir, vschemaWrapper, false) - testFile(t, "cte_cases.json", testOutputTempDir, vschemaWrapper, false) + s.testFile("aggr_cases.json", vschemaWrapper, false) + s.testFile("dml_cases.json", vschemaWrapper, false) + s.testFile("from_cases.json", vschemaWrapper, false) + s.testFile("filter_cases.json", vschemaWrapper, false) + s.testFile("postprocess_cases.json", vschemaWrapper, false) + s.testFile("select_cases.json", vschemaWrapper, false) + s.testFile("symtab_cases.json", vschemaWrapper, false) + s.testFile("unsupported_cases.json", vschemaWrapper, false) + s.testFile("unknown_schema_cases.json", vschemaWrapper, false) + s.testFile("vindex_func_cases.json", vschemaWrapper, false) + s.testFile("wireup_cases.json", vschemaWrapper, false) + s.testFile("memory_sort_cases.json", vschemaWrapper, false) + s.testFile("use_cases.json", vschemaWrapper, false) + s.testFile("set_cases.json", vschemaWrapper, false) + s.testFile("union_cases.json", vschemaWrapper, false) + s.testFile("large_union_cases.json", vschemaWrapper, false) + s.testFile("transaction_cases.json", vschemaWrapper, false) + s.testFile("lock_cases.json", vschemaWrapper, false) + s.testFile("large_cases.json", vschemaWrapper, false) + s.testFile("ddl_cases_no_default_keyspace.json", vschemaWrapper, false) + s.testFile("flush_cases_no_default_keyspace.json", vschemaWrapper, false) + s.testFile("show_cases_no_default_keyspace.json", vschemaWrapper, false) + s.testFile("stream_cases.json", vschemaWrapper, false) + s.testFile("info_schema80_cases.json", vschemaWrapper, false) + s.testFile("reference_cases.json", vschemaWrapper, false) + s.testFile("vexplain_cases.json", vschemaWrapper, false) + s.testFile("misc_cases.json", vschemaWrapper, false) + s.testFile("cte_cases.json", vschemaWrapper, false) } // TestForeignKeyPlanning tests the planning of foreign keys in a managed mode by Vitess. -func TestForeignKeyPlanning(t *testing.T) { - vschema := loadSchema(t, "vschemas/schema.json", true) - setFks(t, vschema) +func (s *planTestSuite) TestForeignKeyPlanning() { + vschema := loadSchema(s.T(), "vschemas/schema.json", true) + s.setFks(vschema) vschemaWrapper := &vschemawrapper.VSchemaWrapper{ V: vschema, TestBuilder: TestBuilder, Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - - testFile(t, "foreignkey_cases.json", testOutputTempDir, vschemaWrapper, false) + s.testFile("foreignkey_cases.json", vschemaWrapper, false) } // TestForeignKeyChecksOn tests the planning when the session variable for foreign_key_checks is set to ON. -func TestForeignKeyChecksOn(t *testing.T) { - vschema := loadSchema(t, "vschemas/schema.json", true) - setFks(t, vschema) +func (s *planTestSuite) TestForeignKeyChecksOn() { + vschema := loadSchema(s.T(), "vschemas/schema.json", true) + s.setFks(vschema) fkChecksState := true vschemaWrapper := &vschemawrapper.VSchemaWrapper{ V: vschema, @@ -128,15 +145,13 @@ func TestForeignKeyChecksOn(t *testing.T) { Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - - testFile(t, "foreignkey_checks_on_cases.json", testOutputTempDir, vschemaWrapper, false) + s.testFile("foreignkey_checks_on_cases.json", vschemaWrapper, false) } // TestForeignKeyChecksOff tests the planning when the session variable for foreign_key_checks is set to OFF. -func TestForeignKeyChecksOff(t *testing.T) { - vschema := loadSchema(t, "vschemas/schema.json", true) - setFks(t, vschema) +func (s *planTestSuite) TestForeignKeyChecksOff() { + vschema := loadSchema(s.T(), "vschemas/schema.json", true) + s.setFks(vschema) fkChecksState := false vschemaWrapper := &vschemawrapper.VSchemaWrapper{ V: vschema, @@ -145,12 +160,10 @@ func TestForeignKeyChecksOff(t *testing.T) { Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - - testFile(t, "foreignkey_checks_off_cases.json", testOutputTempDir, vschemaWrapper, false) + s.testFile("foreignkey_checks_off_cases.json", vschemaWrapper, false) } -func setFks(t *testing.T, vschema *vindexes.VSchema) { +func (s *planTestSuite) setFks(vschema *vindexes.VSchema) { if vschema.Keyspaces["sharded_fk_allow"] != nil { // FK from multicol_tbl2 referencing multicol_tbl1 that is shard scoped. _ = vschema.AddForeignKey("sharded_fk_allow", "multicol_tbl2", createFkDefinition([]string{"colb", "cola", "x", "colc", "y"}, "multicol_tbl1", []string{"colb", "cola", "y", "colc", "x"}, sqlparser.Cascade, sqlparser.Cascade)) @@ -185,7 +198,7 @@ func setFks(t *testing.T, vschema *vindexes.VSchema) { // FK from tbl_auth referencing tbl20 that is shard scoped of CASCADE types. _ = vschema.AddForeignKey("sharded_fk_allow", "tbl_auth", createFkDefinition([]string{"id"}, "tbl20", []string{"col2"}, sqlparser.Cascade, sqlparser.Cascade)) - addPKs(t, vschema, "sharded_fk_allow", []string{"tbl1", "tbl2", "tbl3", "tbl4", "tbl5", "tbl6", "tbl7", "tbl9", "tbl10", + s.addPKs(vschema, "sharded_fk_allow", []string{"tbl1", "tbl2", "tbl3", "tbl4", "tbl5", "tbl6", "tbl7", "tbl9", "tbl10", "multicol_tbl1", "multicol_tbl2", "tbl_auth", "tblrefDef", "tbl20"}) } if vschema.Keyspaces["unsharded_fk_allow"] != nil { @@ -225,86 +238,85 @@ func setFks(t *testing.T, vschema *vindexes.VSchema) { _ = vschema.AddUniqueKey("unsharded_fk_allow", "u_tbl9", sqlparser.Exprs{sqlparser.NewColName("bar"), sqlparser.NewColName("col9")}) _ = vschema.AddUniqueKey("unsharded_fk_allow", "u_tbl8", sqlparser.Exprs{sqlparser.NewColName("col8")}) - addPKs(t, vschema, "unsharded_fk_allow", []string{"u_tbl1", "u_tbl2", "u_tbl3", "u_tbl4", "u_tbl5", "u_tbl6", "u_tbl7", "u_tbl8", "u_tbl9", "u_tbl10", "u_tbl11", + s.addPKs(vschema, "unsharded_fk_allow", []string{"u_tbl1", "u_tbl2", "u_tbl3", "u_tbl4", "u_tbl5", "u_tbl6", "u_tbl7", "u_tbl8", "u_tbl9", "u_tbl10", "u_tbl11", "u_multicol_tbl1", "u_multicol_tbl2", "u_multicol_tbl3"}) } } -func addPKs(t *testing.T, vschema *vindexes.VSchema, ks string, tbls []string) { +func (s *planTestSuite) addPKs(vschema *vindexes.VSchema, ks string, tbls []string) { for _, tbl := range tbls { - require.NoError(t, + require.NoError(s.T(), vschema.AddPrimaryKey(ks, tbl, []string{"id"})) } } -func TestSystemTables57(t *testing.T) { +func (s *planTestSuite) TestSystemTables57() { // first we move everything to use 5.7 logic env, err := vtenv.New(vtenv.Options{ MySQLServerVersion: "5.7.9", }) - require.NoError(t, err) + require.NoError(s.T(), err) vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Env: env, } - testOutputTempDir := makeTestOutput(t) - testFile(t, "info_schema57_cases.json", testOutputTempDir, vschemaWrapper, false) + s.testFile("info_schema57_cases.json", vschemaWrapper, false) } -func TestSysVarSetDisabled(t *testing.T) { +func (s *planTestSuite) TestSysVarSetDisabled() { vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), SysVarEnabled: false, Env: vtenv.NewTestEnv(), } - testFile(t, "set_sysvar_disabled_cases.json", makeTestOutput(t), vschemaWrapper, false) + s.testFile("set_sysvar_disabled_cases.json", vschemaWrapper, false) } -func TestViews(t *testing.T) { +func (s *planTestSuite) TestViews() { vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), EnableViews: true, Env: vtenv.NewTestEnv(), } - testFile(t, "view_cases.json", makeTestOutput(t), vschemaWrapper, false) + s.testFile("view_cases.json", vschemaWrapper, false) } -func TestOne(t *testing.T) { +func (s *planTestSuite) TestOne() { reset := operators.EnableDebugPrinting() defer reset() - lv := loadSchema(t, "vschemas/schema.json", true) - setFks(t, lv) - addPKs(t, lv, "user", []string{"user", "music"}) + lv := loadSchema(s.T(), "vschemas/schema.json", true) + s.setFks(lv) + s.addPKs(lv, "user", []string{"user", "music"}) vschema := &vschemawrapper.VSchemaWrapper{ V: lv, TestBuilder: TestBuilder, Env: vtenv.NewTestEnv(), } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestOneTPCC(t *testing.T) { +func (s *planTestSuite) TestOneTPCC() { reset := operators.EnableDebugPrinting() defer reset() vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/tpcc_schema.json", true), + V: loadSchema(s.T(), "vschemas/tpcc_schema.json", true), Env: vtenv.NewTestEnv(), } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestOneWithMainAsDefault(t *testing.T) { +func (s *planTestSuite) TestOneWithMainAsDefault() { reset := operators.EnableDebugPrinting() defer reset() vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "main", Sharded: false, @@ -312,14 +324,14 @@ func TestOneWithMainAsDefault(t *testing.T) { Env: vtenv.NewTestEnv(), } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestOneWithSecondUserAsDefault(t *testing.T) { +func (s *planTestSuite) TestOneWithSecondUserAsDefault() { reset := operators.EnableDebugPrinting() defer reset() vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "second_user", Sharded: true, @@ -327,14 +339,14 @@ func TestOneWithSecondUserAsDefault(t *testing.T) { Env: vtenv.NewTestEnv(), } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestOneWithUserAsDefault(t *testing.T) { +func (s *planTestSuite) TestOneWithUserAsDefault() { reset := operators.EnableDebugPrinting() defer reset() vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "user", Sharded: true, @@ -342,75 +354,75 @@ func TestOneWithUserAsDefault(t *testing.T) { Env: vtenv.NewTestEnv(), } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestOneWithTPCHVSchema(t *testing.T) { +func (s *planTestSuite) TestOneWithTPCHVSchema() { reset := operators.EnableDebugPrinting() defer reset() vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/tpch_schema.json", true), + V: loadSchema(s.T(), "vschemas/tpch_schema.json", true), SysVarEnabled: true, Env: vtenv.NewTestEnv(), } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestOneWith57Version(t *testing.T) { +func (s *planTestSuite) TestOneWith57Version() { reset := operators.EnableDebugPrinting() defer reset() // first we move everything to use 5.7 logic env, err := vtenv.New(vtenv.Options{ MySQLServerVersion: "5.7.9", }) - require.NoError(t, err) + require.NoError(s.T(), err) vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Env: env, } - testFile(t, "onecase.json", "", vschema, false) + s.testFile("onecase.json", vschema, false) } -func TestRubyOnRailsQueries(t *testing.T) { +func (s *planTestSuite) TestRubyOnRailsQueries() { vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/rails_schema.json", true), + V: loadSchema(s.T(), "vschemas/rails_schema.json", true), SysVarEnabled: true, Env: vtenv.NewTestEnv(), } - testFile(t, "rails_cases.json", makeTestOutput(t), vschemaWrapper, false) + s.testFile("rails_cases.json", vschemaWrapper, false) } -func TestOLTP(t *testing.T) { +func (s *planTestSuite) TestOLTP() { vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/oltp_schema.json", true), + V: loadSchema(s.T(), "vschemas/oltp_schema.json", true), SysVarEnabled: true, Env: vtenv.NewTestEnv(), } - testFile(t, "oltp_cases.json", makeTestOutput(t), vschemaWrapper, false) + s.testFile("oltp_cases.json", vschemaWrapper, false) } -func TestTPCC(t *testing.T) { +func (s *planTestSuite) TestTPCC() { vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/tpcc_schema.json", true), + V: loadSchema(s.T(), "vschemas/tpcc_schema.json", true), SysVarEnabled: true, Env: vtenv.NewTestEnv(), } - testFile(t, "tpcc_cases.json", makeTestOutput(t), vschemaWrapper, false) + s.testFile("tpcc_cases.json", vschemaWrapper, false) } -func TestTPCH(t *testing.T) { +func (s *planTestSuite) TestTPCH() { vschemaWrapper := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/tpch_schema.json", true), + V: loadSchema(s.T(), "vschemas/tpch_schema.json", true), SysVarEnabled: true, Env: vtenv.NewTestEnv(), } - testFile(t, "tpch_cases.json", makeTestOutput(t), vschemaWrapper, false) + s.testFile("tpch_cases.json", vschemaWrapper, false) } func BenchmarkOLTP(b *testing.B) { @@ -441,9 +453,9 @@ func benchmarkWorkload(b *testing.B, name string) { } } -func TestBypassPlanningShardTargetFromFile(t *testing.T) { +func (s *planTestSuite) TestBypassPlanningShardTargetFromFile() { vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "main", Sharded: false, @@ -453,14 +465,14 @@ func TestBypassPlanningShardTargetFromFile(t *testing.T) { Env: vtenv.NewTestEnv(), } - testFile(t, "bypass_shard_cases.json", makeTestOutput(t), vschema, false) + s.testFile("bypass_shard_cases.json", vschema, false) } -func TestBypassPlanningKeyrangeTargetFromFile(t *testing.T) { +func (s *planTestSuite) TestBypassPlanningKeyrangeTargetFromFile() { keyRange, _ := key.ParseShardingSpec("-") vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "main", Sharded: false, @@ -470,15 +482,15 @@ func TestBypassPlanningKeyrangeTargetFromFile(t *testing.T) { Env: vtenv.NewTestEnv(), } - testFile(t, "bypass_keyrange_cases.json", makeTestOutput(t), vschema, false) + s.testFile("bypass_keyrange_cases.json", vschema, false) } -func TestWithDefaultKeyspaceFromFile(t *testing.T) { +func (s *planTestSuite) TestWithDefaultKeyspaceFromFile() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // We are testing this separately so we can set a default keyspace vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "main", Sharded: false, @@ -498,21 +510,20 @@ func TestWithDefaultKeyspaceFromFile(t *testing.T) { } return ki.SidecarDbName, nil }) - require.True(t, created) + require.True(s.T(), created) - testOutputTempDir := makeTestOutput(t) - testFile(t, "alterVschema_cases.json", testOutputTempDir, vschema, false) - testFile(t, "ddl_cases.json", testOutputTempDir, vschema, false) - testFile(t, "migration_cases.json", testOutputTempDir, vschema, false) - testFile(t, "flush_cases.json", testOutputTempDir, vschema, false) - testFile(t, "show_cases.json", testOutputTempDir, vschema, false) - testFile(t, "call_cases.json", testOutputTempDir, vschema, false) + s.testFile("alterVschema_cases.json", vschema, false) + s.testFile("ddl_cases.json", vschema, false) + s.testFile("migration_cases.json", vschema, false) + s.testFile("flush_cases.json", vschema, false) + s.testFile("show_cases.json", vschema, false) + s.testFile("call_cases.json", vschema, false) } -func TestWithDefaultKeyspaceFromFileSharded(t *testing.T) { +func (s *planTestSuite) TestWithDefaultKeyspaceFromFileSharded() { // We are testing this separately so we can set a default keyspace vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "second_user", Sharded: true, @@ -521,14 +532,13 @@ func TestWithDefaultKeyspaceFromFileSharded(t *testing.T) { Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - testFile(t, "select_cases_with_default.json", testOutputTempDir, vschema, false) + s.testFile("select_cases_with_default.json", vschema, false) } -func TestWithUserDefaultKeyspaceFromFileSharded(t *testing.T) { +func (s *planTestSuite) TestWithUserDefaultKeyspaceFromFileSharded() { // We are testing this separately so we can set a default keyspace vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "user", Sharded: true, @@ -537,26 +547,25 @@ func TestWithUserDefaultKeyspaceFromFileSharded(t *testing.T) { Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - testFile(t, "select_cases_with_user_as_default.json", testOutputTempDir, vschema, false) + s.testFile("select_cases_with_user_as_default.json", vschema, false) } -func TestWithSystemSchemaAsDefaultKeyspace(t *testing.T) { +func (s *planTestSuite) TestWithSystemSchemaAsDefaultKeyspace() { // We are testing this separately so we can set a default keyspace vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{Name: "information_schema"}, TabletType_: topodatapb.TabletType_PRIMARY, Env: vtenv.NewTestEnv(), } - testFile(t, "sysschema_default.json", makeTestOutput(t), vschema, false) + s.testFile("sysschema_default.json", vschema, false) } -func TestOtherPlanningFromFile(t *testing.T) { +func (s *planTestSuite) TestOtherPlanningFromFile() { // We are testing this separately so we can set a default keyspace vschema := &vschemawrapper.VSchemaWrapper{ - V: loadSchema(t, "vschemas/schema.json", true), + V: loadSchema(s.T(), "vschemas/schema.json", true), Keyspace: &vindexes.Keyspace{ Name: "main", Sharded: false, @@ -565,9 +574,8 @@ func TestOtherPlanningFromFile(t *testing.T) { Env: vtenv.NewTestEnv(), } - testOutputTempDir := makeTestOutput(t) - testFile(t, "other_read_cases.json", testOutputTempDir, vschema, false) - testFile(t, "other_admin_cases.json", testOutputTempDir, vschema, false) + s.testFile("other_read_cases.json", vschema, false) + s.testFile("other_admin_cases.json", vschema, false) } func loadSchema(t testing.TB, filename string, setCollation bool) *vindexes.VSchema { @@ -630,10 +638,11 @@ type ( } ) -func testFile(t *testing.T, filename, tempDir string, vschema *vschemawrapper.VSchemaWrapper, render bool) { +func (s *planTestSuite) testFile(filename string, vschema *vschemawrapper.VSchemaWrapper, render bool) { opts := jsondiff.DefaultConsoleOptions() - t.Run(filename, func(t *testing.T) { + s.T().Run(filename, func(t *testing.T) { + failed := false var expected []planTest for _, tcase := range readJSONTests(filename) { testName := tcase.Comment @@ -655,6 +664,11 @@ func testFile(t *testing.T, filename, tempDir string, vschema *vschemawrapper.VS // - produces a different plan than expected // - fails to produce a plan t.Run(testName, func(t *testing.T) { + defer func() { + if t.Failed() { + failed = true + } + }() compare, s := jsondiff.Compare(tcase.Plan, []byte(out), &opts) if compare != jsondiff.FullMatch { message := fmt.Sprintf("%s\nDiff:\n%s\n[%s] \n[%s]", filename, s, tcase.Plan, out) @@ -670,9 +684,9 @@ func testFile(t *testing.T, filename, tempDir string, vschema *vschemawrapper.VS }) expected = append(expected, current) } - if tempDir != "" { + if s.outputDir != "" && failed { name := strings.TrimSuffix(filename, filepath.Ext(filename)) - name = filepath.Join(tempDir, name+".json") + name = filepath.Join(s.outputDir, name+".json") file, err := os.Create(name) require.NoError(t, err) enc := json.NewEncoder(file)