github.com/filosottile/go@v0.0.0-20170906193555-dbed9972d994/src/reflect/set_test.go (about)

     1  // Copyright 2011 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 reflect_test
     6  
     7  import (
     8  	"bytes"
     9  	"go/ast"
    10  	"go/token"
    11  	"io"
    12  	. "reflect"
    13  	"testing"
    14  	"unsafe"
    15  )
    16  
    17  type MyBuffer bytes.Buffer
    18  
    19  func TestImplicitMapConversion(t *testing.T) {
    20  	// Test implicit conversions in MapIndex and SetMapIndex.
    21  	{
    22  		// direct
    23  		m := make(map[int]int)
    24  		mv := ValueOf(m)
    25  		mv.SetMapIndex(ValueOf(1), ValueOf(2))
    26  		x, ok := m[1]
    27  		if x != 2 {
    28  			t.Errorf("#1 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
    29  		}
    30  		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
    31  			t.Errorf("#1 MapIndex(1) = %d", n)
    32  		}
    33  	}
    34  	{
    35  		// convert interface key
    36  		m := make(map[interface{}]int)
    37  		mv := ValueOf(m)
    38  		mv.SetMapIndex(ValueOf(1), ValueOf(2))
    39  		x, ok := m[1]
    40  		if x != 2 {
    41  			t.Errorf("#2 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
    42  		}
    43  		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
    44  			t.Errorf("#2 MapIndex(1) = %d", n)
    45  		}
    46  	}
    47  	{
    48  		// convert interface value
    49  		m := make(map[int]interface{})
    50  		mv := ValueOf(m)
    51  		mv.SetMapIndex(ValueOf(1), ValueOf(2))
    52  		x, ok := m[1]
    53  		if x != 2 {
    54  			t.Errorf("#3 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
    55  		}
    56  		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
    57  			t.Errorf("#3 MapIndex(1) = %d", n)
    58  		}
    59  	}
    60  	{
    61  		// convert both interface key and interface value
    62  		m := make(map[interface{}]interface{})
    63  		mv := ValueOf(m)
    64  		mv.SetMapIndex(ValueOf(1), ValueOf(2))
    65  		x, ok := m[1]
    66  		if x != 2 {
    67  			t.Errorf("#4 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
    68  		}
    69  		if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
    70  			t.Errorf("#4 MapIndex(1) = %d", n)
    71  		}
    72  	}
    73  	{
    74  		// convert both, with non-empty interfaces
    75  		m := make(map[io.Reader]io.Writer)
    76  		mv := ValueOf(m)
    77  		b1 := new(bytes.Buffer)
    78  		b2 := new(bytes.Buffer)
    79  		mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
    80  		x, ok := m[b1]
    81  		if x != b2 {
    82  			t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
    83  		}
    84  		if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) {
    85  			t.Errorf("#5 MapIndex(b1) = %#x want %p", p, b2)
    86  		}
    87  	}
    88  	{
    89  		// convert channel direction
    90  		m := make(map[<-chan int]chan int)
    91  		mv := ValueOf(m)
    92  		c1 := make(chan int)
    93  		c2 := make(chan int)
    94  		mv.SetMapIndex(ValueOf(c1), ValueOf(c2))
    95  		x, ok := m[c1]
    96  		if x != c2 {
    97  			t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m)
    98  		}
    99  		if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() {
   100  			t.Errorf("#6 MapIndex(c1) = %#x want %p", p, c2)
   101  		}
   102  	}
   103  	{
   104  		// convert identical underlying types
   105  		// TODO(rsc): Should be able to define MyBuffer here.
   106  		// 6l prints very strange messages about .this.Bytes etc
   107  		// when we do that though, so MyBuffer is defined
   108  		// at top level.
   109  		m := make(map[*MyBuffer]*bytes.Buffer)
   110  		mv := ValueOf(m)
   111  		b1 := new(MyBuffer)
   112  		b2 := new(bytes.Buffer)
   113  		mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
   114  		x, ok := m[b1]
   115  		if x != b2 {
   116  			t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
   117  		}
   118  		if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) {
   119  			t.Errorf("#7 MapIndex(b1) = %#x want %p", p, b2)
   120  		}
   121  	}
   122  
   123  }
   124  
   125  func TestImplicitSetConversion(t *testing.T) {
   126  	// Assume TestImplicitMapConversion covered the basics.
   127  	// Just make sure conversions are being applied at all.
   128  	var r io.Reader
   129  	b := new(bytes.Buffer)
   130  	rv := ValueOf(&r).Elem()
   131  	rv.Set(ValueOf(b))
   132  	if r != b {
   133  		t.Errorf("after Set: r=%T(%v)", r, r)
   134  	}
   135  }
   136  
   137  func TestImplicitSendConversion(t *testing.T) {
   138  	c := make(chan io.Reader, 10)
   139  	b := new(bytes.Buffer)
   140  	ValueOf(c).Send(ValueOf(b))
   141  	if bb := <-c; bb != b {
   142  		t.Errorf("Received %p != %p", bb, b)
   143  	}
   144  }
   145  
   146  func TestImplicitCallConversion(t *testing.T) {
   147  	// Arguments must be assignable to parameter types.
   148  	fv := ValueOf(io.WriteString)
   149  	b := new(bytes.Buffer)
   150  	fv.Call([]Value{ValueOf(b), ValueOf("hello world")})
   151  	if b.String() != "hello world" {
   152  		t.Errorf("After call: string=%q want %q", b.String(), "hello world")
   153  	}
   154  }
   155  
   156  func TestImplicitAppendConversion(t *testing.T) {
   157  	// Arguments must be assignable to the slice's element type.
   158  	s := []io.Reader{}
   159  	sv := ValueOf(&s).Elem()
   160  	b := new(bytes.Buffer)
   161  	sv.Set(Append(sv, ValueOf(b)))
   162  	if len(s) != 1 || s[0] != b {
   163  		t.Errorf("after append: s=%v want [%p]", s, b)
   164  	}
   165  }
   166  
   167  var implementsTests = []struct {
   168  	x interface{}
   169  	t interface{}
   170  	b bool
   171  }{
   172  	{new(*bytes.Buffer), new(io.Reader), true},
   173  	{new(bytes.Buffer), new(io.Reader), false},
   174  	{new(*bytes.Buffer), new(io.ReaderAt), false},
   175  	{new(*ast.Ident), new(ast.Expr), true},
   176  	{new(*notAnExpr), new(ast.Expr), false},
   177  	{new(*ast.Ident), new(notASTExpr), false},
   178  	{new(notASTExpr), new(ast.Expr), false},
   179  	{new(ast.Expr), new(notASTExpr), false},
   180  	{new(*notAnExpr), new(notASTExpr), true},
   181  }
   182  
   183  type notAnExpr struct{}
   184  
   185  func (notAnExpr) Pos() token.Pos { return token.NoPos }
   186  func (notAnExpr) End() token.Pos { return token.NoPos }
   187  func (notAnExpr) exprNode()      {}
   188  
   189  type notASTExpr interface {
   190  	Pos() token.Pos
   191  	End() token.Pos
   192  	exprNode()
   193  }
   194  
   195  func TestImplements(t *testing.T) {
   196  	for _, tt := range implementsTests {
   197  		xv := TypeOf(tt.x).Elem()
   198  		xt := TypeOf(tt.t).Elem()
   199  		if b := xv.Implements(xt); b != tt.b {
   200  			t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
   201  		}
   202  	}
   203  }
   204  
   205  var assignableTests = []struct {
   206  	x interface{}
   207  	t interface{}
   208  	b bool
   209  }{
   210  	{new(chan int), new(<-chan int), true},
   211  	{new(<-chan int), new(chan int), false},
   212  	{new(*int), new(IntPtr), true},
   213  	{new(IntPtr), new(*int), true},
   214  	{new(IntPtr), new(IntPtr1), false},
   215  	{new(Ch), new(<-chan interface{}), true},
   216  	// test runs implementsTests too
   217  }
   218  
   219  type IntPtr *int
   220  type IntPtr1 *int
   221  type Ch <-chan interface{}
   222  
   223  func TestAssignableTo(t *testing.T) {
   224  	for _, tt := range append(assignableTests, implementsTests...) {
   225  		xv := TypeOf(tt.x).Elem()
   226  		xt := TypeOf(tt.t).Elem()
   227  		if b := xv.AssignableTo(xt); b != tt.b {
   228  			t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
   229  		}
   230  	}
   231  }