263 lines
4.6 KiB
Go
263 lines
4.6 KiB
Go
|
package winio
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"io"
|
||
|
"net"
|
||
|
"os"
|
||
|
"syscall"
|
||
|
"testing"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
var testPipeName = `\\.\pipe\winiotestpipe`
|
||
|
|
||
|
func TestDialUnknownFailsImmediately(t *testing.T) {
|
||
|
_, err := DialPipe(testPipeName, nil)
|
||
|
if err.(*os.PathError).Err != syscall.ENOENT {
|
||
|
t.Fatalf("expected ENOENT got %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDialListenerTimesOut(t *testing.T) {
|
||
|
l, err := ListenPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer l.Close()
|
||
|
var d = time.Duration(10 * time.Millisecond)
|
||
|
_, err = DialPipe(testPipeName, &d)
|
||
|
if err != ErrTimeout {
|
||
|
t.Fatalf("expected ErrTimeout, got %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDialAccessDeniedWithRestrictedSD(t *testing.T) {
|
||
|
c := PipeConfig{
|
||
|
SecurityDescriptor: "D:P(A;;0x1200FF;;;WD)",
|
||
|
}
|
||
|
l, err := ListenPipe(testPipeName, &c)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer l.Close()
|
||
|
_, err = DialPipe(testPipeName, nil)
|
||
|
if err.(*os.PathError).Err != syscall.ERROR_ACCESS_DENIED {
|
||
|
t.Fatalf("expected ERROR_ACCESS_DENIED, got %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func getConnection(cfg *PipeConfig) (client net.Conn, server net.Conn, err error) {
|
||
|
l, err := ListenPipe(testPipeName, cfg)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer l.Close()
|
||
|
|
||
|
type response struct {
|
||
|
c net.Conn
|
||
|
err error
|
||
|
}
|
||
|
ch := make(chan response)
|
||
|
go func() {
|
||
|
c, err := l.Accept()
|
||
|
ch <- response{c, err}
|
||
|
}()
|
||
|
|
||
|
c, err := DialPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
r := <-ch
|
||
|
if err = r.err; err != nil {
|
||
|
c.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
client = c
|
||
|
server = r.c
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func TestReadTimeout(t *testing.T) {
|
||
|
c, s, err := getConnection(nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer c.Close()
|
||
|
defer s.Close()
|
||
|
|
||
|
c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
|
||
|
|
||
|
buf := make([]byte, 10)
|
||
|
_, err = c.Read(buf)
|
||
|
if err != ErrTimeout {
|
||
|
t.Fatalf("expected ErrTimeout, got %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func server(l net.Listener, ch chan int) {
|
||
|
c, err := l.Accept()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
rw := bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c))
|
||
|
s, err := rw.ReadString('\n')
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
_, err = rw.WriteString("got " + s)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
err = rw.Flush()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
c.Close()
|
||
|
ch <- 1
|
||
|
}
|
||
|
|
||
|
func TestFullListenDialReadWrite(t *testing.T) {
|
||
|
l, err := ListenPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer l.Close()
|
||
|
|
||
|
ch := make(chan int)
|
||
|
go server(l, ch)
|
||
|
|
||
|
c, err := DialPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer c.Close()
|
||
|
|
||
|
rw := bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c))
|
||
|
_, err = rw.WriteString("hello world\n")
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
err = rw.Flush()
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
s, err := rw.ReadString('\n')
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
ms := "got hello world\n"
|
||
|
if s != ms {
|
||
|
t.Errorf("expected '%s', got '%s'", ms, s)
|
||
|
}
|
||
|
|
||
|
<-ch
|
||
|
}
|
||
|
|
||
|
func TestCloseAbortsListen(t *testing.T) {
|
||
|
l, err := ListenPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
ch := make(chan error)
|
||
|
go func() {
|
||
|
_, err := l.Accept()
|
||
|
ch <- err
|
||
|
}()
|
||
|
|
||
|
time.Sleep(30 * time.Millisecond)
|
||
|
l.Close()
|
||
|
|
||
|
err = <-ch
|
||
|
if err != ErrPipeListenerClosed {
|
||
|
t.Fatalf("expected ErrPipeListenerClosed, got %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ensureEOFOnClose(t *testing.T, r io.Reader, w io.Closer) {
|
||
|
b := make([]byte, 10)
|
||
|
w.Close()
|
||
|
n, err := r.Read(b)
|
||
|
if n > 0 {
|
||
|
t.Errorf("unexpected byte count %d", n)
|
||
|
}
|
||
|
if err != io.EOF {
|
||
|
t.Errorf("expected EOF: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestCloseClientEOFServer(t *testing.T) {
|
||
|
c, s, err := getConnection(nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer c.Close()
|
||
|
defer s.Close()
|
||
|
ensureEOFOnClose(t, c, s)
|
||
|
}
|
||
|
|
||
|
func TestCloseServerEOFClient(t *testing.T) {
|
||
|
c, s, err := getConnection(nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer c.Close()
|
||
|
defer s.Close()
|
||
|
ensureEOFOnClose(t, s, c)
|
||
|
}
|
||
|
|
||
|
func TestCloseWriteEOF(t *testing.T) {
|
||
|
cfg := &PipeConfig{
|
||
|
MessageMode: true,
|
||
|
}
|
||
|
c, s, err := getConnection(cfg)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer c.Close()
|
||
|
defer s.Close()
|
||
|
|
||
|
type closeWriter interface {
|
||
|
CloseWrite() error
|
||
|
}
|
||
|
|
||
|
err = c.(closeWriter).CloseWrite()
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
b := make([]byte, 10)
|
||
|
_, err = s.Read(b)
|
||
|
if err != io.EOF {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestAcceptAfterCloseFails(t *testing.T) {
|
||
|
l, err := ListenPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
l.Close()
|
||
|
_, err = l.Accept()
|
||
|
if err != ErrPipeListenerClosed {
|
||
|
t.Fatalf("expected ErrPipeListenerClosed, got %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDialTimesOutByDefault(t *testing.T) {
|
||
|
l, err := ListenPipe(testPipeName, nil)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer l.Close()
|
||
|
_, err = DialPipe(testPipeName, nil)
|
||
|
if err != ErrTimeout {
|
||
|
t.Fatalf("expected ErrTimeout, got %v", err)
|
||
|
}
|
||
|
}
|