223 lines
5.8 KiB
Go
223 lines
5.8 KiB
Go
package testutil
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/elfoundation/hatch/internal/store"
|
|
)
|
|
|
|
// FakeRepository implements store.Repository for tests.
|
|
type FakeRepository struct {
|
|
Endpoints map[string]*store.Endpoint
|
|
Requests []*store.Request
|
|
Mocks map[string]*store.MockConfig
|
|
|
|
// Space-related fields
|
|
Spaces map[string]*store.Space
|
|
Photos map[string]*store.Photo
|
|
FaceEmbeddings map[string]*store.FaceEmbedding
|
|
RateLimits map[string]*store.RateLimit
|
|
}
|
|
|
|
// NewFakeRepository creates a new FakeRepository.
|
|
func NewFakeRepository() *FakeRepository {
|
|
return &FakeRepository{
|
|
Endpoints: map[string]*store.Endpoint{},
|
|
Mocks: map[string]*store.MockConfig{},
|
|
Spaces: map[string]*store.Space{},
|
|
Photos: map[string]*store.Photo{},
|
|
FaceEmbeddings: map[string]*store.FaceEmbedding{},
|
|
RateLimits: map[string]*store.RateLimit{},
|
|
}
|
|
}
|
|
|
|
func (f *FakeRepository) CreateEndpoint(_ context.Context, url string) (*store.Endpoint, error) {
|
|
e := &store.Endpoint{ID: url, URL: url, CreatedAt: "t", UpdatedAt: "t"}
|
|
f.Endpoints[url] = e
|
|
return e, nil
|
|
}
|
|
|
|
func (f *FakeRepository) GetEndpoint(_ context.Context, id string) (*store.Endpoint, error) {
|
|
e, ok := f.Endpoints[id]
|
|
if !ok {
|
|
return nil, errNotFound
|
|
}
|
|
return e, nil
|
|
}
|
|
|
|
func (f *FakeRepository) AppendRequest(_ context.Context, eid string, r *store.Request) error {
|
|
r.ID = "req-" + string(rune(len(f.Requests)+'0'))
|
|
r.EndpointID = eid
|
|
f.Requests = append(f.Requests, r)
|
|
return nil
|
|
}
|
|
|
|
func (f *FakeRepository) GetRequest(_ context.Context, id string) (*store.Request, error) {
|
|
for _, r := range f.Requests {
|
|
if r.ID == id {
|
|
return r, nil
|
|
}
|
|
}
|
|
return nil, errNotFound
|
|
}
|
|
|
|
func (f *FakeRepository) ListRequests(_ context.Context, _ string, _ int) ([]*store.Request, error) {
|
|
return f.Requests, nil
|
|
}
|
|
|
|
func (f *FakeRepository) SearchRequests(_ context.Context, _ string, query string, limit int) ([]*store.Request, error) {
|
|
if query == "" {
|
|
return f.Requests, nil
|
|
}
|
|
var matched []*store.Request
|
|
for _, r := range f.Requests {
|
|
if strings.Contains(r.Method, query) ||
|
|
strings.Contains(r.Path, query) ||
|
|
strings.Contains(r.Headers, query) ||
|
|
strings.Contains(r.Query, query) ||
|
|
strings.Contains(string(r.Body), query) {
|
|
matched = append(matched, r)
|
|
if limit > 0 && len(matched) >= limit {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return matched, nil
|
|
}
|
|
|
|
func (f *FakeRepository) GetMock(_ context.Context, endpointID string) (*store.MockConfig, error) {
|
|
m, ok := f.Mocks[endpointID]
|
|
if !ok {
|
|
return nil, errNotFound
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func (f *FakeRepository) SetMock(_ context.Context, mock *store.MockConfig) error {
|
|
f.Mocks[mock.EndpointID] = mock
|
|
return nil
|
|
}
|
|
|
|
func (f *FakeRepository) Close() error { return nil }
|
|
|
|
func (f *FakeRepository) Ping(_ context.Context) error { return nil }
|
|
|
|
// Space operations
|
|
|
|
func (f *FakeRepository) CreateSpace(_ context.Context, space *store.Space) (*store.Space, error) {
|
|
f.Spaces[space.Slug] = space
|
|
return space, nil
|
|
}
|
|
|
|
func (f *FakeRepository) GetSpaceBySlug(_ context.Context, slug string) (*store.Space, error) {
|
|
space, ok := f.Spaces[slug]
|
|
if !ok {
|
|
return nil, errNotFound
|
|
}
|
|
return space, nil
|
|
}
|
|
|
|
func (f *FakeRepository) UpdateSpace(_ context.Context, space *store.Space) (*store.Space, error) {
|
|
f.Spaces[space.Slug] = space
|
|
return space, nil
|
|
}
|
|
|
|
func (f *FakeRepository) DeleteSpace(_ context.Context, id string) error {
|
|
for slug, space := range f.Spaces {
|
|
if space.ID == id {
|
|
delete(f.Spaces, slug)
|
|
return nil
|
|
}
|
|
}
|
|
return errNotFound
|
|
}
|
|
|
|
func (f *FakeRepository) ListPublicSpaces(_ context.Context) ([]*store.Space, error) {
|
|
var spaces []*store.Space
|
|
for _, space := range f.Spaces {
|
|
if space.IsPublic {
|
|
spaces = append(spaces, space)
|
|
}
|
|
}
|
|
return spaces, nil
|
|
}
|
|
|
|
// Photo operations
|
|
|
|
func (f *FakeRepository) CreatePhoto(_ context.Context, photo *store.Photo) (*store.Photo, error) {
|
|
f.Photos[photo.ID] = photo
|
|
return photo, nil
|
|
}
|
|
|
|
func (f *FakeRepository) GetPhoto(_ context.Context, id string) (*store.Photo, error) {
|
|
photo, ok := f.Photos[id]
|
|
if !ok {
|
|
return nil, errNotFound
|
|
}
|
|
return photo, nil
|
|
}
|
|
|
|
func (f *FakeRepository) ListPhotosBySpace(_ context.Context, spaceID string, limit int) ([]*store.Photo, error) {
|
|
var photos []*store.Photo
|
|
for _, photo := range f.Photos {
|
|
if photo.SpaceID == spaceID {
|
|
photos = append(photos, photo)
|
|
if limit > 0 && len(photos) >= limit {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return photos, nil
|
|
}
|
|
|
|
func (f *FakeRepository) DeletePhoto(_ context.Context, id string) error {
|
|
for photoID := range f.Photos {
|
|
if photoID == id {
|
|
delete(f.Photos, photoID)
|
|
return nil
|
|
}
|
|
}
|
|
return errNotFound
|
|
}
|
|
|
|
// Face embedding operations
|
|
|
|
func (f *FakeRepository) CreateFaceEmbedding(_ context.Context, embedding *store.FaceEmbedding) (*store.FaceEmbedding, error) {
|
|
f.FaceEmbeddings[embedding.ID] = embedding
|
|
return embedding, nil
|
|
}
|
|
|
|
func (f *FakeRepository) ListFaceEmbeddingsBySpace(_ context.Context, spaceID string) ([]*store.FaceEmbedding, error) {
|
|
var embeddings []*store.FaceEmbedding
|
|
for _, embedding := range f.FaceEmbeddings {
|
|
if embedding.SpaceID == spaceID {
|
|
embeddings = append(embeddings, embedding)
|
|
}
|
|
}
|
|
return embeddings, nil
|
|
}
|
|
|
|
func (f *FakeRepository) SearchFaceEmbeddings(_ context.Context, spaceID string, embedding []float32, limit int) ([]*store.FaceEmbedding, error) {
|
|
// For fake repo, just return all embeddings in the space
|
|
return f.ListFaceEmbeddingsBySpace(nil, spaceID)
|
|
}
|
|
|
|
// Rate limiting operations
|
|
|
|
func (f *FakeRepository) CheckRateLimit(_ context.Context, ipAddress, spaceID string, limit, windowMinutes int) (bool, error) {
|
|
// For fake repo, always allow
|
|
return true, nil
|
|
}
|
|
|
|
func (f *FakeRepository) IncrementRateLimit(_ context.Context, ipAddress, spaceID string, windowMinutes int) error {
|
|
// For fake repo, do nothing
|
|
return nil
|
|
}
|
|
|
|
type notFoundError struct{}
|
|
|
|
func (e *notFoundError) Error() string { return "not found" }
|
|
|
|
var errNotFound = ¬FoundError{}
|