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

* update or to sync with clients branch Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * Add empty lines Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * update inline constant Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * rebase pr to sync with master branch Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * update pr to sync with updated master #1849 Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> --------- Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
1424 lines
42 KiB
Go
1424 lines
42 KiB
Go
package sdk_test
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-zoo/bone"
|
|
"github.com/mainflux/mainflux/internal/apiutil"
|
|
"github.com/mainflux/mainflux/internal/testsutil"
|
|
mflog "github.com/mainflux/mainflux/logger"
|
|
mfclients "github.com/mainflux/mainflux/pkg/clients"
|
|
"github.com/mainflux/mainflux/pkg/errors"
|
|
sdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
|
"github.com/mainflux/mainflux/things/clients"
|
|
"github.com/mainflux/mainflux/things/clients/api"
|
|
"github.com/mainflux/mainflux/things/clients/mocks"
|
|
gmocks "github.com/mainflux/mainflux/things/groups/mocks"
|
|
"github.com/mainflux/mainflux/things/policies"
|
|
papi "github.com/mainflux/mainflux/things/policies/api/http"
|
|
pmocks "github.com/mainflux/mainflux/things/policies/mocks"
|
|
cmocks "github.com/mainflux/mainflux/users/clients/mocks"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
var (
|
|
adminToken = "token"
|
|
adminID = generateUUID(&testing.T{})
|
|
users = map[string]string{adminToken: adminID}
|
|
ID = testsutil.GenerateUUID(&testing.T{}, idProvider)
|
|
uadminPolicy = cmocks.SubjectSet{Subject: ID, Relation: clients.AdminRelationKey}
|
|
)
|
|
|
|
func newThingsServer(svc clients.Service, psvc policies.Service) *httptest.Server {
|
|
logger := mflog.NewMock()
|
|
mux := bone.New()
|
|
api.MakeHandler(svc, mux, logger, instanceID)
|
|
papi.MakeHandler(svc, psvc, mux, logger)
|
|
return httptest.NewServer(mux)
|
|
}
|
|
|
|
func TestCreateThing(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
thing := sdk.Thing{
|
|
Name: "test",
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
client sdk.Thing
|
|
response sdk.Thing
|
|
token string
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "register new thing",
|
|
client: thing,
|
|
response: thing,
|
|
token: token,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "register existing thing",
|
|
client: thing,
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedCreation, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "register empty thing",
|
|
client: sdk.Thing{},
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrMalformedEntity, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register a thing that can't be marshalled",
|
|
client: sdk.Thing{
|
|
Name: "test",
|
|
Metadata: map[string]interface{}{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "register thing with empty secret",
|
|
client: sdk.Thing{
|
|
Name: "emptysecret",
|
|
Credentials: sdk.Credentials{
|
|
Secret: "",
|
|
},
|
|
},
|
|
response: sdk.Thing{
|
|
Name: "emptysecret",
|
|
Credentials: sdk.Credentials{
|
|
Secret: "",
|
|
},
|
|
},
|
|
token: token,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "register thing with empty identity",
|
|
client: sdk.Thing{
|
|
Credentials: sdk.Credentials{
|
|
Identity: "",
|
|
Secret: secret,
|
|
},
|
|
},
|
|
response: sdk.Thing{
|
|
Credentials: sdk.Credentials{
|
|
Identity: "",
|
|
Secret: secret,
|
|
},
|
|
},
|
|
token: token,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "register empty thing",
|
|
client: sdk.Thing{},
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMalformedEntity, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register thing with every field defined",
|
|
client: sdk.Thing{
|
|
ID: id,
|
|
Name: "name",
|
|
Tags: []string{"tag1", "tag2"},
|
|
Owner: id,
|
|
Credentials: user.Credentials,
|
|
Metadata: validMetadata,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
Status: mfclients.EnabledStatus.String(),
|
|
},
|
|
response: sdk.Thing{
|
|
ID: id,
|
|
Name: "name",
|
|
Tags: []string{"tag1", "tag2"},
|
|
Owner: id,
|
|
Credentials: user.Credentials,
|
|
Metadata: validMetadata,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
Status: mfclients.EnabledStatus.String(),
|
|
},
|
|
token: token,
|
|
err: nil,
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
repoCall := cRepo.On("Save", mock.Anything, mock.Anything).Return(tc.response, tc.err)
|
|
rThing, err := mfsdk.CreateThing(tc.client, tc.token)
|
|
tc.response.ID = rThing.ID
|
|
tc.response.Owner = rThing.Owner
|
|
tc.response.CreatedAt = rThing.CreatedAt
|
|
tc.response.UpdatedAt = rThing.UpdatedAt
|
|
rThing.Credentials.Secret = tc.response.Credentials.Secret
|
|
rThing.Status = tc.response.Status
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, rThing, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, rThing))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "Save", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("Save was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
}
|
|
}
|
|
|
|
func TestCreateThings(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
things := []sdk.Thing{
|
|
{
|
|
Name: "test",
|
|
Status: mfclients.EnabledStatus.String(),
|
|
},
|
|
{
|
|
Name: "test2",
|
|
Status: mfclients.EnabledStatus.String(),
|
|
},
|
|
}
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
things []sdk.Thing
|
|
response []sdk.Thing
|
|
token string
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "register new things",
|
|
things: things,
|
|
response: things,
|
|
token: token,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "register existing things",
|
|
things: things,
|
|
response: []sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedCreation, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "register empty things",
|
|
things: []sdk.Thing{},
|
|
response: []sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrEmptyList, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register things that can't be marshalled",
|
|
things: []sdk.Thing{
|
|
{
|
|
Name: "test",
|
|
Metadata: map[string]interface{}{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
},
|
|
response: []sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
repoCall := cRepo.On("Save", mock.Anything, mock.Anything).Return(tc.response, tc.err)
|
|
rThing, err := mfsdk.CreateThings(tc.things, tc.token)
|
|
for i, t := range rThing {
|
|
tc.response[i].ID = t.ID
|
|
tc.response[i].Owner = t.Owner
|
|
tc.response[i].CreatedAt = t.CreatedAt
|
|
tc.response[i].UpdatedAt = t.UpdatedAt
|
|
tc.response[i].Credentials.Secret = t.Credentials.Secret
|
|
t.Status = tc.response[i].Status
|
|
}
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, rThing, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, rThing))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "Save", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("Save was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
}
|
|
}
|
|
|
|
func TestListThings(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
var ths []sdk.Thing
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
owner := generateUUID(t)
|
|
for i := 10; i < 100; i++ {
|
|
th := sdk.Thing{
|
|
ID: generateUUID(t),
|
|
Name: fmt.Sprintf("thing_%d", i),
|
|
Credentials: sdk.Credentials{
|
|
Identity: fmt.Sprintf("identity_%d", i),
|
|
Secret: generateUUID(t),
|
|
},
|
|
Metadata: sdk.Metadata{"name": fmt.Sprintf("thing_%d", i)},
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
if i == 50 {
|
|
th.Owner = owner
|
|
th.Status = mfclients.DisabledStatus.String()
|
|
th.Tags = []string{"tag1", "tag2"}
|
|
}
|
|
ths = append(ths, th)
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
status string
|
|
total uint64
|
|
offset uint64
|
|
limit uint64
|
|
name string
|
|
identifier string
|
|
ownerID string
|
|
tag string
|
|
metadata sdk.Metadata
|
|
err errors.SDKError
|
|
response []sdk.Thing
|
|
}{
|
|
{
|
|
desc: "get a list of things",
|
|
token: token,
|
|
limit: limit,
|
|
offset: offset,
|
|
total: total,
|
|
err: nil,
|
|
response: ths[offset:limit],
|
|
},
|
|
{
|
|
desc: "get a list of things with invalid token",
|
|
token: invalidToken,
|
|
offset: offset,
|
|
limit: limit,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedList, http.StatusInternalServerError),
|
|
response: nil,
|
|
},
|
|
{
|
|
desc: "get a list of things with empty token",
|
|
token: "",
|
|
offset: offset,
|
|
limit: limit,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedList, http.StatusInternalServerError),
|
|
response: nil,
|
|
},
|
|
{
|
|
desc: "get a list of things with zero limit",
|
|
token: token,
|
|
offset: offset,
|
|
limit: 0,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusInternalServerError),
|
|
response: nil,
|
|
},
|
|
{
|
|
desc: "get a list of things with limit greater than max",
|
|
token: token,
|
|
offset: offset,
|
|
limit: 110,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusInternalServerError),
|
|
response: []sdk.Thing(nil),
|
|
},
|
|
{
|
|
desc: "get a list of things with same identity",
|
|
token: token,
|
|
offset: 0,
|
|
limit: 1,
|
|
err: nil,
|
|
identifier: Identity,
|
|
metadata: sdk.Metadata{},
|
|
response: []sdk.Thing{ths[89]},
|
|
},
|
|
{
|
|
desc: "get a list of things with same identity and metadata",
|
|
token: token,
|
|
offset: 0,
|
|
limit: 1,
|
|
err: nil,
|
|
identifier: Identity,
|
|
metadata: sdk.Metadata{
|
|
"name": "client99",
|
|
},
|
|
response: []sdk.Thing{ths[89]},
|
|
},
|
|
{
|
|
desc: "list things with given metadata",
|
|
token: adminToken,
|
|
offset: 0,
|
|
limit: 1,
|
|
metadata: sdk.Metadata{
|
|
"name": "client99",
|
|
},
|
|
response: []sdk.Thing{ths[89]},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given name",
|
|
token: adminToken,
|
|
offset: 0,
|
|
limit: 1,
|
|
name: "client10",
|
|
response: []sdk.Thing{ths[0]},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given owner",
|
|
token: adminToken,
|
|
offset: 0,
|
|
limit: 1,
|
|
ownerID: owner,
|
|
response: []sdk.Thing{ths[50]},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given status",
|
|
token: adminToken,
|
|
offset: 0,
|
|
limit: 1,
|
|
status: mfclients.DisabledStatus.String(),
|
|
response: []sdk.Thing{ths[50]},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given tag",
|
|
token: adminToken,
|
|
offset: 0,
|
|
limit: 1,
|
|
tag: "tag1",
|
|
response: []sdk.Thing{ths[50]},
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
pm := sdk.PageMetadata{
|
|
Status: tc.status,
|
|
Total: total,
|
|
Offset: tc.offset,
|
|
Limit: tc.limit,
|
|
Name: tc.name,
|
|
OwnerID: tc.ownerID,
|
|
Metadata: tc.metadata,
|
|
Tag: tc.tag,
|
|
}
|
|
|
|
repoCall := cRepo.On("RetrieveAll", mock.Anything, mock.Anything).Return(mfclients.ClientsPage{Page: convertClientPage(pm), Clients: convertThings(tc.response)}, tc.err)
|
|
page, err := mfsdk.Things(pm, adminToken)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, page.Things, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, page))
|
|
repoCall.Unset()
|
|
}
|
|
}
|
|
|
|
func TestListThingsByChannel(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
var nThing = uint64(10)
|
|
var aThings = []sdk.Thing{}
|
|
|
|
for i := uint64(1); i < nThing; i++ {
|
|
thing := sdk.Thing{
|
|
Name: fmt.Sprintf("member_%d@example.com", i),
|
|
Credentials: sdk.Credentials{
|
|
Secret: generateUUID(t),
|
|
},
|
|
Tags: []string{"tag1", "tag2"},
|
|
Metadata: sdk.Metadata{"role": "client"},
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
aThings = append(aThings, thing)
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
channelID string
|
|
page sdk.PageMetadata
|
|
response []sdk.Thing
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "list things with authorized token",
|
|
token: adminToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{},
|
|
response: aThings,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with offset and limit",
|
|
token: adminToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{
|
|
Offset: 4,
|
|
Limit: nThing,
|
|
},
|
|
response: aThings[4:],
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given name",
|
|
token: adminToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{
|
|
Name: Identity,
|
|
Offset: 6,
|
|
Limit: nThing,
|
|
},
|
|
response: aThings[6:],
|
|
err: nil,
|
|
},
|
|
|
|
{
|
|
desc: "list things with given ownerID",
|
|
token: adminToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{
|
|
OwnerID: user.Owner,
|
|
Offset: 6,
|
|
Limit: nThing,
|
|
},
|
|
response: aThings[6:],
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given subject",
|
|
token: adminToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{
|
|
Subject: subject,
|
|
Offset: 6,
|
|
Limit: nThing,
|
|
},
|
|
response: aThings[6:],
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with given object",
|
|
token: adminToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{
|
|
Object: object,
|
|
Offset: 6,
|
|
Limit: nThing,
|
|
},
|
|
response: aThings[6:],
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list things with an invalid token",
|
|
token: invalidToken,
|
|
channelID: testsutil.GenerateUUID(t, idProvider),
|
|
page: sdk.PageMetadata{},
|
|
response: []sdk.Thing(nil),
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "list things with an invalid id",
|
|
token: adminToken,
|
|
channelID: mocks.WrongID,
|
|
page: sdk.PageMetadata{},
|
|
response: []sdk.Thing(nil),
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrNotFound, http.StatusNotFound),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := cRepo.On("Members", mock.Anything, tc.channelID, mock.Anything).Return(mfclients.MembersPage{Members: convertThings(tc.response)}, tc.err)
|
|
membersPage, err := mfsdk.ThingsByChannel(tc.channelID, tc.page, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, membersPage.Things, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, membersPage.Things))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "Members", mock.Anything, tc.channelID, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("Members was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
}
|
|
}
|
|
|
|
func TestThing(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
thing := sdk.Thing{
|
|
Name: "thingname",
|
|
Tags: []string{"tag1", "tag2"},
|
|
Credentials: sdk.Credentials{Identity: "clientidentity", Secret: generateUUID(t)},
|
|
Metadata: validMetadata,
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
thingID string
|
|
response sdk.Thing
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "view thing successfully",
|
|
response: thing,
|
|
token: adminToken,
|
|
thingID: generateUUID(t),
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "view thing with an invalid token",
|
|
response: sdk.Thing{},
|
|
token: invalidToken,
|
|
thingID: generateUUID(t),
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "view thing with valid token and invalid thing id",
|
|
response: sdk.Thing{},
|
|
token: adminToken,
|
|
thingID: mocks.WrongID,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrNotFound, http.StatusNotFound),
|
|
},
|
|
{
|
|
desc: "view thing with an invalid token and invalid thing id",
|
|
response: sdk.Thing{},
|
|
token: invalidToken,
|
|
thingID: mocks.WrongID,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("RetrieveByID", mock.Anything, tc.thingID).Return(convertThing(tc.response), tc.err)
|
|
rClient, err := mfsdk.Thing(tc.thingID, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, rClient, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, rClient))
|
|
if tc.err == nil {
|
|
ok := repoCall1.Parent.AssertCalled(t, "RetrieveByID", mock.Anything, tc.thingID)
|
|
assert.True(t, ok, fmt.Sprintf("RetrieveByID was not called on %s", tc.desc))
|
|
}
|
|
repoCall1.Unset()
|
|
repoCall.Unset()
|
|
}
|
|
}
|
|
|
|
func TestUpdateThing(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
thing := sdk.Thing{
|
|
ID: generateUUID(t),
|
|
Name: "clientname",
|
|
Credentials: sdk.Credentials{Secret: generateUUID(t)},
|
|
Metadata: validMetadata,
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
|
|
thing1 := thing
|
|
thing1.Name = "Updated client"
|
|
|
|
thing2 := thing
|
|
thing2.Metadata = sdk.Metadata{"role": "test"}
|
|
thing2.ID = invalidIdentity
|
|
|
|
cases := []struct {
|
|
desc string
|
|
thing sdk.Thing
|
|
response sdk.Thing
|
|
token string
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update thing name with valid token",
|
|
thing: thing1,
|
|
response: thing1,
|
|
token: adminToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update thing name with invalid token",
|
|
thing: thing1,
|
|
response: sdk.Thing{},
|
|
token: invalidToken,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update thing name with invalid id",
|
|
thing: thing2,
|
|
response: sdk.Thing{},
|
|
token: adminToken,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedUpdate, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "update thing that can't be marshalled",
|
|
thing: sdk.Thing{
|
|
Name: "test",
|
|
Metadata: map[string]interface{}{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("Update", mock.Anything, mock.Anything).Return(convertThing(tc.response), tc.err)
|
|
uClient, err := mfsdk.UpdateThing(tc.thing, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, uClient, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, uClient))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "EvaluateThingAccess", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("EvaluateThingAccess was not called on %s", tc.desc))
|
|
ok = repoCall1.Parent.AssertCalled(t, "Update", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("Update was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
func TestUpdateThingTags(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
thing := sdk.Thing{
|
|
ID: generateUUID(t),
|
|
Name: "clientname",
|
|
Tags: []string{"tag1", "tag2"},
|
|
Credentials: sdk.Credentials{Secret: generateUUID(t)},
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
|
|
thing1 := thing
|
|
thing1.Tags = []string{"updatedTag1", "updatedTag2"}
|
|
|
|
thing2 := thing
|
|
thing2.ID = invalidIdentity
|
|
|
|
cases := []struct {
|
|
desc string
|
|
thing sdk.Thing
|
|
response sdk.Thing
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update thing name with valid token",
|
|
thing: thing,
|
|
response: thing1,
|
|
token: adminToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update thing name with invalid token",
|
|
thing: thing1,
|
|
response: sdk.Thing{},
|
|
token: invalidToken,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update thing name with invalid id",
|
|
thing: thing2,
|
|
response: sdk.Thing{},
|
|
token: adminToken,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedUpdate, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "update thing that can't be marshalled",
|
|
thing: sdk.Thing{
|
|
Name: "test",
|
|
Metadata: map[string]interface{}{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("UpdateTags", mock.Anything, mock.Anything).Return(convertThing(tc.response), tc.err)
|
|
uClient, err := mfsdk.UpdateThingTags(tc.thing, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, uClient, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, uClient))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "EvaluateThingAccess", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("EvaluateThingAccess was not called on %s", tc.desc))
|
|
ok = repoCall1.Parent.AssertCalled(t, "UpdateTags", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("UpdateTags was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
func TestUpdateThingSecret(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
user.ID = generateUUID(t)
|
|
rthing := thing
|
|
rthing.Credentials.Secret, _ = phasher.Hash(user.Credentials.Secret)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
oldSecret string
|
|
newSecret string
|
|
token string
|
|
response sdk.Thing
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update thing secret with valid token",
|
|
oldSecret: thing.Credentials.Secret,
|
|
newSecret: "newSecret",
|
|
token: adminToken,
|
|
response: rthing,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update thing secret with invalid token",
|
|
oldSecret: thing.Credentials.Secret,
|
|
newSecret: "newPassword",
|
|
token: "non-existent",
|
|
response: sdk.Thing{},
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update thing secret with wrong old secret",
|
|
oldSecret: "oldSecret",
|
|
newSecret: "newSecret",
|
|
token: adminToken,
|
|
response: sdk.Thing{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrInvalidSecret, http.StatusBadRequest),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("UpdateSecret", mock.Anything, mock.Anything).Return(convertThing(tc.response), tc.err)
|
|
uClient, err := mfsdk.UpdateThingSecret(tc.oldSecret, tc.newSecret, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, uClient, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, uClient))
|
|
if tc.err == nil {
|
|
ok := repoCall1.Parent.AssertCalled(t, "UpdateSecret", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("UpdateSecret was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
func TestUpdateThingOwner(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
thing = sdk.Thing{
|
|
ID: generateUUID(t),
|
|
Name: "clientname",
|
|
Tags: []string{"tag1", "tag2"},
|
|
Credentials: sdk.Credentials{Identity: "clientidentity", Secret: generateUUID(t)},
|
|
Metadata: validMetadata,
|
|
Status: mfclients.EnabledStatus.String(),
|
|
Owner: "owner",
|
|
}
|
|
|
|
thing2 := thing
|
|
thing2.ID = invalidIdentity
|
|
|
|
cases := []struct {
|
|
desc string
|
|
thing sdk.Thing
|
|
response sdk.Thing
|
|
token string
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update thing name with valid token",
|
|
thing: thing,
|
|
response: thing,
|
|
token: adminToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update thing name with invalid token",
|
|
thing: thing2,
|
|
response: sdk.Thing{},
|
|
token: invalidToken,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update thing name with invalid id",
|
|
thing: thing2,
|
|
response: sdk.Thing{},
|
|
token: adminToken,
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedUpdate, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "update thing that can't be marshalled",
|
|
thing: sdk.Thing{
|
|
Name: "test",
|
|
Metadata: map[string]interface{}{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
response: sdk.Thing{},
|
|
token: token,
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("UpdateOwner", mock.Anything, mock.Anything).Return(convertThing(tc.response), tc.err)
|
|
uClient, err := mfsdk.UpdateThingOwner(tc.thing, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, uClient, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, uClient))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "EvaluateThingAccess", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("EvaluateThingAccess was not called on %s", tc.desc))
|
|
ok = repoCall1.Parent.AssertCalled(t, "UpdateOwner", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("UpdateOwner was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
func TestEnableThing(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
enabledThing1 := sdk.Thing{ID: testsutil.GenerateUUID(t, idProvider), Credentials: sdk.Credentials{Identity: "client1@example.com", Secret: generateUUID(t)}, Status: mfclients.EnabledStatus.String()}
|
|
disabledThing1 := sdk.Thing{ID: testsutil.GenerateUUID(t, idProvider), Credentials: sdk.Credentials{Identity: "client3@example.com", Secret: generateUUID(t)}, Status: mfclients.DisabledStatus.String()}
|
|
endisabledThing1 := disabledThing1
|
|
endisabledThing1.Status = mfclients.EnabledStatus.String()
|
|
endisabledThing1.ID = testsutil.GenerateUUID(t, idProvider)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
token string
|
|
thing sdk.Thing
|
|
response sdk.Thing
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "enable disabled thing",
|
|
id: disabledThing1.ID,
|
|
token: adminToken,
|
|
thing: disabledThing1,
|
|
response: endisabledThing1,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "enable enabled thing",
|
|
id: enabledThing1.ID,
|
|
token: adminToken,
|
|
thing: enabledThing1,
|
|
response: sdk.Thing{},
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedEnable, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "enable non-existing thing",
|
|
id: mocks.WrongID,
|
|
token: adminToken,
|
|
thing: sdk.Thing{},
|
|
response: sdk.Thing{},
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedEnable, http.StatusNotFound),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("RetrieveByID", mock.Anything, tc.id).Return(convertThing(tc.thing), tc.err)
|
|
repoCall2 := cRepo.On("ChangeStatus", mock.Anything, mock.Anything).Return(convertThing(tc.response), tc.err)
|
|
eClient, err := mfsdk.EnableThing(tc.id, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, eClient, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, eClient))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "EvaluateThingAccess", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("EvaluateThingAccess was not called on %s", tc.desc))
|
|
ok = repoCall1.Parent.AssertCalled(t, "RetrieveByID", mock.Anything, tc.id)
|
|
assert.True(t, ok, fmt.Sprintf("RetrieveByID was not called on %s", tc.desc))
|
|
ok = repoCall2.Parent.AssertCalled(t, "ChangeStatus", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("ChangeStatus was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
repoCall2.Unset()
|
|
}
|
|
|
|
cases2 := []struct {
|
|
desc string
|
|
token string
|
|
status string
|
|
metadata sdk.Metadata
|
|
response sdk.ThingsPage
|
|
size uint64
|
|
}{
|
|
{
|
|
desc: "list enabled clients",
|
|
status: mfclients.EnabledStatus.String(),
|
|
size: 2,
|
|
response: sdk.ThingsPage{
|
|
Things: []sdk.Thing{enabledThing1, endisabledThing1},
|
|
},
|
|
},
|
|
{
|
|
desc: "list disabled clients",
|
|
status: mfclients.DisabledStatus.String(),
|
|
size: 1,
|
|
response: sdk.ThingsPage{
|
|
Things: []sdk.Thing{disabledThing1},
|
|
},
|
|
},
|
|
{
|
|
desc: "list enabled and disabled clients",
|
|
status: mfclients.AllStatus.String(),
|
|
size: 3,
|
|
response: sdk.ThingsPage{
|
|
Things: []sdk.Thing{enabledThing1, disabledThing1, endisabledThing1},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases2 {
|
|
pm := sdk.PageMetadata{
|
|
Total: 100,
|
|
Offset: 0,
|
|
Limit: 100,
|
|
Status: tc.status,
|
|
}
|
|
repoCall := pRepo.On("CheckAdmin", mock.Anything, mock.Anything).Return(nil)
|
|
repoCall1 := cRepo.On("RetrieveAll", mock.Anything, mock.Anything).Return(convertThingsPage(tc.response), nil)
|
|
clientsPage, err := mfsdk.Things(pm, adminToken)
|
|
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
|
|
size := uint64(len(clientsPage.Things))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", tc.desc, tc.size, size))
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
func TestDisableThing(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
enabledThing1 := sdk.Thing{ID: testsutil.GenerateUUID(t, idProvider), Credentials: sdk.Credentials{Identity: "client1@example.com", Secret: generateUUID(t)}, Status: mfclients.EnabledStatus.String()}
|
|
disabledThing1 := sdk.Thing{ID: testsutil.GenerateUUID(t, idProvider), Credentials: sdk.Credentials{Identity: "client3@example.com", Secret: generateUUID(t)}, Status: mfclients.DisabledStatus.String()}
|
|
disenabledThing1 := enabledThing1
|
|
disenabledThing1.Status = mfclients.DisabledStatus.String()
|
|
disenabledThing1.ID = testsutil.GenerateUUID(t, idProvider)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
token string
|
|
thing sdk.Thing
|
|
response sdk.Thing
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "disable enabled thing",
|
|
id: enabledThing1.ID,
|
|
token: adminToken,
|
|
thing: enabledThing1,
|
|
response: disenabledThing1,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "disable disabled thing",
|
|
id: disabledThing1.ID,
|
|
token: adminToken,
|
|
thing: disabledThing1,
|
|
response: sdk.Thing{},
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedDisable, http.StatusInternalServerError),
|
|
},
|
|
{
|
|
desc: "disable non-existing thing",
|
|
id: mocks.WrongID,
|
|
thing: sdk.Thing{},
|
|
token: adminToken,
|
|
response: sdk.Thing{},
|
|
err: errors.NewSDKErrorWithStatus(sdk.ErrFailedDisable, http.StatusNotFound),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := cRepo.On("RetrieveByID", mock.Anything, tc.id).Return(convertThing(tc.thing), tc.err)
|
|
repoCall2 := cRepo.On("ChangeStatus", mock.Anything, mock.Anything).Return(convertThing(tc.response), tc.err)
|
|
dThing, err := mfsdk.DisableThing(tc.id, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, dThing, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, dThing))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "EvaluateThingAccess", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("EvaluateThingAccess was not called on %s", tc.desc))
|
|
ok = repoCall1.Parent.AssertCalled(t, "RetrieveByID", mock.Anything, tc.id)
|
|
assert.True(t, ok, fmt.Sprintf("RetrieveByID was not called on %s", tc.desc))
|
|
ok = repoCall2.Parent.AssertCalled(t, "ChangeStatus", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("ChangeStatus was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
repoCall2.Unset()
|
|
}
|
|
|
|
cases2 := []struct {
|
|
desc string
|
|
token string
|
|
status string
|
|
metadata sdk.Metadata
|
|
response sdk.ThingsPage
|
|
size uint64
|
|
}{
|
|
{
|
|
desc: "list enabled things",
|
|
status: mfclients.EnabledStatus.String(),
|
|
size: 2,
|
|
response: sdk.ThingsPage{
|
|
Things: []sdk.Thing{enabledThing1, disenabledThing1},
|
|
},
|
|
},
|
|
{
|
|
desc: "list disabled things",
|
|
status: mfclients.DisabledStatus.String(),
|
|
size: 1,
|
|
response: sdk.ThingsPage{
|
|
Things: []sdk.Thing{disabledThing1},
|
|
},
|
|
},
|
|
{
|
|
desc: "list enabled and disabled things",
|
|
status: mfclients.AllStatus.String(),
|
|
size: 3,
|
|
response: sdk.ThingsPage{
|
|
Things: []sdk.Thing{enabledThing1, disabledThing1, disenabledThing1},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases2 {
|
|
pm := sdk.PageMetadata{
|
|
Total: 100,
|
|
Offset: 0,
|
|
Limit: 100,
|
|
Status: tc.status,
|
|
}
|
|
repoCall := pRepo.On("CheckAdmin", mock.Anything, mock.Anything).Return(nil)
|
|
repoCall1 := cRepo.On("RetrieveAll", mock.Anything, mock.Anything).Return(convertThingsPage(tc.response), nil)
|
|
page, err := mfsdk.Things(pm, adminToken)
|
|
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
|
|
size := uint64(len(page.Things))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", tc.desc, tc.size, size))
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
}
|
|
}
|
|
|
|
func TestIdentify(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
thing = sdk.Thing{
|
|
ID: generateUUID(t),
|
|
Name: "clientname",
|
|
Credentials: sdk.Credentials{Identity: "clientidentity", Secret: generateUUID(t)},
|
|
Status: mfclients.EnabledStatus.String(),
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
secret string
|
|
response string
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "identify thing successfully",
|
|
response: thing.ID,
|
|
secret: thing.Credentials.Secret,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "identify thing with an invalid token",
|
|
response: "",
|
|
secret: invalidToken,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := cRepo.On("RetrieveBySecret", mock.Anything, mock.Anything).Return(convertThing(thing), tc.err)
|
|
id, err := mfsdk.IdentifyThing(tc.secret)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, id, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, id))
|
|
if tc.err == nil {
|
|
ok := repoCall.Parent.AssertCalled(t, "RetrieveBySecret", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("RetrieveBySecret was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
}
|
|
}
|
|
|
|
func TestShareThing(t *testing.T) {
|
|
cRepo := new(mocks.Repository)
|
|
gRepo := new(gmocks.Repository)
|
|
uauth := cmocks.NewAuthService(users, map[string][]cmocks.SubjectSet{adminID: {uadminPolicy}})
|
|
thingCache := mocks.NewCache()
|
|
policiesCache := pmocks.NewCache()
|
|
|
|
pRepo := new(pmocks.Repository)
|
|
psvc := policies.NewService(uauth, pRepo, policiesCache, idProvider)
|
|
|
|
svc := clients.NewService(uauth, psvc, cRepo, gRepo, thingCache, idProvider)
|
|
ts := newThingsServer(svc, psvc)
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
ThingsURL: ts.URL,
|
|
}
|
|
mfsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
groupID string
|
|
userID string
|
|
token string
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "share thing with valid token",
|
|
groupID: generateUUID(t),
|
|
userID: generateUUID(t),
|
|
token: adminToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "share thing with invalid token",
|
|
groupID: generateUUID(t),
|
|
userID: generateUUID(t),
|
|
token: invalidToken,
|
|
err: errors.NewSDKErrorWithStatus(errors.ErrAuthorization, http.StatusUnauthorized),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
repoCall := pRepo.On("EvaluateGroupAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall1 := pRepo.On("EvaluateThingAccess", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
repoCall3 := pRepo.On("Retrieve", mock.Anything, mock.Anything).Return(policies.PolicyPage{}, nil)
|
|
repoCall4 := pRepo.On("Save", mock.Anything, mock.Anything).Return(policies.Policy{}, nil)
|
|
err := mfsdk.ShareThing(tc.groupID, tc.userID, []string{"c_list", "c_delete"}, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err))
|
|
if tc.err == nil {
|
|
ok := repoCall4.Parent.AssertCalled(t, "Save", mock.Anything, mock.Anything)
|
|
assert.True(t, ok, fmt.Sprintf("Save was not called on %s", tc.desc))
|
|
}
|
|
repoCall.Unset()
|
|
repoCall1.Unset()
|
|
repoCall3.Unset()
|
|
repoCall4.Unset()
|
|
}
|
|
}
|