github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/tests/map_test.go (about)

     1  package tests
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  )
     7  
     8  // These tests exercise the api of maps and built-in functions that operate on maps
     9  func Test_MapLiteral(t *testing.T) {
    10  	myMap := map[string]int{"test": 0, "key": 1, "charm": 2}
    11  
    12  	assertMapApi(t, myMap)
    13  }
    14  
    15  func Test_MapLiteralAssign(t *testing.T) {
    16  	myMap := map[string]int{}
    17  	myMap["test"] = 0
    18  	myMap["key"] = 1
    19  	myMap["charm"] = 2
    20  
    21  	assertMapApi(t, myMap)
    22  }
    23  
    24  func Test_MapMake(t *testing.T) {
    25  	myMap := make(map[string]int)
    26  	myMap["test"] = 0
    27  	myMap["key"] = 1
    28  	myMap["charm"] = 2
    29  
    30  	assertMapApi(t, myMap)
    31  }
    32  
    33  func Test_MapMakeSizeHint(t *testing.T) {
    34  	myMap := make(map[string]int, 3)
    35  	myMap["test"] = 0
    36  	myMap["key"] = 1
    37  	myMap["charm"] = 2
    38  
    39  	assertMapApi(t, myMap)
    40  }
    41  
    42  func Test_MapNew(t *testing.T) {
    43  	myMap := new(map[string]int)
    44  	if *myMap != nil {
    45  		t.Errorf("Got: %v, Want: nil when made with new()", *myMap)
    46  	}
    47  }
    48  
    49  func Test_MapType(t *testing.T) {
    50  	defer func() {
    51  		if err := recover(); err == nil {
    52  			t.Error("assignment on nil map should panic")
    53  		} else {
    54  			str := err.(error).Error()
    55  			if !strings.Contains(str, "assignment to entry in nil map") {
    56  				t.Errorf("nil map assignment Got: %s, Want: assigning to a nil map", str)
    57  			}
    58  		}
    59  	}()
    60  
    61  	var myMap map[string]int
    62  	if myMap != nil {
    63  		t.Errorf("map declared with var, Got: %v, Want: nil", myMap)
    64  	}
    65  
    66  	myMap["key"] = 666
    67  }
    68  
    69  func Test_MapLenPrecedence(t *testing.T) {
    70  	// This test verifies that the expression len(m) compiles to is evaluated
    71  	// correctly in the context of the enclosing expression.
    72  	m := make(map[string]string)
    73  
    74  	if len(m) != 0 {
    75  		t.Errorf("inline len Got: %d, Want: 0", len(m))
    76  	}
    77  
    78  	i := len(m)
    79  	if i != 0 {
    80  		t.Errorf("assigned len Got: %d, Want: 0", i)
    81  	}
    82  }
    83  
    84  func Test_MapRangeMutation(t *testing.T) {
    85  	// This test verifies that all of a map is iterated, even if the map is modified during iteration.
    86  
    87  	myMap := map[string]int{"one": 1, "two": 2, "three": 3}
    88  
    89  	var seenKeys []string
    90  
    91  	for k := range myMap {
    92  		seenKeys = append(seenKeys, k)
    93  		if k == "two" {
    94  			delete(myMap, k)
    95  		}
    96  	}
    97  
    98  	if len(seenKeys) != 3 {
    99  		t.Errorf("iteration seenKeys len Got: %d, Want: 3", len(seenKeys))
   100  	}
   101  }
   102  
   103  func Test_MapRangeNil(t *testing.T) {
   104  	// Tests that loops on nil maps do not error.
   105  	i := 0
   106  	var m map[string]int
   107  	for k, v := range m {
   108  		_, _ = k, v
   109  		i++
   110  	}
   111  
   112  	if i > 0 {
   113  		t.Error("Got: Loops happened on a nil map, Want: no looping")
   114  	}
   115  }
   116  
   117  func Test_MapDelete(t *testing.T) {
   118  	var nilMap map[string]string
   119  	m := map[string]string{"key": "value"}
   120  
   121  	delete(nilMap, "key") // noop
   122  	delete(m, "key")
   123  	if m["key"] == "value" {
   124  		t.Error("Got: entry still set, Want: should have been deleted")
   125  	}
   126  	delete(m, "key") // noop
   127  }
   128  
   129  func assertMapApi(t *testing.T, myMap map[string]int) {
   130  	if len(myMap) != 3 {
   131  		t.Errorf("initial len of map Got: %d, Want: 3", len(myMap))
   132  	}
   133  
   134  	var keys []string
   135  	var values []int
   136  
   137  	for k, v := range myMap {
   138  		keys = append(keys, k)
   139  		values = append(values, v)
   140  	}
   141  
   142  	if len(keys) != 3 || !containsString(keys, "test") || !containsString(keys, "key") || !containsString(keys, "charm") {
   143  		t.Error("range did not contain the correct keys")
   144  	}
   145  
   146  	if len(values) != 3 || !containsInt(values, 0) || !containsInt(values, 1) || !containsInt(values, 2) {
   147  		t.Error("range did not contain the correct values")
   148  	}
   149  
   150  	if myMap["test"] != 0 {
   151  		t.Errorf("test value Got: %d, Want: 0", myMap["test"])
   152  	}
   153  	if myMap["key"] != 1 {
   154  		t.Errorf("key value Got: %d, Want: 1", myMap["key"])
   155  	}
   156  	if myMap["missing"] != 0 {
   157  		t.Errorf("missing value Got: %d, Want: 0", myMap["missing"])
   158  	}
   159  
   160  	charm, found := myMap["charm"]
   161  	if charm != 2 {
   162  		t.Errorf("charm value Got: %d, Want: 2", charm)
   163  	}
   164  	if !found {
   165  		t.Error("charm should be found")
   166  	}
   167  
   168  	missing2, found := myMap["missing"]
   169  	if missing2 != 0 {
   170  		t.Errorf("missing value Got: %d, Want: 0", missing2)
   171  	}
   172  	if found {
   173  		t.Error("absent key should not be found")
   174  	}
   175  
   176  	delete(myMap, "missing")
   177  	if len(myMap) != 3 {
   178  		t.Errorf("len after noop delete Got: %d , Want: 3", len(myMap))
   179  	}
   180  
   181  	delete(myMap, "charm")
   182  	if len(myMap) != 2 {
   183  		t.Errorf("len after delete Got: %d, Want: 2", len(myMap))
   184  	}
   185  
   186  	myMap["add"] = 3
   187  	if len(myMap) != 3 {
   188  		t.Errorf("len after assign by key Got: %d, Want: 3", len(myMap))
   189  	}
   190  	if myMap["add"] != 3 {
   191  		t.Errorf("add value Got: %d, Want: 3", myMap["add"])
   192  	}
   193  
   194  	myMap["add"] = 10
   195  	if len(myMap) != 3 {
   196  		t.Errorf("len after update by key Got: %d, Want: 3", len(myMap))
   197  	}
   198  	if myMap["add"] != 10 {
   199  		t.Errorf("add value Got: %d, Want: 10", myMap["add"])
   200  	}
   201  
   202  	myMap2 := myMap
   203  	if len(myMap2) != len(myMap) {
   204  		t.Errorf("copy len Got: %d, Want: %d", len(myMap2), len(myMap))
   205  	}
   206  }
   207  
   208  func containsInt(s []int, e int) bool {
   209  	for _, a := range s {
   210  		if a == e {
   211  			return true
   212  		}
   213  	}
   214  	return false
   215  }
   216  
   217  func containsString(s []string, e string) bool {
   218  	for _, a := range s {
   219  		if a == e {
   220  			return true
   221  		}
   222  	}
   223  	return false
   224  }
   225  
   226  // These benchmarks test various Map operations, and include a slice benchmark for reference.
   227  const size = 10000
   228  
   229  func makeMap(size int) map[int]string {
   230  	myMap := make(map[int]string, size)
   231  	for i := 0; i < size; i++ {
   232  		myMap[i] = "data"
   233  	}
   234  
   235  	return myMap
   236  }
   237  
   238  func makeSlice(size int) []int {
   239  	slice := make([]int, size)
   240  	for i := 0; i < size; i++ {
   241  		slice[i] = i
   242  	}
   243  
   244  	return slice
   245  }
   246  
   247  func BenchmarkSliceLen(b *testing.B) {
   248  	slice := makeSlice(size)
   249  
   250  	for i := 0; i < b.N; i++ {
   251  		if len(slice) > 0 {
   252  		}
   253  	}
   254  }
   255  
   256  func BenchmarkMapLen(b *testing.B) {
   257  	myMap := makeMap(size)
   258  
   259  	for i := 0; i < b.N; i++ {
   260  		if len(myMap) > 0 {
   261  		}
   262  	}
   263  }
   264  
   265  func BenchmarkMapNilCheck(b *testing.B) {
   266  	myMap := makeMap(size)
   267  
   268  	for i := 0; i < b.N; i++ {
   269  		if myMap != nil {
   270  		}
   271  	}
   272  }
   273  
   274  func BenchmarkMapNilElementCheck(b *testing.B) {
   275  	myMap := makeMap(size)
   276  
   277  	for i := 0; i < b.N; i++ {
   278  		if myMap[0] != "" {
   279  		}
   280  	}
   281  }
   282  
   283  func BenchmarkSliceRange(b *testing.B) {
   284  	slice := makeSlice(size)
   285  
   286  	for i := 0; i < b.N; i++ {
   287  		for range slice {
   288  		}
   289  	}
   290  }
   291  
   292  func BenchmarkMapRange(b *testing.B) {
   293  	myMap := makeMap(size)
   294  
   295  	for i := 0; i < b.N; i++ {
   296  		for range myMap {
   297  		}
   298  	}
   299  }