Skip to content

Commit

Permalink
[release-branch.go1.9] internal/poll: add tests for Windows file and …
Browse files Browse the repository at this point in the history
…serial ports

I also wanted to test net sockets, but I do not know how to
access their file handles. So I did not implement socket tests.

Updates #21172

Change-Id: I5062c0e65a817571d755397d60762c175f9791ce
Reviewed-on: https://go-review.googlesource.com/53530
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/71131
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
  • Loading branch information
alexbrainman authored and rsc committed Oct 25, 2017
1 parent 93322a5 commit ed3b0d6
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 3 deletions.
17 changes: 17 additions & 0 deletions src/internal/poll/export_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2017 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.

// Export guts for testing on windows.
// Since testing imports os and os imports internal/poll,
// the internal/poll tests can not be in package poll.

package poll

var (
LogInitFD = &logInitFD
)

func (fd *FD) IsPartOfNetpoll() bool {
return fd.pd.runtimeCtx != 0
}
14 changes: 11 additions & 3 deletions src/internal/poll/fd_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ type FD struct {
isDir bool
}

// logInitFD is set by tests to enable file descriptor initialization logging.
var logInitFD func(net string, fd *FD, err error)

// Init initializes the FD. The Sysfd field should already be set.
// This can be called multiple times on a single FD.
// The net argument is a network name from the net package (e.g., "tcp"),
Expand All @@ -319,6 +322,7 @@ func (fd *FD) Init(net string) (string, error) {
return "", errors.New("internal error: unknown network type " + net)
}

var err error
if !fd.isFile && !fd.isConsole && !fd.isDir {
// Only call init for a network socket.
// This means that we don't add files to the runtime poller.
Expand All @@ -331,9 +335,13 @@ func (fd *FD) Init(net string) (string, error) {
// somehow call ExecIO, then ExecIO, and therefore the
// calling method, will return an error, because
// fd.pd.runtimeCtx will be 0.
if err := fd.pd.init(fd); err != nil {
return "", err
}
err = fd.pd.init(fd)
}
if logInitFD != nil {
logInitFD(net, fd, err)
}
if err != nil {
return "", err
}
if hasLoadSetFileCompletionNotificationModes {
// We do not use events, so we can skip them always.
Expand Down
111 changes: 111 additions & 0 deletions src/internal/poll/fd_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2017 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.

package poll_test

import (
"fmt"
"internal/poll"
"os"
"sync"
"syscall"
"testing"
)

type loggedFD struct {
Net string
FD *poll.FD
Err error
}

var (
logMu sync.Mutex
loggedFDs map[syscall.Handle]*loggedFD
)

func logFD(net string, fd *poll.FD, err error) {
logMu.Lock()
defer logMu.Unlock()

loggedFDs[fd.Sysfd] = &loggedFD{
Net: net,
FD: fd,
Err: err,
}
}

func init() {
loggedFDs = make(map[syscall.Handle]*loggedFD)
*poll.LogInitFD = logFD
}

func findLoggedFD(h syscall.Handle) (lfd *loggedFD, found bool) {
logMu.Lock()
defer logMu.Unlock()

lfd, found = loggedFDs[h]
return lfd, found
}

// checkFileIsNotPartOfNetpoll verifies that f is not managed by netpoll.
// It returns error, if check fails.
func checkFileIsNotPartOfNetpoll(f *os.File) error {
lfd, found := findLoggedFD(syscall.Handle(f.Fd()))
if !found {
return fmt.Errorf("%v fd=%v: is not found in the log", f.Name(), f.Fd())
}
if lfd.FD.IsPartOfNetpoll() {
return fmt.Errorf("%v fd=%v: is part of netpoll, but should not be (logged: net=%v err=%v)", f.Name(), f.Fd(), lfd.Net, lfd.Err)
}
return nil
}

func TestFileFdsAreInitialised(t *testing.T) {
exe, err := os.Executable()
if err != nil {
t.Fatal(err)
}
f, err := os.Open(exe)
if err != nil {
t.Fatal(err)
}
defer f.Close()

err = checkFileIsNotPartOfNetpoll(f)
if err != nil {
t.Fatal(err)
}
}

func TestSerialFdsAreInitialised(t *testing.T) {
for _, name := range []string{"COM1", "COM2", "COM3", "COM4"} {
t.Run(name, func(t *testing.T) {
h, err := syscall.CreateFile(syscall.StringToUTF16Ptr(name),
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
0,
nil,
syscall.OPEN_EXISTING,
syscall.FILE_ATTRIBUTE_NORMAL|syscall.FILE_FLAG_OVERLAPPED,
0)
if err != nil {
if errno, ok := err.(syscall.Errno); ok {
switch errno {
case syscall.ERROR_FILE_NOT_FOUND,
syscall.ERROR_ACCESS_DENIED:
t.Log("Skipping: ", err)
return
}
}
t.Fatal(err)
}
f := os.NewFile(uintptr(h), name)
defer f.Close()

err = checkFileIsNotPartOfNetpoll(f)
if err != nil {
t.Fatal(err)
}
})
}
}

0 comments on commit ed3b0d6

Please sign in to comment.