diff --git a/twins/api/http/endpoint_test.go b/twins/api/http/endpoint_test.go index 57bc9e40..9d36a7ee 100644 --- a/twins/api/http/endpoint_test.go +++ b/twins/api/http/endpoint_test.go @@ -28,6 +28,7 @@ import ( ) const ( + twinName = "name" contentType = "application/json" email = "user@example.com" token = "token" @@ -201,9 +202,11 @@ func TestUpdateTwin(t *testing.T) { twin := twins.Twin{ThingID: thingID} def := twins.Definition{} - data := toJSON(twin) stw, _ := svc.AddTwin(context.Background(), token, twin, def) + twin.Name = twinName + data := toJSON(twin) + tw := twin tw.Name = invalidName invalidData := toJSON(tw) @@ -230,7 +233,7 @@ func TestUpdateTwin(t *testing.T) { id: stw.ID, contentType: contentType, auth: token, - status: http.StatusOK, + status: http.StatusBadRequest, }, { desc: "update non-existent twin", diff --git a/twins/service.go b/twins/service.go index 0f574b74..a48eb6af 100644 --- a/twins/service.go +++ b/twins/service.go @@ -154,27 +154,38 @@ func (ts *twinsService) UpdateTwin(ctx context.Context, token string, twin Twin, if err != nil { return err } - tw.Updated = time.Now() - tw.Revision++ + + revision := false if twin.Name != "" { + revision = true tw.Name = twin.Name } if twin.ThingID != "" { + revision = true tw.ThingID = twin.ThingID } if len(def.Attributes) > 0 { + revision = true def.Created = time.Now() def.ID = tw.Definitions[len(tw.Definitions)-1].ID + 1 tw.Definitions = append(tw.Definitions, def) } - if len(twin.Metadata) == 0 { + if len(twin.Metadata) > 0 { + revision = true tw.Metadata = twin.Metadata } + if !revision { + return ErrMalformedEntity + } + + tw.Updated = time.Now() + tw.Revision++ + if err := ts.twins.Update(ctx, tw); err != nil { return err } diff --git a/twins/service_test.go b/twins/service_test.go index 7a1f6aa4..2311df9f 100644 --- a/twins/service_test.go +++ b/twins/service_test.go @@ -86,6 +86,8 @@ func TestUpdateTwin(t *testing.T) { saved, err := svc.AddTwin(context.Background(), token, twin, def) require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err)) + saved.Name = twinName + cases := []struct { desc string twin twins.Twin diff --git a/twins/twins.go b/twins/twins.go index a7f01a9b..fa2c57e8 100644 --- a/twins/twins.go +++ b/twins/twins.go @@ -13,16 +13,16 @@ type Metadata map[string]interface{} // Attribute stores individual attribute data type Attribute struct { - Channel string - Subtopic string - PersistState bool + Channel string `json:"channel"` + Subtopic string `json:"subtopic"` + PersistState bool `json:"persist_state"` } // Definition stores entity's attributes type Definition struct { - ID int - Created time.Time - Attributes map[string]Attribute + ID int `json:"id"` + Created time.Time `json:"created"` + Attributes map[string]Attribute `json:"attributes"` } // Twin represents a Mainflux thing digital twin. Each twin is owned by one thing, and