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

executor: migrate test-infra to testify for executor/cte_test.go [DO NOT MERGE, JUST A DEMO] #27377

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions executor/cte_serial_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2021 PingCAP, 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 executor_test

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

"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/testkit"
"github.com/stretchr/testify/require"
)

func TestSpillToDisk(t *testing.T) {
defer config.RestoreFunc()()
config.UpdateGlobal(func(conf *config.Config) {
conf.OOMUseTmpStorage = true
})

store, clean := testkit.CreateMockStore(t)
defer clean()

tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testCTEStorageSpill", "return(true)"))
defer func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testCTEStorageSpill"))
tk.MustExec("set tidb_mem_quota_query = 1073741824;")
}()

require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)"))
defer func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill"))
}()

// Use duplicated rows to test UNION DISTINCT.
tk.MustExec("set tidb_mem_quota_query = 1073741824;")
insertStr := "insert into t1 values(0)"
rowNum := 1000
vals := make([]int, rowNum)
vals[0] = 0
for i := 1; i < rowNum; i++ {
v := rand.Intn(100)
vals[i] = v
insertStr += fmt.Sprintf(", (%d)", v)
}
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(c1 int);")
tk.MustExec(insertStr)
tk.MustExec("set tidb_mem_quota_query = 40000;")
tk.MustExec("set cte_max_recursion_depth = 500000;")
sql := fmt.Sprintf("with recursive cte1 as ( "+
"select c1 from t1 "+
"union "+
"select c1 + 1 c1 from cte1 where c1 < %d) "+
"select c1 from cte1 order by c1;", rowNum)
rows := tk.MustQuery(sql)

memTracker := tk.Session().GetSessionVars().StmtCtx.MemTracker
diskTracker := tk.Session().GetSessionVars().StmtCtx.DiskTracker
require.Greater(t, memTracker.MaxConsumed(), int64(0))
require.Greater(t, diskTracker.MaxConsumed(), int64(0))

sort.Ints(vals)
resRows := make([]string, 0, rowNum)
for i := vals[0]; i <= rowNum; i++ {
resRows = append(resRows, fmt.Sprintf("%d", i))
}
rows.Check(testkit.Rows(resRows...))
}
175 changes: 42 additions & 133 deletions executor/cte_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,68 +15,21 @@
package executor_test

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

"github.com/pingcap/check"
"github.com/stretchr/testify/require"

"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/session"
"github.com/pingcap/tidb/sessionctx"

"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/store/mockstore"
"github.com/pingcap/tidb/util/mock"
"github.com/pingcap/tidb/util/testkit"
"github.com/pingcap/tidb/testkit"
)

var _ = check.Suite(&CTETestSuite{&baseCTETestSuite{}})
var _ = check.SerialSuites(&CTESerialTestSuite{&baseCTETestSuite{}})

type baseCTETestSuite struct {
store kv.Storage
dom *domain.Domain
sessionCtx sessionctx.Context
session session.Session
ctx context.Context
}

type CTETestSuite struct {
*baseCTETestSuite
}

type CTESerialTestSuite struct {
*baseCTETestSuite
}

