Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improving random query generation for endtoend testing #13460

Merged
merged 29 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3d10df5
added flag for if the randomly generated query can have aggregation
arvind-murty Jun 30, 2023
b40e319
added ExprGeneratorConfig to random expression generation
arvind-murty Jul 4, 2023
54368c6
refactor tableT struct
arvind-murty Jul 4, 2023
0b07313
simplified random predicate generation
arvind-murty Jul 6, 2023
f14943d
refactor column struct
arvind-murty Jul 8, 2023
e005e78
added aggregation to random expressions and changed random query gene…
arvind-murty Jul 10, 2023
8e28e60
added queryGen struct to pass along Rand and ExprGeneratorConfig
arvind-murty Jul 11, 2023
f32f5dd
added random column aliases
arvind-murty Jul 13, 2023
e92b3c2
added more complex aggregate expressions
arvind-murty Jul 13, 2023
1953053
added scalar subqueries to fuzzer
arvind-murty Jul 16, 2023
bf53801
added scalar subqueries to all random expression generation for the f…
arvind-murty Jul 17, 2023
98055b7
added support for tuple random expressions
arvind-murty Jul 18, 2023
dccd6ec
added support for random expressions with exists
arvind-murty Jul 19, 2023
35e045b
added union queries in fuzzer
arvind-murty Jul 20, 2023
13c89ca
added tuple comparisons to random expression generator
arvind-murty Jul 21, 2023
60ec73c
exported vschemaWrapper to go/test/utils
arvind-murty Jul 21, 2023
a0acb5a
added query simplification to fuzzer
arvind-murty Jul 24, 2023
a28cd5f
simplified vschema and schema for simplifying fuzzer queries
arvind-murty Jul 24, 2023
ce019af
added simplification for case expressions
arvind-murty Jul 24, 2023
10c2034
moved VSchemaWrapper to its own package
arvind-murty Jul 24, 2023
a066e09
updated caseExpr simplification and reverted reverted simplifier changes
arvind-murty Jul 25, 2023
a2f7920
added sqlparser.NewCaseExpr
arvind-murty Jul 25, 2023
1d2ab6c
removed separate testing runs from simplifier in query fuzzer
arvind-murty Jul 26, 2023
756ad95
simplified existing results mismatched queries
arvind-murty Jul 26, 2023
359189e
minor fixes/improvements
arvind-murty Jul 27, 2023
a60a1c2
fixed goimports and failing endtoend tests
arvind-murty Jul 28, 2023
6736793
skip TestRandom
arvind-murty Jul 28, 2023
2c85a63
Merge remote-tracking branch 'upstream/main' into am-random-2
systay Aug 9, 2023
5c159f9
Merge remote-tracking branch 'upstream/main' into am-random-2
systay Aug 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
749 changes: 455 additions & 294 deletions go/test/endtoend/vtgate/queries/random/query_gen.go

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions go/test/endtoend/vtgate/queries/random/query_gen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright 2023 The Vitess Authors.

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 random

import (
"fmt"
"math/rand"
"testing"

"github.com/stretchr/testify/require"

"vitess.io/vitess/go/vt/sqlparser"
)

// TestSeed makes sure that the seed is deterministic
func TestSeed(t *testing.T) {
// specify the schema (that is defined in schema.sql)
schemaTables := []tableT{
{tableExpr: sqlparser.NewTableName("emp")},
{tableExpr: sqlparser.NewTableName("dept")},
}
schemaTables[0].addColumns([]column{
{name: "empno", typ: "bigint"},
{name: "ename", typ: "varchar"},
{name: "job", typ: "varchar"},
{name: "mgr", typ: "bigint"},
{name: "hiredate", typ: "date"},
{name: "sal", typ: "bigint"},
{name: "comm", typ: "bigint"},
{name: "deptno", typ: "bigint"},
}...)
schemaTables[1].addColumns([]column{
{name: "deptno", typ: "bigint"},
{name: "dname", typ: "varchar"},
{name: "loc", typ: "varchar"},
}...)

seed := int64(1689757943775102000)
genConfig := sqlparser.NewExprGeneratorConfig(sqlparser.CannotAggregate, "", 0, false)
qg := newQueryGenerator(rand.New(rand.NewSource(seed)), genConfig, 2, 2, 2, schemaTables)
qg.randomQuery()
query1 := sqlparser.String(qg.stmt)
qg = newQueryGenerator(rand.New(rand.NewSource(seed)), genConfig, 2, 2, 2, schemaTables)
qg.randomQuery()
query2 := sqlparser.String(qg.stmt)
fmt.Println(query1)
require.Equal(t, query1, query2)
}
19 changes: 13 additions & 6 deletions go/test/endtoend/vtgate/queries/random/random_expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ limitations under the License.
package random

