235 lines
7.0 KiB
Go
235 lines
7.0 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package configtx
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
cb "github.com/hyperledger/fabric-protos-go/common"
|
|
mockpolicies "github.com/hyperledger/fabric/common/configtx/mock"
|
|
"github.com/hyperledger/fabric/common/policies"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestReadSetNotPresent(t *testing.T) {
|
|
vi := &ValidatorImpl{
|
|
configMap: make(map[string]comparable),
|
|
}
|
|
|
|
vi.configMap["1"] = comparable{}
|
|
vi.configMap["2"] = comparable{}
|
|
|
|
readSet := make(map[string]comparable)
|
|
readSet["1"] = comparable{}
|
|
readSet["3"] = comparable{}
|
|
|
|
require.Error(t, vi.verifyReadSet(readSet), "ReadSet contained '3', not in config")
|
|
}
|
|
|
|
func TestReadSetBackVersioned(t *testing.T) {
|
|
vi := &ValidatorImpl{
|
|
configMap: make(map[string]comparable),
|
|
}
|
|
|
|
vi.configMap["1"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}
|
|
vi.configMap["2"] = comparable{}
|
|
|
|
readSet := make(map[string]comparable)
|
|
readSet["1"] = comparable{}
|
|
|
|
require.Error(t, vi.verifyReadSet(readSet), "ReadSet contained '1', at old version")
|
|
}
|
|
|
|
func TestComputeDeltaSet(t *testing.T) {
|
|
readSet := make(map[string]comparable)
|
|
readSet["1"] = comparable{}
|
|
readSet["2"] = comparable{}
|
|
|
|
writeSet := make(map[string]comparable)
|
|
writeSet["1"] = comparable{}
|
|
writeSet["2"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}
|
|
writeSet["3"] = comparable{}
|
|
|
|
result := computeDeltaSet(readSet, writeSet)
|
|
require.Len(t, result, 2, "Should have two values in the delta set")
|
|
require.NotNil(t, result["2"], "Element had version increased")
|
|
require.NotNil(t, result["3"], "Element was new")
|
|
}
|
|
|
|
func TestVerifyDeltaSet(t *testing.T) {
|
|
pm := &mockpolicies.PolicyManager{}
|
|
pm.GetPolicyReturns(&mockpolicies.Policy{}, true)
|
|
vi := &ValidatorImpl{
|
|
pm: pm,
|
|
configMap: make(map[string]comparable),
|
|
}
|
|
|
|
vi.configMap["foo"] = comparable{path: []string{"foo"}}
|
|
|
|
t.Run("Green path", func(t *testing.T) {
|
|
deltaSet := make(map[string]comparable)
|
|
|
|
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}}
|
|
|
|
require.NoError(t, vi.verifyDeltaSet(deltaSet, nil), "Good update")
|
|
})
|
|
|
|
t.Run("Bad mod policy", func(t *testing.T) {
|
|
deltaSet := make(map[string]comparable)
|
|
|
|
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}
|
|
|
|
require.Regexp(t, "invalid mod_policy for element", vi.verifyDeltaSet(deltaSet, nil))
|
|
})
|
|
|
|
t.Run("Big Skip", func(t *testing.T) {
|
|
deltaSet := make(map[string]comparable)
|
|
|
|
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 2, ModPolicy: "foo"}}
|
|
|
|
require.Error(t, vi.verifyDeltaSet(deltaSet, nil), "Version skip from 0 to 2")
|
|
})
|
|
|
|
t.Run("New item high version", func(t *testing.T) {
|
|
deltaSet := make(map[string]comparable)
|
|
|
|
deltaSet["bar"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}}
|
|
|
|
require.Error(t, vi.verifyDeltaSet(deltaSet, nil), "New key not at version 0")
|
|
})
|
|
|
|
t.Run("Policy evalaution to false", func(t *testing.T) {
|
|
deltaSet := make(map[string]comparable)
|
|
|
|
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}}
|
|
fakePolicy := &mockpolicies.Policy{}
|
|
fakePolicy.EvaluateSignedDataReturns(fmt.Errorf("MockErr-fakePolicy.Evaluate-1557327297"))
|
|
vi.pm.(*mockpolicies.PolicyManager).GetPolicyReturns(fakePolicy, true)
|
|
|
|
require.Error(t, vi.verifyDeltaSet(deltaSet, nil), "Policy evaluation should have failed")
|
|
})
|
|
|
|
t.Run("Empty delta set", func(t *testing.T) {
|
|
err := (&ValidatorImpl{}).verifyDeltaSet(map[string]comparable{}, nil)
|
|
require.Error(t, err, "Empty delta set should be rejected")
|
|
require.Contains(t, err.Error(), "delta set was empty -- update would have no effect")
|
|
})
|
|
}
|
|
|
|
func TestPolicyForItem(t *testing.T) {
|
|
// Policies are set to different error values to differentiate them in equal assertion
|
|
|
|
fakeFooPolicy := &mockpolicies.Policy{}
|
|
fakeFooPolicy.EvaluateSignedDataReturns(fmt.Errorf("MockErr-fooPolicy-1557327481"))
|
|
fakeFooPolicyManager := &mockpolicies.PolicyManager{}
|
|
fakeFooPolicyManager.GetPolicyStub = func(s string) (i policies.Policy, b bool) {
|
|
if s == "foo" {
|
|
return fakeFooPolicy, true
|
|
}
|
|
return nil, false
|
|
}
|
|
fakeRootPolicy := &mockpolicies.Policy{}
|
|
fakeRootPolicy.EvaluateSignedDataReturns(fmt.Errorf("MockErr-rootPolicy-1557327456"))
|
|
fakeRootPolicyManager := &mockpolicies.PolicyManager{}
|
|
fakeRootPolicyManager.GetPolicyStub = func(s string) (i policies.Policy, b bool) {
|
|
if s == "rootPolicy" {
|
|
return fakeRootPolicy, true
|
|
}
|
|
return nil, false
|
|
}
|
|
fakeRootPolicyManager.ManagerStub = func(path []string) (manager policies.Manager, b bool) {
|
|
switch {
|
|
case len(path) == 0:
|
|
return fakeRootPolicyManager, true
|
|
case reflect.DeepEqual(path, []string{"foo"}):
|
|
return fakeFooPolicyManager, true
|
|
default:
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
vi := &ValidatorImpl{
|
|
pm: fakeRootPolicyManager,
|
|
}
|
|
|
|
t.Run("Root manager", func(t *testing.T) {
|
|
policy, ok := vi.policyForItem(comparable{
|
|
path: []string{"root"},
|
|
ConfigValue: &cb.ConfigValue{
|
|
ModPolicy: "rootPolicy",
|
|
},
|
|
})
|
|
require.True(t, ok)
|
|
require.Equal(t, policy, fakeRootPolicy, "Should have found relative policy off the root manager")
|
|
})
|
|
|
|
t.Run("Nonexistent manager", func(t *testing.T) {
|
|
_, ok := vi.policyForItem(comparable{
|
|
path: []string{"root", "wrong"},
|
|
ConfigValue: &cb.ConfigValue{
|
|
ModPolicy: "rootPolicy",
|
|
},
|
|
})
|
|
require.False(t, ok, "Should not have found rootPolicy off a nonexistent manager")
|
|
})
|
|
|
|
t.Run("Foo manager", func(t *testing.T) {
|
|
policy, ok := vi.policyForItem(comparable{
|
|
path: []string{"root", "foo"},
|
|
ConfigValue: &cb.ConfigValue{
|
|
ModPolicy: "foo",
|
|
},
|
|
})
|
|
require.True(t, ok)
|
|
require.Equal(t, policy, fakeFooPolicy, "Should have found relative foo policy off the foo manager")
|
|
})
|
|
|
|
t.Run("Foo group", func(t *testing.T) {
|
|
policy, ok := vi.policyForItem(comparable{
|
|
key: "foo",
|
|
path: []string{"root"},
|
|
ConfigGroup: &cb.ConfigGroup{
|
|
ModPolicy: "foo",
|
|
},
|
|
})
|
|
require.True(t, ok)
|
|
require.Equal(t, policy, fakeFooPolicy, "Should have found relative foo policy for foo group")
|
|
})
|
|
|
|
t.Run("Root group manager", func(t *testing.T) {
|
|
policy, ok := vi.policyForItem(comparable{
|
|
path: []string{},
|
|
key: "root",
|
|
ConfigGroup: &cb.ConfigGroup{
|
|
ModPolicy: "rootPolicy",
|
|
},
|
|
})
|
|
require.True(t, ok)
|
|
require.Equal(t, policy, fakeRootPolicy, "Should have found relative policy off the root manager")
|
|
})
|
|
}
|
|
|
|
func TestValidateModPolicy(t *testing.T) {
|
|
t.Run("Valid", func(t *testing.T) {
|
|
require.Nil(t, validateModPolicy("/foo/bar"))
|
|
})
|
|
t.Run("Empty", func(t *testing.T) {
|
|
require.Regexp(t, "mod_policy not set", validateModPolicy(""))
|
|
})
|
|
t.Run("InvalidFirstChar", func(t *testing.T) {
|
|
require.Regexp(t, "path element at 0 is invalid", validateModPolicy("^foo"))
|
|
})
|
|
t.Run("InvalidRootPath", func(t *testing.T) {
|
|
require.Regexp(t, "path element at 0 is invalid", validateModPolicy("/"))
|
|
})
|
|
t.Run("InvalidSubPath", func(t *testing.T) {
|
|
require.Regexp(t, "path element at 1 is invalid", validateModPolicy("foo//bar"))
|
|
})
|
|
}
|