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

* Uncomment all code Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(linters): add godox and dupword linters This commit adds two new linters, godox and dupword, to the linter configuration file (.golangci.yml). The godox linter checks for occurrences of TODO and FIXME comments in the codebase, helping to ensure that these comments are not forgotten or left unresolved. The dupword linter detects duplicate words in comments and strings, which can be a sign of typos or errors. These new linters will enhance the code quality and maintainability of the project. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * uncomment tests in /pkg/sdk/go/tokens_test.go Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --------- Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
798 lines
21 KiB
Go
798 lines
21 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package bootstrap_test
|
|
|
|
import (
|
|
"context"
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"net/http/httptest"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/mainflux/mainflux"
|
|
authmocks "github.com/mainflux/mainflux/auth/mocks"
|
|
"github.com/mainflux/mainflux/bootstrap"
|
|
"github.com/mainflux/mainflux/bootstrap/mocks"
|
|
"github.com/mainflux/mainflux/internal/groups"
|
|
chmocks "github.com/mainflux/mainflux/internal/groups/mocks"
|
|
mflog "github.com/mainflux/mainflux/logger"
|
|
"github.com/mainflux/mainflux/pkg/errors"
|
|
mfgroups "github.com/mainflux/mainflux/pkg/groups"
|
|
mfsdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
|
"github.com/mainflux/mainflux/pkg/uuid"
|
|
"github.com/mainflux/mainflux/things"
|
|
thapi "github.com/mainflux/mainflux/things/api/http"
|
|
thmocks "github.com/mainflux/mainflux/things/mocks"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
validToken = "validToken"
|
|
invalidToken = "invalidToken"
|
|
email = "test@example.com"
|
|
unknown = "unknown"
|
|
channelsNum = 3
|
|
instanceID = "5de9b29a-feb9-11ed-be56-0242ac120002"
|
|
)
|
|
|
|
var (
|
|
encKey = []byte("1234567891011121")
|
|
|
|
channel = bootstrap.Channel{
|
|
ID: "1",
|
|
Name: "name",
|
|
Metadata: map[string]interface{}{"name": "value"},
|
|
}
|
|
|
|
config = bootstrap.Config{
|
|
ExternalID: "external_id",
|
|
ExternalKey: "external_key",
|
|
Channels: []bootstrap.Channel{channel},
|
|
Content: "config",
|
|
}
|
|
)
|
|
|
|
func newService(url string, auth mainflux.AuthServiceClient) bootstrap.Service {
|
|
things := mocks.NewConfigsRepository()
|
|
config := mfsdk.Config{
|
|
ThingsURL: url,
|
|
}
|
|
|
|
sdk := mfsdk.NewSDK(config)
|
|
return bootstrap.New(auth, things, sdk, encKey)
|
|
}
|
|
|
|
func newThingsService() (things.Service, mfgroups.Service, mainflux.AuthServiceClient) {
|
|
auth := new(authmocks.Service)
|
|
thingCache := thmocks.NewCache()
|
|
idProvider := uuid.NewMock()
|
|
cRepo := new(thmocks.Repository)
|
|
gRepo := new(chmocks.Repository)
|
|
|
|
return things.NewService(auth, cRepo, gRepo, thingCache, idProvider), groups.NewService(gRepo, idProvider, auth), auth
|
|
}
|
|
|
|
func newThingsServer(tsvc things.Service, gsvc mfgroups.Service) *httptest.Server {
|
|
logger := mflog.NewMock()
|
|
mux := chi.NewRouter()
|
|
thapi.MakeHandler(tsvc, gsvc, mux, logger, instanceID)
|
|
|
|
return httptest.NewServer(mux)
|
|
}
|
|
|
|
func enc(in []byte) ([]byte, error) {
|
|
block, err := aes.NewCipher(encKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ciphertext := make([]byte, aes.BlockSize+len(in))
|
|
iv := ciphertext[:aes.BlockSize]
|
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
return nil, err
|
|
}
|
|
stream := cipher.NewCFBEncrypter(block, iv)
|
|
stream.XORKeyStream(ciphertext[aes.BlockSize:], in)
|
|
return ciphertext, nil
|
|
}
|
|
|
|
func TestAdd(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
neID := config
|
|
neID.ThingID = "non-existent"
|
|
|
|
wrongChannels := config
|
|
ch := channel
|
|
ch.ID = "invalid"
|
|
wrongChannels.Channels = append(wrongChannels.Channels, ch)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
config bootstrap.Config
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "add a new config",
|
|
config: config,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "add a config with an invalid ID",
|
|
config: neID,
|
|
token: validToken,
|
|
err: errors.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "add a config with wrong credentials",
|
|
config: config,
|
|
token: invalidToken,
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
{
|
|
desc: "add a config with invalid list of channels",
|
|
config: wrongChannels,
|
|
token: validToken,
|
|
err: errors.ErrMalformedEntity,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
_, err := svc.Add(context.Background(), tc.token, tc.config)
|
|
switch err {
|
|
case nil:
|
|
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error : %s", tc.desc, err))
|
|
default:
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestView(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
saved, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "view an existing config",
|
|
id: saved.ThingID,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "view a non-existing config",
|
|
id: unknown,
|
|
token: validToken,
|
|
err: errors.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "view a config with wrong credentials",
|
|
id: config.ThingID,
|
|
token: invalidToken,
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
_, err := svc.View(context.Background(), tc.token, tc.id)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
c := config
|
|
|
|
ch := channel
|
|
ch.ID = "2"
|
|
c.Channels = append(c.Channels, ch)
|
|
saved, err := svc.Add(context.Background(), validToken, c)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
modifiedCreated := saved
|
|
modifiedCreated.Content = "new-config"
|
|
modifiedCreated.Name = "new name"
|
|
|
|
nonExisting := config
|
|
nonExisting.ThingID = unknown
|
|
|
|
cases := []struct {
|
|
desc string
|
|
config bootstrap.Config
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update a config with state Created",
|
|
config: modifiedCreated,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update a non-existing config",
|
|
config: nonExisting,
|
|
token: validToken,
|
|
err: errors.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "update a config with wrong credentials",
|
|
config: saved,
|
|
token: invalidToken,
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.Update(context.Background(), tc.token, tc.config)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestUpdateCert(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
c := config
|
|
|
|
ch := channel
|
|
ch.ID = "2"
|
|
c.Channels = append(c.Channels, ch)
|
|
saved, err := svc.Add(context.Background(), validToken, c)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
thingKey string
|
|
clientCert string
|
|
clientKey string
|
|
caCert string
|
|
expectedConfig bootstrap.Config
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update certs for the valid config",
|
|
thingKey: saved.ThingKey,
|
|
clientCert: "newCert",
|
|
clientKey: "newKey",
|
|
caCert: "newCert",
|
|
token: validToken,
|
|
expectedConfig: bootstrap.Config{
|
|
Name: saved.Name,
|
|
ThingKey: saved.ThingKey,
|
|
Channels: saved.Channels,
|
|
ExternalID: saved.ExternalID,
|
|
ExternalKey: saved.ExternalKey,
|
|
Content: saved.Content,
|
|
State: saved.State,
|
|
Owner: saved.Owner,
|
|
ThingID: saved.ThingID,
|
|
ClientCert: "newCert",
|
|
CACert: "newCert",
|
|
ClientKey: "newKey",
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update cert for a non-existing config",
|
|
thingKey: "empty",
|
|
clientCert: "newCert",
|
|
clientKey: "newKey",
|
|
caCert: "newCert",
|
|
token: validToken,
|
|
expectedConfig: bootstrap.Config{},
|
|
err: errors.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "update config cert with wrong credentials",
|
|
thingKey: saved.ThingKey,
|
|
clientCert: "newCert",
|
|
clientKey: "newKey",
|
|
caCert: "newCert",
|
|
token: invalidToken,
|
|
expectedConfig: bootstrap.Config{},
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
cfg, err := svc.UpdateCert(context.Background(), tc.token, tc.thingKey, tc.clientCert, tc.clientKey, tc.caCert)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
sort.Slice(cfg.Channels, func(i, j int) bool {
|
|
return cfg.Channels[i].ID < cfg.Channels[j].ID
|
|
})
|
|
sort.Slice(tc.expectedConfig.Channels, func(i, j int) bool {
|
|
return tc.expectedConfig.Channels[i].ID < tc.expectedConfig.Channels[j].ID
|
|
})
|
|
assert.Equal(t, tc.expectedConfig, cfg, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.expectedConfig, cfg))
|
|
}
|
|
}
|
|
|
|
func TestUpdateConnections(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
c := config
|
|
|
|
ch := channel
|
|
ch.ID = "2"
|
|
c.Channels = append(c.Channels, ch)
|
|
created, err := svc.Add(context.Background(), validToken, c)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
externalID, err := uuid.New().ID()
|
|
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
|
c.ExternalID = externalID
|
|
active, err := svc.Add(context.Background(), validToken, c)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
err = svc.ChangeState(context.Background(), validToken, active.ThingID, bootstrap.Active)
|
|
assert.Nil(t, err, fmt.Sprintf("Changing state expected to succeed: %s.\n", err))
|
|
|
|
nonExisting := config
|
|
nonExisting.ThingID = unknown
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
id string
|
|
connections []string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update connections for config with state Inactive",
|
|
token: validToken,
|
|
id: created.ThingID,
|
|
connections: []string{"2"},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update connections for config with state Active",
|
|
token: validToken,
|
|
id: active.ThingID,
|
|
connections: []string{"3"},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update connections for non-existing config",
|
|
token: validToken,
|
|
id: "",
|
|
connections: []string{"3"},
|
|
err: errors.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "update connections with invalid channels",
|
|
token: validToken,
|
|
id: created.ThingID,
|
|
connections: []string{"wrong"},
|
|
err: errors.ErrMalformedEntity,
|
|
},
|
|
{
|
|
desc: "update connections a config with wrong credentials",
|
|
token: invalidToken,
|
|
id: created.ThingKey,
|
|
connections: []string{"2", "3"},
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.UpdateConnections(context.Background(), tc.token, tc.id, tc.connections)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestList(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
numThings := 101
|
|
var saved []bootstrap.Config
|
|
for i := 0; i < numThings; i++ {
|
|
c := config
|
|
id, err := uuid.New().ID()
|
|
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
|
c.ExternalID = id
|
|
c.ExternalKey = id
|
|
c.Name = fmt.Sprintf("%s-%d", config.Name, i)
|
|
s, err := svc.Add(context.Background(), validToken, c)
|
|
saved = append(saved, s)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
}
|
|
// Set one Thing to the different state
|
|
err := svc.ChangeState(context.Background(), validToken, "42", bootstrap.Active)
|
|
assert.Nil(t, err, fmt.Sprintf("Changing config state expected to succeed: %s.\n", err))
|
|
saved[41].State = bootstrap.Active
|
|
|
|
cases := []struct {
|
|
desc string
|
|
config bootstrap.ConfigsPage
|
|
filter bootstrap.Filter
|
|
offset uint64
|
|
limit uint64
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "list configs",
|
|
config: bootstrap.ConfigsPage{
|
|
Total: uint64(len(saved)),
|
|
Offset: 0,
|
|
Limit: 10,
|
|
Configs: saved[0:10],
|
|
},
|
|
filter: bootstrap.Filter{},
|
|
token: validToken,
|
|
offset: 0,
|
|
limit: 10,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list configs with specified name",
|
|
config: bootstrap.ConfigsPage{
|
|
Total: 1,
|
|
Offset: 0,
|
|
Limit: 100,
|
|
Configs: saved[95:96],
|
|
},
|
|
filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "95"}},
|
|
token: validToken,
|
|
offset: 0,
|
|
limit: 100,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list configs with invalid token",
|
|
config: bootstrap.ConfigsPage{},
|
|
filter: bootstrap.Filter{},
|
|
token: invalidToken,
|
|
offset: 0,
|
|
limit: 10,
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
{
|
|
desc: "list last page",
|
|
config: bootstrap.ConfigsPage{
|
|
Total: uint64(len(saved)),
|
|
Offset: 95,
|
|
Limit: 10,
|
|
Configs: saved[95:],
|
|
},
|
|
filter: bootstrap.Filter{},
|
|
token: validToken,
|
|
offset: 95,
|
|
limit: 10,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list configs with Active state",
|
|
config: bootstrap.ConfigsPage{
|
|
Total: 1,
|
|
Offset: 35,
|
|
Limit: 20,
|
|
Configs: []bootstrap.Config{saved[41]},
|
|
},
|
|
filter: bootstrap.Filter{FullMatch: map[string]string{"state": bootstrap.Active.String()}},
|
|
token: validToken,
|
|
offset: 35,
|
|
limit: 20,
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
result, err := svc.List(context.Background(), tc.token, tc.filter, tc.offset, tc.limit)
|
|
assert.ElementsMatch(t, tc.config.Configs, result.Configs, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Configs, result.Configs))
|
|
assert.Equal(t, tc.config.Total, result.Total, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Total, result.Total))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestRemove(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
saved, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "view a config with wrong credentials",
|
|
id: saved.ThingID,
|
|
token: invalidToken,
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
{
|
|
desc: "remove an existing config",
|
|
id: saved.ThingID,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "remove removed config",
|
|
id: saved.ThingID,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "remove non-existing config",
|
|
id: unknown,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.Remove(context.Background(), tc.token, tc.id)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestBootstrap(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
saved, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
e, err := enc([]byte(saved.ExternalKey))
|
|
assert.Nil(t, err, fmt.Sprintf("Encrypting external key expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
config bootstrap.Config
|
|
externalKey string
|
|
externalID string
|
|
err error
|
|
encrypted bool
|
|
}{
|
|
{
|
|
desc: "bootstrap using invalid external id",
|
|
config: bootstrap.Config{},
|
|
externalID: "invalid",
|
|
externalKey: saved.ExternalKey,
|
|
err: errors.ErrNotFound,
|
|
encrypted: false,
|
|
},
|
|
{
|
|
desc: "bootstrap using invalid external key",
|
|
config: bootstrap.Config{},
|
|
externalID: saved.ExternalID,
|
|
externalKey: "invalid",
|
|
err: bootstrap.ErrExternalKey,
|
|
encrypted: false,
|
|
},
|
|
{
|
|
desc: "bootstrap an existing config",
|
|
config: saved,
|
|
externalID: saved.ExternalID,
|
|
externalKey: saved.ExternalKey,
|
|
err: nil,
|
|
encrypted: false,
|
|
},
|
|
{
|
|
desc: "bootstrap encrypted",
|
|
config: saved,
|
|
externalID: saved.ExternalID,
|
|
externalKey: hex.EncodeToString(e),
|
|
err: nil,
|
|
encrypted: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
config, err := svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, tc.encrypted)
|
|
assert.Equal(t, tc.config, config, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.config, config))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestChangeState(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
saved, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
state bootstrap.State
|
|
id string
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "change state with wrong credentials",
|
|
state: bootstrap.Active,
|
|
id: saved.ThingID,
|
|
token: invalidToken,
|
|
err: errors.ErrAuthentication,
|
|
},
|
|
{
|
|
desc: "change state of non-existing config",
|
|
state: bootstrap.Active,
|
|
id: unknown,
|
|
token: validToken,
|
|
err: errors.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "change state to Active",
|
|
state: bootstrap.Active,
|
|
id: saved.ThingID,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "change state to current state",
|
|
state: bootstrap.Active,
|
|
id: saved.ThingID,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "change state to Inactive",
|
|
state: bootstrap.Inactive,
|
|
id: saved.ThingID,
|
|
token: validToken,
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.ChangeState(context.Background(), tc.token, tc.id, tc.state)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestUpdateChannelHandler(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
_, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
ch := bootstrap.Channel{
|
|
ID: channel.ID,
|
|
Name: "new name",
|
|
Metadata: map[string]interface{}{"meta": "new"},
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
channel bootstrap.Channel
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update an existing channel",
|
|
channel: ch,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update a non-existing channel",
|
|
channel: bootstrap.Channel{ID: ""},
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.UpdateChannelHandler(context.Background(), tc.channel)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestRemoveChannelHandler(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
_, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "remove an existing channel",
|
|
id: channel.ID,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "remove a non-existing channel",
|
|
id: "unknown",
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.RemoveChannelHandler(context.Background(), tc.id)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestRemoveCoinfigHandler(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
saved, err := svc.Add(context.Background(), validToken, config)
|
|
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "remove an existing config",
|
|
id: saved.ThingID,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "remove a non-existing channel",
|
|
id: "unknown",
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.RemoveConfigHandler(context.Background(), tc.id)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestDisconnectThingsHandler(t *testing.T) {
|
|
tsvc, gsvc, auth := newThingsService()
|
|
ts := newThingsServer(tsvc, gsvc)
|
|
svc := newService(ts.URL, auth)
|
|
saved, err := svc.Add(context.Background(), validToken, config)
|
|
require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
thingID string
|
|
channelID string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "disconnect",
|
|
channelID: channel.ID,
|
|
thingID: saved.ThingID,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "disconnect disconnected",
|
|
channelID: channel.ID,
|
|
thingID: saved.ThingID,
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.DisconnectThingHandler(context.Background(), tc.channelID, tc.thingID)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|