Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 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 | |
Russ Cox | 3b864e4 | 2009-08-12 13:18:37 -0700 | [diff] [blame] | 5 | package reflect_test |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 6 | |
| 7 | import ( |
Russ Cox | e1ee3b5 | 2011-04-20 16:24:45 -0400 | [diff] [blame] | 8 | "bytes" |
Rob Pike | ab44a81 | 2011-08-22 13:22:42 +1000 | [diff] [blame] | 9 | "encoding/base64" |
Russ Cox | 46f379c | 2012-09-22 08:52:27 -0400 | [diff] [blame] | 10 | "flag" |
Russ Cox | 6672b40 | 2010-06-14 11:23:11 -0700 | [diff] [blame] | 11 | "fmt" |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 12 | "io" |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 13 | "math/rand" |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 14 | "os" |
| 15 | . "reflect" |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 16 | "runtime" |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 17 | "sync" |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 18 | "testing" |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 19 | "time" |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 20 | "unsafe" |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 21 | ) |
| 22 | |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 23 | func TestBool(t *testing.T) { |
| 24 | v := ValueOf(true) |
| 25 | if v.Bool() != true { |
| 26 | t.Fatal("ValueOf(true).Bool() = false") |
| 27 | } |
| 28 | } |
| 29 | |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 30 | type integer int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 31 | type T struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 32 | a int |
| 33 | b float64 |
| 34 | c string |
| 35 | d *int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 36 | } |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 37 | |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 38 | type pair struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 39 | i interface{} |
| 40 | s string |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 41 | } |
| 42 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 43 | func isDigit(c uint8) bool { return '0' <= c && c <= '9' } |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 44 | |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 45 | func assert(t *testing.T, s, want string) { |
| 46 | if s != want { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 47 | t.Errorf("have %#q want %#q", s, want) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 48 | } |
| 49 | } |
| 50 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 51 | func typestring(i interface{}) string { return TypeOf(i).String() } |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 52 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 53 | var typeTests = []pair{ |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 54 | {struct{ x int }{}, "int"}, |
| 55 | {struct{ x int8 }{}, "int8"}, |
| 56 | {struct{ x int16 }{}, "int16"}, |
| 57 | {struct{ x int32 }{}, "int32"}, |
| 58 | {struct{ x int64 }{}, "int64"}, |
| 59 | {struct{ x uint }{}, "uint"}, |
| 60 | {struct{ x uint8 }{}, "uint8"}, |
| 61 | {struct{ x uint16 }{}, "uint16"}, |
| 62 | {struct{ x uint32 }{}, "uint32"}, |
| 63 | {struct{ x uint64 }{}, "uint64"}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 64 | {struct{ x float32 }{}, "float32"}, |
| 65 | {struct{ x float64 }{}, "float64"}, |
| 66 | {struct{ x int8 }{}, "int8"}, |
| 67 | {struct{ x (**int8) }{}, "**int8"}, |
| 68 | {struct{ x (**integer) }{}, "**reflect_test.integer"}, |
| 69 | {struct{ x ([32]int32) }{}, "[32]int32"}, |
| 70 | {struct{ x ([]int8) }{}, "[]int8"}, |
Russ Cox | 434a6c8 | 2011-12-02 14:45:07 -0500 | [diff] [blame] | 71 | {struct{ x (map[string]int32) }{}, "map[string]int32"}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 72 | {struct{ x (chan<- string) }{}, "chan<- string"}, |
| 73 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 74 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 75 | c chan *int32 |
| 76 | d float32 |
| 77 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 78 | }{}, |
| 79 | "struct { c chan *int32; d float32 }", |
| 80 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 81 | {struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"}, |
| 82 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 83 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 84 | c func(chan *integer, *int8) |
| 85 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 86 | }{}, |
| 87 | "struct { c func(chan *reflect_test.integer, *int8) }", |
| 88 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 89 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 90 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 91 | a int8 |
| 92 | b int32 |
| 93 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 94 | }{}, |
| 95 | "struct { a int8; b int32 }", |
| 96 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 97 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 98 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 99 | a int8 |
| 100 | b int8 |
| 101 | c int32 |
| 102 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 103 | }{}, |
| 104 | "struct { a int8; b int8; c int32 }", |
| 105 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 106 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 107 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 108 | a int8 |
| 109 | b int8 |
| 110 | c int8 |
| 111 | d int32 |
| 112 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 113 | }{}, |
| 114 | "struct { a int8; b int8; c int8; d int32 }", |
| 115 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 116 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 117 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 118 | a int8 |
| 119 | b int8 |
| 120 | c int8 |
| 121 | d int8 |
| 122 | e int32 |
| 123 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 124 | }{}, |
| 125 | "struct { a int8; b int8; c int8; d int8; e int32 }", |
| 126 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 127 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 128 | x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 129 | a int8 |
| 130 | b int8 |
| 131 | c int8 |
| 132 | d int8 |
| 133 | e int8 |
| 134 | f int32 |
| 135 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 136 | }{}, |
| 137 | "struct { a int8; b int8; c int8; d int8; e int8; f int32 }", |
| 138 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 139 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 140 | x struct { |
Russ Cox | 25733a9 | 2011-06-29 09:52:34 -0400 | [diff] [blame] | 141 | a int8 `reflect:"hi there"` |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 142 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 143 | }{}, |
Russ Cox | 25733a9 | 2011-06-29 09:52:34 -0400 | [diff] [blame] | 144 | `struct { a int8 "reflect:\"hi there\"" }`, |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 145 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 146 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 147 | x struct { |
Russ Cox | 25733a9 | 2011-06-29 09:52:34 -0400 | [diff] [blame] | 148 | a int8 `reflect:"hi \x00there\t\n\"\\"` |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 149 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 150 | }{}, |
Russ Cox | 25733a9 | 2011-06-29 09:52:34 -0400 | [diff] [blame] | 151 | `struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`, |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 152 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 153 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 154 | x struct { |
Russ Cox | 6672b40 | 2010-06-14 11:23:11 -0700 | [diff] [blame] | 155 | f func(args ...int) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 156 | } |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 157 | }{}, |
Russ Cox | 6672b40 | 2010-06-14 11:23:11 -0700 | [diff] [blame] | 158 | "struct { f func(...int) }", |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 159 | }, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 160 | {struct { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 161 | x (interface { |
Robert Griesemer | 1be05bb | 2010-02-24 13:24:37 -0800 | [diff] [blame] | 162 | a(func(func(int) int) func(func(int)) int) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 163 | b() |
| 164 | }) |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 165 | }{}, |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 166 | "interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }", |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 167 | }, |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 168 | } |
| 169 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 170 | var valueTests = []pair{ |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 171 | {new(int8), "8"}, |
| 172 | {new(int16), "16"}, |
| 173 | {new(int32), "32"}, |
| 174 | {new(int64), "64"}, |
| 175 | {new(uint8), "8"}, |
| 176 | {new(uint16), "16"}, |
| 177 | {new(uint32), "32"}, |
| 178 | {new(uint64), "64"}, |
| 179 | {new(float32), "256.25"}, |
| 180 | {new(float64), "512.125"}, |
| 181 | {new(string), "stringy cheese"}, |
| 182 | {new(bool), "true"}, |
| 183 | {new(*int8), "*int8(0)"}, |
| 184 | {new(**int8), "**int8(0)"}, |
| 185 | {new([5]int32), "[5]int32{0, 0, 0, 0, 0}"}, |
| 186 | {new(**integer), "**reflect_test.integer(0)"}, |
Russ Cox | 434a6c8 | 2011-12-02 14:45:07 -0500 | [diff] [blame] | 187 | {new(map[string]int32), "map[string]int32{<can't iterate on maps>}"}, |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 188 | {new(chan<- string), "chan<- string"}, |
| 189 | {new(func(a int8, b int32)), "func(int8, int32)(0)"}, |
| 190 | {new(struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 191 | c chan *int32 |
| 192 | d float32 |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 193 | }), |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 194 | "struct { c chan *int32; d float32 }{chan *int32, 0}", |
| 195 | }, |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 196 | {new(struct{ c func(chan *integer, *int8) }), |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 197 | "struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}", |
| 198 | }, |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 199 | {new(struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 200 | a int8 |
| 201 | b int32 |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 202 | }), |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 203 | "struct { a int8; b int32 }{0, 0}", |
| 204 | }, |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 205 | {new(struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 206 | a int8 |
| 207 | b int8 |
| 208 | c int32 |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 209 | }), |
Robert Griesemer | 7151d23 | 2009-11-05 18:27:30 -0800 | [diff] [blame] | 210 | "struct { a int8; b int8; c int32 }{0, 0, 0}", |
| 211 | }, |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 212 | } |
| 213 | |
| 214 | func testType(t *testing.T, i int, typ Type, want string) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 215 | s := typ.String() |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 216 | if s != want { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 217 | t.Errorf("#%d: have %#q, want %#q", i, s, want) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 218 | } |
| 219 | } |
| 220 | |
| 221 | func TestTypes(t *testing.T) { |
| 222 | for i, tt := range typeTests { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 223 | testType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 224 | } |
| 225 | } |
| 226 | |
Adam Langley | a8a678f | 2009-10-21 19:51:27 -0700 | [diff] [blame] | 227 | func TestSet(t *testing.T) { |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 228 | for i, tt := range valueTests { |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 229 | v := ValueOf(tt.i) |
| 230 | v = v.Elem() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 231 | switch v.Kind() { |
| 232 | case Int: |
| 233 | v.SetInt(132) |
| 234 | case Int8: |
| 235 | v.SetInt(8) |
| 236 | case Int16: |
| 237 | v.SetInt(16) |
| 238 | case Int32: |
| 239 | v.SetInt(32) |
| 240 | case Int64: |
| 241 | v.SetInt(64) |
| 242 | case Uint: |
| 243 | v.SetUint(132) |
| 244 | case Uint8: |
| 245 | v.SetUint(8) |
| 246 | case Uint16: |
| 247 | v.SetUint(16) |
| 248 | case Uint32: |
| 249 | v.SetUint(32) |
| 250 | case Uint64: |
| 251 | v.SetUint(64) |
| 252 | case Float32: |
| 253 | v.SetFloat(256.25) |
| 254 | case Float64: |
| 255 | v.SetFloat(512.125) |
| 256 | case Complex64: |
| 257 | v.SetComplex(532.125 + 10i) |
| 258 | case Complex128: |
| 259 | v.SetComplex(564.25 + 1i) |
| 260 | case String: |
| 261 | v.SetString("stringy cheese") |
| 262 | case Bool: |
| 263 | v.SetBool(true) |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 264 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 265 | s := valueToString(v) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 266 | if s != tt.s { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 267 | t.Errorf("#%d: have %#q, want %#q", i, s, tt.s) |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 268 | } |
| 269 | } |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 270 | } |
| 271 | |
Adam Langley | a8a678f | 2009-10-21 19:51:27 -0700 | [diff] [blame] | 272 | func TestSetValue(t *testing.T) { |
| 273 | for i, tt := range valueTests { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 274 | v := ValueOf(tt.i).Elem() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 275 | switch v.Kind() { |
| 276 | case Int: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 277 | v.Set(ValueOf(int(132))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 278 | case Int8: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 279 | v.Set(ValueOf(int8(8))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 280 | case Int16: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 281 | v.Set(ValueOf(int16(16))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 282 | case Int32: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 283 | v.Set(ValueOf(int32(32))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 284 | case Int64: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 285 | v.Set(ValueOf(int64(64))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 286 | case Uint: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 287 | v.Set(ValueOf(uint(132))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 288 | case Uint8: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 289 | v.Set(ValueOf(uint8(8))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 290 | case Uint16: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 291 | v.Set(ValueOf(uint16(16))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 292 | case Uint32: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 293 | v.Set(ValueOf(uint32(32))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 294 | case Uint64: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 295 | v.Set(ValueOf(uint64(64))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 296 | case Float32: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 297 | v.Set(ValueOf(float32(256.25))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 298 | case Float64: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 299 | v.Set(ValueOf(512.125)) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 300 | case Complex64: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 301 | v.Set(ValueOf(complex64(532.125 + 10i))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 302 | case Complex128: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 303 | v.Set(ValueOf(complex128(564.25 + 1i))) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 304 | case String: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 305 | v.Set(ValueOf("stringy cheese")) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 306 | case Bool: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 307 | v.Set(ValueOf(true)) |
Adam Langley | a8a678f | 2009-10-21 19:51:27 -0700 | [diff] [blame] | 308 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 309 | s := valueToString(v) |
Adam Langley | a8a678f | 2009-10-21 19:51:27 -0700 | [diff] [blame] | 310 | if s != tt.s { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 311 | t.Errorf("#%d: have %#q, want %#q", i, s, tt.s) |
Adam Langley | a8a678f | 2009-10-21 19:51:27 -0700 | [diff] [blame] | 312 | } |
| 313 | } |
| 314 | } |
| 315 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 316 | var _i = 7 |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 317 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 318 | var valueToStringTests = []pair{ |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 319 | {123, "123"}, |
| 320 | {123.5, "123.5"}, |
| 321 | {byte(123), "123"}, |
| 322 | {"abc", "abc"}, |
| 323 | {T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"}, |
| 324 | {new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"}, |
| 325 | {[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"}, |
| 326 | {&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"}, |
| 327 | {[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"}, |
| 328 | {&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"}, |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 329 | } |
| 330 | |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 331 | func TestValueToString(t *testing.T) { |
| 332 | for i, test := range valueToStringTests { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 333 | s := valueToString(ValueOf(test.i)) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 334 | if s != test.s { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 335 | t.Errorf("#%d: have %#q, want %#q", i, s, test.s) |
Rob Pike | 419e1e0 | 2008-11-12 19:05:05 -0800 | [diff] [blame] | 336 | } |
| 337 | } |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 338 | } |
Rob Pike | 419e1e0 | 2008-11-12 19:05:05 -0800 | [diff] [blame] | 339 | |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 340 | func TestArrayElemSet(t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 341 | v := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 342 | v.Index(4).SetInt(123) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 343 | s := valueToString(v) |
| 344 | const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}" |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 345 | if s != want { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 346 | t.Errorf("[10]int: have %#q want %#q", s, want) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 347 | } |
Rob Pike | a45f947 | 2008-11-04 22:54:11 -0800 | [diff] [blame] | 348 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 349 | v = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 350 | v.Index(4).SetInt(123) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 351 | s = valueToString(v) |
| 352 | const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}" |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 353 | if s != want1 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 354 | t.Errorf("[]int: have %#q want %#q", s, want1) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 355 | } |
| 356 | } |
Rob Pike | a45f947 | 2008-11-04 22:54:11 -0800 | [diff] [blame] | 357 | |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 358 | func TestPtrPointTo(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 359 | var ip *int32 |
| 360 | var i int32 = 1234 |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 361 | vip := ValueOf(&ip) |
| 362 | vi := ValueOf(&i).Elem() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 363 | vip.Elem().Set(vi.Addr()) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 364 | if *ip != 1234 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 365 | t.Errorf("got %d, want 1234", *ip) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 366 | } |
Robert Griesemer | a48b35e | 2010-08-17 15:12:28 -0700 | [diff] [blame] | 367 | |
| 368 | ip = nil |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 369 | vp := ValueOf(&ip).Elem() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 370 | vp.Set(Zero(vp.Type())) |
Robert Griesemer | a48b35e | 2010-08-17 15:12:28 -0700 | [diff] [blame] | 371 | if ip != nil { |
| 372 | t.Errorf("got non-nil (%p), want nil", ip) |
| 373 | } |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 374 | } |
Rob Pike | a45f947 | 2008-11-04 22:54:11 -0800 | [diff] [blame] | 375 | |
Russ Cox | 7295b61 | 2010-04-20 17:02:08 -0700 | [diff] [blame] | 376 | func TestPtrSetNil(t *testing.T) { |
| 377 | var i int32 = 1234 |
| 378 | ip := &i |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 379 | vip := ValueOf(&ip) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 380 | vip.Elem().Set(Zero(vip.Elem().Type())) |
Russ Cox | 7295b61 | 2010-04-20 17:02:08 -0700 | [diff] [blame] | 381 | if ip != nil { |
| 382 | t.Errorf("got non-nil (%d), want nil", *ip) |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | func TestMapSetNil(t *testing.T) { |
| 387 | m := make(map[string]int) |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 388 | vm := ValueOf(&m) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 389 | vm.Elem().Set(Zero(vm.Elem().Type())) |
Russ Cox | 7295b61 | 2010-04-20 17:02:08 -0700 | [diff] [blame] | 390 | if m != nil { |
| 391 | t.Errorf("got non-nil (%p), want nil", m) |
| 392 | } |
| 393 | } |
| 394 | |
Rob Pike | e02f2b5 | 2009-11-08 21:57:59 -0800 | [diff] [blame] | 395 | func TestAll(t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 396 | testType(t, 1, TypeOf((int8)(0)), "int8") |
| 397 | testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8") |
Rob Pike | a45f947 | 2008-11-04 22:54:11 -0800 | [diff] [blame] | 398 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 399 | typ := TypeOf((*struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 400 | c chan *int32 |
| 401 | d float32 |
| 402 | })(nil)) |
| 403 | testType(t, 3, typ, "*struct { c chan *int32; d float32 }") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 404 | etyp := typ.Elem() |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 405 | testType(t, 4, etyp, "struct { c chan *int32; d float32 }") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 406 | styp := etyp |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 407 | f := styp.Field(0) |
| 408 | testType(t, 5, f.Type, "chan *int32") |
Rob Pike | a93c5c8 | 2009-07-16 18:21:14 -0700 | [diff] [blame] | 409 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 410 | f, present := styp.FieldByName("d") |
Rob Pike | a93c5c8 | 2009-07-16 18:21:14 -0700 | [diff] [blame] | 411 | if !present { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 412 | t.Errorf("FieldByName says present field is absent") |
Rob Pike | a93c5c8 | 2009-07-16 18:21:14 -0700 | [diff] [blame] | 413 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 414 | testType(t, 6, f.Type, "float32") |
Rob Pike | a45f947 | 2008-11-04 22:54:11 -0800 | [diff] [blame] | 415 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 416 | f, present = styp.FieldByName("absent") |
Rob Pike | a93c5c8 | 2009-07-16 18:21:14 -0700 | [diff] [blame] | 417 | if present { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 418 | t.Errorf("FieldByName says absent field is present") |
Rob Pike | a93c5c8 | 2009-07-16 18:21:14 -0700 | [diff] [blame] | 419 | } |
| 420 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 421 | typ = TypeOf([32]int32{}) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 422 | testType(t, 7, typ, "[32]int32") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 423 | testType(t, 8, typ.Elem(), "int32") |
Rob Pike | a45f947 | 2008-11-04 22:54:11 -0800 | [diff] [blame] | 424 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 425 | typ = TypeOf((map[string]*int32)(nil)) |
Russ Cox | 434a6c8 | 2011-12-02 14:45:07 -0500 | [diff] [blame] | 426 | testType(t, 9, typ, "map[string]*int32") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 427 | mtyp := typ |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 428 | testType(t, 10, mtyp.Key(), "string") |
| 429 | testType(t, 11, mtyp.Elem(), "*int32") |
Rob Pike | bdbb958 | 2008-11-05 08:17:01 -0800 | [diff] [blame] | 430 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 431 | typ = TypeOf((chan<- string)(nil)) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 432 | testType(t, 12, typ, "chan<- string") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 433 | testType(t, 13, typ.Elem(), "string") |
Rob Pike | 5a1cbe8 | 2008-11-05 13:01:33 -0800 | [diff] [blame] | 434 | |
| 435 | // make sure tag strings are not part of element type |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 436 | typ = TypeOf(struct { |
Russ Cox | 25733a9 | 2011-06-29 09:52:34 -0400 | [diff] [blame] | 437 | d []uint32 `reflect:"TAG"` |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 438 | }{}).Field(0).Type |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 439 | testType(t, 14, typ, "[]uint32") |
Rob Pike | 536b1f2 | 2008-10-23 17:13:34 -0700 | [diff] [blame] | 440 | } |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 441 | |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 442 | func TestInterfaceGet(t *testing.T) { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 443 | var inter struct { |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 444 | E interface{} |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 445 | } |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 446 | inter.E = 123.456 |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 447 | v1 := ValueOf(&inter) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 448 | v2 := v1.Elem().Field(0) |
Luuk van Dijk | 50110c9 | 2011-10-31 18:09:40 +0100 | [diff] [blame] | 449 | assert(t, v2.Type().String(), "interface {}") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 450 | i2 := v2.Interface() |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 451 | v3 := ValueOf(i2) |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 452 | assert(t, v3.Type().String(), "float64") |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 453 | } |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 454 | |
Russ Cox | ac6ebfd | 2009-04-06 21:28:04 -0700 | [diff] [blame] | 455 | func TestInterfaceValue(t *testing.T) { |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 456 | var inter struct { |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 457 | E interface{} |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 458 | } |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 459 | inter.E = 123.456 |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 460 | v1 := ValueOf(&inter) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 461 | v2 := v1.Elem().Field(0) |
Luuk van Dijk | 50110c9 | 2011-10-31 18:09:40 +0100 | [diff] [blame] | 462 | assert(t, v2.Type().String(), "interface {}") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 463 | v3 := v2.Elem() |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 464 | assert(t, v3.Type().String(), "float64") |
Russ Cox | 64627b0 | 2009-04-15 00:55:58 -0700 | [diff] [blame] | 465 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 466 | i3 := v2.Interface() |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 467 | if _, ok := i3.(float64); !ok { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 468 | t.Error("v2.Interface() did not return float64, got ", TypeOf(i3)) |
Russ Cox | 4b8c13d | 2009-04-14 19:03:57 -0700 | [diff] [blame] | 469 | } |
Russ Cox | ac6ebfd | 2009-04-06 21:28:04 -0700 | [diff] [blame] | 470 | } |
| 471 | |
Ian Lance Taylor | ca9765d | 2009-04-14 06:46:01 -0700 | [diff] [blame] | 472 | func TestFunctionValue(t *testing.T) { |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 473 | var x interface{} = func() {} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 474 | v := ValueOf(x) |
Russ Cox | 46deaa2 | 2011-12-06 10:48:17 -0500 | [diff] [blame] | 475 | if fmt.Sprint(v.Interface()) != fmt.Sprint(x) { |
| 476 | t.Fatalf("TestFunction returned wrong pointer") |
Ian Lance Taylor | ca9765d | 2009-04-14 06:46:01 -0700 | [diff] [blame] | 477 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 478 | assert(t, v.Type().String(), "func()") |
Ian Lance Taylor | ca9765d | 2009-04-14 06:46:01 -0700 | [diff] [blame] | 479 | } |
| 480 | |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 481 | var appendTests = []struct { |
| 482 | orig, extra []int |
| 483 | }{ |
| 484 | {make([]int, 2, 4), []int{22}}, |
| 485 | {make([]int, 2, 4), []int{22, 33, 44}}, |
| 486 | } |
| 487 | |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 488 | func sameInts(x, y []int) bool { |
| 489 | if len(x) != len(y) { |
| 490 | return false |
| 491 | } |
| 492 | for i, xx := range x { |
| 493 | if xx != y[i] { |
| 494 | return false |
| 495 | } |
| 496 | } |
| 497 | return true |
| 498 | } |
| 499 | |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 500 | func TestAppend(t *testing.T) { |
| 501 | for i, test := range appendTests { |
| 502 | origLen, extraLen := len(test.orig), len(test.extra) |
| 503 | want := append(test.orig, test.extra...) |
| 504 | // Convert extra from []int to []Value. |
| 505 | e0 := make([]Value, len(test.extra)) |
| 506 | for j, e := range test.extra { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 507 | e0[j] = ValueOf(e) |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 508 | } |
| 509 | // Convert extra from []int to *SliceValue. |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 510 | e1 := ValueOf(test.extra) |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 511 | // Test Append. |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 512 | a0 := ValueOf(test.orig) |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 513 | have0 := Append(a0, e0...).Interface().([]int) |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 514 | if !sameInts(have0, want) { |
| 515 | t.Errorf("Append #%d: have %v, want %v (%p %p)", i, have0, want, test.orig, have0) |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 516 | } |
| 517 | // Check that the orig and extra slices were not modified. |
| 518 | if len(test.orig) != origLen { |
| 519 | t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen) |
| 520 | } |
| 521 | if len(test.extra) != extraLen { |
| 522 | t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen) |
| 523 | } |
| 524 | // Test AppendSlice. |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 525 | a1 := ValueOf(test.orig) |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 526 | have1 := AppendSlice(a1, e1).Interface().([]int) |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 527 | if !sameInts(have1, want) { |
Nigel Tao | 8b64cd9 | 2010-12-15 08:50:08 +1100 | [diff] [blame] | 528 | t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want) |
| 529 | } |
| 530 | // Check that the orig and extra slices were not modified. |
| 531 | if len(test.orig) != origLen { |
| 532 | t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen) |
| 533 | } |
| 534 | if len(test.extra) != extraLen { |
| 535 | t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen) |
| 536 | } |
| 537 | } |
| 538 | } |
| 539 | |
| 540 | func TestCopy(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 541 | a := []int{1, 2, 3, 4, 10, 9, 8, 7} |
| 542 | b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44} |
| 543 | c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44} |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 544 | for i := 0; i < len(b); i++ { |
| 545 | if b[i] != c[i] { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 546 | t.Fatalf("b != c before test") |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 547 | } |
| 548 | } |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 549 | a1 := a |
| 550 | b1 := b |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 551 | aa := ValueOf(&a1).Elem() |
| 552 | ab := ValueOf(&b1).Elem() |
Russ Cox | d47d888 | 2008-12-18 22:37:22 -0800 | [diff] [blame] | 553 | for tocopy := 1; tocopy <= 7; tocopy++ { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 554 | aa.SetLen(tocopy) |
Nigel Tao | 73fd298 | 2010-12-12 20:27:29 +1100 | [diff] [blame] | 555 | Copy(ab, aa) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 556 | aa.SetLen(8) |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 557 | for i := 0; i < tocopy; i++ { |
| 558 | if a[i] != b[i] { |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 559 | t.Errorf("(i) tocopy=%d a[%d]=%d, b[%d]=%d", |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 560 | tocopy, i, a[i], i, b[i]) |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 561 | } |
| 562 | } |
| 563 | for i := tocopy; i < len(b); i++ { |
| 564 | if b[i] != c[i] { |
| 565 | if i < len(a) { |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 566 | t.Errorf("(ii) tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d", |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 567 | tocopy, i, a[i], i, b[i], i, c[i]) |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 568 | } else { |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 569 | t.Errorf("(iii) tocopy=%d b[%d]=%d, c[%d]=%d", |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 570 | tocopy, i, b[i], i, c[i]) |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 571 | } |
Russ Cox | d47d888 | 2008-12-18 22:37:22 -0800 | [diff] [blame] | 572 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 573 | t.Logf("tocopy=%d elem %d is okay\n", tocopy, i) |
Russ Cox | d0e30cd | 2008-12-10 15:55:59 -0800 | [diff] [blame] | 574 | } |
| 575 | } |
| 576 | } |
| 577 | } |
Russ Cox | 484ba93 | 2009-01-09 00:17:46 -0800 | [diff] [blame] | 578 | |
Gustavo Niemeyer | 6850dba | 2011-04-27 18:22:53 -0300 | [diff] [blame] | 579 | func TestCopyArray(t *testing.T) { |
| 580 | a := [8]int{1, 2, 3, 4, 10, 9, 8, 7} |
| 581 | b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44} |
| 582 | c := b |
| 583 | aa := ValueOf(&a).Elem() |
| 584 | ab := ValueOf(&b).Elem() |
| 585 | Copy(ab, aa) |
| 586 | for i := 0; i < len(a); i++ { |
| 587 | if a[i] != b[i] { |
| 588 | t.Errorf("(i) a[%d]=%d, b[%d]=%d", i, a[i], i, b[i]) |
| 589 | } |
| 590 | } |
| 591 | for i := len(a); i < len(b); i++ { |
| 592 | if b[i] != c[i] { |
Gustavo Niemeyer | 3e9a1d5 | 2011-04-28 14:16:41 -0300 | [diff] [blame] | 593 | t.Errorf("(ii) b[%d]=%d, c[%d]=%d", i, b[i], i, c[i]) |
Gustavo Niemeyer | 6850dba | 2011-04-27 18:22:53 -0300 | [diff] [blame] | 594 | } else { |
| 595 | t.Logf("elem %d is okay\n", i) |
| 596 | } |
| 597 | } |
| 598 | } |
| 599 | |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 600 | func TestBigUnnamedStruct(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 601 | b := struct{ a, b, c, d int64 }{1, 2, 3, 4} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 602 | v := ValueOf(b) |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 603 | b1 := v.Interface().(struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 604 | a, b, c, d int64 |
| 605 | }) |
Russ Cox | 484ba93 | 2009-01-09 00:17:46 -0800 | [diff] [blame] | 606 | if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 607 | t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1) |
Russ Cox | 484ba93 | 2009-01-09 00:17:46 -0800 | [diff] [blame] | 608 | } |
| 609 | } |
| 610 | |
Rob Pike | ed2ac9b | 2009-01-16 12:48:07 -0800 | [diff] [blame] | 611 | type big struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 612 | a, b, c, d, e int64 |
Russ Cox | 484ba93 | 2009-01-09 00:17:46 -0800 | [diff] [blame] | 613 | } |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 614 | |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 615 | func TestBigStruct(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 616 | b := big{1, 2, 3, 4, 5} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 617 | v := ValueOf(b) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 618 | b1 := v.Interface().(big) |
Russ Cox | 484ba93 | 2009-01-09 00:17:46 -0800 | [diff] [blame] | 619 | if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 620 | t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1) |
Russ Cox | 484ba93 | 2009-01-09 00:17:46 -0800 | [diff] [blame] | 621 | } |
| 622 | } |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 623 | |
| 624 | type Basic struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 625 | x int |
| 626 | y float32 |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 627 | } |
| 628 | |
Russ Cox | 64627b0 | 2009-04-15 00:55:58 -0700 | [diff] [blame] | 629 | type NotBasic Basic |
| 630 | |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 631 | type DeepEqualTest struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 632 | a, b interface{} |
| 633 | eq bool |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 634 | } |
| 635 | |
Rob Pike | 3a1c226 | 2012-02-24 16:25:39 +1100 | [diff] [blame] | 636 | // Simple functions for DeepEqual tests. |
| 637 | var ( |
| 638 | fn1 func() // nil. |
| 639 | fn2 func() // nil. |
| 640 | fn3 = func() { fn1() } // Not nil. |
| 641 | ) |
| 642 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 643 | var deepEqualTests = []DeepEqualTest{ |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 644 | // Equalities |
Rob Pike | 5337290 | 2012-04-23 12:07:02 +1000 | [diff] [blame] | 645 | {nil, nil, true}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 646 | {1, 1, true}, |
| 647 | {int32(1), int32(1), true}, |
| 648 | {0.5, 0.5, true}, |
| 649 | {float32(0.5), float32(0.5), true}, |
| 650 | {"hello", "hello", true}, |
| 651 | {make([]int, 10), make([]int, 10), true}, |
| 652 | {&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true}, |
| 653 | {Basic{1, 0.5}, Basic{1, 0.5}, true}, |
Russ Cox | eb69292 | 2011-11-01 22:05:34 -0400 | [diff] [blame] | 654 | {error(nil), error(nil), true}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 655 | {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true}, |
Rob Pike | 3a1c226 | 2012-02-24 16:25:39 +1100 | [diff] [blame] | 656 | {fn1, fn2, true}, |
Russ Cox | a439f66 | 2009-07-01 16:45:09 -0700 | [diff] [blame] | 657 | |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 658 | // Inequalities |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 659 | {1, 2, false}, |
| 660 | {int32(1), int32(2), false}, |
| 661 | {0.5, 0.6, false}, |
| 662 | {float32(0.5), float32(0.6), false}, |
| 663 | {"hello", "hey", false}, |
| 664 | {make([]int, 10), make([]int, 11), false}, |
| 665 | {&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false}, |
| 666 | {Basic{1, 0.5}, Basic{1, 0.6}, false}, |
| 667 | {Basic{1, 0}, Basic{2, 0}, false}, |
| 668 | {map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false}, |
| 669 | {map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false}, |
| 670 | {map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false}, |
| 671 | {map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false}, |
| 672 | {nil, 1, false}, |
| 673 | {1, nil, false}, |
Rob Pike | 3a1c226 | 2012-02-24 16:25:39 +1100 | [diff] [blame] | 674 | {fn1, fn3, false}, |
| 675 | {fn3, fn3, false}, |
Russ Cox | a439f66 | 2009-07-01 16:45:09 -0700 | [diff] [blame] | 676 | |
Russ Cox | 4e65478 | 2011-11-14 16:11:15 -0500 | [diff] [blame] | 677 | // Nil vs empty: not the same. |
| 678 | {[]int{}, []int(nil), false}, |
| 679 | {[]int{}, []int{}, true}, |
| 680 | {[]int(nil), []int(nil), true}, |
| 681 | {map[int]int{}, map[int]int(nil), false}, |
| 682 | {map[int]int{}, map[int]int{}, true}, |
| 683 | {map[int]int(nil), map[int]int(nil), true}, |
| 684 | |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 685 | // Mismatched types |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 686 | {1, 1.0, false}, |
| 687 | {int32(1), int64(1), false}, |
| 688 | {0.5, "hello", false}, |
| 689 | {[]int{1, 2, 3}, [3]int{1, 2, 3}, false}, |
| 690 | {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, |
| 691 | {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, |
| 692 | {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 693 | } |
| 694 | |
| 695 | func TestDeepEqual(t *testing.T) { |
Russ Cox | ca6a0fe | 2009-09-15 09:41:59 -0700 | [diff] [blame] | 696 | for _, test := range deepEqualTests { |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 697 | if r := DeepEqual(test.a, test.b); r != test.eq { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 698 | t.Errorf("DeepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq) |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 699 | } |
| 700 | } |
| 701 | } |
| 702 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 703 | func TestTypeOf(t *testing.T) { |
Rob Pike | 5337290 | 2012-04-23 12:07:02 +1000 | [diff] [blame] | 704 | // Special case for nil |
| 705 | if typ := TypeOf(nil); typ != nil { |
| 706 | t.Errorf("expected nil type for nil value; got %v", typ) |
| 707 | } |
Russ Cox | ca6a0fe | 2009-09-15 09:41:59 -0700 | [diff] [blame] | 708 | for _, test := range deepEqualTests { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 709 | v := ValueOf(test.a) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 710 | if !v.IsValid() { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 711 | continue |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 712 | } |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 713 | typ := TypeOf(test.a) |
Russ Cox | 4866223 | 2009-06-25 14:25:38 -0700 | [diff] [blame] | 714 | if typ != v.Type() { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 715 | t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type()) |
Russ Cox | 4866223 | 2009-06-25 14:25:38 -0700 | [diff] [blame] | 716 | } |
| 717 | } |
| 718 | } |
| 719 | |
Rob Pike | 1880b90 | 2009-07-10 11:20:10 -0700 | [diff] [blame] | 720 | type Recursive struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 721 | x int |
| 722 | r *Recursive |
Rob Pike | 1880b90 | 2009-07-10 11:20:10 -0700 | [diff] [blame] | 723 | } |
| 724 | |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 725 | func TestDeepEqualRecursiveStruct(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 726 | a, b := new(Recursive), new(Recursive) |
| 727 | *a = Recursive{12, a} |
| 728 | *b = Recursive{12, b} |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 729 | if !DeepEqual(a, b) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 730 | t.Error("DeepEqual(recursive same) = false, want true") |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 731 | } |
| 732 | } |
| 733 | |
Russ Cox | 45bdf03 | 2010-06-20 12:16:25 -0700 | [diff] [blame] | 734 | type _Complex struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 735 | a int |
Russ Cox | 45bdf03 | 2010-06-20 12:16:25 -0700 | [diff] [blame] | 736 | b [3]*_Complex |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 737 | c *string |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 738 | d map[float64]float64 |
Rob Pike | 1880b90 | 2009-07-10 11:20:10 -0700 | [diff] [blame] | 739 | } |
| 740 | |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 741 | func TestDeepEqualComplexStruct(t *testing.T) { |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 742 | m := make(map[float64]float64) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 743 | stra, strb := "hello", "hello" |
Russ Cox | 45bdf03 | 2010-06-20 12:16:25 -0700 | [diff] [blame] | 744 | a, b := new(_Complex), new(_Complex) |
| 745 | *a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m} |
| 746 | *b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m} |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 747 | if !DeepEqual(a, b) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 748 | t.Error("DeepEqual(complex same) = false, want true") |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 749 | } |
| 750 | } |
| 751 | |
| 752 | func TestDeepEqualComplexStructInequality(t *testing.T) { |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 753 | m := make(map[float64]float64) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 754 | stra, strb := "hello", "helloo" // Difference is here |
Russ Cox | 45bdf03 | 2010-06-20 12:16:25 -0700 | [diff] [blame] | 755 | a, b := new(_Complex), new(_Complex) |
| 756 | *a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m} |
| 757 | *b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m} |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 758 | if DeepEqual(a, b) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 759 | t.Error("DeepEqual(complex different) = true, want false") |
Daniel Nadasi | c4ad4f9 | 2009-04-01 22:20:18 -0700 | [diff] [blame] | 760 | } |
| 761 | } |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 762 | |
Russ Cox | 86e6a44 | 2011-05-03 10:38:37 -0400 | [diff] [blame] | 763 | type UnexpT struct { |
| 764 | m map[int]int |
| 765 | } |
| 766 | |
| 767 | func TestDeepEqualUnexportedMap(t *testing.T) { |
| 768 | // Check that DeepEqual can look at unexported fields. |
| 769 | x1 := UnexpT{map[int]int{1: 2}} |
| 770 | x2 := UnexpT{map[int]int{1: 2}} |
| 771 | if !DeepEqual(&x1, &x2) { |
| 772 | t.Error("DeepEqual(x1, x2) = false, want true") |
| 773 | } |
| 774 | |
| 775 | y1 := UnexpT{map[int]int{2: 3}} |
| 776 | if DeepEqual(&x1, &y1) { |
| 777 | t.Error("DeepEqual(x1, y1) = true, want false") |
| 778 | } |
| 779 | } |
| 780 | |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 781 | func check2ndField(x interface{}, offs uintptr, t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 782 | s := ValueOf(x) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 783 | f := s.Type().Field(1) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 784 | if f.Offset != offs { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 785 | t.Error("mismatched offsets in structure alignment:", f.Offset, offs) |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 786 | } |
| 787 | } |
| 788 | |
| 789 | // Check that structure alignment & offsets viewed through reflect agree with those |
| 790 | // from the compiler itself. |
| 791 | func TestAlignment(t *testing.T) { |
| 792 | type T1inner struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 793 | a int |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 794 | } |
| 795 | type T1 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 796 | T1inner |
| 797 | f int |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 798 | } |
| 799 | type T2inner struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 800 | a, b int |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 801 | } |
| 802 | type T2 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 803 | T2inner |
| 804 | f int |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 805 | } |
| 806 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 807 | x := T1{T1inner{2}, 17} |
| 808 | check2ndField(x, uintptr(unsafe.Pointer(&x.f))-uintptr(unsafe.Pointer(&x)), t) |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 809 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 810 | x1 := T2{T2inner{2, 3}, 17} |
| 811 | check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t) |
Rob Pike | 93831d2 | 2009-04-29 22:16:53 -0700 | [diff] [blame] | 812 | } |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 813 | |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 814 | func Nil(a interface{}, t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 815 | n := ValueOf(a).Field(0) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 816 | if !n.IsNil() { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 817 | t.Errorf("%v should be nil", a) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 818 | } |
| 819 | } |
| 820 | |
| 821 | func NotNil(a interface{}, t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 822 | n := ValueOf(a).Field(0) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 823 | if n.IsNil() { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 824 | t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String()) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 825 | } |
| 826 | } |
| 827 | |
| 828 | func TestIsNil(t *testing.T) { |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 829 | // These implement IsNil. |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 830 | // Wrap in extra struct to hide interface type. |
| 831 | doNil := []interface{}{ |
Robert Griesemer | a05a546 | 2009-11-06 16:33:53 -0800 | [diff] [blame] | 832 | struct{ x *int }{}, |
| 833 | struct{ x interface{} }{}, |
| 834 | struct{ x map[string]int }{}, |
| 835 | struct{ x func() bool }{}, |
| 836 | struct{ x chan int }{}, |
| 837 | struct{ x []string }{}, |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 838 | } |
Russ Cox | ca6a0fe | 2009-09-15 09:41:59 -0700 | [diff] [blame] | 839 | for _, ts := range doNil { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 840 | ty := TypeOf(ts).Field(0).Type |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 841 | v := Zero(ty) |
| 842 | v.IsNil() // panics if not okay to call |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 843 | } |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 844 | |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 845 | // Check the implementations |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 846 | var pi struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 847 | x *int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 848 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 849 | Nil(pi, t) |
| 850 | pi.x = new(int) |
| 851 | NotNil(pi, t) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 852 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 853 | var si struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 854 | x []int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 855 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 856 | Nil(si, t) |
| 857 | si.x = make([]int, 10) |
| 858 | NotNil(si, t) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 859 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 860 | var ci struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 861 | x chan int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 862 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 863 | Nil(ci, t) |
| 864 | ci.x = make(chan int) |
| 865 | NotNil(ci, t) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 866 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 867 | var mi struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 868 | x map[int]int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 869 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 870 | Nil(mi, t) |
| 871 | mi.x = make(map[int]int) |
| 872 | NotNil(mi, t) |
Russ Cox | 64f4e0b | 2009-07-07 11:03:12 -0700 | [diff] [blame] | 873 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 874 | var ii struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 875 | x interface{} |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 876 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 877 | Nil(ii, t) |
| 878 | ii.x = 2 |
| 879 | NotNil(ii, t) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 880 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 881 | var fi struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 882 | x func(t *testing.T) |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 883 | } |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 884 | Nil(fi, t) |
| 885 | fi.x = TestIsNil |
| 886 | NotNil(fi, t) |
Rob Pike | a8f6e38 | 2009-05-12 14:57:44 -0700 | [diff] [blame] | 887 | } |
Russ Cox | 96cfd15 | 2009-05-21 11:50:20 -0700 | [diff] [blame] | 888 | |
| 889 | func TestInterfaceExtraction(t *testing.T) { |
| 890 | var s struct { |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 891 | W io.Writer |
Russ Cox | 96cfd15 | 2009-05-21 11:50:20 -0700 | [diff] [blame] | 892 | } |
| 893 | |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 894 | s.W = os.Stdout |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 895 | v := Indirect(ValueOf(&s)).Field(0).Interface() |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 896 | if v != s.W.(interface{}) { |
| 897 | t.Error("Interface() on interface: ", v, s.W) |
Russ Cox | 96cfd15 | 2009-05-21 11:50:20 -0700 | [diff] [blame] | 898 | } |
| 899 | } |
Russ Cox | f966623 | 2009-05-21 14:06:43 -0700 | [diff] [blame] | 900 | |
David Symonds | d4e57ff | 2009-06-15 18:35:04 -0700 | [diff] [blame] | 901 | func TestNilPtrValueSub(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 902 | var pi *int |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 903 | if pv := ValueOf(pi); pv.Elem().IsValid() { |
| 904 | t.Error("ValueOf((*int)(nil)).Elem().IsValid()") |
David Symonds | d4e57ff | 2009-06-15 18:35:04 -0700 | [diff] [blame] | 905 | } |
| 906 | } |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 907 | |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 908 | func TestMap(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 909 | m := map[string]int{"a": 1, "b": 2} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 910 | mv := ValueOf(m) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 911 | if n := mv.Len(); n != len(m) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 912 | t.Errorf("Len = %d, want %d", n, len(m)) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 913 | } |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 914 | keys := mv.MapKeys() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 915 | newmap := MakeMap(mv.Type()) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 916 | for k, v := range m { |
| 917 | // Check that returned Keys match keys in range. |
David Symonds | 9049abb | 2011-10-18 12:47:34 +1100 | [diff] [blame] | 918 | // These aren't required to be in the same order. |
| 919 | seen := false |
| 920 | for _, kv := range keys { |
| 921 | if kv.String() == k { |
| 922 | seen = true |
| 923 | break |
| 924 | } |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 925 | } |
David Symonds | 9049abb | 2011-10-18 12:47:34 +1100 | [diff] [blame] | 926 | if !seen { |
| 927 | t.Errorf("Missing key %q", k) |
| 928 | } |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 929 | |
| 930 | // Check that value lookup is correct. |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 931 | vv := mv.MapIndex(ValueOf(k)) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 932 | if vi := vv.Int(); vi != int64(v) { |
Rob Pike | 1ce6245 | 2010-12-07 16:42:54 -0500 | [diff] [blame] | 933 | t.Errorf("Key %q: have value %d, want %d", k, vi, v) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 934 | } |
| 935 | |
| 936 | // Copy into new map. |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 937 | newmap.SetMapIndex(ValueOf(k), ValueOf(v)) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 938 | } |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 939 | vv := mv.MapIndex(ValueOf("not-present")) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 940 | if vv.IsValid() { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 941 | t.Errorf("Invalid key: got non-nil value %s", valueToString(vv)) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 942 | } |
| 943 | |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 944 | newm := newmap.Interface().(map[string]int) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 945 | if len(newm) != len(m) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 946 | t.Errorf("length after copy: newm=%d, m=%d", newm, m) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 947 | } |
| 948 | |
| 949 | for k, v := range newm { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 950 | mv, ok := m[k] |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 951 | if mv != v { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 952 | t.Errorf("newm[%q] = %d, but m[%q] = %d, %v", k, v, k, mv, ok) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 953 | } |
| 954 | } |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 955 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 956 | newmap.SetMapIndex(ValueOf("a"), Value{}) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 957 | v, ok := newm["a"] |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 958 | if ok { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 959 | t.Errorf("newm[\"a\"] = %d after delete", v) |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 960 | } |
Russ Cox | 7295b61 | 2010-04-20 17:02:08 -0700 | [diff] [blame] | 961 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 962 | mv = ValueOf(&m).Elem() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 963 | mv.Set(Zero(mv.Type())) |
Russ Cox | 7295b61 | 2010-04-20 17:02:08 -0700 | [diff] [blame] | 964 | if m != nil { |
| 965 | t.Errorf("mv.Set(nil) failed") |
| 966 | } |
Russ Cox | 764b6ec | 2009-07-08 13:55:57 -0700 | [diff] [blame] | 967 | } |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 968 | |
| 969 | func TestChan(t *testing.T) { |
| 970 | for loop := 0; loop < 2; loop++ { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 971 | var c chan int |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 972 | var cv Value |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 973 | |
| 974 | // check both ways to allocate channels |
| 975 | switch loop { |
| 976 | case 1: |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 977 | c = make(chan int, 1) |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 978 | cv = ValueOf(c) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 979 | case 0: |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 980 | cv = MakeChan(TypeOf(c), 1) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 981 | c = cv.Interface().(chan int) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 982 | } |
| 983 | |
| 984 | // Send |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 985 | cv.Send(ValueOf(2)) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 986 | if i := <-c; i != 2 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 987 | t.Errorf("reflect Send 2, native recv %d", i) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 988 | } |
| 989 | |
| 990 | // Recv |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 991 | c <- 3 |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 992 | if i, ok := cv.Recv(); i.Int() != 3 || !ok { |
| 993 | t.Errorf("native send 3, reflect Recv %d, %t", i.Int(), ok) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 994 | } |
| 995 | |
| 996 | // TryRecv fail |
Russ Cox | 3f915f5 | 2011-03-11 14:47:44 -0500 | [diff] [blame] | 997 | val, ok := cv.TryRecv() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 998 | if val.IsValid() || ok { |
Russ Cox | 3f915f5 | 2011-03-11 14:47:44 -0500 | [diff] [blame] | 999 | t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1000 | } |
| 1001 | |
| 1002 | // TryRecv success |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1003 | c <- 4 |
Russ Cox | 3f915f5 | 2011-03-11 14:47:44 -0500 | [diff] [blame] | 1004 | val, ok = cv.TryRecv() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1005 | if !val.IsValid() { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1006 | t.Errorf("TryRecv on ready chan got nil") |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1007 | } else if i := val.Int(); i != 4 || !ok { |
Russ Cox | 3f915f5 | 2011-03-11 14:47:44 -0500 | [diff] [blame] | 1008 | t.Errorf("native send 4, TryRecv %d, %t", i, ok) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1009 | } |
| 1010 | |
| 1011 | // TrySend fail |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1012 | c <- 100 |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1013 | ok = cv.TrySend(ValueOf(5)) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1014 | i := <-c |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1015 | if ok { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1016 | t.Errorf("TrySend on full chan succeeded: value %d", i) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1017 | } |
| 1018 | |
| 1019 | // TrySend success |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1020 | ok = cv.TrySend(ValueOf(6)) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1021 | if !ok { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1022 | t.Errorf("TrySend on empty chan failed") |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1023 | } else { |
| 1024 | if i = <-c; i != 6 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1025 | t.Errorf("TrySend 6, recv %d", i) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1026 | } |
| 1027 | } |
Russ Cox | 653cef1 | 2009-08-26 10:47:18 -0700 | [diff] [blame] | 1028 | |
| 1029 | // Close |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1030 | c <- 123 |
| 1031 | cv.Close() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1032 | if i, ok := cv.Recv(); i.Int() != 123 || !ok { |
| 1033 | t.Errorf("send 123 then close; Recv %d, %t", i.Int(), ok) |
Russ Cox | 653cef1 | 2009-08-26 10:47:18 -0700 | [diff] [blame] | 1034 | } |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1035 | if i, ok := cv.Recv(); i.Int() != 0 || ok { |
| 1036 | t.Errorf("after close Recv %d, %t", i.Int(), ok) |
Russ Cox | 653cef1 | 2009-08-26 10:47:18 -0700 | [diff] [blame] | 1037 | } |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1038 | } |
| 1039 | |
| 1040 | // check creation of unbuffered channel |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1041 | var c chan int |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1042 | cv := MakeChan(TypeOf(c), 0) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1043 | c = cv.Interface().(chan int) |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1044 | if cv.TrySend(ValueOf(7)) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1045 | t.Errorf("TrySend on sync chan succeeded") |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1046 | } |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1047 | if v, ok := cv.TryRecv(); v.IsValid() || ok { |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 1048 | t.Errorf("TryRecv on sync chan succeeded: isvalid=%v ok=%v", v.IsValid(), ok) |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1049 | } |
Russ Cox | de7920e | 2009-08-26 12:42:22 -0700 | [diff] [blame] | 1050 | |
| 1051 | // len/cap |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1052 | cv = MakeChan(TypeOf(c), 10) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1053 | c = cv.Interface().(chan int) |
Russ Cox | de7920e | 2009-08-26 12:42:22 -0700 | [diff] [blame] | 1054 | for i := 0; i < 3; i++ { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1055 | c <- i |
Russ Cox | de7920e | 2009-08-26 12:42:22 -0700 | [diff] [blame] | 1056 | } |
| 1057 | if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1058 | t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c)) |
Russ Cox | de7920e | 2009-08-26 12:42:22 -0700 | [diff] [blame] | 1059 | } |
Russ Cox | 5ddaf9a | 2009-07-08 15:00:54 -0700 | [diff] [blame] | 1060 | } |
| 1061 | |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 1062 | // caseInfo describes a single case in a select test. |
| 1063 | type caseInfo struct { |
| 1064 | desc string |
| 1065 | canSelect bool |
| 1066 | recv Value |
| 1067 | closed bool |
| 1068 | helper func() |
| 1069 | panic bool |
| 1070 | } |
| 1071 | |
Russ Cox | 46f379c | 2012-09-22 08:52:27 -0400 | [diff] [blame] | 1072 | var allselect = flag.Bool("allselect", false, "exhaustive select test") |
| 1073 | |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 1074 | func TestSelect(t *testing.T) { |
| 1075 | selectWatch.once.Do(func() { go selectWatcher() }) |
| 1076 | |
| 1077 | var x exhaustive |
| 1078 | nch := 0 |
| 1079 | newop := func(n int, cap int) (ch, val Value) { |
| 1080 | nch++ |
| 1081 | if nch%101%2 == 1 { |
| 1082 | c := make(chan int, cap) |
| 1083 | ch = ValueOf(c) |
| 1084 | val = ValueOf(n) |
| 1085 | } else { |
| 1086 | c := make(chan string, cap) |
| 1087 | ch = ValueOf(c) |
| 1088 | val = ValueOf(fmt.Sprint(n)) |
| 1089 | } |
| 1090 | return |
| 1091 | } |
| 1092 | |
| 1093 | for n := 0; x.Next(); n++ { |
| 1094 | if testing.Short() && n >= 1000 { |
| 1095 | break |
| 1096 | } |
Russ Cox | 46f379c | 2012-09-22 08:52:27 -0400 | [diff] [blame] | 1097 | if n >= 100000 && !*allselect { |
| 1098 | break |
| 1099 | } |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 1100 | if n%100000 == 0 && testing.Verbose() { |
| 1101 | println("TestSelect", n) |
| 1102 | } |
| 1103 | var cases []SelectCase |
| 1104 | var info []caseInfo |
| 1105 | |
| 1106 | // Ready send. |
| 1107 | if x.Maybe() { |
| 1108 | ch, val := newop(len(cases), 1) |
| 1109 | cases = append(cases, SelectCase{ |
| 1110 | Dir: SelectSend, |
| 1111 | Chan: ch, |
| 1112 | Send: val, |
| 1113 | }) |
| 1114 | info = append(info, caseInfo{desc: "ready send", canSelect: true}) |
| 1115 | } |
| 1116 | |
| 1117 | // Ready recv. |
| 1118 | if x.Maybe() { |
| 1119 | ch, val := newop(len(cases), 1) |
| 1120 | ch.Send(val) |
| 1121 | cases = append(cases, SelectCase{ |
| 1122 | Dir: SelectRecv, |
| 1123 | Chan: ch, |
| 1124 | }) |
| 1125 | info = append(info, caseInfo{desc: "ready recv", canSelect: true, recv: val}) |
| 1126 | } |
| 1127 | |
| 1128 | // Blocking send. |
| 1129 | if x.Maybe() { |
| 1130 | ch, val := newop(len(cases), 0) |
| 1131 | cases = append(cases, SelectCase{ |
| 1132 | Dir: SelectSend, |
| 1133 | Chan: ch, |
| 1134 | Send: val, |
| 1135 | }) |
| 1136 | // Let it execute? |
| 1137 | if x.Maybe() { |
| 1138 | f := func() { ch.Recv() } |
| 1139 | info = append(info, caseInfo{desc: "blocking send", helper: f}) |
| 1140 | } else { |
| 1141 | info = append(info, caseInfo{desc: "blocking send"}) |
| 1142 | } |
| 1143 | } |
| 1144 | |
| 1145 | // Blocking recv. |
| 1146 | if x.Maybe() { |
| 1147 | ch, val := newop(len(cases), 0) |
| 1148 | cases = append(cases, SelectCase{ |
| 1149 | Dir: SelectRecv, |
| 1150 | Chan: ch, |
| 1151 | }) |
| 1152 | // Let it execute? |
| 1153 | if x.Maybe() { |
| 1154 | f := func() { ch.Send(val) } |
| 1155 | info = append(info, caseInfo{desc: "blocking recv", recv: val, helper: f}) |
| 1156 | } else { |
| 1157 | info = append(info, caseInfo{desc: "blocking recv"}) |
| 1158 | } |
| 1159 | } |
| 1160 | |
| 1161 | // Zero Chan send. |
| 1162 | if x.Maybe() { |
| 1163 | // Maybe include value to send. |
| 1164 | var val Value |
| 1165 | if x.Maybe() { |
| 1166 | val = ValueOf(100) |
| 1167 | } |
| 1168 | cases = append(cases, SelectCase{ |
| 1169 | Dir: SelectSend, |
| 1170 | Send: val, |
| 1171 | }) |
| 1172 | info = append(info, caseInfo{desc: "zero Chan send"}) |
| 1173 | } |
| 1174 | |
| 1175 | // Zero Chan receive. |
| 1176 | if x.Maybe() { |
| 1177 | cases = append(cases, SelectCase{ |
| 1178 | Dir: SelectRecv, |
| 1179 | }) |
| 1180 | info = append(info, caseInfo{desc: "zero Chan recv"}) |
| 1181 | } |
| 1182 | |
| 1183 | // nil Chan send. |
| 1184 | if x.Maybe() { |
| 1185 | cases = append(cases, SelectCase{ |
| 1186 | Dir: SelectSend, |
| 1187 | Chan: ValueOf((chan int)(nil)), |
| 1188 | Send: ValueOf(101), |
| 1189 | }) |
| 1190 | info = append(info, caseInfo{desc: "nil Chan send"}) |
| 1191 | } |
| 1192 | |
| 1193 | // nil Chan recv. |
| 1194 | if x.Maybe() { |
| 1195 | cases = append(cases, SelectCase{ |
| 1196 | Dir: SelectRecv, |
| 1197 | Chan: ValueOf((chan int)(nil)), |
| 1198 | }) |
| 1199 | info = append(info, caseInfo{desc: "nil Chan recv"}) |
| 1200 | } |
| 1201 | |
| 1202 | // closed Chan send. |
| 1203 | if x.Maybe() { |
| 1204 | ch := make(chan int) |
| 1205 | close(ch) |
| 1206 | cases = append(cases, SelectCase{ |
| 1207 | Dir: SelectSend, |
| 1208 | Chan: ValueOf(ch), |
| 1209 | Send: ValueOf(101), |
| 1210 | }) |
| 1211 | info = append(info, caseInfo{desc: "closed Chan send", canSelect: true, panic: true}) |
| 1212 | } |
| 1213 | |
| 1214 | // closed Chan recv. |
| 1215 | if x.Maybe() { |
| 1216 | ch, val := newop(len(cases), 0) |
| 1217 | ch.Close() |
| 1218 | val = Zero(val.Type()) |
| 1219 | cases = append(cases, SelectCase{ |
| 1220 | Dir: SelectRecv, |
| 1221 | Chan: ch, |
| 1222 | }) |
| 1223 | info = append(info, caseInfo{desc: "closed Chan recv", canSelect: true, closed: true, recv: val}) |
| 1224 | } |
| 1225 | |
| 1226 | var helper func() // goroutine to help the select complete |
| 1227 | |
| 1228 | // Add default? Must be last case here, but will permute. |
| 1229 | // Add the default if the select would otherwise |
| 1230 | // block forever, and maybe add it anyway. |
| 1231 | numCanSelect := 0 |
| 1232 | canProceed := false |
| 1233 | canBlock := true |
| 1234 | canPanic := false |
| 1235 | helpers := []int{} |
| 1236 | for i, c := range info { |
| 1237 | if c.canSelect { |
| 1238 | canProceed = true |
| 1239 | canBlock = false |
| 1240 | numCanSelect++ |
| 1241 | if c.panic { |
| 1242 | canPanic = true |
| 1243 | } |
| 1244 | } else if c.helper != nil { |
| 1245 | canProceed = true |
| 1246 | helpers = append(helpers, i) |
| 1247 | } |
| 1248 | } |
| 1249 | if !canProceed || x.Maybe() { |
| 1250 | cases = append(cases, SelectCase{ |
| 1251 | Dir: SelectDefault, |
| 1252 | }) |
| 1253 | info = append(info, caseInfo{desc: "default", canSelect: canBlock}) |
| 1254 | numCanSelect++ |
| 1255 | } else if canBlock { |
| 1256 | // Select needs to communicate with another goroutine. |
| 1257 | cas := &info[helpers[x.Choose(len(helpers))]] |
| 1258 | helper = cas.helper |
| 1259 | cas.canSelect = true |
| 1260 | numCanSelect++ |
| 1261 | } |
| 1262 | |
| 1263 | // Permute cases and case info. |
| 1264 | // Doing too much here makes the exhaustive loop |
| 1265 | // too exhausting, so just do two swaps. |
| 1266 | for loop := 0; loop < 2; loop++ { |
| 1267 | i := x.Choose(len(cases)) |
| 1268 | j := x.Choose(len(cases)) |
| 1269 | cases[i], cases[j] = cases[j], cases[i] |
| 1270 | info[i], info[j] = info[j], info[i] |
| 1271 | } |
| 1272 | |
| 1273 | if helper != nil { |
| 1274 | // We wait before kicking off a goroutine to satisfy a blocked select. |
| 1275 | // The pause needs to be big enough to let the select block before |
| 1276 | // we run the helper, but if we lose that race once in a while it's okay: the |
| 1277 | // select will just proceed immediately. Not a big deal. |
| 1278 | // For short tests we can grow [sic] the timeout a bit without fear of taking too long |
| 1279 | pause := 10 * time.Microsecond |
| 1280 | if testing.Short() { |
| 1281 | pause = 100 * time.Microsecond |
| 1282 | } |
| 1283 | time.AfterFunc(pause, helper) |
| 1284 | } |
| 1285 | |
| 1286 | // Run select. |
| 1287 | i, recv, recvOK, panicErr := runSelect(cases, info) |
| 1288 | if panicErr != nil && !canPanic { |
| 1289 | t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info), panicErr) |
| 1290 | } |
| 1291 | if panicErr == nil && canPanic && numCanSelect == 1 { |
| 1292 | t.Fatalf("%s\nselected #%d incorrectly (should panic)", fmtSelect(info), i) |
| 1293 | } |
| 1294 | if panicErr != nil { |
| 1295 | continue |
| 1296 | } |
| 1297 | |
| 1298 | cas := info[i] |
| 1299 | if !cas.canSelect { |
| 1300 | recvStr := "" |
| 1301 | if recv.IsValid() { |
| 1302 | recvStr = fmt.Sprintf(", received %v, %v", recv.Interface(), recvOK) |
| 1303 | } |
| 1304 | t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(info), i, recvStr) |
| 1305 | continue |
| 1306 | } |
| 1307 | if cas.panic { |
| 1308 | t.Fatalf("%s\nselected #%d incorrectly (case should panic)", fmtSelect(info), i) |
| 1309 | continue |
| 1310 | } |
| 1311 | |
| 1312 | if cases[i].Dir == SelectRecv { |
| 1313 | if !recv.IsValid() { |
| 1314 | t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed) |
| 1315 | } |
| 1316 | if !cas.recv.IsValid() { |
| 1317 | t.Fatalf("%s\nselected #%d but internal error: missing recv value", fmtSelect(info), i) |
| 1318 | } |
| 1319 | if recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed { |
| 1320 | if recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed { |
| 1321 | t.Fatalf("%s\nselected #%d, got %#v, %v, and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface()) |
| 1322 | } |
| 1323 | t.Fatalf("%s\nselected #%d but got %#v, %v, want %#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed) |
| 1324 | } |
| 1325 | } else { |
| 1326 | if recv.IsValid() || recvOK { |
| 1327 | t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false) |
| 1328 | } |
| 1329 | } |
| 1330 | } |
| 1331 | } |
| 1332 | |
| 1333 | // selectWatch and the selectWatcher are a watchdog mechanism for running Select. |
| 1334 | // If the selectWatcher notices that the select has been blocked for >1 second, it prints |
| 1335 | // an error describing the select and panics the entire test binary. |
| 1336 | var selectWatch struct { |
| 1337 | sync.Mutex |
| 1338 | once sync.Once |
| 1339 | now time.Time |
| 1340 | info []caseInfo |
| 1341 | } |
| 1342 | |
| 1343 | func selectWatcher() { |
| 1344 | for { |
| 1345 | time.Sleep(1 * time.Second) |
| 1346 | selectWatch.Lock() |
| 1347 | if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second { |
| 1348 | fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info)) |
| 1349 | panic("select stuck") |
| 1350 | } |
| 1351 | selectWatch.Unlock() |
| 1352 | } |
| 1353 | } |
| 1354 | |
| 1355 | // runSelect runs a single select test. |
| 1356 | // It returns the values returned by Select but also returns |
| 1357 | // a panic value if the Select panics. |
| 1358 | func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) { |
| 1359 | defer func() { |
| 1360 | panicErr = recover() |
| 1361 | |
| 1362 | selectWatch.Lock() |
| 1363 | selectWatch.info = nil |
| 1364 | selectWatch.Unlock() |
| 1365 | }() |
| 1366 | |
| 1367 | selectWatch.Lock() |
| 1368 | selectWatch.now = time.Now() |
| 1369 | selectWatch.info = info |
| 1370 | selectWatch.Unlock() |
| 1371 | |
| 1372 | chosen, recv, recvOK = Select(cases) |
| 1373 | return |
| 1374 | } |
| 1375 | |
| 1376 | // fmtSelect formats the information about a single select test. |
| 1377 | func fmtSelect(info []caseInfo) string { |
| 1378 | var buf bytes.Buffer |
| 1379 | fmt.Fprintf(&buf, "\nselect {\n") |
| 1380 | for i, cas := range info { |
| 1381 | fmt.Fprintf(&buf, "%d: %s", i, cas.desc) |
| 1382 | if cas.recv.IsValid() { |
| 1383 | fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface()) |
| 1384 | } |
| 1385 | if cas.canSelect { |
| 1386 | fmt.Fprintf(&buf, " canselect") |
| 1387 | } |
| 1388 | if cas.panic { |
| 1389 | fmt.Fprintf(&buf, " panic") |
| 1390 | } |
| 1391 | fmt.Fprintf(&buf, "\n") |
| 1392 | } |
| 1393 | fmt.Fprintf(&buf, "}") |
| 1394 | return buf.String() |
| 1395 | } |
| 1396 | |
Russ Cox | ba4625c | 2012-09-24 20:06:32 -0400 | [diff] [blame] | 1397 | type two [2]uintptr |
| 1398 | |
Russ Cox | bba278a | 2009-07-08 18:16:09 -0700 | [diff] [blame] | 1399 | // Difficult test for function call because of |
| 1400 | // implicit padding between arguments. |
Russ Cox | ba4625c | 2012-09-24 20:06:32 -0400 | [diff] [blame] | 1401 | func dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) { |
| 1402 | return b, c, d, e, f, g, h |
Russ Cox | bba278a | 2009-07-08 18:16:09 -0700 | [diff] [blame] | 1403 | } |
| 1404 | |
| 1405 | func TestFunc(t *testing.T) { |
Russ Cox | ba4625c | 2012-09-24 20:06:32 -0400 | [diff] [blame] | 1406 | ret := ValueOf(dummy).Call([]Value{ |
| 1407 | ValueOf(byte(10)), |
| 1408 | ValueOf(20), |
| 1409 | ValueOf(byte(30)), |
| 1410 | ValueOf(two{40, 50}), |
| 1411 | ValueOf(byte(60)), |
| 1412 | ValueOf(float32(70)), |
| 1413 | ValueOf(byte(80)), |
| 1414 | }) |
| 1415 | if len(ret) != 7 { |
| 1416 | t.Fatalf("Call returned %d values, want 7", len(ret)) |
Russ Cox | bba278a | 2009-07-08 18:16:09 -0700 | [diff] [blame] | 1417 | } |
| 1418 | |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1419 | i := byte(ret[0].Uint()) |
| 1420 | j := int(ret[1].Int()) |
| 1421 | k := byte(ret[2].Uint()) |
Russ Cox | ba4625c | 2012-09-24 20:06:32 -0400 | [diff] [blame] | 1422 | l := ret[3].Interface().(two) |
| 1423 | m := byte(ret[4].Uint()) |
| 1424 | n := float32(ret[5].Float()) |
| 1425 | o := byte(ret[6].Uint()) |
| 1426 | |
| 1427 | if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 { |
| 1428 | t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o) |
| 1429 | } |
| 1430 | } |
| 1431 | |
| 1432 | func TestMakeFunc(t *testing.T) { |
| 1433 | f := dummy |
| 1434 | fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in }) |
| 1435 | ValueOf(&f).Elem().Set(fv) |
| 1436 | |
| 1437 | // Call g with small arguments so that there is |
| 1438 | // something predictable (and different from the |
| 1439 | // correct results) in those positions on the stack. |
| 1440 | g := dummy |
| 1441 | g(1, 2, 3, two{4, 5}, 6, 7, 8) |
| 1442 | |
| 1443 | // Call constructed function f. |
| 1444 | i, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80) |
| 1445 | if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 { |
| 1446 | t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o) |
Russ Cox | bba278a | 2009-07-08 18:16:09 -0700 | [diff] [blame] | 1447 | } |
| 1448 | } |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1449 | |
| 1450 | type Point struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1451 | x, y int |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1452 | } |
| 1453 | |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1454 | // This will be index 0. |
| 1455 | func (p Point) AnotherMethod(scale int) int { |
| 1456 | return -1 |
| 1457 | } |
| 1458 | |
| 1459 | // This will be index 1. |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 1460 | func (p Point) Dist(scale int) int { |
| 1461 | // println("Point.Dist", p.x, p.y, scale) |
| 1462 | return p.x*p.x*scale + p.y*p.y*scale |
| 1463 | } |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1464 | |
| 1465 | func TestMethod(t *testing.T) { |
| 1466 | // Non-curried method of type. |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1467 | p := Point{3, 4} |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1468 | i := TypeOf(p).Method(1).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int() |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1469 | if i != 250 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1470 | t.Errorf("Type Method returned %d; want 250", i) |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1471 | } |
| 1472 | |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1473 | m, ok := TypeOf(p).MethodByName("Dist") |
| 1474 | if !ok { |
| 1475 | t.Fatalf("method by name failed") |
| 1476 | } |
| 1477 | m.Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int() |
| 1478 | if i != 250 { |
| 1479 | t.Errorf("Type MethodByName returned %d; want 250", i) |
| 1480 | } |
| 1481 | |
| 1482 | i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int() |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1483 | if i != 250 { |
| 1484 | t.Errorf("Pointer Type Method returned %d; want 250", i) |
| 1485 | } |
| 1486 | |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1487 | m, ok = TypeOf(&p).MethodByName("Dist") |
| 1488 | if !ok { |
| 1489 | t.Fatalf("ptr method by name failed") |
| 1490 | } |
| 1491 | i = m.Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int() |
| 1492 | if i != 250 { |
| 1493 | t.Errorf("Pointer Type MethodByName returned %d; want 250", i) |
| 1494 | } |
| 1495 | |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1496 | // Curried method of value. |
Robert Griesemer | 1065c6f | 2012-10-04 21:03:50 -0700 | [diff] [blame] | 1497 | tfunc := TypeOf((func(int) int)(nil)) |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 1498 | v := ValueOf(p).Method(1) |
| 1499 | if tt := v.Type(); tt != tfunc { |
| 1500 | t.Errorf("Value Method Type is %s; want %s", tt, tfunc) |
| 1501 | } |
| 1502 | i = v.Call([]Value{ValueOf(10)})[0].Int() |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1503 | if i != 250 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1504 | t.Errorf("Value Method returned %d; want 250", i) |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1505 | } |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 1506 | v = ValueOf(p).MethodByName("Dist") |
| 1507 | if tt := v.Type(); tt != tfunc { |
| 1508 | t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc) |
| 1509 | } |
| 1510 | i = v.Call([]Value{ValueOf(10)})[0].Int() |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1511 | if i != 250 { |
| 1512 | t.Errorf("Value MethodByName returned %d; want 250", i) |
| 1513 | } |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1514 | |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1515 | // Curried method of pointer. |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 1516 | v = ValueOf(&p).Method(1) |
| 1517 | if tt := v.Type(); tt != tfunc { |
| 1518 | t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc) |
| 1519 | } |
| 1520 | i = v.Call([]Value{ValueOf(10)})[0].Int() |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1521 | if i != 250 { |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1522 | t.Errorf("Pointer Value Method returned %d; want 250", i) |
| 1523 | } |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 1524 | v = ValueOf(&p).MethodByName("Dist") |
| 1525 | if tt := v.Type(); tt != tfunc { |
| 1526 | t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc) |
| 1527 | } |
| 1528 | i = v.Call([]Value{ValueOf(10)})[0].Int() |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1529 | if i != 250 { |
| 1530 | t.Errorf("Pointer Value MethodByName returned %d; want 250", i) |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1531 | } |
| 1532 | |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1533 | // Curried method of interface value. |
| 1534 | // Have to wrap interface value in a struct to get at it. |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1535 | // Passing it to ValueOf directly would |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1536 | // access the underlying Point, not the interface. |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 1537 | var s = struct { |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 1538 | X interface { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1539 | Dist(int) int |
| 1540 | } |
| 1541 | }{p} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1542 | pv := ValueOf(s).Field(0) |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 1543 | v = pv.Method(0) |
| 1544 | if tt := v.Type(); tt != tfunc { |
| 1545 | t.Errorf("Interface Method Type is %s; want %s", tt, tfunc) |
| 1546 | } |
| 1547 | i = v.Call([]Value{ValueOf(10)})[0].Int() |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1548 | if i != 250 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1549 | t.Errorf("Interface Method returned %d; want 250", i) |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1550 | } |
Russ Cox | a479a45 | 2011-11-16 19:18:25 -0500 | [diff] [blame] | 1551 | v = pv.MethodByName("Dist") |
| 1552 | if tt := v.Type(); tt != tfunc { |
| 1553 | t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc) |
| 1554 | } |
| 1555 | i = v.Call([]Value{ValueOf(10)})[0].Int() |
Rob Pike | 22484e2 | 2011-06-29 13:11:49 +1000 | [diff] [blame] | 1556 | if i != 250 { |
| 1557 | t.Errorf("Interface MethodByName returned %d; want 250", i) |
| 1558 | } |
Russ Cox | 12ebbe7 | 2009-07-09 17:27:49 -0700 | [diff] [blame] | 1559 | } |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1560 | |
| 1561 | func TestInterfaceSet(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1562 | p := &Point{3, 4} |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1563 | |
| 1564 | var s struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1565 | I interface{} |
| 1566 | P interface { |
| 1567 | Dist(int) int |
| 1568 | } |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1569 | } |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1570 | sv := ValueOf(&s).Elem() |
| 1571 | sv.Field(0).Set(ValueOf(p)) |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1572 | if q := s.I.(*Point); q != p { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1573 | t.Errorf("i: have %p want %p", q, p) |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1574 | } |
| 1575 | |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1576 | pv := sv.Field(1) |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1577 | pv.Set(ValueOf(p)) |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1578 | if q := s.P.(*Point); q != p { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1579 | t.Errorf("i: have %p want %p", q, p) |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1580 | } |
Russ Cox | 3b864e4 | 2009-08-12 13:18:37 -0700 | [diff] [blame] | 1581 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1582 | i := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int() |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1583 | if i != 250 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1584 | t.Errorf("Interface Method returned %d; want 250", i) |
Russ Cox | 92e9257 | 2009-07-10 16:32:26 -0700 | [diff] [blame] | 1585 | } |
| 1586 | } |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1587 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 1588 | type T1 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1589 | a string |
| 1590 | int |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 1591 | } |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1592 | |
| 1593 | func TestAnonymousFields(t *testing.T) { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1594 | var field StructField |
| 1595 | var ok bool |
| 1596 | var t1 T1 |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1597 | type1 := TypeOf(t1) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1598 | if field, ok = type1.FieldByName("int"); !ok { |
Russ Cox | 5e3224c | 2012-09-05 09:35:53 -0400 | [diff] [blame] | 1599 | t.Fatal("no field 'int'") |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1600 | } |
| 1601 | if field.Index[0] != 1 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1602 | t.Error("field index should be 1; is", field.Index) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1603 | } |
| 1604 | } |
| 1605 | |
| 1606 | type FTest struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1607 | s interface{} |
| 1608 | name string |
| 1609 | index []int |
| 1610 | value int |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1611 | } |
| 1612 | |
Russ Cox | 92543da | 2009-08-24 17:04:12 -0700 | [diff] [blame] | 1613 | type D1 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1614 | d int |
Russ Cox | 92543da | 2009-08-24 17:04:12 -0700 | [diff] [blame] | 1615 | } |
| 1616 | type D2 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1617 | d int |
Russ Cox | 92543da | 2009-08-24 17:04:12 -0700 | [diff] [blame] | 1618 | } |
| 1619 | |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1620 | type S0 struct { |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1621 | A, B, C int |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1622 | D1 |
| 1623 | D2 |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1624 | } |
| 1625 | |
| 1626 | type S1 struct { |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1627 | B int |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1628 | S0 |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1629 | } |
| 1630 | |
| 1631 | type S2 struct { |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1632 | A int |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1633 | *S1 |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1634 | } |
| 1635 | |
Russ Cox | 92543da | 2009-08-24 17:04:12 -0700 | [diff] [blame] | 1636 | type S1x struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1637 | S1 |
Russ Cox | 92543da | 2009-08-24 17:04:12 -0700 | [diff] [blame] | 1638 | } |
| 1639 | |
| 1640 | type S1y struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1641 | S1 |
Russ Cox | 92543da | 2009-08-24 17:04:12 -0700 | [diff] [blame] | 1642 | } |
| 1643 | |
| 1644 | type S3 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1645 | S1x |
| 1646 | S2 |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1647 | D, E int |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1648 | *S1y |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1649 | } |
| 1650 | |
| 1651 | type S4 struct { |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1652 | *S4 |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1653 | A int |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1654 | } |
| 1655 | |
Russ Cox | 5e3224c | 2012-09-05 09:35:53 -0400 | [diff] [blame] | 1656 | // The X in S6 and S7 annihilate, but they also block the X in S8.S9. |
| 1657 | type S5 struct { |
| 1658 | S6 |
| 1659 | S7 |
| 1660 | S8 |
| 1661 | } |
| 1662 | |
| 1663 | type S6 struct { |
| 1664 | X int |
| 1665 | } |
| 1666 | |
| 1667 | type S7 S6 |
| 1668 | |
| 1669 | type S8 struct { |
| 1670 | S9 |
| 1671 | } |
| 1672 | |
| 1673 | type S9 struct { |
| 1674 | X int |
| 1675 | Y int |
| 1676 | } |
| 1677 | |
| 1678 | // The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. |
| 1679 | type S10 struct { |
| 1680 | S11 |
| 1681 | S12 |
| 1682 | S13 |
| 1683 | } |
| 1684 | |
| 1685 | type S11 struct { |
| 1686 | S6 |
| 1687 | } |
| 1688 | |
| 1689 | type S12 struct { |
| 1690 | S6 |
| 1691 | } |
| 1692 | |
| 1693 | type S13 struct { |
| 1694 | S8 |
| 1695 | } |
| 1696 | |
Robert Griesemer | 77334b98 | 2009-11-05 14:23:20 -0800 | [diff] [blame] | 1697 | var fieldTests = []FTest{ |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 1698 | {struct{}{}, "", nil, 0}, |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1699 | {struct{}{}, "Foo", nil, 0}, |
| 1700 | {S0{A: 'a'}, "A", []int{0}, 'a'}, |
| 1701 | {S0{}, "D", nil, 0}, |
| 1702 | {S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'}, |
| 1703 | {S1{B: 'b'}, "B", []int{0}, 'b'}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 1704 | {S1{}, "S0", []int{1}, 0}, |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1705 | {S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'}, |
| 1706 | {S2{A: 'a'}, "A", []int{0}, 'a'}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 1707 | {S2{}, "S1", []int{1}, 0}, |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1708 | {S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'}, |
| 1709 | {S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'}, |
| 1710 | {S2{}, "D", nil, 0}, |
Robert Griesemer | 3478891 | 2010-10-22 10:06:33 -0700 | [diff] [blame] | 1711 | {S3{}, "S1", nil, 0}, |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 1712 | {S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'}, |
| 1713 | {S3{}, "B", nil, 0}, |
| 1714 | {S3{D: 'd'}, "D", []int{2}, 0}, |
| 1715 | {S3{E: 'e'}, "E", []int{3}, 'e'}, |
| 1716 | {S4{A: 'a'}, "A", []int{1}, 'a'}, |
| 1717 | {S4{}, "B", nil, 0}, |
Russ Cox | 5e3224c | 2012-09-05 09:35:53 -0400 | [diff] [blame] | 1718 | {S5{}, "X", nil, 0}, |
| 1719 | {S5{}, "Y", []int{2, 0, 1}, 0}, |
| 1720 | {S10{}, "X", nil, 0}, |
| 1721 | {S10{}, "Y", []int{2, 0, 0, 1}, 0}, |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1722 | } |
| 1723 | |
| 1724 | func TestFieldByIndex(t *testing.T) { |
| 1725 | for _, test := range fieldTests { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1726 | s := TypeOf(test.s) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1727 | f := s.FieldByIndex(test.index) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1728 | if f.Name != "" { |
| 1729 | if test.index != nil { |
| 1730 | if f.Name != test.name { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1731 | t.Errorf("%s.%s found; want %s", s.Name(), f.Name, test.name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1732 | } |
| 1733 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1734 | t.Errorf("%s.%s found", s.Name(), f.Name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1735 | } |
| 1736 | } else if len(test.index) > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1737 | t.Errorf("%s.%s not found", s.Name(), test.name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1738 | } |
| 1739 | |
| 1740 | if test.value != 0 { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1741 | v := ValueOf(test.s).FieldByIndex(test.index) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1742 | if v.IsValid() { |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1743 | if x, ok := v.Interface().(int); ok { |
| 1744 | if x != test.value { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1745 | t.Errorf("%s%v is %d; want %d", s.Name(), test.index, x, test.value) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1746 | } |
| 1747 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1748 | t.Errorf("%s%v value not an int", s.Name(), test.index) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1749 | } |
| 1750 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1751 | t.Errorf("%s%v value not found", s.Name(), test.index) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1752 | } |
| 1753 | } |
| 1754 | } |
| 1755 | } |
| 1756 | |
| 1757 | func TestFieldByName(t *testing.T) { |
| 1758 | for _, test := range fieldTests { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1759 | s := TypeOf(test.s) |
Robert Griesemer | d65a5cc | 2009-12-15 15:40:16 -0800 | [diff] [blame] | 1760 | f, found := s.FieldByName(test.name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1761 | if found { |
| 1762 | if test.index != nil { |
| 1763 | // Verify field depth and index. |
| 1764 | if len(f.Index) != len(test.index) { |
Russ Cox | 5e3224c | 2012-09-05 09:35:53 -0400 | [diff] [blame] | 1765 | t.Errorf("%s.%s depth %d; want %d: %v vs %v", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1766 | } else { |
| 1767 | for i, x := range f.Index { |
| 1768 | if x != test.index[i] { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1769 | t.Errorf("%s.%s.Index[%d] is %d; want %d", s.Name(), test.name, i, x, test.index[i]) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1770 | } |
| 1771 | } |
| 1772 | } |
| 1773 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1774 | t.Errorf("%s.%s found", s.Name(), f.Name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1775 | } |
| 1776 | } else if len(test.index) > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1777 | t.Errorf("%s.%s not found", s.Name(), test.name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1778 | } |
Russ Cox | 3b864e4 | 2009-08-12 13:18:37 -0700 | [diff] [blame] | 1779 | |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1780 | if test.value != 0 { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1781 | v := ValueOf(test.s).FieldByName(test.name) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1782 | if v.IsValid() { |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1783 | if x, ok := v.Interface().(int); ok { |
| 1784 | if x != test.value { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1785 | t.Errorf("%s.%s is %d; want %d", s.Name(), test.name, x, test.value) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1786 | } |
| 1787 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1788 | t.Errorf("%s.%s value not an int", s.Name(), test.name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1789 | } |
| 1790 | } else { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 1791 | t.Errorf("%s.%s value not found", s.Name(), test.name) |
Robert Griesemer | a288095 | 2009-08-05 15:56:44 -0700 | [diff] [blame] | 1792 | } |
| 1793 | } |
| 1794 | } |
| 1795 | } |
Russ Cox | 1cecac8 | 2010-01-24 23:33:59 -0800 | [diff] [blame] | 1796 | |
| 1797 | func TestImportPath(t *testing.T) { |
David Symonds | ee09a8c | 2012-01-20 09:26:17 +1100 | [diff] [blame] | 1798 | tests := []struct { |
| 1799 | t Type |
| 1800 | path string |
| 1801 | }{ |
| 1802 | {TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"}, |
Russ Cox | a96c2b8 | 2012-09-01 19:55:55 -0400 | [diff] [blame] | 1803 | {TypeOf(int(0)), ""}, |
| 1804 | {TypeOf(int8(0)), ""}, |
| 1805 | {TypeOf(int16(0)), ""}, |
| 1806 | {TypeOf(int32(0)), ""}, |
| 1807 | {TypeOf(int64(0)), ""}, |
David Symonds | ee09a8c | 2012-01-20 09:26:17 +1100 | [diff] [blame] | 1808 | {TypeOf(uint(0)), ""}, |
Russ Cox | a96c2b8 | 2012-09-01 19:55:55 -0400 | [diff] [blame] | 1809 | {TypeOf(uint8(0)), ""}, |
| 1810 | {TypeOf(uint16(0)), ""}, |
| 1811 | {TypeOf(uint32(0)), ""}, |
| 1812 | {TypeOf(uint64(0)), ""}, |
| 1813 | {TypeOf(uintptr(0)), ""}, |
| 1814 | {TypeOf(float32(0)), ""}, |
| 1815 | {TypeOf(float64(0)), ""}, |
| 1816 | {TypeOf(complex64(0)), ""}, |
| 1817 | {TypeOf(complex128(0)), ""}, |
| 1818 | {TypeOf(byte(0)), ""}, |
| 1819 | {TypeOf(rune(0)), ""}, |
| 1820 | {TypeOf([]byte(nil)), ""}, |
| 1821 | {TypeOf([]rune(nil)), ""}, |
| 1822 | {TypeOf(string("")), ""}, |
| 1823 | {TypeOf((*interface{})(nil)).Elem(), ""}, |
| 1824 | {TypeOf((*byte)(nil)), ""}, |
| 1825 | {TypeOf((*rune)(nil)), ""}, |
| 1826 | {TypeOf((*int64)(nil)), ""}, |
David Symonds | ee09a8c | 2012-01-20 09:26:17 +1100 | [diff] [blame] | 1827 | {TypeOf(map[string]int{}), ""}, |
| 1828 | {TypeOf((*error)(nil)).Elem(), ""}, |
| 1829 | } |
| 1830 | for _, test := range tests { |
| 1831 | if path := test.t.PkgPath(); path != test.path { |
| 1832 | t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path) |
| 1833 | } |
Russ Cox | 1cecac8 | 2010-01-24 23:33:59 -0800 | [diff] [blame] | 1834 | } |
| 1835 | } |
Russ Cox | 6672b40 | 2010-06-14 11:23:11 -0700 | [diff] [blame] | 1836 | |
David Symonds | c913cb8 | 2011-07-27 13:44:57 +1000 | [diff] [blame] | 1837 | func TestVariadicType(t *testing.T) { |
David Symonds | fc1cf58 | 2011-07-27 13:29:44 +1000 | [diff] [blame] | 1838 | // Test example from Type documentation. |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 1839 | var f func(x int, y ...float64) |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1840 | typ := TypeOf(f) |
| 1841 | if typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) { |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1842 | sl := typ.In(1) |
| 1843 | if sl.Kind() == Slice { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1844 | if sl.Elem() == TypeOf(0.0) { |
Russ Cox | 6672b40 | 2010-06-14 11:23:11 -0700 | [diff] [blame] | 1845 | // ok |
| 1846 | return |
| 1847 | } |
| 1848 | } |
| 1849 | } |
| 1850 | |
| 1851 | // Failed |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 1852 | t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64") |
Russ Cox | 6672b40 | 2010-06-14 11:23:11 -0700 | [diff] [blame] | 1853 | s := fmt.Sprintf("have NumIn() = %d", typ.NumIn()) |
| 1854 | for i := 0; i < typ.NumIn(); i++ { |
| 1855 | s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i)) |
| 1856 | } |
| 1857 | t.Error(s) |
| 1858 | } |
Russ Cox | 2d5e732 | 2010-09-27 14:09:10 -0400 | [diff] [blame] | 1859 | |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1860 | type inner struct { |
| 1861 | x int |
| 1862 | } |
Russ Cox | 2d5e732 | 2010-09-27 14:09:10 -0400 | [diff] [blame] | 1863 | |
| 1864 | type outer struct { |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1865 | y int |
Russ Cox | 2d5e732 | 2010-09-27 14:09:10 -0400 | [diff] [blame] | 1866 | inner |
| 1867 | } |
| 1868 | |
| 1869 | func (*inner) m() {} |
| 1870 | func (*outer) m() {} |
| 1871 | |
| 1872 | func TestNestedMethods(t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1873 | typ := TypeOf((*outer)(nil)) |
| 1874 | if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() { |
Russ Cox | 2d5e732 | 2010-09-27 14:09:10 -0400 | [diff] [blame] | 1875 | t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m) |
| 1876 | for i := 0; i < typ.NumMethod(); i++ { |
| 1877 | m := typ.Method(i) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1878 | t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) |
Russ Cox | 2d5e732 | 2010-09-27 14:09:10 -0400 | [diff] [blame] | 1879 | } |
| 1880 | } |
| 1881 | } |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1882 | |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1883 | type InnerInt struct { |
| 1884 | X int |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1885 | } |
| 1886 | |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1887 | type OuterInt struct { |
| 1888 | Y int |
| 1889 | InnerInt |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1890 | } |
| 1891 | |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1892 | func (i *InnerInt) M() int { |
| 1893 | return i.X |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1894 | } |
| 1895 | |
| 1896 | func TestEmbeddedMethods(t *testing.T) { |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1897 | typ := TypeOf((*OuterInt)(nil)) |
| 1898 | if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() { |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1899 | t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M) |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1900 | for i := 0; i < typ.NumMethod(); i++ { |
| 1901 | m := typ.Method(i) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1902 | t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1903 | } |
| 1904 | } |
| 1905 | |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1906 | i := &InnerInt{3} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1907 | if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 { |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1908 | t.Errorf("i.M() = %d, want 3", v) |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1909 | } |
| 1910 | |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1911 | o := &OuterInt{1, InnerInt{2}} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1912 | if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 { |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1913 | t.Errorf("i.M() = %d, want 2", v) |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1914 | } |
| 1915 | |
Russ Cox | 5ff3336 | 2011-04-21 08:14:50 -0400 | [diff] [blame] | 1916 | f := (*OuterInt).M |
Russ Cox | 00ffd59 | 2010-09-28 13:43:50 -0400 | [diff] [blame] | 1917 | if v := f(o); v != 2 { |
| 1918 | t.Errorf("f(o) = %d, want 2", v) |
| 1919 | } |
| 1920 | } |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1921 | |
| 1922 | func TestPtrTo(t *testing.T) { |
| 1923 | var i int |
| 1924 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1925 | typ := TypeOf(i) |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1926 | for i = 0; i < 100; i++ { |
| 1927 | typ = PtrTo(typ) |
| 1928 | } |
| 1929 | for i = 0; i < 100; i++ { |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1930 | typ = typ.Elem() |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1931 | } |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1932 | if typ != TypeOf(i) { |
| 1933 | t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i)) |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1934 | } |
| 1935 | } |
| 1936 | |
| 1937 | func TestAddr(t *testing.T) { |
| 1938 | var p struct { |
| 1939 | X, Y int |
| 1940 | } |
| 1941 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1942 | v := ValueOf(&p) |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1943 | v = v.Elem() |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1944 | v = v.Addr() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1945 | v = v.Elem() |
| 1946 | v = v.Field(0) |
| 1947 | v.SetInt(2) |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1948 | if p.X != 2 { |
| 1949 | t.Errorf("Addr.Elem.Set failed to set value") |
| 1950 | } |
| 1951 | |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1952 | // Again but take address of the ValueOf value. |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1953 | // Exercises generation of PtrTypes not present in the binary. |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 1954 | q := &p |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1955 | v = ValueOf(&q).Elem() |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1956 | v = v.Addr() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1957 | v = v.Elem() |
| 1958 | v = v.Elem() |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1959 | v = v.Addr() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1960 | v = v.Elem() |
| 1961 | v = v.Field(0) |
| 1962 | v.SetInt(3) |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1963 | if p.X != 3 { |
| 1964 | t.Errorf("Addr.Elem.Set failed to set value") |
| 1965 | } |
| 1966 | |
| 1967 | // Starting without pointer we should get changed value |
| 1968 | // in interface. |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 1969 | qq := p |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 1970 | v = ValueOf(&qq).Elem() |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1971 | v0 := v |
| 1972 | v = v.Addr() |
Russ Cox | fb175cf | 2011-04-08 12:26:51 -0400 | [diff] [blame] | 1973 | v = v.Elem() |
| 1974 | v = v.Field(0) |
| 1975 | v.SetInt(4) |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1976 | if p.X != 3 { // should be unchanged from last time |
| 1977 | t.Errorf("somehow value Set changed original p") |
| 1978 | } |
| 1979 | p = v0.Interface().(struct { |
| 1980 | X, Y int |
| 1981 | }) |
| 1982 | if p.X != 4 { |
| 1983 | t.Errorf("Addr.Elem.Set valued to set value in top value") |
| 1984 | } |
Ian Lance Taylor | ae5c4ea | 2012-02-03 17:36:25 -0800 | [diff] [blame] | 1985 | |
| 1986 | // Verify that taking the address of a type gives us a pointer |
| 1987 | // which we can convert back using the usual interface |
| 1988 | // notation. |
| 1989 | var s struct { |
| 1990 | B *bool |
| 1991 | } |
| 1992 | ps := ValueOf(&s).Elem().Field(0).Addr().Interface() |
| 1993 | *(ps.(**bool)) = new(bool) |
| 1994 | if s.B == nil { |
| 1995 | t.Errorf("Addr.Interface direct assignment failed") |
| 1996 | } |
Russ Cox | e46acb0 | 2011-03-03 13:20:17 -0500 | [diff] [blame] | 1997 | } |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 1998 | |
| 1999 | func noAlloc(t *testing.T, n int, f func(int)) { |
| 2000 | // once to prime everything |
| 2001 | f(-1) |
Rémy Oudompheng | 842c906 | 2012-02-06 19:16:26 +0100 | [diff] [blame] | 2002 | memstats := new(runtime.MemStats) |
| 2003 | runtime.ReadMemStats(memstats) |
| 2004 | oldmallocs := memstats.Mallocs |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 2005 | |
| 2006 | for j := 0; j < n; j++ { |
| 2007 | f(j) |
| 2008 | } |
Rob Pike | 1242c76 | 2011-05-17 11:15:14 -0400 | [diff] [blame] | 2009 | // A few allocs may happen in the testing package when GOMAXPROCS > 1, so don't |
| 2010 | // require zero mallocs. |
Dmitriy Vyukov | 21de1ab | 2012-07-02 20:55:08 +0400 | [diff] [blame] | 2011 | // A new thread, one of which will be created if GOMAXPROCS>1, does 6 allocations. |
Rémy Oudompheng | 842c906 | 2012-02-06 19:16:26 +0100 | [diff] [blame] | 2012 | runtime.ReadMemStats(memstats) |
| 2013 | mallocs := memstats.Mallocs - oldmallocs |
Dmitriy Vyukov | 21de1ab | 2012-07-02 20:55:08 +0400 | [diff] [blame] | 2014 | if mallocs > 10 { |
Rémy Oudompheng | 842c906 | 2012-02-06 19:16:26 +0100 | [diff] [blame] | 2015 | t.Fatalf("%d mallocs after %d iterations", mallocs, n) |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 2016 | } |
| 2017 | } |
| 2018 | |
| 2019 | func TestAllocations(t *testing.T) { |
| 2020 | noAlloc(t, 100, func(j int) { |
| 2021 | var i interface{} |
| 2022 | var v Value |
| 2023 | i = 42 + j |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 2024 | v = ValueOf(i) |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 2025 | if int(v.Int()) != 42+j { |
| 2026 | panic("wrong int") |
| 2027 | } |
| 2028 | }) |
| 2029 | } |
| 2030 | |
| 2031 | func TestSmallNegativeInt(t *testing.T) { |
| 2032 | i := int16(-1) |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 2033 | v := ValueOf(i) |
Russ Cox | 40fccbc | 2011-04-18 14:35:33 -0400 | [diff] [blame] | 2034 | if v.Int() != -1 { |
| 2035 | t.Errorf("int16(-1).Int() returned %v", v.Int()) |
| 2036 | } |
| 2037 | } |
Russ Cox | 3bac16a | 2011-04-18 20:00:42 -0400 | [diff] [blame] | 2038 | |
Evan Shaw | 772decb | 2012-10-21 17:02:10 -0400 | [diff] [blame^] | 2039 | func TestIndex(t *testing.T) { |
| 2040 | xs := []byte{1, 2, 3, 4, 5, 6, 7, 8} |
| 2041 | v := ValueOf(xs).Index(3).Interface().(byte) |
| 2042 | if v != xs[3] { |
| 2043 | t.Errorf("xs.Index(3) = %v; expected %v", v, xs[3]) |
| 2044 | } |
| 2045 | xa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80} |
| 2046 | v = ValueOf(xa).Index(2).Interface().(byte) |
| 2047 | if v != xa[2] { |
| 2048 | t.Errorf("xa.Index(2) = %v; expected %v", v, xa[2]) |
| 2049 | } |
| 2050 | s := "0123456789" |
| 2051 | v = ValueOf(s).Index(3).Interface().(byte) |
| 2052 | if v != s[3] { |
| 2053 | t.Errorf("s.Index(3) = %v; expected %v", v, s[3]) |
| 2054 | } |
| 2055 | } |
| 2056 | |
Russ Cox | 3bac16a | 2011-04-18 20:00:42 -0400 | [diff] [blame] | 2057 | func TestSlice(t *testing.T) { |
| 2058 | xs := []int{1, 2, 3, 4, 5, 6, 7, 8} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 2059 | v := ValueOf(xs).Slice(3, 5).Interface().([]int) |
Gustavo Niemeyer | 3dc278d | 2011-12-12 19:45:40 -0200 | [diff] [blame] | 2060 | if len(v) != 2 { |
| 2061 | t.Errorf("len(xs.Slice(3, 5)) = %d", len(v)) |
| 2062 | } |
| 2063 | if cap(v) != 5 { |
| 2064 | t.Errorf("cap(xs.Slice(3, 5)) = %d", cap(v)) |
| 2065 | } |
| 2066 | if !DeepEqual(v[0:5], xs[3:]) { |
| 2067 | t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5]) |
Russ Cox | 3bac16a | 2011-04-18 20:00:42 -0400 | [diff] [blame] | 2068 | } |
Gustavo Niemeyer | 3dc278d | 2011-12-12 19:45:40 -0200 | [diff] [blame] | 2069 | xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80} |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 2070 | v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int) |
Gustavo Niemeyer | 3dc278d | 2011-12-12 19:45:40 -0200 | [diff] [blame] | 2071 | if len(v) != 3 { |
| 2072 | t.Errorf("len(xa.Slice(2, 5)) = %d", len(v)) |
| 2073 | } |
| 2074 | if cap(v) != 6 { |
| 2075 | t.Errorf("cap(xa.Slice(2, 5)) = %d", cap(v)) |
| 2076 | } |
| 2077 | if !DeepEqual(v[0:6], xa[2:]) { |
| 2078 | t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6]) |
Russ Cox | 3bac16a | 2011-04-18 20:00:42 -0400 | [diff] [blame] | 2079 | } |
Evan Shaw | 772decb | 2012-10-21 17:02:10 -0400 | [diff] [blame^] | 2080 | s := "0123456789" |
| 2081 | vs := ValueOf(s).Slice(3, 5).Interface().(string) |
| 2082 | if vs != s[3:5] { |
| 2083 | t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5]) |
| 2084 | } |
Russ Cox | 3bac16a | 2011-04-18 20:00:42 -0400 | [diff] [blame] | 2085 | } |
Russ Cox | e1ee3b5 | 2011-04-20 16:24:45 -0400 | [diff] [blame] | 2086 | |
| 2087 | func TestVariadic(t *testing.T) { |
| 2088 | var b bytes.Buffer |
Russ Cox | 0e2bb62 | 2011-04-25 13:39:16 -0400 | [diff] [blame] | 2089 | V := ValueOf |
Russ Cox | e1ee3b5 | 2011-04-20 16:24:45 -0400 | [diff] [blame] | 2090 | |
| 2091 | b.Reset() |
| 2092 | V(fmt.Fprintf).Call([]Value{V(&b), V("%s, %d world"), V("hello"), V(42)}) |
| 2093 | if b.String() != "hello, 42 world" { |
| 2094 | t.Errorf("after Fprintf Call: %q != %q", b.String(), "hello 42 world") |
| 2095 | } |
| 2096 | |
| 2097 | b.Reset() |
| 2098 | V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})}) |
| 2099 | if b.String() != "hello, 42 world" { |
| 2100 | t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world") |
| 2101 | } |
| 2102 | } |
Russ Cox | 25733a9 | 2011-06-29 09:52:34 -0400 | [diff] [blame] | 2103 | |
| 2104 | var tagGetTests = []struct { |
| 2105 | Tag StructTag |
| 2106 | Key string |
| 2107 | Value string |
| 2108 | }{ |
| 2109 | {`protobuf:"PB(1,2)"`, `protobuf`, `PB(1,2)`}, |
| 2110 | {`protobuf:"PB(1,2)"`, `foo`, ``}, |
| 2111 | {`protobuf:"PB(1,2)"`, `rotobuf`, ``}, |
| 2112 | {`protobuf:"PB(1,2)" json:"name"`, `json`, `name`}, |
| 2113 | {`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`}, |
| 2114 | } |
| 2115 | |
| 2116 | func TestTagGet(t *testing.T) { |
| 2117 | for _, tt := range tagGetTests { |
| 2118 | if v := tt.Tag.Get(tt.Key); v != tt.Value { |
| 2119 | t.Errorf("StructTag(%#q).Get(%#q) = %#q, want %#q", tt.Tag, tt.Key, v, tt.Value) |
| 2120 | } |
| 2121 | } |
| 2122 | } |
Russ Cox | 00d64c7 | 2011-08-23 22:50:08 -0400 | [diff] [blame] | 2123 | |
| 2124 | func TestBytes(t *testing.T) { |
| 2125 | type B []byte |
| 2126 | x := B{1, 2, 3, 4} |
| 2127 | y := ValueOf(x).Bytes() |
| 2128 | if !bytes.Equal(x, y) { |
| 2129 | t.Fatalf("ValueOf(%v).Bytes() = %v", x, y) |
| 2130 | } |
| 2131 | if &x[0] != &y[0] { |
| 2132 | t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0]) |
| 2133 | } |
| 2134 | } |
| 2135 | |
| 2136 | func TestSetBytes(t *testing.T) { |
| 2137 | type B []byte |
| 2138 | var x B |
| 2139 | y := []byte{1, 2, 3, 4} |
| 2140 | ValueOf(&x).Elem().SetBytes(y) |
| 2141 | if !bytes.Equal(x, y) { |
| 2142 | t.Fatalf("ValueOf(%v).Bytes() = %v", x, y) |
| 2143 | } |
| 2144 | if &x[0] != &y[0] { |
| 2145 | t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0]) |
| 2146 | } |
| 2147 | } |
Russ Cox | 304cf4d | 2011-10-17 18:48:45 -0400 | [diff] [blame] | 2148 | |
| 2149 | type Private struct { |
| 2150 | x int |
| 2151 | y **int |
| 2152 | } |
| 2153 | |
| 2154 | func (p *Private) m() { |
| 2155 | } |
| 2156 | |
| 2157 | type Public struct { |
| 2158 | X int |
| 2159 | Y **int |
| 2160 | } |
| 2161 | |
| 2162 | func (p *Public) M() { |
| 2163 | } |
| 2164 | |
| 2165 | func TestUnexported(t *testing.T) { |
| 2166 | var pub Public |
| 2167 | v := ValueOf(&pub) |
| 2168 | isValid(v.Elem().Field(0)) |
| 2169 | isValid(v.Elem().Field(1)) |
| 2170 | isValid(v.Elem().FieldByName("X")) |
| 2171 | isValid(v.Elem().FieldByName("Y")) |
| 2172 | isValid(v.Type().Method(0).Func) |
| 2173 | isNonNil(v.Elem().Field(0).Interface()) |
| 2174 | isNonNil(v.Elem().Field(1).Interface()) |
| 2175 | isNonNil(v.Elem().FieldByName("X").Interface()) |
| 2176 | isNonNil(v.Elem().FieldByName("Y").Interface()) |
| 2177 | isNonNil(v.Type().Method(0).Func.Interface()) |
| 2178 | |
| 2179 | var priv Private |
| 2180 | v = ValueOf(&priv) |
| 2181 | isValid(v.Elem().Field(0)) |
| 2182 | isValid(v.Elem().Field(1)) |
| 2183 | isValid(v.Elem().FieldByName("x")) |
| 2184 | isValid(v.Elem().FieldByName("y")) |
| 2185 | isValid(v.Type().Method(0).Func) |
| 2186 | shouldPanic(func() { v.Elem().Field(0).Interface() }) |
| 2187 | shouldPanic(func() { v.Elem().Field(1).Interface() }) |
| 2188 | shouldPanic(func() { v.Elem().FieldByName("x").Interface() }) |
| 2189 | shouldPanic(func() { v.Elem().FieldByName("y").Interface() }) |
| 2190 | shouldPanic(func() { v.Type().Method(0).Func.Interface() }) |
| 2191 | } |
| 2192 | |
| 2193 | func shouldPanic(f func()) { |
| 2194 | defer func() { |
| 2195 | if recover() == nil { |
| 2196 | panic("did not panic") |
| 2197 | } |
| 2198 | }() |
| 2199 | f() |
| 2200 | } |
| 2201 | |
| 2202 | func isNonNil(x interface{}) { |
| 2203 | if x == nil { |
| 2204 | panic("nil interface") |
| 2205 | } |
| 2206 | } |
| 2207 | |
| 2208 | func isValid(v Value) { |
| 2209 | if !v.IsValid() { |
| 2210 | panic("zero Value") |
| 2211 | } |
| 2212 | } |
Russ Cox | a72b87e | 2012-03-01 11:48:27 -0500 | [diff] [blame] | 2213 | |
| 2214 | func TestAlias(t *testing.T) { |
| 2215 | x := string("hello") |
| 2216 | v := ValueOf(&x).Elem() |
| 2217 | oldvalue := v.Interface() |
| 2218 | v.SetString("world") |
| 2219 | newvalue := v.Interface() |
| 2220 | |
| 2221 | if oldvalue != "hello" || newvalue != "world" { |
| 2222 | t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue) |
| 2223 | } |
| 2224 | } |
Russ Cox | 5e3224c | 2012-09-05 09:35:53 -0400 | [diff] [blame] | 2225 | |
Russ Cox | 46f379c | 2012-09-22 08:52:27 -0400 | [diff] [blame] | 2226 | var V = ValueOf |
| 2227 | |
| 2228 | func EmptyInterfaceV(x interface{}) Value { |
| 2229 | return ValueOf(&x).Elem() |
| 2230 | } |
| 2231 | |
| 2232 | func ReaderV(x io.Reader) Value { |
| 2233 | return ValueOf(&x).Elem() |
| 2234 | } |
| 2235 | |
| 2236 | func ReadWriterV(x io.ReadWriter) Value { |
| 2237 | return ValueOf(&x).Elem() |
| 2238 | } |
| 2239 | |
| 2240 | type Empty struct{} |
| 2241 | type MyString string |
| 2242 | type MyBytes []byte |
| 2243 | type MyRunes []int32 |
| 2244 | type MyFunc func() |
| 2245 | type MyByte byte |
| 2246 | |
| 2247 | var convertTests = []struct { |
| 2248 | in Value |
| 2249 | out Value |
| 2250 | }{ |
| 2251 | // numbers |
| 2252 | /* |
| 2253 | Edit .+1,/\*\//-1>cat >/tmp/x.go && go run /tmp/x.go |
| 2254 | |
| 2255 | package main |
| 2256 | |
| 2257 | import "fmt" |
| 2258 | |
| 2259 | var numbers = []string{ |
| 2260 | "int8", "uint8", "int16", "uint16", |
| 2261 | "int32", "uint32", "int64", "uint64", |
| 2262 | "int", "uint", "uintptr", |
| 2263 | "float32", "float64", |
| 2264 | } |
| 2265 | |
| 2266 | func main() { |
| 2267 | // all pairs but in an unusual order, |
| 2268 | // to emit all the int8, uint8 cases |
| 2269 | // before n grows too big. |
| 2270 | n := 1 |
| 2271 | for i, f := range numbers { |
| 2272 | for _, g := range numbers[i:] { |
| 2273 | fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", f, n, g, n) |
| 2274 | n++ |
| 2275 | if f != g { |
| 2276 | fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", g, n, f, n) |
| 2277 | n++ |
| 2278 | } |
| 2279 | } |
| 2280 | } |
| 2281 | } |
| 2282 | */ |
| 2283 | {V(int8(1)), V(int8(1))}, |
| 2284 | {V(int8(2)), V(uint8(2))}, |
| 2285 | {V(uint8(3)), V(int8(3))}, |
| 2286 | {V(int8(4)), V(int16(4))}, |
| 2287 | {V(int16(5)), V(int8(5))}, |
| 2288 | {V(int8(6)), V(uint16(6))}, |
| 2289 | {V(uint16(7)), V(int8(7))}, |
| 2290 | {V(int8(8)), V(int32(8))}, |
| 2291 | {V(int32(9)), V(int8(9))}, |
| 2292 | {V(int8(10)), V(uint32(10))}, |
| 2293 | {V(uint32(11)), V(int8(11))}, |
| 2294 | {V(int8(12)), V(int64(12))}, |
| 2295 | {V(int64(13)), V(int8(13))}, |
| 2296 | {V(int8(14)), V(uint64(14))}, |
| 2297 | {V(uint64(15)), V(int8(15))}, |
| 2298 | {V(int8(16)), V(int(16))}, |
| 2299 | {V(int(17)), V(int8(17))}, |
| 2300 | {V(int8(18)), V(uint(18))}, |
| 2301 | {V(uint(19)), V(int8(19))}, |
| 2302 | {V(int8(20)), V(uintptr(20))}, |
| 2303 | {V(uintptr(21)), V(int8(21))}, |
| 2304 | {V(int8(22)), V(float32(22))}, |
| 2305 | {V(float32(23)), V(int8(23))}, |
| 2306 | {V(int8(24)), V(float64(24))}, |
| 2307 | {V(float64(25)), V(int8(25))}, |
| 2308 | {V(uint8(26)), V(uint8(26))}, |
| 2309 | {V(uint8(27)), V(int16(27))}, |
| 2310 | {V(int16(28)), V(uint8(28))}, |
| 2311 | {V(uint8(29)), V(uint16(29))}, |
| 2312 | {V(uint16(30)), V(uint8(30))}, |
| 2313 | {V(uint8(31)), V(int32(31))}, |
| 2314 | {V(int32(32)), V(uint8(32))}, |
| 2315 | {V(uint8(33)), V(uint32(33))}, |
| 2316 | {V(uint32(34)), V(uint8(34))}, |
| 2317 | {V(uint8(35)), V(int64(35))}, |
| 2318 | {V(int64(36)), V(uint8(36))}, |
| 2319 | {V(uint8(37)), V(uint64(37))}, |
| 2320 | {V(uint64(38)), V(uint8(38))}, |
| 2321 | {V(uint8(39)), V(int(39))}, |
| 2322 | {V(int(40)), V(uint8(40))}, |
| 2323 | {V(uint8(41)), V(uint(41))}, |
| 2324 | {V(uint(42)), V(uint8(42))}, |
| 2325 | {V(uint8(43)), V(uintptr(43))}, |
| 2326 | {V(uintptr(44)), V(uint8(44))}, |
| 2327 | {V(uint8(45)), V(float32(45))}, |
| 2328 | {V(float32(46)), V(uint8(46))}, |
| 2329 | {V(uint8(47)), V(float64(47))}, |
| 2330 | {V(float64(48)), V(uint8(48))}, |
| 2331 | {V(int16(49)), V(int16(49))}, |
| 2332 | {V(int16(50)), V(uint16(50))}, |
| 2333 | {V(uint16(51)), V(int16(51))}, |
| 2334 | {V(int16(52)), V(int32(52))}, |
| 2335 | {V(int32(53)), V(int16(53))}, |
| 2336 | {V(int16(54)), V(uint32(54))}, |
| 2337 | {V(uint32(55)), V(int16(55))}, |
| 2338 | {V(int16(56)), V(int64(56))}, |
| 2339 | {V(int64(57)), V(int16(57))}, |
| 2340 | {V(int16(58)), V(uint64(58))}, |
| 2341 | {V(uint64(59)), V(int16(59))}, |
| 2342 | {V(int16(60)), V(int(60))}, |
| 2343 | {V(int(61)), V(int16(61))}, |
| 2344 | {V(int16(62)), V(uint(62))}, |
| 2345 | {V(uint(63)), V(int16(63))}, |
| 2346 | {V(int16(64)), V(uintptr(64))}, |
| 2347 | {V(uintptr(65)), V(int16(65))}, |
| 2348 | {V(int16(66)), V(float32(66))}, |
| 2349 | {V(float32(67)), V(int16(67))}, |
| 2350 | {V(int16(68)), V(float64(68))}, |
| 2351 | {V(float64(69)), V(int16(69))}, |
| 2352 | {V(uint16(70)), V(uint16(70))}, |
| 2353 | {V(uint16(71)), V(int32(71))}, |
| 2354 | {V(int32(72)), V(uint16(72))}, |
| 2355 | {V(uint16(73)), V(uint32(73))}, |
| 2356 | {V(uint32(74)), V(uint16(74))}, |
| 2357 | {V(uint16(75)), V(int64(75))}, |
| 2358 | {V(int64(76)), V(uint16(76))}, |
| 2359 | {V(uint16(77)), V(uint64(77))}, |
| 2360 | {V(uint64(78)), V(uint16(78))}, |
| 2361 | {V(uint16(79)), V(int(79))}, |
| 2362 | {V(int(80)), V(uint16(80))}, |
| 2363 | {V(uint16(81)), V(uint(81))}, |
| 2364 | {V(uint(82)), V(uint16(82))}, |
| 2365 | {V(uint16(83)), V(uintptr(83))}, |
| 2366 | {V(uintptr(84)), V(uint16(84))}, |
| 2367 | {V(uint16(85)), V(float32(85))}, |
| 2368 | {V(float32(86)), V(uint16(86))}, |
| 2369 | {V(uint16(87)), V(float64(87))}, |
| 2370 | {V(float64(88)), V(uint16(88))}, |
| 2371 | {V(int32(89)), V(int32(89))}, |
| 2372 | {V(int32(90)), V(uint32(90))}, |
| 2373 | {V(uint32(91)), V(int32(91))}, |
| 2374 | {V(int32(92)), V(int64(92))}, |
| 2375 | {V(int64(93)), V(int32(93))}, |
| 2376 | {V(int32(94)), V(uint64(94))}, |
| 2377 | {V(uint64(95)), V(int32(95))}, |
| 2378 | {V(int32(96)), V(int(96))}, |
| 2379 | {V(int(97)), V(int32(97))}, |
| 2380 | {V(int32(98)), V(uint(98))}, |
| 2381 | {V(uint(99)), V(int32(99))}, |
| 2382 | {V(int32(100)), V(uintptr(100))}, |
| 2383 | {V(uintptr(101)), V(int32(101))}, |
| 2384 | {V(int32(102)), V(float32(102))}, |
| 2385 | {V(float32(103)), V(int32(103))}, |
| 2386 | {V(int32(104)), V(float64(104))}, |
| 2387 | {V(float64(105)), V(int32(105))}, |
| 2388 | {V(uint32(106)), V(uint32(106))}, |
| 2389 | {V(uint32(107)), V(int64(107))}, |
| 2390 | {V(int64(108)), V(uint32(108))}, |
| 2391 | {V(uint32(109)), V(uint64(109))}, |
| 2392 | {V(uint64(110)), V(uint32(110))}, |
| 2393 | {V(uint32(111)), V(int(111))}, |
| 2394 | {V(int(112)), V(uint32(112))}, |
| 2395 | {V(uint32(113)), V(uint(113))}, |
| 2396 | {V(uint(114)), V(uint32(114))}, |
| 2397 | {V(uint32(115)), V(uintptr(115))}, |
| 2398 | {V(uintptr(116)), V(uint32(116))}, |
| 2399 | {V(uint32(117)), V(float32(117))}, |
| 2400 | {V(float32(118)), V(uint32(118))}, |
| 2401 | {V(uint32(119)), V(float64(119))}, |
| 2402 | {V(float64(120)), V(uint32(120))}, |
| 2403 | {V(int64(121)), V(int64(121))}, |
| 2404 | {V(int64(122)), V(uint64(122))}, |
| 2405 | {V(uint64(123)), V(int64(123))}, |
| 2406 | {V(int64(124)), V(int(124))}, |
| 2407 | {V(int(125)), V(int64(125))}, |
| 2408 | {V(int64(126)), V(uint(126))}, |
| 2409 | {V(uint(127)), V(int64(127))}, |
| 2410 | {V(int64(128)), V(uintptr(128))}, |
| 2411 | {V(uintptr(129)), V(int64(129))}, |
| 2412 | {V(int64(130)), V(float32(130))}, |
| 2413 | {V(float32(131)), V(int64(131))}, |
| 2414 | {V(int64(132)), V(float64(132))}, |
| 2415 | {V(float64(133)), V(int64(133))}, |
| 2416 | {V(uint64(134)), V(uint64(134))}, |
| 2417 | {V(uint64(135)), V(int(135))}, |
| 2418 | {V(int(136)), V(uint64(136))}, |
| 2419 | {V(uint64(137)), V(uint(137))}, |
| 2420 | {V(uint(138)), V(uint64(138))}, |
| 2421 | {V(uint64(139)), V(uintptr(139))}, |
| 2422 | {V(uintptr(140)), V(uint64(140))}, |
| 2423 | {V(uint64(141)), V(float32(141))}, |
| 2424 | {V(float32(142)), V(uint64(142))}, |
| 2425 | {V(uint64(143)), V(float64(143))}, |
| 2426 | {V(float64(144)), V(uint64(144))}, |
| 2427 | {V(int(145)), V(int(145))}, |
| 2428 | {V(int(146)), V(uint(146))}, |
| 2429 | {V(uint(147)), V(int(147))}, |
| 2430 | {V(int(148)), V(uintptr(148))}, |
| 2431 | {V(uintptr(149)), V(int(149))}, |
| 2432 | {V(int(150)), V(float32(150))}, |
| 2433 | {V(float32(151)), V(int(151))}, |
| 2434 | {V(int(152)), V(float64(152))}, |
| 2435 | {V(float64(153)), V(int(153))}, |
| 2436 | {V(uint(154)), V(uint(154))}, |
| 2437 | {V(uint(155)), V(uintptr(155))}, |
| 2438 | {V(uintptr(156)), V(uint(156))}, |
| 2439 | {V(uint(157)), V(float32(157))}, |
| 2440 | {V(float32(158)), V(uint(158))}, |
| 2441 | {V(uint(159)), V(float64(159))}, |
| 2442 | {V(float64(160)), V(uint(160))}, |
| 2443 | {V(uintptr(161)), V(uintptr(161))}, |
| 2444 | {V(uintptr(162)), V(float32(162))}, |
| 2445 | {V(float32(163)), V(uintptr(163))}, |
| 2446 | {V(uintptr(164)), V(float64(164))}, |
| 2447 | {V(float64(165)), V(uintptr(165))}, |
| 2448 | {V(float32(166)), V(float32(166))}, |
| 2449 | {V(float32(167)), V(float64(167))}, |
| 2450 | {V(float64(168)), V(float32(168))}, |
| 2451 | {V(float64(169)), V(float64(169))}, |
| 2452 | |
| 2453 | // truncation |
| 2454 | {V(float64(1.5)), V(int(1))}, |
| 2455 | |
| 2456 | // complex |
| 2457 | {V(complex64(1i)), V(complex64(1i))}, |
| 2458 | {V(complex64(2i)), V(complex128(2i))}, |
| 2459 | {V(complex128(3i)), V(complex64(3i))}, |
| 2460 | {V(complex128(4i)), V(complex128(4i))}, |
| 2461 | |
| 2462 | // string |
| 2463 | {V(string("hello")), V(string("hello"))}, |
| 2464 | {V(string("bytes1")), V([]byte("bytes1"))}, |
| 2465 | {V([]byte("bytes2")), V(string("bytes2"))}, |
| 2466 | {V([]byte("bytes3")), V([]byte("bytes3"))}, |
| 2467 | {V(string("runes♝")), V([]rune("runes♝"))}, |
| 2468 | {V([]rune("runes♕")), V(string("runes♕"))}, |
| 2469 | {V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))}, |
| 2470 | {V(int('a')), V(string("a"))}, |
| 2471 | {V(int8('a')), V(string("a"))}, |
| 2472 | {V(int16('a')), V(string("a"))}, |
| 2473 | {V(int32('a')), V(string("a"))}, |
| 2474 | {V(int64('a')), V(string("a"))}, |
| 2475 | {V(uint('a')), V(string("a"))}, |
| 2476 | {V(uint8('a')), V(string("a"))}, |
| 2477 | {V(uint16('a')), V(string("a"))}, |
| 2478 | {V(uint32('a')), V(string("a"))}, |
| 2479 | {V(uint64('a')), V(string("a"))}, |
| 2480 | {V(uintptr('a')), V(string("a"))}, |
| 2481 | {V(int(-1)), V(string("\uFFFD"))}, |
| 2482 | {V(int8(-2)), V(string("\uFFFD"))}, |
| 2483 | {V(int16(-3)), V(string("\uFFFD"))}, |
| 2484 | {V(int32(-4)), V(string("\uFFFD"))}, |
| 2485 | {V(int64(-5)), V(string("\uFFFD"))}, |
| 2486 | {V(uint(0x110001)), V(string("\uFFFD"))}, |
| 2487 | {V(uint32(0x110002)), V(string("\uFFFD"))}, |
| 2488 | {V(uint64(0x110003)), V(string("\uFFFD"))}, |
| 2489 | {V(uintptr(0x110004)), V(string("\uFFFD"))}, |
| 2490 | |
| 2491 | // named string |
| 2492 | {V(MyString("hello")), V(string("hello"))}, |
| 2493 | {V(string("hello")), V(MyString("hello"))}, |
| 2494 | {V(string("hello")), V(string("hello"))}, |
| 2495 | {V(MyString("hello")), V(MyString("hello"))}, |
| 2496 | {V(MyString("bytes1")), V([]byte("bytes1"))}, |
| 2497 | {V([]byte("bytes2")), V(MyString("bytes2"))}, |
| 2498 | {V([]byte("bytes3")), V([]byte("bytes3"))}, |
| 2499 | {V(MyString("runes♝")), V([]rune("runes♝"))}, |
| 2500 | {V([]rune("runes♕")), V(MyString("runes♕"))}, |
| 2501 | {V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))}, |
| 2502 | {V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))}, |
| 2503 | {V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))}, |
| 2504 | {V(int('a')), V(MyString("a"))}, |
| 2505 | {V(int8('a')), V(MyString("a"))}, |
| 2506 | {V(int16('a')), V(MyString("a"))}, |
| 2507 | {V(int32('a')), V(MyString("a"))}, |
| 2508 | {V(int64('a')), V(MyString("a"))}, |
| 2509 | {V(uint('a')), V(MyString("a"))}, |
| 2510 | {V(uint8('a')), V(MyString("a"))}, |
| 2511 | {V(uint16('a')), V(MyString("a"))}, |
| 2512 | {V(uint32('a')), V(MyString("a"))}, |
| 2513 | {V(uint64('a')), V(MyString("a"))}, |
| 2514 | {V(uintptr('a')), V(MyString("a"))}, |
| 2515 | {V(int(-1)), V(MyString("\uFFFD"))}, |
| 2516 | {V(int8(-2)), V(MyString("\uFFFD"))}, |
| 2517 | {V(int16(-3)), V(MyString("\uFFFD"))}, |
| 2518 | {V(int32(-4)), V(MyString("\uFFFD"))}, |
| 2519 | {V(int64(-5)), V(MyString("\uFFFD"))}, |
| 2520 | {V(uint(0x110001)), V(MyString("\uFFFD"))}, |
| 2521 | {V(uint32(0x110002)), V(MyString("\uFFFD"))}, |
| 2522 | {V(uint64(0x110003)), V(MyString("\uFFFD"))}, |
| 2523 | {V(uintptr(0x110004)), V(MyString("\uFFFD"))}, |
| 2524 | |
| 2525 | // named []byte |
| 2526 | {V(string("bytes1")), V(MyBytes("bytes1"))}, |
| 2527 | {V(MyBytes("bytes2")), V(string("bytes2"))}, |
| 2528 | {V(MyBytes("bytes3")), V(MyBytes("bytes3"))}, |
| 2529 | {V(MyString("bytes1")), V(MyBytes("bytes1"))}, |
| 2530 | {V(MyBytes("bytes2")), V(MyString("bytes2"))}, |
| 2531 | |
| 2532 | // named []rune |
| 2533 | {V(string("runes♝")), V(MyRunes("runes♝"))}, |
| 2534 | {V(MyRunes("runes♕")), V(string("runes♕"))}, |
| 2535 | {V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))}, |
| 2536 | {V(MyString("runes♝")), V(MyRunes("runes♝"))}, |
| 2537 | {V(MyRunes("runes♕")), V(MyString("runes♕"))}, |
| 2538 | |
| 2539 | // named types and equal underlying types |
| 2540 | {V(new(int)), V(new(integer))}, |
| 2541 | {V(new(integer)), V(new(int))}, |
| 2542 | {V(Empty{}), V(struct{}{})}, |
| 2543 | {V(new(Empty)), V(new(struct{}))}, |
| 2544 | {V(struct{}{}), V(Empty{})}, |
| 2545 | {V(new(struct{})), V(new(Empty))}, |
| 2546 | {V(Empty{}), V(Empty{})}, |
| 2547 | {V(MyBytes{}), V([]byte{})}, |
| 2548 | {V([]byte{}), V(MyBytes{})}, |
| 2549 | {V((func())(nil)), V(MyFunc(nil))}, |
| 2550 | {V((MyFunc)(nil)), V((func())(nil))}, |
| 2551 | |
| 2552 | // can convert *byte and *MyByte |
| 2553 | {V((*byte)(nil)), V((*MyByte)(nil))}, |
| 2554 | {V((*MyByte)(nil)), V((*byte)(nil))}, |
| 2555 | |
| 2556 | // cannot convert mismatched array sizes |
| 2557 | {V([2]byte{}), V([2]byte{})}, |
| 2558 | {V([3]byte{}), V([3]byte{})}, |
| 2559 | |
| 2560 | // cannot convert other instances |
| 2561 | {V((**byte)(nil)), V((**byte)(nil))}, |
| 2562 | {V((**MyByte)(nil)), V((**MyByte)(nil))}, |
| 2563 | {V((chan byte)(nil)), V((chan byte)(nil))}, |
| 2564 | {V((chan MyByte)(nil)), V((chan MyByte)(nil))}, |
| 2565 | {V(([]byte)(nil)), V(([]byte)(nil))}, |
| 2566 | {V(([]MyByte)(nil)), V(([]MyByte)(nil))}, |
| 2567 | {V((map[int]byte)(nil)), V((map[int]byte)(nil))}, |
| 2568 | {V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))}, |
| 2569 | {V((map[byte]int)(nil)), V((map[byte]int)(nil))}, |
| 2570 | {V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))}, |
| 2571 | {V([2]byte{}), V([2]byte{})}, |
| 2572 | {V([2]MyByte{}), V([2]MyByte{})}, |
| 2573 | |
| 2574 | // other |
| 2575 | {V((***int)(nil)), V((***int)(nil))}, |
| 2576 | {V((***byte)(nil)), V((***byte)(nil))}, |
| 2577 | {V((***int32)(nil)), V((***int32)(nil))}, |
| 2578 | {V((***int64)(nil)), V((***int64)(nil))}, |
| 2579 | {V((chan int)(nil)), V((<-chan int)(nil))}, |
| 2580 | {V((chan int)(nil)), V((chan<- int)(nil))}, |
| 2581 | {V((chan string)(nil)), V((<-chan string)(nil))}, |
| 2582 | {V((chan string)(nil)), V((chan<- string)(nil))}, |
| 2583 | {V((chan byte)(nil)), V((chan byte)(nil))}, |
| 2584 | {V((chan MyByte)(nil)), V((chan MyByte)(nil))}, |
| 2585 | {V((map[int]bool)(nil)), V((map[int]bool)(nil))}, |
| 2586 | {V((map[int]byte)(nil)), V((map[int]byte)(nil))}, |
| 2587 | {V((map[uint]bool)(nil)), V((map[uint]bool)(nil))}, |
| 2588 | {V([]uint(nil)), V([]uint(nil))}, |
| 2589 | {V([]int(nil)), V([]int(nil))}, |
| 2590 | {V(new(interface{})), V(new(interface{}))}, |
| 2591 | {V(new(io.Reader)), V(new(io.Reader))}, |
| 2592 | {V(new(io.Writer)), V(new(io.Writer))}, |
| 2593 | |
| 2594 | // interfaces |
| 2595 | {V(int(1)), EmptyInterfaceV(int(1))}, |
| 2596 | {V(string("hello")), EmptyInterfaceV(string("hello"))}, |
| 2597 | {V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))}, |
| 2598 | {ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))}, |
| 2599 | {V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))}, |
| 2600 | } |
| 2601 | |
| 2602 | func TestConvert(t *testing.T) { |
| 2603 | canConvert := map[[2]Type]bool{} |
| 2604 | all := map[Type]bool{} |
| 2605 | |
| 2606 | for _, tt := range convertTests { |
| 2607 | t1 := tt.in.Type() |
| 2608 | if !t1.ConvertibleTo(t1) { |
| 2609 | t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t1) |
| 2610 | continue |
| 2611 | } |
| 2612 | |
| 2613 | t2 := tt.out.Type() |
| 2614 | if !t1.ConvertibleTo(t2) { |
| 2615 | t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t2) |
| 2616 | continue |
| 2617 | } |
| 2618 | |
| 2619 | all[t1] = true |
| 2620 | all[t2] = true |
| 2621 | canConvert[[2]Type{t1, t2}] = true |
| 2622 | |
| 2623 | v1 := tt.in |
| 2624 | vout1 := v1.Convert(t1) |
| 2625 | out1 := vout1.Interface() |
| 2626 | if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) { |
| 2627 | t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t1, out1, out1, tt.in.Interface(), tt.in.Interface()) |
| 2628 | } |
| 2629 | |
| 2630 | vout := v1.Convert(t2) |
| 2631 | out := vout.Interface() |
| 2632 | if vout.Type() != tt.out.Type() || !DeepEqual(out, tt.out.Interface()) { |
| 2633 | t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t2, out, out, tt.out.Interface(), tt.out.Interface()) |
| 2634 | } |
| 2635 | |
| 2636 | if IsRO(v1) { |
| 2637 | t.Errorf("table entry %v is RO, should not be", v1) |
| 2638 | } |
| 2639 | if IsRO(vout1) { |
| 2640 | t.Errorf("self-conversion output %v is RO, should not be", vout1) |
| 2641 | } |
| 2642 | if IsRO(vout) { |
| 2643 | t.Errorf("conversion output %v is RO, should not be", vout) |
| 2644 | } |
| 2645 | if !IsRO(MakeRO(v1).Convert(t1)) { |
| 2646 | t.Errorf("RO self-conversion output %v is not RO, should be", v1) |
| 2647 | } |
| 2648 | if !IsRO(MakeRO(v1).Convert(t2)) { |
| 2649 | t.Errorf("RO conversion output %v is not RO, should be", v1) |
| 2650 | } |
| 2651 | } |
| 2652 | |
| 2653 | // Assume that of all the types we saw during the tests, |
| 2654 | // if there wasn't an explicit entry for a conversion between |
| 2655 | // a pair of types, then it's not to be allowed. This checks for |
| 2656 | // things like 'int64' converting to '*int'. |
| 2657 | for t1 := range all { |
| 2658 | for t2 := range all { |
| 2659 | expectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0 |
| 2660 | if ok := t1.ConvertibleTo(t2); ok != expectOK { |
| 2661 | t.Errorf("(%s).ConvertibleTo(%s) = %v, want %v", t1, t2, ok, expectOK) |
| 2662 | } |
| 2663 | } |
| 2664 | } |
| 2665 | } |
| 2666 | |
Russ Cox | 5e3224c | 2012-09-05 09:35:53 -0400 | [diff] [blame] | 2667 | type B1 struct { |
| 2668 | X int |
| 2669 | Y int |
| 2670 | Z int |
| 2671 | } |
| 2672 | |
| 2673 | func BenchmarkFieldByName1(b *testing.B) { |
| 2674 | t := TypeOf(B1{}) |
| 2675 | for i := 0; i < b.N; i++ { |
| 2676 | t.FieldByName("Z") |
| 2677 | } |
| 2678 | } |
| 2679 | |
| 2680 | func BenchmarkFieldByName2(b *testing.B) { |
| 2681 | t := TypeOf(S3{}) |
| 2682 | for i := 0; i < b.N; i++ { |
| 2683 | t.FieldByName("B") |
| 2684 | } |
| 2685 | } |
| 2686 | |
| 2687 | type R0 struct { |
| 2688 | *R1 |
| 2689 | *R2 |
| 2690 | *R3 |
| 2691 | *R4 |
| 2692 | } |
| 2693 | |
| 2694 | type R1 struct { |
| 2695 | *R5 |
| 2696 | *R6 |
| 2697 | *R7 |
| 2698 | *R8 |
| 2699 | } |
| 2700 | |
| 2701 | type R2 R1 |
| 2702 | type R3 R1 |
| 2703 | type R4 R1 |
| 2704 | |
| 2705 | type R5 struct { |
| 2706 | *R9 |
| 2707 | *R10 |
| 2708 | *R11 |
| 2709 | *R12 |
| 2710 | } |
| 2711 | |
| 2712 | type R6 R5 |
| 2713 | type R7 R5 |
| 2714 | type R8 R5 |
| 2715 | |
| 2716 | type R9 struct { |
| 2717 | *R13 |
| 2718 | *R14 |
| 2719 | *R15 |
| 2720 | *R16 |
| 2721 | } |
| 2722 | |
| 2723 | type R10 R9 |
| 2724 | type R11 R9 |
| 2725 | type R12 R9 |
| 2726 | |
| 2727 | type R13 struct { |
| 2728 | *R17 |
| 2729 | *R18 |
| 2730 | *R19 |
| 2731 | *R20 |
| 2732 | } |
| 2733 | |
| 2734 | type R14 R13 |
| 2735 | type R15 R13 |
| 2736 | type R16 R13 |
| 2737 | |
| 2738 | type R17 struct { |
| 2739 | *R21 |
| 2740 | *R22 |
| 2741 | *R23 |
| 2742 | *R24 |
| 2743 | } |
| 2744 | |
| 2745 | type R18 R17 |
| 2746 | type R19 R17 |
| 2747 | type R20 R17 |
| 2748 | |
| 2749 | type R21 struct { |
| 2750 | X int |
| 2751 | } |
| 2752 | |
| 2753 | type R22 R21 |
| 2754 | type R23 R21 |
| 2755 | type R24 R21 |
| 2756 | |
| 2757 | func TestEmbed(t *testing.T) { |
| 2758 | typ := TypeOf(R0{}) |
| 2759 | f, ok := typ.FieldByName("X") |
| 2760 | if ok { |
| 2761 | t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index) |
| 2762 | } |
| 2763 | } |
| 2764 | |
| 2765 | func BenchmarkFieldByName3(b *testing.B) { |
| 2766 | t := TypeOf(R0{}) |
| 2767 | for i := 0; i < b.N; i++ { |
| 2768 | t.FieldByName("X") |
| 2769 | } |
| 2770 | } |
Russ Cox | 370ae05 | 2012-09-18 14:22:41 -0400 | [diff] [blame] | 2771 | |
| 2772 | // An exhaustive is a mechanism for writing exhaustive or stochastic tests. |
| 2773 | // The basic usage is: |
| 2774 | // |
| 2775 | // for x.Next() { |
| 2776 | // ... code using x.Maybe() or x.Choice(n) to create test cases ... |
| 2777 | // } |
| 2778 | // |
| 2779 | // Each iteration of the loop returns a different set of results, until all |
| 2780 | // possible result sets have been explored. It is okay for different code paths |
| 2781 | // to make different method call sequences on x, but there must be no |
| 2782 | // other source of non-determinism in the call sequences. |
| 2783 | // |
| 2784 | // When faced with a new decision, x chooses randomly. Future explorations |
| 2785 | // of that path will choose successive values for the result. Thus, stopping |
| 2786 | // the loop after a fixed number of iterations gives somewhat stochastic |
| 2787 | // testing. |
| 2788 | // |
| 2789 | // Example: |
| 2790 | // |
| 2791 | // for x.Next() { |
| 2792 | // v := make([]bool, x.Choose(4)) |
| 2793 | // for i := range v { |
| 2794 | // v[i] = x.Maybe() |
| 2795 | // } |
| 2796 | // fmt.Println(v) |
| 2797 | // } |
| 2798 | // |
| 2799 | // prints (in some order): |
| 2800 | // |
| 2801 | // [] |
| 2802 | // [false] |
| 2803 | // [true] |
| 2804 | // [false false] |
| 2805 | // [false true] |
| 2806 | // ... |
| 2807 | // [true true] |
| 2808 | // [false false false] |
| 2809 | // ... |
| 2810 | // [true true true] |
| 2811 | // [false false false false] |
| 2812 | // ... |
| 2813 | // [true true true true] |
| 2814 | // |
| 2815 | type exhaustive struct { |
| 2816 | r *rand.Rand |
| 2817 | pos int |
| 2818 | last []choice |
| 2819 | } |
| 2820 | |
| 2821 | type choice struct { |
| 2822 | off int |
| 2823 | n int |
| 2824 | max int |
| 2825 | } |
| 2826 | |
| 2827 | func (x *exhaustive) Next() bool { |
| 2828 | if x.r == nil { |
| 2829 | x.r = rand.New(rand.NewSource(time.Now().UnixNano())) |
| 2830 | } |
| 2831 | x.pos = 0 |
| 2832 | if x.last == nil { |
| 2833 | x.last = []choice{} |
| 2834 | return true |
| 2835 | } |
| 2836 | for i := len(x.last) - 1; i >= 0; i-- { |
| 2837 | c := &x.last[i] |
| 2838 | if c.n+1 < c.max { |
| 2839 | c.n++ |
| 2840 | x.last = x.last[:i+1] |
| 2841 | return true |
| 2842 | } |
| 2843 | } |
| 2844 | return false |
| 2845 | } |
| 2846 | |
| 2847 | func (x *exhaustive) Choose(max int) int { |
| 2848 | if x.pos >= len(x.last) { |
| 2849 | x.last = append(x.last, choice{x.r.Intn(max), 0, max}) |
| 2850 | } |
| 2851 | c := &x.last[x.pos] |
| 2852 | x.pos++ |
| 2853 | if c.max != max { |
| 2854 | panic("inconsistent use of exhaustive tester") |
| 2855 | } |
| 2856 | return (c.n + c.off) % max |
| 2857 | } |
| 2858 | |
| 2859 | func (x *exhaustive) Maybe() bool { |
| 2860 | return x.Choose(2) == 1 |
| 2861 | } |