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 }