This centralizes filestat logic by making our own `Stat_t` similar to `syscall.Stat_t`. This exposes utilities in the platform package and adds a new function `FS.Stat` which avoids having to use `fs.File` to get the same info. Doing so at the FS abstraction allows us to optimize how it is implemented internally using portable means (e.g. `os.StatFile`) or OS-specific means where necessary, e.g. in windows. This also ensures `platform.OpenFile` returns syscall.Errno and centralizes error checking with a new `require.EqualErrno` test. Signed-off-by: Adrian Cole <adrian@tetrate.io>
84 lines
1.8 KiB
Go
84 lines
1.8 KiB
Go
package platform
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"github.com/tetratelabs/wazero/internal/testing/require"
|
|
)
|
|
|
|
func TestUnwrapOSError(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input error
|
|
expected syscall.Errno
|
|
}{
|
|
{
|
|
name: "LinkError ErrInvalid",
|
|
input: &os.LinkError{Err: fs.ErrInvalid},
|
|
expected: syscall.EINVAL,
|
|
},
|
|
{
|
|
name: "PathError ErrInvalid",
|
|
input: &os.PathError{Err: fs.ErrInvalid},
|
|
expected: syscall.EINVAL,
|
|
},
|
|
{
|
|
name: "SyscallError ErrInvalid",
|
|
input: &os.SyscallError{Err: fs.ErrInvalid},
|
|
expected: syscall.EINVAL,
|
|
},
|
|
{
|
|
name: "PathError ErrPermission",
|
|
input: &os.PathError{Err: os.ErrPermission},
|
|
expected: syscall.EPERM,
|
|
},
|
|
{
|
|
name: "PathError ErrExist",
|
|
input: &os.PathError{Err: os.ErrExist},
|
|
expected: syscall.EEXIST,
|
|
},
|
|
{
|
|
name: "PathError syscall.ErrnotExist",
|
|
input: &os.PathError{Err: os.ErrNotExist},
|
|
expected: syscall.ENOENT,
|
|
},
|
|
{
|
|
name: "PathError ErrClosed",
|
|
input: &os.PathError{Err: os.ErrClosed},
|
|
expected: syscall.EBADF,
|
|
},
|
|
{
|
|
name: "PathError unknown == syscall.EIO",
|
|
input: &os.PathError{Err: errors.New("ice cream")},
|
|
expected: syscall.EIO,
|
|
},
|
|
{
|
|
name: "unknown == syscall.EIO",
|
|
input: errors.New("ice cream"),
|
|
expected: syscall.EIO,
|
|
},
|
|
{
|
|
name: "very wrapped unknown == syscall.EIO",
|
|
input: fmt.Errorf("%w", fmt.Errorf("%w", fmt.Errorf("%w", errors.New("ice cream")))),
|
|
expected: syscall.EIO,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
errno := UnwrapOSError(tc.input)
|
|
require.EqualErrno(t, tc.expected, errno)
|
|
})
|
|
}
|
|
|
|
t.Run("nil", func(t *testing.T) {
|
|
require.Nil(t, UnwrapOSError(nil))
|
|
})
|
|
}
|