Files
2026-07-13 13:00:08 +08:00

76 lines
2.2 KiB
Go

package main
import (
"errors"
"os"
"runtime"
"strings"
"syscall"
"testing"
)
// Platform errnos for the blocked-file classes. Windows values follow the
// isRenameCrossDeviceOrBusy convention of naming the raw code inline.
func blockedFileErrnos(t *testing.T) (inUse, accessDenied, diskFull syscall.Errno) {
t.Helper()
if runtime.GOOS == "windows" {
return 32, 5, 112 // ERROR_SHARING_VIOLATION, ERROR_ACCESS_DENIED, ERROR_DISK_FULL
}
return syscall.EBUSY, syscall.EACCES, syscall.ENOSPC
}
func TestFriendlySessionFileErrorMapsBlockedFileErrors(t *testing.T) {
inUse, accessDenied, diskFull := blockedFileErrnos(t)
secret := "/very/secret/session.jsonl"
cases := []struct {
name string
err error
want error
}{
{
name: "rename sharing violation",
err: &os.LinkError{Op: "rename", Old: secret, New: secret + ".trash", Err: inUse},
want: errSessionFileLocked,
},
{
name: "remove access denied",
err: &os.PathError{Op: "remove", Path: secret, Err: accessDenied},
want: errSessionFileAccessDenied,
},
{
name: "write disk full",
err: &os.PathError{Op: "write", Path: secret, Err: diskFull},
want: errSessionDiskFull,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := friendlySessionFileError(tc.err)
if got != tc.want {
t.Fatalf("friendlySessionFileError() = %v, want %v", got, tc.want)
}
if strings.Contains(got.Error(), secret) {
t.Fatalf("sanitized error leaks the path: %v", got)
}
})
}
}
func TestFriendlySessionFileErrorPassesThroughOtherErrors(t *testing.T) {
if err := friendlySessionFileError(nil); err != nil {
t.Fatalf("nil should stay nil, got %v", err)
}
plain := errors.New("plain failure")
if got := friendlySessionFileError(plain); got != plain {
t.Fatalf("plain error rewritten to %v", got)
}
if got := friendlySessionFileError(errSessionBusyElsewhere); got != errSessionBusyElsewhere {
t.Fatalf("sanitized busy error rewritten to %v", got)
}
notExist := &os.PathError{Op: "lstat", Path: "gone.jsonl", Err: syscall.ENOENT}
if got := friendlySessionFileError(notExist); got != error(notExist) {
t.Fatalf("not-exist error rewritten to %v", got)
}
}