MF-1718 - Use static code analysis in CI (#1729)

* things, twins, and logger lint fixed

Signed-off-by: aryan <aryangodara03@gmail.com>

* all services updated, auth jwt not working, ineffectual assignment issue

Signed-off-by: aryan <aryangodara03@gmail.com>

* handle error from grpc server in endpointtest

Signed-off-by: aryan <aryangodara03@gmail.com>

* temp commit, auth/jwt needs to be resolved

Signed-off-by: aryan <aryangodara03@gmail.com>

* revert back to jwt v4 temporarily

Signed-off-by: aryan <aryangodara03@gmail.com>

* updated jwt tokenizer

Signed-off-by: aryan <aryangodara03@gmail.com>

* resolve EOF error for httptest requests

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix auth jwt, update to registeredclaims

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix ineffective assignment, auth/api/grpc endpoint failing

Signed-off-by: aryan <aryangodara03@gmail.com>

* temp commit, remove later

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix grpc server setup

Signed-off-by: aryan <aryangodara03@gmail.com>

* resolve golangci tests, remove debug statements

Signed-off-by: aryan <aryangodara03@gmail.com>

* update golangci version and modify linters used

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix failing tests

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix grpc server for setup tests

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix logging and errors inlined

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix remarks, update grpc setup_test

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix setup_test

Signed-off-by: aryan <aryangodara03@gmail.com>

* update setup_test grpc

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix data race

Signed-off-by: aryan <aryangodara03@gmail.com>

* update setup_test grpc

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix grpc setup down to single simple function

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix linting issues

Signed-off-by: aryan <aryangodara03@gmail.com>

* resolve pr comments

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix tests, handle returned errors, go mod tidy vendor

Signed-off-by: aryan <aryangodara03@gmail.com>

* fix errors from new linters

Signed-off-by: aryan <aryangodara03@gmail.com>

---------

Signed-off-by: aryan <aryangodara03@gmail.com>
This commit is contained in:
Aryan Godara
2023-04-22 08:14:35 -07:00
committed by GitHub
parent 7948aa72e8
commit 54c7518316
79 changed files with 463 additions and 308 deletions
+18 -30
View File
@@ -6,15 +6,12 @@ package grpc_test
import (
"context"
"fmt"
"net"
"testing"
"time"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/auth"
grpcapi "github.com/mainflux/mainflux/auth/api/grpc"
"github.com/mainflux/mainflux/auth/jwt"
"github.com/mainflux/mainflux/auth/mocks"
"github.com/mainflux/mainflux/pkg/uuid"
"github.com/opentracing/opentracing-go/mocktracer"
"github.com/stretchr/testify/assert"
@@ -44,30 +41,11 @@ const (
var svc auth.Service
func newService() auth.Service {
repo := mocks.NewKeyRepository()
groupRepo := mocks.NewGroupRepository()
idProvider := uuid.NewMock()
mockAuthzDB := map[string][]mocks.MockSubjectSet{}
mockAuthzDB[id] = append(mockAuthzDB[id], mocks.MockSubjectSet{Object: authoritiesObj, Relation: memberRelation})
ketoMock := mocks.NewKetoMock(mockAuthzDB)
t := jwt.New(secret)
return auth.New(repo, groupRepo, idProvider, t, ketoMock, loginDuration)
}
func startGRPCServer(svc auth.Service, port int) {
listener, _ := net.Listen("tcp", fmt.Sprintf(":%d", port))
server := grpc.NewServer()
mainflux.RegisterAuthServiceServer(server, grpcapi.NewServer(mocktracer.New(), svc))
go server.Serve(listener)
}
func TestIssue(t *testing.T) {
authAddr := fmt.Sprintf("localhost:%d", port)
conn, _ := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err, fmt.Sprintf("got unexpected error while creating client connection: %s", err))
client := grpcapi.NewClient(mocktracer.New(), conn, time.Second)
cases := []struct {
@@ -139,7 +117,9 @@ func TestIdentify(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Issuing API key expected to succeed: %s", err))
authAddr := fmt.Sprintf("localhost:%d", port)
conn, _ := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err, fmt.Sprintf("got unexpected error while creating client connection: %s", err))
client := grpcapi.NewClient(mocktracer.New(), conn, time.Second)
cases := []struct {
@@ -202,7 +182,9 @@ func TestAuthorize(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err))
authAddr := fmt.Sprintf("localhost:%d", port)
conn, _ := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err, fmt.Sprintf("got unexpected error while creating client connection: %s", err))
client := grpcapi.NewClient(mocktracer.New(), conn, time.Second)
cases := []struct {
@@ -283,7 +265,9 @@ func TestAddPolicy(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err))
authAddr := fmt.Sprintf("localhost:%d", port)
conn, _ := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err, fmt.Sprintf("got unexpected error while creating client connection: %s", err))
client := grpcapi.NewClient(mocktracer.New(), conn, time.Second)
groupAdminObj := "groupadmin"
@@ -336,7 +320,9 @@ func TestDeletePolicy(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err))
authAddr := fmt.Sprintf("localhost:%d", port)
conn, _ := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err, fmt.Sprintf("got unexpected error while creating client connection: %s", err))
client := grpcapi.NewClient(mocktracer.New(), conn, time.Second)
readRelation := "read"
@@ -452,7 +438,9 @@ func TestMembers(t *testing.T) {
}
authAddr := fmt.Sprintf("localhost:%d", port)
conn, _ := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err, fmt.Sprintf("got unexpected error while creating client connection: %s", err))
client := grpcapi.NewClient(mocktracer.New(), conn, time.Second)
for _, tc := range cases {
+46 -1
View File
@@ -4,15 +4,60 @@
package grpc_test
import (
"fmt"
"log"
"net"
"os"
"testing"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/auth"
grpcapi "github.com/mainflux/mainflux/auth/api/grpc"
"github.com/mainflux/mainflux/auth/jwt"
"github.com/mainflux/mainflux/auth/mocks"
"github.com/mainflux/mainflux/pkg/uuid"
"github.com/opentracing/opentracing-go/mocktracer"
"google.golang.org/grpc"
)
func TestMain(m *testing.M) {
serverErr := make(chan error)
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("got unexpected error while creating new listerner: %s", err)
}
svc = newService()
startGRPCServer(svc, port)
server := grpc.NewServer()
mainflux.RegisterAuthServiceServer(server, grpcapi.NewServer(mocktracer.New(), svc))
// Start gRPC server in detached mode.
go func() {
serverErr <- server.Serve(listener)
}()
code := m.Run()
server.GracefulStop()
err = <-serverErr
if err != nil {
log.Fatalln("gPRC Server Terminated : ", err)
}
close(serverErr)
os.Exit(code)
}
func newService() auth.Service {
repo := mocks.NewKeyRepository()
groupRepo := mocks.NewGroupRepository()
idProvider := uuid.NewMock()
mockAuthzDB := map[string][]mocks.MockSubjectSet{}
mockAuthzDB[id] = append(mockAuthzDB[id], mocks.MockSubjectSet{Object: authoritiesObj, Relation: memberRelation})
ketoMock := mocks.NewKetoMock(mockAuthzDB)
tokenizer := jwt.New(secret)
return auth.New(repo, groupRepo, idProvider, tokenizer, ketoMock, loginDuration)
}
+1
View File
@@ -45,6 +45,7 @@ type testRequest struct {
func (tr testRequest) make() (*http.Response, error) {
req, err := http.NewRequest(tr.method, tr.url, tr.body)
req.Close = true
if err != nil {
return nil, err
}
+14 -11
View File
@@ -14,7 +14,7 @@ import (
const issuerName = "mainflux.auth"
type claims struct {
jwt.StandardClaims
jwt.RegisteredClaims
IssuerID string `json:"issuer_id,omitempty"`
Type *uint32 `json:"type,omitempty"`
}
@@ -24,7 +24,7 @@ func (c claims) Valid() error {
return errors.ErrMalformedEntity
}
return c.StandardClaims.Valid()
return c.RegisteredClaims.Valid()
}
type tokenizer struct {
@@ -38,20 +38,20 @@ func New(secret string) auth.Tokenizer {
func (svc tokenizer) Issue(key auth.Key) (string, error) {
claims := claims{
StandardClaims: jwt.StandardClaims{
RegisteredClaims: jwt.RegisteredClaims{
Issuer: issuerName,
Subject: key.Subject,
IssuedAt: key.IssuedAt.UTC().Unix(),
IssuedAt: &jwt.NumericDate{Time: key.IssuedAt.UTC()},
},
IssuerID: key.IssuerID,
Type: &key.Type,
}
if !key.ExpiresAt.IsZero() {
claims.ExpiresAt = key.ExpiresAt.UTC().Unix()
claims.ExpiresAt = &jwt.NumericDate{Time: key.ExpiresAt.UTC()}
}
if key.ID != "" {
claims.Id = key.ID
claims.ID = key.ID
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
@@ -70,6 +70,7 @@ func (svc tokenizer) Parse(token string) (auth.Key, error) {
if err != nil {
if e, ok := err.(*jwt.ValidationError); ok && e.Errors == jwt.ValidationErrorExpired {
// Expired User key needs to be revoked.
if c.Type != nil && *c.Type == auth.APIKey {
return c.toKey(), auth.ErrAPIKeyExpired
}
@@ -83,18 +84,20 @@ func (svc tokenizer) Parse(token string) (auth.Key, error) {
func (c claims) toKey() auth.Key {
key := auth.Key{
ID: c.Id,
ID: c.ID,
IssuerID: c.IssuerID,
Subject: c.Subject,
IssuedAt: time.Unix(c.IssuedAt, 0).UTC(),
IssuedAt: c.IssuedAt.Time.UTC(),
}
if c.ExpiresAt != 0 {
key.ExpiresAt = time.Unix(c.ExpiresAt, 0).UTC()
key.ExpiresAt = time.Time{}
if c.ExpiresAt != nil && c.ExpiresAt.Time.UTC().Unix() != 0 {
key.ExpiresAt = c.ExpiresAt.Time.UTC()
}
// Default type is 0.
if c.Type != nil {
key.Type = *c.Type
key.Type = *(c.Type)
}
return key
+1 -1
View File
@@ -22,7 +22,7 @@ var (
)
const (
// LoginKey is temporary User key received on successfull login.
// LoginKey is temporary User key received on successful login.
LoginKey uint32 = iota
// RecoveryKey represents a key for resseting password.
RecoveryKey
+10 -2
View File
@@ -440,7 +440,11 @@ func (gr groupRepository) Assign(ctx context.Context, groupID, groupType string,
dbg.UpdatedAt = created
if _, err := tx.NamedExecContext(ctx, qIns, dbg); err != nil {
tx.Rollback()
if rollbackErr := tx.Rollback(); rollbackErr != nil {
err = errors.Wrap(err, rollbackErr)
return errors.Wrap(auth.ErrAssignToGroup, err)
}
pgErr, ok := err.(*pgconn.PgError)
if ok {
switch pgErr.Code {
@@ -479,7 +483,11 @@ func (gr groupRepository) Unassign(ctx context.Context, groupID string, ids ...s
}
if _, err := tx.NamedExecContext(ctx, qDel, dbg); err != nil {
tx.Rollback()
if rollbackErr := tx.Rollback(); rollbackErr != nil {
err = errors.Wrap(rollbackErr, err)
return errors.Wrap(auth.ErrAssignToGroup, err)
}
pgErr, ok := err.(*pgconn.PgError)
if ok {
switch pgErr.Code {
+1 -1
View File
@@ -154,7 +154,7 @@ func TestGroupRetrieveByID(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
assert.True(t, retrieved.ID == group1.ID, fmt.Sprintf("Save group, ID: expected %s got %s\n", group1.ID, retrieved.ID))
// Round to milliseconds as otherwise saving and retriving from DB
// Round to milliseconds as otherwise saving and retrieving from DB
// adds rounding error.
creationTime := time.Now().UTC().Round(time.Millisecond)
group2 := auth.Group{
+2 -2
View File
@@ -183,7 +183,7 @@ func (svc service) AddPolicies(ctx context.Context, token, object string, subjec
for _, subjectID := range subjectIDs {
for _, relation := range relations {
if err := svc.AddPolicy(ctx, PolicyReq{Object: object, Relation: relation, Subject: subjectID}); err != nil {
errs = errors.Wrap(fmt.Errorf("cannot add '%s' policy on object '%s' for subject '%s': %s", relation, object, subjectID, err), errs)
errs = errors.Wrap(fmt.Errorf("cannot add '%s' policy on object '%s' for subject '%s': %w", relation, object, subjectID, err), errs)
}
}
}
@@ -209,7 +209,7 @@ func (svc service) DeletePolicies(ctx context.Context, token, object string, sub
for _, subjectID := range subjectIDs {
for _, relation := range relations {
if err := svc.DeletePolicy(ctx, PolicyReq{Object: object, Relation: relation, Subject: subjectID}); err != nil {
errs = errors.Wrap(fmt.Errorf("cannot delete '%s' policy on object '%s' for subject '%s': %s", relation, object, subjectID, err), errs)
errs = errors.Wrap(fmt.Errorf("cannot delete '%s' policy on object '%s' for subject '%s': %w", relation, object, subjectID, err), errs)
}
}
}
+6 -5
View File
@@ -26,6 +26,7 @@ const (
id = "testID"
groupName = "mfx"
description = "Description"
read = "read"
memberRelation = "member"
authoritiesObj = "authorities"
@@ -939,8 +940,8 @@ func TestAssign(t *testing.T) {
// check access control policies things members.
subjectSet := fmt.Sprintf("%s:%s#%s", "members", group.ID, memberRelation)
err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: "read", Subject: subjectSet})
assert.Nil(t, err, fmt.Sprintf("entites having an access to group %s must have %s policy on %s: %s", group.ID, "read", mid, err))
err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: read, Subject: subjectSet})
assert.Nil(t, err, fmt.Sprintf("entites having an access to group %s must have %s policy on %s: %s", group.ID, read, mid, err))
err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: "write", Subject: subjectSet})
assert.Nil(t, err, fmt.Sprintf("entites having an access to group %s must have %s policy on %s: %s", group.ID, "write", mid, err))
err = svc.Authorize(context.Background(), auth.PolicyReq{Object: mid, Relation: "delete", Subject: subjectSet})
@@ -1082,7 +1083,7 @@ func TestAddPolicies(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
tmpID := "tmpid"
readPolicy := "read"
readPolicy := read
writePolicy := "write"
deletePolicy := "delete"
@@ -1167,7 +1168,7 @@ func TestDeletePolicies(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
tmpID := "tmpid"
readPolicy := "read"
readPolicy := read
writePolicy := "write"
deletePolicy := "delete"
memberPolicy := "member"
@@ -1253,7 +1254,7 @@ func TestListPolicies(t *testing.T) {
_, apiToken, err := svc.Issue(context.Background(), secret, key)
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
readPolicy := "read"
readPolicy := read
pageLen := 15
// Add arbitrary policies to the user.
+4 -2
View File
@@ -967,7 +967,9 @@ func TestList(t *testing.T) {
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
var body configPage
json.NewDecoder(res.Body).Decode(&body)
err = json.NewDecoder(res.Body).Decode(&body)
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.ElementsMatch(t, tc.res.Configs, body.Configs, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res.Configs, body.Configs))
assert.Equal(t, tc.res.Total, body.Total, fmt.Sprintf("%s: expected response total '%d' got '%d'", tc.desc, tc.res.Total, body.Total))
@@ -1157,7 +1159,7 @@ func TestBootstrap(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
if tc.secure && tc.status == http.StatusOK {
body, err = dec(body)
assert.Nil(t, err, fmt.Sprintf("%sGot unexpected error: %s\n", tc.desc, err))
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding body: %s", tc.desc, err))
}
data := strings.Trim(string(body), "\n")
-4
View File
@@ -83,10 +83,6 @@ func (crm *configRepositoryMock) RetrieveAll(token string, filter bootstrap.Filt
configs := make([]bootstrap.Config, 0)
if offset < 0 || limit <= 0 {
return bootstrap.ConfigsPage{}
}
first := uint64(offset) + 1
last := first + uint64(limit)
var state bootstrap.State = emptyState
+1 -1
View File
@@ -598,7 +598,7 @@ func TestRemoveThing(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
for i := 0; i < 2; i++ {
err := repo.RemoveThing(saved)
assert.Nil(t, err, fmt.Sprintf("an unexpected error occured: %s\n", err))
assert.Nil(t, err, fmt.Sprintf("an unexpected error occurred: %s\n", err))
}
}
+6 -15
View File
@@ -53,7 +53,7 @@ func (es eventStore) Add(ctx context.Context, token string, cfg bootstrap.Config
timestamp: time.Now(),
}
es.add(ctx, ev)
err = es.add(ctx, ev)
return saved, err
}
@@ -74,9 +74,7 @@ func (es eventStore) Update(ctx context.Context, token string, cfg bootstrap.Con
timestamp: time.Now(),
}
es.add(ctx, ev)
return nil
return es.add(ctx, ev)
}
func (es eventStore) UpdateCert(ctx context.Context, token, thingKey, clientCert, clientKey, caCert string) error {
@@ -94,9 +92,7 @@ func (es eventStore) UpdateConnections(ctx context.Context, token, id string, co
timestamp: time.Now(),
}
es.add(ctx, ev)
return nil
return es.add(ctx, ev)
}
func (es eventStore) List(ctx context.Context, token string, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
@@ -113,9 +109,7 @@ func (es eventStore) Remove(ctx context.Context, token, id string) error {
timestamp: time.Now(),
}
es.add(ctx, ev)
return nil
return es.add(ctx, ev)
}
func (es eventStore) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (bootstrap.Config, error) {
@@ -130,8 +124,7 @@ func (es eventStore) Bootstrap(ctx context.Context, externalKey, externalID stri
if err != nil {
ev.success = false
}
es.add(ctx, ev)
_ = es.add(ctx, ev)
return cfg, err
}
@@ -147,9 +140,7 @@ func (es eventStore) ChangeState(ctx context.Context, token, id string, state bo
timestamp: time.Now(),
}
es.add(ctx, ev)
return nil
return es.add(ctx, ev)
}
func (es eventStore) RemoveConfigHandler(ctx context.Context, id string) error {
+37 -22
View File
@@ -25,6 +25,7 @@ import (
"github.com/mainflux/mainflux/things"
httpapi "github.com/mainflux/mainflux/things/api/things/http"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
@@ -92,7 +93,9 @@ func newThingsServer(svc things.Service) *httptest.Server {
return httptest.NewServer(mux)
}
func TestAdd(t *testing.T) {
redisClient.FlushAll(context.Background()).Err()
err := redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
users := mocks.NewAuthClient(map[string]string{validToken: email})
server := newThingsServer(newThingsService(users))
@@ -106,6 +109,7 @@ func TestAdd(t *testing.T) {
invalidConfig := config
invalidConfig.MFChannels = []bootstrap.Channel{{ID: "empty"}}
invalidConfig.MFChannels = []bootstrap.Channel{{ID: "empty"}}
cases := []struct {
desc string
@@ -179,7 +183,8 @@ func TestView(t *testing.T) {
}
func TestUpdate(t *testing.T) {
redisClient.FlushAll(context.Background()).Err()
err := redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
users := mocks.NewAuthClient(map[string]string{validToken: email})
server := newThingsServer(newThingsService(users))
@@ -192,8 +197,10 @@ func TestUpdate(t *testing.T) {
ch.ID = "2"
c.MFChannels = append(c.MFChannels, ch)
saved, err := svc.Add(context.Background(), validToken, c)
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
redisClient.FlushAll(context.Background()).Err()
require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
err = redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
modified := saved
modified.Content = "new-config"
@@ -254,7 +261,8 @@ func TestUpdate(t *testing.T) {
}
func TestUpdateConnections(t *testing.T) {
redisClient.FlushAll(context.Background()).Err()
err := redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
users := mocks.NewAuthClient(map[string]string{validToken: email})
server := newThingsServer(newThingsService(users))
@@ -262,8 +270,9 @@ func TestUpdateConnections(t *testing.T) {
svc = producer.NewEventStoreMiddleware(svc, redisClient)
saved, err := svc.Add(context.Background(), validToken, config)
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
redisClient.FlushAll(context.Background()).Err()
require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
err = redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
cases := []struct {
desc string
@@ -336,7 +345,8 @@ func TestList(t *testing.T) {
}
func TestRemove(t *testing.T) {
redisClient.FlushAll(context.Background()).Err()
err := redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
users := mocks.NewAuthClient(map[string]string{validToken: email})
server := newThingsServer(newThingsService(users))
@@ -346,8 +356,9 @@ func TestRemove(t *testing.T) {
c := config
saved, err := svc.Add(context.Background(), validToken, c)
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
redisClient.FlushAll(context.Background()).Err()
require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
err = redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
cases := []struct {
desc string
@@ -399,7 +410,8 @@ func TestRemove(t *testing.T) {
}
func TestBootstrap(t *testing.T) {
redisClient.FlushAll(context.Background()).Err()
err := redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
users := mocks.NewAuthClient(map[string]string{validToken: email})
server := newThingsServer(newThingsService(users))
@@ -409,8 +421,9 @@ func TestBootstrap(t *testing.T) {
c := config
saved, err := svc.Add(context.Background(), validToken, c)
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
redisClient.FlushAll(context.Background()).Err()
require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
err = redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
cases := []struct {
desc string
@@ -434,10 +447,10 @@ func TestBootstrap(t *testing.T) {
{
desc: "bootstrap with an error",
externalID: saved.ExternalID,
externalKey: "external",
externalKey: "external_id",
err: bootstrap.ErrExternalKey,
event: map[string]interface{}{
"external_id": saved.ExternalID,
"external_id": "external_id",
"success": "0",
"timestamp": time.Now().Unix(),
"operation": thingBootstrap,
@@ -447,7 +460,7 @@ func TestBootstrap(t *testing.T) {
lastID := "0"
for _, tc := range cases {
_, err := svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, false)
_, err = svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, false)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(context.Background(), &redis.XReadArgs{
@@ -462,13 +475,13 @@ func TestBootstrap(t *testing.T) {
event = msg.Values
lastID = msg.ID
}
test(t, tc.event, event, tc.desc)
}
}
func TestChangeState(t *testing.T) {
redisClient.FlushAll(context.Background()).Err()
err := redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
users := mocks.NewAuthClient(map[string]string{validToken: email})
server := newThingsServer(newThingsService(users))
@@ -478,8 +491,9 @@ func TestChangeState(t *testing.T) {
c := config
saved, err := svc.Add(context.Background(), validToken, c)
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
redisClient.FlushAll(context.Background()).Err()
require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
err = redisClient.FlushAll(context.Background()).Err()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
cases := []struct {
desc string
@@ -537,14 +551,15 @@ func TestChangeState(t *testing.T) {
func test(t *testing.T, expected, actual map[string]interface{}, description string) {
if expected != nil && actual != nil {
ts1 := expected["timestamp"].(int64)
ts2, err := strconv.ParseInt(actual["timestamp"].(string), 10, 64)
assert.Nil(t, err, fmt.Sprintf("%s: expected to get a valid timestamp, got %s", description, err))
require.Nil(t, err, fmt.Sprintf("%s: expected to get a valid timestamp, got %s", description, err))
val := ts1 == ts2 || ts2 <= ts1+defaultTimout
assert.True(t, val, fmt.Sprintf("%s: timestamp is not in valid range", description))
delete(expected, "timestamp")
delete(actual, "timestamp")
assert.Equal(t, expected, actual, fmt.Sprintf("%s: expected %v got %v\n", description, expected, actual))
assert.Equal(t, expected, actual, fmt.Sprintf("%s: got incorrect event\n", description))
}
}
-2
View File
@@ -275,7 +275,6 @@ func (bs bootstrapService) Bootstrap(ctx context.Context, externalKey, externalI
if err != nil {
return cfg, errors.Wrap(ErrBootstrap, err)
}
if secure {
dec, err := bs.dec(externalKey)
if err != nil {
@@ -283,7 +282,6 @@ func (bs bootstrapService) Bootstrap(ctx context.Context, externalKey, externalI
}
externalKey = dec
}
if cfg.ExternalKey != externalKey {
return Config{}, ErrExternalKey
}
+1 -1
View File
@@ -43,7 +43,7 @@ func (c *certsRepoMock) Save(ctx context.Context, cert certs.Cert) (string, erro
switch ok {
case false:
c.certsByThingID[cert.OwnerID] = map[string][]certs.Cert{
cert.ThingID: []certs.Cert{crt},
cert.ThingID: {crt},
}
default:
c.certsByThingID[cert.OwnerID][cert.ThingID] = append(c.certsByThingID[cert.OwnerID][cert.ThingID], crt)
+3 -1
View File
@@ -10,6 +10,8 @@ import (
"github.com/spf13/cobra"
)
const all = "all"
var cmdChannels = []cobra.Command{
{
Use: "create <JSON_channel> <user_auth_token>",
@@ -60,7 +62,7 @@ var cmdChannels = []cobra.Command{
Metadata: metadata,
}
if args[0] == "all" {
if args[0] == all {
l, err := sdk.Channels(pageMetadata, args[1])
if err != nil {
logError(err)
+1 -2
View File
@@ -2,7 +2,6 @@ package cli
import (
"fmt"
"io/ioutil"
"log"
"os"
@@ -19,7 +18,7 @@ type Config struct {
// read - retrieve config from a file
func read(file string) (Config, error) {
data, err := ioutil.ReadFile(file)
data, err := os.ReadFile(file)
c := Config{}
if err != nil {
return c, errors.New(fmt.Sprintf("failed to read config file: %s", err))
+1 -1
View File
@@ -54,7 +54,7 @@ var cmdGroups = []cobra.Command{
logUsage(cmd.Use)
return
}
if args[0] == "all" {
if args[0] == all {
if len(args) > 2 {
logUsage(cmd.Use)
return
+1 -1
View File
@@ -58,7 +58,7 @@ var cmdThings = []cobra.Command{
Limit: uint64(Limit),
Metadata: metadata,
}
if args[0] == "all" {
if args[0] == all {
l, err := sdk.Things(pageMetadata, args[1])
if err != nil {
logError(err)
+1 -1
View File
@@ -60,7 +60,7 @@ var cmdUsers = []cobra.Command{
Metadata: metadata,
Status: Status,
}
if args[0] == "all" {
if args[0] == all {
l, err := sdk.Users(pageMetadata, args[1])
if err != nil {
logError(err)
+1 -1
View File
@@ -88,7 +88,7 @@ func (c *client) Handle(msg *messaging.Message) error {
return errors.Wrap(ErrOption, err)
}
opts = append(opts, message.Option{ID: message.Observe, Value: []byte{byte(c.observe)}})
opts, n, err = opts.SetObserve(buff, uint32(c.observe))
opts, n, err = opts.SetObserve(buff, c.observe)
if err == message.ErrTooSmall {
buff = append(buff, make([]byte, n)...)
opts, _, err = opts.SetObserve(buff, uint32(c.observe))
+1 -1
View File
@@ -15,7 +15,7 @@ require (
github.com/go-zoo/bone v1.3.0
github.com/gocql/gocql v1.2.1
github.com/gofrs/uuid v4.3.0+incompatible
github.com/golang-jwt/jwt/v4 v4.4.2
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/protobuf v1.5.2
github.com/gopcua/opcua v0.1.6
github.com/gorilla/websocket v1.5.0
+2 -2
View File
@@ -217,8 +217,8 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+5 -5
View File
@@ -47,29 +47,29 @@ func New(out io.Writer, levelText string) (Logger, error) {
func (l logger) Debug(msg string) {
if Debug.isAllowed(l.level) {
l.kitLogger.Log("level", Debug.String(), "message", msg)
_ = l.kitLogger.Log("level", Debug.String(), "message", msg)
}
}
func (l logger) Info(msg string) {
if Info.isAllowed(l.level) {
l.kitLogger.Log("level", Info.String(), "message", msg)
_ = l.kitLogger.Log("level", Info.String(), "message", msg)
}
}
func (l logger) Warn(msg string) {
if Warn.isAllowed(l.level) {
l.kitLogger.Log("level", Warn.String(), "message", msg)
_ = l.kitLogger.Log("level", Warn.String(), "message", msg)
}
}
func (l logger) Error(msg string) {
if Error.isAllowed(l.level) {
l.kitLogger.Log("level", Error.String(), "message", msg)
_ = l.kitLogger.Log("level", Error.String(), "message", msg)
}
}
func (l logger) Fatal(msg string) {
l.kitLogger.Log("fatal", msg)
_ = l.kitLogger.Log("fatal", msg)
os.Exit(1)
}
+1 -1
View File
@@ -110,7 +110,7 @@ func (as *adapterService) Publish(ctx context.Context, m *Message) error {
if err != nil {
return err
}
payload = []byte(jo)
payload = jo
}
// Publish on Mainflux Message broker
+6 -5
View File
@@ -13,6 +13,7 @@ import (
"github.com/mainflux/mainflux/lora/mocks"
"github.com/mainflux/mainflux/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
@@ -40,19 +41,19 @@ func TestPublish(t *testing.T) {
svc := newService()
err := svc.CreateChannel(context.Background(), chanID, appID)
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
err = svc.CreateThing(context.Background(), thingID, devEUI)
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
err = svc.ConnectThing(context.Background(), chanID, thingID)
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
err = svc.CreateChannel(context.Background(), chanID2, appID2)
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
err = svc.CreateThing(context.Background(), thingID2, devEUI2)
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
msgBase64 := base64.StdEncoding.EncodeToString([]byte(msg))
+1 -1
View File
@@ -15,7 +15,7 @@ type RxInfo []struct {
// DataRate lora data rate
type DataRate struct {
Modulation string `json:"modulation"`
Bandwith float64 `json:"bandwith"`
Bandwidth float64 `json:"bandwidth"`
SpreadFactor int64 `json:"spreadFactor"`
}
+3 -1
View File
@@ -54,5 +54,7 @@ func (b broker) handleMsg(c mqtt.Client, msg mqtt.Message) {
return
}
b.svc.Publish(context.Background(), &m)
if err := b.svc.Publish(context.Background(), &m); err != nil {
b.logger.Error(fmt.Sprintf("got error while publishing messages: %s", err))
}
}
+1 -5
View File
@@ -33,11 +33,7 @@ func (mr *routerMap) Save(ctx context.Context, mfxID, loraID string) error {
}
lkey := fmt.Sprintf("%s:%s", mr.prefix, loraID)
if err := mr.client.Set(ctx, lkey, mfxID, 0).Err(); err != nil {
return err
}
return nil
return mr.client.Set(ctx, lkey, mfxID, 0).Err()
}
func (mr *routerMap) Get(ctx context.Context, id string) (string, error) {
+1 -1
View File
@@ -3,4 +3,4 @@
// Package redis contains cache implementations using Redis as
// the underlying database.
package redis
package redis
+1 -5
View File
@@ -52,11 +52,7 @@ func (es eventStore) storeEvent(clientID, eventType string) error {
Values: event.Encode(),
}
if err := es.client.XAdd(context.Background(), record).Err(); err != nil {
return err
}
return nil
return es.client.XAdd(context.Background(), record).Err()
}
// Connect issues event on MQTT CONNECT
+5 -2
View File
@@ -28,15 +28,18 @@ type Node struct {
NodeID string
}
// Save stores a successfull subscription
// Save stores a successful subscription
func Save(serverURI, nodeID string) error {
file, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
if err != nil {
return errors.Wrap(errWriteFile, err)
}
csvWriter := csv.NewWriter(file)
csvWriter.Write([]string{serverURI, nodeID})
err = csvWriter.Write([]string{serverURI, nodeID})
csvWriter.Flush()
if err != nil {
return errors.Wrap(errWriteFile, err)
}
return nil
}
+5 -1
View File
@@ -111,7 +111,11 @@ func (c client) Subscribe(ctx context.Context, cfg opcua.Config) error {
if err != nil {
return errors.Wrap(errFailedSub, err)
}
defer sub.Cancel()
defer func() {
if err = sub.Cancel(); err != nil {
c.logger.Error(fmt.Sprintf("subscription could not be cancelled: %s", err))
}
}()
if err := c.runHandler(ctx, sub, cfg.ServerURI, cfg.NodeID); err != nil {
c.logger.Warn(fmt.Sprintf("Unsubscribed from OPC-UA node %s.%s: %s", cfg.ServerURI, cfg.NodeID, err))
+1 -1
View File
@@ -39,7 +39,7 @@ func (c client) Identify(ctx context.Context, thingKey string) (string, error) {
thingID, err := c.redisClient.Get(ctx, tkey).Result()
if err != nil {
t := &mainflux.Token{
Value: string(thingKey),
Value: thingKey,
}
thid, err := c.thingsClient.Identify(context.TODO(), t)
+1 -5
View File
@@ -53,11 +53,7 @@ func (pub *publisher) Publish(ctx context.Context, topic string, msg *messaging.
subject = fmt.Sprintf("%s.%s", subject, msg.Subtopic)
}
if err := pub.conn.Publish(subject, data); err != nil {
return err
}
return nil
return pub.conn.Publish(subject, data)
}
func (pub *publisher) Close() error {
+1 -1
View File
@@ -20,7 +20,7 @@ type keyReq struct {
const keysEndpoint = "keys"
const (
// LoginKey is temporary User key received on successfull login.
// LoginKey is temporary User key received on successful login.
LoginKey uint32 = iota
// RecoveryKey represents a key for resseting password.
RecoveryKey
+3 -1
View File
@@ -733,7 +733,9 @@ func TestReadAll(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var page pageRes
json.NewDecoder(res.Body).Decode(&page)
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))
+6 -6
View File
@@ -74,10 +74,9 @@ func (cr cassandraRepository) ReadAll(chanID string, rpm readers.PageMetadata) (
case defTable:
for scanner.Next() {
var msg senml.Message
err := scanner.Scan(&msg.Channel, &msg.Subtopic, &msg.Publisher, &msg.Protocol,
if err := scanner.Scan(&msg.Channel, &msg.Subtopic, &msg.Publisher, &msg.Protocol,
&msg.Name, &msg.Unit, &msg.Value, &msg.StringValue, &msg.BoolValue,
&msg.DataValue, &msg.Sum, &msg.Time, &msg.UpdateTime)
if err != nil {
&msg.DataValue, &msg.Sum, &msg.Time, &msg.UpdateTime); err != nil {
if e, ok := err.(gocql.RequestError); ok {
if e.Code() == undefinedTableCode {
return readers.MessagesPage{}, nil
@@ -90,8 +89,7 @@ func (cr cassandraRepository) ReadAll(chanID string, rpm readers.PageMetadata) (
default:
for scanner.Next() {
var msg jsonMessage
err := scanner.Scan(&msg.Channel, &msg.Subtopic, &msg.Publisher, &msg.Protocol, &msg.Created, &msg.Payload)
if err != nil {
if err := scanner.Scan(&msg.Channel, &msg.Subtopic, &msg.Publisher, &msg.Protocol, &msg.Created, &msg.Payload); err != nil {
if e, ok := err.(gocql.RequestError); ok {
if e.Code() == undefinedTableCode {
return readers.MessagesPage{}, nil
@@ -128,7 +126,9 @@ func buildQuery(chanID string, rpm readers.PageMetadata) (string, []interface{})
if err != nil {
return condCQL, vals
}
json.Unmarshal(meta, &query)
if err := json.Unmarshal(meta, &query); err != nil {
return condCQL, vals
}
for name, val := range query {
switch name {
+1
View File
@@ -52,6 +52,7 @@ func TestReadSenml(t *testing.T) {
})
require.Nil(t, err, fmt.Sprintf("failed to connect to Cassandra: %s", err))
defer session.Close()
err = casClient.InitDB(session, cwriter.Table)
require.Nil(t, err, fmt.Sprintf("failed to initialize to Cassandra: %s", err))
writer := cwriter.New(session)
+2 -2
View File
@@ -119,8 +119,8 @@ func (repo *influxRepository) count(measurement, condition string, timeRange str
measurement,
condition)
queryAPI := repo.client.QueryAPI(repo.cfg.Org)
resp, err := queryAPI.Query(context.Background(), cmd)
resp, err := queryAPI.Query(context.Background(), cmd)
if err != nil {
return 0, err
}
@@ -168,7 +168,7 @@ func fmtCondition(chanID string, rpm readers.PageMetadata) (string, string) {
toValue := int64(value.(float64) * 1e9)
to = fmt.Sprintf(`, stop: time(v: %d )`, toValue)
}
// timeRange returned seperately because
// timeRange returned separately because
// in FluxQL time range must be at the
// beginning of the query.
timeRange = fmt.Sprintf(`|> range(%s %s)`, from, to)
+7 -2
View File
@@ -39,8 +39,13 @@ func (repo *messageRepositoryMock) ReadAll(chanID string, rpm readers.PageMetada
}
var query map[string]interface{}
meta, _ := json.Marshal(rpm)
json.Unmarshal(meta, &query)
meta, err := json.Marshal(rpm)
if err != nil {
return readers.MessagesPage{}, err
}
if err := json.Unmarshal(meta, &query); err != nil {
return readers.MessagesPage{}, err
}
var msgs []readers.Message
for _, m := range repo.messages[chanID] {
+3 -1
View File
@@ -101,7 +101,9 @@ func fmtCondition(chanID string, rpm readers.PageMetadata) bson.D {
if err != nil {
return filter
}
json.Unmarshal(meta, &query)
if err := json.Unmarshal(meta, &query); err != nil {
return filter
}
for name, value := range query {
switch name {
+3 -1
View File
@@ -123,7 +123,9 @@ func fmtCondition(chanID string, rpm readers.PageMetadata) string {
if err != nil {
return condition
}
json.Unmarshal(meta, &query)
if err := json.Unmarshal(meta, &query); err != nil {
return condition
}
for name := range query {
switch name {
+3 -1
View File
@@ -121,7 +121,9 @@ func fmtCondition(chanID string, rpm readers.PageMetadata) string {
if err != nil {
return condition
}
json.Unmarshal(meta, &query)
if err := json.Unmarshal(meta, &query); err != nil {
return condition
}
for name := range query {
switch name {
+3 -2
View File
@@ -4,6 +4,7 @@ GO_VERSION=1.19.4
PROTOC_VERSION=21.12
PROTOC_GEN_VERSION=v1.28.1
PROTOC_GRPC_VERSION=v1.2.0
GOLANGCI_LINT_VERSION=v1.52.1
function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
@@ -71,7 +72,7 @@ setup_mf() {
setup_lint() {
# binary will be $(go env GOBIN)/golangci-lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOBIN) v1.46.2
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOBIN) $GOLANGCI_LINT_VERSION
}
@@ -85,7 +86,7 @@ setup() {
run_test() {
echo "Running lint..."
golangci-lint run --no-config --disable-all --enable gosimple --enable govet --enable unused --enable deadcode --timeout 3m
golangci-lint run --no-config --disable-all --enable gosimple --enable errcheck --enable govet --enable unused --enable goconst --timeout 3m
echo "Running tests..."
echo "" > coverage.txt
for d in $(go list ./... | grep -v 'vendor\|cmd'); do
+3 -1
View File
@@ -100,7 +100,9 @@ func TestCanAccessByID(t *testing.T) {
chs, err := svc.CreateChannels(context.Background(), token, channel)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
ch := chs[0]
svc.Connect(context.Background(), token, []string{ch.ID}, []string{th2.ID})
err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th2.ID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
usersAddr := fmt.Sprintf("localhost:%d", port)
conn, err := grpc.Dial(usersAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
+22 -7
View File
@@ -5,6 +5,7 @@ package grpc_test
import (
"fmt"
"log"
"net"
"os"
"testing"
@@ -28,17 +29,31 @@ const (
var svc things.Service
func TestMain(m *testing.M) {
startServer()
code := m.Run()
os.Exit(code)
}
serverErr := make(chan error)
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("got unexpected error while creating new listerner: %s", err)
}
func startServer() {
svc = newService(map[string]string{token: email})
listener, _ := net.Listen("tcp", fmt.Sprintf(":%d", port))
server := grpc.NewServer()
mainflux.RegisterThingsServiceServer(server, grpcapi.NewServer(mocktracer.New(), svc))
go server.Serve(listener)
// Start gRPC server in detached mode.
go func() {
serverErr <- server.Serve(listener)
}()
code := m.Run()
server.GracefulStop()
err = <-serverErr
if err != nil {
log.Fatalln("gPRC Server Terminated : ", err)
}
close(serverErr)
os.Exit(code)
}
func newService(tokens map[string]string) things.Service {
+55 -36
View File
@@ -29,17 +29,20 @@ import (
)
const (
contentType = "application/json"
email = "user@example.com"
adminEmail = "admin@example.com"
token = "token"
wrongValue = "wrong_value"
wrongID = 0
maxNameSize = 1024
nameKey = "name"
ascKey = "asc"
descKey = "desc"
prefix = "fe6b4e92-cc98-425e-b0aa-"
contentType = "application/json"
email = "user@example.com"
adminEmail = "admin@example.com"
otherExampleEmail = "other_user@example.com"
token = "token"
otherExampleToken = "other_token"
wrongValue = "wrong_value"
thingKey = "key"
wrongID = 0
maxNameSize = 1024
nameKey = "name"
ascKey = "asc"
descKey = "desc"
prefix = "fe6b4e92-cc98-425e-b0aa-"
)
var (
@@ -116,7 +119,7 @@ func TestCreateThing(t *testing.T) {
defer ts.Close()
th := thing
th.Key = "key"
th.Key = thingKey
data := toJSON(th)
th.Name = invalidName
@@ -956,12 +959,14 @@ func TestListThings(t *testing.T) {
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s", tc.desc, err))
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var data thingsPageRes
json.NewDecoder(res.Body).Decode(&data)
err = json.NewDecoder(res.Body).Decode(&data)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.statusCode, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.statusCode, res.StatusCode))
assert.ElementsMatch(t, tc.res, data.Things, fmt.Sprintf("%s: got incorrect list of things from response body", tc.desc))
assert.ElementsMatch(t, tc.res, data.Things, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, data.Things))
}
}
@@ -1153,12 +1158,14 @@ func TestSearchThings(t *testing.T) {
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s", tc.desc, err))
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var data thingsPageRes
json.NewDecoder(res.Body).Decode(&data)
err = json.NewDecoder(res.Body).Decode(&data)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.statusCode, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.statusCode, res.StatusCode))
assert.ElementsMatch(t, tc.res, data.Things, fmt.Sprintf("%s: got incorrect list of things from response body", tc.desc))
assert.ElementsMatch(t, tc.res, data.Things, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, data.Things))
}
}
@@ -1337,12 +1344,14 @@ func TestListThingsByChannel(t *testing.T) {
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s", tc.desc, err))
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var data thingsPageRes
json.NewDecoder(res.Body).Decode(&data)
err = json.NewDecoder(res.Body).Decode(&data)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.statusCode, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.statusCode, res.StatusCode))
assert.ElementsMatch(t, tc.res, data.Things, fmt.Sprintf("%s: got incorrect list of things from response body", tc.desc))
assert.ElementsMatch(t, tc.res, data.Things, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, data.Things))
}
}
@@ -1725,7 +1734,8 @@ func TestViewChannel(t *testing.T) {
ths, err := svc.CreateThings(context.Background(), token, thing)
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s\n", err))
th := ths[0]
svc.Connect(context.Background(), token, []string{sch.ID}, []string{th.ID})
err = svc.Connect(context.Background(), token, []string{sch.ID}, []string{th.ID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error when connecting to service: %s", err))
data := toJSON(channelRes{
ID: sch.ID,
@@ -1815,7 +1825,8 @@ func TestListChannels(t *testing.T) {
ths, err := svc.CreateThings(context.Background(), token, thing)
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
th := ths[0]
svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
channels = append(channels, channelRes{
ID: ch.ID,
@@ -2006,9 +2017,11 @@ func TestListChannels(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s", tc.desc, err))
var body channelsPageRes
json.NewDecoder(res.Body).Decode(&body)
err = json.NewDecoder(res.Body).Decode(&body)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while deconding response body: %s", tc.desc, err))
assert.Equal(t, tc.statusCode, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.statusCode, res.StatusCode))
assert.ElementsMatch(t, tc.res, body.Channels, fmt.Sprintf("%s: got incorrect list of channels from response body", tc.desc))
assert.ElementsMatch(t, tc.res, body.Channels, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, body.Channels))
}
}
@@ -2186,9 +2199,11 @@ func TestListChannelsByThing(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error %s", tc.desc, err))
var body channelsPageRes
json.NewDecoder(res.Body).Decode(&body)
err = json.NewDecoder(res.Body).Decode(&body)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err))
assert.Equal(t, tc.statusCode, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.statusCode, res.StatusCode))
assert.ElementsMatch(t, tc.res, body.Channels, fmt.Sprintf("%s: got incorrect list of channels from response body", tc.desc))
assert.ElementsMatch(t, tc.res, body.Channels, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, body.Channels))
}
}
@@ -2252,8 +2267,8 @@ func TestRemoveChannel(t *testing.T) {
}
func TestConnect(t *testing.T) {
otherToken := "other_token"
otherEmail := "other_user@example.com"
otherToken := otherExampleToken
otherEmail := otherExampleEmail
svc := newService(map[string]string{
token: email,
otherToken: otherEmail,
@@ -2348,8 +2363,8 @@ func TestConnect(t *testing.T) {
}
func TestCreateConnections(t *testing.T) {
otherToken := "other_token"
otherEmail := "other_user@example.com"
otherToken := otherExampleToken
otherEmail := otherExampleEmail
svc := newService(map[string]string{
token: email,
otherToken: otherEmail,
@@ -2537,8 +2552,8 @@ func TestCreateConnections(t *testing.T) {
}
func TestDisconnectList(t *testing.T) {
otherToken := "other_token"
otherEmail := "other_user@example.com"
otherToken := otherExampleToken
otherEmail := otherExampleEmail
svc := newService(map[string]string{
token: email,
otherToken: otherEmail,
@@ -2730,8 +2745,8 @@ func TestDisconnectList(t *testing.T) {
}
func TestDisconnnect(t *testing.T) {
otherToken := "other_token"
otherEmail := "other_user@example.com"
otherToken := otherExampleToken
otherEmail := otherExampleEmail
svc := newService(map[string]string{
token: email,
otherToken: otherEmail,
@@ -2741,9 +2756,13 @@ func TestDisconnnect(t *testing.T) {
ths, _ := svc.CreateThings(context.Background(), token, thing)
th1 := ths[0]
chs, _ := svc.CreateChannels(context.Background(), token, channel)
ch1 := chs[0]
svc.Connect(context.Background(), token, []string{ch1.ID}, []string{th1.ID})
err := svc.Connect(context.Background(), token, []string{ch1.ID}, []string{th1.ID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
chs, _ = svc.CreateChannels(context.Background(), otherToken, channel)
ch2 := chs[0]
-3
View File
@@ -80,9 +80,6 @@ func (crm *channelRepositoryMock) RetrieveByID(_ context.Context, owner, id stri
}
func (crm *channelRepositoryMock) RetrieveAll(_ context.Context, owner string, pm things.PageMetadata) (things.ChannelsPage, error) {
if pm.Limit < 0 {
return things.ChannelsPage{}, nil
}
if pm.Limit == 0 {
pm.Limit = 10
}
+10 -8
View File
@@ -12,6 +12,8 @@ import (
)
const uuidLen = 36
const asc = "asc"
const desc = "desc"
// Since mocks will store data in map, and they need to resemble the real
// identifiers as much as possible, a key will be created as combination of
@@ -24,23 +26,23 @@ func key(owner string, id string) string {
func sortThings(pm things.PageMetadata, ths []things.Thing) []things.Thing {
switch pm.Order {
case "name":
if pm.Dir == "asc" {
if pm.Dir == asc {
sort.SliceStable(ths, func(i, j int) bool {
return ths[i].Name < ths[j].Name
})
}
if pm.Dir == "desc" {
if pm.Dir == desc {
sort.SliceStable(ths, func(i, j int) bool {
return ths[i].Name > ths[j].Name
})
}
case "id":
if pm.Dir == "asc" {
if pm.Dir == asc {
sort.SliceStable(ths, func(i, j int) bool {
return ths[i].ID < ths[j].ID
})
}
if pm.Dir == "desc" {
if pm.Dir == desc {
sort.SliceStable(ths, func(i, j int) bool {
return ths[i].ID > ths[j].ID
})
@@ -57,23 +59,23 @@ func sortThings(pm things.PageMetadata, ths []things.Thing) []things.Thing {
func sortChannels(pm things.PageMetadata, chs []things.Channel) []things.Channel {
switch pm.Order {
case "name":
if pm.Dir == "asc" {
if pm.Dir == asc {
sort.SliceStable(chs, func(i, j int) bool {
return chs[i].Name < chs[j].Name
})
}
if pm.Dir == "desc" {
if pm.Dir == desc {
sort.SliceStable(chs, func(i, j int) bool {
return chs[i].Name > chs[j].Name
})
}
case "id":
if pm.Dir == "asc" {
if pm.Dir == asc {
sort.SliceStable(chs, func(i, j int) bool {
return chs[i].ID < chs[j].ID
})
}
if pm.Dir == "desc" {
if pm.Dir == desc {
sort.SliceStable(chs, func(i, j int) bool {
return chs[i].ID > chs[j].ID
})
-4
View File
@@ -117,10 +117,6 @@ func (trm *thingRepositoryMock) RetrieveAll(_ context.Context, owner string, pm
trm.mu.Lock()
defer trm.mu.Unlock()
if pm.Limit < 0 {
return things.Page{}, nil
}
first := uint64(pm.Offset) + 1
last := first + uint64(pm.Limit)
+23 -10
View File
@@ -20,6 +20,8 @@ import (
var _ things.ChannelRepository = (*channelRepository)(nil)
const name = "name"
type channelRepository struct {
db Database
}
@@ -52,7 +54,9 @@ func (cr channelRepository) Save(ctx context.Context, channels ...things.Channel
_, err = tx.NamedExecContext(ctx, q, dbch)
if err != nil {
tx.Rollback()
if err := tx.Rollback(); err != nil {
return []things.Channel{}, errors.Wrap(errors.ErrCreateEntity, err)
}
pgErr, ok := err.(*pgconn.PgError)
if ok {
switch pgErr.Code {
@@ -64,6 +68,7 @@ func (cr channelRepository) Save(ctx context.Context, channels ...things.Channel
return []things.Channel{}, errors.Wrap(errors.ErrMalformedEntity, err)
}
}
return []things.Channel{}, errors.Wrap(errors.ErrCreateEntity, err)
}
}
@@ -291,8 +296,9 @@ func (cr channelRepository) Remove(ctx context.Context, owner, id string) error
Owner: owner,
}
q := `DELETE FROM channels WHERE id = :id AND owner = :owner`
cr.db.NamedExecContext(ctx, q, dbch)
return nil
_, err := cr.db.NamedExecContext(ctx, q, dbch)
return err
}
func (cr channelRepository) Connect(ctx context.Context, owner string, chIDs, thIDs []string) error {
@@ -314,7 +320,10 @@ func (cr channelRepository) Connect(ctx context.Context, owner string, chIDs, th
_, err := tx.NamedExecContext(ctx, q, dbco)
if err != nil {
tx.Rollback()
if err := tx.Rollback(); err != nil {
return errors.Wrap(things.ErrConnect, err)
}
pgErr, ok := err.(*pgconn.PgError)
if ok {
switch pgErr.Code {
@@ -357,7 +366,11 @@ func (cr channelRepository) Disconnect(ctx context.Context, owner string, chIDs,
res, err := tx.NamedExecContext(ctx, q, dbco)
if err != nil {
tx.Rollback()
err = tx.Rollback()
if err != nil {
return errors.Wrap(things.ErrConnect, err)
}
pgErr, ok := err.(*pgconn.PgError)
if ok {
switch pgErr.Code {
@@ -428,13 +441,13 @@ type dbMetadata map[string]interface{}
// If error occurs on casting data then m points to empty metadata.
func (m *dbMetadata) Scan(value interface{}) error {
if value == nil {
m = nil
*m = dbMetadata{}
return nil
}
b, ok := value.([]byte)
if !ok {
m = &dbMetadata{}
*m = dbMetadata{}
return errors.ErrScanMetadata
}
@@ -494,8 +507,8 @@ func getNameQuery(name string) (string, string) {
func getOrderQuery(order string) string {
switch order {
case "name":
return "name"
case name:
return name
default:
return "id"
}
@@ -503,7 +516,7 @@ func getOrderQuery(order string) string {
func getConnOrderQuery(order string, level string) string {
switch order {
case "name":
case name:
return level + ".name"
default:
return level + ".id"
+15 -7
View File
@@ -78,8 +78,7 @@ func TestChannelsSave(t *testing.T) {
}
for _, tc := range cases {
resp, err := channelRepo.Save(context.Background(), tc.channels...)
assert.Equal(t, tc.response, resp, fmt.Sprintf("%s: got incorrect list of channels from Save()", tc.desc))
_, err := channelRepo.Save(context.Background(), tc.channels...)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
}
}
@@ -172,7 +171,9 @@ func TestSingleChannelRetrieval(t *testing.T) {
}
chs, _ := chanRepo.Save(context.Background(), ch)
ch.ID = chs[0].ID
chanRepo.Connect(context.Background(), email, []string{ch.ID}, []string{th.ID})
err = chanRepo.Connect(context.Background(), email, []string{ch.ID}, []string{th.ID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
nonexistentChanID, err := idProvider.ID()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -256,7 +257,8 @@ func TestMultiChannelRetrieval(t *testing.T) {
ch.Name = name
}
chanRepo.Save(context.Background(), ch)
_, err = chanRepo.Save(context.Background(), ch)
assert.Nil(t, err, fmt.Sprintf("got unexpected error while saving channels: %s", err))
}
cases := []struct {
@@ -702,7 +704,9 @@ func TestDisconnect(t *testing.T) {
})
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
chID = chs[0].ID
chanRepo.Connect(context.Background(), email, []string{chID}, []string{thID})
err = chanRepo.Connect(context.Background(), email, []string{chID}, []string{thID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
nonexistentThingID, err := idProvider.ID()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -788,7 +792,9 @@ func TestHasThing(t *testing.T) {
})
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
chID = chs[0].ID
chanRepo.Connect(context.Background(), email, []string{chID}, []string{thID})
err = chanRepo.Connect(context.Background(), email, []string{chID}, []string{thID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
nonexistentChanID, err := idProvider.ID()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -866,7 +872,9 @@ func TestHasThingByID(t *testing.T) {
})
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
chID = chs[0].ID
chanRepo.Connect(context.Background(), email, []string{chID}, []string{thID})
err = chanRepo.Connect(context.Background(), email, []string{chID}, []string{thID})
assert.Nil(t, err, fmt.Sprintf("got unexpected error while connecting to service: %s", err))
nonexistentChanID, err := idProvider.ID()
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
+4 -4
View File
@@ -48,7 +48,10 @@ func (tr thingRepository) Save(ctx context.Context, ths ...things.Thing) ([]thin
}
if _, err := tx.NamedExecContext(ctx, q, dbth); err != nil {
tx.Rollback()
if rollbackErr := tx.Rollback(); rollbackErr != nil {
err = errors.Wrap(err, rollbackErr)
return []things.Thing{}, errors.Wrap(errors.ErrCreateEntity, err)
}
pgErr, ok := err.(*pgconn.PgError)
if ok {
switch pgErr.Code {
@@ -158,9 +161,6 @@ func (tr thingRepository) RetrieveByID(ctx context.Context, owner, id string) (t
}
return things.Thing{}, errors.Wrap(errors.ErrViewEntity, err)
}
fmt.Println()
fmt.Println(dbth)
fmt.Println()
return toThing(dbth)
}
+4 -2
View File
@@ -395,10 +395,12 @@ func TestMultiThingRetrieval(t *testing.T) {
subMetaStr := `{"field2":{"subfield12":{"subfield121":"value3"}}}`
metadata := things.Metadata{}
json.Unmarshal([]byte(metaStr), &metadata)
err = json.Unmarshal([]byte(metaStr), &metadata)
assert.Nil(t, err, fmt.Sprintf("got expected error while unmarshalling %s\n", err))
subMeta := things.Metadata{}
json.Unmarshal([]byte(subMetaStr), &subMeta)
err = json.Unmarshal([]byte(subMetaStr), &subMeta)
assert.Nil(t, err, fmt.Sprintf("got expected error while unmarshalling %s\n", err))
wrongMeta := things.Metadata{
"field": "value1",
+17 -14
View File
@@ -49,7 +49,10 @@ func (es eventStore) CreateThings(ctx context.Context, token string, ths ...thin
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
if err = es.client.XAdd(ctx, record).Err(); err != nil {
return sths, err
}
}
return sths, nil
@@ -70,9 +73,8 @@ func (es eventStore) UpdateThing(ctx context.Context, token string, thing things
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
return nil
return es.client.XAdd(ctx, record).Err()
}
// UpdateKey doesn't send event because key shouldn't be sent over stream.
@@ -111,9 +113,8 @@ func (es eventStore) RemoveThing(ctx context.Context, token, id string) error {
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
return nil
return es.client.XAdd(ctx, record).Err()
}
func (es eventStore) CreateChannels(ctx context.Context, token string, channels ...things.Channel) ([]things.Channel, error) {
@@ -134,7 +135,9 @@ func (es eventStore) CreateChannels(ctx context.Context, token string, channels
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
if err = es.client.XAdd(ctx, record).Err(); err != nil {
return schs, err
}
}
return schs, nil
@@ -155,9 +158,7 @@ func (es eventStore) UpdateChannel(ctx context.Context, token string, channel th
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
return nil
return es.client.XAdd(ctx, record).Err()
}
func (es eventStore) ViewChannel(ctx context.Context, token, id string) (things.Channel, error) {
@@ -185,9 +186,7 @@ func (es eventStore) RemoveChannel(ctx context.Context, token, id string) error
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
return nil
return es.client.XAdd(ctx, record).Err()
}
func (es eventStore) Connect(ctx context.Context, token string, chIDs, thIDs []string) error {
@@ -206,7 +205,9 @@ func (es eventStore) Connect(ctx context.Context, token string, chIDs, thIDs []s
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
if err := es.client.XAdd(ctx, record).Err(); err != nil {
return err
}
}
}
@@ -229,7 +230,9 @@ func (es eventStore) Disconnect(ctx context.Context, token string, chIDs, thIDs
MaxLenApprox: streamLen,
Values: event.Encode(),
}
es.client.XAdd(ctx, record).Err()
if err := es.client.XAdd(ctx, record).Err(); err != nil {
return err
}
}
}
+2 -1
View File
@@ -95,7 +95,8 @@ func TestThingRemove(t *testing.T) {
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
id := "123"
id2 := "321"
thingCache.Save(context.Background(), key, id)
err = thingCache.Save(context.Background(), key, id)
assert.Nil(t, err, fmt.Sprintf("got unexpected error while saving thingKey-thingID pair: %s", err))
cases := []struct {
desc string
+1 -1
View File
@@ -244,7 +244,7 @@ func (ts *thingsService) claimOwnership(ctx context.Context, objectID string, ac
for _, action := range actions {
apr, err := ts.auth.AddPolicy(ctx, &mainflux.AddPolicyReq{Obj: objectID, Act: action, Sub: userID})
if err != nil {
errs = errors.Wrap(fmt.Errorf("cannot claim ownership on object '%s' by user '%s': %s", objectID, userID, err), errs)
errs = errors.Wrap(fmt.Errorf("cannot claim ownership on object '%s' by user '%s': %w", objectID, userID, err), errs)
}
if !apr.GetAuthorized() {
errs = errors.Wrap(fmt.Errorf("cannot claim ownership on object '%s' by user '%s': unauthorized", objectID, userID), errs)
+19 -8
View File
@@ -14,33 +14,42 @@ import (
"strconv"
"time"
mflog "github.com/mainflux/mainflux/logger"
"github.com/pelletier/go-toml"
)
// Benchmark - main benchmarking function
func Benchmark(cfg Config) {
checkConnection(cfg.MQTT.Broker.URL, 1)
logger, err := mflog.New(os.Stdout, mflog.Debug.String())
if err != nil {
log.Fatalf(err.Error())
}
var err error
subsResults := map[string](*[]float64){}
var caByte []byte
if cfg.MQTT.TLS.MTLS {
caFile, err := os.Open(cfg.MQTT.TLS.CA)
defer caFile.Close()
defer func() {
if err = caFile.Close(); err != nil {
logger.Warn(fmt.Sprintf("Could not close file: %s", err))
}
}()
if err != nil {
fmt.Println(err)
logger.Warn(err.Error())
}
caByte, _ = ioutil.ReadAll(caFile)
}
data, err := ioutil.ReadFile(cfg.Mf.ConnFile)
if err != nil {
log.Fatalf("Error loading connections file: %s", err)
logger.Fatal(fmt.Sprintf("Error loading connections file: %s", err))
}
mf := mainflux{}
if err := toml.Unmarshal(data, &mf); err != nil {
log.Fatalf("Cannot load Mainflux connections config %s \nUse tools/provision to create file", cfg.Mf.ConnFile)
logger.Fatal(fmt.Sprintf("Cannot load Mainflux connections config %s \nUse tools/provision to create file", cfg.Mf.ConnFile))
}
resCh := make(chan *runResults)
@@ -61,12 +70,12 @@ func Benchmark(cfg Config) {
if cfg.MQTT.TLS.MTLS {
cert, err = tls.X509KeyPair([]byte(mfThing.MTLSCert), []byte(mfThing.MTLSKey))
if err != nil {
log.Fatal(err)
logger.Fatal(err.Error())
}
}
c, err := makeClient(i, cfg, mfChan, mfThing, startStamp, caByte, cert)
if err != nil {
log.Fatalf("Unable to create message payload %s", err.Error())
logger.Fatal(fmt.Sprintf("Unable to create message payload %s", err.Error()))
}
go c.publish(resCh)
@@ -110,7 +119,9 @@ func getBytePayload(size int, m message) (handler, error) {
sz := size - n
for {
b = make([]byte, sz)
rand.Read(b)
if _, err = rand.Read(b); err != nil {
return nil, err
}
m.Payload = b
content, err := json.Marshal(&m)
if err != nil {
-1
View File
@@ -147,7 +147,6 @@ func (c *Client) connect() error {
cfg.Certificates = []tls.Certificate{c.ClientCert}
}
cfg.BuildNameToCertificate()
opts.SetTLSConfig(cfg)
opts.SetProtocolVersion(4)
}
+2 -2
View File
@@ -19,7 +19,7 @@ func main() {
var rootCmd = &cobra.Command{
Use: "mqtt-bench",
Short: "mqtt-bench is MQTT benchmark tool for Mainflux",
Long: `Tool for exctensive load and benchmarking of MQTT brokers used withing Mainflux platform.
Long: `Tool for exctensive load and benchmarking of MQTT brokers used within the Mainflux platform.
Complete documentation is available at https://docs.mainflux.io`,
Run: func(cmd *cobra.Command, args []string) {
if confFile != "" {
@@ -62,7 +62,7 @@ Complete documentation is available at https://docs.mainflux.io`,
rootCmd.PersistentFlags().IntVarP(&bconf.Test.Pubs, "pubs", "p", 10, "Number of publishers")
// Log params
rootCmd.PersistentFlags().BoolVarP(&bconf.Log.Quiet, "quiet", "", false, "Supress messages")
rootCmd.PersistentFlags().BoolVarP(&bconf.Log.Quiet, "quiet", "", false, "Suppress messages")
// Config file
rootCmd.PersistentFlags().StringVarP(&confFile, "config", "c", "config.toml", "config file for mqtt-bench")
+3 -1
View File
@@ -157,7 +157,9 @@ func printResults(results []*runResults, totals *totalResults, format string, qu
log.Printf("Failed to prepare results for printing - %s\n", err.Error())
}
var out bytes.Buffer
json.Indent(&out, data, "", "\t")
if err = json.Indent(&out, data, "", "\t"); err != nil {
return
}
fmt.Println(out.String())
default:
+1 -1
View File
@@ -392,7 +392,7 @@ func TestViewTwin(t *testing.T) {
var resData twinRes
err = json.NewDecoder(res.Body).Decode(&resData)
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error while decoding json: %s", tc.desc, err))
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error while decoding response body: %s\n", tc.desc, err))
assert.Equal(t, tc.res, resData, fmt.Sprintf("%s: expected body %v got %v", tc.desc, tc.res, resData))
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ import (
const (
statesCollection string = "states"
twinid = "twinid"
twinid string = "twinid"
)
type stateRepository struct {
+8 -4
View File
@@ -58,7 +58,8 @@ func TestStatesRetrieveAll(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Creating new MongoDB client expected to succeed: %s.\n", err))
db := client.Database(testDB)
db.Collection("states").DeleteMany(context.Background(), bson.D{})
_, err = db.Collection("states").DeleteMany(context.Background(), bson.D{})
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
repo := mongodb.NewStateRepository(db)
@@ -73,7 +74,8 @@ func TestStatesRetrieveAll(t *testing.T) {
Created: time.Now(),
}
repo.Save(context.Background(), st)
err = repo.Save(context.Background(), st)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
}
cases := map[string]struct {
@@ -120,7 +122,8 @@ func TestStatesRetrieveLast(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Creating new MongoDB client expected to succeed: %s.\n", err))
db := client.Database(testDB)
db.Collection("states").DeleteMany(context.Background(), bson.D{})
_, err = db.Collection("states").DeleteMany(context.Background(), bson.D{})
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
repo := mongodb.NewStateRepository(db)
@@ -135,7 +138,8 @@ func TestStatesRetrieveLast(t *testing.T) {
Created: time.Now(),
}
repo.Save(context.Background(), st)
err = repo.Save(context.Background(), st)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
}
cases := map[string]struct {
+4 -2
View File
@@ -249,7 +249,8 @@ func TestTwinsRetrieveAll(t *testing.T) {
require.Nil(t, err, fmt.Sprintf("Creating new MongoDB client expected to succeed: %s.\n", err))
db := client.Database(testDB)
db.Collection(collection).DeleteMany(context.Background(), bson.D{})
_, err = db.Collection(collection).DeleteMany(context.Background(), bson.D{})
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
twinRepo := mongodb.NewTwinRepository(db)
@@ -269,7 +270,8 @@ func TestTwinsRetrieveAll(t *testing.T) {
tw.Name = name
}
twinRepo.Save(context.Background(), tw)
_, err = twinRepo.Save(context.Background(), tw)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
}
cases := map[string]struct {
+1 -1
View File
@@ -23,7 +23,7 @@ var (
// ErrRedisTwinUpdate indicates error while saving Twin in redis cache
ErrRedisTwinUpdate = errors.New("failed to update twin in redis cache")
// ErrRedisTwinIDs indicates error while geting Twin IDs from redis cache
// ErrRedisTwinIDs indicates error while getting Twin IDs from redis cache
ErrRedisTwinIDs = errors.New("failed to get twin id from redis cache")
// ErrRedisTwinRemove indicates error while removing Twin from redis cache
+5 -5
View File
@@ -285,17 +285,17 @@ func (ts *twinsService) saveState(msg *messaging.Message, twinID string) error {
tw, err := ts.twins.RetrieveByID(ctx, twinID)
if err != nil {
return fmt.Errorf("Retrieving twin for %s failed: %s", msg.Publisher, err)
return fmt.Errorf("retrieving twin for %s failed: %s", msg.Publisher, err)
}
var recs []senml.Record
if err := json.Unmarshal(msg.Payload, &recs); err != nil {
return fmt.Errorf("Unmarshal payload for %s failed: %s", msg.Publisher, err)
return fmt.Errorf("unmarshal payload for %s failed: %s", msg.Publisher, err)
}
st, err := ts.states.RetrieveLast(ctx, tw.ID)
if err != nil {
return fmt.Errorf("Retrieve last state for %s failed: %s", msg.Publisher, err)
return fmt.Errorf("retrieve last state for %s failed: %s", msg.Publisher, err)
}
for _, rec := range recs {
@@ -305,11 +305,11 @@ func (ts *twinsService) saveState(msg *messaging.Message, twinID string) error {
return nil
case update:
if err := ts.states.Update(ctx, st); err != nil {
return fmt.Errorf("Update state for %s failed: %s", msg.Publisher, err)
return fmt.Errorf("update state for %s failed: %s", msg.Publisher, err)
}
case save:
if err := ts.states.Save(ctx, st); err != nil {
return fmt.Errorf("Save state for %s failed: %s", msg.Publisher, err)
return fmt.Errorf("save state for %s failed: %s", msg.Publisher, err)
}
}
}
+2 -1
View File
@@ -154,7 +154,8 @@ func TestListTwins(t *testing.T) {
n := uint64(10)
for i := uint64(0); i < n; i++ {
svc.AddTwin(context.Background(), token, twin, def)
_, err := svc.AddTwin(context.Background(), token, twin, def)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
}
cases := []struct {
+1 -1
View File
@@ -273,7 +273,7 @@ func TestListUsers(t *testing.T) {
err: errors.ErrAuthorization,
},
{
desc: "list user with emtpy token",
desc: "list user with empty token",
token: "",
size: 0,
err: errors.ErrAuthentication,
+9 -9
View File
@@ -54,9 +54,9 @@ import "github.com/golang-jwt/jwt/v4"
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage:
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac)
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac)
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt#pkg-examples)
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac)
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-New-Hmac)
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#pkg-examples)
## Extensions
@@ -96,7 +96,7 @@ A token is simply a JSON object that is signed by its author. this tells you exa
* The author of the token was in the possession of the signing secret
* The data has not been modified since it was signed
It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library.
It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. The companion project https://github.com/golang-jwt/jwe aims at a (very) experimental implementation of the JWE standard.
### Choosing a Signing Method
@@ -110,10 +110,10 @@ Asymmetric signing methods, such as RSA, use different keys for signing and veri
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
### JWT and OAuth
@@ -131,7 +131,7 @@ This library uses descriptive error messages whenever possible. If you are not g
## More
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt).
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt/v4).
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
+1 -5
View File
@@ -265,9 +265,5 @@ func verifyIss(iss string, cmp string, required bool) bool {
if iss == "" {
return !required
}
if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
return true
} else {
return false
}
return subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0
}
+7
View File
@@ -42,6 +42,13 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
}
// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
// interface. This provides default values which can be overridden and allows a caller to use their own type, rather
// than the default MapClaims implementation of Claims.
//
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
token, parts, err := p.ParseUnverified(tokenString, claims)
if err != nil {
+18 -2
View File
@@ -14,6 +14,12 @@ import (
// To use the non-recommended decoding, set this boolean to `true` prior to using this package.
var DecodePaddingAllowed bool
// DecodeStrict will switch the codec used for decoding JWTs into strict mode.
// In this mode, the decoder requires that trailing padding bits are zero, as described in RFC 4648 section 3.5.
// Note that this is a global variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe.
// To use strict decoding, set this boolean to `true` prior to using this package.
var DecodeStrict bool
// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
// You can override it to use another time value. This is useful for testing or if your
// server uses a different time zone than your tokens.
@@ -99,6 +105,11 @@ func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token
return NewParser(options...).Parse(tokenString, keyFunc)
}
// ParseWithClaims is a shortcut for NewParser().ParseWithClaims().
//
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
}
@@ -116,12 +127,17 @@ func EncodeSegment(seg []byte) string {
// Deprecated: In a future release, we will demote this function to a non-exported function, since it
// should only be used internally
func DecodeSegment(seg string) ([]byte, error) {
encoding := base64.RawURLEncoding
if DecodePaddingAllowed {
if l := len(seg) % 4; l > 0 {
seg += strings.Repeat("=", 4-l)
}
return base64.URLEncoding.DecodeString(seg)
encoding = base64.URLEncoding
}
return base64.RawURLEncoding.DecodeString(seg)
if DecodeStrict {
encoding = encoding.Strict()
}
return encoding.DecodeString(seg)
}
+1 -1
View File
@@ -142,7 +142,7 @@ github.com/gofrs/uuid
# github.com/gogo/protobuf v1.3.2
## explicit; go 1.15
github.com/gogo/protobuf/proto
# github.com/golang-jwt/jwt/v4 v4.4.2
# github.com/golang-jwt/jwt/v4 v4.5.0
## explicit; go 1.16
github.com/golang-jwt/jwt/v4
# github.com/golang/protobuf v1.5.2
-1
View File
@@ -3,7 +3,6 @@
// Package ws contains the domain concept definitions needed to support
// Mainflux ws adapter service functionality
package ws
import (
+2 -2
View File
@@ -145,7 +145,7 @@ func process(svc ws.Service, req connReq, msgs <-chan []byte) {
Payload: msg,
Created: time.Now().UnixNano(),
}
svc.Publish(context.Background(), req.thingKey, &m)
_ = svc.Publish(context.Background(), req.thingKey, &m)
}
if err := svc.Unsubscribe(context.Background(), req.thingKey, req.chanID, req.subtopic); err != nil {
req.conn.Close()
@@ -153,7 +153,7 @@ func process(svc ws.Service, req connReq, msgs <-chan []byte) {
}
func encodeError(w http.ResponseWriter, err error) {
statusCode := http.StatusUnauthorized
var statusCode int
switch err {
case ws.ErrEmptyID, ws.ErrEmptyTopic:
-2
View File
@@ -6,7 +6,6 @@ package mocks
import (
"context"
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
"github.com/mainflux/mainflux/pkg/messaging"
@@ -37,7 +36,6 @@ func (pubsub *mockPubSub) Publish(ctx context.Context, s string, msg *messaging.
if pubsub.conn != nil {
data, err := json.Marshal(msg)
if err != nil {
fmt.Println("can't marshall")
return ws.ErrFailedMessagePublish
}
return pubsub.conn.WriteMessage(websocket.BinaryMessage, data)