-
Notifications
You must be signed in to change notification settings - Fork 674
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MF-995 - Add Twins tests for endpoint list twins and list states (#1174)
* Add ListTwins test Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Remove monotonic time from twins, definitions and attributes creation and update Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Separate twins and states endpoint tests in two files Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add state generation helper funcs to state endpoint tests Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add createStateResponse() to states test Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add states test cases Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Simplify RetrieveAll twins and states methods Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add service.go to mocks Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Rename mocks.NewService to mocks.New Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add error checking to endpoint state tests Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Fix method comment Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add json response decode success check Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Remove created and updated fields from twin and state res Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Remove definition fields from twin req and res Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add Create funcs to mocks package Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add service save state tests Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add service list states test Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com>
- Loading branch information
1 parent
d7670e7
commit b4c8013
Showing
10 changed files
with
725 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
// Copyright (c) Mainflux | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package http_test | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/mainflux/mainflux/twins" | ||
"github.com/mainflux/senml" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/mainflux/mainflux/twins/mocks" | ||
) | ||
|
||
const ( | ||
nanosec = 1e9 | ||
|
||
attrName1 = "temperature" | ||
attrSubtopic1 = "engine" | ||
attrName2 = "humidity" | ||
attrSubtopic2 = "chassis" | ||
|
||
publisher = "twins" | ||
) | ||
|
||
type stateRes struct { | ||
TwinID string `json:"twin_id"` | ||
ID int64 `json:"id"` | ||
Definition int `json:"definition"` | ||
Payload map[string]interface{} `json:"payload"` | ||
} | ||
|
||
type statesPageRes struct { | ||
pageRes | ||
States []stateRes `json:"states"` | ||
} | ||
|
||
func TestListStates(t *testing.T) { | ||
svc := mocks.NewService(map[string]string{token: email}) | ||
ts := newServer(svc) | ||
defer ts.Close() | ||
|
||
twin := twins.Twin{ | ||
Owner: email, | ||
} | ||
def := mocks.CreateDefinition([]string{attrName1, attrName2}, []string{attrSubtopic1, attrSubtopic2}) | ||
tw, err := svc.AddTwin(context.Background(), token, twin, def) | ||
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) | ||
attr := def.Attributes[0] | ||
|
||
recs := mocks.CreateSenML(100, attrName1) | ||
message, err := mocks.CreateMessage(attr, recs) | ||
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) | ||
err = svc.SaveStates(message) | ||
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) | ||
|
||
var data []stateRes | ||
for i := 0; i < len(recs); i++ { | ||
res := createStateResponse(i, tw, recs[i]) | ||
data = append(data, res) | ||
} | ||
|
||
baseURL := fmt.Sprintf("%s/states/%s", ts.URL, tw.ID) | ||
queryFmt := "%s?offset=%d&limit=%d" | ||
cases := []struct { | ||
desc string | ||
auth string | ||
status int | ||
url string | ||
res []stateRes | ||
}{ | ||
{ | ||
desc: "get a list of states", | ||
auth: token, | ||
status: http.StatusOK, | ||
url: baseURL, | ||
res: data[0:10], | ||
}, | ||
{ | ||
desc: "get a list of states with valid offset and limit", | ||
auth: token, | ||
status: http.StatusOK, | ||
url: fmt.Sprintf(queryFmt, baseURL, 20, 15), | ||
res: data[20:35], | ||
}, | ||
{ | ||
desc: "get a list of states with invalid token", | ||
auth: wrongValue, | ||
status: http.StatusForbidden, | ||
url: fmt.Sprintf(queryFmt, baseURL, 0, 5), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with empty token", | ||
auth: "", | ||
status: http.StatusForbidden, | ||
url: fmt.Sprintf(queryFmt, baseURL, 0, 5), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with + limit > total", | ||
auth: token, | ||
status: http.StatusOK, | ||
url: fmt.Sprintf(queryFmt, baseURL, 91, 20), | ||
res: data[91:], | ||
}, | ||
{ | ||
desc: "get a list of states with negative offset", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf(queryFmt, baseURL, -1, 5), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with negative limit", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf(queryFmt, baseURL, 0, -5), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with zero limit", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf(queryFmt, baseURL, 0, 0), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with limit greater than max", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf(queryFmt, baseURL, 0, 110), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with invalid offset", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf("%s?offset=invalid&limit=%d", baseURL, 15), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with invalid limit", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf("%s?offset=%d&limit=invalid", baseURL, 0), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states without offset", | ||
auth: token, | ||
status: http.StatusOK, | ||
url: fmt.Sprintf("%s?limit=%d", baseURL, 15), | ||
res: data[0:15], | ||
}, | ||
{ | ||
desc: "get a list of states without limit", | ||
auth: token, | ||
status: http.StatusOK, | ||
url: fmt.Sprintf("%s?offset=%d", baseURL, 14), | ||
res: data[14:24], | ||
}, | ||
{ | ||
desc: "get a list of states with invalid number of parameters", | ||
auth: token, | ||
status: http.StatusBadRequest, | ||
url: fmt.Sprintf("%s%s", baseURL, "?offset=4&limit=4&limit=5&offset=5"), | ||
res: nil, | ||
}, | ||
{ | ||
desc: "get a list of states with redundant query parameters", | ||
auth: token, | ||
status: http.StatusOK, | ||
url: fmt.Sprintf("%s?offset=%d&limit=%d&value=something", baseURL, 0, 5), | ||
res: data[0:5], | ||
}, | ||
} | ||
|
||
for _, tc := range cases { | ||
req := testRequest{ | ||
client: ts.Client(), | ||
method: http.MethodGet, | ||
url: tc.url, | ||
token: tc.auth, | ||
} | ||
res, err := req.make() | ||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) | ||
|
||
var resData statesPageRes | ||
if tc.res != nil { | ||
err = json.NewDecoder(res.Body).Decode(&resData) | ||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) | ||
} | ||
|
||
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) | ||
assert.ElementsMatch(t, tc.res, resData.States, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, resData.States)) | ||
} | ||
} | ||
|
||
func createStateResponse(id int, tw twins.Twin, rec senml.Record) stateRes { | ||
return stateRes{ | ||
TwinID: tw.ID, | ||
ID: int64(id), | ||
Definition: tw.Definitions[len(tw.Definitions)-1].ID, | ||
Payload: map[string]interface{}{rec.BaseName: nil}, | ||
} | ||
} |
Oops, something went wrong.