LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package reflect_test | 5 package reflect_test |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "encoding/base64" | 9 "encoding/base64" |
10 "fmt" | 10 "fmt" |
11 "io" | 11 "io" |
| 12 "math/rand" |
12 "os" | 13 "os" |
13 . "reflect" | 14 . "reflect" |
14 "runtime" | 15 "runtime" |
| 16 "sync" |
15 "testing" | 17 "testing" |
| 18 "time" |
16 "unsafe" | 19 "unsafe" |
17 ) | 20 ) |
18 | 21 |
19 func TestBool(t *testing.T) { | 22 func TestBool(t *testing.T) { |
20 v := ValueOf(true) | 23 v := ValueOf(true) |
21 if v.Bool() != true { | 24 if v.Bool() != true { |
22 t.Fatal("ValueOf(true).Bool() = false") | 25 t.Fatal("ValueOf(true).Bool() = false") |
23 } | 26 } |
24 } | 27 } |
25 | 28 |
(...skipping 1022 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 cv = MakeChan(TypeOf(c), 10) | 1051 cv = MakeChan(TypeOf(c), 10) |
1049 c = cv.Interface().(chan int) | 1052 c = cv.Interface().(chan int) |
1050 for i := 0; i < 3; i++ { | 1053 for i := 0; i < 3; i++ { |
1051 c <- i | 1054 c <- i |
1052 } | 1055 } |
1053 if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) { | 1056 if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) { |
1054 t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c)) | 1057 t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c)) |
1055 } | 1058 } |
1056 } | 1059 } |
1057 | 1060 |
| 1061 // caseInfo describes a single case in a select test. |
| 1062 type caseInfo struct { |
| 1063 desc string |
| 1064 canSelect bool |
| 1065 recv Value |
| 1066 closed bool |
| 1067 helper func() |
| 1068 panic bool |
| 1069 } |
| 1070 |
| 1071 func TestSelect(t *testing.T) { |
| 1072 selectWatch.once.Do(func() { go selectWatcher() }) |
| 1073 |
| 1074 var x exhaustive |
| 1075 nch := 0 |
| 1076 newop := func(n int, cap int) (ch, val Value) { |
| 1077 nch++ |
| 1078 if nch%101%2 == 1 { |
| 1079 c := make(chan int, cap) |
| 1080 ch = ValueOf(c) |
| 1081 val = ValueOf(n) |
| 1082 } else { |
| 1083 c := make(chan string, cap) |
| 1084 ch = ValueOf(c) |
| 1085 val = ValueOf(fmt.Sprint(n)) |
| 1086 } |
| 1087 return |
| 1088 } |
| 1089 |
| 1090 for n := 0; x.Next(); n++ { |
| 1091 if testing.Short() && n >= 1000 { |
| 1092 break |
| 1093 } |
| 1094 if n%100000 == 0 && testing.Verbose() { |
| 1095 println("TestSelect", n) |
| 1096 } |
| 1097 var cases []SelectCase |
| 1098 var info []caseInfo |
| 1099 |
| 1100 // Ready send. |
| 1101 if x.Maybe() { |
| 1102 ch, val := newop(len(cases), 1) |
| 1103 cases = append(cases, SelectCase{ |
| 1104 Dir: SelectSend, |
| 1105 Chan: ch, |
| 1106 Send: val, |
| 1107 }) |
| 1108 info = append(info, caseInfo{desc: "ready send", canSele
ct: true}) |
| 1109 } |
| 1110 |
| 1111 // Ready recv. |
| 1112 if x.Maybe() { |
| 1113 ch, val := newop(len(cases), 1) |
| 1114 ch.Send(val) |
| 1115 cases = append(cases, SelectCase{ |
| 1116 Dir: SelectRecv, |
| 1117 Chan: ch, |
| 1118 }) |
| 1119 info = append(info, caseInfo{desc: "ready recv", canSele
ct: true, recv: val}) |
| 1120 } |
| 1121 |
| 1122 // Blocking send. |
| 1123 if x.Maybe() { |
| 1124 ch, val := newop(len(cases), 0) |
| 1125 cases = append(cases, SelectCase{ |
| 1126 Dir: SelectSend, |
| 1127 Chan: ch, |
| 1128 Send: val, |
| 1129 }) |
| 1130 // Let it execute? |
| 1131 if x.Maybe() { |
| 1132 f := func() { ch.Recv() } |
| 1133 info = append(info, caseInfo{desc: "blocking sen
d", helper: f}) |
| 1134 } else { |
| 1135 info = append(info, caseInfo{desc: "blocking sen
d"}) |
| 1136 } |
| 1137 } |
| 1138 |
| 1139 // Blocking recv. |
| 1140 if x.Maybe() { |
| 1141 ch, val := newop(len(cases), 0) |
| 1142 cases = append(cases, SelectCase{ |
| 1143 Dir: SelectRecv, |
| 1144 Chan: ch, |
| 1145 }) |
| 1146 // Let it execute? |
| 1147 if x.Maybe() { |
| 1148 f := func() { ch.Send(val) } |
| 1149 info = append(info, caseInfo{desc: "blocking rec
v", recv: val, helper: f}) |
| 1150 } else { |
| 1151 info = append(info, caseInfo{desc: "blocking rec
v"}) |
| 1152 } |
| 1153 } |
| 1154 |
| 1155 // Zero Chan send. |
| 1156 if x.Maybe() { |
| 1157 // Maybe include value to send. |
| 1158 var val Value |
| 1159 if x.Maybe() { |
| 1160 val = ValueOf(100) |
| 1161 } |
| 1162 cases = append(cases, SelectCase{ |
| 1163 Dir: SelectSend, |
| 1164 Send: val, |
| 1165 }) |
| 1166 info = append(info, caseInfo{desc: "zero Chan send"}) |
| 1167 } |
| 1168 |
| 1169 // Zero Chan receive. |
| 1170 if x.Maybe() { |
| 1171 cases = append(cases, SelectCase{ |
| 1172 Dir: SelectRecv, |
| 1173 }) |
| 1174 info = append(info, caseInfo{desc: "zero Chan recv"}) |
| 1175 } |
| 1176 |
| 1177 // nil Chan send. |
| 1178 if x.Maybe() { |
| 1179 cases = append(cases, SelectCase{ |
| 1180 Dir: SelectSend, |
| 1181 Chan: ValueOf((chan int)(nil)), |
| 1182 Send: ValueOf(101), |
| 1183 }) |
| 1184 info = append(info, caseInfo{desc: "nil Chan send"}) |
| 1185 } |
| 1186 |
| 1187 // nil Chan recv. |
| 1188 if x.Maybe() { |
| 1189 cases = append(cases, SelectCase{ |
| 1190 Dir: SelectRecv, |
| 1191 Chan: ValueOf((chan int)(nil)), |
| 1192 }) |
| 1193 info = append(info, caseInfo{desc: "nil Chan recv"}) |
| 1194 } |
| 1195 |
| 1196 // closed Chan send. |
| 1197 if x.Maybe() { |
| 1198 ch := make(chan int) |
| 1199 close(ch) |
| 1200 cases = append(cases, SelectCase{ |
| 1201 Dir: SelectSend, |
| 1202 Chan: ValueOf(ch), |
| 1203 Send: ValueOf(101), |
| 1204 }) |
| 1205 info = append(info, caseInfo{desc: "closed Chan send", c
anSelect: true, panic: true}) |
| 1206 } |
| 1207 |
| 1208 // closed Chan recv. |
| 1209 if x.Maybe() { |
| 1210 ch, val := newop(len(cases), 0) |
| 1211 ch.Close() |
| 1212 val = Zero(val.Type()) |
| 1213 cases = append(cases, SelectCase{ |
| 1214 Dir: SelectRecv, |
| 1215 Chan: ch, |
| 1216 }) |
| 1217 info = append(info, caseInfo{desc: "closed Chan recv", c
anSelect: true, closed: true, recv: val}) |
| 1218 } |
| 1219 |
| 1220 var helper func() // goroutine to help the select complete |
| 1221 |
| 1222 // Add default? Must be last case here, but will permute. |
| 1223 // Add the default if the select would otherwise |
| 1224 // block forever, and maybe add it anyway. |
| 1225 numCanSelect := 0 |
| 1226 canProceed := false |
| 1227 canBlock := true |
| 1228 canPanic := false |
| 1229 helpers := []int{} |
| 1230 for i, c := range info { |
| 1231 if c.canSelect { |
| 1232 canProceed = true |
| 1233 canBlock = false |
| 1234 numCanSelect++ |
| 1235 if c.panic { |
| 1236 canPanic = true |
| 1237 } |
| 1238 } else if c.helper != nil { |
| 1239 canProceed = true |
| 1240 helpers = append(helpers, i) |
| 1241 } |
| 1242 } |
| 1243 if !canProceed || x.Maybe() { |
| 1244 cases = append(cases, SelectCase{ |
| 1245 Dir: SelectDefault, |
| 1246 }) |
| 1247 info = append(info, caseInfo{desc: "default", canSelect:
canBlock}) |
| 1248 numCanSelect++ |
| 1249 } else if canBlock { |
| 1250 // Select needs to communicate with another goroutine. |
| 1251 cas := &info[helpers[x.Choose(len(helpers))]] |
| 1252 helper = cas.helper |
| 1253 cas.canSelect = true |
| 1254 numCanSelect++ |
| 1255 } |
| 1256 |
| 1257 // Permute cases and case info. |
| 1258 // Doing too much here makes the exhaustive loop |
| 1259 // too exhausting, so just do two swaps. |
| 1260 for loop := 0; loop < 2; loop++ { |
| 1261 i := x.Choose(len(cases)) |
| 1262 j := x.Choose(len(cases)) |
| 1263 cases[i], cases[j] = cases[j], cases[i] |
| 1264 info[i], info[j] = info[j], info[i] |
| 1265 } |
| 1266 |
| 1267 if helper != nil { |
| 1268 // We wait before kicking off a goroutine to satisfy a b
locked select. |
| 1269 // The pause needs to be big enough to let the select bl
ock before |
| 1270 // we run the helper, but if we lose that race once in a
while it's okay: the |
| 1271 // select will just proceed immediately. Not a big deal. |
| 1272 // For short tests we can grow [sic] the timeout a bit w
ithout fear of taking too long |
| 1273 pause := 10 * time.Microsecond |
| 1274 if testing.Short() { |
| 1275 pause = 100 * time.Microsecond |
| 1276 } |
| 1277 time.AfterFunc(pause, helper) |
| 1278 } |
| 1279 |
| 1280 // Run select. |
| 1281 i, recv, recvOK, panicErr := runSelect(cases, info) |
| 1282 if panicErr != nil && !canPanic { |
| 1283 t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info
), panicErr) |
| 1284 } |
| 1285 if panicErr == nil && canPanic && numCanSelect == 1 { |
| 1286 t.Fatalf("%s\nselected #%d incorrectly (should panic)",
fmtSelect(info), i) |
| 1287 } |
| 1288 if panicErr != nil { |
| 1289 continue |
| 1290 } |
| 1291 |
| 1292 cas := info[i] |
| 1293 if !cas.canSelect { |
| 1294 recvStr := "" |
| 1295 if recv.IsValid() { |
| 1296 recvStr = fmt.Sprintf(", received %v, %v", recv.
Interface(), recvOK) |
| 1297 } |
| 1298 t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(inf
o), i, recvStr) |
| 1299 continue |
| 1300 } |
| 1301 if cas.panic { |
| 1302 t.Fatalf("%s\nselected #%d incorrectly (case should pani
c)", fmtSelect(info), i) |
| 1303 continue |
| 1304 } |
| 1305 |
| 1306 if cases[i].Dir == SelectRecv { |
| 1307 if !recv.IsValid() { |
| 1308 t.Fatalf("%s\nselected #%d but got %v, %v, want
%v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed) |
| 1309 } |
| 1310 if !cas.recv.IsValid() { |
| 1311 t.Fatalf("%s\nselected #%d but internal error: m
issing recv value", fmtSelect(info), i) |
| 1312 } |
| 1313 if recv.Interface() != cas.recv.Interface() || recvOK !=
!cas.closed { |
| 1314 if recv.Interface() == cas.recv.Interface() && r
ecvOK == !cas.closed { |
| 1315 t.Fatalf("%s\nselected #%d, got %#v, %v,
and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, r
ecv.Interface()) |
| 1316 } |
| 1317 t.Fatalf("%s\nselected #%d but got %#v, %v, want
%#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !
cas.closed) |
| 1318 } |
| 1319 } else { |
| 1320 if recv.IsValid() || recvOK { |
| 1321 t.Fatalf("%s\nselected #%d but got %v, %v, want
%v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false) |
| 1322 } |
| 1323 } |
| 1324 } |
| 1325 } |
| 1326 |
| 1327 // selectWatch and the selectWatcher are a watchdog mechanism for running Select
. |
| 1328 // If the selectWatcher notices that the select has been blocked for >1 second,
it prints |
| 1329 // an error describing the select and panics the entire test binary.· |
| 1330 var selectWatch struct { |
| 1331 sync.Mutex |
| 1332 once sync.Once |
| 1333 now time.Time |
| 1334 info []caseInfo |
| 1335 } |
| 1336 |
| 1337 func selectWatcher() { |
| 1338 for { |
| 1339 time.Sleep(1 * time.Second) |
| 1340 selectWatch.Lock() |
| 1341 if selectWatch.info != nil && time.Since(selectWatch.now) > 1*ti
me.Second { |
| 1342 fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefini
tely\n", fmtSelect(selectWatch.info)) |
| 1343 panic("select stuck") |
| 1344 } |
| 1345 selectWatch.Unlock() |
| 1346 } |
| 1347 } |
| 1348 |
| 1349 // runSelect runs a single select test. |
| 1350 // It returns the values returned by Select but also returns |
| 1351 // a panic value if the Select panics. |
| 1352 func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, rec
vOK bool, panicErr interface{}) { |
| 1353 defer func() { |
| 1354 panicErr = recover() |
| 1355 |
| 1356 selectWatch.Lock() |
| 1357 selectWatch.info = nil |
| 1358 selectWatch.Unlock() |
| 1359 }() |
| 1360 |
| 1361 selectWatch.Lock() |
| 1362 selectWatch.now = time.Now() |
| 1363 selectWatch.info = info |
| 1364 selectWatch.Unlock() |
| 1365 |
| 1366 chosen, recv, recvOK = Select(cases) |
| 1367 return |
| 1368 } |
| 1369 |
| 1370 // fmtSelect formats the information about a single select test. |
| 1371 func fmtSelect(info []caseInfo) string { |
| 1372 var buf bytes.Buffer |
| 1373 fmt.Fprintf(&buf, "\nselect {\n") |
| 1374 for i, cas := range info { |
| 1375 fmt.Fprintf(&buf, "%d: %s", i, cas.desc) |
| 1376 if cas.recv.IsValid() { |
| 1377 fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface()) |
| 1378 } |
| 1379 if cas.canSelect { |
| 1380 fmt.Fprintf(&buf, " canselect") |
| 1381 } |
| 1382 if cas.panic { |
| 1383 fmt.Fprintf(&buf, " panic") |
| 1384 } |
| 1385 fmt.Fprintf(&buf, "\n") |
| 1386 } |
| 1387 fmt.Fprintf(&buf, "}") |
| 1388 return buf.String() |
| 1389 } |
| 1390 |
1058 // Difficult test for function call because of | 1391 // Difficult test for function call because of |
1059 // implicit padding between arguments. | 1392 // implicit padding between arguments. |
1060 func dummy(b byte, c int, d byte) (i byte, j int, k byte) { | 1393 func dummy(b byte, c int, d byte) (i byte, j int, k byte) { |
1061 return b, c, d | 1394 return b, c, d |
1062 } | 1395 } |
1063 | 1396 |
1064 func TestFunc(t *testing.T) { | 1397 func TestFunc(t *testing.T) { |
1065 ret := ValueOf(dummy).Call([]Value{ValueOf(byte(10)), ValueOf(20), Value
Of(byte(30))}) | 1398 ret := ValueOf(dummy).Call([]Value{ValueOf(byte(10)), ValueOf(20), Value
Of(byte(30))}) |
1066 if len(ret) != 3 { | 1399 if len(ret) != 3 { |
1067 t.Fatalf("Call returned %d values, want 3", len(ret)) | 1400 t.Fatalf("Call returned %d values, want 3", len(ret)) |
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index) | 2259 t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index) |
1927 } | 2260 } |
1928 } | 2261 } |
1929 | 2262 |
1930 func BenchmarkFieldByName3(b *testing.B) { | 2263 func BenchmarkFieldByName3(b *testing.B) { |
1931 t := TypeOf(R0{}) | 2264 t := TypeOf(R0{}) |
1932 for i := 0; i < b.N; i++ { | 2265 for i := 0; i < b.N; i++ { |
1933 t.FieldByName("X") | 2266 t.FieldByName("X") |
1934 } | 2267 } |
1935 } | 2268 } |
| 2269 |
| 2270 // An exhaustive is a mechanism for writing exhaustive or stochastic tests. |
| 2271 // The basic usage is: |
| 2272 // |
| 2273 // for x.Next() { |
| 2274 // ... code using x.Maybe() or x.Choice(n) to create test cases ... |
| 2275 // } |
| 2276 // |
| 2277 // Each iteration of the loop returns a different set of results, until all |
| 2278 // possible result sets have been explored. It is okay for different code paths |
| 2279 // to make different method call sequences on x, but there must be no |
| 2280 // other source of non-determinism in the call sequences. |
| 2281 // |
| 2282 // When faced with a new decision, x chooses randomly. Future explorations |
| 2283 // of that path will choose successive values for the result. Thus, stopping |
| 2284 // the loop after a fixed number of iterations gives somewhat stochastic |
| 2285 // testing. |
| 2286 // |
| 2287 // Example: |
| 2288 // |
| 2289 // for x.Next() { |
| 2290 // v := make([]bool, x.Choose(4)) |
| 2291 // for i := range v { |
| 2292 // v[i] = x.Maybe() |
| 2293 // } |
| 2294 // fmt.Println(v) |
| 2295 // } |
| 2296 // |
| 2297 // prints (in some order): |
| 2298 // |
| 2299 // [] |
| 2300 // [false] |
| 2301 // [true] |
| 2302 // [false false] |
| 2303 // [false true] |
| 2304 // ... |
| 2305 // [true true] |
| 2306 // [false false false] |
| 2307 // ... |
| 2308 // [true true true] |
| 2309 // [false false false false] |
| 2310 // ... |
| 2311 // [true true true true] |
| 2312 // |
| 2313 type exhaustive struct { |
| 2314 r *rand.Rand |
| 2315 pos int |
| 2316 last []choice |
| 2317 } |
| 2318 |
| 2319 type choice struct { |
| 2320 off int |
| 2321 n int |
| 2322 max int |
| 2323 } |
| 2324 |
| 2325 func (x *exhaustive) Next() bool { |
| 2326 if x.r == nil { |
| 2327 x.r = rand.New(rand.NewSource(time.Now().UnixNano())) |
| 2328 } |
| 2329 x.pos = 0 |
| 2330 if x.last == nil { |
| 2331 x.last = []choice{} |
| 2332 return true |
| 2333 } |
| 2334 for i := len(x.last) - 1; i >= 0; i-- { |
| 2335 c := &x.last[i] |
| 2336 if c.n+1 < c.max { |
| 2337 c.n++ |
| 2338 x.last = x.last[:i+1] |
| 2339 return true |
| 2340 } |
| 2341 } |
| 2342 return false |
| 2343 } |
| 2344 |
| 2345 func (x *exhaustive) Choose(max int) int { |
| 2346 if x.pos >= len(x.last) { |
| 2347 x.last = append(x.last, choice{x.r.Intn(max), 0, max}) |
| 2348 } |
| 2349 c := &x.last[x.pos] |
| 2350 x.pos++ |
| 2351 if c.max != max { |
| 2352 panic("inconsistent use of exhaustive tester") |
| 2353 } |
| 2354 return (c.n + c.off) % max |
| 2355 } |
| 2356 |
| 2357 func (x *exhaustive) Maybe() bool { |
| 2358 return x.Choose(2) == 1 |
| 2359 } |
LEFT | RIGHT |