diff --git a/api/datastore/datastore_test.go b/api/datastore/datastore_test.go deleted file mode 100644 index c1ad34845..000000000 --- a/api/datastore/datastore_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package datastore - -import ( - "bytes" - "github.com/Sirupsen/logrus" - "github.com/gin-gonic/gin" - "github.com/iron-io/functions/api/models" - "log" -) - -func setLogBuffer() *bytes.Buffer { - var buf bytes.Buffer - buf.WriteByte('\n') - logrus.SetOutput(&buf) - gin.DefaultErrorWriter = &buf - gin.DefaultWriter = &buf - log.SetOutput(&buf) - return &buf -} - -var testApp = &models.App{ - Name: "Test", -} - -var testRoute = &models.Route{ - AppName: testApp.Name, - Path: "/test", - Image: "iron/hello", - Type: "sync", - Format: "http", -} diff --git a/api/datastore/mock.go b/api/datastore/mock.go index bc86abda1..e1d466742 100644 --- a/api/datastore/mock.go +++ b/api/datastore/mock.go @@ -9,6 +9,7 @@ import ( type Mock struct { Apps []*models.App Routes []*models.Route + data map[string][]byte } func NewMock(apps []*models.App, routes []*models.Route) *Mock { @@ -18,10 +19,13 @@ func NewMock(apps []*models.App, routes []*models.Route) *Mock { if routes == nil { routes = []*models.Route{} } - return &Mock{apps, routes} + return &Mock{apps, routes, make(map[string][]byte)} } func (m *Mock) GetApp(ctx context.Context, appName string) (app *models.App, err error) { + if appName == "" { + return nil, models.ErrDatastoreEmptyAppName + } for _, a := range m.Apps { if a.Name == appName { return a, nil @@ -36,6 +40,13 @@ func (m *Mock) GetApps(ctx context.Context, appFilter *models.AppFilter) ([]*mod } func (m *Mock) InsertApp(ctx context.Context, app *models.App) (*models.App, error) { + if app == nil { + return nil, models.ErrDatastoreEmptyApp + } + if app.Name == "" { + return nil, models.ErrDatastoreEmptyAppName + } + if a, _ := m.GetApp(ctx, app.Name); a != nil { return nil, models.ErrAppsAlreadyExists } @@ -48,18 +59,15 @@ func (m *Mock) UpdateApp(ctx context.Context, app *models.App) (*models.App, err if err != nil { return nil, err } - if app.Config != nil { - if a.Config == nil { - a.Config = map[string]string{} - } - for k, v := range app.Config { - a.Config[k] = v - } - } - return a, nil + a.UpdateConfig(app.Config) + + return a.Clone(), nil } func (m *Mock) RemoveApp(ctx context.Context, appName string) error { + if appName == "" { + return models.ErrDatastoreEmptyAppName + } for i, a := range m.Apps { if a.Name == appName { m.Apps = append(m.Apps[:i], m.Apps[i+1:]...) @@ -70,6 +78,12 @@ func (m *Mock) RemoveApp(ctx context.Context, appName string) error { } func (m *Mock) GetRoute(ctx context.Context, appName, routePath string) (*models.Route, error) { + if appName == "" { + return nil, models.ErrDatastoreEmptyAppName + } + if routePath == "" { + return nil, models.ErrDatastoreEmptyRoutePath + } for _, r := range m.Routes { if r.AppName == appName && r.Path == routePath { return r, nil @@ -95,8 +109,24 @@ func (m *Mock) GetRoutesByApp(ctx context.Context, appName string, routeFilter * } func (m *Mock) InsertRoute(ctx context.Context, route *models.Route) (*models.Route, error) { + if route == nil { + return nil, models.ErrDatastoreEmptyRoute + } + + if route.AppName == "" { + return nil, models.ErrDatastoreEmptyAppName + } + + if route.Path == "" { + return nil, models.ErrDatastoreEmptyRoutePath + } + + if _, err := m.GetApp(ctx, route.AppName); err != nil { + return nil, err + } + if r, _ := m.GetRoute(ctx, route.AppName, route.Path); r != nil { - return nil, models.ErrAppsAlreadyExists + return nil, models.ErrRoutesAlreadyExists } m.Routes = append(m.Routes, route) return route, nil @@ -107,18 +137,17 @@ func (m *Mock) UpdateRoute(ctx context.Context, route *models.Route) (*models.Ro if err != nil { return nil, err } - if route.Config != nil { - if route.Config == nil { - r.Config = map[string]string{} - } - for k, v := range route.Config { - r.Config[k] = v - } - } - return r, nil + r.Update(route) + return r.Clone(), nil } func (m *Mock) RemoveRoute(ctx context.Context, appName, routePath string) error { + if appName == "" { + return models.ErrDatastoreEmptyAppName + } + if routePath == "" { + return models.ErrDatastoreEmptyRoutePath + } for i, r := range m.Routes { if r.AppName == appName && r.Path == routePath { m.Routes = append(m.Routes[:i], m.Routes[i+1:]...) @@ -129,11 +158,20 @@ func (m *Mock) RemoveRoute(ctx context.Context, appName, routePath string) error } func (m *Mock) Put(ctx context.Context, key, value []byte) error { - // TODO: improve this mock method + if len(key) == 0 { + return models.ErrDatastoreEmptyKey + } + if len(value) == 0 { + delete(m.data, string(key)) + } else { + m.data[string(key)] = value + } return nil } func (m *Mock) Get(ctx context.Context, key []byte) ([]byte, error) { - // TODO: improve this mock method - return []byte{}, nil + if len(key) == 0 { + return nil, models.ErrDatastoreEmptyKey + } + return m.data[string(key)], nil } diff --git a/api/datastore/mock_test.go b/api/datastore/mock_test.go new file mode 100644 index 000000000..77e6b4814 --- /dev/null +++ b/api/datastore/mock_test.go @@ -0,0 +1,11 @@ +package datastore + +import ( + "testing" + + "github.com/iron-io/functions/api/datastore/internal/datastoretest" +) + +func TestDatastore(t *testing.T) { + datastoretest.Test(t, NewMock(nil, nil)) +} \ No newline at end of file diff --git a/api/models/app.go b/api/models/app.go index db8d4e693..3ba982146 100644 --- a/api/models/app.go +++ b/api/models/app.go @@ -53,6 +53,23 @@ func (a *App) Validate() error { return nil } +func (a *App) Clone() *App { + var c App + c.Name = a.Name + if a.Routes != nil { + for i := range a.Routes { + c.Routes = append(c.Routes, a.Routes[i].Clone()) + } + } + if a.Config != nil { + c.Config = make(Config) + for k, v := range a.Config { + c.Config[k] = v + } + } + return &c +} + // UpdateConfig adds entries from patch to a.Config, and removes entries with empty values. func (a *App) UpdateConfig(patch Config) { if patch != nil { diff --git a/api/models/route.go b/api/models/route.go index 82eaa90b0..7ce6ee726 100644 --- a/api/models/route.go +++ b/api/models/route.go @@ -125,6 +125,14 @@ func (r *Route) Validate() error { return nil } +func (r *Route) Clone() *Route { + var clone Route + clone.AppName = r.AppName + clone.Path = r.Path + clone.Update(r) + return &clone +} + // Update updates fields in r with non-zero field values from new. // 0-length slice Header values, and empty-string Config values trigger removal of map entry. func (r *Route) Update(new *Route) {