mirror of
https://github.com/autc04/Retro68.git
synced 2024-10-20 05:25:11 +00:00
206 lines
3.6 KiB
Go
206 lines
3.6 KiB
Go
// Copyright 2020 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.
|
|
|
|
package intern
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
)
|
|
|
|
func TestBasics(t *testing.T) {
|
|
clearMap()
|
|
foo := Get("foo")
|
|
bar := Get("bar")
|
|
empty := Get("")
|
|
nilEface := Get(nil)
|
|
i := Get(0x7777777)
|
|
foo2 := Get("foo")
|
|
bar2 := Get("bar")
|
|
empty2 := Get("")
|
|
nilEface2 := Get(nil)
|
|
i2 := Get(0x7777777)
|
|
foo3 := GetByString("foo")
|
|
empty3 := GetByString("")
|
|
|
|
if foo.Get() != foo2.Get() {
|
|
t.Error("foo/foo2 values differ")
|
|
}
|
|
if foo.Get() != foo3.Get() {
|
|
t.Error("foo/foo3 values differ")
|
|
}
|
|
if foo.Get() != "foo" {
|
|
t.Error("foo.Get not foo")
|
|
}
|
|
if foo != foo2 {
|
|
t.Error("foo/foo2 pointers differ")
|
|
}
|
|
if foo != foo3 {
|
|
t.Error("foo/foo3 pointers differ")
|
|
}
|
|
|
|
if bar.Get() != bar2.Get() {
|
|
t.Error("bar values differ")
|
|
}
|
|
if bar.Get() != "bar" {
|
|
t.Error("bar.Get not bar")
|
|
}
|
|
if bar != bar2 {
|
|
t.Error("bar pointers differ")
|
|
}
|
|
|
|
if i.Get() != i.Get() {
|
|
t.Error("i values differ")
|
|
}
|
|
if i.Get() != 0x7777777 {
|
|
t.Error("i.Get not 0x7777777")
|
|
}
|
|
if i != i2 {
|
|
t.Error("i pointers differ")
|
|
}
|
|
|
|
if empty.Get() != empty2.Get() {
|
|
t.Error("empty/empty2 values differ")
|
|
}
|
|
if empty.Get() != empty.Get() {
|
|
t.Error("empty/empty3 values differ")
|
|
}
|
|
if empty.Get() != "" {
|
|
t.Error("empty.Get not empty string")
|
|
}
|
|
if empty != empty2 {
|
|
t.Error("empty/empty2 pointers differ")
|
|
}
|
|
if empty != empty3 {
|
|
t.Error("empty/empty3 pointers differ")
|
|
}
|
|
|
|
if nilEface.Get() != nilEface2.Get() {
|
|
t.Error("nilEface values differ")
|
|
}
|
|
if nilEface.Get() != nil {
|
|
t.Error("nilEface.Get not nil")
|
|
}
|
|
if nilEface != nilEface2 {
|
|
t.Error("nilEface pointers differ")
|
|
}
|
|
|
|
if n := mapLen(); n != 5 {
|
|
if runtime.Compiler != "gccgo" {
|
|
t.Errorf("map len = %d; want 4", n)
|
|
}
|
|
}
|
|
|
|
wantEmpty(t)
|
|
}
|
|
|
|
func wantEmpty(t testing.TB) {
|
|
if runtime.Compiler == "gccgo" {
|
|
// Fails with conservative GC.
|
|
return
|
|
}
|
|
t.Helper()
|
|
const gcTries = 5000
|
|
for try := 0; try < gcTries; try++ {
|
|
runtime.GC()
|
|
n := mapLen()
|
|
if n == 0 {
|
|
break
|
|
}
|
|
if try == gcTries-1 {
|
|
t.Errorf("map len = %d after (%d GC tries); want 0, contents: %v", n, gcTries, mapKeys())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStress(t *testing.T) {
|
|
iters := 10000
|
|
if testing.Short() {
|
|
iters = 1000
|
|
}
|
|
var sink []byte
|
|
for i := 0; i < iters; i++ {
|
|
_ = Get("foo")
|
|
sink = make([]byte, 1<<20)
|
|
}
|
|
_ = sink
|
|
}
|
|
|
|
func BenchmarkStress(b *testing.B) {
|
|
done := make(chan struct{})
|
|
defer close(done)
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-done:
|
|
return
|
|
default:
|
|
}
|
|
runtime.GC()
|
|
}
|
|
}()
|
|
|
|
clearMap()
|
|
v1 := Get("foo")
|
|
b.ReportAllocs()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
v2 := Get("foo")
|
|
if v1 != v2 {
|
|
b.Fatal("wrong value")
|
|
}
|
|
// And also a key we don't retain:
|
|
_ = Get("bar")
|
|
}
|
|
})
|
|
runtime.GC()
|
|
wantEmpty(b)
|
|
}
|
|
|
|
func mapLen() int {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
return len(valMap)
|
|
}
|
|
|
|
func mapKeys() (keys []string) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
for k := range valMap {
|
|
keys = append(keys, fmt.Sprint(k))
|
|
}
|
|
return keys
|
|
}
|
|
|
|
func clearMap() {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
for k := range valMap {
|
|
delete(valMap, k)
|
|
}
|
|
}
|
|
|
|
var (
|
|
globalString = "not a constant"
|
|
sink string
|
|
)
|
|
|
|
func TestGetByStringAllocs(t *testing.T) {
|
|
allocs := int(testing.AllocsPerRun(100, func() {
|
|
GetByString(globalString)
|
|
}))
|
|
if allocs != 0 {
|
|
t.Errorf("GetString allocated %d objects, want 0", allocs)
|
|
}
|
|
}
|
|
|
|
func BenchmarkGetByString(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
v := GetByString(globalString)
|
|
sink = v.Get().(string)
|
|
}
|
|
}
|