Black Lives Matter. Support the Equal Justice Initiative.

Source file src/reflect/set_test.go

Documentation: reflect

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

View as plain text