1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-29 13:49:28 +08:00
Mainflux.mainflux/things/redis/streams_test.go
Aleksandar Novaković b9bf63e377 MF-475 - Replace increment ID with UUID (#490)
* Update increment ID to UUID in things service

Update increment ID to UUID for things and channels in things
service and proto files. Also, update ID type from uint to string.

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in http adapter

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in ws adapter

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in CoAP adapter

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in normalizer service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in writer services

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in reader services

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in SDK

Update increment ID to UUID in SDK. Update id type to string.
Update tests.

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update increment ID to UUID in mqtt adapter

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Remove unnecessary case from influxdb reader

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update tests in order to increase code coverage

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update lora adapter to use string ID instead of unsigned int

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-12-05 13:09:25 +01:00

532 lines
13 KiB
Go

//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package redis_test
import (
"fmt"
"math"
"strconv"
"testing"
r "github.com/go-redis/redis"
"github.com/mainflux/mainflux/things"
"github.com/mainflux/mainflux/things/mocks"
"github.com/mainflux/mainflux/things/redis"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
streamID = "mainflux.things"
email = "user@example.com"
token = "token"
thingPrefix = "thing."
thingCreate = thingPrefix + "create"
thingUpdate = thingPrefix + "update"
thingRemove = thingPrefix + "remove"
thingConnect = thingPrefix + "connect"
thingDisconnect = thingPrefix + "disconnect"
channelPrefix = "channel."
channelCreate = channelPrefix + "create"
channelUpdate = channelPrefix + "update"
channelRemove = channelPrefix + "remove"
)
func newService(tokens map[string]string) things.Service {
users := mocks.NewUsersService(tokens)
thingsRepo := mocks.NewThingRepository()
channelsRepo := mocks.NewChannelRepository(thingsRepo)
chanCache := mocks.NewChannelCache()
thingCache := mocks.NewThingCache()
idp := mocks.NewIdentityProvider()
return things.New(users, thingsRepo, channelsRepo, chanCache, thingCache, idp)
}
func TestAddThing(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
thing things.Thing
key string
err error
event map[string]interface{}
}{
{
desc: "create thing successfully",
thing: things.Thing{Type: "app", Name: "a", Metadata: "metadata"},
key: token,
err: nil,
event: map[string]interface{}{
"id": "1",
"name": "a",
"owner": email,
"type": "app",
"metadata": "metadata",
"operation": thingCreate,
},
},
{
desc: "create invalid thing",
thing: things.Thing{Type: "a", Name: "a"},
key: token,
err: things.ErrMalformedEntity,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
_, err := svc.AddThing(tc.key, tc.thing)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestUpdateThing(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
// Create thing without sending event.
sth, err := svc.AddThing(token, things.Thing{Type: "app", Name: "a", Metadata: "metadata"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
thing things.Thing
key string
err error
event map[string]interface{}
}{
{
desc: "update existing thing successfully",
thing: things.Thing{ID: sth.ID, Type: "app", Name: "a", Metadata: "metadata1"},
key: token,
err: nil,
event: map[string]interface{}{
"id": sth.ID,
"name": "a",
"type": "app",
"metadata": "metadata1",
"operation": thingUpdate,
},
},
{
desc: "update invalid thing",
thing: things.Thing{
ID: strconv.FormatUint(math.MaxUint64, 10),
Type: "a",
Name: "a",
},
key: token,
err: things.ErrMalformedEntity,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
err := svc.UpdateThing(tc.key, tc.thing)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestRemoveThing(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
// Create thing without sending event.
sth, err := svc.AddThing(token, things.Thing{Type: "app", Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
id string
key string
err error
event map[string]interface{}
}{
{
desc: "delete existing thing successfully",
id: sth.ID,
key: token,
err: nil,
event: map[string]interface{}{
"id": sth.ID,
"operation": thingRemove,
},
},
{
desc: "delete thing with invalid credentials",
id: strconv.FormatUint(math.MaxUint64, 10),
key: "",
err: things.ErrUnauthorizedAccess,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
err := svc.RemoveThing(tc.key, tc.id)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestCreateChannel(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
channel things.Channel
key string
err error
event map[string]interface{}
}{
{
desc: "create channel successfully",
channel: things.Channel{Name: "a", Metadata: "metadata"},
key: token,
err: nil,
event: map[string]interface{}{
"id": "1",
"name": "a",
"metadata": "metadata",
"owner": email,
"operation": channelCreate,
},
},
{
desc: "create channel with invalid credentials",
channel: things.Channel{Name: "a", Metadata: "metadata"},
key: "",
err: things.ErrUnauthorizedAccess,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
_, err := svc.CreateChannel(tc.key, tc.channel)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestUpdateChannel(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
// Create channel without sending event.
sch, err := svc.CreateChannel(token, things.Channel{Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
channel things.Channel
key string
err error
event map[string]interface{}
}{
{
desc: "update channel successfully",
channel: things.Channel{ID: sch.ID, Name: "b", Metadata: "metadata"},
key: token,
err: nil,
event: map[string]interface{}{
"id": sch.ID,
"name": "b",
"metadata": "metadata",
"operation": channelUpdate,
},
},
{
desc: "create non-existent channel",
channel: things.Channel{
ID: strconv.FormatUint(math.MaxUint64, 10),
Name: "c",
},
key: token,
err: things.ErrNotFound,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
err := svc.UpdateChannel(tc.key, tc.channel)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestRemoveChannel(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
// Create channel without sending event.
sch, err := svc.CreateChannel(token, things.Channel{Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
id string
key string
err error
event map[string]interface{}
}{
{
desc: "update channel successfully",
id: sch.ID,
key: token,
err: nil,
event: map[string]interface{}{
"id": sch.ID,
"operation": channelRemove,
},
},
{
desc: "create non-existent channel",
id: strconv.FormatUint(math.MaxUint64, 10),
key: "",
err: things.ErrUnauthorizedAccess,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
err := svc.RemoveChannel(tc.key, tc.id)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestConnectEvent(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
// Create thing and channel that will be connected.
sth, err := svc.AddThing(token, things.Thing{Type: "device", Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
sch, err := svc.CreateChannel(token, things.Channel{Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
thingID string
chanID string
key string
err error
event map[string]interface{}
}{
{
desc: "connect existing thing to existing channel",
thingID: sth.ID,
chanID: sch.ID,
key: token,
err: nil,
event: map[string]interface{}{
"chan_id": sch.ID,
"thing_id": sth.ID,
"operation": thingConnect,
},
},
{
desc: "connect non-existent thing to channel",
thingID: strconv.FormatUint(math.MaxUint64, 10),
chanID: sch.ID,
key: token,
err: things.ErrNotFound,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
err := svc.Connect(tc.key, tc.chanID, tc.thingID)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}
func TestDisconnectEvent(t *testing.T) {
redisClient.FlushAll().Err()
svc := newService(map[string]string{token: email})
// Create thing and channel that will be connected.
sth, err := svc.AddThing(token, things.Thing{Type: "device", Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
sch, err := svc.CreateChannel(token, things.Channel{Name: "a"})
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
err = svc.Connect(token, sch.ID, sth.ID)
require.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
svc = redis.NewEventStoreMiddleware(svc, redisClient)
cases := []struct {
desc string
thingID string
chanID string
key string
err error
event map[string]interface{}
}{
{
desc: "disconnect thing from channel",
thingID: sth.ID,
chanID: sch.ID,
key: token,
err: nil,
event: map[string]interface{}{
"chan_id": sch.ID,
"thing_id": sth.ID,
"operation": thingDisconnect,
},
},
{
desc: "disconnect non-existent thing from channel",
thingID: strconv.FormatUint(math.MaxUint64, 10),
chanID: sch.ID,
key: token,
err: things.ErrNotFound,
event: nil,
},
}
lastID := "0"
for _, tc := range cases {
err := svc.Disconnect(tc.key, tc.chanID, tc.thingID)
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
streams := redisClient.XRead(&r.XReadArgs{
Streams: []string{streamID, lastID},
Count: 1,
}).Val()
var event map[string]interface{}
if len(streams) > 0 && len(streams[0].Messages) > 0 {
msg := streams[0].Messages[0]
event = msg.Values
lastID = msg.ID
}
assert.Equal(t, tc.event, event, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.event, event))
}
}