Skip to content

Commit bc421d9

Browse files
authored
Bug: Close hvsock handle on listen error; fix tests (#310)
* Bug: Close hvsock handle on listen error; fix tests Close the socket created in `github.com/Microsoft/go-winio/pkg/ListenHvsock` if either the `Bind` or `Listen` calls fail. Go changed `filepath.VolumeName` code, resulting in different behavior in `github.com/Microsoft/go-winio/pkg/fs.GetFileSystemType`. Update test accordingly. Also add more debug logs to `pkg\fs\resolve_test.go`. Also, move add skip for fuzzing on WS2019 or older to `FuzzHvSockRxTx` code directly, instead of in ci.yml. See: https://go-review.googlesource.com/c/go/+/540277 Signed-off-by: Hamza El-Saawy <[email protected]> * PR: unskip TestResolvePath Signed-off-by: Hamza El-Saawy <[email protected]> --------- Signed-off-by: Hamza El-Saawy <[email protected]>
1 parent 553a715 commit bc421d9

File tree

5 files changed

+63
-18
lines changed

5 files changed

+63
-18
lines changed

.github/workflows/ci.yml

+29-15
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ jobs:
1313
runs-on: windows-2019
1414
steps:
1515
- name: Checkout
16-
uses: actions/checkout@v3
16+
uses: actions/checkout@v4
17+
with:
18+
show-progress: false
1719

1820
- name: Install go
19-
uses: actions/setup-go@v4
21+
uses: actions/setup-go@v5
2022
with:
2123
go-version: ${{ env.GO_VERSION }}
24+
cache: false
2225

2326
- name: Run golangci-lint
2427
uses: golangci/golangci-lint-action@v3
@@ -37,12 +40,17 @@ jobs:
3740
runs-on: windows-2019
3841
steps:
3942
- name: Checkout
40-
uses: actions/checkout@v3
43+
uses: actions/checkout@v4
44+
with:
45+
show-progress: false
4146

4247
- name: Install go
43-
uses: actions/setup-go@v4
48+
uses: actions/setup-go@v5
4449
with:
4550
go-version: ${{ env.GO_VERSION }}
51+
# don't really need to cache Go packages, since go generate doesn't require much.
52+
# otherwise, the cache used in the `test` stage will be (basically) empty.
53+
cache: false
4654

4755
- name: Run go generate
4856
shell: pwsh
@@ -78,26 +86,30 @@ jobs:
7886
os: [windows-2019, windows-2022, ubuntu-latest]
7987
steps:
8088
- name: Checkout
81-
uses: actions/checkout@v3
89+
uses: actions/checkout@v4
90+
with:
91+
show-progress: false
8292

8393
- name: Install go
84-
uses: actions/setup-go@v4
94+
uses: actions/setup-go@v5
8595
with:
8696
go-version: ${{ env.GO_VERSION }}
8797

98+
# avoid needing to download packages during test runs
99+
- name: Pre-fill Module Cache
100+
run: go mod download -x
101+
88102
- name: Install gotestsum
89103
run: go install gotest.tools/gotestsum@${{ env.GOTESTSUM_VERSION }}
90104

91105
- name: Test repo
92106
run: gotestsum --format standard-verbose --debug -- -gcflags=all=-d=checkptr -race -v ./...
93107

94-
# Fuzzing was added in go1.18, so all stable/supported versions of go should support it.
95-
# hvsock fuzzing fails on windows 2019, even though tests pass.
96-
#
97-
# If fuzzing tests are added to different packages, add them here.
98-
- name: Fuzz repo
99-
if: ${{ matrix.os == 'windows-2022' }}
100-
run: gotestsum --format standard-verbose --debug -- -run "^#" -fuzztime 500x -fuzz "FuzzHvSock"
108+
# !NOTE:
109+
# Fuzzing cannot be run across multiple packages, (ie, `go -fuzz "^Fuzz" ./...` fails).
110+
# If new fuzzing tests are added, exec additional runs for each package.
111+
- name: Fuzz root package
112+
run: gotestsum --format standard-verbose --debug -- -run "^#" -fuzztime 1m -fuzz "^Fuzz"
101113

102114
build:
103115
name: Build Repo
@@ -106,10 +118,12 @@ jobs:
106118
runs-on: "windows-2019"
107119
steps:
108120
- name: Checkout
109-
uses: actions/checkout@v3
121+
uses: actions/checkout@v4
122+
with:
123+
show-progress: false
110124

111125
- name: Install go
112-
uses: actions/setup-go@v4
126+
uses: actions/setup-go@v5
113127
with:
114128
go-version: ${{ env.GO_VERSION }}
115129

hvsock.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,18 @@ func newHVSocket() (*win32File, error) {
196196
// ListenHvsock listens for connections on the specified hvsock address.
197197
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
198198
l := &HvsockListener{addr: *addr}
199-
sock, err := newHVSocket()
199+
200+
var sock *win32File
201+
sock, err = newHVSocket()
200202
if err != nil {
201203
return nil, l.opErr("listen", err)
202204
}
205+
defer func() {
206+
if err != nil {
207+
_ = sock.Close()
208+
}
209+
}()
210+
203211
sa := addr.raw()
204212
err = socket.Bind(sock.handle, &sa)
205213
if err != nil {

hvsock_go118_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ import (
77
"fmt"
88
"testing"
99
"time"
10+
11+
"golang.org/x/sys/windows"
1012
)
1113

1214
func FuzzHvSockRxTx(f *testing.F) {
15+
// fuzzing fails on windows 2019 for some reason, even though tests pass
16+
if _, _, build := windows.RtlGetNtVersionNumbers(); build <= 17763 {
17+
f.Skipf("build (%d) must be > %d", build, 17763)
18+
}
19+
1320
for _, b := range [][]byte{
1421
[]byte("hello?"),
1522
[]byte("This is a really long string that should be a good example of the really long " +

pkg/fs/fs_windows_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ func TestGetFSTypeOfKnownDrive(t *testing.T) {
1818
}
1919

2020
func TestGetFSTypeOfInvalidPath(t *testing.T) {
21-
_, err := GetFileSystemType("7:\\")
21+
// [filepath.VolumeName] doesn't mandate that the drive letters matches [a-zA-Z].
22+
// Instead, use non-character drive.
23+
_, err := GetFileSystemType(`No:\`)
2224
if !errors.Is(err, ErrInvalidPath) {
2325
t.Fatalf("Expected `ErrInvalidPath`, got %v", err)
2426
}

pkg/fs/resolve_test.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,19 @@ func getWindowsBuildNumber() uint32 {
2525
func makeSymlink(t *testing.T, oldName string, newName string) {
2626
t.Helper()
2727

28+
t.Logf("make symlink: %s -> %s", oldName, newName)
29+
30+
if _, err := os.Lstat(oldName); err != nil {
31+
t.Fatalf("could not open file %q: %v", oldName, err)
32+
}
33+
2834
if err := os.Symlink(oldName, newName); err != nil {
2935
t.Fatalf("creating symlink: %s", err)
3036
}
37+
38+
if _, err := os.Lstat(newName); err != nil {
39+
t.Fatalf("could not open file %q: %v", newName, err)
40+
}
3141
}
3242

3343
func getVolumeGUIDPath(t *testing.T, path string) string {
@@ -209,14 +219,18 @@ func TestResolvePath(t *testing.T) {
209219
{filepath.Join(dir, "lnk4"), filepath.Join(volumePathVHD2, "data.txt"), "symlink to volume with mount point"},
210220
} {
211221
t.Run(tc.description, func(t *testing.T) {
222+
t.Logf("resolving: %s -> %s", tc.input, tc.expected)
223+
212224
actual, err := ResolvePath(tc.input)
213225
if err != nil {
214-
t.Fatalf("resolvePath should return no error, but %v", err)
226+
t.Fatalf("ResolvePath should return no error, but: %v", err)
215227
}
216228
if actual != tc.expected {
217229
t.Fatalf("expected %v but got %v", tc.expected, actual)
218230
}
231+
219232
// Make sure EvalSymlinks works with the resolved path, as an extra safety measure.
233+
t.Logf("filepath.EvalSymlinks(%s)", actual)
220234
p, err := filepath.EvalSymlinks(actual)
221235
if err != nil {
222236
t.Fatalf("EvalSymlinks should return no error, but %v", err)

0 commit comments

Comments
 (0)