Files
kunchenguid--no-mistakes/internal/agent/serverpid_transient_windows_test.go
wehub-resource-sync 26f897c1ec
release / release-please (push) Failing after 1m49s
docs / build (push) Failing after 6m34s
release / build-and-upload (arm64, linux) (push) Has been cancelled
release / build-and-upload (arm64, windows) (push) Has been cancelled
release / build-darwin (amd64, darwin) (push) Has been cancelled
release / checksums (push) Has been cancelled
release / finalize (push) Has been cancelled
release / build-darwin (arm64, darwin) (push) Has been cancelled
release / build-and-upload (amd64, linux) (push) Has been cancelled
release / build-and-upload (amd64, windows) (push) Has been cancelled
docs / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:34:16 +08:00

98 lines
2.9 KiB
Go

//go:build windows
package agent
import (
"errors"
"io/fs"
"os"
"syscall"
"testing"
)
func TestIsTransientPIDOpenError_Windows(t *testing.T) {
cases := []struct {
name string
err error
want bool
}{
{name: "nil", err: nil, want: false},
{name: "sharing_violation", err: &fs.PathError{Op: "open", Path: "x", Err: syscall.Errno(32)}, want: true},
{name: "access_denied", err: &fs.PathError{Op: "open", Path: "x", Err: syscall.Errno(5)}, want: false},
{name: "not_exist", err: os.ErrNotExist, want: false},
{name: "other_errno", err: &fs.PathError{Op: "open", Path: "x", Err: syscall.Errno(2)}, want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := isTransientPIDOpenError(tc.err); got != tc.want {
t.Fatalf("isTransientPIDOpenError(%v) = %v, want %v", tc.err, got, tc.want)
}
})
}
}
func TestIsTransientPIDReplaceError_Windows(t *testing.T) {
cases := []struct {
name string
err error
want bool
}{
{name: "nil", err: nil, want: false},
{name: "sharing_violation", err: &fs.PathError{Op: "rename", Path: "x", Err: syscall.Errno(32)}, want: true},
{name: "access_denied", err: &fs.PathError{Op: "rename", Path: "x", Err: syscall.Errno(5)}, want: true},
{name: "not_exist", err: os.ErrNotExist, want: false},
{name: "other_errno", err: &fs.PathError{Op: "rename", Path: "x", Err: syscall.Errno(2)}, want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := isTransientPIDReplaceError(tc.err); got != tc.want {
t.Fatalf("isTransientPIDReplaceError(%v) = %v, want %v", tc.err, got, tc.want)
}
})
}
}
func TestReplaceServerPIDFile_WindowsRetriesTransientRenameError(t *testing.T) {
prevRename := renameServerPIDFile
prevSleep := sleepServerPIDRenameRetry
t.Cleanup(func() {
renameServerPIDFile = prevRename
sleepServerPIDRenameRetry = prevSleep
})
var calls int
renameServerPIDFile = func(oldpath, newpath string) error {
calls++
if calls < 3 {
return &fs.PathError{Op: "rename", Path: newpath, Err: syscall.Errno(5)}
}
return nil
}
sleepServerPIDRenameRetry = func() {}
if err := replaceServerPIDFile("tmp.json", "dst.json"); err != nil {
t.Fatalf("replaceServerPIDFile() error = %v", err)
}
if calls != 3 {
t.Fatalf("replaceServerPIDFile() calls = %d, want 3", calls)
}
}
func TestReplaceServerPIDFile_WindowsStopsOnPermanentRenameError(t *testing.T) {
prevRename := renameServerPIDFile
prevSleep := sleepServerPIDRenameRetry
t.Cleanup(func() {
renameServerPIDFile = prevRename
sleepServerPIDRenameRetry = prevSleep
})
wantErr := &fs.PathError{Op: "rename", Path: "dst.json", Err: errors.New("boom")}
renameServerPIDFile = func(oldpath, newpath string) error { return wantErr }
sleepServerPIDRenameRetry = func() {}
err := replaceServerPIDFile("tmp.json", "dst.json")
if !errors.Is(err, wantErr) {
t.Fatalf("replaceServerPIDFile() error = %v, want %v", err, wantErr)
}
}