github.com/3JoB/go-reflect@v1.0.1/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/3JoB/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[any]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]any) 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[any]any) 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 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 any 164 t any 165 b bool 166 }{ 167 {x: new(*bytes.Buffer), t: new(io.Reader), b: true}, 168 {x: new(bytes.Buffer), t: new(io.Reader), b: false}, 169 {x: new(*bytes.Buffer), t: new(io.ReaderAt), b: false}, 170 {x: new(*ast.Ident), t: new(ast.Expr), b: true}, 171 {x: new(*notAnExpr), t: new(ast.Expr), b: false}, 172 {x: new(*ast.Ident), t: new(notASTExpr), b: false}, 173 {x: new(notASTExpr), t: new(ast.Expr), b: false}, 174 {x: new(ast.Expr), t: new(notASTExpr), b: false}, 175 {x: new(*notAnExpr), t: new(notASTExpr), b: true}, 176 } 177 178 type notAnExpr struct{} 179 180 func (notAnExpr) Pos() token.Pos { return token.NoPos } 181 182 func (notAnExpr) End() token.Pos { return token.NoPos } 183 184 func (notAnExpr) exprNode() {} 185 186 type notASTExpr interface { 187 Pos() token.Pos 188 End() token.Pos 189 exprNode() 190 } 191 192 func TestImplements(t *testing.T) { 193 for _, tt := range implementsTests { 194 xv := TypeOf(tt.x).Elem() 195 xt := TypeOf(tt.t).Elem() 196 if b := xv.Implements(xt); b != tt.b { 197 t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b) 198 } 199 } 200 } 201 202 var assignableTests = []struct { 203 x any 204 t any 205 b bool 206 }{ 207 {x: new(chan int), t: new(<-chan int), b: true}, 208 {x: new(<-chan int), t: new(chan int), b: false}, 209 {x: new(*int), t: new(IntPtr), b: true}, 210 {x: new(IntPtr), t: new(*int), b: true}, 211 {x: new(IntPtr), t: new(IntPtr1), b: false}, 212 {x: new(Ch), t: new(<-chan any), b: true}, 213 // test runs implementsTests too 214 } 215 216 type IntPtr *int 217 218 type IntPtr1 *int 219 220 type Ch <-chan any 221 222 func TestAssignableTo(t *testing.T) { 223 for _, tt := range append(assignableTests, implementsTests...) { 224 xv := TypeOf(tt.x).Elem() 225 xt := TypeOf(tt.t).Elem() 226 if b := xv.AssignableTo(xt); b != tt.b { 227 t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b) 228 } 229 } 230 }