github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/filesort/filesort_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 filesort
    15  
    16  import (
    17  	"io/ioutil"
    18  	"math/rand"
    19  	"os"
    20  	"testing"
    21  	"time"
    22  
    23  	. "github.com/whtcorpsinc/check"
    24  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    25  	"github.com/whtcorpsinc/milevadb/types"
    26  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    27  )
    28  
    29  func TestT(t *testing.T) {
    30  	CustomVerboseFlag = true
    31  	TestingT(t)
    32  }
    33  
    34  var _ = Suite(&testFileSortSuite{})
    35  
    36  type testFileSortSuite struct {
    37  }
    38  
    39  func nextRow(r *rand.Rand, keySize int, valSize int) (key []types.Causet, val []types.Causet, handle int64) {
    40  	key = make([]types.Causet, keySize)
    41  	for i := range key {
    42  		key[i] = types.NewCauset(r.Int())
    43  	}
    44  
    45  	val = make([]types.Causet, valSize)
    46  	for j := range val {
    47  		val[j] = types.NewCauset(r.Int())
    48  	}
    49  
    50  	handle = r.Int63()
    51  	return
    52  }
    53  
    54  func (s *testFileSortSuite) TestLessThan(c *C) {
    55  	defer testleak.AfterTest(c)()
    56  
    57  	sc := new(stmtctx.StatementContext)
    58  
    59  	d0 := types.NewCauset(0)
    60  	d1 := types.NewCauset(1)
    61  
    62  	tblOneDeferredCauset := []struct {
    63  		Arg1 []types.Causet
    64  		Arg2 []types.Causet
    65  		Arg3 []bool
    66  		Ret  bool
    67  	}{
    68  		{[]types.Causet{d0}, []types.Causet{d0}, []bool{false}, false},
    69  		{[]types.Causet{d0}, []types.Causet{d1}, []bool{false}, true},
    70  		{[]types.Causet{d1}, []types.Causet{d0}, []bool{false}, false},
    71  		{[]types.Causet{d0}, []types.Causet{d0}, []bool{true}, false},
    72  		{[]types.Causet{d0}, []types.Causet{d1}, []bool{true}, false},
    73  		{[]types.Causet{d1}, []types.Causet{d0}, []bool{true}, true},
    74  	}
    75  
    76  	for _, t := range tblOneDeferredCauset {
    77  		ret, err := lessThan(sc, t.Arg1, t.Arg2, t.Arg3)
    78  		c.Assert(err, IsNil)
    79  		c.Assert(ret, Equals, t.Ret)
    80  	}
    81  
    82  	tblTwoDeferredCausets := []struct {
    83  		Arg1 []types.Causet
    84  		Arg2 []types.Causet
    85  		Arg3 []bool
    86  		Ret  bool
    87  	}{
    88  		{[]types.Causet{d0, d0}, []types.Causet{d1, d1}, []bool{false, false}, true},
    89  		{[]types.Causet{d0, d1}, []types.Causet{d1, d1}, []bool{false, false}, true},
    90  		{[]types.Causet{d0, d0}, []types.Causet{d1, d1}, []bool{false, false}, true},
    91  		{[]types.Causet{d0, d0}, []types.Causet{d0, d1}, []bool{false, false}, true},
    92  		{[]types.Causet{d0, d1}, []types.Causet{d0, d1}, []bool{false, false}, false},
    93  		{[]types.Causet{d0, d1}, []types.Causet{d0, d0}, []bool{false, false}, false},
    94  		{[]types.Causet{d1, d0}, []types.Causet{d0, d1}, []bool{false, false}, false},
    95  		{[]types.Causet{d1, d1}, []types.Causet{d0, d1}, []bool{false, false}, false},
    96  		{[]types.Causet{d1, d1}, []types.Causet{d0, d0}, []bool{false, false}, false},
    97  	}
    98  
    99  	for _, t := range tblTwoDeferredCausets {
   100  		ret, err := lessThan(sc, t.Arg1, t.Arg2, t.Arg3)
   101  		c.Assert(err, IsNil)
   102  		c.Assert(ret, Equals, t.Ret)
   103  	}
   104  }
   105  
   106  func (s *testFileSortSuite) TestInMemory(c *C) {
   107  	defer testleak.AfterTest(c)()
   108  
   109  	seed := rand.NewSource(time.Now().UnixNano())
   110  	r := rand.New(seed)
   111  
   112  	sc := new(stmtctx.StatementContext)
   113  	keySize := r.Intn(10) + 1 // random int in range [1, 10]
   114  	valSize := r.Intn(20) + 1 // random int in range [1, 20]
   115  	bufSize := 40             // hold up to 40 items per file
   116  	byDesc := make([]bool, keySize)
   117  	for i := range byDesc {
   118  		byDesc[i] = r.Intn(2) == 0
   119  	}
   120  
   121  	var (
   122  		err    error
   123  		fs     *FileSorter
   124  		pkey   []types.Causet
   125  		key    []types.Causet
   126  		tmFIDelir string
   127  		ret    bool
   128  	)
   129  
   130  	tmFIDelir, err = ioutil.TemFIDelir("", "util_filesort_test")
   131  	c.Assert(err, IsNil)
   132  
   133  	fsBuilder := new(Builder)
   134  	fs, err = fsBuilder.SetSC(sc).SetSchema(keySize, valSize).SetBuf(bufSize).SetWorkers(1).SetDesc(byDesc).SetDir(tmFIDelir).Build()
   135  	c.Assert(err, IsNil)
   136  	defer fs.Close()
   137  
   138  	nRows := r.Intn(bufSize-1) + 1 // random int in range [1, bufSize - 1]
   139  	for i := 1; i <= nRows; i++ {
   140  		err = fs.Input(nextRow(r, keySize, valSize))
   141  		c.Assert(err, IsNil)
   142  	}
   143  
   144  	pkey, _, _, err = fs.Output()
   145  	c.Assert(err, IsNil)
   146  	for i := 1; i < nRows; i++ {
   147  		key, _, _, err = fs.Output()
   148  		c.Assert(err, IsNil)
   149  		ret, err = lessThan(sc, key, pkey, byDesc)
   150  		c.Assert(err, IsNil)
   151  		c.Assert(ret, IsFalse)
   152  		pkey = key
   153  	}
   154  }
   155  
   156  func (s *testFileSortSuite) TestMultipleFiles(c *C) {
   157  	defer testleak.AfterTest(c)()
   158  
   159  	seed := rand.NewSource(time.Now().UnixNano())
   160  	r := rand.New(seed)
   161  
   162  	sc := new(stmtctx.StatementContext)
   163  	keySize := r.Intn(10) + 1 // random int in range [1, 10]
   164  	valSize := r.Intn(20) + 1 // random int in range [1, 20]
   165  	bufSize := 40             // hold up to 40 items per file
   166  	byDesc := make([]bool, keySize)
   167  	for i := range byDesc {
   168  		byDesc[i] = r.Intn(2) == 0
   169  	}
   170  
   171  	var (
   172  		err    error
   173  		fs     *FileSorter
   174  		pkey   []types.Causet
   175  		key    []types.Causet
   176  		tmFIDelir string
   177  		ret    bool
   178  	)
   179  
   180  	tmFIDelir, err = ioutil.TemFIDelir("", "util_filesort_test")
   181  	c.Assert(err, IsNil)
   182  
   183  	fsBuilder := new(Builder)
   184  
   185  	// Test for basic function.
   186  	_, err = fsBuilder.Build()
   187  	c.Assert(err.Error(), Equals, "StatementContext is nil")
   188  	fsBuilder.SetSC(sc)
   189  	_, err = fsBuilder.Build()
   190  	c.Assert(err.Error(), Equals, "key size is not positive")
   191  	fsBuilder.SetDesc(byDesc)
   192  	_, err = fsBuilder.Build()
   193  	c.Assert(err.Error(), Equals, "mismatch in key size and byDesc slice")
   194  	fsBuilder.SetSchema(keySize, valSize)
   195  	_, err = fsBuilder.Build()
   196  	c.Assert(err.Error(), Equals, "buffer size is not positive")
   197  	fsBuilder.SetBuf(bufSize)
   198  	_, err = fsBuilder.Build()
   199  	c.Assert(err.Error(), Equals, "tmFIDelir does not exist")
   200  	fsBuilder.SetDir(tmFIDelir)
   201  
   202  	fs, err = fsBuilder.SetWorkers(1).Build()
   203  	c.Assert(err, IsNil)
   204  	defer fs.Close()
   205  
   206  	nRows := (r.Intn(bufSize) + 1) * (r.Intn(10) + 2)
   207  	for i := 1; i <= nRows; i++ {
   208  		err = fs.Input(nextRow(r, keySize, valSize))
   209  		c.Assert(err, IsNil)
   210  	}
   211  
   212  	pkey, _, _, err = fs.Output()
   213  	c.Assert(err, IsNil)
   214  	for i := 1; i < nRows; i++ {
   215  		key, _, _, err = fs.Output()
   216  		c.Assert(err, IsNil)
   217  		ret, err = lessThan(sc, key, pkey, byDesc)
   218  		c.Assert(err, IsNil)
   219  		c.Assert(ret, IsFalse)
   220  		pkey = key
   221  	}
   222  }
   223  
   224  func (s *testFileSortSuite) TestMultipleWorkers(c *C) {
   225  	defer testleak.AfterTest(c)()
   226  
   227  	seed := rand.NewSource(time.Now().UnixNano())
   228  	r := rand.New(seed)
   229  
   230  	sc := new(stmtctx.StatementContext)
   231  	keySize := r.Intn(10) + 1 // random int in range [1, 10]
   232  	valSize := r.Intn(20) + 1 // random int in range [1, 20]
   233  	bufSize := 40             // hold up to 40 items per file
   234  	byDesc := make([]bool, keySize)
   235  	for i := range byDesc {
   236  		byDesc[i] = r.Intn(2) == 0
   237  	}
   238  
   239  	var (
   240  		err    error
   241  		fs     *FileSorter
   242  		pkey   []types.Causet
   243  		key    []types.Causet
   244  		tmFIDelir string
   245  		ret    bool
   246  	)
   247  
   248  	tmFIDelir, err = ioutil.TemFIDelir("", "util_filesort_test")
   249  	c.Assert(err, IsNil)
   250  
   251  	fsBuilder := new(Builder)
   252  	fs, err = fsBuilder.SetSC(sc).SetSchema(keySize, valSize).SetBuf(bufSize).SetWorkers(4).SetDesc(byDesc).SetDir(tmFIDelir).Build()
   253  	c.Assert(err, IsNil)
   254  	defer fs.Close()
   255  
   256  	nRows := (r.Intn(bufSize) + 1) * (r.Intn(10) + 2)
   257  	for i := 1; i <= nRows; i++ {
   258  		err = fs.Input(nextRow(r, keySize, valSize))
   259  		c.Assert(err, IsNil)
   260  	}
   261  
   262  	pkey, _, _, err = fs.Output()
   263  	c.Assert(err, IsNil)
   264  	for i := 1; i < nRows; i++ {
   265  		key, _, _, err = fs.Output()
   266  		c.Assert(err, IsNil)
   267  		ret, err = lessThan(sc, key, pkey, byDesc)
   268  		c.Assert(err, IsNil)
   269  		c.Assert(ret, IsFalse)
   270  		pkey = key
   271  	}
   272  }
   273  
   274  func (s *testFileSortSuite) TestClose(c *C) {
   275  	defer testleak.AfterTest(c)()
   276  
   277  	seed := rand.NewSource(time.Now().UnixNano())
   278  	r := rand.New(seed)
   279  
   280  	sc := new(stmtctx.StatementContext)
   281  	keySize := 2
   282  	valSize := 2
   283  	bufSize := 40
   284  	byDesc := []bool{false, false}
   285  
   286  	var (
   287  		err     error
   288  		fs0     *FileSorter
   289  		fs1     *FileSorter
   290  		tmFIDelir0 string
   291  		tmFIDelir1 string
   292  		errmsg  = "FileSorter has been closed"
   293  	)
   294  
   295  	// Prepare two FileSorter instances for tests
   296  	fsBuilder := new(Builder)
   297  	tmFIDelir0, err = ioutil.TemFIDelir("", "util_filesort_test")
   298  	c.Assert(err, IsNil)
   299  	fs0, err = fsBuilder.SetSC(sc).SetSchema(keySize, valSize).SetBuf(bufSize).SetWorkers(1).SetDesc(byDesc).SetDir(tmFIDelir0).Build()
   300  	c.Assert(err, IsNil)
   301  	defer fs0.Close()
   302  
   303  	tmFIDelir1, err = ioutil.TemFIDelir("", "util_filesort_test")
   304  	c.Assert(err, IsNil)
   305  	fs1, err = fsBuilder.SetSC(sc).SetSchema(keySize, valSize).SetBuf(bufSize).SetWorkers(1).SetDesc(byDesc).SetDir(tmFIDelir1).Build()
   306  	c.Assert(err, IsNil)
   307  	defer fs1.Close()
   308  
   309  	// 1. Close after some Input
   310  	err = fs0.Input(nextRow(r, keySize, valSize))
   311  	c.Assert(err, IsNil)
   312  
   313  	err = fs0.Close()
   314  	c.Assert(err, IsNil)
   315  
   316  	_, err = os.Stat(tmFIDelir0)
   317  	c.Assert(os.IsNotExist(err), IsTrue)
   318  
   319  	_, _, _, err = fs0.Output()
   320  	c.Assert(err, ErrorMatches, errmsg)
   321  
   322  	err = fs0.Input(nextRow(r, keySize, valSize))
   323  	c.Assert(err, ErrorMatches, errmsg)
   324  
   325  	err = fs0.Close()
   326  	c.Assert(err, IsNil)
   327  
   328  	// 2. Close after some Output
   329  	err = fs1.Input(nextRow(r, keySize, valSize))
   330  	c.Assert(err, IsNil)
   331  	err = fs1.Input(nextRow(r, keySize, valSize))
   332  	c.Assert(err, IsNil)
   333  
   334  	_, _, _, err = fs1.Output()
   335  	c.Assert(err, IsNil)
   336  
   337  	err = fs1.Close()
   338  	c.Assert(err, IsNil)
   339  
   340  	_, err = os.Stat(tmFIDelir1)
   341  	c.Assert(os.IsNotExist(err), IsTrue)
   342  
   343  	_, _, _, err = fs1.Output()
   344  	c.Assert(err, ErrorMatches, errmsg)
   345  
   346  	err = fs1.Input(nextRow(r, keySize, valSize))
   347  	c.Assert(err, ErrorMatches, errmsg)
   348  
   349  	err = fs1.Close()
   350  	c.Assert(err, IsNil)
   351  }
   352  
   353  func (s *testFileSortSuite) TestMismatchedUsage(c *C) {
   354  	defer testleak.AfterTest(c)()
   355  
   356  	seed := rand.NewSource(time.Now().UnixNano())
   357  	r := rand.New(seed)
   358  
   359  	sc := new(stmtctx.StatementContext)
   360  	keySize := 2
   361  	valSize := 2
   362  	bufSize := 40
   363  	byDesc := []bool{false, false}
   364  
   365  	var (
   366  		err    error
   367  		fs0    *FileSorter
   368  		fs1    *FileSorter
   369  		key    []types.Causet
   370  		tmFIDelir string
   371  		errmsg = "call input after output"
   372  	)
   373  
   374  	// Prepare two FileSorter instances for tests
   375  	fsBuilder := new(Builder)
   376  	tmFIDelir, err = ioutil.TemFIDelir("", "util_filesort_test")
   377  	c.Assert(err, IsNil)
   378  	fs0, err = fsBuilder.SetSC(sc).SetSchema(keySize, valSize).SetBuf(bufSize).SetWorkers(1).SetDesc(byDesc).SetDir(tmFIDelir).Build()
   379  	c.Assert(err, IsNil)
   380  	defer fs0.Close()
   381  
   382  	tmFIDelir, err = ioutil.TemFIDelir("", "util_filesort_test")
   383  	c.Assert(err, IsNil)
   384  	fs1, err = fsBuilder.SetSC(sc).SetSchema(keySize, valSize).SetBuf(bufSize).SetWorkers(1).SetDesc(byDesc).SetDir(tmFIDelir).Build()
   385  	c.Assert(err, IsNil)
   386  	defer fs1.Close()
   387  
   388  	// 1. call Output after fetched all rows
   389  	err = fs0.Input(nextRow(r, keySize, valSize))
   390  	c.Assert(err, IsNil)
   391  
   392  	key, _, _, err = fs0.Output()
   393  	c.Assert(err, IsNil)
   394  	c.Assert(key, NotNil)
   395  
   396  	key, _, _, err = fs0.Output()
   397  	c.Assert(err, IsNil)
   398  	c.Assert(key, IsNil)
   399  
   400  	// 2. call Input after Output
   401  	err = fs1.Input(nextRow(r, keySize, valSize))
   402  	c.Assert(err, IsNil)
   403  
   404  	key, _, _, err = fs1.Output()
   405  	c.Assert(err, IsNil)
   406  	c.Assert(key, NotNil)
   407  
   408  	err = fs1.Input(nextRow(r, keySize, valSize))
   409  	c.Assert(err, ErrorMatches, errmsg)
   410  }