mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-08 20:55:01 +00:00
263 lines
6.1 KiB
Go
263 lines
6.1 KiB
Go
// Copyright 2009 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 gob
|
|
|
|
import (
|
|
"bytes"
|
|
"reflect"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
type typeT struct {
|
|
id typeId
|
|
str string
|
|
}
|
|
|
|
var basicTypes = []typeT{
|
|
{tBool, "bool"},
|
|
{tInt, "int"},
|
|
{tUint, "uint"},
|
|
{tFloat, "float"},
|
|
{tBytes, "bytes"},
|
|
{tString, "string"},
|
|
}
|
|
|
|
func getTypeUnlocked(name string, rt reflect.Type) gobType {
|
|
typeLock.Lock()
|
|
defer typeLock.Unlock()
|
|
t, err := getBaseType(name, rt)
|
|
if err != nil {
|
|
panic("getTypeUnlocked: " + err.Error())
|
|
}
|
|
return t
|
|
}
|
|
|
|
// Sanity checks
|
|
func TestBasic(t *testing.T) {
|
|
for _, tt := range basicTypes {
|
|
if tt.id.string() != tt.str {
|
|
t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string())
|
|
}
|
|
if tt.id == 0 {
|
|
t.Errorf("id for %q is zero", tt.str)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reregister some basic types to check registration is idempotent.
|
|
func TestReregistration(t *testing.T) {
|
|
newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0)))
|
|
if newtyp != tInt.gobType() {
|
|
t.Errorf("reregistration of %s got new type", newtyp.string())
|
|
}
|
|
newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0)))
|
|
if newtyp != tUint.gobType() {
|
|
t.Errorf("reregistration of %s got new type", newtyp.string())
|
|
}
|
|
newtyp = getTypeUnlocked("string", reflect.TypeOf("hello"))
|
|
if newtyp != tString.gobType() {
|
|
t.Errorf("reregistration of %s got new type", newtyp.string())
|
|
}
|
|
}
|
|
|
|
func TestArrayType(t *testing.T) {
|
|
var a3 [3]int
|
|
a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
|
|
newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
|
|
if a3int != newa3int {
|
|
t.Errorf("second registration of [3]int creates new type")
|
|
}
|
|
var a4 [4]int
|
|
a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
|
|
if a3int == a4int {
|
|
t.Errorf("registration of [3]int creates same type as [4]int")
|
|
}
|
|
var b3 [3]bool
|
|
a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
|
|
if a3int == a3bool {
|
|
t.Errorf("registration of [3]bool creates same type as [3]int")
|
|
}
|
|
str := a3bool.string()
|
|
expected := "[3]bool"
|
|
if str != expected {
|
|
t.Errorf("array printed as %q; expected %q", str, expected)
|
|
}
|
|
}
|
|
|
|
func TestSliceType(t *testing.T) {
|
|
var s []int
|
|
sint := getTypeUnlocked("slice", reflect.TypeOf(s))
|
|
var news []int
|
|
newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
|
|
if sint != newsint {
|
|
t.Errorf("second registration of []int creates new type")
|
|
}
|
|
var b []bool
|
|
sbool := getTypeUnlocked("", reflect.TypeOf(b))
|
|
if sbool == sint {
|
|
t.Errorf("registration of []bool creates same type as []int")
|
|
}
|
|
str := sbool.string()
|
|
expected := "[]bool"
|
|
if str != expected {
|
|
t.Errorf("slice printed as %q; expected %q", str, expected)
|
|
}
|
|
}
|
|
|
|
func TestMapType(t *testing.T) {
|
|
var m map[string]int
|
|
mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
|
|
var newm map[string]int
|
|
newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
|
|
if mapStringInt != newMapStringInt {
|
|
t.Errorf("second registration of map[string]int creates new type")
|
|
}
|
|
var b map[string]bool
|
|
mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
|
|
if mapStringBool == mapStringInt {
|
|
t.Errorf("registration of map[string]bool creates same type as map[string]int")
|
|
}
|
|
str := mapStringBool.string()
|
|
expected := "map[string]bool"
|
|
if str != expected {
|
|
t.Errorf("map printed as %q; expected %q", str, expected)
|
|
}
|
|
}
|
|
|
|
type Bar struct {
|
|
X string
|
|
}
|
|
|
|
// This structure has pointers and refers to itself, making it a good test case.
|
|
type Foo struct {
|
|
A int
|
|
B int32 // will become int
|
|
C string
|
|
D []byte
|
|
E *float64 // will become float64
|
|
F ****float64 // will become float64
|
|
G *Bar
|
|
H *Bar // should not interpolate the definition of Bar again
|
|
I *Foo // will not explode
|
|
}
|
|
|
|
func TestStructType(t *testing.T) {
|
|
sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{}))
|
|
str := sstruct.string()
|
|
// If we can print it correctly, we built it correctly.
|
|
expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
|
|
if str != expected {
|
|
t.Errorf("struct printed as %q; expected %q", str, expected)
|
|
}
|
|
}
|
|
|
|
// Should be OK to register the same type multiple times, as long as they're
|
|
// at the same level of indirection.
|
|
func TestRegistration(t *testing.T) {
|
|
type T struct{ a int }
|
|
Register(new(T))
|
|
Register(new(T))
|
|
}
|
|
|
|
type N1 struct{}
|
|
type N2 struct{}
|
|
|
|
// See comment in type.go/Register.
|
|
func TestRegistrationNaming(t *testing.T) {
|
|
testCases := []struct {
|
|
t any
|
|
name string
|
|
}{
|
|
{&N1{}, "*gob.N1"},
|
|
{N2{}, "encoding/gob.N2"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
Register(tc.t)
|
|
|
|
tct := reflect.TypeOf(tc.t)
|
|
ct, _ := nameToConcreteType.Load(tc.name)
|
|
if ct != tct {
|
|
t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
|
|
}
|
|
// concreteTypeToName is keyed off the base type.
|
|
if tct.Kind() == reflect.Pointer {
|
|
tct = tct.Elem()
|
|
}
|
|
if n, _ := concreteTypeToName.Load(tct); n != tc.name {
|
|
t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStressParallel(t *testing.T) {
|
|
type T2 struct{ A int }
|
|
c := make(chan bool)
|
|
const N = 10
|
|
for i := 0; i < N; i++ {
|
|
go func() {
|
|
p := new(T2)
|
|
Register(p)
|
|
b := new(bytes.Buffer)
|
|
enc := NewEncoder(b)
|
|
err := enc.Encode(p)
|
|
if err != nil {
|
|
t.Error("encoder fail:", err)
|
|
}
|
|
dec := NewDecoder(b)
|
|
err = dec.Decode(p)
|
|
if err != nil {
|
|
t.Error("decoder fail:", err)
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for i := 0; i < N; i++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
// Issue 23328. Note that this test name is known to cmd/dist/test.go.
|
|
func TestTypeRace(t *testing.T) {
|
|
c := make(chan bool)
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 2; i++ {
|
|
wg.Add(1)
|
|
go func(i int) {
|
|
defer wg.Done()
|
|
var buf bytes.Buffer
|
|
enc := NewEncoder(&buf)
|
|
dec := NewDecoder(&buf)
|
|
var x any
|
|
switch i {
|
|
case 0:
|
|
x = &N1{}
|
|
case 1:
|
|
x = &N2{}
|
|
default:
|
|
t.Errorf("bad i %d", i)
|
|
return
|
|
}
|
|
m := make(map[string]string)
|
|
<-c
|
|
if err := enc.Encode(x); err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
if err := enc.Encode(x); err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
if err := dec.Decode(&m); err == nil {
|
|
t.Error("decode unexpectedly succeeded")
|
|
return
|
|
}
|
|
}(i)
|
|
}
|
|
close(c)
|
|
wg.Wait()
|
|
}
|