Skip to content
Snippets Groups Projects
Commit 07e4c477 authored by Lyuben Penkovski's avatar Lyuben Penkovski
Browse files

Merge branch 'unit-tests' into 'main'

Unit tests for policy service

See merge request !10
parents 86370c70 f639edee
No related branches found
No related tags found
1 merge request!10Unit tests for policy service
Pipeline #50288 passed with stage
in 37 seconds
Showing
with 799 additions and 0 deletions
...@@ -6,6 +6,7 @@ require ( ...@@ -6,6 +6,7 @@ require (
code.vereign.com/gaiax/tsa/golib v0.0.0-20220321093827-5fdf8f34aad9 code.vereign.com/gaiax/tsa/golib v0.0.0-20220321093827-5fdf8f34aad9
github.com/kelseyhightower/envconfig v1.4.0 github.com/kelseyhightower/envconfig v1.4.0
github.com/open-policy-agent/opa v0.38.1 github.com/open-policy-agent/opa v0.38.1
github.com/stretchr/testify v1.7.0
go.mongodb.org/mongo-driver v1.8.4 go.mongodb.org/mongo-driver v1.8.4
go.uber.org/zap v1.21.0 go.uber.org/zap v1.21.0
goa.design/goa/v3 v3.7.0 goa.design/goa/v3 v3.7.0
...@@ -14,6 +15,7 @@ require ( ...@@ -14,6 +15,7 @@ require (
require ( require (
github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect
github.com/dimfeld/httptreemux/v5 v5.4.0 // indirect github.com/dimfeld/httptreemux/v5 v5.4.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect
...@@ -27,6 +29,7 @@ require ( ...@@ -27,6 +29,7 @@ require (
github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/compress v1.13.6 // indirect
github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect
github.com/smartystreets/assertions v1.2.1 // indirect github.com/smartystreets/assertions v1.2.1 // indirect
...@@ -47,4 +50,5 @@ require ( ...@@ -47,4 +50,5 @@ require (
golang.org/x/tools v0.1.10 // indirect golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )
package regocache_test
import (
"context"
"testing"
"github.com/open-policy-agent/opa/rego"
"github.com/stretchr/testify/assert"
"code.vereign.com/gaiax/tsa/policy/internal/regocache"
"code.vereign.com/gaiax/tsa/policy/internal/service/policy"
)
const regoPolicy = `
package test
allow {
input.val == 1
}
`
func TestNew(t *testing.T) {
cache := regocache.New()
assert.Implements(t, (*policy.RegoCache)(nil), cache)
}
func TestCache_SetAndGet(t *testing.T) {
q1, err := rego.New(
rego.Module("filename.rego", regoPolicy),
rego.Query("data"),
).PrepareForEval(context.Background())
assert.NoError(t, err)
cache := regocache.New()
cache.Set("query1", &q1)
q2, ok := cache.Get("query1")
assert.True(t, ok)
assert.Equal(t, q1, *q2)
}
func TestCache_Purge(t *testing.T) {
q1, err := rego.New(
rego.Module("filename.rego", regoPolicy),
rego.Query("data"),
).PrepareForEval(context.Background())
assert.NoError(t, err)
cache := regocache.New()
cache.Set("query1", &q1)
cache.Purge()
q2, ok := cache.Get("query1")
assert.False(t, ok)
assert.Nil(t, q2)
}
func TestCache_PolicyDataChange(t *testing.T) {
q1, err := rego.New(
rego.Module("filename.rego", regoPolicy),
rego.Query("data"),
).PrepareForEval(context.Background())
assert.NoError(t, err)
cache := regocache.New()
cache.Set("query1", &q1)
cache.PolicyDataChange()
q2, ok := cache.Get("query1")
assert.False(t, ok)
assert.Nil(t, q2)
}
// Code generated by counterfeiter. DO NOT EDIT.
package policyfakes
import (
"sync"
"code.vereign.com/gaiax/tsa/policy/internal/service/policy"
"github.com/open-policy-agent/opa/rego"
)
type FakeRegoCache struct {
GetStub func(string) (*rego.PreparedEvalQuery, bool)
getMutex sync.RWMutex
getArgsForCall []struct {
arg1 string
}
getReturns struct {
result1 *rego.PreparedEvalQuery
result2 bool
}
getReturnsOnCall map[int]struct {
result1 *rego.PreparedEvalQuery
result2 bool
}
SetStub func(string, *rego.PreparedEvalQuery)
setMutex sync.RWMutex
setArgsForCall []struct {
arg1 string
arg2 *rego.PreparedEvalQuery
}
invocations map[string][][]interface{}
invocationsMutex sync.RWMutex
}
func (fake *FakeRegoCache) Get(arg1 string) (*rego.PreparedEvalQuery, bool) {
fake.getMutex.Lock()
ret, specificReturn := fake.getReturnsOnCall[len(fake.getArgsForCall)]
fake.getArgsForCall = append(fake.getArgsForCall, struct {
arg1 string
}{arg1})
stub := fake.GetStub
fakeReturns := fake.getReturns
fake.recordInvocation("Get", []interface{}{arg1})
fake.getMutex.Unlock()
if stub != nil {
return stub(arg1)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeRegoCache) GetCallCount() int {
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
return len(fake.getArgsForCall)
}
func (fake *FakeRegoCache) GetCalls(stub func(string) (*rego.PreparedEvalQuery, bool)) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = stub
}
func (fake *FakeRegoCache) GetArgsForCall(i int) string {
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
argsForCall := fake.getArgsForCall[i]
return argsForCall.arg1
}
func (fake *FakeRegoCache) GetReturns(result1 *rego.PreparedEvalQuery, result2 bool) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = nil
fake.getReturns = struct {
result1 *rego.PreparedEvalQuery
result2 bool
}{result1, result2}
}
func (fake *FakeRegoCache) GetReturnsOnCall(i int, result1 *rego.PreparedEvalQuery, result2 bool) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = nil
if fake.getReturnsOnCall == nil {
fake.getReturnsOnCall = make(map[int]struct {
result1 *rego.PreparedEvalQuery
result2 bool
})
}
fake.getReturnsOnCall[i] = struct {
result1 *rego.PreparedEvalQuery
result2 bool
}{result1, result2}
}
func (fake *FakeRegoCache) Set(arg1 string, arg2 *rego.PreparedEvalQuery) {
fake.setMutex.Lock()
fake.setArgsForCall = append(fake.setArgsForCall, struct {
arg1 string
arg2 *rego.PreparedEvalQuery
}{arg1, arg2})
stub := fake.SetStub
fake.recordInvocation("Set", []interface{}{arg1, arg2})
fake.setMutex.Unlock()
if stub != nil {
fake.SetStub(arg1, arg2)
}
}
func (fake *FakeRegoCache) SetCallCount() int {
fake.setMutex.RLock()
defer fake.setMutex.RUnlock()
return len(fake.setArgsForCall)
}
func (fake *FakeRegoCache) SetCalls(stub func(string, *rego.PreparedEvalQuery)) {
fake.setMutex.Lock()
defer fake.setMutex.Unlock()
fake.SetStub = stub
}
func (fake *FakeRegoCache) SetArgsForCall(i int) (string, *rego.PreparedEvalQuery) {
fake.setMutex.RLock()
defer fake.setMutex.RUnlock()
argsForCall := fake.setArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeRegoCache) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
fake.setMutex.RLock()
defer fake.setMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
for key, value := range fake.invocations {
copiedInvocations[key] = value
}
return copiedInvocations
}
func (fake *FakeRegoCache) recordInvocation(key string, args []interface{}) {
fake.invocationsMutex.Lock()
defer fake.invocationsMutex.Unlock()
if fake.invocations == nil {
fake.invocations = map[string][][]interface{}{}
}
if fake.invocations[key] == nil {
fake.invocations[key] = [][]interface{}{}
}
fake.invocations[key] = append(fake.invocations[key], args)
}
var _ policy.RegoCache = new(FakeRegoCache)
// Code generated by counterfeiter. DO NOT EDIT.
package policyfakes
import (
"context"
"sync"
"code.vereign.com/gaiax/tsa/policy/internal/service/policy"
"code.vereign.com/gaiax/tsa/policy/internal/storage"
)
type FakeStorage struct {
PolicyStub func(context.Context, string, string, string) (*storage.Policy, error)
policyMutex sync.RWMutex
policyArgsForCall []struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
}
policyReturns struct {
result1 *storage.Policy
result2 error
}
policyReturnsOnCall map[int]struct {
result1 *storage.Policy
result2 error
}
SetPolicyLockStub func(context.Context, string, string, string, bool) error
setPolicyLockMutex sync.RWMutex
setPolicyLockArgsForCall []struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
arg5 bool
}
setPolicyLockReturns struct {
result1 error
}
setPolicyLockReturnsOnCall map[int]struct {
result1 error
}
invocations map[string][][]interface{}
invocationsMutex sync.RWMutex
}
func (fake *FakeStorage) Policy(arg1 context.Context, arg2 string, arg3 string, arg4 string) (*storage.Policy, error) {
fake.policyMutex.Lock()
ret, specificReturn := fake.policyReturnsOnCall[len(fake.policyArgsForCall)]
fake.policyArgsForCall = append(fake.policyArgsForCall, struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
}{arg1, arg2, arg3, arg4})
stub := fake.PolicyStub
fakeReturns := fake.policyReturns
fake.recordInvocation("Policy", []interface{}{arg1, arg2, arg3, arg4})
fake.policyMutex.Unlock()
if stub != nil {
return stub(arg1, arg2, arg3, arg4)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeStorage) PolicyCallCount() int {
fake.policyMutex.RLock()
defer fake.policyMutex.RUnlock()
return len(fake.policyArgsForCall)
}
func (fake *FakeStorage) PolicyCalls(stub func(context.Context, string, string, string) (*storage.Policy, error)) {
fake.policyMutex.Lock()
defer fake.policyMutex.Unlock()
fake.PolicyStub = stub
}
func (fake *FakeStorage) PolicyArgsForCall(i int) (context.Context, string, string, string) {
fake.policyMutex.RLock()
defer fake.policyMutex.RUnlock()
argsForCall := fake.policyArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
}
func (fake *FakeStorage) PolicyReturns(result1 *storage.Policy, result2 error) {
fake.policyMutex.Lock()
defer fake.policyMutex.Unlock()
fake.PolicyStub = nil
fake.policyReturns = struct {
result1 *storage.Policy
result2 error
}{result1, result2}
}
func (fake *FakeStorage) PolicyReturnsOnCall(i int, result1 *storage.Policy, result2 error) {
fake.policyMutex.Lock()
defer fake.policyMutex.Unlock()
fake.PolicyStub = nil
if fake.policyReturnsOnCall == nil {
fake.policyReturnsOnCall = make(map[int]struct {
result1 *storage.Policy
result2 error
})
}
fake.policyReturnsOnCall[i] = struct {
result1 *storage.Policy
result2 error
}{result1, result2}
}
func (fake *FakeStorage) SetPolicyLock(arg1 context.Context, arg2 string, arg3 string, arg4 string, arg5 bool) error {
fake.setPolicyLockMutex.Lock()
ret, specificReturn := fake.setPolicyLockReturnsOnCall[len(fake.setPolicyLockArgsForCall)]
fake.setPolicyLockArgsForCall = append(fake.setPolicyLockArgsForCall, struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
arg5 bool
}{arg1, arg2, arg3, arg4, arg5})
stub := fake.SetPolicyLockStub
fakeReturns := fake.setPolicyLockReturns
fake.recordInvocation("SetPolicyLock", []interface{}{arg1, arg2, arg3, arg4, arg5})
fake.setPolicyLockMutex.Unlock()
if stub != nil {
return stub(arg1, arg2, arg3, arg4, arg5)
}
if specificReturn {
return ret.result1
}
return fakeReturns.result1
}
func (fake *FakeStorage) SetPolicyLockCallCount() int {
fake.setPolicyLockMutex.RLock()
defer fake.setPolicyLockMutex.RUnlock()
return len(fake.setPolicyLockArgsForCall)
}
func (fake *FakeStorage) SetPolicyLockCalls(stub func(context.Context, string, string, string, bool) error) {
fake.setPolicyLockMutex.Lock()
defer fake.setPolicyLockMutex.Unlock()
fake.SetPolicyLockStub = stub
}
func (fake *FakeStorage) SetPolicyLockArgsForCall(i int) (context.Context, string, string, string, bool) {
fake.setPolicyLockMutex.RLock()
defer fake.setPolicyLockMutex.RUnlock()
argsForCall := fake.setPolicyLockArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5
}
func (fake *FakeStorage) SetPolicyLockReturns(result1 error) {
fake.setPolicyLockMutex.Lock()
defer fake.setPolicyLockMutex.Unlock()
fake.SetPolicyLockStub = nil
fake.setPolicyLockReturns = struct {
result1 error
}{result1}
}
func (fake *FakeStorage) SetPolicyLockReturnsOnCall(i int, result1 error) {
fake.setPolicyLockMutex.Lock()
defer fake.setPolicyLockMutex.Unlock()
fake.SetPolicyLockStub = nil
if fake.setPolicyLockReturnsOnCall == nil {
fake.setPolicyLockReturnsOnCall = make(map[int]struct {
result1 error
})
}
fake.setPolicyLockReturnsOnCall[i] = struct {
result1 error
}{result1}
}
func (fake *FakeStorage) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.policyMutex.RLock()
defer fake.policyMutex.RUnlock()
fake.setPolicyLockMutex.RLock()
defer fake.setPolicyLockMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
for key, value := range fake.invocations {
copiedInvocations[key] = value
}
return copiedInvocations
}
func (fake *FakeStorage) recordInvocation(key string, args []interface{}) {
fake.invocationsMutex.Lock()
defer fake.invocationsMutex.Unlock()
if fake.invocations == nil {
fake.invocations = map[string][][]interface{}{}
}
if fake.invocations[key] == nil {
fake.invocations[key] = [][]interface{}{}
}
fake.invocations[key] = append(fake.invocations[key], args)
}
var _ policy.Storage = new(FakeStorage)
...@@ -12,6 +12,9 @@ import ( ...@@ -12,6 +12,9 @@ import (
"code.vereign.com/gaiax/tsa/policy/internal/storage" "code.vereign.com/gaiax/tsa/policy/internal/storage"
) )
//go:generate counterfeiter . Storage
//go:generate counterfeiter . RegoCache
type Storage interface { type Storage interface {
Policy(ctx context.Context, name, group, version string) (*storage.Policy, error) Policy(ctx context.Context, name, group, version string) (*storage.Policy, error)
SetPolicyLock(ctx context.Context, name, group, version string, lock bool) error SetPolicyLock(ctx context.Context, name, group, version string, lock bool) error
......
package policy_test
import (
"context"
"testing"
"time"
"github.com/open-policy-agent/opa/rego"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"code.vereign.com/gaiax/tsa/golib/errors"
goapolicy "code.vereign.com/gaiax/tsa/policy/gen/policy"
"code.vereign.com/gaiax/tsa/policy/internal/service/policy"
"code.vereign.com/gaiax/tsa/policy/internal/service/policy/policyfakes"
"code.vereign.com/gaiax/tsa/policy/internal/storage"
)
func TestNew(t *testing.T) {
storage := &policyfakes.FakeStorage{}
regocache := &policyfakes.FakeRegoCache{}
svc := policy.New(storage, regocache, zap.NewNop())
assert.Implements(t, (*goapolicy.Service)(nil), svc)
}
func TestService_Evaluate(t *testing.T) {
// prepare test policy source code that will be evaluated
testPolicy := `package testgroup.example allow { input.msg == "yes" }`
// prepare test query that can be retrieved from rego cache
testQuery, err := rego.New(
rego.Module("example.rego", testPolicy),
rego.Query("data.testgroup.example"),
).PrepareForEval(context.Background())
assert.NoError(t, err)
// prepare test request to be used in tests
testReq := func() *goapolicy.EvaluateRequest {
return &goapolicy.EvaluateRequest{
Group: "testgroup",
PolicyName: "example",
Version: "1.0",
Input: map[string]interface{}{"msg": "yes"},
}
}
tests := []struct {
// test input
name string
req *goapolicy.EvaluateRequest
storage policy.Storage
regocache policy.RegoCache
// expected result
res *goapolicy.EvaluateResult
errkind errors.Kind
errtext string
}{
{
name: "prepared query is found in cache",
req: testReq(),
regocache: &policyfakes.FakeRegoCache{
GetStub: func(key string) (*rego.PreparedEvalQuery, bool) {
q := testQuery
return &q, true
},
},
res: &goapolicy.EvaluateResult{Result: map[string]interface{}{"allow": true}},
},
{
name: "policy is not found",
req: testReq(),
regocache: &policyfakes.FakeRegoCache{
GetStub: func(key string) (*rego.PreparedEvalQuery, bool) {
return nil, false
},
},
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return nil, errors.New(errors.NotFound)
},
},
res: nil,
errkind: errors.NotFound,
errtext: "not found",
},
{
name: "error getting policy from storage",
req: testReq(),
regocache: &policyfakes.FakeRegoCache{
GetStub: func(key string) (*rego.PreparedEvalQuery, bool) {
return nil, false
},
},
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return nil, errors.New("some error")
},
},
res: nil,
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "policy is locked",
req: testReq(),
regocache: &policyfakes.FakeRegoCache{
GetStub: func(key string) (*rego.PreparedEvalQuery, bool) {
return nil, false
},
},
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: true}, nil
},
},
res: nil,
errkind: errors.Forbidden,
errtext: "policy is locked",
},
{
name: "policy is found in storage and isn't locked",
req: testReq(),
regocache: &policyfakes.FakeRegoCache{
GetStub: func(key string) (*rego.PreparedEvalQuery, bool) {
return nil, false
},
},
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{
Name: "example",
Group: "testgroup",
Version: "1.0",
Rego: testPolicy,
Locked: false,
LastUpdate: time.Now(),
}, nil
},
},
res: &goapolicy.EvaluateResult{Result: map[string]interface{}{"allow": true}},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
svc := policy.New(test.storage, test.regocache, zap.NewNop())
res, err := svc.Evaluate(context.Background(), test.req)
if err == nil {
assert.Empty(t, test.errtext)
assert.Equal(t, test.res, res)
} else {
e, ok := err.(*errors.Error)
assert.True(t, ok)
assert.Contains(t, e.Error(), test.errtext)
assert.Equal(t, test.errkind, e.Kind)
assert.Equal(t, test.res, res)
}
})
}
}
func TestService_Lock(t *testing.T) {
// prepare test request to be used in tests
testReq := func() *goapolicy.LockRequest {
return &goapolicy.LockRequest{
Group: "testgroup",
PolicyName: "example",
Version: "1.0",
}
}
tests := []struct {
name string
req *goapolicy.LockRequest
storage policy.Storage
errkind errors.Kind
errtext string
}{
{
name: "policy is not found",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return nil, errors.New(errors.NotFound)
},
},
errkind: errors.NotFound,
errtext: "not found",
},
{
name: "error getting policy from storage",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return nil, errors.New("some error")
},
},
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "policy is already locked",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: true}, nil
},
},
errkind: errors.Forbidden,
errtext: "policy is already locked",
},
{
name: "fail to lock policy",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: false}, nil
},
SetPolicyLockStub: func(ctx context.Context, name, group, version string, lock bool) error {
return errors.New(errors.Internal, "error locking policy")
},
},
errkind: errors.Internal,
errtext: "error locking policy",
},
{
name: "policy is locked successfully",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: false}, nil
},
SetPolicyLockStub: func(ctx context.Context, name, group, version string, lock bool) error {
return nil
},
},
errtext: "",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
svc := policy.New(test.storage, nil, zap.NewNop())
err := svc.Lock(context.Background(), test.req)
if err == nil {
assert.Empty(t, test.errtext)
} else {
e, ok := err.(*errors.Error)
assert.True(t, ok)
assert.Contains(t, e.Error(), test.errtext)
assert.Equal(t, test.errkind, e.Kind)
}
})
}
}
func TestService_Unlock(t *testing.T) {
// prepare test request to be used in tests
testReq := func() *goapolicy.UnlockRequest {
return &goapolicy.UnlockRequest{
Group: "testgroup",
PolicyName: "example",
Version: "1.0",
}
}
tests := []struct {
name string
req *goapolicy.UnlockRequest
storage policy.Storage
errkind errors.Kind
errtext string
}{
{
name: "policy is not found",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return nil, errors.New(errors.NotFound)
},
},
errkind: errors.NotFound,
errtext: "not found",
},
{
name: "error getting policy from storage",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return nil, errors.New("some error")
},
},
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "policy is unlocked",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: false}, nil
},
},
errkind: errors.Forbidden,
errtext: "policy is unlocked",
},
{
name: "fail to unlock policy",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: true}, nil
},
SetPolicyLockStub: func(ctx context.Context, name, group, version string, lock bool) error {
return errors.New(errors.Internal, "error unlocking policy")
},
},
errkind: errors.Internal,
errtext: "error unlocking policy",
},
{
name: "policy is unlocked successfully",
req: testReq(),
storage: &policyfakes.FakeStorage{
PolicyStub: func(ctx context.Context, s string, s2 string, s3 string) (*storage.Policy, error) {
return &storage.Policy{Locked: true}, nil
},
SetPolicyLockStub: func(ctx context.Context, name, group, version string, lock bool) error {
return nil
},
},
errtext: "",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
svc := policy.New(test.storage, nil, zap.NewNop())
err := svc.Unlock(context.Background(), test.req)
if err == nil {
assert.Empty(t, test.errtext)
} else {
e, ok := err.(*errors.Error)
assert.True(t, ok)
assert.Contains(t, e.Error(), test.errtext)
assert.Equal(t, test.errkind, e.Kind)
}
})
}
}
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment