github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/encoding/gob/type_test.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gob
     6  
     7  import (
     8  	"bytes"
     9  	"reflect"
    10  	"testing"
    11  )
    12  
    13  type typeT struct {
    14  	id  typeId
    15  	str string
    16  }
    17  
    18  var basicTypes = []typeT{
    19  	{tBool, "bool"},
    20  	{tInt, "int"},
    21  	{tUint, "uint"},
    22  	{tFloat, "float"},
    23  	{tBytes, "bytes"},
    24  	{tString, "string"},
    25  }
    26  
    27  func getTypeUnlocked(name string, rt reflect.Type) gobType {
    28  	typeLock.Lock()
    29  	defer typeLock.Unlock()
    30  	t, err := getBaseType(name, rt)
    31  	if err != nil {
    32  		panic("getTypeUnlocked: " + err.Error())
    33  	}
    34  	return t
    35  }
    36  
    37  // Sanity checks
    38  func TestBasic(t *testing.T) {
    39  	for _, tt := range basicTypes {
    40  		if tt.id.string() != tt.str {
    41  			t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string())
    42  		}
    43  		if tt.id == 0 {
    44  			t.Errorf("id for %q is zero", tt.str)
    45  		}
    46  	}
    47  }
    48  
    49  // Reregister some basic types to check registration is idempotent.
    50  func TestReregistration(t *testing.T) {
    51  	newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0)))
    52  	if newtyp != tInt.gobType() {
    53  		t.Errorf("reregistration of %s got new type", newtyp.string())
    54  	}
    55  	newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0)))
    56  	if newtyp != tUint.gobType() {
    57  		t.Errorf("reregistration of %s got new type", newtyp.string())
    58  	}
    59  	newtyp = getTypeUnlocked("string", reflect.TypeOf("hello"))
    60  	if newtyp != tString.gobType() {
    61  		t.Errorf("reregistration of %s got new type", newtyp.string())
    62  	}
    63  }
    64  
    65  func TestArrayType(t *testing.T) {
    66  	var a3 [3]int
    67  	a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
    68  	newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
    69  	if a3int != newa3int {
    70  		t.Errorf("second registration of [3]int creates new type")
    71  	}
    72  	var a4 [4]int
    73  	a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
    74  	if a3int == a4int {
    75  		t.Errorf("registration of [3]int creates same type as [4]int")
    76  	}
    77  	var b3 [3]bool
    78  	a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
    79  	if a3int == a3bool {
    80  		t.Errorf("registration of [3]bool creates same type as [3]int")
    81  	}
    82  	str := a3bool.string()
    83  	expected := "[3]bool"
    84  	if str != expected {
    85  		t.Errorf("array printed as %q; expected %q", str, expected)
    86  	}
    87  }
    88  
    89  func TestSliceType(t *testing.T) {
    90  	var s []int
    91  	sint := getTypeUnlocked("slice", reflect.TypeOf(s))
    92  	var news []int
    93  	newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
    94  	if sint != newsint {
    95  		t.Errorf("second registration of []int creates new type")
    96  	}
    97  	var b []bool
    98  	sbool := getTypeUnlocked("", reflect.TypeOf(b))
    99  	if sbool == sint {
   100  		t.Errorf("registration of []bool creates same type as []int")
   101  	}
   102  	str := sbool.string()
   103  	expected := "[]bool"
   104  	if str != expected {
   105  		t.Errorf("slice printed as %q; expected %q", str, expected)
   106  	}
   107  }
   108  
   109  func TestMapType(t *testing.T) {
   110  	var m map[string]int
   111  	mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
   112  	var newm map[string]int
   113  	newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
   114  	if mapStringInt != newMapStringInt {
   115  		t.Errorf("second registration of map[string]int creates new type")
   116  	}
   117  	var b map[string]bool
   118  	mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
   119  	if mapStringBool == mapStringInt {
   120  		t.Errorf("registration of map[string]bool creates same type as map[string]int")
   121  	}
   122  	str := mapStringBool.string()
   123  	expected := "map[string]bool"
   124  	if str != expected {
   125  		t.Errorf("map printed as %q; expected %q", str, expected)
   126  	}
   127  }
   128  
   129  type Bar struct {
   130  	X string
   131  }
   132  
   133  // This structure has pointers and refers to itself, making it a good test case.
   134  type Foo struct {
   135  	A int
   136  	B int32 // will become int
   137  	C string
   138  	D []byte
   139  	E *float64    // will become float64
   140  	F ****float64 // will become float64
   141  	G *Bar
   142  	H *Bar // should not interpolate the definition of Bar again
   143  	I *Foo // will not explode
   144  }
   145  
   146  func TestStructType(t *testing.T) {
   147  	sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{}))
   148  	str := sstruct.string()
   149  	// If we can print it correctly, we built it correctly.
   150  	expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
   151  	if str != expected {
   152  		t.Errorf("struct printed as %q; expected %q", str, expected)
   153  	}
   154  }
   155  
   156  // Should be OK to register the same type multiple times, as long as they're
   157  // at the same level of indirection.
   158  func TestRegistration(t *testing.T) {
   159  	type T struct{ a int }
   160  	Register(new(T))
   161  	Register(new(T))
   162  }
   163  
   164  type N1 struct{}
   165  type N2 struct{}
   166  
   167  // See comment in type.go/Register.
   168  func TestRegistrationNaming(t *testing.T) {
   169  	testCases := []struct {
   170  		t    interface{}
   171  		name string
   172  	}{
   173  		{&N1{}, "*gob.N1"},
   174  		{N2{}, "encoding/gob.N2"},
   175  	}
   176  
   177  	for _, tc := range testCases {
   178  		Register(tc.t)
   179  
   180  		tct := reflect.TypeOf(tc.t)
   181  		registerLock.RLock()
   182  		ct := nameToConcreteType[tc.name]
   183  		registerLock.RUnlock()
   184  		if ct != tct {
   185  			t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
   186  		}
   187  		// concreteTypeToName is keyed off the base type.
   188  		if tct.Kind() == reflect.Ptr {
   189  			tct = tct.Elem()
   190  		}
   191  		if n := concreteTypeToName[tct]; n != tc.name {
   192  			t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name)
   193  		}
   194  	}
   195  }
   196  
   197  func TestStressParallel(t *testing.T) {
   198  	type T2 struct{ A int }
   199  	c := make(chan bool)
   200  	const N = 10
   201  	for i := 0; i < N; i++ {
   202  		go func() {
   203  			p := new(T2)
   204  			Register(p)
   205  			b := new(bytes.Buffer)
   206  			enc := NewEncoder(b)
   207  			err := enc.Encode(p)
   208  			if err != nil {
   209  				t.Error("encoder fail:", err)
   210  			}
   211  			dec := NewDecoder(b)
   212  			err = dec.Decode(p)
   213  			if err != nil {
   214  				t.Error("decoder fail:", err)
   215  			}
   216  			c <- true
   217  		}()
   218  	}
   219  	for i := 0; i < N; i++ {
   220  		<-c
   221  	}
   222  }