From 1f983f7896be29bc80e2187fca981405423ce8d0 Mon Sep 17 00:00:00 2001 From: Kelvin Wang Date: Mon, 17 Dec 2018 11:13:39 -0500 Subject: [PATCH 1/2] fix(http): convert view errors --- bolt/view.go | 49 +++++++++++++++++++++++++++++++++++-------------- view.go | 11 +++++++---- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/bolt/view.go b/bolt/view.go index 2caefacb97..b270f38a5c 100644 --- a/bolt/view.go +++ b/bolt/view.go @@ -40,21 +40,28 @@ func (c *Client) FindViewByID(ctx context.Context, id platform.ID) (*platform.Vi return d, nil } -func (c *Client) findViewByID(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, error) { +func (c *Client) findViewByID(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, *platform.Error) { var d platform.View encodedID, err := id.Encode() if err != nil { - return nil, err + return nil, &platform.Error{ + Err: err, + } } v := tx.Bucket(viewBucket).Get(encodedID) if len(v) == 0 { - return nil, platform.ErrViewNotFound + return nil, &platform.Error{ + Code: platform.ENotFound, + Msg: platform.ErrViewNotFound, + } } if err := json.Unmarshal(v, &d); err != nil { - return nil, err + return nil, &platform.Error{ + Err: err, + } } return &d, nil @@ -99,11 +106,16 @@ func (c *Client) FindView(ctx context.Context, filter platform.ViewFilter) (*pla }) if err != nil { - return nil, err + return nil, &platform.Error{ + Err: err, + } } if d == nil { - return nil, platform.ErrViewNotFound + return nil, &platform.Error{ + Code: platform.ENotFound, + Msg: platform.ErrViewNotFound, + } } return d, nil @@ -269,20 +281,29 @@ func (c *Client) DeleteView(ctx context.Context, id platform.ID) error { }) } -func (c *Client) deleteView(ctx context.Context, tx *bolt.Tx, id platform.ID) error { - _, err := c.findViewByID(ctx, tx, id) - if err != nil { - return err +func (c *Client) deleteView(ctx context.Context, tx *bolt.Tx, id platform.ID) *platform.Error { + _, pe := c.findViewByID(ctx, tx, id) + if pe != nil { + return pe } encodedID, err := id.Encode() if err != nil { - return err + return &platform.Error{ + Err: err, + } } if err := tx.Bucket(viewBucket).Delete(encodedID); err != nil { - return err + return &platform.Error{ + Err: err, + } } - return c.deleteUserResourceMappings(ctx, tx, platform.UserResourceMappingFilter{ + if err := c.deleteUserResourceMappings(ctx, tx, platform.UserResourceMappingFilter{ ResourceID: id, ResourceType: platform.ViewResourceType, - }) + }); err != nil { + return &platform.Error{ + Err: err, + } + } + return nil } diff --git a/view.go b/view.go index 82f7baadf9..bf616d1de2 100644 --- a/view.go +++ b/view.go @@ -6,8 +6,8 @@ import ( "fmt" ) -// ErrViewNotFound is the error for a missing View. -const ErrViewNotFound = ChronografError("view not found") +// ErrViewNotFound is the error msg for a missing View. +const ErrViewNotFound = "view not found" // ViewService represents a service for managing View data. type ViewService interface { @@ -36,10 +36,13 @@ type ViewUpdate struct { } // Valid validates the update struct. It expects minimal values to be set. -func (u ViewUpdate) Valid() error { +func (u ViewUpdate) Valid() *Error { _, ok := u.Properties.(EmptyViewProperties) if u.Name == nil && ok { - return fmt.Errorf("expected at least one attribute to be updated") + return &Error{ + Code: EInvalid, + Msg: "expected at least one attribute to be updated", + } } return nil From f1c562f848956fb0ddfac1e8d652acf519faf086 Mon Sep 17 00:00:00 2001 From: Kelvin Wang Date: Tue, 18 Dec 2018 11:19:11 -0500 Subject: [PATCH 2/2] fix(http): view errors endpoint conversion --- bolt/dashboard.go | 8 +- bolt/view.go | 95 +++++++++++++++-------- bolt/view_test.go | 5 +- http/telegraf.go | 6 -- http/view_service.go | 56 ++++++++------ http/view_test.go | 15 +++- inmem/view.go | 53 ++++++++++--- inmem/view_test.go | 4 +- testing/cells.go | 176 +++++++++++++++++++++++++++++-------------- view.go | 9 +++ 10 files changed, 285 insertions(+), 142 deletions(-) diff --git a/bolt/dashboard.go b/bolt/dashboard.go index e30f6aa307..c4316b198f 100644 --- a/bolt/dashboard.go +++ b/bolt/dashboard.go @@ -219,12 +219,12 @@ func (c *Client) CreateDashboard(ctx context.Context, d *platform.Dashboard) err return nil } -func (c *Client) createViewIfNotExists(ctx context.Context, tx *bolt.Tx, cell *platform.Cell, opts platform.AddDashboardCellOptions) error { +func (c *Client) createViewIfNotExists(ctx context.Context, tx *bolt.Tx, cell *platform.Cell, opts platform.AddDashboardCellOptions) *platform.Error { if opts.UsingView.Valid() { // Creates a hard copy of a view - v, err := c.findViewByID(ctx, tx, opts.UsingView) - if err != nil { - return err + v, pe := c.findViewByID(ctx, tx, opts.UsingView) + if pe != nil { + return pe } view, err := c.copyView(ctx, tx, v.ID) if err != nil { diff --git a/bolt/view.go b/bolt/view.go index b270f38a5c..5173d667a9 100644 --- a/bolt/view.go +++ b/bolt/view.go @@ -27,17 +27,16 @@ func (c *Client) FindViewByID(ctx context.Context, id platform.ID) (*platform.Vi err := c.db.View(func(tx *bolt.Tx) error { dash, err := c.findViewByID(ctx, tx, id) if err != nil { - return err + return &platform.Error{ + Err: err, + Op: getOp(platform.OpFindViewByID), + } } d = dash return nil }) - if err != nil { - return nil, err - } - - return d, nil + return d, err } func (c *Client) findViewByID(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, *platform.Error) { @@ -67,10 +66,10 @@ func (c *Client) findViewByID(ctx context.Context, tx *bolt.Tx, id platform.ID) return &d, nil } -func (c *Client) copyView(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, error) { - v, err := c.findViewByID(ctx, tx, id) - if err != nil { - return nil, err +func (c *Client) copyView(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, *platform.Error) { + v, pe := c.findViewByID(ctx, tx, id) + if pe != nil { + return nil, pe } view := &platform.View{ @@ -80,8 +79,8 @@ func (c *Client) copyView(ctx context.Context, tx *bolt.Tx, id platform.ID) (*pl Properties: v.Properties, } - if err := c.createView(ctx, tx, view); err != nil { - return nil, err + if pe := c.createView(ctx, tx, view); pe != nil { + return nil, pe } return view, nil @@ -144,30 +143,36 @@ func filterViewsFn(filter platform.ViewFilter) func(v *platform.View) bool { // FindViews retrives all views that match an arbitrary view filter. func (c *Client) FindViews(ctx context.Context, filter platform.ViewFilter) ([]*platform.View, int, error) { + ds := []*platform.View{} + op := getOp(platform.OpFindViews) if filter.ID != nil { d, err := c.FindViewByID(ctx, *filter.ID) - if err != nil { - return nil, 0, err + if err != nil && platform.ErrorCode(err) != platform.ENotFound { + return nil, 0, &platform.Error{ + Err: err, + Op: op, + } + } + if d != nil { + ds = append(ds, d) } - return []*platform.View{d}, 1, nil + return ds, 1, nil } - ds := []*platform.View{} err := c.db.View(func(tx *bolt.Tx) error { dashs, err := c.findViews(ctx, tx, filter) if err != nil { - return err + return &platform.Error{ + Err: err, + Op: op, + } } ds = dashs return nil }) - if err != nil { - return nil, 0, err - } - - return ds, len(ds), nil + return ds, len(ds), err } func (c *Client) findViews(ctx context.Context, tx *bolt.Tx, filter platform.ViewFilter) ([]*platform.View, error) { @@ -191,11 +196,17 @@ func (c *Client) findViews(ctx context.Context, tx *bolt.Tx, filter platform.Vie // CreateView creates a platform view and sets d.ID. func (c *Client) CreateView(ctx context.Context, d *platform.View) error { return c.db.Update(func(tx *bolt.Tx) error { - return c.createView(ctx, tx, d) + if pe := c.createView(ctx, tx, d); pe != nil { + return &platform.Error{ + Op: getOp(platform.OpCreateView), + Err: pe, + } + } + return nil }) } -func (c *Client) createView(ctx context.Context, tx *bolt.Tx, d *platform.View) error { +func (c *Client) createView(ctx context.Context, tx *bolt.Tx, d *platform.View) *platform.Error { d.ID = c.IDGenerator.ID() return c.putView(ctx, tx, d) } @@ -203,21 +214,30 @@ func (c *Client) createView(ctx context.Context, tx *bolt.Tx, d *platform.View) // PutView will put a view without setting an ID. func (c *Client) PutView(ctx context.Context, d *platform.View) error { return c.db.Update(func(tx *bolt.Tx) error { - return c.putView(ctx, tx, d) + if pe := c.putView(ctx, tx, d); pe != nil { + return pe + } + return nil }) } -func (c *Client) putView(ctx context.Context, tx *bolt.Tx, d *platform.View) error { +func (c *Client) putView(ctx context.Context, tx *bolt.Tx, d *platform.View) *platform.Error { v, err := json.Marshal(d) if err != nil { - return err + return &platform.Error{ + Err: err, + } } encodedID, err := d.ID.Encode() if err != nil { - return err + return &platform.Error{ + Err: err, + } } if err := tx.Bucket(viewBucket).Put(encodedID, v); err != nil { - return err + return &platform.Error{ + Err: err, + } } return nil } @@ -242,9 +262,12 @@ func (c *Client) forEachView(ctx context.Context, tx *bolt.Tx, fn func(*platform func (c *Client) UpdateView(ctx context.Context, id platform.ID, upd platform.ViewUpdate) (*platform.View, error) { var d *platform.View err := c.db.Update(func(tx *bolt.Tx) error { - dash, err := c.updateView(ctx, tx, id, upd) - if err != nil { - return err + dash, pe := c.updateView(ctx, tx, id, upd) + if pe != nil { + return &platform.Error{ + Err: pe, + Op: getOp(platform.OpUpdateView), + } } d = dash return nil @@ -277,7 +300,13 @@ func (c *Client) updateView(ctx context.Context, tx *bolt.Tx, id platform.ID, up // DeleteView deletes a view and prunes it from the index. func (c *Client) DeleteView(ctx context.Context, id platform.ID) error { return c.db.Update(func(tx *bolt.Tx) error { - return c.deleteView(ctx, tx, id) + if pe := c.deleteView(ctx, tx, id); pe != nil { + return &platform.Error{ + Err: pe, + Op: getOp(platform.OpDeleteView), + } + } + return nil }) } diff --git a/bolt/view_test.go b/bolt/view_test.go index c6284636b3..66415fe893 100644 --- a/bolt/view_test.go +++ b/bolt/view_test.go @@ -5,10 +5,11 @@ import ( "testing" "github.com/influxdata/platform" + "github.com/influxdata/platform/bolt" platformtesting "github.com/influxdata/platform/testing" ) -func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, func()) { +func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, string, func()) { c, closeFn, err := NewTestClient() if err != nil { t.Fatalf("failed to create new bolt client: %v", err) @@ -20,7 +21,7 @@ func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewS t.Fatalf("failed to populate cells") } } - return c, func() { + return c, bolt.OpPrefix, func() { defer closeFn() for _, b := range f.Views { if err := c.DeleteView(ctx, b.ID); err != nil { diff --git a/http/telegraf.go b/http/telegraf.go index 847d6c2f5d..c50ff752e8 100644 --- a/http/telegraf.go +++ b/http/telegraf.go @@ -129,9 +129,6 @@ func (h *TelegrafHandler) handleGetTelegrafs(w http.ResponseWriter, r *http.Requ } tcs, _, err := h.TelegrafService.FindTelegrafConfigs(ctx, *filter) if err != nil { - if err == platform.ErrViewNotFound { - err = errors.New(err.Error(), errors.NotFound) - } EncodeError(ctx, err, w) return } @@ -150,9 +147,6 @@ func (h *TelegrafHandler) handleGetTelegraf(w http.ResponseWriter, r *http.Reque } tc, err := h.TelegrafService.FindTelegrafConfigByID(ctx, id) if err != nil { - if err == platform.ErrViewNotFound { - err = errors.New(err.Error(), errors.NotFound) - } EncodeError(ctx, err, w) return } diff --git a/http/view_service.go b/http/view_service.go index 8e56ec209c..6193d6dc10 100644 --- a/http/view_service.go +++ b/http/view_service.go @@ -7,7 +7,6 @@ import ( "net/http" "github.com/influxdata/platform" - "github.com/influxdata/platform/kit/errors" "github.com/julienschmidt/httprouter" ) @@ -106,7 +105,7 @@ func (h *ViewHandler) handleGetViews(w http.ResponseWriter, r *http.Request) { views, _, err := h.ViewService.FindViews(ctx, req.filter) if err != nil { - EncodeError(ctx, errors.InternalErrorf("Error loading views: %v", err), w) + EncodeError(ctx, err, w) return } @@ -164,7 +163,7 @@ func (h *ViewHandler) handlePostViews(w http.ResponseWriter, r *http.Request) { return } if err := h.ViewService.CreateView(ctx, req.View); err != nil { - EncodeError(ctx, errors.InternalErrorf("Error loading views: %v", err), w) + EncodeError(ctx, err, w) return } @@ -200,9 +199,6 @@ func (h *ViewHandler) handleGetView(w http.ResponseWriter, r *http.Request) { view, err := h.ViewService.FindViewByID(ctx, req.ViewID) if err != nil { - if err == platform.ErrViewNotFound { - err = errors.New(err.Error(), errors.NotFound) - } EncodeError(ctx, err, w) return } @@ -221,7 +217,10 @@ func decodeGetViewRequest(ctx context.Context, r *http.Request) (*getViewRequest params := httprouter.ParamsFromContext(ctx) id := params.ByName("id") if id == "" { - return nil, errors.InvalidDataf("url missing id") + return nil, &platform.Error{ + Code: platform.EInvalid, + Msg: "url missing id", + } } var i platform.ID @@ -245,9 +244,6 @@ func (h *ViewHandler) handleDeleteView(w http.ResponseWriter, r *http.Request) { } if err := h.ViewService.DeleteView(ctx, req.ViewID); err != nil { - if err == platform.ErrViewNotFound { - err = errors.New(err.Error(), errors.NotFound) - } EncodeError(ctx, err, w) return } @@ -263,7 +259,10 @@ func decodeDeleteViewRequest(ctx context.Context, r *http.Request) (*deleteViewR params := httprouter.ParamsFromContext(ctx) id := params.ByName("id") if id == "" { - return nil, errors.InvalidDataf("url missing id") + return nil, &platform.Error{ + Code: platform.EInvalid, + Msg: "url missing id", + } } var i platform.ID @@ -280,16 +279,13 @@ func decodeDeleteViewRequest(ctx context.Context, r *http.Request) (*deleteViewR func (h *ViewHandler) handlePatchView(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - req, err := decodePatchViewRequest(ctx, r) - if err != nil { - EncodeError(ctx, err, w) + req, pe := decodePatchViewRequest(ctx, r) + if pe != nil { + EncodeError(ctx, pe, w) return } view, err := h.ViewService.UpdateView(ctx, req.ViewID, req.Upd) if err != nil { - if err == platform.ErrViewNotFound { - err = errors.New(err.Error(), errors.NotFound) - } EncodeError(ctx, err, w) return } @@ -305,11 +301,13 @@ type patchViewRequest struct { Upd platform.ViewUpdate } -func decodePatchViewRequest(ctx context.Context, r *http.Request) (*patchViewRequest, error) { +func decodePatchViewRequest(ctx context.Context, r *http.Request) (*patchViewRequest, *platform.Error) { req := &patchViewRequest{} upd := platform.ViewUpdate{} if err := json.NewDecoder(r.Body).Decode(&upd); err != nil { - return nil, errors.MalformedDataf(err.Error()) + return nil, &platform.Error{ + Err: err, + } } req.Upd = upd @@ -317,26 +315,36 @@ func decodePatchViewRequest(ctx context.Context, r *http.Request) (*patchViewReq params := httprouter.ParamsFromContext(ctx) id := params.ByName("id") if id == "" { - return nil, errors.InvalidDataf("url missing id") + return nil, &platform.Error{ + Code: platform.EInvalid, + Msg: "url missing id", + } } var i platform.ID if err := i.DecodeFromString(id); err != nil { - return nil, err + return nil, &platform.Error{ + Err: err, + } } req.ViewID = i if err := req.Valid(); err != nil { - return nil, errors.MalformedDataf(err.Error()) + return nil, &platform.Error{ + Err: err, + } } return req, nil } // Valid validates that the view ID is non zero valued and update has expected values set. -func (r *patchViewRequest) Valid() error { +func (r *patchViewRequest) Valid() *platform.Error { if !r.ViewID.Valid() { - return fmt.Errorf("missing view ID") + return &platform.Error{ + Code: platform.EInvalid, + Msg: "missing view ID", + } } return r.Upd.Valid() diff --git a/http/view_test.go b/http/view_test.go index 8a3e1c82b5..8f5f91e1a8 100644 --- a/http/view_test.go +++ b/http/view_test.go @@ -222,7 +222,10 @@ func TestService_handleGetView(t *testing.T) { fields: fields{ &mock.ViewService{ FindViewByIDF: func(ctx context.Context, id platform.ID) (*platform.View, error) { - return nil, platform.ErrViewNotFound + return nil, &platform.Error{ + Code: platform.ENotFound, + Msg: platform.ErrViewNotFound, + } }, }, }, @@ -416,7 +419,10 @@ func TestService_handleDeleteView(t *testing.T) { fields: fields{ &mock.ViewService{ DeleteViewF: func(ctx context.Context, id platform.ID) error { - return platform.ErrViewNotFound + return &platform.Error{ + Code: platform.ENotFound, + Msg: platform.ErrViewNotFound, + } }, }, }, @@ -571,7 +577,10 @@ func TestService_handlePatchView(t *testing.T) { fields: fields{ &mock.ViewService{ UpdateViewF: func(ctx context.Context, id platform.ID, upd platform.ViewUpdate) (*platform.View, error) { - return nil, platform.ErrViewNotFound + return nil, &platform.Error{ + Code: platform.ENotFound, + Msg: platform.ErrViewNotFound, + } }, }, }, diff --git a/inmem/view.go b/inmem/view.go index d28fbe6c2d..2ec25e7898 100644 --- a/inmem/view.go +++ b/inmem/view.go @@ -7,22 +7,35 @@ import ( "github.com/influxdata/platform" ) -func (s *Service) loadView(ctx context.Context, id platform.ID) (*platform.View, error) { +func (s *Service) loadView(ctx context.Context, id platform.ID) (*platform.View, *platform.Error) { i, ok := s.viewKV.Load(id.String()) if !ok { - return nil, fmt.Errorf("view not found") + return nil, &platform.Error{ + Code: platform.ENotFound, + Msg: "view not found", + } } d, ok := i.(*platform.View) if !ok { - return nil, fmt.Errorf("type %T is not a view", i) + return nil, &platform.Error{ + Code: platform.EInvalid, + Msg: fmt.Sprintf("type %T is not a view", i), + } } return d, nil } // FindViewByID returns a single view by ID. func (s *Service) FindViewByID(ctx context.Context, id platform.ID) (*platform.View, error) { - return s.loadView(ctx, id) + v, pe := s.loadView(ctx, id) + if pe != nil { + return nil, &platform.Error{ + Err: pe, + Op: OpPrefix + platform.OpFindViewByID, + } + } + return v, nil } func filterViewFn(filter platform.ViewFilter) func(d *platform.View) bool { @@ -37,16 +50,22 @@ func filterViewFn(filter platform.ViewFilter) func(d *platform.View) bool { // FindViews implements platform.ViewService interface. func (s *Service) FindViews(ctx context.Context, filter platform.ViewFilter) ([]*platform.View, int, error) { + var ds []*platform.View if filter.ID != nil { d, err := s.FindViewByID(ctx, *filter.ID) - if err != nil { - return nil, 0, err + if err != nil && platform.ErrorCode(err) != platform.ENotFound { + return nil, 0, &platform.Error{ + Err: err, + Op: OpPrefix + platform.OpFindViews, + } + } + if d != nil { + ds = append(ds, d) } - return []*platform.View{d}, 1, nil + return ds, len(ds), nil } - var ds []*platform.View var err error filterF := filterViewFn(filter) s.viewKV.Range(func(k, v interface{}) bool { @@ -66,7 +85,13 @@ func (s *Service) FindViews(ctx context.Context, filter platform.ViewFilter) ([] // CreateView implements platform.ViewService interface. func (s *Service) CreateView(ctx context.Context, c *platform.View) error { c.ID = s.IDGenerator.ID() - return s.PutView(ctx, c) + if err := s.PutView(ctx, c); err != nil { + return &platform.Error{ + Err: err, + Op: OpPrefix + platform.OpCreateView, + } + } + return nil } // PutView implements platform.ViewService interface. @@ -82,7 +107,10 @@ func (s *Service) PutView(ctx context.Context, c *platform.View) error { func (s *Service) UpdateView(ctx context.Context, id platform.ID, upd platform.ViewUpdate) (*platform.View, error) { c, err := s.FindViewByID(ctx, id) if err != nil { - return nil, err + return nil, &platform.Error{ + Err: err, + Op: OpPrefix + platform.OpUpdateView, + } } if upd.Name != nil { @@ -101,7 +129,10 @@ func (s *Service) UpdateView(ctx context.Context, id platform.ID, upd platform.V // DeleteView implements platform.ViewService interface. func (s *Service) DeleteView(ctx context.Context, id platform.ID) error { if _, err := s.FindViewByID(ctx, id); err != nil { - return err + return &platform.Error{ + Err: err, + Op: OpPrefix + platform.OpDeleteView, + } } s.viewKV.Delete(id.String()) return nil diff --git a/inmem/view_test.go b/inmem/view_test.go index 3183315dfb..0421b2db06 100644 --- a/inmem/view_test.go +++ b/inmem/view_test.go @@ -8,7 +8,7 @@ import ( platformtesting "github.com/influxdata/platform/testing" ) -func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, func()) { +func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, string, func()) { s := NewService() s.IDGenerator = f.IDGenerator ctx := context.TODO() @@ -17,7 +17,7 @@ func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewS t.Fatalf("failed to populate Views") } } - return s, func() {} + return s, OpPrefix, func() {} } func TestViewService_CreateView(t *testing.T) { diff --git a/testing/cells.go b/testing/cells.go index fe199ac889..edd72f6ed9 100644 --- a/testing/cells.go +++ b/testing/cells.go @@ -3,7 +3,6 @@ package testing import ( "bytes" "context" - "fmt" "sort" "testing" @@ -39,7 +38,7 @@ type ViewFields struct { // CreateView testing func CreateView( - init func(ViewFields, *testing.T) (platform.ViewService, func()), + init func(ViewFields, *testing.T) (platform.ViewService, string, func()), t *testing.T, ) { type args struct { @@ -110,19 +109,11 @@ func CreateView( for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s, done := init(tt.fields, t) + s, opPrefix, done := init(tt.fields, t) defer done() ctx := context.TODO() err := s.CreateView(ctx, tt.args.view) - if (err != nil) != (tt.wants.err != nil) { - t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err) - } - - if err != nil && tt.wants.err != nil { - if err.Error() != tt.wants.err.Error() { - t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error()) - } - } + diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t) defer s.DeleteView(ctx, tt.args.view.ID) views, _, err := s.FindViews(ctx, platform.ViewFilter{}) @@ -138,7 +129,7 @@ func CreateView( // FindViewByID testing func FindViewByID( - init func(ViewFields, *testing.T) (platform.ViewService, func()), + init func(ViewFields, *testing.T) (platform.ViewService, string, func()), t *testing.T, ) { type args struct { @@ -194,24 +185,50 @@ func FindViewByID( }, }, }, + { + name: "find view by id not found", + fields: ViewFields{ + Views: []*platform.View{ + { + ViewContents: platform.ViewContents{ + ID: MustIDBase16(viewOneID), + Name: "view1", + }, + Properties: platform.EmptyViewProperties{}, + }, + { + ViewContents: platform.ViewContents{ + ID: MustIDBase16(viewTwoID), + Name: "view2", + }, + Properties: platform.TableViewProperties{ + Type: "table", + TimeFormat: "rfc3339", + }, + }, + }, + }, + args: args{ + id: MustIDBase16(threeID), + }, + wants: wants{ + err: &platform.Error{ + Code: platform.ENotFound, + Op: platform.OpFindViewByID, + Msg: "view not found", + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s, done := init(tt.fields, t) + s, opPrefix, done := init(tt.fields, t) defer done() ctx := context.TODO() view, err := s.FindViewByID(ctx, tt.args.id) - if (err != nil) != (tt.wants.err != nil) { - t.Fatalf("expected errors to be equal '%v' got '%v'", tt.wants.err, err) - } - - if err != nil && tt.wants.err != nil { - if err.Error() != tt.wants.err.Error() { - t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err) - } - } + diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t) if diff := cmp.Diff(view, tt.wants.view, viewCmpOptions...); diff != "" { t.Errorf("view is different -got/+want\ndiff %s", diff) @@ -222,7 +239,7 @@ func FindViewByID( // FindViews testing func FindViews( - init func(ViewFields, *testing.T) (platform.ViewService, func()), + init func(ViewFields, *testing.T) (platform.ViewService, string, func()), t *testing.T, ) { type args struct { @@ -326,11 +343,41 @@ func FindViews( }, }, }, + { + name: "find view by id not found", + fields: ViewFields{ + Views: []*platform.View{ + { + ViewContents: platform.ViewContents{ + ID: MustIDBase16(viewOneID), + Name: "view1", + }, + Properties: platform.EmptyViewProperties{}, + }, + { + ViewContents: platform.ViewContents{ + ID: MustIDBase16(viewTwoID), + Name: "view2", + }, + Properties: platform.TableViewProperties{ + Type: "table", + TimeFormat: "rfc3339", + }, + }, + }, + }, + args: args{ + ID: MustIDBase16(threeID), + }, + wants: wants{ + views: []*platform.View{}, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s, done := init(tt.fields, t) + s, opPrefix, done := init(tt.fields, t) defer done() ctx := context.TODO() @@ -340,15 +387,7 @@ func FindViews( } views, _, err := s.FindViews(ctx, filter) - if (err != nil) != (tt.wants.err != nil) { - t.Fatalf("expected errors to be equal '%v' got '%v'", tt.wants.err, err) - } - - if err != nil && tt.wants.err != nil { - if err.Error() != tt.wants.err.Error() { - t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err) - } - } + diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t) if diff := cmp.Diff(views, tt.wants.views, viewCmpOptions...); diff != "" { t.Errorf("views are different -got/+want\ndiff %s", diff) @@ -359,7 +398,7 @@ func FindViews( // DeleteView testing func DeleteView( - init func(ViewFields, *testing.T) (platform.ViewService, func()), + init func(ViewFields, *testing.T) (platform.ViewService, string, func()), t *testing.T, ) { type args struct { @@ -444,7 +483,11 @@ func DeleteView( ID: MustIDBase16(viewThreeID), }, wants: wants{ - err: fmt.Errorf("view not found"), + err: &platform.Error{ + Code: platform.ENotFound, + Op: platform.OpDeleteView, + Msg: "view not found", + }, views: []*platform.View{ { ViewContents: platform.ViewContents{ @@ -470,19 +513,11 @@ func DeleteView( for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s, done := init(tt.fields, t) + s, opPrefix, done := init(tt.fields, t) defer done() ctx := context.TODO() err := s.DeleteView(ctx, tt.args.ID) - if (err != nil) != (tt.wants.err != nil) { - t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err) - } - - if err != nil && tt.wants.err != nil { - if err.Error() != tt.wants.err.Error() { - t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error()) - } - } + diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t) filter := platform.ViewFilter{} views, _, err := s.FindViews(ctx, filter) @@ -498,7 +533,7 @@ func DeleteView( // UpdateView testing func UpdateView( - init func(ViewFields, *testing.T) (platform.ViewService, func()), + init func(ViewFields, *testing.T) (platform.ViewService, string, func()), t *testing.T, ) { type args struct { @@ -597,11 +632,46 @@ func UpdateView( }, }, }, + { + name: "update id not exists", + fields: ViewFields{ + Views: []*platform.View{ + { + ViewContents: platform.ViewContents{ + ID: MustIDBase16(viewOneID), + Name: "view1", + }, + Properties: platform.EmptyViewProperties{}, + }, + { + ViewContents: platform.ViewContents{ + ID: MustIDBase16(viewTwoID), + Name: "view2", + }, + Properties: platform.TableViewProperties{ + Type: "table", + TimeFormat: "rfc3339", + }, + }, + }, + }, + args: args{ + id: MustIDBase16(threeID), + name: "changed", + }, + wants: wants{ + err: &platform.Error{ + Code: platform.ENotFound, + Op: platform.OpUpdateView, + Msg: "view not found", + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s, done := init(tt.fields, t) + s, opPrefix, done := init(tt.fields, t) defer done() ctx := context.TODO() @@ -614,15 +684,7 @@ func UpdateView( } view, err := s.UpdateView(ctx, tt.args.id, upd) - if (err != nil) != (tt.wants.err != nil) { - t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err) - } - - if err != nil && tt.wants.err != nil { - if err.Error() != tt.wants.err.Error() { - t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error()) - } - } + diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t) if diff := cmp.Diff(view, tt.wants.view, viewCmpOptions...); diff != "" { t.Errorf("view is different -got/+want\ndiff %s", diff) diff --git a/view.go b/view.go index bf616d1de2..015e4e3930 100644 --- a/view.go +++ b/view.go @@ -9,6 +9,15 @@ import ( // ErrViewNotFound is the error msg for a missing View. const ErrViewNotFound = "view not found" +// ops for view. +const ( + OpFindViewByID = "FindViewByID" + OpFindViews = "FindViews" + OpCreateView = "CreateView" + OpUpdateView = "UpdateView" + OpDeleteView = "DeleteView" +) + // ViewService represents a service for managing View data. type ViewService interface { // FindViewByID returns a single View by ID.