github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/store/store_test.go (about)

     1  // Copyright 2015 PingCAP, 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 store
    15  
    16  import (
    17  	"flag"
    18  	"fmt"
    19  	"os"
    20  	"strconv"
    21  	"sync"
    22  	"sync/atomic"
    23  	"testing"
    24  
    25  	"github.com/insionng/yougam/libraries/ngaut/log"
    26  	. "github.com/insionng/yougam/libraries/pingcap/check"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/kv"
    29  	"github.com/insionng/yougam/libraries/pingcap/tidb/store/localstore"
    30  	"github.com/insionng/yougam/libraries/pingcap/tidb/store/localstore/boltdb"
    31  	"github.com/insionng/yougam/libraries/pingcap/tidb/store/localstore/goleveldb"
    32  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testleak"
    33  )
    34  
    35  var (
    36  	testStore     = flag.String("teststore", "memory", "test store name, [memory, goleveldb, boltdb, hbase]")
    37  	testStorePath = flag.String("testpath", "testkv", "test storage path")
    38  )
    39  
    40  const (
    41  	startIndex = 0
    42  	testCount  = 2
    43  	indexStep  = 2
    44  )
    45  
    46  func TestT(t *testing.T) {
    47  	TestingT(t)
    48  }
    49  
    50  var _ = Suite(&testKVSuite{})
    51  
    52  type testKVSuite struct {
    53  	s kv.Storage
    54  }
    55  
    56  func (s *testKVSuite) SetUpSuite(c *C) {
    57  	store, err := tidb.NewStore(fmt.Sprintf("%s://%s", *testStore, *testStorePath))
    58  	c.Assert(err, IsNil)
    59  	s.s = store
    60  
    61  	cacheS, _ := tidb.NewStore(fmt.Sprintf("%s://%s", *testStore, *testStorePath))
    62  	c.Assert(cacheS, Equals, store)
    63  	log.SetLevelByString("warn")
    64  }
    65  
    66  func (s *testKVSuite) TearDownSuite(c *C) {
    67  	log.SetLevelByString("debug")
    68  	err := s.s.Close()
    69  	c.Assert(err, IsNil)
    70  }
    71  
    72  func insertData(c *C, txn kv.Transaction) {
    73  	for i := startIndex; i < testCount; i++ {
    74  		val := encodeInt(i * indexStep)
    75  		err := txn.Set(val, val)
    76  		c.Assert(err, IsNil)
    77  	}
    78  }
    79  
    80  func mustDel(c *C, txn kv.Transaction) {
    81  	for i := startIndex; i < testCount; i++ {
    82  		val := encodeInt(i * indexStep)
    83  		err := txn.Delete(val)
    84  		c.Assert(err, IsNil)
    85  	}
    86  }
    87  
    88  func encodeInt(n int) []byte {
    89  	return []byte(fmt.Sprintf("%010d", n))
    90  }
    91  
    92  func decodeInt(s []byte) int {
    93  	var n int
    94  	fmt.Sscanf(string(s), "%010d", &n)
    95  	return n
    96  }
    97  
    98  func valToStr(c *C, iter kv.Iterator) string {
    99  	val := iter.Value()
   100  	return string(val)
   101  }
   102  
   103  func checkSeek(c *C, txn kv.Transaction) {
   104  	for i := startIndex; i < testCount; i++ {
   105  		val := encodeInt(i * indexStep)
   106  		iter, err := txn.Seek(val)
   107  		c.Assert(err, IsNil)
   108  		c.Assert([]byte(iter.Key()), BytesEquals, val)
   109  		c.Assert(decodeInt([]byte(valToStr(c, iter))), Equals, i*indexStep)
   110  		iter.Close()
   111  	}
   112  
   113  	// Test iterator Next()
   114  	for i := startIndex; i < testCount-1; i++ {
   115  		val := encodeInt(i * indexStep)
   116  		iter, err := txn.Seek(val)
   117  		c.Assert(err, IsNil)
   118  		c.Assert([]byte(iter.Key()), BytesEquals, val)
   119  		c.Assert(valToStr(c, iter), Equals, string(val))
   120  
   121  		err = iter.Next()
   122  		c.Assert(err, IsNil)
   123  		c.Assert(iter.Valid(), IsTrue)
   124  
   125  		val = encodeInt((i + 1) * indexStep)
   126  		c.Assert([]byte(iter.Key()), BytesEquals, val)
   127  		c.Assert(valToStr(c, iter), Equals, string(val))
   128  		iter.Close()
   129  	}
   130  
   131  	// Non exist and beyond maximum seek test
   132  	iter, err := txn.Seek(encodeInt(testCount * indexStep))
   133  	c.Assert(err, IsNil)
   134  	c.Assert(iter.Valid(), IsFalse)
   135  
   136  	// Non exist but between existing keys seek test,
   137  	// it returns the smallest key that larger than the one we are seeking
   138  	inBetween := encodeInt((testCount-1)*indexStep - 1)
   139  	last := encodeInt((testCount - 1) * indexStep)
   140  	iter, err = txn.Seek(inBetween)
   141  	c.Assert(err, IsNil)
   142  	c.Assert(iter.Valid(), IsTrue)
   143  	c.Assert([]byte(iter.Key()), Not(BytesEquals), inBetween)
   144  	c.Assert([]byte(iter.Key()), BytesEquals, last)
   145  	iter.Close()
   146  }
   147  
   148  func mustNotGet(c *C, txn kv.Transaction) {
   149  	for i := startIndex; i < testCount; i++ {
   150  		s := encodeInt(i * indexStep)
   151  		_, err := txn.Get(s)
   152  		c.Assert(err, NotNil)
   153  	}
   154  }
   155  
   156  func mustGet(c *C, txn kv.Transaction) {
   157  	for i := startIndex; i < testCount; i++ {
   158  		s := encodeInt(i * indexStep)
   159  		val, err := txn.Get(s)
   160  		c.Assert(err, IsNil)
   161  		c.Assert(string(val), Equals, string(s))
   162  	}
   163  }
   164  
   165  func (s *testKVSuite) TestGetSet(c *C) {
   166  	defer testleak.AfterTest(c)()
   167  	txn, err := s.s.Begin()
   168  	c.Assert(err, IsNil)
   169  
   170  	insertData(c, txn)
   171  
   172  	mustGet(c, txn)
   173  
   174  	// Check transaction results
   175  	err = txn.Commit()
   176  	c.Assert(err, IsNil)
   177  
   178  	txn, err = s.s.Begin()
   179  	c.Assert(err, IsNil)
   180  	defer txn.Commit()
   181  
   182  	mustGet(c, txn)
   183  	mustDel(c, txn)
   184  }
   185  
   186  func (s *testKVSuite) TestSeek(c *C) {
   187  	defer testleak.AfterTest(c)()
   188  	txn, err := s.s.Begin()
   189  	c.Assert(err, IsNil)
   190  
   191  	insertData(c, txn)
   192  	checkSeek(c, txn)
   193  
   194  	// Check transaction results
   195  	err = txn.Commit()
   196  	c.Assert(err, IsNil)
   197  
   198  	txn, err = s.s.Begin()
   199  	c.Assert(err, IsNil)
   200  	defer txn.Commit()
   201  
   202  	checkSeek(c, txn)
   203  	mustDel(c, txn)
   204  }
   205  
   206  func (s *testKVSuite) TestInc(c *C) {
   207  	defer testleak.AfterTest(c)()
   208  	txn, err := s.s.Begin()
   209  	c.Assert(err, IsNil)
   210  
   211  	key := []byte("incKey")
   212  	n, err := kv.IncInt64(txn, key, 100)
   213  	c.Assert(err, IsNil)
   214  	c.Assert(n, Equals, int64(100))
   215  
   216  	// Check transaction results
   217  	err = txn.Commit()
   218  	c.Assert(err, IsNil)
   219  
   220  	txn, err = s.s.Begin()
   221  	c.Assert(err, IsNil)
   222  
   223  	n, err = kv.IncInt64(txn, key, -200)
   224  	c.Assert(err, IsNil)
   225  	c.Assert(n, Equals, int64(-100))
   226  
   227  	err = txn.Delete(key)
   228  	c.Assert(err, IsNil)
   229  
   230  	n, err = kv.IncInt64(txn, key, 100)
   231  	c.Assert(err, IsNil)
   232  	c.Assert(n, Equals, int64(100))
   233  
   234  	err = txn.Delete(key)
   235  	c.Assert(err, IsNil)
   236  
   237  	err = txn.Commit()
   238  	c.Assert(err, IsNil)
   239  }
   240  
   241  func (s *testKVSuite) TestDelete(c *C) {
   242  	defer testleak.AfterTest(c)()
   243  	txn, err := s.s.Begin()
   244  	c.Assert(err, IsNil)
   245  
   246  	insertData(c, txn)
   247  
   248  	mustDel(c, txn)
   249  
   250  	mustNotGet(c, txn)
   251  	txn.Commit()
   252  
   253  	// Try get
   254  	txn, err = s.s.Begin()
   255  	c.Assert(err, IsNil)
   256  
   257  	mustNotGet(c, txn)
   258  
   259  	// Insert again
   260  	insertData(c, txn)
   261  	txn.Commit()
   262  
   263  	// Delete all
   264  	txn, err = s.s.Begin()
   265  	c.Assert(err, IsNil)
   266  
   267  	mustDel(c, txn)
   268  	txn.Commit()
   269  
   270  	txn, err = s.s.Begin()
   271  	c.Assert(err, IsNil)
   272  
   273  	mustNotGet(c, txn)
   274  	txn.Commit()
   275  }
   276  
   277  func (s *testKVSuite) TestDelete2(c *C) {
   278  	defer testleak.AfterTest(c)()
   279  	txn, err := s.s.Begin()
   280  	c.Assert(err, IsNil)
   281  	val := []byte("test")
   282  	txn.Set([]byte("DATA_test_tbl_department_record__0000000001_0003"), val)
   283  	txn.Set([]byte("DATA_test_tbl_department_record__0000000001_0004"), val)
   284  	txn.Set([]byte("DATA_test_tbl_department_record__0000000002_0003"), val)
   285  	txn.Set([]byte("DATA_test_tbl_department_record__0000000002_0004"), val)
   286  	txn.Commit()
   287  
   288  	// Delete all
   289  	txn, err = s.s.Begin()
   290  	c.Assert(err, IsNil)
   291  
   292  	it, err := txn.Seek([]byte("DATA_test_tbl_department_record__0000000001_0003"))
   293  	c.Assert(err, IsNil)
   294  	for it.Valid() {
   295  		err = txn.Delete([]byte(it.Key()))
   296  		c.Assert(err, IsNil)
   297  		err = it.Next()
   298  		c.Assert(err, IsNil)
   299  	}
   300  	txn.Commit()
   301  
   302  	txn, err = s.s.Begin()
   303  	c.Assert(err, IsNil)
   304  	it, _ = txn.Seek([]byte("DATA_test_tbl_department_record__000000000"))
   305  	c.Assert(it.Valid(), IsFalse)
   306  	txn.Commit()
   307  }
   308  
   309  func (s *testKVSuite) TestSetNil(c *C) {
   310  	defer testleak.AfterTest(c)()
   311  	txn, err := s.s.Begin()
   312  	defer txn.Commit()
   313  	c.Assert(err, IsNil)
   314  	err = txn.Set([]byte("1"), nil)
   315  	c.Assert(err, NotNil)
   316  }
   317  
   318  func (s *testKVSuite) TestBasicSeek(c *C) {
   319  	defer testleak.AfterTest(c)()
   320  	txn, err := s.s.Begin()
   321  	c.Assert(err, IsNil)
   322  	txn.Set([]byte("1"), []byte("1"))
   323  	txn.Commit()
   324  	txn, err = s.s.Begin()
   325  	c.Assert(err, IsNil)
   326  	defer txn.Commit()
   327  
   328  	it, err := txn.Seek([]byte("2"))
   329  	c.Assert(err, IsNil)
   330  	c.Assert(it.Valid(), Equals, false)
   331  	txn.Delete([]byte("1"))
   332  }
   333  
   334  func (s *testKVSuite) TestBasicTable(c *C) {
   335  	defer testleak.AfterTest(c)()
   336  	txn, err := s.s.Begin()
   337  	c.Assert(err, IsNil)
   338  	for i := 1; i < 5; i++ {
   339  		b := []byte(strconv.Itoa(i))
   340  		txn.Set(b, b)
   341  	}
   342  	txn.Commit()
   343  	txn, err = s.s.Begin()
   344  	c.Assert(err, IsNil)
   345  	defer txn.Commit()
   346  
   347  	err = txn.Set([]byte("1"), []byte("1"))
   348  	c.Assert(err, IsNil)
   349  
   350  	it, err := txn.Seek([]byte("0"))
   351  	c.Assert(err, IsNil)
   352  	c.Assert(string(it.Key()), Equals, "1")
   353  
   354  	err = txn.Set([]byte("0"), []byte("0"))
   355  	c.Assert(err, IsNil)
   356  	it, err = txn.Seek([]byte("0"))
   357  	c.Assert(err, IsNil)
   358  	c.Assert(string(it.Key()), Equals, "0")
   359  	err = txn.Delete([]byte("0"))
   360  	c.Assert(err, IsNil)
   361  
   362  	txn.Delete([]byte("1"))
   363  	it, err = txn.Seek([]byte("0"))
   364  	c.Assert(err, IsNil)
   365  	c.Assert(string(it.Key()), Equals, "2")
   366  
   367  	err = txn.Delete([]byte("3"))
   368  	c.Assert(err, IsNil)
   369  	it, err = txn.Seek([]byte("2"))
   370  	c.Assert(err, IsNil)
   371  	c.Assert(string(it.Key()), Equals, "2")
   372  
   373  	it, err = txn.Seek([]byte("3"))
   374  	c.Assert(err, IsNil)
   375  	c.Assert(string(it.Key()), Equals, "4")
   376  	err = txn.Delete([]byte("2"))
   377  	c.Assert(err, IsNil)
   378  	err = txn.Delete([]byte("4"))
   379  	c.Assert(err, IsNil)
   380  }
   381  
   382  func (s *testKVSuite) TestRollback(c *C) {
   383  	defer testleak.AfterTest(c)()
   384  	txn, err := s.s.Begin()
   385  	c.Assert(err, IsNil)
   386  
   387  	err = txn.Rollback()
   388  	c.Assert(err, IsNil)
   389  
   390  	txn, err = s.s.Begin()
   391  	c.Assert(err, IsNil)
   392  
   393  	insertData(c, txn)
   394  
   395  	mustGet(c, txn)
   396  
   397  	err = txn.Rollback()
   398  	c.Assert(err, IsNil)
   399  
   400  	txn, err = s.s.Begin()
   401  	c.Assert(err, IsNil)
   402  	defer txn.Commit()
   403  
   404  	for i := startIndex; i < testCount; i++ {
   405  		_, err := txn.Get([]byte(strconv.Itoa(i)))
   406  		c.Assert(err, NotNil)
   407  	}
   408  }
   409  
   410  func (s *testKVSuite) TestSeekMin(c *C) {
   411  	defer testleak.AfterTest(c)()
   412  	kvs := []struct {
   413  		key   string
   414  		value string
   415  	}{
   416  		{"DATA_test_main_db_tbl_tbl_test_record__00000000000000000001", "lock-version"},
   417  		{"DATA_test_main_db_tbl_tbl_test_record__00000000000000000001_0002", "1"},
   418  		{"DATA_test_main_db_tbl_tbl_test_record__00000000000000000001_0003", "hello"},
   419  		{"DATA_test_main_db_tbl_tbl_test_record__00000000000000000002", "lock-version"},
   420  		{"DATA_test_main_db_tbl_tbl_test_record__00000000000000000002_0002", "2"},
   421  		{"DATA_test_main_db_tbl_tbl_test_record__00000000000000000002_0003", "hello"},
   422  	}
   423  
   424  	txn, err := s.s.Begin()
   425  	c.Assert(err, IsNil)
   426  	for _, kv := range kvs {
   427  		txn.Set([]byte(kv.key), []byte(kv.value))
   428  	}
   429  
   430  	it, err := txn.Seek(nil)
   431  	for it.Valid() {
   432  		fmt.Printf("%s, %s\n", it.Key(), it.Value())
   433  		it.Next()
   434  	}
   435  
   436  	it, err = txn.Seek([]byte("DATA_test_main_db_tbl_tbl_test_record__00000000000000000000"))
   437  	c.Assert(err, IsNil)
   438  	c.Assert(string(it.Key()), Equals, "DATA_test_main_db_tbl_tbl_test_record__00000000000000000001")
   439  
   440  	for _, kv := range kvs {
   441  		txn.Delete([]byte(kv.key))
   442  	}
   443  }
   444  
   445  func (s *testKVSuite) TestConditionIfNotExist(c *C) {
   446  	defer testleak.AfterTest(c)()
   447  	var success int64
   448  	cnt := 100
   449  	b := []byte("1")
   450  	var wg sync.WaitGroup
   451  	wg.Add(cnt)
   452  	for i := 0; i < cnt; i++ {
   453  		go func() {
   454  			defer wg.Done()
   455  			txn, err := s.s.Begin()
   456  			c.Assert(err, IsNil)
   457  			err = txn.Set(b, b)
   458  			if err != nil {
   459  				return
   460  			}
   461  			err = txn.Commit()
   462  			if err == nil {
   463  				atomic.AddInt64(&success, 1)
   464  			}
   465  		}()
   466  	}
   467  	wg.Wait()
   468  	// At least one txn can success.
   469  	c.Assert(success, Greater, int64(0))
   470  
   471  	// Clean up
   472  	txn, err := s.s.Begin()
   473  	c.Assert(err, IsNil)
   474  	err = txn.Delete(b)
   475  	c.Assert(err, IsNil)
   476  	err = txn.Commit()
   477  	c.Assert(err, IsNil)
   478  }
   479  
   480  func (s *testKVSuite) TestConditionIfEqual(c *C) {
   481  	defer testleak.AfterTest(c)()
   482  	var success int64
   483  	cnt := 100
   484  	b := []byte("1")
   485  	var wg sync.WaitGroup
   486  	wg.Add(cnt)
   487  
   488  	txn, err := s.s.Begin()
   489  	c.Assert(err, IsNil)
   490  	txn.Set(b, b)
   491  	err = txn.Commit()
   492  	c.Assert(err, IsNil)
   493  
   494  	for i := 0; i < cnt; i++ {
   495  		go func() {
   496  			defer wg.Done()
   497  			// Use txn1/err1 instead of txn/err is
   498  			// to pass `go tool vet -shadow` check.
   499  			txn1, err1 := s.s.Begin()
   500  			c.Assert(err1, IsNil)
   501  			txn1.Set(b, []byte("newValue"))
   502  			err1 = txn1.Commit()
   503  			if err1 == nil {
   504  				atomic.AddInt64(&success, 1)
   505  			}
   506  		}()
   507  	}
   508  	wg.Wait()
   509  	c.Assert(success, Greater, int64(0))
   510  
   511  	// Clean up
   512  	txn, err = s.s.Begin()
   513  	c.Assert(err, IsNil)
   514  	err = txn.Delete(b)
   515  	c.Assert(err, IsNil)
   516  	err = txn.Commit()
   517  	c.Assert(err, IsNil)
   518  }
   519  
   520  func (s *testKVSuite) TestConditionUpdate(c *C) {
   521  	defer testleak.AfterTest(c)()
   522  	txn, err := s.s.Begin()
   523  	c.Assert(err, IsNil)
   524  	txn.Delete([]byte("b"))
   525  	kv.IncInt64(txn, []byte("a"), 1)
   526  	err = txn.Commit()
   527  	c.Assert(err, IsNil)
   528  }
   529  
   530  func (s *testKVSuite) TestDBClose(c *C) {
   531  	defer testleak.AfterTest(c)()
   532  	path := "memory:test"
   533  	d := localstore.Driver{
   534  		Driver: goleveldb.MemoryDriver{},
   535  	}
   536  	store, err := d.Open(path)
   537  	c.Assert(err, IsNil)
   538  
   539  	txn, err := store.Begin()
   540  	c.Assert(err, IsNil)
   541  
   542  	err = txn.Set([]byte("a"), []byte("b"))
   543  	c.Assert(err, IsNil)
   544  
   545  	err = txn.Commit()
   546  	c.Assert(err, IsNil)
   547  
   548  	ver, err := store.CurrentVersion()
   549  	c.Assert(err, IsNil)
   550  	c.Assert(kv.MaxVersion.Cmp(ver), Equals, 1)
   551  
   552  	snap, err := store.GetSnapshot(kv.MaxVersion)
   553  	c.Assert(err, IsNil)
   554  
   555  	_, err = snap.Get([]byte("a"))
   556  	c.Assert(err, IsNil)
   557  
   558  	txn, err = store.Begin()
   559  	c.Assert(err, IsNil)
   560  
   561  	err = store.Close()
   562  	c.Assert(err, IsNil)
   563  
   564  	_, err = store.Begin()
   565  	c.Assert(err, NotNil)
   566  
   567  	_, err = store.GetSnapshot(kv.MaxVersion)
   568  	c.Assert(err, NotNil)
   569  
   570  	err = txn.Set([]byte("a"), []byte("b"))
   571  	c.Assert(err, IsNil)
   572  
   573  	err = txn.Commit()
   574  	c.Assert(err, NotNil)
   575  
   576  	snap.Release()
   577  }
   578  
   579  func (s *testKVSuite) TestBoltDBDeadlock(c *C) {
   580  	defer testleak.AfterTest(c)()
   581  	d := localstore.Driver{
   582  		Driver: boltdb.Driver{},
   583  	}
   584  	path := "boltdb_test"
   585  	defer os.Remove(path)
   586  	store, err := d.Open(path)
   587  	c.Assert(err, IsNil)
   588  	defer store.Close()
   589  
   590  	kv.RunInNewTxn(store, false, func(txn kv.Transaction) error {
   591  		txn.Set([]byte("a"), []byte("0"))
   592  		kv.IncInt64(txn, []byte("a"), 1)
   593  
   594  		kv.RunInNewTxn(store, false, func(txn kv.Transaction) error {
   595  			txn.Set([]byte("b"), []byte("0"))
   596  			kv.IncInt64(txn, []byte("b"), 1)
   597  
   598  			return nil
   599  		})
   600  
   601  		return nil
   602  	})
   603  
   604  	kv.RunInNewTxn(store, false, func(txn kv.Transaction) error {
   605  		n, err := kv.GetInt64(txn, []byte("a"))
   606  		c.Assert(err, IsNil)
   607  		c.Assert(n, Equals, int64(1))
   608  
   609  		n, err = kv.GetInt64(txn, []byte("b"))
   610  		c.Assert(err, IsNil)
   611  		c.Assert(n, Equals, int64(1))
   612  		return nil
   613  	})
   614  }
   615  
   616  func (s *testKVSuite) TestIsolationInc(c *C) {
   617  	defer testleak.AfterTest(c)()
   618  	threadCnt := 4
   619  
   620  	ids := make(map[int64]struct{}, threadCnt*100)
   621  	var m sync.Mutex
   622  	var wg sync.WaitGroup
   623  
   624  	wg.Add(threadCnt)
   625  	for i := 0; i < threadCnt; i++ {
   626  		go func() {
   627  			defer wg.Done()
   628  			for j := 0; j < 100; j++ {
   629  				var id int64
   630  				err := kv.RunInNewTxn(s.s, true, func(txn kv.Transaction) error {
   631  					var err1 error
   632  					id, err1 = kv.IncInt64(txn, []byte("key"), 1)
   633  					return err1
   634  				})
   635  				c.Assert(err, IsNil)
   636  
   637  				m.Lock()
   638  				_, ok := ids[id]
   639  				ids[id] = struct{}{}
   640  				m.Unlock()
   641  				c.Assert(ok, IsFalse)
   642  			}
   643  		}()
   644  	}
   645  
   646  	wg.Wait()
   647  
   648  	// delete
   649  	txn, err := s.s.Begin()
   650  	c.Assert(err, IsNil)
   651  	defer txn.Commit()
   652  	txn.Delete([]byte("key"))
   653  }
   654  
   655  func (s *testKVSuite) TestIsolationMultiInc(c *C) {
   656  	defer testleak.AfterTest(c)()
   657  	threadCnt := 4
   658  	incCnt := 100
   659  	keyCnt := 4
   660  
   661  	keys := make([][]byte, 0, keyCnt)
   662  	for i := 0; i < keyCnt; i++ {
   663  		keys = append(keys, []byte(fmt.Sprintf("test_key_%d", i)))
   664  	}
   665  
   666  	var wg sync.WaitGroup
   667  
   668  	wg.Add(threadCnt)
   669  	for i := 0; i < threadCnt; i++ {
   670  		go func() {
   671  			defer wg.Done()
   672  			for j := 0; j < incCnt; j++ {
   673  				err1 := kv.RunInNewTxn(s.s, true, func(txn kv.Transaction) error {
   674  					for _, key := range keys {
   675  						_, err2 := kv.IncInt64(txn, key, 1)
   676  						if err2 != nil {
   677  							return err2
   678  						}
   679  					}
   680  
   681  					return nil
   682  				})
   683  				c.Assert(err1, IsNil)
   684  			}
   685  		}()
   686  	}
   687  
   688  	wg.Wait()
   689  
   690  	err := kv.RunInNewTxn(s.s, false, func(txn kv.Transaction) error {
   691  		for _, key := range keys {
   692  			id, err1 := kv.GetInt64(txn, key)
   693  			if err1 != nil {
   694  				return err1
   695  			}
   696  			c.Assert(id, Equals, int64(threadCnt*incCnt))
   697  			txn.Delete(key)
   698  		}
   699  		return nil
   700  	})
   701  	c.Assert(err, IsNil)
   702  }