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