Commit c341fe5a authored by Srinivasan Muralidharan's avatar Srinivasan Muralidharan Committed by Gerrit Code Review
Browse files

Merge "[FAB-2142] Make new config comparable"

parents 64754cae dc30c8e4
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configtx
import (
"bytes"
cb "github.com/hyperledger/fabric/protos/common"
)
type comparable struct {
*cb.ConfigGroup
*cb.ConfigValue
*cb.ConfigPolicy
}
func (cg comparable) equals(other comparable) bool {
switch {
case cg.ConfigGroup != nil:
if other.ConfigGroup == nil {
return false
}
return equalConfigGroup(cg.ConfigGroup, other.ConfigGroup)
case cg.ConfigValue != nil:
if other.ConfigValue == nil {
return false
}
return equalConfigValues(cg.ConfigValue, other.ConfigValue)
case cg.ConfigPolicy != nil:
if other.ConfigPolicy == nil {
return false
}
return equalConfigPolicies(cg.ConfigPolicy, other.ConfigPolicy)
}
// Unreachable
return false
}
func equalConfigValues(lhs, rhs *cb.ConfigValue) bool {
return lhs.Version == rhs.Version &&
lhs.ModPolicy == rhs.ModPolicy &&
bytes.Equal(lhs.Value, rhs.Value)
}
func equalConfigPolicies(lhs, rhs *cb.ConfigPolicy) bool {
if lhs.Version != rhs.Version ||
lhs.ModPolicy != rhs.ModPolicy {
return false
}
if lhs.Policy == nil || rhs.Policy == nil {
return lhs.Policy == rhs.Policy
}
return lhs.Policy.Type == rhs.Policy.Type &&
bytes.Equal(lhs.Policy.Policy, rhs.Policy.Policy)
}
// The subset functions check if inner is a subset of outer
// TODO, try to consolidate these three methods into one, as the code
// contents are the same, but the function signatures need to be different
func subsetOfGroups(inner, outer map[string]*cb.ConfigGroup) bool {
// The empty set is a subset of all sets
if len(inner) == 0 {
return true
}
// If inner is not the empty set, then the outer empty set cannot be a superset of inner
if len(outer) == 0 {
return false
}
// If any element in inner is not in outer, it is not a subset
for key := range inner {
if _, ok := outer[key]; !ok {
return false
}
}
return true
}
func subsetOfPolicies(inner, outer map[string]*cb.ConfigPolicy) bool {
// The empty set is a subset of all sets
if len(inner) == 0 {
return true
}
// If inner is not the empty set, then the outer empty set cannot be a superset of inner
if len(outer) == 0 {
return false
}
// If any element in inner is not in outer, it is not a subset
for key := range inner {
if _, ok := outer[key]; !ok {
return false
}
}
return true
}
func subsetOfValues(inner, outer map[string]*cb.ConfigValue) bool {
// The empty set is a subset of all sets
if len(inner) == 0 {
return true
}
// If inner is not the empty set, then the outer empty set cannot be a superset of inner
if len(outer) == 0 {
return false
}
// If any element in inner is not in outer, it is not a subset
for key := range inner {
if _, ok := outer[key]; !ok {
return false
}
}
return true
}
func equalConfigGroup(lhs, rhs *cb.ConfigGroup) bool {
if lhs.Version != rhs.Version ||
lhs.ModPolicy != rhs.ModPolicy {
return false
}
if !subsetOfGroups(lhs.Groups, rhs.Groups) {
return false
}
if !subsetOfGroups(rhs.Groups, lhs.Groups) {
return false
}
if !subsetOfPolicies(lhs.Policies, rhs.Policies) {
return false
}
if !subsetOfPolicies(rhs.Policies, lhs.Policies) {
return false
}
if !subsetOfValues(lhs.Values, rhs.Values) {
return false
}
if !subsetOfValues(rhs.Values, lhs.Values) {
return false
}
return true
}
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configtx
import (
"github.com/stretchr/testify/assert"
"testing"
cb "github.com/hyperledger/fabric/protos/common"
)
func TestCompareConfigValue(t *testing.T) {
// Normal equality
assert.True(t, comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("bar"),
}}.equals(comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("bar"),
}}), "Should have found identical config values to be identical")
// Different Mod Policy
assert.False(t, comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("bar"),
}}.equals(comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "bar",
Value: []byte("bar"),
}}), "Should have detected different mod policy")
// Different Value
assert.False(t, comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("bar"),
}}.equals(comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("foo"),
}}), "Should have detected different value")
// Different Version
assert.False(t, comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("bar"),
}}.equals(comparable{
ConfigValue: &cb.ConfigValue{
Version: 1,
ModPolicy: "foo",
Value: []byte("bar"),
}}), "Should have detected different version")
// One nil value
assert.False(t, comparable{
ConfigValue: &cb.ConfigValue{
Version: 0,
ModPolicy: "foo",
Value: []byte("bar"),
}}.equals(comparable{}), "Should have detected nil other value")
}
func TestCompareConfigPolicy(t *testing.T) {
// Normal equality
assert.True(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}), "Should have found identical config policies to be identical")
// Different mod policy
assert.False(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "bar",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}), "Should have detected different mod policy")
// Different version
assert.False(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 1,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}), "Should have detected different version")
// Different policy type
assert.False(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 2,
Policy: []byte("foo"),
},
}}), "Should have detected different policy type")
// Different policy value
assert.False(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("bar"),
},
}}), "Should have detected different policy value")
// One nil value
assert.False(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{}), "Should have detected one nil value")
// One nil policy
assert.False(t, comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
Policy: []byte("foo"),
},
}}.equals(comparable{
ConfigPolicy: &cb.ConfigPolicy{
Version: 0,
ModPolicy: "foo",
Policy: &cb.Policy{
Type: 1,
},
}}), "Should have detected one nil policy")
}
func TestCompareConfigGroup(t *testing.T) {
// Normal equality
assert.True(t, comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}.equals(comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}), "Should have found identical config groups to be identical")
// Different mod policy
assert.False(t, comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
}}.equals(comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "bar",
}}), "Should have detected different mod policy")
// Different version
assert.False(t, comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
}}.equals(comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 1,
ModPolicy: "foo",
}}), "Should have detected different version")
// Different groups
assert.False(t, comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}.equals(comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}), "Should have detected different groups entries")
// Different values
assert.False(t, comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}.equals(comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}), "Should have detected fifferent values entries")
// Different policies
assert.False(t, comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar3": nil},
}}.equals(comparable{
ConfigGroup: &cb.ConfigGroup{
Version: 0,
ModPolicy: "foo",
Groups: map[string]*cb.ConfigGroup{"Foo1": nil, "Bar1": nil},
Values: map[string]*cb.ConfigValue{"Foo2": nil, "Bar2": nil},
Policies: map[string]*cb.ConfigPolicy{"Foo3": nil, "Bar4": nil},
}}), "Should have detected fifferent policies entries")
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment