github.com/mhmtszr/concurrent-swiss-map@v1.0.8/concurrent_swiss_map_test.go (about)

     1  package csmap_test
     2  
     3  import (
     4  	"strconv"
     5  	"sync"
     6  	"testing"
     7  
     8  	csmap "github.com/mhmtszr/concurrent-swiss-map"
     9  )
    10  
    11  func TestHas(t *testing.T) {
    12  	myMap := csmap.Create[int, string]()
    13  	myMap.Store(1, "test")
    14  	if !myMap.Has(1) {
    15  		t.Fatal("1 should exists")
    16  	}
    17  }
    18  
    19  func TestLoad(t *testing.T) {
    20  	myMap := csmap.Create[int, string]()
    21  	myMap.Store(1, "test")
    22  	v, ok := myMap.Load(1)
    23  	v2, ok2 := myMap.Load(2)
    24  	if v != "test" || !ok {
    25  		t.Fatal("1 should test")
    26  	}
    27  	if v2 != "" || ok2 {
    28  		t.Fatal("2 should not exist")
    29  	}
    30  }
    31  
    32  func TestDelete(t *testing.T) {
    33  	myMap := csmap.Create[int, string]()
    34  	myMap.Store(1, "test")
    35  	ok1 := myMap.Delete(20)
    36  	ok2 := myMap.Delete(1)
    37  	if myMap.Has(1) {
    38  		t.Fatal("1 should be deleted")
    39  	}
    40  	if ok1 {
    41  		t.Fatal("ok1 should be false")
    42  	}
    43  	if !ok2 {
    44  		t.Fatal("ok2 should be true")
    45  	}
    46  }
    47  
    48  func TestSetIfAbsent(t *testing.T) {
    49  	myMap := csmap.Create[int, string]()
    50  	myMap.SetIfAbsent(1, "test")
    51  	if !myMap.Has(1) {
    52  		t.Fatal("1 should be exist")
    53  	}
    54  }
    55  
    56  func TestSetIfPresent(t *testing.T) {
    57  	myMap := csmap.Create[int, string]()
    58  	myMap.SetIfPresent(1, "test")
    59  	if myMap.Has(1) {
    60  		t.Fatal("1 should be not exist")
    61  	}
    62  
    63  	myMap.Store(1, "test")
    64  	myMap.SetIfPresent(1, "new-test")
    65  	val, _ := myMap.Load(1)
    66  	if val != "new-test" {
    67  		t.Fatal("val should be new-test")
    68  	}
    69  }
    70  
    71  func TestSetIf(t *testing.T) {
    72  	myMap := csmap.Create[int, string]()
    73  	valueA := "value a"
    74  	myMap.SetIf(1, func(previousVale string, previousFound bool) (value string, set bool) {
    75  		// operate like  a SetIfAbsent...
    76  		if !previousFound {
    77  			return valueA, true
    78  		}
    79  		return "", false
    80  	})
    81  	value, _ := myMap.Load(1)
    82  	if value != valueA {
    83  		t.Fatal("value should value a")
    84  	}
    85  
    86  	myMap.SetIf(1, func(previousVale string, previousFound bool) (value string, set bool) {
    87  		// operate like  a SetIfAbsent...
    88  		if !previousFound {
    89  			return "bad", true
    90  		}
    91  		return "", false
    92  	})
    93  	value, _ = myMap.Load(1)
    94  	if value != valueA {
    95  		t.Fatal("value should value a")
    96  	}
    97  }
    98  
    99  func TestDeleteIf(t *testing.T) {
   100  	myMap := csmap.Create[int, string]()
   101  	myMap.Store(1, "value b")
   102  	ok1 := myMap.DeleteIf(20, func(value string) bool {
   103  		t.Fatal("condition function should not have been called")
   104  		return false
   105  	})
   106  	if ok1 {
   107  		t.Fatal("ok1 should be false")
   108  	}
   109  
   110  	ok2 := myMap.DeleteIf(1, func(value string) bool {
   111  		if value != "value b" {
   112  			t.Fatal("condition function arg should be tests")
   113  		}
   114  		return false // don't delete
   115  	})
   116  	if ok2 {
   117  		t.Fatal("ok1 should be false")
   118  	}
   119  
   120  	ok3 := myMap.DeleteIf(1, func(value string) bool {
   121  		if value != "value b" {
   122  			t.Fatal("condition function arg should be tests")
   123  		}
   124  		return true // delete the entry
   125  	})
   126  	if !ok3 {
   127  		t.Fatal("ok2 should be true")
   128  	}
   129  }
   130  
   131  func TestCount(t *testing.T) {
   132  	myMap := csmap.Create[int, string]()
   133  	myMap.SetIfAbsent(1, "test")
   134  	myMap.SetIfAbsent(2, "test2")
   135  	if myMap.Count() != 2 {
   136  		t.Fatal("count should be 2")
   137  	}
   138  }
   139  
   140  func TestIsEmpty(t *testing.T) {
   141  	myMap := csmap.Create[int, string]()
   142  	if !myMap.IsEmpty() {
   143  		t.Fatal("map should be empty")
   144  	}
   145  }
   146  
   147  func TestRangeStop(t *testing.T) {
   148  	myMap := csmap.Create[int, string](
   149  		csmap.WithShardCount[int, string](1),
   150  	)
   151  	myMap.SetIfAbsent(1, "test")
   152  	myMap.SetIfAbsent(2, "test2")
   153  	myMap.SetIfAbsent(3, "test2")
   154  	total := 0
   155  	myMap.Range(func(key int, value string) (stop bool) {
   156  		total++
   157  		return true
   158  	})
   159  	if total != 1 {
   160  		t.Fatal("total should be 1")
   161  	}
   162  }
   163  
   164  func TestRange(t *testing.T) {
   165  	myMap := csmap.Create[int, string]()
   166  	myMap.SetIfAbsent(1, "test")
   167  	myMap.SetIfAbsent(2, "test2")
   168  	total := 0
   169  	myMap.Range(func(key int, value string) (stop bool) {
   170  		total++
   171  		return
   172  	})
   173  	if total != 2 {
   174  		t.Fatal("total should be 2")
   175  	}
   176  }
   177  
   178  func TestCustomHasherWithRange(t *testing.T) {
   179  	myMap := csmap.Create[int, string](
   180  		csmap.WithCustomHasher[int, string](func(key int) uint64 {
   181  			return 0
   182  		}),
   183  	)
   184  	myMap.SetIfAbsent(1, "test")
   185  	myMap.SetIfAbsent(2, "test2")
   186  	myMap.SetIfAbsent(3, "test2")
   187  	myMap.SetIfAbsent(4, "test2")
   188  	total := 0
   189  	myMap.Range(func(key int, value string) (stop bool) {
   190  		total++
   191  		return true
   192  	})
   193  	if total != 1 {
   194  		t.Fatal("total should be 1, because currently range stops current shard only.")
   195  	}
   196  }
   197  
   198  func TestDeleteFromRange(t *testing.T) {
   199  	myMap := csmap.Create[string, int](
   200  		csmap.WithSize[string, int](1024),
   201  	)
   202  
   203  	myMap.Store("aaa", 10)
   204  	myMap.Store("aab", 11)
   205  	myMap.Store("aac", 15)
   206  	myMap.Store("aad", 124)
   207  	myMap.Store("aaf", 987)
   208  
   209  	myMap.Range(func(key string, value int) (stop bool) {
   210  		if value > 20 {
   211  			myMap.Delete(key)
   212  		}
   213  		return false
   214  	})
   215  	if myMap.Count() != 3 {
   216  		t.Fatal("total should be 3, because currently range deletes values that bigger than 20.")
   217  	}
   218  }
   219  
   220  func TestMarshal(t *testing.T) {
   221  	myMap := csmap.Create[string, int](
   222  		csmap.WithSize[string, int](1024),
   223  	)
   224  
   225  	myMap.Store("aaa", 10)
   226  	myMap.Store("aab", 11)
   227  
   228  	b, _ := myMap.MarshalJSON()
   229  
   230  	newMap := csmap.Create[string, int](
   231  		csmap.WithSize[string, int](1024),
   232  	)
   233  
   234  	_ = newMap.UnmarshalJSON(b)
   235  
   236  	if myMap.Count() != 2 || !myMap.Has("aaa") || !myMap.Has("aab") {
   237  		t.Fatal("count should be 2 after unmarshal")
   238  	}
   239  }
   240  
   241  func TestBasicConcurrentWriteDeleteCount(t *testing.T) {
   242  	myMap := csmap.Create[int, string](
   243  		csmap.WithShardCount[int, string](32),
   244  		csmap.WithSize[int, string](1000),
   245  	)
   246  
   247  	var wg sync.WaitGroup
   248  	wg.Add(1000000)
   249  	for i := 0; i < 1000000; i++ {
   250  		i := i
   251  		go func() {
   252  			defer wg.Done()
   253  			myMap.Store(i, strconv.Itoa(i))
   254  		}()
   255  	}
   256  	wg.Wait()
   257  	wg.Add(1000000)
   258  	for i := 0; i < 1000000; i++ {
   259  		i := i
   260  		go func() {
   261  			defer wg.Done()
   262  			if !myMap.Has(i) {
   263  				t.Error(strconv.Itoa(i) + " should exist")
   264  				return
   265  			}
   266  		}()
   267  	}
   268  
   269  	wg.Wait()
   270  	wg.Add(1000000)
   271  
   272  	for i := 0; i < 1000000; i++ {
   273  		i := i
   274  		go func() {
   275  			defer wg.Done()
   276  			myMap.Delete(i)
   277  		}()
   278  	}
   279  
   280  	wg.Wait()
   281  	wg.Add(1000000)
   282  
   283  	for i := 0; i < 1000000; i++ {
   284  		i := i
   285  		go func() {
   286  			defer wg.Done()
   287  			if myMap.Has(i) {
   288  				t.Error(strconv.Itoa(i) + " should not exist")
   289  				return
   290  			}
   291  		}()
   292  	}
   293  
   294  	wg.Wait()
   295  }
   296  
   297  func TestClear(t *testing.T) {
   298  	myMap := csmap.Create[int, string]()
   299  	loop := 10000
   300  	for i := 0; i < loop; i++ {
   301  		myMap.Store(i, "test")
   302  	}
   303  
   304  	myMap.Clear()
   305  
   306  	if !myMap.IsEmpty() {
   307  		t.Fatal("count should be true")
   308  	}
   309  
   310  	// store again
   311  	for i := 0; i < loop; i++ {
   312  		myMap.Store(i, "test")
   313  	}
   314  
   315  	// get again
   316  	for i := 0; i < loop; i++ {
   317  		val, ok := myMap.Load(i)
   318  		if ok != true {
   319  			t.Fatal("ok should be true")
   320  		}
   321  
   322  		if val != "test" {
   323  			t.Fatal("val should be test")
   324  		}
   325  	}
   326  
   327  	// check again
   328  	count := myMap.Count()
   329  	if count != loop {
   330  		t.Fatal("count should be 1000")
   331  	}
   332  }