diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index b3426e14830..9dffe1b6d28 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -183,4 +183,4 @@ jobs: - name: Stop containers if: always() - run: make run down args="-v" + run: make run down args="-v" \ No newline at end of file diff --git a/.github/workflows/check-generated-files.yml b/.github/workflows/check-generated-files.yml index d02ebd91488..84c1b1b9ee2 100644 --- a/.github/workflows/check-generated-files.yml +++ b/.github/workflows/check-generated-files.yml @@ -63,6 +63,7 @@ jobs: - "invitations/invitations.go" - "users/emailer.go" - "users/hasher.go" + - "mqtt/events/streams.go" - name: Set up protoc if: steps.changes.outputs.proto == 'true' @@ -132,6 +133,7 @@ jobs: mv ./invitations/mocks/repository.go ./invitations/mocks/repository.go.tmp mv ./users/mocks/emailer.go ./users/mocks/emailer.go.tmp mv ./users/mocks/hasher.go ./users/mocks/hasher.go.tmp + mv ./mqtt/mocks/redis.go ./mqtt/mocks/redis.go.tmp make mocks @@ -170,3 +172,4 @@ jobs: check_mock_changes ./invitations/mocks/repository.go "Invitations Repository ./invitations/mocks/repository.go" check_mock_changes ./users/mocks/emailer.go "Users Emailer ./users/mocks/emailer.go" check_mock_changes ./users/mocks/hasher.go "Users Hasher ./users/mocks/hasher.go" + check_mock_changes ./mqtt/mocks/redis.go "MQTT Redis ./mqtt/mocks/redis.go" diff --git a/mqtt/events/streams.go b/mqtt/events/streams.go index ee03a243ab0..bd5325bd8c8 100644 --- a/mqtt/events/streams.go +++ b/mqtt/events/streams.go @@ -12,6 +12,7 @@ import ( const streamID = "magistrala.mqtt" +//go:generate mockery --name EventStore --output=../mocks --filename redis.go --quiet --note "Copyright (c) Abstract Machines" type EventStore interface { Connect(ctx context.Context, clientID string) error Disconnect(ctx context.Context, clientID string) error diff --git a/mqtt/handler_test.go b/mqtt/handler_test.go index 0dd52808e2e..61ce01b2826 100644 --- a/mqtt/handler_test.go +++ b/mqtt/handler_test.go @@ -61,10 +61,11 @@ var ( Username: invalidID, Password: []byte(password), } + svcCall *mock.Call ) func TestAuthConnect(t *testing.T) { - handler, _ := newHandler() + handler, _, eventStore := newHandler(t) cases := []struct { desc string @@ -105,19 +106,24 @@ func TestAuthConnect(t *testing.T) { session: &sessionClient, }, } - for _, tc := range cases { ctx := context.TODO() + if tc.session != nil { + svcCall = eventStore.On("Connect", mock.Anything, string(tc.session.Password)).Return(tc.err) + } else { + svcCall = eventStore.On("Connect", ctx, "").Return(tc.err) + } if tc.session != nil { ctx = session.NewContext(ctx, tc.session) } err := handler.AuthConnect(ctx) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + svcCall.Unset() } } func TestAuthPublish(t *testing.T) { - handler, auth := newHandler() + handler, auth, _ := newHandler(t) cases := []struct { desc string @@ -157,7 +163,7 @@ func TestAuthPublish(t *testing.T) { } for _, tc := range cases { - repocall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, nil) + repocall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, tc.err) ctx := context.TODO() if tc.session != nil { ctx = session.NewContext(ctx, tc.session) @@ -169,7 +175,7 @@ func TestAuthPublish(t *testing.T) { } func TestAuthSubscribe(t *testing.T) { - handler, auth := newHandler() + handler, auth, _ := newHandler(t) cases := []struct { desc string @@ -210,7 +216,7 @@ func TestAuthSubscribe(t *testing.T) { } for _, tc := range cases { - repocall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, nil) + repocall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true, Id: testsutil.GenerateUUID(t)}, tc.err) ctx := context.TODO() if tc.session != nil { ctx = session.NewContext(ctx, tc.session) @@ -222,7 +228,7 @@ func TestAuthSubscribe(t *testing.T) { } func TestConnect(t *testing.T) { - handler, _ := newHandler() + handler, _, _ := newHandler(t) logBuffer.Reset() cases := []struct { @@ -256,7 +262,7 @@ func TestConnect(t *testing.T) { } func TestPublish(t *testing.T) { - handler, _ := newHandler() + handler, _, _ := newHandler(t) logBuffer.Reset() malformedSubtopics := topic + "/" + subtopic + "%" @@ -335,7 +341,7 @@ func TestPublish(t *testing.T) { } func TestSubscribe(t *testing.T) { - handler, _ := newHandler() + handler, _, _ := newHandler(t) logBuffer.Reset() cases := []struct { @@ -371,7 +377,7 @@ func TestSubscribe(t *testing.T) { } func TestUnsubscribe(t *testing.T) { - handler, _ := newHandler() + handler, _, _ := newHandler(t) logBuffer.Reset() cases := []struct { @@ -407,7 +413,7 @@ func TestUnsubscribe(t *testing.T) { } func TestDisconnect(t *testing.T) { - handler, _ := newHandler() + handler, _, eventStore := newHandler(t) logBuffer.Reset() cases := []struct { @@ -433,21 +439,27 @@ func TestDisconnect(t *testing.T) { for _, tc := range cases { ctx := context.TODO() + if tc.session != nil { + svcCall = eventStore.On("Disconnect", mock.Anything, string(tc.session.Password)).Return(tc.err) + } else { + svcCall = eventStore.On("Disconnect", ctx, "").Return(tc.err) + } if tc.session != nil { ctx = session.NewContext(ctx, tc.session) } err := handler.Disconnect(ctx) assert.Contains(t, logBuffer.String(), tc.logMsg) assert.Equal(t, tc.err, err) + svcCall.Unset() } } -func newHandler() (session.Handler, *authmocks.AuthClient) { +func newHandler(t *testing.T) (session.Handler, *authmocks.AuthClient, *mocks.EventStore) { logger, err := mglog.New(&logBuffer, "debug") if err != nil { log.Fatalf("failed to create logger: %s", err) } auth := new(authmocks.AuthClient) - eventStore := mocks.NewEventStore() - return mqtt.NewHandler(mocks.NewPublisher(), eventStore, logger, auth), auth + eventStore := mocks.NewEventStore(t) + return mqtt.NewHandler(mocks.NewPublisher(), eventStore, logger, auth), auth, eventStore } diff --git a/mqtt/mocks/redis.go b/mqtt/mocks/redis.go index be63be8a44c..d7ba830bad5 100644 --- a/mqtt/mocks/redis.go +++ b/mqtt/mocks/redis.go @@ -1,24 +1,66 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + // Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 package mocks import ( - "context" + context "context" - "github.com/absmach/magistrala/mqtt/events" + mock "github.com/stretchr/testify/mock" ) -type MockEventStore struct{} +// EventStore is an autogenerated mock type for the EventStore type +type EventStore struct { + mock.Mock +} + +// Connect provides a mock function with given fields: ctx, clientID +func (_m *EventStore) Connect(ctx context.Context, clientID string) error { + ret := _m.Called(ctx, clientID) + + if len(ret) == 0 { + panic("no return value specified for Connect") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, clientID) + } else { + r0 = ret.Error(0) + } -func NewEventStore() events.EventStore { - return MockEventStore{} + return r0 } -func (es MockEventStore) Connect(ctx context.Context, clientID string) error { - return nil +// Disconnect provides a mock function with given fields: ctx, clientID +func (_m *EventStore) Disconnect(ctx context.Context, clientID string) error { + ret := _m.Called(ctx, clientID) + + if len(ret) == 0 { + panic("no return value specified for Disconnect") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, clientID) + } else { + r0 = ret.Error(0) + } + + return r0 } -func (es MockEventStore) Disconnect(ctx context.Context, clientID string) error { - return nil +// NewEventStore creates a new instance of EventStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewEventStore(t interface { + mock.TestingT + Cleanup(func()) +}) *EventStore { + mock := &EventStore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock }