NOISSUE - Improve tests in users service (#194)

Signed-off-by: felix.gateru <felix.gateru@gmail.com>
This commit is contained in:
Felix Gateru
2024-01-18 19:14:46 +03:00
committed by GitHub
parent e7129fe502
commit d7cd911613
8 changed files with 6316 additions and 850 deletions
-18
View File
@@ -1458,15 +1458,6 @@ components:
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Visibility:
name: visibility
description: The visibility specifier when listing users. Either all, shared or mine.
in: path
schema:
type: string
required: true
example: all
UserName:
name: name
description: User's name.
@@ -1505,15 +1496,6 @@ components:
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
UserVisibility:
name: visibility
description: visibility to list either users I own or users that are shared with me or both users I own and shared with me
in: query
schema:
type: string
required: false
example: shared
Status:
name: status
description: User account status.
+2 -26
View File
@@ -189,7 +189,6 @@ func decodeViewProfile(_ context.Context, r *http.Request) (interface{}, error)
}
func decodeListClients(_ context.Context, r *http.Request) (interface{}, error) {
var sharedID, ownerID string
s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefClientStatus)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
@@ -222,10 +221,6 @@ func decodeListClients(_ context.Context, r *http.Request) (interface{}, error)
if err != nil {
return nil, err
}
visibility, err := apiutil.ReadStringQuery(r, api.VisibilityKey, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
order, err := apiutil.ReadStringQuery(r, api.OrderKey, api.DefOrder)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
@@ -234,18 +229,6 @@ func decodeListClients(_ context.Context, r *http.Request) (interface{}, error)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
switch visibility {
case api.MyVisibility:
ownerID = api.MyVisibility
case api.SharedVisibility:
sharedID = api.MyVisibility
case api.AllVisibility:
sharedID = api.MyVisibility
ownerID = api.MyVisibility
}
if oid != "" {
ownerID = oid
}
st, err := mgclients.ToStatus(s)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
@@ -259,8 +242,7 @@ func decodeListClients(_ context.Context, r *http.Request) (interface{}, error)
name: n,
identity: i,
tag: t,
sharedBy: sharedID,
owner: ownerID,
owner: oid,
order: order,
dir: dir,
}
@@ -473,13 +455,7 @@ func decodeListMembersByDomain(_ context.Context, r *http.Request) (interface{},
if err != nil {
return nil, err
}
// For domains default permission in membership, In "queryPageParams" default is view,
// so overwriting the permission given by queryPageParams function with default membership permission.
p, err := apiutil.ReadStringQuery(r, api.PermissionKey, auth.MembershipPermission)
if err != nil {
return mgclients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
page.Permission = p
req := listMembersByObjectReq{
token: apiutil.ExtractBearerToken(r),
Page: page,
File diff suppressed because it is too large Load Diff
+11 -19
View File
@@ -53,19 +53,17 @@ func (req viewProfileReq) validate() error {
}
type listClientsReq struct {
token string
status mgclients.Status
offset uint64
limit uint64
name string
tag string
identity string
visibility string
owner string
sharedBy string
metadata mgclients.Metadata
order string
dir string
token string
status mgclients.Status
offset uint64
limit uint64
name string
tag string
identity string
owner string
metadata mgclients.Metadata
order string
dir string
}
func (req listClientsReq) validate() error {
@@ -75,12 +73,6 @@ func (req listClientsReq) validate() error {
if req.limit > maxLimitSize || req.limit < 1 {
return apiutil.ErrLimitSize
}
if req.visibility != "" &&
req.visibility != api.AllVisibility &&
req.visibility != api.MyVisibility &&
req.visibility != api.SharedVisibility {
return apiutil.ErrInvalidVisibilityType
}
if req.dir != "" && (req.dir != api.AscDir && req.dir != api.DescDir) {
return apiutil.ErrInvalidDirection
}
+853
View File
@@ -0,0 +1,853 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"strings"
"testing"
"github.com/absmach/magistrala/internal/api"
"github.com/absmach/magistrala/internal/apiutil"
"github.com/absmach/magistrala/internal/testsutil"
mgclients "github.com/absmach/magistrala/pkg/clients"
"github.com/stretchr/testify/assert"
)
const (
valid = "valid"
invalid = "invalid"
)
var validID = testsutil.GenerateUUID(&testing.T{})
func TestCreateClientReqValidate(t *testing.T) {
cases := []struct {
desc string
req createClientReq
err error
}{
{
desc: "valid request",
req: createClientReq{
token: valid,
client: mgclients.Client{
ID: validID,
Name: valid,
Credentials: mgclients.Credentials{
Identity: "example@example.com",
Secret: valid,
},
},
},
err: nil,
},
{
desc: "empty token",
req: createClientReq{
token: "",
client: mgclients.Client{
ID: validID,
Name: valid,
Credentials: mgclients.Credentials{
Identity: "example@example.com",
Secret: valid,
},
},
},
},
{
desc: "name too long",
req: createClientReq{
token: valid,
client: mgclients.Client{
ID: validID,
Name: strings.Repeat("a", api.MaxNameSize+1),
},
},
err: apiutil.ErrNameSize,
},
}
for _, tc := range cases {
err := tc.req.validate()
assert.Equal(t, tc.err, err)
}
}
func TestViewClientReqValidate(t *testing.T) {
cases := []struct {
desc string
req viewClientReq
err error
}{
{
desc: "valid request",
req: viewClientReq{
token: valid,
id: validID,
},
err: nil,
},
{
desc: "empty token",
req: viewClientReq{
token: "",
id: validID,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: viewClientReq{
token: valid,
id: "",
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestViewProfileReqValidate(t *testing.T) {
cases := []struct {
desc string
req viewProfileReq
err error
}{
{
desc: "valid request",
req: viewProfileReq{
token: valid,
},
err: nil,
},
{
desc: "empty token",
req: viewProfileReq{
token: "",
},
err: apiutil.ErrBearerToken,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err)
}
}
func TestListClientsReqValidate(t *testing.T) {
cases := []struct {
desc string
req listClientsReq
err error
}{
{
desc: "valid request",
req: listClientsReq{
token: valid,
limit: 10,
},
err: nil,
},
{
desc: "empty token",
req: listClientsReq{
token: "",
limit: 10,
},
err: apiutil.ErrBearerToken,
},
{
desc: "limit too big",
req: listClientsReq{
token: valid,
limit: api.MaxLimitSize + 1,
},
err: apiutil.ErrLimitSize,
},
{
desc: "limit too small",
req: listClientsReq{
token: valid,
limit: 0,
},
err: apiutil.ErrLimitSize,
},
{
desc: "invalid direction",
req: listClientsReq{
token: valid,
limit: 10,
dir: "invalid",
},
err: apiutil.ErrInvalidDirection,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestListMembersByObjectReqValidate(t *testing.T) {
cases := []struct {
desc string
req listMembersByObjectReq
err error
}{
{
desc: "valid request",
req: listMembersByObjectReq{
token: valid,
objectKind: "group",
objectID: validID,
},
err: nil,
},
{
desc: "empty token",
req: listMembersByObjectReq{
token: "",
objectKind: "group",
objectID: validID,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty object kind",
req: listMembersByObjectReq{
token: valid,
objectKind: "",
objectID: validID,
},
err: apiutil.ErrMissingMemberKind,
},
{
desc: "empty object id",
req: listMembersByObjectReq{
token: valid,
objectKind: "group",
objectID: "",
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err)
}
}
func TestUpdateClientReqValidate(t *testing.T) {
cases := []struct {
desc string
req updateClientReq
err error
}{
{
desc: "valid request",
req: updateClientReq{
token: valid,
id: validID,
Name: valid,
},
err: nil,
},
{
desc: "empty token",
req: updateClientReq{
token: "",
id: validID,
Name: valid,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: updateClientReq{
token: valid,
id: "",
Name: valid,
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestUpdateClientTagsReqValidate(t *testing.T) {
cases := []struct {
desc string
req updateClientTagsReq
err error
}{
{
desc: "valid request",
req: updateClientTagsReq{
token: valid,
id: validID,
Tags: []string{"tag1", "tag2"},
},
err: nil,
},
{
desc: "empty token",
req: updateClientTagsReq{
token: "",
id: validID,
Tags: []string{"tag1", "tag2"},
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: updateClientTagsReq{
token: valid,
id: "",
Tags: []string{"tag1", "tag2"},
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestUpdateClientRoleReqValidate(t *testing.T) {
cases := []struct {
desc string
req updateClientRoleReq
err error
}{
{
desc: "valid request",
req: updateClientRoleReq{
token: valid,
id: validID,
Role: "admin",
},
err: nil,
},
{
desc: "empty token",
req: updateClientRoleReq{
token: "",
id: validID,
Role: "admin",
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: updateClientRoleReq{
token: valid,
id: "",
Role: "admin",
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestUpdateClientIdentityReqValidate(t *testing.T) {
cases := []struct {
desc string
req updateClientIdentityReq
err error
}{
{
desc: "valid request",
req: updateClientIdentityReq{
token: valid,
id: validID,
Identity: "example@example.com",
},
err: nil,
},
{
desc: "empty token",
req: updateClientIdentityReq{
token: "",
id: validID,
Identity: "example@example.com",
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: updateClientIdentityReq{
token: valid,
id: "",
Identity: "example@example.com",
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestUpdateClientSecretReqValidate(t *testing.T) {
cases := []struct {
desc string
req updateClientSecretReq
err error
}{
{
desc: "valid request",
req: updateClientSecretReq{
token: valid,
OldSecret: valid,
NewSecret: valid,
},
err: nil,
},
{
desc: "empty token",
req: updateClientSecretReq{
token: "",
OldSecret: valid,
NewSecret: valid,
},
err: apiutil.ErrBearerToken,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err)
}
}
func TestChangeClientStatusReqValidate(t *testing.T) {
cases := []struct {
desc string
req changeClientStatusReq
err error
}{
{
desc: "valid request",
req: changeClientStatusReq{
token: valid,
id: validID,
},
err: nil,
},
{
desc: "empty token",
req: changeClientStatusReq{
token: "",
id: validID,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: changeClientStatusReq{
token: valid,
id: "",
},
err: apiutil.ErrMissingID,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestLoginClientReqValidate(t *testing.T) {
cases := []struct {
desc string
req loginClientReq
err error
}{
{
desc: "valid request",
req: loginClientReq{
Identity: "eaxmple,example.com",
Secret: valid,
},
err: nil,
},
{
desc: "empty identity",
req: loginClientReq{
Identity: "",
Secret: valid,
},
err: apiutil.ErrMissingIdentity,
},
{
desc: "empty secret",
req: loginClientReq{
Identity: "eaxmple,example.com",
Secret: "",
},
err: apiutil.ErrMissingSecret,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestTokenReqValidate(t *testing.T) {
cases := []struct {
desc string
req tokenReq
err error
}{
{
desc: "valid request",
req: tokenReq{
RefreshToken: valid,
},
err: nil,
},
{
desc: "empty token",
req: tokenReq{
RefreshToken: "",
},
err: apiutil.ErrBearerToken,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestPasswResetReqValidate(t *testing.T) {
cases := []struct {
desc string
req passwResetReq
err error
}{
{
desc: "valid request",
req: passwResetReq{
Email: "example@example.com",
Host: "example.com",
},
err: nil,
},
{
desc: "empty email",
req: passwResetReq{
Email: "",
Host: "example.com",
},
err: apiutil.ErrMissingEmail,
},
{
desc: "empty host",
req: passwResetReq{
Email: "example@example.com",
Host: "",
},
err: apiutil.ErrMissingHost,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestResetTokenReqValidate(t *testing.T) {
cases := []struct {
desc string
req resetTokenReq
err error
}{
{
desc: "valid request",
req: resetTokenReq{
Token: valid,
Password: valid,
ConfPass: valid,
},
err: nil,
},
{
desc: "empty token",
req: resetTokenReq{
Token: "",
Password: valid,
ConfPass: valid,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty password",
req: resetTokenReq{
Token: valid,
Password: "",
ConfPass: valid,
},
err: apiutil.ErrMissingPass,
},
{
desc: "empty confpass",
req: resetTokenReq{
Token: valid,
Password: valid,
ConfPass: "",
},
err: apiutil.ErrMissingConfPass,
},
{
desc: "mismatching password and confpass",
req: resetTokenReq{
Token: valid,
Password: "valid2",
ConfPass: valid,
},
err: apiutil.ErrInvalidResetPass,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err)
}
}
func TestAssignUsersRequestValidate(t *testing.T) {
cases := []struct {
desc string
req assignUsersReq
err error
}{
{
desc: "valid request",
req: assignUsersReq{
token: valid,
groupID: validID,
UserIDs: []string{validID},
Relation: valid,
},
err: nil,
},
{
desc: "empty token",
req: assignUsersReq{
token: "",
groupID: validID,
UserIDs: []string{validID},
Relation: valid,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: assignUsersReq{
token: valid,
groupID: "",
UserIDs: []string{validID},
Relation: valid,
},
err: apiutil.ErrMissingID,
},
{
desc: "empty users",
req: assignUsersReq{
token: valid,
groupID: validID,
UserIDs: []string{},
Relation: valid,
},
err: apiutil.ErrEmptyList,
},
{
desc: "empty relation",
req: assignUsersReq{
token: valid,
groupID: validID,
UserIDs: []string{validID},
Relation: "",
},
err: apiutil.ErrMissingRelation,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestUnassignUsersRequestValidate(t *testing.T) {
cases := []struct {
desc string
req unassignUsersReq
err error
}{
{
desc: "valid request",
req: unassignUsersReq{
token: valid,
groupID: validID,
UserIDs: []string{validID},
Relation: valid,
},
err: nil,
},
{
desc: "empty token",
req: unassignUsersReq{
token: "",
groupID: validID,
UserIDs: []string{validID},
Relation: valid,
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty id",
req: unassignUsersReq{
token: valid,
groupID: "",
UserIDs: []string{validID},
Relation: valid,
},
err: apiutil.ErrMissingID,
},
{
desc: "empty users",
req: unassignUsersReq{
token: valid,
groupID: validID,
UserIDs: []string{},
Relation: valid,
},
err: apiutil.ErrEmptyList,
},
{
desc: "empty relation",
req: unassignUsersReq{
token: valid,
groupID: validID,
UserIDs: []string{validID},
Relation: "",
},
err: apiutil.ErrMissingRelation,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestAssignGroupsRequestValidate(t *testing.T) {
cases := []struct {
desc string
req assignGroupsReq
err error
}{
{
desc: "valid request",
req: assignGroupsReq{
token: valid,
groupID: validID,
GroupIDs: []string{validID},
},
err: nil,
},
{
desc: "empty token",
req: assignGroupsReq{
token: "",
groupID: validID,
GroupIDs: []string{validID},
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty group id",
req: assignGroupsReq{
token: valid,
groupID: "",
GroupIDs: []string{validID},
},
err: apiutil.ErrMissingID,
},
{
desc: "empty user group ids",
req: assignGroupsReq{
token: valid,
groupID: validID,
GroupIDs: []string{},
},
err: apiutil.ErrEmptyList,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
func TestUnassignGroupsRequestValidate(t *testing.T) {
cases := []struct {
desc string
req unassignGroupsReq
err error
}{
{
desc: "valid request",
req: unassignGroupsReq{
token: valid,
groupID: validID,
GroupIDs: []string{validID},
},
err: nil,
},
{
desc: "empty token",
req: unassignGroupsReq{
token: "",
groupID: validID,
GroupIDs: []string{validID},
},
err: apiutil.ErrBearerToken,
},
{
desc: "empty group id",
req: unassignGroupsReq{
token: valid,
groupID: "",
GroupIDs: []string{validID},
},
err: apiutil.ErrMissingID,
},
{
desc: "empty user group ids",
req: unassignGroupsReq{
token: valid,
groupID: validID,
GroupIDs: []string{},
},
err: apiutil.ErrEmptyList,
},
}
for _, c := range cases {
err := c.req.validate()
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
}
}
+22 -20
View File
@@ -5,7 +5,6 @@ package postgres
import (
"context"
"database/sql"
"fmt"
"github.com/absmach/magistrala/internal/postgres"
@@ -79,19 +78,17 @@ func (repo clientRepo) CheckSuperAdmin(ctx context.Context, adminID string) erro
q := "SELECT 1 FROM clients WHERE id = $1 AND role = $2"
rows, err := repo.DB.QueryContext(ctx, q, adminID, mgclients.AdminRole)
if err != nil {
if err == sql.ErrNoRows {
return errors.ErrAuthorization
}
return errors.Wrap(errors.ErrAuthorization, err)
}
defer rows.Close()
if !rows.Next() {
return errors.ErrAuthorization
if rows.Next() {
if err := rows.Err(); err != nil {
return errors.Wrap(errors.ErrAuthorization, err)
}
return nil
}
if err := rows.Err(); err != nil {
return errors.Wrap(errors.ErrAuthorization, err)
}
return nil
return errors.ErrAuthorization
}
func (repo clientRepo) RetrieveByID(ctx context.Context, id string) (mgclients.Client, error) {
@@ -102,22 +99,27 @@ func (repo clientRepo) RetrieveByID(ctx context.Context, id string) (mgclients.C
ID: id,
}
row, err := repo.DB.NamedQueryContext(ctx, q, dbc)
rows, err := repo.DB.NamedQueryContext(ctx, q, dbc)
if err != nil {
if err == sql.ErrNoRows {
return mgclients.Client{}, errors.Wrap(errors.ErrNotFound, err)
}
return mgclients.Client{}, errors.Wrap(errors.ErrViewEntity, err)
return mgclients.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
}
defer rows.Close()
defer row.Close()
row.Next()
dbc = pgclients.DBClient{}
if err := row.StructScan(&dbc); err != nil {
return mgclients.Client{}, errors.Wrap(errors.ErrNotFound, err)
if rows.Next() {
if err = rows.StructScan(&dbc); err != nil {
return mgclients.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
}
client, err := pgclients.ToClient(dbc)
if err != nil {
return mgclients.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
}
return client, nil
}
return pgclients.ToClient(dbc)
return mgclients.Client{}, repoerr.ErrNotFound
}
func (repo clientRepo) RetrieveAll(ctx context.Context, pm mgclients.Page) (mgclients.ClientsPage, error) {
+566
View File
@@ -192,7 +192,23 @@ func TestClientsSave(t *testing.T) {
},
err: nil,
},
{
desc: "add a client with invalid metadata",
client: mgclients.Client{
ID: testsutil.GenerateUUID(t),
Name: namesgen.Generate(),
Credentials: mgclients.Credentials{
Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()),
Secret: password,
},
Metadata: map[string]interface{}{
"key": make(chan int),
},
},
err: errors.ErrMalformedEntity,
},
}
for _, tc := range cases {
rClient, err := repo.Save(context.Background(), tc.client)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
@@ -254,3 +270,553 @@ func TestIsPlatformAdmin(t *testing.T) {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.err, err))
}
}
func TestRetrieveByID(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM clients")
require.Nil(t, err, fmt.Sprintf("clean clients unexpected error: %s", err))
})
repo := cpostgres.NewRepository(database)
client := mgclients.Client{
ID: testsutil.GenerateUUID(t),
Name: namesgen.Generate(),
Credentials: mgclients.Credentials{
Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()),
Secret: password,
},
Metadata: mgclients.Metadata{},
Status: mgclients.EnabledStatus,
}
_, err := repo.Save(context.Background(), client)
require.Nil(t, err, fmt.Sprintf("failed to save client %s", client.ID))
cases := []struct {
desc string
clientID string
err error
}{
{
desc: "retrieve existing client",
clientID: client.ID,
err: nil,
},
{
desc: "retrieve non-existing client",
clientID: invalidName,
err: errors.ErrNotFound,
},
{
desc: "retrieve with empty client id",
clientID: "",
err: errors.ErrNotFound,
},
}
for _, tc := range cases {
_, err := repo.RetrieveByID(context.Background(), tc.clientID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.err, err))
}
}
func TestRetrieveAll(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM clients")
require.Nil(t, err, fmt.Sprintf("clean clients unexpected error: %s", err))
})
repo := cpostgres.NewRepository(database)
ownerID := testsutil.GenerateUUID(t)
num := 200
var items, enabledClients []mgclients.Client
for i := 0; i < num; i++ {
client := mgclients.Client{
ID: testsutil.GenerateUUID(t),
Name: namesgen.Generate(),
Credentials: mgclients.Credentials{
Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()),
Secret: "",
},
Metadata: mgclients.Metadata{},
Status: mgclients.EnabledStatus,
Tags: []string{"tag1"},
}
if i%50 == 0 {
client.Owner = ownerID
client.Metadata = map[string]interface{}{
"key": "value",
}
client.Role = mgclients.AdminRole
client.Status = mgclients.DisabledStatus
}
_, err := repo.Save(context.Background(), client)
require.Nil(t, err, fmt.Sprintf("failed to save client %s", client.ID))
items = append(items, client)
if client.Status == mgclients.EnabledStatus {
enabledClients = append(enabledClients, client)
}
}
cases := []struct {
desc string
pageMeta mgclients.Page
page mgclients.ClientsPage
err error
}{
{
desc: "retrieve first page of clients",
pageMeta: mgclients.Page{
Offset: 0,
Limit: 50,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 200,
Offset: 0,
Limit: 50,
},
Clients: items[0:50],
},
err: nil,
},
{
desc: "retrieve second page of clients",
pageMeta: mgclients.Page{
Offset: 50,
Limit: 200,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 200,
Offset: 50,
Limit: 200,
},
Clients: items[50:200],
},
err: nil,
},
{
desc: "retrieve clients with limit",
pageMeta: mgclients.Page{
Offset: 0,
Limit: 50,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: uint64(num),
Offset: 0,
Limit: 50,
},
Clients: items[:50],
},
},
{
desc: "retrieve with offset out of range",
pageMeta: mgclients.Page{
Offset: 1000,
Limit: 200,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 200,
Offset: 1000,
Limit: 200,
},
Clients: []mgclients.Client{},
},
err: nil,
},
{
desc: "retrieve with limit out of range",
pageMeta: mgclients.Page{
Offset: 0,
Limit: 1000,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 200,
Offset: 0,
Limit: 1000,
},
Clients: items,
},
err: nil,
},
{
desc: "retrieve with empty page",
pageMeta: mgclients.Page{},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 196, // No of enabled clients.
Offset: 0,
Limit: 0,
},
Clients: []mgclients.Client{},
},
err: nil,
},
{
desc: "retrieve with client id",
pageMeta: mgclients.Page{
IDs: []string{items[0].ID},
Offset: 0,
Limit: 3,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 1,
Offset: 0,
Limit: 3,
},
Clients: []mgclients.Client{items[0]},
},
err: nil,
},
{
desc: "retrieve with invalid client id",
pageMeta: mgclients.Page{
IDs: []string{invalidName},
Offset: 0,
Limit: 3,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 0,
Offset: 0,
Limit: 3,
},
Clients: []mgclients.Client{},
},
err: nil,
},
{
desc: "retrieve with client name",
pageMeta: mgclients.Page{
Name: items[0].Name,
Offset: 0,
Limit: 3,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 1,
Offset: 0,
Limit: 3,
},
Clients: []mgclients.Client{items[0]},
},
err: nil,
},
{
desc: "retrieve with enabled status",
pageMeta: mgclients.Page{
Status: mgclients.EnabledStatus,
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 196,
Offset: 0,
Limit: 200,
},
Clients: enabledClients,
},
err: nil,
},
{
desc: "retrieve with disabled status",
pageMeta: mgclients.Page{
Status: mgclients.DisabledStatus,
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 4,
Offset: 0,
Limit: 200,
},
Clients: []mgclients.Client{items[0], items[50], items[100], items[150]},
},
},
{
desc: "retrieve with all status",
pageMeta: mgclients.Page{
Status: mgclients.AllStatus,
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 200,
Offset: 0,
Limit: 200,
},
Clients: items,
},
},
{
desc: "retrieve with owner id",
pageMeta: mgclients.Page{
Owner: ownerID,
Offset: 0,
Limit: 5,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 4,
Offset: 0,
Limit: 5,
},
Clients: []mgclients.Client{items[0], items[50], items[100], items[150]},
},
err: nil,
},
{
desc: "retrieve with invalid owner id",
pageMeta: mgclients.Page{
Owner: invalidName,
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 0,
Offset: 0,
Limit: 200,
},
Clients: []mgclients.Client{},
},
err: nil,
},
{
desc: "retrieve by tags",
pageMeta: mgclients.Page{
Tag: "tag1",
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 200,
Offset: 0,
Limit: 200,
},
Clients: items,
},
err: nil,
},
{
desc: "retrieve with invalid client name",
pageMeta: mgclients.Page{
Name: invalidName,
Offset: 0,
Limit: 3,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 0,
Offset: 0,
Limit: 3,
},
Clients: []mgclients.Client{},
},
},
{
desc: "retrieve with metadata",
pageMeta: mgclients.Page{
Metadata: map[string]interface{}{
"key": "value",
},
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 4,
Offset: 0,
Limit: 200,
},
Clients: []mgclients.Client{items[0], items[50], items[100], items[150]},
},
err: nil,
},
{
desc: "retrieve with invalid metadata",
pageMeta: mgclients.Page{
Metadata: map[string]interface{}{
"key": "value1",
},
Offset: 0,
Limit: 200,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 0,
Offset: 0,
Limit: 200,
},
Clients: []mgclients.Client{},
},
err: nil,
},
{
desc: "retrieve with role",
pageMeta: mgclients.Page{
Role: mgclients.AdminRole,
Offset: 0,
Limit: 200,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 4,
Offset: 0,
Limit: 200,
},
Clients: []mgclients.Client{items[0], items[50], items[100], items[150]},
},
err: nil,
},
{
desc: "retrieve with invalid role",
pageMeta: mgclients.Page{
Role: mgclients.AdminRole + 2,
Offset: 0,
Limit: 200,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 0,
Offset: 0,
Limit: 200,
},
Clients: []mgclients.Client{},
},
err: nil,
},
{
desc: "retrieve with identity",
pageMeta: mgclients.Page{
Identity: items[0].Credentials.Identity,
Offset: 0,
Limit: 3,
Role: mgclients.AllRole,
Status: mgclients.AllStatus,
},
page: mgclients.ClientsPage{
Page: mgclients.Page{
Total: 1,
Offset: 0,
Limit: 3,
},
Clients: []mgclients.Client{items[0]},
},
err: nil,
},
}
for _, tc := range cases {
page, err := repo.RetrieveAll(context.Background(), tc.pageMeta)
assert.Equal(t, tc.page.Total, page.Total, fmt.Sprintf("%s: expected %d got %d\n", tc.desc, tc.page.Total, page.Total))
assert.Equal(t, tc.page.Offset, page.Offset, fmt.Sprintf("%s: expected %d got %d\n", tc.desc, tc.page.Offset, page.Offset))
assert.Equal(t, tc.page.Limit, page.Limit, fmt.Sprintf("%s: expected %d got %d\n", tc.desc, tc.page.Limit, page.Limit))
assert.Equal(t, tc.page.Page, page.Page, fmt.Sprintf("%s: expected %v, got %v", tc.desc, tc.page, page))
assert.ElementsMatch(t, tc.page.Clients, page.Clients, fmt.Sprintf("%s: expected %v, got %v", tc.desc, tc.page.Clients, page.Clients))
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
}
}
func TestUpdateRole(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM clients")
require.Nil(t, err, fmt.Sprintf("clean clients unexpected error: %s", err))
})
repo := cpostgres.NewRepository(database)
client := mgclients.Client{
ID: testsutil.GenerateUUID(t),
Name: namesgen.Generate(),
Credentials: mgclients.Credentials{
Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()),
Secret: password,
},
Metadata: mgclients.Metadata{},
Status: mgclients.EnabledStatus,
Role: mgclients.UserRole,
}
_, err := repo.Save(context.Background(), client)
require.Nil(t, err, fmt.Sprintf("failed to save client %s", client.ID))
cases := []struct {
desc string
client mgclients.Client
newRole mgclients.Role
err error
}{
{
desc: "update role to admin",
client: client,
newRole: mgclients.AdminRole,
err: nil,
},
{
desc: "update role to user",
client: client,
newRole: mgclients.UserRole,
err: nil,
},
{
desc: "update role with invalid client id",
client: mgclients.Client{ID: invalidName},
newRole: mgclients.AdminRole,
err: errors.ErrNotFound,
},
}
for _, tc := range cases {
tc.client.Role = tc.newRole
client, err := repo.UpdateRole(context.Background(), tc.client)
if err != nil {
assert.Equal(t, err, tc.err, fmt.Sprintf("%s: expected error %v, got %v", tc.desc, tc.err, err))
} else {
assert.Equal(t, tc.newRole, client.Role, fmt.Sprintf("%s: expected role %v, got %v", tc.desc, tc.newRole, client.Role))
}
}
}
+1765 -767
View File
File diff suppressed because it is too large Load Diff