github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/stochastik/milevadb_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package stochastik
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"os"
    20  	"sync"
    21  	"sync/atomic"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/whtcorpsinc/BerolinaSQL/auth"
    26  	. "github.com/whtcorpsinc/check"
    27  	"github.com/whtcorpsinc/milevadb/blockcodec"
    28  	"github.com/whtcorpsinc/milevadb/causet/embedded"
    29  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    30  	"github.com/whtcorpsinc/milevadb/ekv"
    31  	"github.com/whtcorpsinc/milevadb/petri"
    32  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    33  	"github.com/whtcorpsinc/milevadb/soliton/sqlexec"
    34  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    35  	"github.com/whtcorpsinc/milevadb/types"
    36  )
    37  
    38  func TestT(t *testing.T) {
    39  	logLevel := os.Getenv("log_level")
    40  	logutil.InitLogger(logutil.NewLogConfig(logLevel, logutil.DefaultLogFormat, "", logutil.EmptyFileLogConfig, false))
    41  	CustomVerboseFlag = true
    42  	SetSchemaLease(20 * time.Millisecond)
    43  	TestingT(t)
    44  }
    45  
    46  var _ = Suite(&testMainSuite{})
    47  var _ = SerialSuites(&testBootstrapSuite{})
    48  
    49  type testMainSuite struct {
    50  	dbName      string
    51  	causetstore ekv.CausetStorage
    52  	dom         *petri.Petri
    53  }
    54  
    55  func (s *testMainSuite) SetUpSuite(c *C) {
    56  	testleak.BeforeTest()
    57  	s.dbName = "test_main_db"
    58  	s.causetstore = newStore(c, s.dbName)
    59  	dom, err := BootstrapStochastik(s.causetstore)
    60  	c.Assert(err, IsNil)
    61  	s.dom = dom
    62  }
    63  
    64  func (s *testMainSuite) TearDownSuite(c *C) {
    65  	defer testleak.AfterTest(c)()
    66  	s.dom.Close()
    67  	err := s.causetstore.Close()
    68  	c.Assert(err, IsNil)
    69  	removeStore(c, s.dbName)
    70  }
    71  
    72  func (s *testMainSuite) TestSysStochastikPoolGoroutineLeak(c *C) {
    73  	causetstore, dom := newStoreWithBootstrap(c, s.dbName+"goroutine_leak")
    74  	defer causetstore.Close()
    75  	defer dom.Close()
    76  	se, err := createStochastik(causetstore)
    77  	c.Assert(err, IsNil)
    78  
    79  	// Test an issue that sysStochastikPool doesn't call stochastik's Close, cause
    80  	// asyncGetTSWorker goroutine leak.
    81  	count := 200
    82  	var wg sync.WaitGroup
    83  	wg.Add(count)
    84  	for i := 0; i < count; i++ {
    85  		go func(se *stochastik) {
    86  			_, _, err := se.InterDircRestrictedALLEGROSQL("select * from allegrosql.user limit 1")
    87  			c.Assert(err, IsNil)
    88  			wg.Done()
    89  		}(se)
    90  	}
    91  	wg.Wait()
    92  }
    93  
    94  func (s *testMainSuite) TestParseErrorWarn(c *C) {
    95  	ctx := embedded.MockContext()
    96  
    97  	nodes, err := Parse(ctx, "select /*+ adf */ 1")
    98  	c.Assert(err, IsNil)
    99  	c.Assert(len(nodes), Equals, 1)
   100  	c.Assert(len(ctx.GetStochastikVars().StmtCtx.GetWarnings()), Equals, 1)
   101  
   102  	_, err = Parse(ctx, "select")
   103  	c.Assert(err, NotNil)
   104  }
   105  
   106  func newStore(c *C, dbPath string) ekv.CausetStorage {
   107  	causetstore, err := mockstore.NewMockStore()
   108  	c.Assert(err, IsNil)
   109  	return causetstore
   110  }
   111  
   112  func newStoreWithBootstrap(c *C, dbPath string) (ekv.CausetStorage, *petri.Petri) {
   113  	causetstore, err := mockstore.NewMockStore()
   114  	c.Assert(err, IsNil)
   115  	dom, err := BootstrapStochastik(causetstore)
   116  	c.Assert(err, IsNil)
   117  	return causetstore, dom
   118  }
   119  
   120  var testConnID uint64
   121  
   122  func newStochastik(c *C, causetstore ekv.CausetStorage, dbName string) Stochastik {
   123  	se, err := CreateStochastik4Test(causetstore)
   124  	id := atomic.AddUint64(&testConnID, 1)
   125  	se.SetConnectionID(id)
   126  	c.Assert(err, IsNil)
   127  	se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890"))
   128  	mustInterDircALLEGROSQL(c, se, "create database if not exists "+dbName)
   129  	mustInterDircALLEGROSQL(c, se, "use "+dbName)
   130  	return se
   131  }
   132  
   133  func removeStore(c *C, dbPath string) {
   134  	os.RemoveAll(dbPath)
   135  }
   136  
   137  func exec(se Stochastik, allegrosql string, args ...interface{}) (sqlexec.RecordSet, error) {
   138  	ctx := context.Background()
   139  	if len(args) == 0 {
   140  		rs, err := se.InterDircute(ctx, allegrosql)
   141  		if err == nil && len(rs) > 0 {
   142  			return rs[0], nil
   143  		}
   144  		return nil, err
   145  	}
   146  	stmtID, _, _, err := se.PrepareStmt(allegrosql)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	params := make([]types.Causet, len(args))
   151  	for i := 0; i < len(params); i++ {
   152  		params[i] = types.NewCauset(args[i])
   153  	}
   154  	rs, err := se.InterDircutePreparedStmt(ctx, stmtID, params)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	return rs, nil
   159  }
   160  
   161  func mustInterDircALLEGROSQL(c *C, se Stochastik, allegrosql string, args ...interface{}) sqlexec.RecordSet {
   162  	rs, err := exec(se, allegrosql, args...)
   163  	c.Assert(err, IsNil)
   164  	return rs
   165  }
   166  
   167  func match(c *C, event []types.Causet, expected ...interface{}) {
   168  	c.Assert(len(event), Equals, len(expected))
   169  	for i := range event {
   170  		got := fmt.Sprintf("%v", event[i].GetValue())
   171  		need := fmt.Sprintf("%v", expected[i])
   172  		c.Assert(got, Equals, need)
   173  	}
   174  }
   175  
   176  func (s *testMainSuite) TestKeysNeedLock(c *C) {
   177  	rowKey := blockcodec.EncodeRowKeyWithHandle(1, ekv.IntHandle(1))
   178  	indexKey := blockcodec.EncodeIndexSeekKey(1, 1, []byte{1})
   179  	uniqueValue := make([]byte, 8)
   180  	uniqueUntouched := append(uniqueValue, '1')
   181  	nonUniqueVal := []byte{'0'}
   182  	nonUniqueUntouched := []byte{'1'}
   183  	var deleteVal []byte
   184  	rowVal := []byte{'a', 'b', 'c'}
   185  	tests := []struct {
   186  		key  []byte
   187  		val  []byte
   188  		need bool
   189  	}{
   190  		{rowKey, rowVal, true},
   191  		{rowKey, deleteVal, true},
   192  		{indexKey, nonUniqueVal, false},
   193  		{indexKey, nonUniqueUntouched, false},
   194  		{indexKey, uniqueValue, true},
   195  		{indexKey, uniqueUntouched, false},
   196  		{indexKey, deleteVal, false},
   197  	}
   198  	for _, tt := range tests {
   199  		c.Assert(keyNeedToLock(tt.key, tt.val, 0), Equals, tt.need)
   200  	}
   201  	flag := ekv.KeyFlags(1)
   202  	c.Assert(flag.HasPresumeKeyNotExists(), IsTrue)
   203  	c.Assert(keyNeedToLock(indexKey, deleteVal, flag), IsTrue)
   204  }