github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/concurrent/cmap/concurrent_map_test.go (about)

     1  package cmap
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"hash/fnv"
     7  	"sort"
     8  	"strconv"
     9  	"testing"
    10  )
    11  
    12  type Animal struct {
    13  	name string
    14  }
    15  
    16  func TestMapCreation(t *testing.T) {
    17  	m := New(32)
    18  	if m == nil {
    19  		t.Error("map is null.")
    20  	}
    21  
    22  	if m.Count() != 0 {
    23  		t.Error("new map should be empty.")
    24  	}
    25  }
    26  
    27  func TestInsert(t *testing.T) {
    28  	m := New(32)
    29  	elephant := Animal{"elephant"}
    30  	monkey := Animal{"monkey"}
    31  
    32  	m.Set("elephant", elephant)
    33  	m.Set("monkey", monkey)
    34  
    35  	if m.Count() != 2 {
    36  		t.Error("map should contain exactly two elements.")
    37  	}
    38  }
    39  
    40  func TestInsertAbsent(t *testing.T) {
    41  	m := New(32)
    42  	elephant := Animal{"elephant"}
    43  	monkey := Animal{"monkey"}
    44  
    45  	m.SetIfAbsent("elephant", elephant)
    46  	if ok, _ := m.SetIfAbsent("elephant", monkey); ok {
    47  		t.Error("map set a new value even the entry is already present")
    48  	}
    49  }
    50  func TestSetIfAbsentCb(t *testing.T) {
    51  	m := New(32)
    52  	cb := func(i ...interface{}) (interface{}, error) {
    53  		if i[0].(int) == 1 {
    54  			return nil, errors.New("ERR")
    55  		}
    56  		return i[0], nil
    57  	}
    58  	ok, v, err := m.SetIfAbsentCb("1", cb, 1)
    59  	if err == nil || ok || v != nil {
    60  		t.Error("SetIfAbsentCb 应返回错误")
    61  	}
    62  	ok, v, err = m.SetIfAbsentCb("2", cb, 2)
    63  	if !ok || v == nil || v.(int) != 2 || err != nil {
    64  		t.Error("SetIfAbsentCb 应返回正确结果")
    65  	}
    66  	if m.Count() != 1 {
    67  		t.Error("SetIfAbsentCb 未设置成功")
    68  	}
    69  	if v, ok := m.Get("2"); !ok || v.(int) != 2 {
    70  		t.Error("SetIfAbsentCb 设置的值错误")
    71  	}
    72  	ok, v, err = m.SetIfAbsentCb("2", cb, 2)
    73  
    74  	if ok || v == nil || err != nil {
    75  		t.Error("SetIfAbsentCb 值已存在时返回结果错误")
    76  	}
    77  
    78  }
    79  
    80  func TestGet(t *testing.T) {
    81  	m := New(32)
    82  
    83  	// Get a missing element.
    84  	val, ok := m.Get("Money")
    85  
    86  	if ok == true {
    87  		t.Error("ok should be false when item is missing from map.")
    88  	}
    89  
    90  	if val != nil {
    91  		t.Error("Missing values should return as null.")
    92  	}
    93  
    94  	elephant := Animal{"elephant"}
    95  	m.Set("elephant", elephant)
    96  
    97  	// Retrieve inserted element.
    98  
    99  	tmp, ok := m.Get("elephant")
   100  	elephant = tmp.(Animal) // Type assertion.
   101  
   102  	if ok == false {
   103  		t.Error("ok should be true for item stored within the map.")
   104  	}
   105  
   106  	if &elephant == nil {
   107  		t.Error("expecting an element, not null.")
   108  	}
   109  
   110  	if elephant.name != "elephant" {
   111  		t.Error("item was modified.")
   112  	}
   113  }
   114  
   115  func TestHas(t *testing.T) {
   116  	m := New(32)
   117  
   118  	// Get a missing element.
   119  	if m.Has("Money") == true {
   120  		t.Error("element shouldn't exists")
   121  	}
   122  
   123  	elephant := Animal{"elephant"}
   124  	m.Set("elephant", elephant)
   125  
   126  	if m.Has("elephant") == false {
   127  		t.Error("element exists, expecting Has to return True.")
   128  	}
   129  }
   130  
   131  func TestRemove(t *testing.T) {
   132  	m := New(32)
   133  
   134  	monkey := Animal{"monkey"}
   135  	m.Set("monkey", monkey)
   136  
   137  	m.Remove("monkey")
   138  
   139  	if m.Count() != 0 {
   140  		t.Error("Expecting count to be zero once item was removed.")
   141  	}
   142  
   143  	temp, ok := m.Get("monkey")
   144  
   145  	if ok != false {
   146  		t.Error("Expecting ok to be false for missing items.")
   147  	}
   148  
   149  	if temp != nil {
   150  		t.Error("Expecting item to be nil after its removal.")
   151  	}
   152  
   153  	// Remove a none existing element.
   154  	m.Remove("noone")
   155  }
   156  
   157  func TestPop(t *testing.T) {
   158  	m := New(32)
   159  
   160  	monkey := Animal{"monkey"}
   161  	m.Set("monkey", monkey)
   162  
   163  	v, exists := m.Pop("monkey")
   164  
   165  	if !exists {
   166  		t.Error("Pop didn't find a monkey.")
   167  	}
   168  
   169  	m1, ok := v.(Animal)
   170  
   171  	if !ok || m1 != monkey {
   172  		t.Error("Pop found something else, but monkey.")
   173  	}
   174  
   175  	v2, exists2 := m.Pop("monkey")
   176  	m1, ok = v2.(Animal)
   177  
   178  	if exists2 || ok || m1 == monkey {
   179  		t.Error("Pop keeps finding monkey")
   180  	}
   181  
   182  	if m.Count() != 0 {
   183  		t.Error("Expecting count to be zero once item was Pop'ed.")
   184  	}
   185  
   186  	temp, ok := m.Get("monkey")
   187  
   188  	if ok != false {
   189  		t.Error("Expecting ok to be false for missing items.")
   190  	}
   191  
   192  	if temp != nil {
   193  		t.Error("Expecting item to be nil after its removal.")
   194  	}
   195  }
   196  
   197  func TestCount(t *testing.T) {
   198  	m := New(32)
   199  	for i := 0; i < 100; i++ {
   200  		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
   201  	}
   202  
   203  	if m.Count() != 100 {
   204  		t.Error("Expecting 100 element within map.")
   205  	}
   206  }
   207  
   208  func TestIsEmpty(t *testing.T) {
   209  	m := New(32)
   210  
   211  	if m.IsEmpty() == false {
   212  		t.Error("new map should be empty")
   213  	}
   214  
   215  	m.Set("elephant", Animal{"elephant"})
   216  
   217  	if m.IsEmpty() != false {
   218  		t.Error("map shouldn't be empty.")
   219  	}
   220  }
   221  
   222  func TestIterator(t *testing.T) {
   223  	m := New(32)
   224  
   225  	// Insert 100 elements.
   226  	for i := 0; i < 100; i++ {
   227  		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
   228  	}
   229  
   230  	counter := 0
   231  	// Iterate over elements.
   232  	for item := range m.Iter() {
   233  		val := item.Val
   234  
   235  		if val == nil {
   236  			t.Error("Expecting an object.")
   237  		}
   238  		counter++
   239  	}
   240  
   241  	if counter != 100 {
   242  		t.Error("We should have counted 100 elements.")
   243  	}
   244  }
   245  
   246  func TestBufferedIterator(t *testing.T) {
   247  	m := New(32)
   248  
   249  	// Insert 100 elements.
   250  	for i := 0; i < 100; i++ {
   251  		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
   252  	}
   253  
   254  	counter := 0
   255  	// Iterate over elements.
   256  	for item := range m.IterBuffered() {
   257  		val := item.Val
   258  
   259  		if val == nil {
   260  			t.Error("Expecting an object.")
   261  		}
   262  		counter++
   263  	}
   264  
   265  	if counter != 100 {
   266  		t.Error("We should have counted 100 elements.")
   267  	}
   268  }
   269  
   270  func TestIterCb(t *testing.T) {
   271  	m := New(32)
   272  
   273  	// Insert 100 elements.
   274  	for i := 0; i < 100; i++ {
   275  		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
   276  	}
   277  
   278  	counter := 0
   279  	// Iterate over elements.
   280  	m.IterCb(func(key string, v interface{}) bool {
   281  		_, ok := v.(Animal)
   282  		if !ok {
   283  			t.Error("Expecting an animal object")
   284  		}
   285  
   286  		counter++
   287  		return true
   288  	})
   289  	if counter != 100 {
   290  		t.Error("We should have counted 100 elements.")
   291  	}
   292  }
   293  
   294  func TestItems(t *testing.T) {
   295  	m := New(32)
   296  
   297  	// Insert 100 elements.
   298  	for i := 0; i < 100; i++ {
   299  		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
   300  	}
   301  
   302  	items := m.Items()
   303  
   304  	if len(items) != 100 {
   305  		t.Error("We should have counted 100 elements.")
   306  	}
   307  }
   308  
   309  func TestConcurrent(t *testing.T) {
   310  	m := New(32)
   311  	ch := make(chan int)
   312  	const iterations = 1000
   313  	var a [iterations]int
   314  
   315  	// Using go routines insert 1000 ints into our map.
   316  	go func() {
   317  		for i := 0; i < iterations/2; i++ {
   318  			// Add item to map.
   319  			m.Set(strconv.Itoa(i), i)
   320  
   321  			// Retrieve item from map.
   322  			val, _ := m.Get(strconv.Itoa(i))
   323  
   324  			// Write to channel inserted value.
   325  			ch <- val.(int)
   326  		} // Call go routine with current index.
   327  	}()
   328  
   329  	go func() {
   330  		for i := iterations / 2; i < iterations; i++ {
   331  			// Add item to map.
   332  			m.Set(strconv.Itoa(i), i)
   333  
   334  			// Retrieve item from map.
   335  			val, _ := m.Get(strconv.Itoa(i))
   336  
   337  			// Write to channel inserted value.
   338  			ch <- val.(int)
   339  		} // Call go routine with current index.
   340  	}()
   341  
   342  	// Wait for all go routines to finish.
   343  	counter := 0
   344  	for elem := range ch {
   345  		a[counter] = elem
   346  		counter++
   347  		if counter == iterations {
   348  			break
   349  		}
   350  	}
   351  
   352  	// Sorts array, will make is simpler to verify all inserted values we're returned.
   353  	sort.Ints(a[0:iterations])
   354  
   355  	// Make sure map contains 1000 elements.
   356  	if m.Count() != iterations {
   357  		t.Error("Expecting 1000 elements.")
   358  	}
   359  
   360  	// Make sure all inserted values we're fetched from map.
   361  	for i := 0; i < iterations; i++ {
   362  		if i != a[i] {
   363  			t.Error("missing value", i)
   364  		}
   365  	}
   366  }
   367  
   368  func TestJsonMarshal(t *testing.T) {
   369  	expected := "{\"a\":1,\"b\":2}"
   370  	m := New(2)
   371  	m.Set("a", 1)
   372  	m.Set("b", 2)
   373  	j, err := json.Marshal(m)
   374  	if err != nil {
   375  		t.Error(err)
   376  	}
   377  
   378  	if string(j) != expected {
   379  		t.Error("json", string(j), "differ from expected", expected)
   380  		return
   381  	}
   382  }
   383  
   384  func TestKeys(t *testing.T) {
   385  	m := New(32)
   386  
   387  	// Insert 100 elements.
   388  	for i := 0; i < 100; i++ {
   389  		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
   390  	}
   391  
   392  	keys := m.Keys()
   393  	if len(keys) != 100 {
   394  		t.Error("We should have counted 100 elements.")
   395  	}
   396  }
   397  
   398  func TestMInsert(t *testing.T) {
   399  	animals := map[string]interface{}{
   400  		"elephant": Animal{"elephant"},
   401  		"monkey":   Animal{"monkey"},
   402  	}
   403  	m := New(32)
   404  	m.MSet(animals)
   405  
   406  	if m.Count() != 2 {
   407  		t.Error("map should contain exactly two elements.")
   408  	}
   409  }
   410  func TestClear(t *testing.T) {
   411  	animals := map[string]interface{}{
   412  		"elephant": Animal{"elephant"},
   413  		"monkey":   Animal{"monkey"},
   414  	}
   415  	m := New(32)
   416  	m.MSet(animals)
   417  	m.Clear()
   418  
   419  	if m.Count() != 0 {
   420  		t.Error("map should contain 0 element.")
   421  	}
   422  }
   423  func TestPopAll(t *testing.T) {
   424  	animals := map[string]interface{}{
   425  		"elephant": Animal{"elephant"},
   426  		"monkey":   Animal{"monkey"},
   427  	}
   428  	m := New(32)
   429  	m.MSet(animals)
   430  
   431  	nAnimals := m.PopAll()
   432  
   433  	if m.Count() != 0 {
   434  		t.Error("PopAll 后元素个数应为0")
   435  	}
   436  
   437  	if len(nAnimals) != len(animals) {
   438  		t.Error("PopAll 返回的元素个数错误", len(nAnimals), len(animals))
   439  	}
   440  	for k, v := range nAnimals {
   441  		if va, ok := animals[k]; !ok || v != va {
   442  			t.Error("PopAll 返回的元素值错误")
   443  		}
   444  	}
   445  }
   446  
   447  func TestFnv32(t *testing.T) {
   448  	key := []byte("ABC")
   449  
   450  	hasher := fnv.New32()
   451  	hasher.Write(key)
   452  	if fnv32(string(key)) != hasher.Sum32() {
   453  		t.Errorf("Bundled fnv32 produced %d, expected result from hash/fnv32 is %d", fnv32(string(key)), hasher.Sum32())
   454  	}
   455  }
   456  
   457  func TestUpsert(t *testing.T) {
   458  	dolphin := Animal{"dolphin"}
   459  	whale := Animal{"whale"}
   460  	tiger := Animal{"tiger"}
   461  	lion := Animal{"lion"}
   462  
   463  	cb := func(exists bool, valueInMap interface{}, newValue interface{}) interface{} {
   464  		nv := newValue.(Animal)
   465  		if !exists {
   466  			return []Animal{nv}
   467  		}
   468  		res := valueInMap.([]Animal)
   469  		return append(res, nv)
   470  	}
   471  
   472  	m := New(32)
   473  	m.Set("marine", []Animal{dolphin})
   474  	m.Upsert("marine", whale, cb)
   475  	m.Upsert("predator", tiger, cb)
   476  	m.Upsert("predator", lion, cb)
   477  
   478  	if m.Count() != 2 {
   479  		t.Error("map should contain exactly two elements.")
   480  	}
   481  
   482  	compare := func(a, b []Animal) bool {
   483  		if a == nil || b == nil {
   484  			return false
   485  		}
   486  
   487  		if len(a) != len(b) {
   488  			return false
   489  		}
   490  
   491  		for i, v := range a {
   492  			if v != b[i] {
   493  				return false
   494  			}
   495  		}
   496  		return true
   497  	}
   498  
   499  	marineAnimals, ok := m.Get("marine")
   500  	if !ok || !compare(marineAnimals.([]Animal), []Animal{dolphin, whale}) {
   501  		t.Error("Set, then Upsert failed")
   502  	}
   503  
   504  	predators, ok := m.Get("predator")
   505  	if !ok || !compare(predators.([]Animal), []Animal{tiger, lion}) {
   506  		t.Error("Upsert, then Upsert failed")
   507  	}
   508  }