mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-08-10 13:36:53 +00:00
c951e5fa4b
Signed-off-by: Noooste <83548733+Noooste@users.noreply.github.com>
216 lines
8.1 KiB
Go
216 lines
8.1 KiB
Go
package mocks
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"Noooste/garage-ui/internal/models"
|
|
"Noooste/garage-ui/internal/services"
|
|
)
|
|
|
|
// The mocks are exercised across the handlers test suite, but Go's per-
|
|
// package coverage counts only statements executed from tests in THIS
|
|
// package. This test calls every mock method with no Fn configured, which
|
|
// covers the default "not configured" error path (and the record() helpers
|
|
// that build the call log).
|
|
|
|
func TestAdminMock_UnconfiguredMethodsReturnSentinel(t *testing.T) {
|
|
ctx := context.Background()
|
|
m := &AdminMock{}
|
|
|
|
type call struct {
|
|
name string
|
|
fn func() error
|
|
}
|
|
calls := []call{
|
|
{"ListKeys", func() error { _, e := m.ListKeys(ctx); return e }},
|
|
{"CreateKey", func() error { _, e := m.CreateKey(ctx, models.CreateKeyRequest{}); return e }},
|
|
{"GetKeyInfo", func() error { _, e := m.GetKeyInfo(ctx, "k", false); return e }},
|
|
{"UpdateKey", func() error { _, e := m.UpdateKey(ctx, "k", models.UpdateKeyRequest{}); return e }},
|
|
{"DeleteKey", func() error { return m.DeleteKey(ctx, "k") }},
|
|
{"ListBuckets", func() error { _, e := m.ListBuckets(ctx); return e }},
|
|
{"GetBucketInfo", func() error { _, e := m.GetBucketInfo(ctx, "b"); return e }},
|
|
{"GetBucketInfoByAlias", func() error { _, e := m.GetBucketInfoByAlias(ctx, "a"); return e }},
|
|
{"CreateBucket", func() error { _, e := m.CreateBucket(ctx, models.CreateBucketAdminRequest{}); return e }},
|
|
{"UpdateBucket", func() error { _, e := m.UpdateBucket(ctx, "b", models.UpdateBucketRequest{}); return e }},
|
|
{"DeleteBucket", func() error { return m.DeleteBucket(ctx, "b") }},
|
|
{"AllowBucketKey", func() error { _, e := m.AllowBucketKey(ctx, models.BucketKeyPermRequest{}); return e }},
|
|
{"DenyBucketKey", func() error { _, e := m.DenyBucketKey(ctx, models.BucketKeyPermRequest{}); return e }},
|
|
{"GetClusterHealth", func() error { _, e := m.GetClusterHealth(ctx); return e }},
|
|
{"GetClusterStatus", func() error { _, e := m.GetClusterStatus(ctx); return e }},
|
|
{"GetClusterStatistics", func() error { _, e := m.GetClusterStatistics(ctx); return e }},
|
|
{"GetNodeInfo", func() error { _, e := m.GetNodeInfo(ctx, "n"); return e }},
|
|
{"GetNodeStatistics", func() error { _, e := m.GetNodeStatistics(ctx, "n"); return e }},
|
|
{"HealthCheck", func() error { return m.HealthCheck(ctx) }},
|
|
{"GetMetrics", func() error { _, e := m.GetMetrics(ctx); return e }},
|
|
}
|
|
|
|
for _, c := range calls {
|
|
err := c.fn()
|
|
if err == nil {
|
|
t.Errorf("%s: expected error from unconfigured mock, got nil", c.name)
|
|
continue
|
|
}
|
|
if !strings.Contains(err.Error(), c.name) {
|
|
t.Errorf("%s: error %q should mention method name", c.name, err.Error())
|
|
}
|
|
}
|
|
if len(m.Calls) != len(calls) {
|
|
t.Errorf("Calls recorded = %d, want %d", len(m.Calls), len(calls))
|
|
}
|
|
}
|
|
|
|
func TestAdminMock_ConfiguredFnsAreInvoked(t *testing.T) {
|
|
ctx := context.Background()
|
|
m := &AdminMock{
|
|
ListKeysFn: func(ctx context.Context) ([]models.ListKeysResponseItem, error) {
|
|
return []models.ListKeysResponseItem{{ID: "k1"}}, nil
|
|
},
|
|
DeleteKeyFn: func(ctx context.Context, id string) error { return nil },
|
|
HealthCheckFn: func(ctx context.Context) error { return nil },
|
|
GetMetricsFn: func(ctx context.Context) (string, error) { return "metric 1", nil },
|
|
}
|
|
if got, err := m.ListKeys(ctx); err != nil || len(got) != 1 {
|
|
t.Errorf("ListKeys = (%v, %v), want one item", got, err)
|
|
}
|
|
if err := m.DeleteKey(ctx, "k"); err != nil {
|
|
t.Errorf("DeleteKey: %v", err)
|
|
}
|
|
if err := m.HealthCheck(ctx); err != nil {
|
|
t.Errorf("HealthCheck: %v", err)
|
|
}
|
|
if got, _ := m.GetMetrics(ctx); got != "metric 1" {
|
|
t.Errorf("GetMetrics = %q", got)
|
|
}
|
|
}
|
|
|
|
func TestS3Mock_UnconfiguredMethodsReturnSentinel(t *testing.T) {
|
|
ctx := context.Background()
|
|
m := &S3Mock{}
|
|
|
|
if _, err := m.ListObjects(ctx, "b", "", 0, ""); err == nil {
|
|
t.Error("ListObjects: want error")
|
|
}
|
|
if _, err := m.UploadObject(ctx, "b", "k", strings.NewReader(""), ""); err == nil {
|
|
t.Error("UploadObject: want error")
|
|
}
|
|
if _, err := m.CreateDirectoryMarker(ctx, "b", "k/"); err == nil {
|
|
t.Error("CreateDirectoryMarker: want error")
|
|
}
|
|
if _, _, err := m.GetObject(ctx, "b", "k"); err == nil {
|
|
t.Error("GetObject: want error")
|
|
}
|
|
if _, err := m.ObjectExists(ctx, "b", "k"); err == nil {
|
|
t.Error("ObjectExists: want error")
|
|
}
|
|
if err := m.DeleteObject(ctx, "b", "k"); err == nil {
|
|
t.Error("DeleteObject: want error")
|
|
}
|
|
if _, err := m.GetObjectMetadata(ctx, "b", "k"); err == nil {
|
|
t.Error("GetObjectMetadata: want error")
|
|
}
|
|
if _, err := m.GetPresignedURL(ctx, "b", "k", time.Minute); err == nil {
|
|
t.Error("GetPresignedURL: want error")
|
|
}
|
|
if err := m.DeleteMultipleObjects(ctx, "b", []string{"k"}); err == nil {
|
|
t.Error("DeleteMultipleObjects: want error")
|
|
}
|
|
// UploadMultipleObjects has no error channel; it must return a result slice
|
|
// with one failed entry per input file.
|
|
results := m.UploadMultipleObjects(ctx, "b", []struct {
|
|
Key string
|
|
Body io.Reader
|
|
ContentType string
|
|
}{
|
|
{Key: "a"}, {Key: "b"},
|
|
})
|
|
if len(results) != 2 {
|
|
t.Fatalf("len(results) = %d, want 2", len(results))
|
|
}
|
|
for _, r := range results {
|
|
if r.Success {
|
|
t.Errorf("result[%s] should not be successful with no Fn set", r.Key)
|
|
}
|
|
}
|
|
if len(m.Calls) < 10 {
|
|
t.Errorf("expected Calls to capture each invocation, got %d entries", len(m.Calls))
|
|
}
|
|
}
|
|
|
|
func TestS3Mock_ConfiguredFnsAreInvoked(t *testing.T) {
|
|
ctx := context.Background()
|
|
m := &S3Mock{
|
|
ListObjectsFn: func(_ context.Context, _, _ string, _ int, _ string) (*models.ObjectListResponse, error) {
|
|
return &models.ObjectListResponse{Count: 1}, nil
|
|
},
|
|
UploadObjectFn: func(_ context.Context, _, _ string, _ io.Reader, _ string) (*models.ObjectUploadResponse, error) {
|
|
return &models.ObjectUploadResponse{}, nil
|
|
},
|
|
CreateDirectoryMarkerFn: func(_ context.Context, _, _ string) (*models.ObjectUploadResponse, error) {
|
|
return &models.ObjectUploadResponse{}, nil
|
|
},
|
|
GetObjectFn: func(_ context.Context, _, _ string) (io.ReadCloser, *models.ObjectInfo, error) {
|
|
return io.NopCloser(strings.NewReader("x")), &models.ObjectInfo{}, nil
|
|
},
|
|
ObjectExistsFn: func(_ context.Context, _, _ string) (bool, error) { return true, nil },
|
|
DeleteObjectFn: func(_ context.Context, _, _ string) error { return nil },
|
|
GetObjectMetadataFn: func(_ context.Context, _, _ string) (*models.ObjectInfo, error) {
|
|
return &models.ObjectInfo{}, nil
|
|
},
|
|
GetPresignedURLFn: func(_ context.Context, _, _ string, _ time.Duration) (string, error) {
|
|
return "http://x", nil
|
|
},
|
|
DeleteMultipleObjectsFn: func(_ context.Context, _ string, _ []string) error { return nil },
|
|
UploadMultipleObjectsFn: func(_ context.Context, _ string, files []struct {
|
|
Key string
|
|
Body io.Reader
|
|
ContentType string
|
|
}) []services.UploadResult {
|
|
out := make([]services.UploadResult, len(files))
|
|
for i, f := range files {
|
|
out[i] = services.UploadResult{Key: f.Key, Success: true}
|
|
}
|
|
return out
|
|
},
|
|
}
|
|
|
|
if r, err := m.ListObjects(ctx, "b", "", 0, ""); err != nil || r.Count != 1 {
|
|
t.Errorf("ListObjects = (%+v, %v)", r, err)
|
|
}
|
|
if _, err := m.UploadObject(ctx, "b", "k", strings.NewReader(""), ""); err != nil {
|
|
t.Errorf("UploadObject: %v", err)
|
|
}
|
|
if _, err := m.CreateDirectoryMarker(ctx, "b", "k/"); err != nil {
|
|
t.Errorf("CreateDirectoryMarker: %v", err)
|
|
}
|
|
if _, _, err := m.GetObject(ctx, "b", "k"); err != nil {
|
|
t.Errorf("GetObject: %v", err)
|
|
}
|
|
if ok, err := m.ObjectExists(ctx, "b", "k"); err != nil || !ok {
|
|
t.Errorf("ObjectExists = (%v, %v)", ok, err)
|
|
}
|
|
if err := m.DeleteObject(ctx, "b", "k"); err != nil {
|
|
t.Errorf("DeleteObject: %v", err)
|
|
}
|
|
if _, err := m.GetObjectMetadata(ctx, "b", "k"); err != nil {
|
|
t.Errorf("GetObjectMetadata: %v", err)
|
|
}
|
|
if u, err := m.GetPresignedURL(ctx, "b", "k", time.Minute); err != nil || u == "" {
|
|
t.Errorf("GetPresignedURL = (%q, %v)", u, err)
|
|
}
|
|
if err := m.DeleteMultipleObjects(ctx, "b", []string{"k"}); err != nil {
|
|
t.Errorf("DeleteMultipleObjects: %v", err)
|
|
}
|
|
results := m.UploadMultipleObjects(ctx, "b", []struct {
|
|
Key string
|
|
Body io.Reader
|
|
ContentType string
|
|
}{{Key: "a"}})
|
|
if len(results) != 1 || !results[0].Success {
|
|
t.Errorf("UploadMultipleObjects results = %+v", results)
|
|
}
|
|
}
|