refactor(ax): align remaining AX surfaces

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-31 14:19:53 +00:00
parent ede0c8bb49
commit 15b6074e46
5 changed files with 193 additions and 193 deletions

View file

@ -338,14 +338,14 @@ func TestDataNode_SnapshotRestore_Good(t *testing.T) {
require.NoError(t, err)
assert.NotEmpty(t, snap)
m2, err := FromTar(snap)
restoredNode, err := FromTar(snap)
require.NoError(t, err)
got, err := m2.Read("a.txt")
got, err := restoredNode.Read("a.txt")
require.NoError(t, err)
assert.Equal(t, "alpha", got)
got, err = m2.Read("b/c.txt")
got, err = restoredNode.Read("b/c.txt")
require.NoError(t, err)
assert.Equal(t, "charlie", got)
}

View file

@ -130,7 +130,7 @@ type WalkOptions struct {
}
// Example: _ = nodeTree.Walk(".", func(_ string, _ fs.DirEntry, _ error) error { return nil }, node.WalkOptions{MaxDepth: 1, SkipErrors: true})
func (node *Node) Walk(root string, fn fs.WalkDirFunc, options WalkOptions) error {
func (node *Node) Walk(root string, walkFunc fs.WalkDirFunc, options WalkOptions) error {
if options.SkipErrors {
if _, err := node.Stat(root); err != nil {
return nil
@ -147,7 +147,7 @@ func (node *Node) Walk(root string, fn fs.WalkDirFunc, options WalkOptions) erro
}
}
walkResult := fn(entryPath, entry, err)
walkResult := walkFunc(entryPath, entry, err)
if walkResult == nil && options.MaxDepth > 0 && entry != nil && entry.IsDir() && entryPath != root {
relativePath := core.TrimPrefix(entryPath, root)

View file

@ -18,7 +18,7 @@ import (
"github.com/stretchr/testify/require"
)
type mockS3 struct {
type testS3Client struct {
mu sync.RWMutex
objects map[string][]byte
mtimes map[string]time.Time
@ -26,8 +26,8 @@ type mockS3 struct {
deleteObjectsErrs map[string]types.Error
}
func newMockS3() *mockS3 {
return &mockS3{
func newTestS3Client() *testS3Client {
return &testS3Client{
objects: make(map[string][]byte),
mtimes: make(map[string]time.Time),
deleteObjectErrors: make(map[string]error),
@ -35,16 +35,16 @@ func newMockS3() *mockS3 {
}
}
func (m *mockS3) GetObject(_ context.Context, params *awss3.GetObjectInput, _ ...func(*awss3.Options)) (*awss3.GetObjectOutput, error) {
m.mu.RLock()
defer m.mu.RUnlock()
func (client *testS3Client) GetObject(operationContext context.Context, params *awss3.GetObjectInput, optionFns ...func(*awss3.Options)) (*awss3.GetObjectOutput, error) {
client.mu.RLock()
defer client.mu.RUnlock()
key := aws.ToString(params.Key)
data, ok := m.objects[key]
data, ok := client.objects[key]
if !ok {
return nil, core.E("s3test.mockS3.GetObject", core.Sprintf("NoSuchKey: key %q not found", key), fs.ErrNotExist)
return nil, core.E("s3test.testS3Client.GetObject", core.Sprintf("NoSuchKey: key %q not found", key), fs.ErrNotExist)
}
mtime := m.mtimes[key]
mtime := client.mtimes[key]
return &awss3.GetObjectOutput{
Body: goio.NopCloser(bytes.NewReader(data)),
ContentLength: aws.Int64(int64(len(data))),
@ -52,69 +52,69 @@ func (m *mockS3) GetObject(_ context.Context, params *awss3.GetObjectInput, _ ..
}, nil
}
func (m *mockS3) PutObject(_ context.Context, params *awss3.PutObjectInput, _ ...func(*awss3.Options)) (*awss3.PutObjectOutput, error) {
m.mu.Lock()
defer m.mu.Unlock()
func (client *testS3Client) PutObject(operationContext context.Context, params *awss3.PutObjectInput, optionFns ...func(*awss3.Options)) (*awss3.PutObjectOutput, error) {
client.mu.Lock()
defer client.mu.Unlock()
key := aws.ToString(params.Key)
data, err := goio.ReadAll(params.Body)
if err != nil {
return nil, err
}
m.objects[key] = data
m.mtimes[key] = time.Now()
client.objects[key] = data
client.mtimes[key] = time.Now()
return &awss3.PutObjectOutput{}, nil
}
func (m *mockS3) DeleteObject(_ context.Context, params *awss3.DeleteObjectInput, _ ...func(*awss3.Options)) (*awss3.DeleteObjectOutput, error) {
m.mu.Lock()
defer m.mu.Unlock()
func (client *testS3Client) DeleteObject(operationContext context.Context, params *awss3.DeleteObjectInput, optionFns ...func(*awss3.Options)) (*awss3.DeleteObjectOutput, error) {
client.mu.Lock()
defer client.mu.Unlock()
key := aws.ToString(params.Key)
if err, ok := m.deleteObjectErrors[key]; ok {
if err, ok := client.deleteObjectErrors[key]; ok {
return nil, err
}
delete(m.objects, key)
delete(m.mtimes, key)
delete(client.objects, key)
delete(client.mtimes, key)
return &awss3.DeleteObjectOutput{}, nil
}
func (m *mockS3) DeleteObjects(_ context.Context, params *awss3.DeleteObjectsInput, _ ...func(*awss3.Options)) (*awss3.DeleteObjectsOutput, error) {
m.mu.Lock()
defer m.mu.Unlock()
func (client *testS3Client) DeleteObjects(operationContext context.Context, params *awss3.DeleteObjectsInput, optionFns ...func(*awss3.Options)) (*awss3.DeleteObjectsOutput, error) {
client.mu.Lock()
defer client.mu.Unlock()
var outErrs []types.Error
for _, obj := range params.Delete.Objects {
key := aws.ToString(obj.Key)
if errInfo, ok := m.deleteObjectsErrs[key]; ok {
if errInfo, ok := client.deleteObjectsErrs[key]; ok {
outErrs = append(outErrs, errInfo)
continue
}
delete(m.objects, key)
delete(m.mtimes, key)
delete(client.objects, key)
delete(client.mtimes, key)
}
return &awss3.DeleteObjectsOutput{Errors: outErrs}, nil
}
func (m *mockS3) HeadObject(_ context.Context, params *awss3.HeadObjectInput, _ ...func(*awss3.Options)) (*awss3.HeadObjectOutput, error) {
m.mu.RLock()
defer m.mu.RUnlock()
func (client *testS3Client) HeadObject(operationContext context.Context, params *awss3.HeadObjectInput, optionFns ...func(*awss3.Options)) (*awss3.HeadObjectOutput, error) {
client.mu.RLock()
defer client.mu.RUnlock()
key := aws.ToString(params.Key)
data, ok := m.objects[key]
data, ok := client.objects[key]
if !ok {
return nil, core.E("s3test.mockS3.HeadObject", core.Sprintf("NotFound: key %q not found", key), fs.ErrNotExist)
return nil, core.E("s3test.testS3Client.HeadObject", core.Sprintf("NotFound: key %q not found", key), fs.ErrNotExist)
}
mtime := m.mtimes[key]
mtime := client.mtimes[key]
return &awss3.HeadObjectOutput{
ContentLength: aws.Int64(int64(len(data))),
LastModified: &mtime,
}, nil
}
func (m *mockS3) ListObjectsV2(_ context.Context, params *awss3.ListObjectsV2Input, _ ...func(*awss3.Options)) (*awss3.ListObjectsV2Output, error) {
m.mu.RLock()
defer m.mu.RUnlock()
func (client *testS3Client) ListObjectsV2(operationContext context.Context, params *awss3.ListObjectsV2Input, optionFns ...func(*awss3.Options)) (*awss3.ListObjectsV2Output, error) {
client.mu.RLock()
defer client.mu.RUnlock()
prefix := aws.ToString(params.Prefix)
delimiter := aws.ToString(params.Delimiter)
@ -124,7 +124,7 @@ func (m *mockS3) ListObjectsV2(_ context.Context, params *awss3.ListObjectsV2Inp
}
var allKeys []string
for k := range m.objects {
for k := range client.objects {
if core.HasPrefix(k, prefix) {
allKeys = append(allKeys, k)
}
@ -150,8 +150,8 @@ func (m *mockS3) ListObjectsV2(_ context.Context, params *awss3.ListObjectsV2Inp
break
}
data := m.objects[k]
mtime := m.mtimes[k]
data := client.objects[k]
mtime := client.mtimes[k]
contents = append(contents, types.Object{
Key: aws.String(k),
Size: aws.Int64(int64(len(data))),
@ -176,47 +176,47 @@ func (m *mockS3) ListObjectsV2(_ context.Context, params *awss3.ListObjectsV2Inp
}, nil
}
func (m *mockS3) CopyObject(_ context.Context, params *awss3.CopyObjectInput, _ ...func(*awss3.Options)) (*awss3.CopyObjectOutput, error) {
m.mu.Lock()
defer m.mu.Unlock()
func (client *testS3Client) CopyObject(operationContext context.Context, params *awss3.CopyObjectInput, optionFns ...func(*awss3.Options)) (*awss3.CopyObjectOutput, error) {
client.mu.Lock()
defer client.mu.Unlock()
source := aws.ToString(params.CopySource)
parts := core.SplitN(source, "/", 2)
if len(parts) != 2 {
return nil, core.E("s3test.mockS3.CopyObject", core.Sprintf("invalid CopySource: %s", source), fs.ErrInvalid)
return nil, core.E("s3test.testS3Client.CopyObject", core.Sprintf("invalid CopySource: %s", source), fs.ErrInvalid)
}
srcKey := parts[1]
data, ok := m.objects[srcKey]
data, ok := client.objects[srcKey]
if !ok {
return nil, core.E("s3test.mockS3.CopyObject", core.Sprintf("NoSuchKey: source key %q not found", srcKey), fs.ErrNotExist)
return nil, core.E("s3test.testS3Client.CopyObject", core.Sprintf("NoSuchKey: source key %q not found", srcKey), fs.ErrNotExist)
}
destKey := aws.ToString(params.Key)
m.objects[destKey] = append([]byte{}, data...)
m.mtimes[destKey] = time.Now()
client.objects[destKey] = append([]byte{}, data...)
client.mtimes[destKey] = time.Now()
return &awss3.CopyObjectOutput{}, nil
}
func newS3Medium(t *testing.T) (*Medium, *mockS3) {
func newS3Medium(t *testing.T) (*Medium, *testS3Client) {
t.Helper()
mock := newMockS3()
m, err := New(Options{Bucket: "test-bucket", Client: mock})
testS3Client := newTestS3Client()
s3Medium, err := New(Options{Bucket: "test-bucket", Client: testS3Client})
require.NoError(t, err)
return m, mock
return s3Medium, testS3Client
}
func TestS3_New_Good(t *testing.T) {
mock := newMockS3()
m, err := New(Options{Bucket: "my-bucket", Client: mock})
testS3Client := newTestS3Client()
s3Medium, err := New(Options{Bucket: "my-bucket", Client: testS3Client})
require.NoError(t, err)
assert.Equal(t, "my-bucket", m.bucket)
assert.Equal(t, "", m.prefix)
assert.Equal(t, "my-bucket", s3Medium.bucket)
assert.Equal(t, "", s3Medium.prefix)
}
func TestS3_New_NoBucket_Bad(t *testing.T) {
_, err := New(Options{Client: newMockS3()})
_, err := New(Options{Client: newTestS3Client()})
assert.Error(t, err)
assert.Contains(t, err.Error(), "bucket name is required")
}
@ -228,56 +228,56 @@ func TestS3_New_NoClient_Bad(t *testing.T) {
}
func TestS3_New_Options_Good(t *testing.T) {
mock := newMockS3()
m, err := New(Options{Bucket: "bucket", Client: mock, Prefix: "data/"})
testS3Client := newTestS3Client()
s3Medium, err := New(Options{Bucket: "bucket", Client: testS3Client, Prefix: "data/"})
require.NoError(t, err)
assert.Equal(t, "data/", m.prefix)
assert.Equal(t, "data/", s3Medium.prefix)
m2, err := New(Options{Bucket: "bucket", Client: mock, Prefix: "data"})
prefixedS3Medium, err := New(Options{Bucket: "bucket", Client: testS3Client, Prefix: "data"})
require.NoError(t, err)
assert.Equal(t, "data/", m2.prefix)
assert.Equal(t, "data/", prefixedS3Medium.prefix)
}
func TestS3_ReadWrite_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
err := m.Write("hello.txt", "world")
err := s3Medium.Write("hello.txt", "world")
require.NoError(t, err)
content, err := m.Read("hello.txt")
content, err := s3Medium.Read("hello.txt")
require.NoError(t, err)
assert.Equal(t, "world", content)
}
func TestS3_ReadWrite_NotFound_Bad(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
_, err := m.Read("nonexistent.txt")
_, err := s3Medium.Read("nonexistent.txt")
assert.Error(t, err)
}
func TestS3_ReadWrite_EmptyPath_Bad(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
_, err := m.Read("")
_, err := s3Medium.Read("")
assert.Error(t, err)
err = m.Write("", "content")
err = s3Medium.Write("", "content")
assert.Error(t, err)
}
func TestS3_ReadWrite_Prefix_Good(t *testing.T) {
mock := newMockS3()
m, err := New(Options{Bucket: "bucket", Client: mock, Prefix: "pfx"})
testS3Client := newTestS3Client()
s3Medium, err := New(Options{Bucket: "bucket", Client: testS3Client, Prefix: "pfx"})
require.NoError(t, err)
err = m.Write("file.txt", "data")
err = s3Medium.Write("file.txt", "data")
require.NoError(t, err)
_, ok := mock.objects["pfx/file.txt"]
_, ok := testS3Client.objects["pfx/file.txt"]
assert.True(t, ok, "object should be stored with prefix")
content, err := m.Read("file.txt")
content, err := s3Medium.Read("file.txt")
require.NoError(t, err)
assert.Equal(t, "data", content)
}
@ -289,123 +289,123 @@ func TestS3_EnsureDir_Good(t *testing.T) {
}
func TestS3_IsFile_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
err := m.Write("file.txt", "content")
err := s3Medium.Write("file.txt", "content")
require.NoError(t, err)
assert.True(t, m.IsFile("file.txt"))
assert.False(t, m.IsFile("nonexistent.txt"))
assert.False(t, m.IsFile(""))
assert.True(t, s3Medium.IsFile("file.txt"))
assert.False(t, s3Medium.IsFile("nonexistent.txt"))
assert.False(t, s3Medium.IsFile(""))
}
func TestS3_Delete_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
err := m.Write("to-delete.txt", "content")
err := s3Medium.Write("to-delete.txt", "content")
require.NoError(t, err)
assert.True(t, m.Exists("to-delete.txt"))
assert.True(t, s3Medium.Exists("to-delete.txt"))
err = m.Delete("to-delete.txt")
err = s3Medium.Delete("to-delete.txt")
require.NoError(t, err)
assert.False(t, m.IsFile("to-delete.txt"))
assert.False(t, s3Medium.IsFile("to-delete.txt"))
}
func TestS3_Delete_EmptyPath_Bad(t *testing.T) {
m, _ := newS3Medium(t)
err := m.Delete("")
s3Medium, _ := newS3Medium(t)
err := s3Medium.Delete("")
assert.Error(t, err)
}
func TestS3_DeleteAll_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("dir/file1.txt", "a"))
require.NoError(t, m.Write("dir/sub/file2.txt", "b"))
require.NoError(t, m.Write("other.txt", "c"))
require.NoError(t, s3Medium.Write("dir/file1.txt", "a"))
require.NoError(t, s3Medium.Write("dir/sub/file2.txt", "b"))
require.NoError(t, s3Medium.Write("other.txt", "c"))
err := m.DeleteAll("dir")
err := s3Medium.DeleteAll("dir")
require.NoError(t, err)
assert.False(t, m.IsFile("dir/file1.txt"))
assert.False(t, m.IsFile("dir/sub/file2.txt"))
assert.True(t, m.IsFile("other.txt"))
assert.False(t, s3Medium.IsFile("dir/file1.txt"))
assert.False(t, s3Medium.IsFile("dir/sub/file2.txt"))
assert.True(t, s3Medium.IsFile("other.txt"))
}
func TestS3_DeleteAll_EmptyPath_Bad(t *testing.T) {
m, _ := newS3Medium(t)
err := m.DeleteAll("")
s3Medium, _ := newS3Medium(t)
err := s3Medium.DeleteAll("")
assert.Error(t, err)
}
func TestS3_DeleteAll_DeleteObjectError_Bad(t *testing.T) {
m, mock := newS3Medium(t)
mock.deleteObjectErrors["dir"] = core.NewError("boom")
s3Medium, testS3Client := newS3Medium(t)
testS3Client.deleteObjectErrors["dir"] = core.NewError("boom")
err := m.DeleteAll("dir")
err := s3Medium.DeleteAll("dir")
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to delete object: dir")
}
func TestS3_DeleteAll_PartialDelete_Bad(t *testing.T) {
m, mock := newS3Medium(t)
s3Medium, testS3Client := newS3Medium(t)
require.NoError(t, m.Write("dir/file1.txt", "a"))
require.NoError(t, m.Write("dir/file2.txt", "b"))
mock.deleteObjectsErrs["dir/file2.txt"] = types.Error{
require.NoError(t, s3Medium.Write("dir/file1.txt", "a"))
require.NoError(t, s3Medium.Write("dir/file2.txt", "b"))
testS3Client.deleteObjectsErrs["dir/file2.txt"] = types.Error{
Key: aws.String("dir/file2.txt"),
Code: aws.String("AccessDenied"),
Message: aws.String("blocked"),
}
err := m.DeleteAll("dir")
err := s3Medium.DeleteAll("dir")
require.Error(t, err)
assert.Contains(t, err.Error(), "partial delete failed")
assert.Contains(t, err.Error(), "dir/file2.txt")
assert.True(t, m.IsFile("dir/file2.txt"))
assert.False(t, m.IsFile("dir/file1.txt"))
assert.True(t, s3Medium.IsFile("dir/file2.txt"))
assert.False(t, s3Medium.IsFile("dir/file1.txt"))
}
func TestS3_Rename_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("old.txt", "content"))
assert.True(t, m.IsFile("old.txt"))
require.NoError(t, s3Medium.Write("old.txt", "content"))
assert.True(t, s3Medium.IsFile("old.txt"))
err := m.Rename("old.txt", "new.txt")
err := s3Medium.Rename("old.txt", "new.txt")
require.NoError(t, err)
assert.False(t, m.IsFile("old.txt"))
assert.True(t, m.IsFile("new.txt"))
assert.False(t, s3Medium.IsFile("old.txt"))
assert.True(t, s3Medium.IsFile("new.txt"))
content, err := m.Read("new.txt")
content, err := s3Medium.Read("new.txt")
require.NoError(t, err)
assert.Equal(t, "content", content)
}
func TestS3_Rename_EmptyPath_Bad(t *testing.T) {
m, _ := newS3Medium(t)
err := m.Rename("", "new.txt")
s3Medium, _ := newS3Medium(t)
err := s3Medium.Rename("", "new.txt")
assert.Error(t, err)
err = m.Rename("old.txt", "")
err = s3Medium.Rename("old.txt", "")
assert.Error(t, err)
}
func TestS3_Rename_SourceNotFound_Bad(t *testing.T) {
m, _ := newS3Medium(t)
err := m.Rename("nonexistent.txt", "new.txt")
s3Medium, _ := newS3Medium(t)
err := s3Medium.Rename("nonexistent.txt", "new.txt")
assert.Error(t, err)
}
func TestS3_List_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("dir/file1.txt", "a"))
require.NoError(t, m.Write("dir/file2.txt", "b"))
require.NoError(t, m.Write("dir/sub/file3.txt", "c"))
require.NoError(t, s3Medium.Write("dir/file1.txt", "a"))
require.NoError(t, s3Medium.Write("dir/file2.txt", "b"))
require.NoError(t, s3Medium.Write("dir/sub/file3.txt", "c"))
entries, err := m.List("dir")
entries, err := s3Medium.List("dir")
require.NoError(t, err)
names := make(map[string]bool)
@ -429,12 +429,12 @@ func TestS3_List_Good(t *testing.T) {
}
func TestS3_List_Root_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("root.txt", "content"))
require.NoError(t, m.Write("dir/nested.txt", "nested"))
require.NoError(t, s3Medium.Write("root.txt", "content"))
require.NoError(t, s3Medium.Write("dir/nested.txt", "nested"))
entries, err := m.List("")
entries, err := s3Medium.List("")
require.NoError(t, err)
names := make(map[string]bool)
@ -447,11 +447,11 @@ func TestS3_List_Root_Good(t *testing.T) {
}
func TestS3_Stat_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("file.txt", "hello world"))
require.NoError(t, s3Medium.Write("file.txt", "hello world"))
info, err := m.Stat("file.txt")
info, err := s3Medium.Stat("file.txt")
require.NoError(t, err)
assert.Equal(t, "file.txt", info.Name())
assert.Equal(t, int64(11), info.Size())
@ -459,24 +459,24 @@ func TestS3_Stat_Good(t *testing.T) {
}
func TestS3_Stat_NotFound_Bad(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
_, err := m.Stat("nonexistent.txt")
_, err := s3Medium.Stat("nonexistent.txt")
assert.Error(t, err)
}
func TestS3_Stat_EmptyPath_Bad(t *testing.T) {
m, _ := newS3Medium(t)
_, err := m.Stat("")
s3Medium, _ := newS3Medium(t)
_, err := s3Medium.Stat("")
assert.Error(t, err)
}
func TestS3_Open_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("file.txt", "open me"))
require.NoError(t, s3Medium.Write("file.txt", "open me"))
f, err := m.Open("file.txt")
f, err := s3Medium.Open("file.txt")
require.NoError(t, err)
defer f.Close()
@ -490,16 +490,16 @@ func TestS3_Open_Good(t *testing.T) {
}
func TestS3_Open_NotFound_Bad(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
_, err := m.Open("nonexistent.txt")
_, err := s3Medium.Open("nonexistent.txt")
assert.Error(t, err)
}
func TestS3_Create_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
w, err := m.Create("new.txt")
w, err := s3Medium.Create("new.txt")
require.NoError(t, err)
n, err := w.Write([]byte("created"))
@ -509,17 +509,17 @@ func TestS3_Create_Good(t *testing.T) {
err = w.Close()
require.NoError(t, err)
content, err := m.Read("new.txt")
content, err := s3Medium.Read("new.txt")
require.NoError(t, err)
assert.Equal(t, "created", content)
}
func TestS3_Append_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("append.txt", "hello"))
require.NoError(t, s3Medium.Write("append.txt", "hello"))
w, err := m.Append("append.txt")
w, err := s3Medium.Append("append.txt")
require.NoError(t, err)
_, err = w.Write([]byte(" world"))
@ -527,15 +527,15 @@ func TestS3_Append_Good(t *testing.T) {
err = w.Close()
require.NoError(t, err)
content, err := m.Read("append.txt")
content, err := s3Medium.Read("append.txt")
require.NoError(t, err)
assert.Equal(t, "hello world", content)
}
func TestS3_Append_NewFile_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
w, err := m.Append("new.txt")
w, err := s3Medium.Append("new.txt")
require.NoError(t, err)
_, err = w.Write([]byte("fresh"))
@ -543,17 +543,17 @@ func TestS3_Append_NewFile_Good(t *testing.T) {
err = w.Close()
require.NoError(t, err)
content, err := m.Read("new.txt")
content, err := s3Medium.Read("new.txt")
require.NoError(t, err)
assert.Equal(t, "fresh", content)
}
func TestS3_ReadStream_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("stream.txt", "streaming content"))
require.NoError(t, s3Medium.Write("stream.txt", "streaming content"))
reader, err := m.ReadStream("stream.txt")
reader, err := s3Medium.ReadStream("stream.txt")
require.NoError(t, err)
defer reader.Close()
@ -563,15 +563,15 @@ func TestS3_ReadStream_Good(t *testing.T) {
}
func TestS3_ReadStream_NotFound_Bad(t *testing.T) {
m, _ := newS3Medium(t)
_, err := m.ReadStream("nonexistent.txt")
s3Medium, _ := newS3Medium(t)
_, err := s3Medium.ReadStream("nonexistent.txt")
assert.Error(t, err)
}
func TestS3_WriteStream_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
writer, err := m.WriteStream("output.txt")
writer, err := s3Medium.WriteStream("output.txt")
require.NoError(t, err)
_, err = goio.Copy(writer, core.NewReader("piped data"))
@ -579,57 +579,57 @@ func TestS3_WriteStream_Good(t *testing.T) {
err = writer.Close()
require.NoError(t, err)
content, err := m.Read("output.txt")
content, err := s3Medium.Read("output.txt")
require.NoError(t, err)
assert.Equal(t, "piped data", content)
}
func TestS3_Exists_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
assert.False(t, m.Exists("nonexistent.txt"))
assert.False(t, s3Medium.Exists("nonexistent.txt"))
require.NoError(t, m.Write("file.txt", "content"))
assert.True(t, m.Exists("file.txt"))
require.NoError(t, s3Medium.Write("file.txt", "content"))
assert.True(t, s3Medium.Exists("file.txt"))
}
func TestS3_Exists_DirectoryPrefix_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("dir/file.txt", "content"))
assert.True(t, m.Exists("dir"))
require.NoError(t, s3Medium.Write("dir/file.txt", "content"))
assert.True(t, s3Medium.Exists("dir"))
}
func TestS3_IsDir_Good(t *testing.T) {
m, _ := newS3Medium(t)
s3Medium, _ := newS3Medium(t)
require.NoError(t, m.Write("dir/file.txt", "content"))
require.NoError(t, s3Medium.Write("dir/file.txt", "content"))
assert.True(t, m.IsDir("dir"))
assert.False(t, m.IsDir("dir/file.txt"))
assert.False(t, m.IsDir("nonexistent"))
assert.False(t, m.IsDir(""))
assert.True(t, s3Medium.IsDir("dir"))
assert.False(t, s3Medium.IsDir("dir/file.txt"))
assert.False(t, s3Medium.IsDir("nonexistent"))
assert.False(t, s3Medium.IsDir(""))
}
func TestS3_ObjectKey_Good(t *testing.T) {
mock := newMockS3()
testS3Client := newTestS3Client()
m, _ := New(Options{Bucket: "bucket", Client: mock})
assert.Equal(t, "file.txt", m.objectKey("file.txt"))
assert.Equal(t, "dir/file.txt", m.objectKey("dir/file.txt"))
assert.Equal(t, "", m.objectKey(""))
assert.Equal(t, "file.txt", m.objectKey("/file.txt"))
assert.Equal(t, "file.txt", m.objectKey("../file.txt"))
s3Medium, _ := New(Options{Bucket: "bucket", Client: testS3Client})
assert.Equal(t, "file.txt", s3Medium.objectKey("file.txt"))
assert.Equal(t, "dir/file.txt", s3Medium.objectKey("dir/file.txt"))
assert.Equal(t, "", s3Medium.objectKey(""))
assert.Equal(t, "file.txt", s3Medium.objectKey("/file.txt"))
assert.Equal(t, "file.txt", s3Medium.objectKey("../file.txt"))
m2, _ := New(Options{Bucket: "bucket", Client: mock, Prefix: "pfx"})
assert.Equal(t, "pfx/file.txt", m2.objectKey("file.txt"))
assert.Equal(t, "pfx/dir/file.txt", m2.objectKey("dir/file.txt"))
assert.Equal(t, "pfx/", m2.objectKey(""))
prefixedS3Medium, _ := New(Options{Bucket: "bucket", Client: testS3Client, Prefix: "pfx"})
assert.Equal(t, "pfx/file.txt", prefixedS3Medium.objectKey("file.txt"))
assert.Equal(t, "pfx/dir/file.txt", prefixedS3Medium.objectKey("dir/file.txt"))
assert.Equal(t, "pfx/", prefixedS3Medium.objectKey(""))
}
func TestS3_InterfaceCompliance_Good(t *testing.T) {
mock := newMockS3()
m, err := New(Options{Bucket: "bucket", Client: mock})
testS3Client := newTestS3Client()
s3Medium, err := New(Options{Bucket: "bucket", Client: testS3Client})
require.NoError(t, err)
var _ interface {
@ -649,5 +649,5 @@ func TestS3_InterfaceCompliance_Good(t *testing.T) {
WriteStream(string) (goio.WriteCloser, error)
Exists(string) bool
IsDir(string) bool
} = m
} = s3Medium
}

View file

@ -222,7 +222,7 @@ func (service *Service) HandleWorkspaceCommand(command WorkspaceCommand) core.Re
}
// Example: result := service.HandleWorkspaceMessage(core.New(), WorkspaceCommand{Action: WorkspaceSwitchAction, WorkspaceID: "f3f0d7"})
func (service *Service) HandleWorkspaceMessage(_ *core.Core, message core.Message) core.Result {
func (service *Service) HandleWorkspaceMessage(coreInstance *core.Core, message core.Message) core.Result {
switch command := message.(type) {
case WorkspaceCommand:
return service.HandleWorkspaceCommand(command)

View file

@ -10,12 +10,12 @@ import (
"github.com/stretchr/testify/require"
)
type stubKeyPairProvider struct {
type testKeyPairProvider struct {
privateKey string
err error
}
func (provider stubKeyPairProvider) CreateKeyPair(_, _ string) (string, error) {
func (provider testKeyPairProvider) CreateKeyPair(identifier, passphrase string) (string, error) {
if provider.err != nil {
return "", provider.err
}
@ -28,7 +28,7 @@ func newWorkspaceService(t *testing.T) (*Service, string) {
tempHome := t.TempDir()
t.Setenv("HOME", tempHome)
service, err := New(Options{KeyPairProvider: stubKeyPairProvider{privateKey: "private-key"}})
service, err := New(Options{KeyPairProvider: testKeyPairProvider{privateKey: "private-key"}})
require.NoError(t, err)
return service, tempHome
}
@ -43,7 +43,7 @@ func TestService_New_CustomRootPathAndMedium_Good(t *testing.T) {
rootPath := core.Path(t.TempDir(), "custom", "workspaces")
service, err := New(Options{
KeyPairProvider: stubKeyPairProvider{privateKey: "private-key"},
KeyPairProvider: testKeyPairProvider{privateKey: "private-key"},
RootPath: rootPath,
Medium: medium,
})