// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build goexperiment.swissmap package runtime_test import ( "internal/abi" "internal/goarch" "internal/runtime/maps" "slices" "testing" "unsafe" ) func TestHmapSize(t *testing.T) { // The structure of Map is defined in internal/runtime/maps/map.go // and in cmd/compile/internal/reflectdata/map_swiss.go and must be in sync. // The size of Map should be 48 bytes on 64 bit and 32 bytes on 32 bit platforms. wantSize := uintptr(2*8 + 4*goarch.PtrSize) gotSize := unsafe.Sizeof(maps.Map{}) if gotSize != wantSize { t.Errorf("sizeof(maps.Map{})==%d, want %d", gotSize, wantSize) } } // See also reflect_test.TestGroupSizeZero. func TestGroupSizeZero(t *testing.T) { var m map[struct{}]struct{} mTyp := abi.TypeOf(m) mt := (*abi.SwissMapType)(unsafe.Pointer(mTyp)) // internal/runtime/maps when create pointers to slots, even if slots // are size 0. The compiler should have reserved an extra word to // ensure that pointers to the zero-size type at the end of group are // valid. if mt.Group.Size() <= 8 { t.Errorf("Group size got %d want >8", mt.Group.Size()) } } func TestMapIterOrder(t *testing.T) { sizes := []int{3, 7, 9, 15} for _, n := range sizes { for i := 0; i < 1000; i++ { // Make m be {0: true, 1: true, ..., n-1: true}. m := make(map[int]bool) for i := 0; i < n; i++ { m[i] = true } // Check that iterating over the map produces at least two different orderings. ord := func() []int { var s []int for key := range m { s = append(s, key) } return s } first := ord() ok := false for try := 0; try < 100; try++ { if !slices.Equal(first, ord()) { ok = true break } } if !ok { t.Errorf("Map with n=%d elements had consistent iteration order: %v", n, first) break } } } }