Skip to content

Commit

Permalink
add validations and tests to cache
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Chacin <[email protected]>
  • Loading branch information
pablochacin committed Jun 17, 2024
1 parent f9be6b2 commit afdc6de
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 22 deletions.
9 changes: 9 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io"
"os"
"path/filepath"
"strings"
)

var (
Expand Down Expand Up @@ -59,6 +60,14 @@ func NewFileCache(path string) (Cache, error) {

// Store stores the object and returns the metadata
func (f *fileCache) Store(_ context.Context, id string, content io.Reader) (Object, error) {
if id == "" {
return Object{}, fmt.Errorf("%w id cannot be empty", ErrCreatingObject)
}

if strings.Contains(id, "/") {
return Object{}, fmt.Errorf("%w id cannot contain '/'", ErrCreatingObject)
}

objectDir := filepath.Join(f.path, id)
// TODO: check permissions
err := os.MkdirAll(objectDir, 0o750)
Expand Down
111 changes: 89 additions & 22 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,102 @@ import (
"bytes"
"context"
"errors"
"fmt"
"net/url"
"os"
"testing"
)

func TestCreateObject(t *testing.T) {
type object struct {
id string
content []byte
}

func setupCache(path string, preload []object) (Cache, error) {
cache, err := NewFileCache(path)
if err != nil {
return nil, fmt.Errorf("test setup %w", err)
}

for _, o := range preload {
_, err = cache.Store(context.TODO(), o.id, bytes.NewBuffer(o.content))
if err != nil {
return nil, fmt.Errorf("test setup %w", err)
}
}

return cache, nil
}

func TestStoreObject(t *testing.T) {
t.Parallel()

testCases := []struct {
title string
content []byte
preload []object
id string
content []byte
expectErr error
}{
{
title: "store object",
id: "object",
content: []byte("content"),
},
{
title: "store existing object",
preload: []object{
{
id: "object",
content: []byte("content"),
},
},
id: "object",
content: []byte("new content"),
},
{
title: "store empty object",
id: "empty",
content: nil,
},
{
title: "store empty id",
id: "",
content: []byte("content"),
expectErr: ErrCreatingObject,
},
{
title: "store invalid id (dot slash)",
id: "./invalid",
content: []byte("content"),
expectErr: ErrCreatingObject,
},
{
title: "store invalid id (trailing slash)",
id: "invalid/",
content: []byte("content"),
expectErr: ErrCreatingObject,
},
}

for _, tc := range testCases {
t.Run(tc.title, func(t *testing.T) {
t.Parallel()

cache, err := NewFileCache(t.TempDir())
cache, err := setupCache(t.TempDir(), tc.preload)
if err != nil {
t.Fatalf("test setup %v", err)
t.Fatalf("test setup: %v", err)
}

obj, err := cache.Store(context.TODO(), "object", bytes.NewBuffer(tc.content))
obj, err := cache.Store(context.TODO(), tc.id, bytes.NewBuffer(tc.content))
if !errors.Is(err, tc.expectErr) {
t.Fatalf("expected %v got %v", tc.expectErr, err)
}

// if expected error, don't validate object
if tc.expectErr != nil {
return
}

fileURL, err := url.Parse(obj.URL)
if err != nil {
t.Fatalf("invalid url %v", err)
Expand All @@ -64,36 +122,45 @@ func TestGetObjectCache(t *testing.T) {

testCases := []struct {
title string
preload []object
id string
expected []byte
expectErr error
}{
{
title: "retrieve existing",
title: "retrieve existing object",
preload: []object{
{
id: "object",
content: []byte("content"),
},
},
id: "object",
expected: []byte("content"),
expectErr: nil,
},
{
title: "retrieve non existing object",
id: "object2",
title: "retrieve non existing object",
preload: []object{
{
id: "object",
content: []byte("content"),
},
},
id: "another object",
expectErr: ErrObjectNotFound,
},
}

cache, err := NewFileCache(t.TempDir())
if err != nil {
t.Fatalf("test setup %v", err)
}

content := []byte("content")
_, err = cache.Store(context.TODO(), "object", bytes.NewBuffer(content))
if err != nil {
t.Fatalf("test setup %v", err)
}

for _, tc := range testCases {
t.Run(tc.title, func(t *testing.T) {
t.Parallel()

cache, err := setupCache(t.TempDir(), tc.preload)
if err != nil {
t.Fatalf("test setup: %v", err)
}

obj, err := cache.Get(context.TODO(), tc.id)
if !errors.Is(err, tc.expectErr) {
t.Fatalf("expected %v got %v", tc.expectErr, err)
Expand All @@ -114,8 +181,8 @@ func TestGetObjectCache(t *testing.T) {
t.Fatalf("reading object url %v", err)
}

if !bytes.Equal(data, content) {
t.Fatalf("expected %v got %v", data, content)
if !bytes.Equal(data, tc.expected) {
t.Fatalf("expected %v got %v", tc.expected, data)
}
})
}
Expand Down

0 comments on commit afdc6de

Please sign in to comment.