Skip to content

Commit

Permalink
fix(fs): Cache data in stdinfs
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Henderson <[email protected]>
  • Loading branch information
hairyhenderson committed Dec 16, 2024
1 parent a69bb64 commit a0380aa
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 4 deletions.
38 changes: 34 additions & 4 deletions internal/datafs/stdinfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ func NewStdinFS(_ *url.URL) (fs.FS, error) {
}

type stdinFS struct {
ctx context.Context
ctx context.Context
data []byte
}

//nolint:gochecknoglobals
Expand Down Expand Up @@ -46,9 +47,15 @@ func (f *stdinFS) Open(name string) (fs.File, error) {
}
}

stdin := StdinFromContext(f.ctx)
if err := f.readData(); err != nil {
return nil, &fs.PathError{
Op: "open",
Path: name,
Err: err,
}
}

return &stdinFile{name: name, body: stdin}, nil
return &stdinFile{name: name, body: bytes.NewReader(f.data)}, nil
}

func (f *stdinFS) ReadFile(name string) ([]byte, error) {
Expand All @@ -60,9 +67,32 @@ func (f *stdinFS) ReadFile(name string) ([]byte, error) {
}
}

if err := f.readData(); err != nil {
return nil, &fs.PathError{
Op: "readFile",
Path: name,
Err: err,
}
}

return f.data, nil
}

func (f *stdinFS) readData() error {
if f.data != nil {
return nil
}

stdin := StdinFromContext(f.ctx)

return io.ReadAll(stdin)
b, err := io.ReadAll(stdin)
if err != nil {
return err
}

f.data = b

return nil
}

type stdinFile struct {
Expand Down
51 changes: 51 additions & 0 deletions internal/datafs/stdinfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,57 @@ func TestStdinFS(t *testing.T) {
_, err = f.Read(p)
require.Error(t, err)
require.ErrorIs(t, err, io.EOF)

t.Run("open/read multiple times", func(t *testing.T) {
ctx := ContextWithStdin(context.Background(), bytes.NewReader(content))
fsys = fsimpl.WithContextFS(ctx, fsys)

for i := 0; i < 3; i++ {
f, err := fsys.Open("foo")
require.NoError(t, err)

b, err := io.ReadAll(f)
require.NoError(t, err)
require.Equal(t, content, b, "read %d failed", i)
}
})

t.Run("readFile multiple times", func(t *testing.T) {
ctx := ContextWithStdin(context.Background(), bytes.NewReader(content))
fsys = fsimpl.WithContextFS(ctx, fsys)

for i := 0; i < 3; i++ {
b, err := fs.ReadFile(fsys, "foo")
require.NoError(t, err)
require.Equal(t, content, b, "read %d failed", i)
}
})

t.Run("open errors", func(t *testing.T) {
ctx := ContextWithStdin(context.Background(), &errorReader{err: fs.ErrPermission})

fsys, err := NewStdinFS(u)
require.NoError(t, err)
assert.IsType(t, &stdinFS{}, fsys)

fsys = fsimpl.WithContextFS(ctx, fsys)

_, err = fsys.Open("foo")
require.ErrorIs(t, err, fs.ErrPermission)
})

t.Run("readFile errors", func(t *testing.T) {
ctx := ContextWithStdin(context.Background(), &errorReader{err: fs.ErrPermission})

fsys, err := NewStdinFS(u)
require.NoError(t, err)
assert.IsType(t, &stdinFS{}, fsys)

fsys = fsimpl.WithContextFS(ctx, fsys)

_, err = fs.ReadFile(fsys, "foo")
require.ErrorIs(t, err, fs.ErrPermission)
})
}

type errorReader struct {
Expand Down

0 comments on commit a0380aa

Please sign in to comment.