NOISSUE - Add test cases for Provision service (#191)

Add test cases for a provision service. The test cases check for valid and invalid tokens, verify the returned content and errors, and test scenarios for configuring the provision service with different authentication methods and expected outcomes.
Additionally, a test function has been added to check the behavior of the "Cert" service method by setting expectations on certain SDK method calls and asserting the expected values for the returned certificate, key, and error.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
This commit is contained in:
b1ackd0t
2024-01-03 12:33:48 +03:00
committed by GitHub
parent 41d9e1bdd0
commit 2ba2237bcc
3 changed files with 227 additions and 6 deletions
+1
View File
@@ -27,6 +27,7 @@ type ServiceConf struct {
HTTPPort string `toml:"http_port" env:"MG_PROVISION_HTTP_PORT" envDefault:"9016"`
MgUser string `toml:"mg_user" env:"MG_PROVISION_USER" envDefault:"test@example.com"`
MgPass string `toml:"mg_pass" env:"MG_PROVISION_PASS" envDefault:"test"`
MgDomainID string `toml:"mg_domain_id" env:"MG_PROVISION_DOMAIN_ID" envDefault:""`
MgAPIKey string `toml:"mg_api_key" env:"MG_PROVISION_API_KEY" envDefault:""`
MgBSURL string `toml:"mg_bs_url" env:"MG_PROVISION_BS_SVC_URL" envDefault:"http://localhost:9000/things/configs"`
MgWhiteListURL string `toml:"mg_white_list" env:"MG_PROVISION_BS_SVC_WHITELIST_URL" envDefault:"http://localhost:9000/things/state"`
+6 -6
View File
@@ -95,16 +95,15 @@ func New(cfg Config, mgsdk sdk.SDK, logger mglog.Logger) Service {
// Mapping retrieves current configuration.
func (ps *provisionService) Mapping(token string) (map[string]interface{}, error) {
userFilter := sdk.PageMetadata{
Identity: "",
Offset: uint64(offset),
Limit: uint64(limit),
Metadata: make(map[string]interface{}),
pm := sdk.PageMetadata{
Offset: uint64(offset),
Limit: uint64(limit),
}
if _, err := ps.sdk.Users(userFilter, token); err != nil {
if _, err := ps.sdk.Users(pm, token); err != nil {
return map[string]interface{}{}, errors.Wrap(ErrUnauthorized, err)
}
return ps.conf.Bootstrap.Content, nil
}
@@ -287,6 +286,7 @@ func (ps *provisionService) createTokenIfEmpty(token string) (string, error) {
u := sdk.Login{
Identity: ps.conf.Server.MgUser,
Secret: ps.conf.Server.MgPass,
DomainID: ps.conf.Server.MgDomainID,
}
tkn, err := ps.sdk.CreateToken(u)
if err != nil {
+220
View File
@@ -0,0 +1,220 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package provision_test
import (
"fmt"
"testing"
"github.com/absmach/magistrala/internal/testsutil"
mglog "github.com/absmach/magistrala/logger"
"github.com/absmach/magistrala/pkg/errors"
sdk "github.com/absmach/magistrala/pkg/sdk/go"
sdkmocks "github.com/absmach/magistrala/pkg/sdk/mocks"
"github.com/absmach/magistrala/provision"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
var validToken = "valid"
func TestMapping(t *testing.T) {
mgsdk := new(sdkmocks.SDK)
svc := provision.New(validConfig, mgsdk, mglog.NewMock())
cases := []struct {
desc string
token string
content map[string]interface{}
sdkerr error
err error
}{
{
desc: "valid token",
token: validToken,
content: validConfig.Bootstrap.Content,
sdkerr: nil,
err: nil,
},
{
desc: "invalid token",
token: "invalid",
content: map[string]interface{}{},
sdkerr: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, 401),
err: provision.ErrUnauthorized,
},
}
for _, c := range cases {
t.Run(c.desc, func(t *testing.T) {
pm := sdk.PageMetadata{Offset: uint64(0), Limit: uint64(10)}
repocall := mgsdk.On("Users", pm, c.token).Return(sdk.UsersPage{}, c.sdkerr)
content, err := svc.Mapping(c.token)
assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected error %v, got %v", c.err, err))
assert.Equal(t, c.content, content)
repocall.Unset()
})
}
}
func TestCert(t *testing.T) {
cases := []struct {
desc string
config provision.Config
token string
thingID string
ttl string
cert string
key string
sdkThingErr error
sdkCertErr error
sdkTokenErr error
err error
}{
{
desc: "valid",
config: validConfig,
token: validToken,
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "cert",
key: "key",
sdkThingErr: nil,
sdkCertErr: nil,
sdkTokenErr: nil,
err: nil,
},
{
desc: "empty token with config API key",
config: provision.Config{
Server: provision.ServiceConf{MgAPIKey: "key"},
Cert: provision.Cert{TTL: "1h"},
},
token: "",
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "cert",
key: "key",
sdkThingErr: nil,
sdkCertErr: nil,
sdkTokenErr: nil,
err: nil,
},
{
desc: "empty token with username and password",
config: provision.Config{
Server: provision.ServiceConf{
MgUser: "test@example.com",
MgPass: "12345678",
MgDomainID: testsutil.GenerateUUID(t),
},
Cert: provision.Cert{TTL: "1h"},
},
token: "",
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "cert",
key: "key",
sdkThingErr: nil,
sdkCertErr: nil,
sdkTokenErr: nil,
err: nil,
},
{
desc: "empty token with username and invalid password",
config: provision.Config{
Server: provision.ServiceConf{
MgUser: "test@example.com",
MgPass: "12345678",
MgDomainID: testsutil.GenerateUUID(t),
},
Cert: provision.Cert{TTL: "1h"},
},
token: "",
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "",
key: "",
sdkThingErr: nil,
sdkCertErr: nil,
sdkTokenErr: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, 401),
err: provision.ErrFailedToCreateToken,
},
{
desc: "empty token with empty username and password",
config: provision.Config{
Server: provision.ServiceConf{},
Cert: provision.Cert{TTL: "1h"},
},
token: "",
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "",
key: "",
sdkThingErr: nil,
sdkCertErr: nil,
sdkTokenErr: nil,
err: provision.ErrMissingCredentials,
},
{
desc: "invalid thingID",
config: validConfig,
token: "invalid",
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "",
key: "",
sdkThingErr: errors.NewSDKErrorWithStatus(errors.ErrAuthentication, 401),
sdkCertErr: nil,
sdkTokenErr: nil,
err: provision.ErrUnauthorized,
},
{
desc: "invalid thingID",
config: validConfig,
token: validToken,
thingID: "invalid",
ttl: "1h",
cert: "",
key: "",
sdkThingErr: errors.NewSDKErrorWithStatus(errors.ErrNotFound, 404),
sdkCertErr: nil,
sdkTokenErr: nil,
err: provision.ErrUnauthorized,
},
{
desc: "failed to issue cert",
config: validConfig,
token: validToken,
thingID: testsutil.GenerateUUID(t),
ttl: "1h",
cert: "",
key: "",
sdkThingErr: nil,
sdkTokenErr: nil,
sdkCertErr: errors.NewSDKError(errors.ErrCreateEntity),
err: errors.ErrCreateEntity,
},
}
for _, c := range cases {
t.Run(c.desc, func(t *testing.T) {
mgsdk := new(sdkmocks.SDK)
svc := provision.New(c.config, mgsdk, mglog.NewMock())
mgsdk.On("Thing", c.thingID, mock.Anything).Return(sdk.Thing{ID: c.thingID}, c.sdkThingErr)
mgsdk.On("IssueCert", c.thingID, c.config.Cert.TTL, mock.Anything).Return(sdk.Cert{ClientCert: c.cert, ClientKey: c.key}, c.sdkCertErr)
login := sdk.Login{
Identity: c.config.Server.MgUser,
Secret: c.config.Server.MgPass,
DomainID: c.config.Server.MgDomainID,
}
mgsdk.On("CreateToken", login).Return(sdk.Token{AccessToken: validToken}, c.sdkTokenErr)
cert, key, err := svc.Cert(c.token, c.thingID, c.ttl)
assert.Equal(t, c.cert, cert)
assert.Equal(t, c.key, key)
assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected error %v, got %v", c.err, err))
})
}
}