package s3 import ( "bytes" "context" "crypto/md5" "fmt" "io" "io/ioutil" "time" "git.kapelle.org/niklas/s3browser/internal/types" ) type mockS3 struct { buckets []string objects map[types.ID]mockObject } type mockObject struct { content []byte contentType string lastMod time.Time } type mockObjectReader struct { *bytes.Reader } func (r mockObjectReader) Close() error { // NOOP return nil } func NewMockS3(buckets []string) (S3Service, error) { return &mockS3{ buckets: buckets, objects: map[types.ID]mockObject{}, }, nil } func (m *mockS3) ListBuckets(ctx context.Context) ([]Bucket, error) { var rtn []Bucket for _, v := range m.buckets { rtn = append(rtn, Bucket(v)) } return rtn, nil } func (m *mockS3) ListObjects(ctx context.Context, id types.ID) ([]types.File, []types.Directory, error) { var files []types.File var dirs []types.Directory for k, v := range m.objects { if k.Bucket == id.Bucket { if k.Parent().Key == id.Key { if k.IsDirectory() { dirs = append(dirs, *mockObjToDir(v, k)) } else { files = append(files, *mockObjToFile(v, k)) } } } } return files, dirs, nil } func (m *mockS3) GetObject(ctx context.Context, id types.ID) (Object, error) { mockObj, exist := m.objects[id] if !exist { return nil, fmt.Errorf("Object not found") } reader := bytes.NewReader(mockObj.content) return mockObjectReader{reader}, nil } func (m *mockS3) PutObject(ctx context.Context, id types.ID, reader io.Reader, objectSize int64) error { content, err := ioutil.ReadAll(reader) if err != nil { return err } m.objects[id] = mockObject{ content: content, lastMod: time.Now(), contentType: "application/octet-stream", // TODO: detect MIME type or dont its just a mock after all } return nil } func (m *mockS3) CopyObject(ctx context.Context, src types.ID, dest types.ID) error { srcObj, exist := m.objects[src] if !exist { return fmt.Errorf("Object not found") } m.objects[dest] = srcObj return nil } func (m *mockS3) StatObject(ctx context.Context, id types.ID) (*types.File, error) { mockObj, exist := m.objects[id] if !exist { return nil, fmt.Errorf("Object not found") } return mockObjToFile(mockObj, id), nil } func (m *mockS3) RemoveObject(ctx context.Context, id types.ID) error { delete(m.objects, id) return nil } func mockObjToFile(mockObj mockObject, id types.ID) *types.File { return &types.File{ ID: id, Name: id.Name(), Size: int64(len(mockObj.content)), ContentType: mockObj.contentType, LastModified: mockObj.lastMod, ETag: fmt.Sprintf("%x", md5.Sum(mockObj.content)), } } func mockObjToDir(mockObj mockObject, id types.ID) *types.Directory { return &types.Directory{ ID: id, Name: id.Name(), } }