1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-26 13:48:53 +08:00
Mainflux.mainflux/ws/api/endpoint_test.go
b1ackd0t e6f34e1546
NOISSUE - Fix WS Tests (#1927)
* feat(testsutil): Add function to generate random UUID

This commit adds a new function to the `common.go` file in the `testsutil` package. The function `GenerateRandomUUID` generates a random UUID using the `github.com/mainflux/mainflux/pkg/uuid` package. This function will be used in tests to generate unique identifiers for testing purposes.

The function is added to the existing `common.go` file in the `testsutil` package, which is used for common utilities in tests.

This change improves the testability of the codebase by providing a convenient way to generate random UUIDs for testing purposes.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(auth): add error constants

This commit adds two error constants, InvalidID and InvalidToken, to the auth package. These constants will be used to represent invalid ID and token values in the authentication service.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(ws): add validation for empty message payload

This commit adds a validation check for an empty message payload in the Publish method of the adapterService struct in the ws/adapter.go file. If the payload is empty, the method will now return an ErrFailedMessagePublish error. This validation ensures that only non-empty payloads are published.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(auth): add constant for invalid value

Added a constant named InvalidValue to the auth/mocks/service.go file. This constant is set to "invalid" and will be used to represent an invalid value in the codebase.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

---------

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
2023-10-18 22:40:55 +02:00

194 lines
5.0 KiB
Go

// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
package api_test
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/gorilla/websocket"
"github.com/mainflux/mainflux"
authmocks "github.com/mainflux/mainflux/auth/mocks"
"github.com/mainflux/mainflux/internal/testsutil"
mflog "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/ws"
"github.com/mainflux/mainflux/ws/api"
"github.com/mainflux/mainflux/ws/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
const (
chanID = "30315311-56ba-484d-b500-c1e08305511f"
id = "1"
thingKey = "c02ff576-ccd5-40f6-ba5f-c85377aad529"
protocol = "ws"
instanceID = "5de9b29a-feb9-11ed-be56-0242ac120002"
)
var msg = []byte(`[{"n":"current","t":-1,"v":1.6}]`)
func newService() (ws.Service, mocks.MockPubSub, *authmocks.Service) {
auth := new(authmocks.Service)
pubsub := mocks.NewPubSub()
return ws.New(auth, pubsub), pubsub, auth
}
func newHTTPServer(svc ws.Service) *httptest.Server {
logger := mflog.NewMock()
mux := api.MakeHandler(context.Background(), svc, logger, instanceID)
return httptest.NewServer(mux)
}
func makeURL(tsURL, chanID, subtopic, thingKey string, header bool) (string, error) {
u, _ := url.Parse(tsURL)
u.Scheme = protocol
if chanID == "0" || chanID == "" {
if header {
return fmt.Sprintf("%s/channels/%s/messages", u, chanID), fmt.Errorf("invalid channel id")
}
return fmt.Sprintf("%s/channels/%s/messages?authorization=%s", u, chanID, thingKey), fmt.Errorf("invalid channel id")
}
subtopicPart := ""
if subtopic != "" {
subtopicPart = fmt.Sprintf("/%s", subtopic)
}
if header {
return fmt.Sprintf("%s/channels/%s/messages%s", u, chanID, subtopicPart), nil
}
return fmt.Sprintf("%s/channels/%s/messages%s?authorization=%s", u, chanID, subtopicPart, thingKey), nil
}
func handshake(tsURL, chanID, subtopic, thingKey string, addHeader bool) (*websocket.Conn, *http.Response, error) {
header := http.Header{}
if addHeader {
header.Add("Authorization", thingKey)
}
url, _ := makeURL(tsURL, chanID, subtopic, thingKey, addHeader)
conn, res, errRet := websocket.DefaultDialer.Dial(url, header)
return conn, res, errRet
}
func TestHandshake(t *testing.T) {
svc, _, auth := newService()
ts := newHTTPServer(svc)
defer ts.Close()
cases := []struct {
desc string
chanID string
subtopic string
header bool
thingKey string
status int
err error
msg []byte
}{
{
desc: "connect and send message",
chanID: id,
subtopic: "",
header: true,
thingKey: thingKey,
status: http.StatusSwitchingProtocols,
msg: msg,
},
{
desc: "connect and send message with thingKey as query parameter",
chanID: id,
subtopic: "",
header: false,
thingKey: thingKey,
status: http.StatusSwitchingProtocols,
msg: msg,
},
{
desc: "connect and send message that cannot be published",
chanID: id,
subtopic: "",
header: true,
thingKey: thingKey,
status: http.StatusSwitchingProtocols,
msg: []byte{},
},
{
desc: "connect and send message to subtopic",
chanID: id,
subtopic: "subtopic",
header: true,
thingKey: thingKey,
status: http.StatusSwitchingProtocols,
msg: msg,
},
{
desc: "connect and send message to nested subtopic",
chanID: id,
subtopic: "subtopic/nested",
header: true,
thingKey: thingKey,
status: http.StatusSwitchingProtocols,
msg: msg,
},
{
desc: "connect and send message to all subtopics",
chanID: id,
subtopic: ">",
header: true,
thingKey: thingKey,
status: http.StatusSwitchingProtocols,
msg: msg,
},
{
desc: "connect to empty channel",
chanID: "",
subtopic: "",
header: true,
thingKey: thingKey,
status: http.StatusBadRequest,
msg: []byte{},
},
{
desc: "connect with empty thingKey",
chanID: id,
subtopic: "",
header: true,
thingKey: "",
status: http.StatusForbidden,
msg: []byte{},
},
{
desc: "connect and send message to subtopic with invalid name",
chanID: id,
subtopic: "sub/a*b/topic",
header: true,
thingKey: thingKey,
status: http.StatusBadRequest,
msg: msg,
},
}
for _, tc := range cases {
repocall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&mainflux.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, nil)
conn, res, err := handshake(ts.URL, tc.chanID, tc.subtopic, tc.thingKey, tc.header)
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code '%d' got '%d'\n", tc.desc, tc.status, res.StatusCode))
if tc.status == http.StatusSwitchingProtocols {
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s\n", tc.desc, err))
err = conn.WriteMessage(websocket.TextMessage, tc.msg)
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s\n", tc.desc, err))
}
repocall.Unset()
}
}