import (
"math/rand"
"testing"
"time"

"vitess.io/vitess/go/slice"
"vitess.io/vitess/go/vt/sqlparser"
)

// This test tests that generating a random expression with a schema does not panic
// This test tests that generating random expressions with a schema does not panic
func TestRandomExprWithTables(t *testing.T) {
// specify the schema (that is defined in schema.sql)
schemaTables := []tableT{
{name: sqlparser.NewTableName("emp")},
{name: sqlparser.NewTableName("dept")},
{tableExpr: sqlparser.NewTableName("emp")},
{tableExpr: sqlparser.NewTableName("dept")},
}
schemaTables[0].addColumns([]column{
{name: "empno", typ: "bigint"},
Expand All @@ -46,7 +48,12 @@ func TestRandomExprWithTables(t *testing.T) {
{name: "loc", typ: "varchar"},
}...)

seed := time.Now().UnixNano()
g := sqlparser.NewGenerator(seed, 3, slice.Map(schemaTables, func(t tableT) sqlparser.ExprGenerator { return &t })...)
g.Expression()
for i := 0; i < 100; i++ {

seed := time.Now().UnixNano()
r := rand.New(rand.NewSource(seed))
genConfig := sqlparser.NewExprGeneratorConfig(sqlparser.CanAggregate, "", 0, false)
g := sqlparser.NewGenerator(r, 3, slice.Map(schemaTables, func(t tableT) sqlparser.ExprGenerator { return &t })...)
g.Expression(genConfig)
}
}
241 changes: 151 additions & 90 deletions go/test/endtoend/vtgate/queries/random/random_test.go

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions go/test/endtoend/vtgate/queries/random/simplifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
Copyright 2023 The Vitess Authors.

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 random

import (
"fmt"
"strings"
"testing"

"vitess.io/vitess/go/test/vschemawrapper"

"github.com/stretchr/testify/require"

"vitess.io/vitess/go/test/endtoend/utils"
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vtgate/planbuilder"
"vitess.io/vitess/go/vt/vtgate/simplifier"
"vitess.io/vitess/go/vt/vtgate/vindexes"
)

func TestSimplifyResultsMismatchedQuery(t *testing.T) {
t.Skip("Skip CI")

var queries []string
queries = append(queries, "select /*vt+ PLANNER=Gen4 */ (68 - -16) / case false when -45 then 3 when 28 then -43 else -62 end as crandom0 from dept as tbl0, (select /*vt+ PLANNER=Gen4 */ distinct not not false and count(*) from emp as tbl0, emp as tbl1 where tbl1.ename) as tbl1 limit 1",
"select /*vt+ PLANNER=Gen4 */ distinct case true when 'burro' then 'trout' else 'elf' end < case count(distinct true) when 'bobcat' then 'turkey' else 'penguin' end from dept as tbl0, emp as tbl1 where 'spider'",
"select /*vt+ PLANNER=Gen4 */ distinct sum(distinct tbl1.deptno) from dept as tbl0, emp as tbl1 where tbl0.deptno and tbl1.comm in (12, tbl0.deptno, case false when 67 then -17 when -78 then -35 end, -76 >> -68)",
"select /*vt+ PLANNER=Gen4 */ count(*) + 1 from emp as tbl0 order by count(*) desc",
"select /*vt+ PLANNER=Gen4 */ count(2 >> tbl2.mgr), sum(distinct tbl2.empno <=> 15) from emp as tbl0 left join emp as tbl2 on -32",
"select /*vt+ PLANNER=Gen4 */ sum(case false when true then tbl1.deptno else -154 / 132 end) as caggr1 from emp as tbl0, dept as tbl1",
"select /*vt+ PLANNER=Gen4 */ tbl1.dname as cgroup0, tbl1.dname as cgroup1 from dept as tbl0, dept as tbl1 group by tbl1.dname, tbl1.deptno order by tbl1.deptno desc",
"select /*vt+ PLANNER=Gen4 */ tbl0.ename as cgroup1 from emp as tbl0 group by tbl0.job, tbl0.ename having sum(tbl0.mgr) = sum(tbl0.mgr) order by tbl0.job desc, tbl0.ename asc limit 8",
"select /*vt+ PLANNER=Gen4 */ distinct count(*) as caggr1 from dept as tbl0, emp as tbl1 group by tbl1.sal having max(tbl1.comm) != true",
"select /*vt+ PLANNER=Gen4 */ distinct sum(tbl1.loc) as caggr0 from dept as tbl0, dept as tbl1 group by tbl1.deptno having max(tbl1.dname) <= 1",
"select /*vt+ PLANNER=Gen4 */ min(tbl0.deptno) as caggr0 from dept as tbl0, emp as tbl1 where case when false then tbl0.dname end group by tbl1.comm",
"select /*vt+ PLANNER=Gen4 */ count(*) as caggr0, 1 as crandom0 from dept as tbl0, emp as tbl1 where 1 = 0",
"select /*vt+ PLANNER=Gen4 */ count(*) as caggr0, 1 as crandom0 from dept as tbl0, emp as tbl1 where 'octopus'",
"select /*vt+ PLANNER=Gen4 */ distinct 'octopus' as crandom0 from dept as tbl0, emp as tbl1 where tbl0.deptno = tbl1.empno having count(*) = count(*)",
"select /*vt+ PLANNER=Gen4 */ max(tbl0.deptno) from dept as tbl0 right join emp as tbl1 on tbl0.deptno = tbl1.empno and tbl0.deptno = tbl1.deptno group by tbl0.deptno",
"select /*vt+ PLANNER=Gen4 */ count(tbl1.comm) from emp as tbl1 right join emp as tbl2 on tbl1.mgr = tbl2.sal")

for _, query := range queries {
var simplified string
t.Run("simplification "+query, func(t *testing.T) {
simplified = simplifyResultsMismatchedQuery(t, query)
})

t.Run("simplified "+query, func(t *testing.T) {
mcmp, closer := start(t)
defer closer()

mcmp.ExecAllowAndCompareError(simplified)
})

fmt.Printf("final simplified query: %s\n", simplified)
}
}

// given a query that errors with results mismatched, simplifyResultsMismatchedQuery returns a simpler version with the same error
func simplifyResultsMismatchedQuery(t *testing.T, query string) string {
t.Helper()
mcmp, closer := start(t)
defer closer()

_, err := mcmp.ExecAllowAndCompareError(query)
if err == nil {
t.Fatalf("query (%s) does not error", query)
} else if !strings.Contains(err.Error(), "mismatched") {
t.Fatalf("query (%s) does not error with results mismatched\nError: %v", query, err)
}

require.NoError(t, utils.WaitForAuthoritative(t, keyspaceName, "emp", clusterInstance.VtgateProcess.ReadVSchema))
require.NoError(t, utils.WaitForAuthoritative(t, keyspaceName, "dept", clusterInstance.VtgateProcess.ReadVSchema))

formal, err := vindexes.LoadFormal("svschema.json")
require.NoError(t, err)
vSchema := vindexes.BuildVSchema(formal)
vSchemaWrapper := &vschemawrapper.VSchemaWrapper{
V: vSchema,
Version: planbuilder.Gen4,
}

stmt, err := sqlparser.Parse(query)
require.NoError(t, err)

simplified := simplifier.SimplifyStatement(
stmt.(sqlparser.SelectStatement),
vSchemaWrapper.CurrentDb(),
vSchemaWrapper,
func(statement sqlparser.SelectStatement) bool {
q := sqlparser.String(statement)
_, newErr := mcmp.ExecAllowAndCompareError(q)
if newErr == nil {
return false
} else {
return strings.Contains(newErr.Error(), "mismatched")
}
},
)

return sqlparser.String(simplified)
}
6 changes: 6 additions & 0 deletions go/test/endtoend/vtgate/queries/random/svschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"keyspaces": {
"ks_random": {
}
}
}
Loading
Loading