github.com/hdt3213/godis@v1.2.9/datastruct/dict/concurrent_test.go (about)

     1  package dict
     2  
     3  import (
     4  	"github.com/hdt3213/godis/lib/utils"
     5  	"strconv"
     6  	"sync"
     7  	"testing"
     8  )
     9  
    10  func TestConcurrentPut(t *testing.T) {
    11  	d := MakeConcurrent(0)
    12  	count := 100
    13  	var wg sync.WaitGroup
    14  	wg.Add(count)
    15  	for i := 0; i < count; i++ {
    16  		go func(i int) {
    17  			// insert
    18  			key := "k" + strconv.Itoa(i)
    19  			ret := d.Put(key, i)
    20  			if ret != 1 { // insert 1
    21  				t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key)
    22  			}
    23  			val, ok := d.Get(key)
    24  			if ok {
    25  				intVal, _ := val.(int)
    26  				if intVal != i {
    27  					t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key)
    28  				}
    29  			} else {
    30  				_, ok := d.Get(key)
    31  				t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok))
    32  			}
    33  			wg.Done()
    34  		}(i)
    35  	}
    36  	wg.Wait()
    37  }
    38  
    39  func TestConcurrentPutWithLock(t *testing.T) {
    40  	d := MakeConcurrent(0)
    41  	count := 100
    42  	var wg sync.WaitGroup
    43  	wg.Add(count)
    44  
    45  	for i := 0; i < count; i++ {
    46  		go func(i int) {
    47  			// insert
    48  			key := "k" + strconv.Itoa(i)
    49  			keys := []string{key}
    50  			d.RWLocks(keys, nil)
    51  			ret := d.PutWithLock(key, i)
    52  			if ret != 1 { // insert 1
    53  				t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key)
    54  			}
    55  			val, ok := d.GetWithLock(key)
    56  			if ok {
    57  				intVal, _ := val.(int)
    58  				if intVal != i {
    59  					t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key)
    60  				}
    61  			} else {
    62  				_, ok := d.GetWithLock(key)
    63  				t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok))
    64  			}
    65  			wg.Done()
    66  			d.RWUnLocks(keys, nil)
    67  		}(i)
    68  	}
    69  	wg.Wait()
    70  }
    71  
    72  func TestConcurrentPutIfAbsent(t *testing.T) {
    73  	d := MakeConcurrent(0)
    74  	count := 100
    75  	var wg sync.WaitGroup
    76  	wg.Add(count)
    77  	for i := 0; i < count; i++ {
    78  		go func(i int) {
    79  			// insert
    80  			key := "k" + strconv.Itoa(i)
    81  			ret := d.PutIfAbsent(key, i)
    82  			if ret != 1 { // insert 1
    83  				t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key)
    84  			}
    85  			val, ok := d.Get(key)
    86  			if ok {
    87  				intVal, _ := val.(int)
    88  				if intVal != i {
    89  					t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) +
    90  						", key: " + key)
    91  				}
    92  			} else {
    93  				_, ok := d.Get(key)
    94  				t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok))
    95  			}
    96  
    97  			// update
    98  			ret = d.PutIfAbsent(key, i*10)
    99  			if ret != 0 { // no update
   100  				t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret))
   101  			}
   102  			val, ok = d.Get(key)
   103  			if ok {
   104  				intVal, _ := val.(int)
   105  				if intVal != i {
   106  					t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key)
   107  				}
   108  			} else {
   109  				t.Error("put test failed: expected true, actual: false, key: " + key)
   110  			}
   111  			wg.Done()
   112  		}(i)
   113  	}
   114  	wg.Wait()
   115  }
   116  
   117  func TestConcurrentPutIfAbsentWithLock(t *testing.T) {
   118  	d := MakeConcurrent(0)
   119  	count := 100
   120  	var wg sync.WaitGroup
   121  	wg.Add(count)
   122  
   123  	for i := 0; i < count; i++ {
   124  		go func(i int) {
   125  			// insert
   126  			key := "k" + strconv.Itoa(i)
   127  			keys := []string{key}
   128  			d.RWLocks(keys, nil)
   129  			ret := d.PutIfAbsentWithLock(key, i)
   130  			if ret != 1 { // insert 1
   131  				t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key)
   132  			}
   133  			val, ok := d.GetWithLock(key)
   134  			if ok {
   135  				intVal, _ := val.(int)
   136  				if intVal != i {
   137  					t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) +
   138  						", key: " + key)
   139  				}
   140  			} else {
   141  				_, ok := d.GetWithLock(key)
   142  				t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok))
   143  			}
   144  
   145  			// update
   146  			ret = d.PutIfAbsentWithLock(key, i*10)
   147  			if ret != 0 { // no update
   148  				t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret))
   149  			}
   150  			val, ok = d.GetWithLock(key)
   151  			if ok {
   152  				intVal, _ := val.(int)
   153  				if intVal != i {
   154  					t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key)
   155  				}
   156  			} else {
   157  				t.Error("put test failed: expected true, actual: false, key: " + key)
   158  			}
   159  			d.RWUnLocks(keys, nil)
   160  			wg.Done()
   161  		}(i)
   162  	}
   163  	wg.Wait()
   164  }
   165  
   166  func TestConcurrentPutIfExists(t *testing.T) {
   167  	d := MakeConcurrent(0)
   168  	count := 100
   169  	var wg sync.WaitGroup
   170  	wg.Add(count)
   171  
   172  	for i := 0; i < count; i++ {
   173  		go func(i int) {
   174  			// insert
   175  			key := "k" + strconv.Itoa(i)
   176  			// insert
   177  			ret := d.PutIfExists(key, i)
   178  			if ret != 0 { // insert
   179  				t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret))
   180  			}
   181  
   182  			d.Put(key, i)
   183  			d.PutIfExists(key, 10*i)
   184  			val, ok := d.Get(key)
   185  			if ok {
   186  				intVal, _ := val.(int)
   187  				if intVal != 10*i {
   188  					t.Error("put test failed: expected " + strconv.Itoa(10*i) + ", actual: " + strconv.Itoa(intVal))
   189  				}
   190  			} else {
   191  				_, ok := d.Get(key)
   192  				t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok))
   193  			}
   194  			wg.Done()
   195  		}(i)
   196  	}
   197  	wg.Wait()
   198  }
   199  
   200  func TestConcurrentPutIfExistsWithLock(t *testing.T) {
   201  	d := MakeConcurrent(0)
   202  	count := 100
   203  	var wg sync.WaitGroup
   204  	wg.Add(count)
   205  
   206  	for i := 0; i < count; i++ {
   207  		go func(i int) {
   208  			// insert
   209  			key := "k" + strconv.Itoa(i)
   210  			keys := []string{key}
   211  			d.RWLocks(keys, nil)
   212  			// insert
   213  			ret := d.PutIfExistsWithLock(key, i)
   214  			if ret != 0 { // insert
   215  				t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret))
   216  			}
   217  			d.PutWithLock(key, i)
   218  			d.PutIfExistsWithLock(key, 10*i)
   219  			val, ok := d.GetWithLock(key)
   220  			if ok {
   221  				intVal, _ := val.(int)
   222  				if intVal != 10*i {
   223  					t.Error("put test failed: expected " + strconv.Itoa(10*i) + ", actual: " + strconv.Itoa(intVal))
   224  				}
   225  			} else {
   226  				_, ok := d.GetWithLock(key)
   227  				t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok))
   228  			}
   229  			d.RWUnLocks(keys, nil)
   230  			wg.Done()
   231  		}(i)
   232  	}
   233  	wg.Wait()
   234  }
   235  
   236  func TestConcurrentRemove(t *testing.T) {
   237  	d := MakeConcurrent(0)
   238  	totalCount := 100
   239  	// remove head node
   240  	for i := 0; i < totalCount; i++ {
   241  		// insert
   242  		key := "k" + strconv.Itoa(i)
   243  		d.Put(key, i)
   244  	}
   245  	if d.Len() != totalCount {
   246  		t.Error("put test failed: expected len is 100, actual: " + strconv.Itoa(d.Len()))
   247  	}
   248  	for i := 0; i < totalCount; i++ {
   249  		key := "k" + strconv.Itoa(i)
   250  
   251  		val, ok := d.Get(key)
   252  		if ok {
   253  			intVal, _ := val.(int)
   254  			if intVal != i {
   255  				t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal))
   256  			}
   257  		} else {
   258  			t.Error("put test failed: expected true, actual: false")
   259  		}
   260  
   261  		ret := d.Remove(key)
   262  		if ret != 1 {
   263  			t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key:" + key)
   264  		}
   265  		if d.Len() != totalCount-i-1 {
   266  			t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len()))
   267  		}
   268  		_, ok = d.Get(key)
   269  		if ok {
   270  			t.Error("remove test failed: expected true, actual false")
   271  		}
   272  		ret = d.Remove(key)
   273  		if ret != 0 {
   274  			t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret))
   275  		}
   276  		if d.Len() != totalCount-i-1 {
   277  			t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len()))
   278  		}
   279  	}
   280  
   281  	// remove tail node
   282  	d = MakeConcurrent(0)
   283  	for i := 0; i < 100; i++ {
   284  		// insert
   285  		key := "k" + strconv.Itoa(i)
   286  		d.Put(key, i)
   287  	}
   288  	for i := 9; i >= 0; i-- {
   289  		key := "k" + strconv.Itoa(i)
   290  
   291  		val, ok := d.Get(key)
   292  		if ok {
   293  			intVal, _ := val.(int)
   294  			if intVal != i {
   295  				t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal))
   296  			}
   297  		} else {
   298  			t.Error("put test failed: expected true, actual: false")
   299  		}
   300  
   301  		ret := d.Remove(key)
   302  		if ret != 1 {
   303  			t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret))
   304  		}
   305  		_, ok = d.Get(key)
   306  		if ok {
   307  			t.Error("remove test failed: expected true, actual false")
   308  		}
   309  		ret = d.Remove(key)
   310  		if ret != 0 {
   311  			t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret))
   312  		}
   313  	}
   314  
   315  	// remove middle node
   316  	d = MakeConcurrent(0)
   317  	d.Put("head", 0)
   318  	for i := 0; i < 10; i++ {
   319  		// insert
   320  		key := "k" + strconv.Itoa(i)
   321  		d.Put(key, i)
   322  	}
   323  	d.Put("tail", 0)
   324  	for i := 9; i >= 0; i-- {
   325  		key := "k" + strconv.Itoa(i)
   326  
   327  		val, ok := d.Get(key)
   328  		if ok {
   329  			intVal, _ := val.(int)
   330  			if intVal != i {
   331  				t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal))
   332  			}
   333  		} else {
   334  			t.Error("put test failed: expected true, actual: false")
   335  		}
   336  
   337  		ret := d.Remove(key)
   338  		if ret != 1 {
   339  			t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret))
   340  		}
   341  		_, ok = d.Get(key)
   342  		if ok {
   343  			t.Error("remove test failed: expected true, actual false")
   344  		}
   345  		ret = d.Remove(key)
   346  		if ret != 0 {
   347  			t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret))
   348  		}
   349  	}
   350  }
   351  
   352  func TestConcurrentRemoveWithLock(t *testing.T) {
   353  	d := MakeConcurrent(0)
   354  	totalCount := 100
   355  	// remove head node
   356  	for i := 0; i < totalCount; i++ {
   357  		// insert
   358  		key := "k" + strconv.Itoa(i)
   359  		d.PutWithLock(key, i)
   360  	}
   361  	if d.Len() != totalCount {
   362  		t.Error("put test failed: expected len is 100, actual: " + strconv.Itoa(d.Len()))
   363  	}
   364  	for i := 0; i < totalCount; i++ {
   365  		key := "k" + strconv.Itoa(i)
   366  
   367  		val, ok := d.GetWithLock(key)
   368  		if ok {
   369  			intVal, _ := val.(int)
   370  			if intVal != i {
   371  				t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal))
   372  			}
   373  		} else {
   374  			t.Error("put test failed: expected true, actual: false")
   375  		}
   376  
   377  		ret := d.RemoveWithLock(key)
   378  		if ret != 1 {
   379  			t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key:" + key)
   380  		}
   381  		if d.Len() != totalCount-i-1 {
   382  			t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len()))
   383  		}
   384  		_, ok = d.GetWithLock(key)
   385  		if ok {
   386  			t.Error("remove test failed: expected true, actual false")
   387  		}
   388  		ret = d.RemoveWithLock(key)
   389  		if ret != 0 {
   390  			t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret))
   391  		}
   392  		if d.Len() != totalCount-i-1 {
   393  			t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len()))
   394  		}
   395  	}
   396  
   397  	// remove tail node
   398  	d = MakeConcurrent(0)
   399  	for i := 0; i < 100; i++ {
   400  		// insert
   401  		key := "k" + strconv.Itoa(i)
   402  		d.PutWithLock(key, i)
   403  	}
   404  	for i := 9; i >= 0; i-- {
   405  		key := "k" + strconv.Itoa(i)
   406  
   407  		val, ok := d.GetWithLock(key)
   408  		if ok {
   409  			intVal, _ := val.(int)
   410  			if intVal != i {
   411  				t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal))
   412  			}
   413  		} else {
   414  			t.Error("put test failed: expected true, actual: false")
   415  		}
   416  
   417  		ret := d.RemoveWithLock(key)
   418  		if ret != 1 {
   419  			t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret))
   420  		}
   421  		_, ok = d.GetWithLock(key)
   422  		if ok {
   423  			t.Error("remove test failed: expected true, actual false")
   424  		}
   425  		ret = d.RemoveWithLock(key)
   426  		if ret != 0 {
   427  			t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret))
   428  		}
   429  	}
   430  
   431  	// remove middle node
   432  	d = MakeConcurrent(0)
   433  	d.Put("head", 0)
   434  	for i := 0; i < 10; i++ {
   435  		// insert
   436  		key := "k" + strconv.Itoa(i)
   437  		d.PutWithLock(key, i)
   438  	}
   439  	d.PutWithLock("tail", 0)
   440  	for i := 9; i >= 0; i-- {
   441  		key := "k" + strconv.Itoa(i)
   442  
   443  		val, ok := d.Get(key)
   444  		if ok {
   445  			intVal, _ := val.(int)
   446  			if intVal != i {
   447  				t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal))
   448  			}
   449  		} else {
   450  			t.Error("put test failed: expected true, actual: false")
   451  		}
   452  
   453  		ret := d.RemoveWithLock(key)
   454  		if ret != 1 {
   455  			t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret))
   456  		}
   457  		_, ok = d.GetWithLock(key)
   458  		if ok {
   459  			t.Error("remove test failed: expected true, actual false")
   460  		}
   461  		ret = d.RemoveWithLock(key)
   462  		if ret != 0 {
   463  			t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret))
   464  		}
   465  	}
   466  }
   467  
   468  //change t.Error remove->forEach
   469  func TestConcurrentForEach(t *testing.T) {
   470  	d := MakeConcurrent(0)
   471  	size := 100
   472  	for i := 0; i < size; i++ {
   473  		// insert
   474  		key := "k" + strconv.Itoa(i)
   475  		d.Put(key, i)
   476  	}
   477  	i := 0
   478  	d.ForEach(func(key string, value interface{}) bool {
   479  		intVal, _ := value.(int)
   480  		expectedKey := "k" + strconv.Itoa(intVal)
   481  		if key != expectedKey {
   482  			t.Error("forEach test failed: expected " + expectedKey + ", actual: " + key)
   483  		}
   484  		i++
   485  		return true
   486  	})
   487  	if i != size {
   488  		t.Error("forEach test failed: expected " + strconv.Itoa(size) + ", actual: " + strconv.Itoa(i))
   489  	}
   490  }
   491  
   492  func TestConcurrentRandomKey(t *testing.T) {
   493  	d := MakeConcurrent(0)
   494  	count := 100
   495  	for i := 0; i < count; i++ {
   496  		key := "k" + strconv.Itoa(i)
   497  		d.Put(key, i)
   498  	}
   499  	fetchSize := 10
   500  	result := d.RandomKeys(fetchSize)
   501  	if len(result) != fetchSize {
   502  		t.Errorf("expect %d random keys acturally %d", fetchSize, len(result))
   503  	}
   504  	result = d.RandomDistinctKeys(fetchSize)
   505  	distinct := make(map[string]struct{})
   506  	for _, key := range result {
   507  		distinct[key] = struct{}{}
   508  	}
   509  	if len(result) != fetchSize {
   510  		t.Errorf("expect %d random keys acturally %d", fetchSize, len(result))
   511  	}
   512  	if len(result) > len(distinct) {
   513  		t.Errorf("get duplicated keys in result")
   514  	}
   515  }
   516  
   517  func TestConcurrentDict_Keys(t *testing.T) {
   518  	d := MakeConcurrent(0)
   519  	size := 10
   520  	for i := 0; i < size; i++ {
   521  		d.Put(utils.RandString(5), utils.RandString(5))
   522  	}
   523  	if len(d.Keys()) != size {
   524  		t.Errorf("expect %d keys, actual: %d", size, len(d.Keys()))
   525  	}
   526  }