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

148 lines
3.3 KiB
Go

package mocks
import (
"fmt"
"sort"
"strings"
"sync"
"github.com/mainflux/mainflux/things"
)
var _ things.ChannelRepository = (*channelRepositoryMock)(nil)
type channelRepositoryMock struct {
mu sync.Mutex
counter uint64
channels map[string]things.Channel
things things.ThingRepository
}
// NewChannelRepository creates in-memory channel repository.
func NewChannelRepository(repo things.ThingRepository) things.ChannelRepository {
return &channelRepositoryMock{
channels: make(map[string]things.Channel),
things: repo,
}
}
func (crm *channelRepositoryMock) Save(channel things.Channel) (uint64, error) {
crm.mu.Lock()
defer crm.mu.Unlock()
crm.counter++
channel.ID = crm.counter
crm.channels[key(channel.Owner, channel.ID)] = channel
return channel.ID, nil
}
func (crm *channelRepositoryMock) Update(channel things.Channel) error {
crm.mu.Lock()
defer crm.mu.Unlock()
dbKey := key(channel.Owner, channel.ID)
if _, ok := crm.channels[dbKey]; !ok {
return things.ErrNotFound
}
crm.channels[dbKey] = channel
return nil
}
func (crm *channelRepositoryMock) RetrieveByID(owner string, id uint64) (things.Channel, error) {
if c, ok := crm.channels[key(owner, id)]; ok {
return c, nil
}
return things.Channel{}, things.ErrNotFound
}
func (crm *channelRepositoryMock) RetrieveAll(owner string, offset, limit int) []things.Channel {
channels := make([]things.Channel, 0)
if offset < 0 || limit <= 0 {
return channels
}
first := uint64(offset) + 1
last := first + uint64(limit)
// This obscure way to examine map keys is enforced by the key structure
// itself (see mocks/commons.go).
prefix := fmt.Sprintf("%s-", owner)
for k, v := range crm.channels {
if strings.HasPrefix(k, prefix) && v.ID >= first && v.ID < last {
channels = append(channels, v)
}
}
sort.SliceStable(channels, func(i, j int) bool {
return channels[i].ID < channels[j].ID
})
return channels
}
func (crm *channelRepositoryMock) Remove(owner string, id uint64) error {
delete(crm.channels, key(owner, id))
return nil
}
func (crm *channelRepositoryMock) Connect(owner string, chanID, thingID uint64) error {
channel, err := crm.RetrieveByID(owner, chanID)
if err != nil {
return err
}
thing, err := crm.things.RetrieveByID(owner, thingID)
if err != nil {
return err
}
channel.Things = append(channel.Things, thing)
return crm.Update(channel)
}
func (crm *channelRepositoryMock) Disconnect(owner string, chanID, thingID uint64) error {
channel, err := crm.RetrieveByID(owner, chanID)
if err != nil {
return err
}
for _, t := range channel.Things {
if t.ID == thingID {
connected := make([]things.Thing, len(channel.Things)-1)
for _, thing := range channel.Things {
if thing.ID != thingID {
connected = append(connected, thing)
}
}
channel.Things = connected
return crm.Update(channel)
}
}
return things.ErrNotFound
}
func (crm *channelRepositoryMock) HasThing(chanID uint64, key string) (uint64, error) {
// This obscure way to examine map keys is enforced by the key structure
// itself (see mocks/commons.go).
suffix := fmt.Sprintf("-%d", chanID)
for k, v := range crm.channels {
if strings.HasSuffix(k, suffix) {
for _, t := range v.Things {
if t.Key == key {
return t.ID, nil
}
}
break
}
}
return 0, things.ErrNotFound
}