func (test *baseCTETestSuite) SetUpSuite(c *check.C) {
var err error
test.store, err = mockstore.NewMockStore()
c.Assert(err, check.IsNil)
func TestBasicCTE(t *testing.T) {
t.Parallel()

test.dom, err = session.BootstrapSession(test.store)
c.Assert(err, check.IsNil)
store, clean := testkit.CreateMockStore(t)
defer clean()

test.sessionCtx = mock.NewContext()

test.session, err = session.CreateSession4Test(test.store)
c.Assert(err, check.IsNil)
test.session.SetConnectionID(0)

test.ctx = context.Background()
}

func (test *baseCTETestSuite) TearDownSuite(c *check.C) {
test.dom.Close()
test.store.Close()
}

func (test *CTETestSuite) TestBasicCTE(c *check.C) {
tk := testkit.NewTestKit(c, test.store)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

rows := tk.MustQuery("with recursive cte1 as (" +
Expand Down Expand Up @@ -121,64 +74,14 @@ func (test *CTETestSuite) TestBasicCTE(c *check.C) {
rows.Check(testkit.Rows("1 1", "2 1", "3 1", "4 1", "5 1"))
}

func (test *CTESerialTestSuite) TestSpillToDisk(c *check.C) {
defer config.RestoreFunc()()
config.UpdateGlobal(func(conf *config.Config) {
conf.OOMUseTmpStorage = true
})

tk := testkit.NewTestKit(c, test.store)
tk.MustExec("use test;")

c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testCTEStorageSpill", "return(true)"), check.IsNil)
defer func() {
c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testCTEStorageSpill"), check.IsNil)
tk.MustExec("set tidb_mem_quota_query = 1073741824;")
}()
c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)"), check.IsNil)
defer func() {
c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill"), check.IsNil)
}()

// Use duplicated rows to test UNION DISTINCT.
tk.MustExec("set tidb_mem_quota_query = 1073741824;")
insertStr := "insert into t1 values(0)"
rowNum := 1000
vals := make([]int, rowNum)
vals[0] = 0
for i := 1; i < rowNum; i++ {
v := rand.Intn(100)
vals[i] = v
insertStr += fmt.Sprintf(", (%d)", v)
}
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(c1 int);")
tk.MustExec(insertStr)
tk.MustExec("set tidb_mem_quota_query = 40000;")
tk.MustExec("set cte_max_recursion_depth = 500000;")
sql := fmt.Sprintf("with recursive cte1 as ( "+
"select c1 from t1 "+
"union "+
"select c1 + 1 c1 from cte1 where c1 < %d) "+
"select c1 from cte1 order by c1;", rowNum)
rows := tk.MustQuery(sql)

memTracker := tk.Se.GetSessionVars().StmtCtx.MemTracker
diskTracker := tk.Se.GetSessionVars().StmtCtx.DiskTracker
c.Assert(memTracker.MaxConsumed(), check.Greater, int64(0))
c.Assert(diskTracker.MaxConsumed(), check.Greater, int64(0))

sort.Ints(vals)
resRows := make([]string, 0, rowNum)
for i := vals[0]; i <= rowNum; i++ {
resRows = append(resRows, fmt.Sprintf("%d", i))
}
rows.Check(testkit.Rows(resRows...))
}
func TestUnionDistinct(t *testing.T) {
t.Parallel()

store, clean := testkit.CreateMockStore(t)
defer clean()

func (test *CTETestSuite) TestUnionDistinct(c *check.C) {
tk := testkit.NewTestKit(c, test.store)
tk.MustExec("use test;")
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

// Basic test. UNION/UNION ALL intersects.
rows := tk.MustQuery("with recursive cte1(c1) as (select 1 union select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1;")
Expand All @@ -200,14 +103,19 @@ func (test *CTETestSuite) TestUnionDistinct(c *check.C) {
rows.Check(testkit.Rows("1", "2", "3", "4"))
}

func (test *CTETestSuite) TestCTEMaxRecursionDepth(c *check.C) {
tk := testkit.NewTestKit(c, test.store)
tk.MustExec("use test;")
func TestCTEMaxRecursionDepth(t *testing.T) {
t.Parallel()

store, clean := testkit.CreateMockStore(t)
defer clean()

tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

tk.MustExec("set @@cte_max_recursion_depth = -1;")
err := tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 100) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")

// If there is no recursive part, query runs ok.
rows := tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;")
rows.Check(testkit.Rows("1", "2"))
Expand All @@ -216,11 +124,10 @@ func (test *CTETestSuite) TestCTEMaxRecursionDepth(c *check.C) {

tk.MustExec("set @@cte_max_recursion_depth = 0;")
err = tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
err = tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")

// If there is no recursive part, query runs ok.
rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;")
rows.Check(testkit.Rows("1", "2"))
Expand All @@ -233,18 +140,23 @@ func (test *CTETestSuite) TestCTEMaxRecursionDepth(c *check.C) {
rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1;")
rows.Check(testkit.Rows("1"))
err = tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 2) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 2 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 2 iterations. Try increasing @@cte_max_recursion_depth to a larger value")

// If there is no recursive part, query runs ok.
rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;")
rows.Check(testkit.Rows("1", "2"))
rows = tk.MustQuery("with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;")
rows.Check(testkit.Rows("1", "2"))
}

func (test *CTETestSuite) TestCTEWithLimit(c *check.C) {
tk := testkit.NewTestKit(c, test.store)
tk.MustExec("use test;")
func TestCTEWithLimit(t *testing.T) {
t.Parallel()

store, clean := testkit.CreateMockStore(t)
defer clean()

tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

// Basic recursive tests.
rows := tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1")
Expand All @@ -268,16 +180,14 @@ func (test *CTETestSuite) TestCTEWithLimit(c *check.C) {
rows.Check(testkit.Rows("2"))

err := tk.QueryToErr("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 3 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 3 iterations. Try increasing @@cte_max_recursion_depth to a larger value")

tk.MustExec("set cte_max_recursion_depth=1000;")
rows = tk.MustQuery("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 996) select * from cte1;")
rows.Check(testkit.Rows("996", "997", "998", "999", "1000"))

err = tk.QueryToErr("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 997) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value")

rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1")
rows.Check(testkit.Rows())
Expand Down Expand Up @@ -312,7 +222,7 @@ func (test *CTETestSuite) TestCTEWithLimit(c *check.C) {
// Error: ERROR 1221 (HY000): Incorrect usage of UNION and LIMIT.
// Limit can only be at the end of SQL stmt.
err = tk.ExecToErr("with recursive cte1(c1) as (select c1 from t1 limit 1 offset 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1")
c.Assert(err.Error(), check.Equals, "[planner:1221]Incorrect usage of UNION and LIMIT")
require.EqualError(t, err, "[planner:1221]Incorrect usage of UNION and LIMIT")

// Basic non-recusive tests.
rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 1 offset 1) select * from cte1")
Expand Down Expand Up @@ -375,8 +285,7 @@ func (test *CTETestSuite) TestCTEWithLimit(c *check.C) {
rows.Check(testkit.Rows())
// MySQL err: ERROR 1365 (22012): Division by 0. Because it gives error when computing 1/c1.
err = tk.QueryToErr("with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 1) select * from cte1;")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Equals, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")
require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value")

tk.MustExec("set cte_max_recursion_depth = 1000;")
tk.MustExec("drop table if exists t1;")
Expand Down
9 changes: 9 additions & 0 deletions testkit/testkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ func (tk *TestKit) QueryToErr(sql string, args ...interface{}) error {
return resErr
}

// ExecToErr executes a sql statement and discard results.
func (tk *TestKit) ExecToErr(sql string, args ...interface{}) error {
res, err := tk.Exec(sql, args...)
if res != nil {
tk.require.NoError(res.Close())
}
return err
}

// ResultSetToResult converts sqlexec.RecordSet to testkit.Result.
// It is used to check results of execute statement in binary mode.
func (tk *TestKit) ResultSetToResult(rs sqlexec.RecordSet, comment string) *Result {
Expand Down