229 lines
4.1 KiB
Go
229 lines
4.1 KiB
Go
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
// +build linux
|
||
|
|
||
|
package fsnotify
|
||
|
|
||
|
import (
|
||
|
"syscall"
|
||
|
"testing"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type testFd [2]int
|
||
|
|
||
|
func makeTestFd(t *testing.T) testFd {
|
||
|
var tfd testFd
|
||
|
errno := syscall.Pipe(tfd[:])
|
||
|
if errno != nil {
|
||
|
t.Fatalf("Failed to create pipe: %v", errno)
|
||
|
}
|
||
|
return tfd
|
||
|
}
|
||
|
|
||
|
func (tfd testFd) fd() int {
|
||
|
return tfd[0]
|
||
|
}
|
||
|
|
||
|
func (tfd testFd) closeWrite(t *testing.T) {
|
||
|
errno := syscall.Close(tfd[1])
|
||
|
if errno != nil {
|
||
|
t.Fatalf("Failed to close write end of pipe: %v", errno)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (tfd testFd) put(t *testing.T) {
|
||
|
buf := make([]byte, 10)
|
||
|
_, errno := syscall.Write(tfd[1], buf)
|
||
|
if errno != nil {
|
||
|
t.Fatalf("Failed to write to pipe: %v", errno)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (tfd testFd) get(t *testing.T) {
|
||
|
buf := make([]byte, 10)
|
||
|
_, errno := syscall.Read(tfd[0], buf)
|
||
|
if errno != nil {
|
||
|
t.Fatalf("Failed to read from pipe: %v", errno)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (tfd testFd) close() {
|
||
|
syscall.Close(tfd[1])
|
||
|
syscall.Close(tfd[0])
|
||
|
}
|
||
|
|
||
|
func makePoller(t *testing.T) (testFd, *fdPoller) {
|
||
|
tfd := makeTestFd(t)
|
||
|
poller, err := newFdPoller(tfd.fd())
|
||
|
if err != nil {
|
||
|
t.Fatalf("Failed to create poller: %v", err)
|
||
|
}
|
||
|
return tfd, poller
|
||
|
}
|
||
|
|
||
|
func TestPollerWithBadFd(t *testing.T) {
|
||
|
_, err := newFdPoller(-1)
|
||
|
if err != syscall.EBADF {
|
||
|
t.Fatalf("Expected EBADF, got: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPollerWithData(t *testing.T) {
|
||
|
tfd, poller := makePoller(t)
|
||
|
defer tfd.close()
|
||
|
defer poller.close()
|
||
|
|
||
|
tfd.put(t)
|
||
|
ok, err := poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
if !ok {
|
||
|
t.Fatalf("expected poller to return true")
|
||
|
}
|
||
|
tfd.get(t)
|
||
|
}
|
||
|
|
||
|
func TestPollerWithWakeup(t *testing.T) {
|
||
|
tfd, poller := makePoller(t)
|
||
|
defer tfd.close()
|
||
|
defer poller.close()
|
||
|
|
||
|
err := poller.wake()
|
||
|
if err != nil {
|
||
|
t.Fatalf("wake failed: %v", err)
|
||
|
}
|
||
|
ok, err := poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
if ok {
|
||
|
t.Fatalf("expected poller to return false")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPollerWithClose(t *testing.T) {
|
||
|
tfd, poller := makePoller(t)
|
||
|
defer tfd.close()
|
||
|
defer poller.close()
|
||
|
|
||
|
tfd.closeWrite(t)
|
||
|
ok, err := poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
if !ok {
|
||
|
t.Fatalf("expected poller to return true")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPollerWithWakeupAndData(t *testing.T) {
|
||
|
tfd, poller := makePoller(t)
|
||
|
defer tfd.close()
|
||
|
defer poller.close()
|
||
|
|
||
|
tfd.put(t)
|
||
|
err := poller.wake()
|
||
|
if err != nil {
|
||
|
t.Fatalf("wake failed: %v", err)
|
||
|
}
|
||
|
|
||
|
// both data and wakeup
|
||
|
ok, err := poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
if !ok {
|
||
|
t.Fatalf("expected poller to return true")
|
||
|
}
|
||
|
|
||
|
// data is still in the buffer, wakeup is cleared
|
||
|
ok, err = poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
if !ok {
|
||
|
t.Fatalf("expected poller to return true")
|
||
|
}
|
||
|
|
||
|
tfd.get(t)
|
||
|
// data is gone, only wakeup now
|
||
|
err = poller.wake()
|
||
|
if err != nil {
|
||
|
t.Fatalf("wake failed: %v", err)
|
||
|
}
|
||
|
ok, err = poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
if ok {
|
||
|
t.Fatalf("expected poller to return false")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPollerConcurrent(t *testing.T) {
|
||
|
tfd, poller := makePoller(t)
|
||
|
defer tfd.close()
|
||
|
defer poller.close()
|
||
|
|
||
|
oks := make(chan bool)
|
||
|
live := make(chan bool)
|
||
|
defer close(live)
|
||
|
go func() {
|
||
|
defer close(oks)
|
||
|
for {
|
||
|
ok, err := poller.wait()
|
||
|
if err != nil {
|
||
|
t.Fatalf("poller failed: %v", err)
|
||
|
}
|
||
|
oks <- ok
|
||
|
if !<-live {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
// Try a write
|
||
|
select {
|
||
|
case <-time.After(50 * time.Millisecond):
|
||
|
case <-oks:
|
||
|
t.Fatalf("poller did not wait")
|
||
|
}
|
||
|
tfd.put(t)
|
||
|
if !<-oks {
|
||
|
t.Fatalf("expected true")
|
||
|
}
|
||
|
tfd.get(t)
|
||
|
live <- true
|
||
|
|
||
|
// Try a wakeup
|
||
|
select {
|
||
|
case <-time.After(50 * time.Millisecond):
|
||
|
case <-oks:
|
||
|
t.Fatalf("poller did not wait")
|
||
|
}
|
||
|
err := poller.wake()
|
||
|
if err != nil {
|
||
|
t.Fatalf("wake failed: %v", err)
|
||
|
}
|
||
|
if <-oks {
|
||
|
t.Fatalf("expected false")
|
||
|
}
|
||
|
live <- true
|
||
|
|
||
|
// Try a close
|
||
|
select {
|
||
|
case <-time.After(50 * time.Millisecond):
|
||
|
case <-oks:
|
||
|
t.Fatalf("poller did not wait")
|
||
|
}
|
||
|
tfd.closeWrite(t)
|
||
|
if !<-oks {
|
||
|
t.Fatalf("expected true")
|
||
|
}
|
||
|
tfd.get(t)
|
||
|
}
|