github.com/true-sqn/fabric@v2.1.1+incompatible/common/policies/inquire/inquire_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package inquire
     8  
     9  import (
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-protos-go/msp"
    15  	"github.com/hyperledger/fabric/common/policydsl"
    16  	"github.com/hyperledger/fabric/protoutil"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  type testCase struct {
    21  	name       string
    22  	policy     string
    23  	expected   map[string]struct{}
    24  	principals []*msp.MSPPrincipal
    25  }
    26  
    27  func createPrincipals(orgNames ...string) []*msp.MSPPrincipal {
    28  	principals := make([]*msp.MSPPrincipal, 0)
    29  	appendPrincipal := func(orgName string) {
    30  		principals = append(principals, &msp.MSPPrincipal{
    31  			PrincipalClassification: msp.MSPPrincipal_ROLE,
    32  			Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: orgName})})
    33  	}
    34  	for _, org := range orgNames {
    35  		appendPrincipal(org)
    36  	}
    37  	return principals
    38  }
    39  
    40  var cases = []testCase{
    41  	{
    42  		name:   "orOfAnds",
    43  		policy: "OR(AND('A.member', 'B.member'), 'C.member', AND('A.member', 'D.member'))",
    44  		expected: map[string]struct{}{
    45  			fmt.Sprintf("%v", []string{"A", "B"}): {},
    46  			fmt.Sprintf("%v", []string{"C"}):      {},
    47  			fmt.Sprintf("%v", []string{"A", "D"}): {},
    48  		},
    49  		principals: createPrincipals("A", "B", "C", "D", "A"),
    50  	},
    51  	{
    52  		name:   "andOfOrs",
    53  		policy: "AND('A.member', 'C.member', OR('B.member', 'D.member'))",
    54  		expected: map[string]struct{}{
    55  			fmt.Sprintf("%v", []string{"A", "C", "B"}): {},
    56  			fmt.Sprintf("%v", []string{"A", "C", "D"}): {},
    57  		},
    58  		principals: createPrincipals("A", "C", "B", "D"),
    59  	},
    60  	{
    61  		name:   "orOfOrs",
    62  		policy: "OR('A.member', OR('B.member', 'C.member'))",
    63  		expected: map[string]struct{}{
    64  			fmt.Sprintf("%v", []string{"A"}): {},
    65  			fmt.Sprintf("%v", []string{"B"}): {},
    66  			fmt.Sprintf("%v", []string{"C"}): {},
    67  		},
    68  		principals: createPrincipals("A", "B", "C"),
    69  	},
    70  	{
    71  		name:   "andOfAnds",
    72  		policy: "AND('A.member', AND('B.member', 'C.member'), AND('D.member','A.member'))",
    73  		expected: map[string]struct{}{
    74  			fmt.Sprintf("%v", []string{"A", "B", "C", "D", "A"}): {},
    75  		},
    76  		principals: createPrincipals("A", "B", "C", "D"),
    77  	},
    78  }
    79  
    80  func mspId(principal *msp.MSPPrincipal) string {
    81  	role := &msp.MSPRole{}
    82  	proto.Unmarshal(principal.Principal, role)
    83  	return role.MspIdentifier
    84  }
    85  
    86  func TestSatisfiedBy(t *testing.T) {
    87  	for _, test := range cases {
    88  		t.Run(test.name, func(t *testing.T) {
    89  			p, err := policydsl.FromString(test.policy)
    90  			assert.NoError(t, err)
    91  
    92  			ip := NewInquireableSignaturePolicy(p)
    93  			satisfiedBy := ip.SatisfiedBy()
    94  
    95  			actual := make(map[string]struct{})
    96  			for _, ps := range satisfiedBy {
    97  				var principals []string
    98  				for _, principal := range ps {
    99  					principals = append(principals, mspId(principal))
   100  				}
   101  				actual[fmt.Sprintf("%v", principals)] = struct{}{}
   102  			}
   103  
   104  			assert.Equal(t, test.expected, actual)
   105  		})
   106  	}
   107  }
   108  
   109  func TestSatisfiedByTooManyCombinations(t *testing.T) {
   110  	// We have 26 choose 15 members which is 7,726,160
   111  	// and we ensure we don't return so many combinations,
   112  	// but limit it to combinationsUpperBound.
   113  
   114  	p, err := policydsl.FromString("OutOf(15, 'A.member', 'B.member', 'C.member', 'D.member', 'E.member', 'F.member'," +
   115  		" 'G.member', 'H.member', 'I.member', 'J.member', 'K.member', 'L.member', 'M.member', 'N.member', 'O.member', " +
   116  		"'P.member', 'Q.member', 'R.member', 'S.member', 'T.member', 'U.member', 'V.member', 'W.member', 'X.member', " +
   117  		"'Y.member', 'Z.member')")
   118  	assert.NoError(t, err)
   119  
   120  	ip := NewInquireableSignaturePolicy(p)
   121  	satisfiedBy := ip.SatisfiedBy()
   122  
   123  	actual := make(map[string]struct{})
   124  	for _, ps := range satisfiedBy {
   125  		// Every subset is of size 15, as needed by the endorsement policy.
   126  		assert.Len(t, ps, 15)
   127  		var principals []string
   128  		for _, principal := range ps {
   129  			principals = append(principals, mspId(principal))
   130  		}
   131  		actual[fmt.Sprintf("%v", principals)] = struct{}{}
   132  	}
   133  	// Total combinations are capped by the combinationsUpperBound.
   134  	assert.True(t, len(actual) < combinationsUpperBound)
   135  }