github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/configtx/update_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package configtx 8 9 import ( 10 "fmt" 11 "reflect" 12 "testing" 13 14 cb "github.com/hyperledger/fabric-protos-go/common" 15 mockpolicies "github.com/hyperledger/fabric/common/configtx/mock" 16 "github.com/hyperledger/fabric/common/policies" 17 "github.com/stretchr/testify/assert" 18 ) 19 20 func TestReadSetNotPresent(t *testing.T) { 21 vi := &ValidatorImpl{ 22 configMap: make(map[string]comparable), 23 } 24 25 vi.configMap["1"] = comparable{} 26 vi.configMap["2"] = comparable{} 27 28 readSet := make(map[string]comparable) 29 readSet["1"] = comparable{} 30 readSet["3"] = comparable{} 31 32 assert.Error(t, vi.verifyReadSet(readSet), "ReadSet contained '3', not in config") 33 } 34 35 func TestReadSetBackVersioned(t *testing.T) { 36 vi := &ValidatorImpl{ 37 configMap: make(map[string]comparable), 38 } 39 40 vi.configMap["1"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}} 41 vi.configMap["2"] = comparable{} 42 43 readSet := make(map[string]comparable) 44 readSet["1"] = comparable{} 45 46 assert.Error(t, vi.verifyReadSet(readSet), "ReadSet contained '1', at old version") 47 } 48 49 func TestComputeDeltaSet(t *testing.T) { 50 readSet := make(map[string]comparable) 51 readSet["1"] = comparable{} 52 readSet["2"] = comparable{} 53 54 writeSet := make(map[string]comparable) 55 writeSet["1"] = comparable{} 56 writeSet["2"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}} 57 writeSet["3"] = comparable{} 58 59 result := computeDeltaSet(readSet, writeSet) 60 assert.Len(t, result, 2, "Should have two values in the delta set") 61 assert.NotNil(t, result["2"], "Element had version increased") 62 assert.NotNil(t, result["3"], "Element was new") 63 } 64 65 func TestVerifyDeltaSet(t *testing.T) { 66 pm := &mockpolicies.PolicyManager{} 67 pm.GetPolicyReturns(&mockpolicies.Policy{}, true) 68 vi := &ValidatorImpl{ 69 pm: pm, 70 configMap: make(map[string]comparable), 71 } 72 73 vi.configMap["foo"] = comparable{path: []string{"foo"}} 74 75 t.Run("Green path", func(t *testing.T) { 76 deltaSet := make(map[string]comparable) 77 78 deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}} 79 80 assert.NoError(t, vi.verifyDeltaSet(deltaSet, nil), "Good update") 81 }) 82 83 t.Run("Bad mod policy", func(t *testing.T) { 84 deltaSet := make(map[string]comparable) 85 86 deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}} 87 88 assert.Regexp(t, "invalid mod_policy for element", vi.verifyDeltaSet(deltaSet, nil)) 89 }) 90 91 t.Run("Big Skip", func(t *testing.T) { 92 deltaSet := make(map[string]comparable) 93 94 deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 2, ModPolicy: "foo"}} 95 96 assert.Error(t, vi.verifyDeltaSet(deltaSet, nil), "Version skip from 0 to 2") 97 }) 98 99 t.Run("New item high version", func(t *testing.T) { 100 deltaSet := make(map[string]comparable) 101 102 deltaSet["bar"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}} 103 104 assert.Error(t, vi.verifyDeltaSet(deltaSet, nil), "New key not at version 0") 105 }) 106 107 t.Run("Policy evalaution to false", func(t *testing.T) { 108 deltaSet := make(map[string]comparable) 109 110 deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}} 111 fakePolicy := &mockpolicies.Policy{} 112 fakePolicy.EvaluateSignedDataReturns(fmt.Errorf("MockErr-fakePolicy.Evaluate-1557327297")) 113 vi.pm.(*mockpolicies.PolicyManager).GetPolicyReturns(fakePolicy, true) 114 115 assert.Error(t, vi.verifyDeltaSet(deltaSet, nil), "Policy evaluation should have failed") 116 }) 117 118 t.Run("Empty delta set", func(t *testing.T) { 119 err := (&ValidatorImpl{}).verifyDeltaSet(map[string]comparable{}, nil) 120 assert.Error(t, err, "Empty delta set should be rejected") 121 assert.Contains(t, err.Error(), "delta set was empty -- update would have no effect") 122 }) 123 } 124 125 func TestPolicyForItem(t *testing.T) { 126 // Policies are set to different error values to differentiate them in equal assertion 127 128 fakeFooPolicy := &mockpolicies.Policy{} 129 fakeFooPolicy.EvaluateSignedDataReturns(fmt.Errorf("MockErr-fooPolicy-1557327481")) 130 fakeFooPolicyManager := &mockpolicies.PolicyManager{} 131 fakeFooPolicyManager.GetPolicyStub = func(s string) (i policies.Policy, b bool) { 132 if s == "foo" { 133 return fakeFooPolicy, true 134 } 135 return nil, false 136 } 137 fakeRootPolicy := &mockpolicies.Policy{} 138 fakeRootPolicy.EvaluateSignedDataReturns(fmt.Errorf("MockErr-rootPolicy-1557327456")) 139 fakeRootPolicyManager := &mockpolicies.PolicyManager{} 140 fakeRootPolicyManager.GetPolicyStub = func(s string) (i policies.Policy, b bool) { 141 if s == "rootPolicy" { 142 return fakeRootPolicy, true 143 } 144 return nil, false 145 } 146 fakeRootPolicyManager.ManagerStub = func(path []string) (manager policies.Manager, b bool) { 147 switch { 148 case len(path) == 0: 149 return fakeRootPolicyManager, true 150 case reflect.DeepEqual(path, []string{"foo"}): 151 return fakeFooPolicyManager, true 152 default: 153 return nil, false 154 } 155 } 156 157 vi := &ValidatorImpl{ 158 pm: fakeRootPolicyManager, 159 } 160 161 t.Run("Root manager", func(t *testing.T) { 162 policy, ok := vi.policyForItem(comparable{ 163 path: []string{"root"}, 164 ConfigValue: &cb.ConfigValue{ 165 ModPolicy: "rootPolicy", 166 }, 167 }) 168 assert.True(t, ok) 169 assert.Equal(t, policy, fakeRootPolicy, "Should have found relative policy off the root manager") 170 }) 171 172 t.Run("Nonexistent manager", func(t *testing.T) { 173 _, ok := vi.policyForItem(comparable{ 174 path: []string{"root", "wrong"}, 175 ConfigValue: &cb.ConfigValue{ 176 ModPolicy: "rootPolicy", 177 }, 178 }) 179 assert.False(t, ok, "Should not have found rootPolicy off a nonexistent manager") 180 }) 181 182 t.Run("Foo manager", func(t *testing.T) { 183 policy, ok := vi.policyForItem(comparable{ 184 path: []string{"root", "foo"}, 185 ConfigValue: &cb.ConfigValue{ 186 ModPolicy: "foo", 187 }, 188 }) 189 assert.True(t, ok) 190 assert.Equal(t, policy, fakeFooPolicy, "Should have found relative foo policy off the foo manager") 191 }) 192 193 t.Run("Foo group", func(t *testing.T) { 194 policy, ok := vi.policyForItem(comparable{ 195 key: "foo", 196 path: []string{"root"}, 197 ConfigGroup: &cb.ConfigGroup{ 198 ModPolicy: "foo", 199 }, 200 }) 201 assert.True(t, ok) 202 assert.Equal(t, policy, fakeFooPolicy, "Should have found relative foo policy for foo group") 203 }) 204 205 t.Run("Root group manager", func(t *testing.T) { 206 policy, ok := vi.policyForItem(comparable{ 207 path: []string{}, 208 key: "root", 209 ConfigGroup: &cb.ConfigGroup{ 210 ModPolicy: "rootPolicy", 211 }, 212 }) 213 assert.True(t, ok) 214 assert.Equal(t, policy, fakeRootPolicy, "Should have found relative policy off the root manager") 215 }) 216 } 217 218 func TestValidateModPolicy(t *testing.T) { 219 t.Run("Valid", func(t *testing.T) { 220 assert.Nil(t, validateModPolicy("/foo/bar")) 221 }) 222 t.Run("Empty", func(t *testing.T) { 223 assert.Regexp(t, "mod_policy not set", validateModPolicy("")) 224 }) 225 t.Run("InvalidFirstChar", func(t *testing.T) { 226 assert.Regexp(t, "path element at 0 is invalid", validateModPolicy("^foo")) 227 }) 228 t.Run("InvalidRootPath", func(t *testing.T) { 229 assert.Regexp(t, "path element at 0 is invalid", validateModPolicy("/")) 230 }) 231 t.Run("InvalidSubPath", func(t *testing.T) { 232 assert.Regexp(t, "path element at 1 is invalid", validateModPolicy("foo//bar")) 233 }) 234 }