| // 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 darwin dragonfly freebsd linux netbsd openbsd | 
 |  | 
 | package os_test | 
 |  | 
 | import ( | 
 | 	"bufio" | 
 | 	"bytes" | 
 | 	"fmt" | 
 | 	"io" | 
 | 	"io/ioutil" | 
 | 	"os" | 
 | 	"path/filepath" | 
 | 	"runtime" | 
 | 	"sync" | 
 | 	"syscall" | 
 | 	"testing" | 
 | 	"time" | 
 | ) | 
 |  | 
 | // Issue 24164. | 
 | func TestFifoEOF(t *testing.T) { | 
 | 	switch runtime.GOOS { | 
 | 	case "android": | 
 | 		t.Skip("skipping on Android; mkfifo syscall not available") | 
 | 	case "openbsd": | 
 | 		// On OpenBSD 6.2 this test just hangs for some reason. | 
 | 		t.Skip("skipping on OpenBSD; issue 25877") | 
 | 	} | 
 |  | 
 | 	dir, err := ioutil.TempDir("", "TestFifoEOF") | 
 | 	if err != nil { | 
 | 		t.Fatal(err) | 
 | 	} | 
 | 	defer os.RemoveAll(dir) | 
 |  | 
 | 	fifoName := filepath.Join(dir, "fifo") | 
 | 	if err := syscall.Mkfifo(fifoName, 0600); err != nil { | 
 | 		t.Fatal(err) | 
 | 	} | 
 |  | 
 | 	var wg sync.WaitGroup | 
 | 	wg.Add(1) | 
 | 	go func() { | 
 | 		defer wg.Done() | 
 |  | 
 | 		w, err := os.OpenFile(fifoName, os.O_WRONLY, 0) | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 			return | 
 | 		} | 
 |  | 
 | 		defer func() { | 
 | 			if err := w.Close(); err != nil { | 
 | 				t.Errorf("error closing writer: %v", err) | 
 | 			} | 
 | 		}() | 
 |  | 
 | 		for i := 0; i < 3; i++ { | 
 | 			time.Sleep(10 * time.Millisecond) | 
 | 			_, err := fmt.Fprintf(w, "line %d\n", i) | 
 | 			if err != nil { | 
 | 				t.Errorf("error writing to fifo: %v", err) | 
 | 				return | 
 | 			} | 
 | 		} | 
 | 		time.Sleep(10 * time.Millisecond) | 
 | 	}() | 
 |  | 
 | 	defer wg.Wait() | 
 |  | 
 | 	r, err := os.Open(fifoName) | 
 | 	if err != nil { | 
 | 		t.Fatal(err) | 
 | 	} | 
 |  | 
 | 	done := make(chan bool) | 
 | 	go func() { | 
 | 		defer close(done) | 
 |  | 
 | 		defer func() { | 
 | 			if err := r.Close(); err != nil { | 
 | 				t.Errorf("error closing reader: %v", err) | 
 | 			} | 
 | 		}() | 
 |  | 
 | 		rbuf := bufio.NewReader(r) | 
 | 		for { | 
 | 			b, err := rbuf.ReadBytes('\n') | 
 | 			if err == io.EOF { | 
 | 				break | 
 | 			} | 
 | 			if err != nil { | 
 | 				t.Error(err) | 
 | 				return | 
 | 			} | 
 | 			t.Logf("%s\n", bytes.TrimSpace(b)) | 
 | 		} | 
 | 	}() | 
 |  | 
 | 	select { | 
 | 	case <-done: | 
 | 		// Test succeeded. | 
 | 	case <-time.After(time.Second): | 
 | 		t.Error("timed out waiting for read") | 
 | 		// Close the reader to force the read to complete. | 
 | 		r.Close() | 
 | 	} | 
 | } |