mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-24 13:48:49 +08:00

* Add things auth and auth Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(auth): add environment variable prefix for authorization gRPC client This commit adds the environment variable prefix `MF_THINGS_AUTH_G` for the authorization gRPC client in the `internal/clients/grpc/auth/client.go` file. The prefix is used to configure the gRPC client for authorization. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(auth): add mock implementation This commit adds a new file `auth.go` to the `mocks` package. The file contains a mock implementation of the `mainflux.AuthzServiceClient` interface. This mock implementation is used for testing purposes and allows for easier unit testing of code that depends on the `AuthzServiceClient` interface. The `auth.go` file includes the necessary imports and initializes a new struct that embeds the `mock.Mock` struct from the `github.com/stretchr/testify/mock` package. This struct provides methods for setting expectations and returning predefined responses during tests. This addition will improve the testability of the codebase and facilitate the testing of components that rely on the `AuthzServiceClient` interface. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(readers): add user authentication to listMessagesEndpoint This commit adds user authentication to the listMessagesEndpoint function in the readers package. The function now takes an additional parameter, uauth, which is an instance of the mainflux.AuthServiceClient. This change allows the endpoint to verify the user's authentication before returning the list of messages. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --------- Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
758 lines
22 KiB
Go
758 lines
22 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package api_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/mainflux/mainflux"
|
|
authmocks "github.com/mainflux/mainflux/auth/mocks"
|
|
"github.com/mainflux/mainflux/internal/apiutil"
|
|
"github.com/mainflux/mainflux/internal/testsutil"
|
|
"github.com/mainflux/mainflux/pkg/transformers/senml"
|
|
"github.com/mainflux/mainflux/readers"
|
|
"github.com/mainflux/mainflux/readers/api"
|
|
"github.com/mainflux/mainflux/readers/mocks"
|
|
thmocks "github.com/mainflux/mainflux/things/mocks"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
const (
|
|
svcName = "test-service"
|
|
thingToken = "1"
|
|
userToken = "token"
|
|
email = "user@example.com"
|
|
invalid = "invalid"
|
|
numOfMessages = 100
|
|
valueFields = 5
|
|
subtopic = "topic"
|
|
mqttProt = "mqtt"
|
|
httpProt = "http"
|
|
msgName = "temperature"
|
|
instanceID = "5de9b29a-feb9-11ed-be56-0242ac120002"
|
|
)
|
|
|
|
var (
|
|
v float64 = 5
|
|
vs = "value"
|
|
vb = true
|
|
vd = "dataValue"
|
|
sum float64 = 42
|
|
)
|
|
|
|
func newServer(repo readers.MessageRepository, ac *authmocks.Service, tc *thmocks.Service) *httptest.Server {
|
|
mux := api.MakeHandler(repo, ac, tc, svcName, instanceID)
|
|
return httptest.NewServer(mux)
|
|
}
|
|
|
|
type testRequest struct {
|
|
client *http.Client
|
|
method string
|
|
url string
|
|
token string
|
|
key string
|
|
}
|
|
|
|
func (tr testRequest) make() (*http.Response, error) {
|
|
req, err := http.NewRequest(tr.method, tr.url, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if tr.token != "" {
|
|
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
|
}
|
|
if tr.key != "" {
|
|
req.Header.Set("Authorization", apiutil.ThingPrefix+tr.key)
|
|
}
|
|
|
|
return tr.client.Do(req)
|
|
}
|
|
|
|
func TestReadAll(t *testing.T) {
|
|
chanID := testsutil.GenerateUUID(t)
|
|
pubID := testsutil.GenerateUUID(t)
|
|
pubID2 := testsutil.GenerateUUID(t)
|
|
|
|
now := time.Now().Unix()
|
|
|
|
var messages []senml.Message
|
|
var queryMsgs []senml.Message
|
|
var valueMsgs []senml.Message
|
|
var boolMsgs []senml.Message
|
|
var stringMsgs []senml.Message
|
|
var dataMsgs []senml.Message
|
|
|
|
for i := 0; i < numOfMessages; i++ {
|
|
// Mix possible values as well as value sum.
|
|
msg := senml.Message{
|
|
Channel: chanID,
|
|
Publisher: pubID,
|
|
Protocol: mqttProt,
|
|
Time: float64(now - int64(i)),
|
|
Name: "name",
|
|
}
|
|
|
|
count := i % valueFields
|
|
switch count {
|
|
case 0:
|
|
msg.Value = &v
|
|
valueMsgs = append(valueMsgs, msg)
|
|
case 1:
|
|
msg.BoolValue = &vb
|
|
boolMsgs = append(boolMsgs, msg)
|
|
case 2:
|
|
msg.StringValue = &vs
|
|
stringMsgs = append(stringMsgs, msg)
|
|
case 3:
|
|
msg.DataValue = &vd
|
|
dataMsgs = append(dataMsgs, msg)
|
|
case 4:
|
|
msg.Sum = &sum
|
|
msg.Subtopic = subtopic
|
|
msg.Protocol = httpProt
|
|
msg.Publisher = pubID2
|
|
msg.Name = msgName
|
|
queryMsgs = append(queryMsgs, msg)
|
|
}
|
|
|
|
messages = append(messages, msg)
|
|
}
|
|
|
|
repo := mocks.NewMessageRepository(chanID, fromSenml(messages))
|
|
auth := new(authmocks.Service)
|
|
tauth := new(thmocks.Service)
|
|
ts := newServer(repo, auth, tauth)
|
|
defer ts.Close()
|
|
|
|
cases := []struct {
|
|
desc string
|
|
req string
|
|
url string
|
|
token string
|
|
key string
|
|
status int
|
|
res pageRes
|
|
}{
|
|
{
|
|
desc: "read page with valid offset and limit",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with valid offset and limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with negative offset as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=-1&limit=10", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with negative limit as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=-10", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with zero limit as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=0", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with non-integer offset as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=abc&limit=10", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with non-integer limit as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=abc", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with invalid channel id as thing",
|
|
url: fmt.Sprintf("%s/channels//messages?offset=0&limit=10", ts.URL),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with invalid token as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: authmocks.InvalidValue,
|
|
status: http.StatusUnauthorized,
|
|
},
|
|
{
|
|
desc: "read page with multiple offset as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with multiple limit as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with empty token as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: "",
|
|
status: http.StatusUnauthorized,
|
|
},
|
|
{
|
|
desc: "read page with default offset as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?limit=10", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with default limit as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with senml format as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?format=messages", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with subtopic as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with subtopic and protocol as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with publisher as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?publisher=%s", ts.URL, chanID, pubID2),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with protocol as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?protocol=http", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with name as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?name=%s", ts.URL, chanID, msgName),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f", ts.URL, chanID, v),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and equal comparator as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v, readers.EqualKey),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and lower-than comparator as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanKey),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and lower-than-or-equal comparator as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanEqualKey),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and greater-than comparator as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanKey),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and greater-than-or-equal comparator as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanEqualKey),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with non-float value as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=ab01", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with value and wrong comparator as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, chanID, v-1),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with boolean value as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vb=true", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(boolMsgs)),
|
|
Messages: boolMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with non-boolean value as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vb=yes", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with string value as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vs=%s", ts.URL, chanID, vs),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(stringMsgs)),
|
|
Messages: stringMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with data value as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vd=%s", ts.URL, chanID, vd),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(dataMsgs)),
|
|
Messages: dataMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with non-float from as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?from=ABCD", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
|
|
{
|
|
desc: "read page with non-float to as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?to=ABCD", ts.URL, chanID),
|
|
key: thingToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with from/to as thing",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
|
key: thingToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages[5:20])),
|
|
Messages: messages[5:15],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with valid offset and limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with negative offset as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=-1&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with negative limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=-10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with zero limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=0", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with non-integer offset as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=abc&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with non-integer limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=abc", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with invalid channel id as user",
|
|
url: fmt.Sprintf("%s/channels//messages?offset=0&limit=10", ts.URL),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with invalid token as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: authmocks.InvalidValue,
|
|
status: http.StatusUnauthorized,
|
|
},
|
|
{
|
|
desc: "read page with multiple offset as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with multiple limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with empty token as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
|
token: "",
|
|
status: http.StatusUnauthorized,
|
|
},
|
|
{
|
|
desc: "read page with default offset as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?limit=10", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with default limit as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?offset=0", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with senml format as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?format=messages", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages)),
|
|
Messages: messages[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with subtopic as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with subtopic and protocol as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with publisher as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?publisher=%s", ts.URL, chanID, pubID2),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with protocol as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?protocol=http", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with name as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?name=%s", ts.URL, chanID, msgName),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(queryMsgs)),
|
|
Messages: queryMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f", ts.URL, chanID, v),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and equal comparator as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v, readers.EqualKey),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and lower-than comparator as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanKey),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and lower-than-or-equal comparator as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanEqualKey),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and greater-than comparator as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanKey),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with value and greater-than-or-equal comparator as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanEqualKey),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(valueMsgs)),
|
|
Messages: valueMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with non-float value as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=ab01", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with value and wrong comparator as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, chanID, v-1),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with boolean value as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vb=true", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(boolMsgs)),
|
|
Messages: boolMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with non-boolean value as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vb=yes", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with string value as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vs=%s", ts.URL, chanID, vs),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(stringMsgs)),
|
|
Messages: stringMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with data value as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?vd=%s", ts.URL, chanID, vd),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(dataMsgs)),
|
|
Messages: dataMsgs[0:10],
|
|
},
|
|
},
|
|
{
|
|
desc: "read page with non-float from as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?from=ABCD", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with non-float to as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?to=ABCD", ts.URL, chanID),
|
|
token: userToken,
|
|
status: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "read page with from/to as user",
|
|
url: fmt.Sprintf("%s/channels/%s/messages?from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
|
token: userToken,
|
|
status: http.StatusOK,
|
|
res: pageRes{
|
|
Total: uint64(len(messages[5:20])),
|
|
Messages: messages[5:15],
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := auth.On("Identify", mock.Anything, mock.Anything).Return(&mainflux.IdentityRes{Id: testsutil.GenerateUUID(t)}, nil)
|
|
repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&mainflux.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, nil)
|
|
if tc.key != "" {
|
|
repoCall1 = tauth.On("Authorize", mock.Anything, mock.Anything).Return(&mainflux.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, nil)
|
|
}
|
|
req := testRequest{
|
|
client: ts.Client(),
|
|
method: http.MethodGet,
|
|
url: tc.url,
|
|
token: tc.token,
|
|
key: tc.key,
|
|
}
|
|
res, err := req.make()
|
|
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
|
|
|
var page pageRes
|
|
err = json.NewDecoder(res.Body).Decode(&page)
|
|
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err))
|
|
|
|
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
|
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.status, res.StatusCode))
|
|
assert.Equal(t, tc.res.Total, page.Total, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.res.Total, page.Total))
|
|
assert.ElementsMatch(t, tc.res.Messages, page.Messages, fmt.Sprintf("%s: got incorrect body from response", tc.desc))
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
type pageRes struct {
|
|
readers.PageMetadata
|
|
Total uint64 `json:"total"`
|
|
Messages []senml.Message `json:"messages,omitempty"`
|
|
}
|
|
|
|
func fromSenml(in []senml.Message) []readers.Message {
|
|
var ret []readers.Message
|
|
for _, m := range in {
|
|
ret = append(ret, m)
|
|
}
|
|
return ret
|
|
}
|