| // 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) |
| } |
| }) |
| } |
| } |