github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/testdata/map.go (about)

     1  package main
     2  
     3  import (
     4  	"sort"
     5  	"unsafe"
     6  )
     7  
     8  var testmap1 = map[string]int{"data": 3}
     9  var testmap2 = map[string]int{
    10  	"one":    1,
    11  	"two":    2,
    12  	"three":  3,
    13  	"four":   4,
    14  	"five":   5,
    15  	"six":    6,
    16  	"seven":  7,
    17  	"eight":  8,
    18  	"nine":   9,
    19  	"ten":    10,
    20  	"eleven": 11,
    21  	"twelve": 12,
    22  }
    23  
    24  type ArrayKey [4]byte
    25  
    26  var testMapArrayKey = map[ArrayKey]int{
    27  	ArrayKey([4]byte{1, 2, 3, 4}): 1234,
    28  	ArrayKey([4]byte{4, 3, 2, 1}): 4321,
    29  }
    30  var testmapIntInt = map[int]int{1: 1, 2: 4, 3: 9}
    31  
    32  type namedFloat struct {
    33  	s string
    34  	f float32
    35  }
    36  
    37  func main() {
    38  	m := map[string]int{"answer": 42, "foo": 3}
    39  	readMap(m, "answer")
    40  	readMap(testmap1, "data")
    41  	readMap(testmap2, "three")
    42  	readMap(testmap2, "ten")
    43  	delete(testmap2, "six")
    44  	readMap(testmap2, "seven")
    45  	lookup(testmap2, "eight")
    46  	lookup(testmap2, "nokey")
    47  
    48  	// operations on nil maps
    49  	var nilmap map[string]int
    50  	println(m == nil, m != nil, len(m))
    51  	println(nilmap == nil, nilmap != nil, len(nilmap))
    52  	delete(nilmap, "foo")
    53  	println("nilmap:", nilmap["bar"])
    54  	println(testmapIntInt[2])
    55  	testmapIntInt[2] = 42
    56  	println(testmapIntInt[2])
    57  	for k := range nilmap {
    58  		println(k) // unreachable
    59  	}
    60  
    61  	var nilbinmap map[uint16]int
    62  	delete(nilbinmap, 4)
    63  	println("nilbinmap:", nilbinmap[5])
    64  
    65  	arrKey := ArrayKey([4]byte{4, 3, 2, 1})
    66  	println(testMapArrayKey[arrKey])
    67  	testMapArrayKey[arrKey] = 5555
    68  	println(testMapArrayKey[arrKey])
    69  
    70  	// test maps with interface keys
    71  	itfMap := map[interface{}]int{
    72  		3.14:         3,
    73  		8:            8,
    74  		uint8(8):     80,
    75  		"eight":      800,
    76  		[2]int{5, 2}: 52,
    77  		true:         1,
    78  	}
    79  	println("itfMap[3]:", itfMap[3]) // doesn't exist
    80  	println("itfMap[3.14]:", itfMap[3.14])
    81  	println("itfMap[8]:", itfMap[8])
    82  	println("itfMap[uint8(8)]:", itfMap[uint8(8)])
    83  	println(`itfMap["eight"]:`, itfMap["eight"])
    84  	println(`itfMap[[2]int{5, 2}]:`, itfMap[[2]int{5, 2}])
    85  	println("itfMap[true]:", itfMap[true])
    86  	delete(itfMap, 8)
    87  	println("itfMap[8]:", itfMap[8])
    88  	for key, value := range itfMap {
    89  		if key == "eight" {
    90  			println("itfMap: found key \"eight\":", value)
    91  		}
    92  	}
    93  
    94  	// test map with float keys
    95  	floatMap := map[float32]int{
    96  		42:   84,
    97  		3.14: 6,
    98  	}
    99  	println("floatMap[42]:", floatMap[42])
   100  	println("floatMap[43]:", floatMap[43])
   101  	delete(floatMap, 42)
   102  	println("floatMap[42]:", floatMap[42])
   103  	for k, v := range floatMap {
   104  		println("floatMap key, value:", k, v)
   105  	}
   106  
   107  	// test maps with struct keys
   108  	structMap := map[namedFloat]int{
   109  		namedFloat{"tau", 6.28}: 5,
   110  	}
   111  	println(`structMap[{"tau", 6.28}]:`, structMap[namedFloat{"tau", 6.28}])
   112  	println(`structMap[{"Tau", 6.28}]:`, structMap[namedFloat{"Tau", 6.28}])
   113  	println(`structMap[{"tau", 3.14}]:`, structMap[namedFloat{"tau", 3.14}])
   114  	delete(structMap, namedFloat{"tau", 6.28})
   115  	println(`structMap[{"tau", 6.28}]:`, structMap[namedFloat{"tau", 6.28}])
   116  
   117  	// test preallocated map
   118  	squares := make(map[int]int, 200)
   119  	testBigMap(squares, 100)
   120  	println("tested preallocated map")
   121  
   122  	// test growing maps
   123  	squares = make(map[int]int, 0)
   124  	testBigMap(squares, 10)
   125  	squares = make(map[int]int, 20)
   126  	testBigMap(squares, 40)
   127  	println("tested growing of a map")
   128  
   129  	floatcmplx()
   130  
   131  	mapgrow()
   132  
   133  	interfacerehash()
   134  }
   135  
   136  func floatcmplx() {
   137  
   138  	var zero float64
   139  	var negz float64 = -zero
   140  
   141  	// test that zero and negative zero hash to the same thing
   142  	m := make(map[float64]int)
   143  	m[zero]++
   144  	m[negz]++
   145  	println(m[negz])
   146  
   147  	cmap := make(map[complex128]int)
   148  
   149  	var c complex128
   150  	c = complex(zero, zero)
   151  	cmap[c]++
   152  
   153  	c = complex(negz, negz)
   154  	cmap[c]++
   155  
   156  	c = complex(0, 0)
   157  	println(cmap[c])
   158  
   159  	c = complex(1, negz)
   160  	cmap[c]++
   161  
   162  	c = complex(1, zero)
   163  	cmap[c]++
   164  
   165  	println(cmap[c])
   166  
   167  	c = complex(negz, 2)
   168  	cmap[c]++
   169  
   170  	c = complex(zero, 2)
   171  	cmap[c]++
   172  
   173  	println(cmap[c])
   174  }
   175  
   176  func readMap(m map[string]int, key string) {
   177  	println("map length:", len(m))
   178  	println("map read:", key, "=", m[key])
   179  	keys := make([]string, 0, len(m))
   180  	for k := range m {
   181  		keys = append(keys, k)
   182  	}
   183  	sort.Strings(keys)
   184  	for _, k := range keys {
   185  		v := m[k]
   186  		println(" ", k, "=", v)
   187  	}
   188  }
   189  
   190  func lookup(m map[string]int, key string) {
   191  	value, ok := m[key]
   192  	println("lookup with comma-ok:", key, value, ok)
   193  }
   194  
   195  func testBigMap(squares map[int]int, n int) {
   196  	for i := 0; i < n; i++ {
   197  		if len(squares) != i {
   198  			println("unexpected length:", len(squares), "at i =", i)
   199  		}
   200  		squares[i] = i * i
   201  		for j := 0; j <= i; j++ {
   202  			if v, ok := squares[j]; !ok || v != j*j {
   203  				if !ok {
   204  					println("key not found in squares map:", j)
   205  				} else {
   206  					println("unexpected value read back from squares map:", j, v)
   207  				}
   208  				return
   209  			}
   210  		}
   211  	}
   212  }
   213  
   214  func mapgrow() {
   215  	m := make(map[int]int)
   216  
   217  	var Delete = 500
   218  	if unsafe.Sizeof(uintptr(0)) < 4 {
   219  		// Reduce the number of iterations on low-memory devices like AVR.
   220  		Delete = 20
   221  	}
   222  	var N = Delete * 2
   223  
   224  	for i := 0; i < Delete; i++ {
   225  		m[i] = i
   226  	}
   227  
   228  	var deleted bool
   229  	for k, v := range m {
   230  		if k == 0 {
   231  			// grow map
   232  			for i := Delete; i < N; i++ {
   233  				m[i] = i
   234  			}
   235  
   236  			// delete some elements
   237  			for i := 0; i < Delete; i++ {
   238  				delete(m, i)
   239  			}
   240  			deleted = true
   241  			continue
   242  		}
   243  
   244  		// make sure we never see a deleted element later in our iteration
   245  		if deleted && v < Delete {
   246  			println("saw deleted element", v)
   247  		}
   248  	}
   249  
   250  	if len(m) != N-Delete {
   251  		println("bad length post grow/delete", len(m))
   252  	}
   253  
   254  	seen := make([]bool, Delete)
   255  
   256  	var mcount int
   257  	for k, v := range m {
   258  		if k != v {
   259  			println("element mismatch", k, v)
   260  		}
   261  		if k < Delete {
   262  			println("saw deleted element post-grow", k)
   263  		}
   264  		seen[v-Delete] = true
   265  		mcount++
   266  	}
   267  
   268  	for _, v := range seen {
   269  		if !v {
   270  			println("missing key", v)
   271  		}
   272  	}
   273  
   274  	if mcount != N-Delete {
   275  		println("bad number of elements post-grow:", mcount)
   276  	}
   277  	println("done")
   278  }
   279  
   280  type Counter interface {
   281  	count() int
   282  }
   283  
   284  type counter struct {
   285  	i int
   286  }
   287  
   288  func (c *counter) count() int {
   289  	return c.i
   290  }
   291  
   292  func interfacerehash() {
   293  	m := make(map[Counter]int)
   294  
   295  	for i := 0; i < 20; i++ {
   296  		c := &counter{i}
   297  		m[c] = i
   298  	}
   299  
   300  	var failures int
   301  	for k, v := range m {
   302  		if got := m[k]; got != v {
   303  			println("lookup failure got", got, "want", v)
   304  			failures++
   305  		}
   306  	}
   307  	if failures == 0 {
   308  		println("no interface lookup failures")
   309  	}
   310  }