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