1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build linux
6
7package fsnotify
8
9import (
10	"testing"
11	"time"
12
13	"golang.org/x/sys/unix"
14)
15
16type testFd [2]int
17
18func makeTestFd(t *testing.T) testFd {
19	var tfd testFd
20	errno := unix.Pipe(tfd[:])
21	if errno != nil {
22		t.Fatalf("Failed to create pipe: %v", errno)
23	}
24	return tfd
25}
26
27func (tfd testFd) fd() int {
28	return tfd[0]
29}
30
31func (tfd testFd) closeWrite(t *testing.T) {
32	errno := unix.Close(tfd[1])
33	if errno != nil {
34		t.Fatalf("Failed to close write end of pipe: %v", errno)
35	}
36}
37
38func (tfd testFd) put(t *testing.T) {
39	buf := make([]byte, 10)
40	_, errno := unix.Write(tfd[1], buf)
41	if errno != nil {
42		t.Fatalf("Failed to write to pipe: %v", errno)
43	}
44}
45
46func (tfd testFd) get(t *testing.T) {
47	buf := make([]byte, 10)
48	_, errno := unix.Read(tfd[0], buf)
49	if errno != nil {
50		t.Fatalf("Failed to read from pipe: %v", errno)
51	}
52}
53
54func (tfd testFd) close() {
55	unix.Close(tfd[1])
56	unix.Close(tfd[0])
57}
58
59func makePoller(t *testing.T) (testFd, *fdPoller) {
60	tfd := makeTestFd(t)
61	poller, err := newFdPoller(tfd.fd())
62	if err != nil {
63		t.Fatalf("Failed to create poller: %v", err)
64	}
65	return tfd, poller
66}
67
68func TestPollerWithBadFd(t *testing.T) {
69	_, err := newFdPoller(-1)
70	if err != unix.EBADF {
71		t.Fatalf("Expected EBADF, got: %v", err)
72	}
73}
74
75func TestPollerWithData(t *testing.T) {
76	tfd, poller := makePoller(t)
77	defer tfd.close()
78	defer poller.close()
79
80	tfd.put(t)
81	ok, err := poller.wait()
82	if err != nil {
83		t.Fatalf("poller failed: %v", err)
84	}
85	if !ok {
86		t.Fatalf("expected poller to return true")
87	}
88	tfd.get(t)
89}
90
91func TestPollerWithWakeup(t *testing.T) {
92	tfd, poller := makePoller(t)
93	defer tfd.close()
94	defer poller.close()
95
96	err := poller.wake()
97	if err != nil {
98		t.Fatalf("wake failed: %v", err)
99	}
100	ok, err := poller.wait()
101	if err != nil {
102		t.Fatalf("poller failed: %v", err)
103	}
104	if ok {
105		t.Fatalf("expected poller to return false")
106	}
107}
108
109func TestPollerWithClose(t *testing.T) {
110	tfd, poller := makePoller(t)
111	defer tfd.close()
112	defer poller.close()
113
114	tfd.closeWrite(t)
115	ok, err := poller.wait()
116	if err != nil {
117		t.Fatalf("poller failed: %v", err)
118	}
119	if !ok {
120		t.Fatalf("expected poller to return true")
121	}
122}
123
124func TestPollerWithWakeupAndData(t *testing.T) {
125	tfd, poller := makePoller(t)
126	defer tfd.close()
127	defer poller.close()
128
129	tfd.put(t)
130	err := poller.wake()
131	if err != nil {
132		t.Fatalf("wake failed: %v", err)
133	}
134
135	// both data and wakeup
136	ok, err := poller.wait()
137	if err != nil {
138		t.Fatalf("poller failed: %v", err)
139	}
140	if !ok {
141		t.Fatalf("expected poller to return true")
142	}
143
144	// data is still in the buffer, wakeup is cleared
145	ok, err = poller.wait()
146	if err != nil {
147		t.Fatalf("poller failed: %v", err)
148	}
149	if !ok {
150		t.Fatalf("expected poller to return true")
151	}
152
153	tfd.get(t)
154	// data is gone, only wakeup now
155	err = poller.wake()
156	if err != nil {
157		t.Fatalf("wake failed: %v", err)
158	}
159	ok, err = poller.wait()
160	if err != nil {
161		t.Fatalf("poller failed: %v", err)
162	}
163	if ok {
164		t.Fatalf("expected poller to return false")
165	}
166}
167
168func TestPollerConcurrent(t *testing.T) {
169	tfd, poller := makePoller(t)
170	defer tfd.close()
171	defer poller.close()
172
173	oks := make(chan bool)
174	live := make(chan bool)
175	defer close(live)
176	go func() {
177		defer close(oks)
178		for {
179			ok, err := poller.wait()
180			if err != nil {
181				t.Fatalf("poller failed: %v", err)
182			}
183			oks <- ok
184			if !<-live {
185				return
186			}
187		}
188	}()
189
190	// Try a write
191	select {
192	case <-time.After(50 * time.Millisecond):
193	case <-oks:
194		t.Fatalf("poller did not wait")
195	}
196	tfd.put(t)
197	if !<-oks {
198		t.Fatalf("expected true")
199	}
200	tfd.get(t)
201	live <- true
202
203	// Try a wakeup
204	select {
205	case <-time.After(50 * time.Millisecond):
206	case <-oks:
207		t.Fatalf("poller did not wait")
208	}
209	err := poller.wake()
210	if err != nil {
211		t.Fatalf("wake failed: %v", err)
212	}
213	if <-oks {
214		t.Fatalf("expected false")
215	}
216	live <- true
217
218	// Try a close
219	select {
220	case <-time.After(50 * time.Millisecond):
221	case <-oks:
222		t.Fatalf("poller did not wait")
223	}
224	tfd.closeWrite(t)
225	if !<-oks {
226		t.Fatalf("expected true")
227	}
228	tfd.get(t)
229}
230