1// run
2
3// Copyright 2016 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package main
8
9import (
10	"fmt"
11	"io"
12	"os"
13	"reflect"
14	"unsafe"
15)
16
17type RWS struct{}
18
19func (x *RWS) Read(p []byte) (n int, err error)                   { return }
20func (x *RWS) Write(p []byte) (n int, err error)                  { return }
21func (x *RWS) Seek(offset int64, whence int) (n int64, err error) { return }
22func (x *RWS) String() string                                     { return "rws" }
23
24func makeRWS() io.ReadWriteSeeker { return &RWS{} }
25func makeStringer() fmt.Stringer  { return &RWS{} }
26
27// Test correct construction of static empty interface values
28var efaces = [...]struct {
29	x interface{}
30	s string
31}{
32	{nil, "<nil> <nil>"},
33	{1, "int 1"},
34	{int(1), "int 1"},
35	{Int(int(2)), "main.Int Int=2"},
36	{int(Int(3)), "int 3"},
37	{[1]int{2}, "[1]int [2]"},
38	{io.Reader(io.ReadWriter(io.ReadWriteSeeker(nil))), "<nil> <nil>"},
39	{io.Reader(io.ReadWriter(io.ReadWriteSeeker(&RWS{}))), "*main.RWS rws"},
40	{makeRWS(), "*main.RWS rws"},
41	{map[string]string{"here": "there"}, "map[string]string map[here:there]"},
42	{chan bool(nil), "chan bool <nil>"},
43	{unsafe.Pointer(uintptr(0)), "unsafe.Pointer <nil>"},
44	{(*byte)(nil), "*uint8 <nil>"},
45	{io.Writer((*os.File)(nil)), "*os.File <nil>"},
46	{(interface{})(io.Writer((*os.File)(nil))), "*os.File <nil>"},
47	{fmt.Stringer(Strunger(((*Int)(nil)))), "*main.Int <nil>"},
48}
49
50type Int int
51
52func (i Int) String() string { return fmt.Sprintf("Int=%d", i) }
53func (i Int) Strung()        {}
54
55type Strunger interface {
56	fmt.Stringer
57	Strung()
58}
59
60// Test correct construction of static non-empty interface values
61var ifaces = [...]struct {
62	x fmt.Stringer
63	s string
64}{
65	{nil, "<nil> <nil> %!s(<nil>)"},
66	{Int(3), "main.Int 3 Int=3"},
67	{Int(int(Int(4))), "main.Int 4 Int=4"},
68	{Strunger(Int(5)), "main.Int 5 Int=5"},
69	{makeStringer(), "*main.RWS &main.RWS{} rws"},
70	{fmt.Stringer(nil), "<nil> <nil> %!s(<nil>)"},
71	{(*RWS)(nil), "*main.RWS (*main.RWS)(nil) rws"},
72}
73
74// Test correct handling of direct interface values
75var (
76	one  int         = 1
77	iptr interface{} = &one
78	clos int
79	f    interface{} = func() { clos++ }
80	deep interface{} = [1]struct{ a *[2]byte }{{a: &[2]byte{'z', 'w'}}}
81	ch   interface{} = make(chan bool, 1)
82)
83
84func main() {
85	var fail bool
86	for i, test := range efaces {
87		s := fmt.Sprintf("%[1]T %[1]v", test.x)
88		if s != test.s {
89			fmt.Printf("eface(%d)=%q want %q\n", i, s, test.s)
90			fail = true
91		}
92	}
93
94	for i, test := range ifaces {
95		s := fmt.Sprintf("%[1]T %#[1]v %[1]s", test.x)
96		if s != test.s {
97			fmt.Printf("iface(%d)=%q want %q\n", i, s, test.s)
98			fail = true
99		}
100	}
101
102	if got := *(iptr.(*int)); got != 1 {
103		fmt.Printf("bad int ptr %d\n", got)
104		fail = true
105	}
106
107	f.(func())()
108	f.(func())()
109	f.(func())()
110	if clos != 3 {
111		fmt.Printf("bad closure exec %d\n", clos)
112		fail = true
113	}
114
115	if !reflect.DeepEqual(*(deep.([1]struct{ a *[2]byte })[0].a), [2]byte{'z', 'w'}) {
116		fmt.Printf("bad deep directiface\n")
117		fail = true
118	}
119
120	cc := ch.(chan bool)
121	cc <- true
122	if got := <-cc; !got {
123		fmt.Printf("bad chan\n")
124		fail = true
125	}
126
127	if fail {
128		fmt.Println("BUG")
129		os.Exit(1)
130	}
131}
132