1// run
2
3// Copyright 2009 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
7// Test nil.
8
9package main
10
11import (
12	"fmt"
13	"time"
14)
15
16type T struct {
17	i int
18}
19
20type IN interface{}
21
22func main() {
23	var i *int
24	var f *float32
25	var s *string
26	var m map[float32]*int
27	var c chan int
28	var t *T
29	var in IN
30	var ta []IN
31
32	i = nil
33	f = nil
34	s = nil
35	m = nil
36	c = nil
37	t = nil
38	i = nil
39	ta = make([]IN, 1)
40	ta[0] = nil
41
42	_, _, _, _, _, _, _, _ = i, f, s, m, c, t, in, ta
43
44	arraytest()
45	chantest()
46	maptest()
47	slicetest()
48}
49
50func shouldPanic(f func()) {
51	defer func() {
52		if recover() == nil {
53			panic("not panicking")
54		}
55	}()
56	f()
57}
58
59func shouldBlock(f func()) {
60	go func() {
61		f()
62		panic("did not block")
63	}()
64	time.Sleep(1e7)
65}
66
67// nil array pointer
68
69func arraytest() {
70	var p *[10]int
71
72	// Looping over indices is fine.
73	s := 0
74	for i := range p {
75		s += i
76	}
77	if s != 45 {
78		panic(s)
79	}
80
81	s = 0
82	for i := 0; i < len(p); i++ {
83		s += i
84	}
85	if s != 45 {
86		panic(s)
87	}
88
89	// Looping over values is not.
90	shouldPanic(func() {
91		for i, v := range p {
92			s += i + v
93		}
94	})
95
96	shouldPanic(func() {
97		for i := 0; i < len(p); i++ {
98			s += p[i]
99		}
100	})
101}
102
103// nil channel
104// select tests already handle select on nil channel
105
106func chantest() {
107	var ch chan int
108
109	// nil channel is never ready
110	shouldBlock(func() {
111		ch <- 1
112	})
113	shouldBlock(func() {
114		<-ch
115	})
116	shouldBlock(func() {
117		x, ok := <-ch
118		println(x, ok) // unreachable
119	})
120
121	if len(ch) != 0 {
122		panic(len(ch))
123	}
124	if cap(ch) != 0 {
125		panic(cap(ch))
126	}
127}
128
129// nil map
130
131func maptest() {
132	var m map[int]int
133
134	// nil map appears empty
135	if len(m) != 0 {
136		panic(len(m))
137	}
138	if m[1] != 0 {
139		panic(m[1])
140	}
141	if x, ok := m[1]; x != 0 || ok {
142		panic(fmt.Sprint(x, ok))
143	}
144
145	for k, v := range m {
146		panic(k)
147		panic(v)
148	}
149
150	// can delete (non-existent) entries
151	delete(m, 2)
152
153	// but cannot be written to
154	shouldPanic(func() {
155		m[2] = 3
156	})
157}
158
159// nil slice
160
161func slicetest() {
162	var x []int
163
164	// nil slice is just a 0-element slice.
165	if len(x) != 0 {
166		panic(len(x))
167	}
168	if cap(x) != 0 {
169		panic(cap(x))
170	}
171
172	// no 0-element slices can be read from or written to
173	var s int
174	shouldPanic(func() {
175		s += x[1]
176	})
177	shouldPanic(func() {
178		x[2] = s
179	})
180}
181