github.com/zhouxv/fabric@v2.1.1+incompatible/core/common/validation/statebased/vpmanager_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package statebased
     8  
     9  import (
    10  	"fmt"
    11  	"math/rand"
    12  	"runtime"
    13  	"strconv"
    14  	"sync"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    19  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    20  	pb "github.com/hyperledger/fabric-protos-go/peer"
    21  	"github.com/hyperledger/fabric/common/policydsl"
    22  	validation "github.com/hyperledger/fabric/core/handlers/validation/api/state"
    23  	"github.com/hyperledger/fabric/protoutil"
    24  	"github.com/pkg/errors"
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  type mockState struct {
    29  	GetStateMetadataRv              map[string][]byte
    30  	GetStateMetadataErr             error
    31  	GetPrivateDataMetadataByHashRv  map[string][]byte
    32  	GetPrivateDataMetadataByHashErr error
    33  	DoneCalled                      bool
    34  }
    35  
    36  func (ms *mockState) GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) {
    37  	return nil, nil
    38  }
    39  
    40  func (ms *mockState) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (validation.ResultsIterator, error) {
    41  	return nil, nil
    42  }
    43  
    44  func (ms *mockState) GetStateMetadata(namespace, key string) (map[string][]byte, error) {
    45  	return ms.GetStateMetadataRv, ms.GetStateMetadataErr
    46  }
    47  
    48  func (ms *mockState) GetPrivateDataMetadataByHash(namespace, collection string, keyhash []byte) (map[string][]byte, error) {
    49  	return ms.GetPrivateDataMetadataByHashRv, ms.GetPrivateDataMetadataByHashErr
    50  }
    51  
    52  func (ms *mockState) Done() {
    53  	ms.DoneCalled = true
    54  }
    55  
    56  type mockStateFetcher struct {
    57  	mutex          sync.Mutex
    58  	returnedStates []*mockState
    59  	FetchStateRv   *mockState
    60  	FetchStateErr  error
    61  }
    62  
    63  func (ms *mockStateFetcher) DoneCalled() bool {
    64  	for _, s := range ms.returnedStates {
    65  		if !s.DoneCalled {
    66  			return false
    67  		}
    68  	}
    69  	return true
    70  }
    71  
    72  type mockTranslator struct {
    73  	TranslateError error
    74  }
    75  
    76  func (n *mockTranslator) Translate(b []byte) ([]byte, error) {
    77  	return b, n.TranslateError
    78  }
    79  
    80  func (ms *mockStateFetcher) FetchState() (validation.State, error) {
    81  	var rv *mockState
    82  	if ms.FetchStateRv != nil {
    83  		rv = &mockState{
    84  			GetPrivateDataMetadataByHashErr: ms.FetchStateRv.GetPrivateDataMetadataByHashErr,
    85  			GetStateMetadataErr:             ms.FetchStateRv.GetStateMetadataErr,
    86  			GetPrivateDataMetadataByHashRv:  ms.FetchStateRv.GetPrivateDataMetadataByHashRv,
    87  			GetStateMetadataRv:              ms.FetchStateRv.GetStateMetadataRv,
    88  		}
    89  		ms.mutex.Lock()
    90  		if ms.returnedStates != nil {
    91  			ms.returnedStates = make([]*mockState, 0, 1)
    92  		}
    93  		ms.returnedStates = append(ms.returnedStates, rv)
    94  		ms.mutex.Unlock()
    95  	}
    96  	return rv, ms.FetchStateErr
    97  }
    98  
    99  func TestSimple(t *testing.T) {
   100  	t.Parallel()
   101  
   102  	// Scenario: validation parameter is retrieved with no dependency
   103  
   104  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   105  	spe := policydsl.SignedByMspMember("foo")
   106  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   107  	ms := &mockStateFetcher{FetchStateRv: mr}
   108  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{},
   109  		StateFetcher: ms,
   110  	}
   111  
   112  	sp, err := pm.GetValidationParameterForKey("cc", "coll", "key", 0, 0)
   113  	assert.NoError(t, err)
   114  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp)
   115  	assert.True(t, ms.DoneCalled())
   116  }
   117  
   118  func rwsetUpdatingMetadataFor(cc, key string) []byte {
   119  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   120  	return protoutil.MarshalOrPanic(
   121  		&rwset.TxReadWriteSet{
   122  			NsRwset: []*rwset.NsReadWriteSet{
   123  				{
   124  					Namespace: cc,
   125  					Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{
   126  						MetadataWrites: []*kvrwset.KVMetadataWrite{
   127  							{
   128  								Key: key,
   129  								Entries: []*kvrwset.KVMetadataEntry{
   130  									{
   131  										Name: vpMetadataKey,
   132  									},
   133  								},
   134  							},
   135  						},
   136  					}),
   137  				},
   138  			}})
   139  }
   140  
   141  func pvtRwsetUpdatingMetadataFor(cc, coll, key string) []byte {
   142  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   143  	return protoutil.MarshalOrPanic(
   144  		&rwset.TxReadWriteSet{
   145  			NsRwset: []*rwset.NsReadWriteSet{
   146  				{
   147  					Namespace: cc,
   148  					CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{
   149  						{
   150  							CollectionName: coll,
   151  							HashedRwset: protoutil.MarshalOrPanic(&kvrwset.HashedRWSet{
   152  								MetadataWrites: []*kvrwset.KVMetadataWriteHash{
   153  									{
   154  										KeyHash: []byte(key),
   155  										Entries: []*kvrwset.KVMetadataEntry{
   156  											{
   157  												Name: vpMetadataKey,
   158  											},
   159  										},
   160  									},
   161  								},
   162  							}),
   163  						},
   164  					},
   165  				},
   166  			}})
   167  }
   168  
   169  func runFunctions(t *testing.T, seed int64, funcs ...func()) {
   170  	r := rand.New(rand.NewSource(seed))
   171  	c := make(chan struct{})
   172  	for _, i := range r.Perm(len(funcs)) {
   173  		iLcl := i
   174  		go func() {
   175  			assert.NotPanics(t, funcs[iLcl], "assert failure occurred with seed %d", seed)
   176  			c <- struct{}{}
   177  		}()
   178  	}
   179  	for range funcs {
   180  		<-c
   181  	}
   182  }
   183  
   184  func TestTranslatorBadPolicy(t *testing.T) {
   185  	t.Parallel()
   186  	seed := time.Now().Unix()
   187  
   188  	// Scenario: we verify that translation from SignaturePolicyEnvelope to ApplicationPolicy fails appropriately
   189  
   190  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   191  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: []byte("barf")}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: []byte("barf")}}
   192  	ms := &mockStateFetcher{FetchStateRv: mr}
   193  	mt := &mockTranslator{}
   194  	mt.TranslateError = errors.New("you shall not pass")
   195  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: mt, StateFetcher: ms}
   196  
   197  	cc, coll, key := "cc", "", "key"
   198  
   199  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   200  
   201  	resC := make(chan []byte, 1)
   202  	errC := make(chan error, 1)
   203  	runFunctions(t, seed,
   204  		func() {
   205  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   206  		},
   207  		func() {
   208  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   209  		},
   210  		func() {
   211  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   212  			resC <- sp
   213  			errC <- err
   214  		})
   215  
   216  	sp := <-resC
   217  	err := <-errC
   218  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   219  	assert.Contains(t, err.Error(), "could not translate policy for cc:key: you shall not pass", "assert failure occurred with seed %d", seed)
   220  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   221  	assert.Nil(t, sp, "assert failure occurred with seed %d", seed)
   222  }
   223  
   224  func TestTranslatorBadPolicyPvt(t *testing.T) {
   225  	t.Parallel()
   226  	seed := time.Now().Unix()
   227  
   228  	// Scenario: we verify that translation from SignaturePolicyEnvelope to ApplicationPolicy fails appropriately with private data
   229  
   230  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   231  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: []byte("barf")}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: []byte("barf")}}
   232  	ms := &mockStateFetcher{FetchStateRv: mr}
   233  	mt := &mockTranslator{}
   234  	mt.TranslateError = errors.New("you shall not pass")
   235  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: mt, StateFetcher: ms}
   236  
   237  	cc, coll, key := "cc", "coll", "key"
   238  
   239  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   240  
   241  	resC := make(chan []byte, 1)
   242  	errC := make(chan error, 1)
   243  	runFunctions(t, seed,
   244  		func() {
   245  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   246  		},
   247  		func() {
   248  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   249  		},
   250  		func() {
   251  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   252  			resC <- sp
   253  			errC <- err
   254  		})
   255  
   256  	sp := <-resC
   257  	err := <-errC
   258  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   259  	assert.Contains(t, err.Error(), "could not translate policy for cc:coll:6b6579: you shall not pass", "assert failure occurred with seed %d", seed)
   260  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   261  	assert.Nil(t, sp, "assert failure occurred with seed %d", seed)
   262  }
   263  
   264  func TestDependencyNoConflict(t *testing.T) {
   265  	t.Parallel()
   266  	seed := time.Now().Unix()
   267  
   268  	// Scenario: validation parameter is retrieved successfully
   269  	// for a ledger key for transaction (1,1) after waiting for
   270  	// the dependency introduced by transaction (1,0). Retrieval
   271  	// was successful because transaction (1,0) was invalid and
   272  	// so we could safely retrieve the validation parameter from
   273  	// the ledger.
   274  
   275  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   276  	spe := policydsl.SignedByMspMember("foo")
   277  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   278  	ms := &mockStateFetcher{FetchStateRv: mr}
   279  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   280  
   281  	cc, coll, key := "cc", "", "key"
   282  
   283  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   284  
   285  	resC := make(chan []byte, 1)
   286  	errC := make(chan error, 1)
   287  	runFunctions(t, seed,
   288  		func() {
   289  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   290  		},
   291  		func() {
   292  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   293  		},
   294  		func() {
   295  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   296  			resC <- sp
   297  			errC <- err
   298  		})
   299  
   300  	sp := <-resC
   301  	err := <-errC
   302  	assert.NoError(t, err, "assert failure occurred with seed %d", seed)
   303  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp, "assert failure occurred with seed %d", seed)
   304  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   305  }
   306  
   307  func TestDependencyConflict(t *testing.T) {
   308  	t.Parallel()
   309  	seed := time.Now().Unix()
   310  
   311  	// Scenario: validation parameter is retrieved
   312  	// for a ledger key for transaction (1,1) after waiting for
   313  	// the dependency introduced by transaction (1,0). Retrieval
   314  	// fails because transaction (1,0) was valid and so we cannot
   315  	// retrieve the validation parameter from the ledger, given
   316  	// that transaction (1,0) may or may not be valid according
   317  	// to the ledger component because of MVCC checks
   318  
   319  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   320  	spe := policydsl.SignedByMspMember("foo")
   321  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   322  	ms := &mockStateFetcher{FetchStateRv: mr}
   323  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   324  
   325  	cc, coll, key := "cc", "", "key"
   326  
   327  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   328  
   329  	resC := make(chan []byte, 1)
   330  	errC := make(chan error, 1)
   331  	runFunctions(t, seed,
   332  		func() {
   333  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   334  		},
   335  		func() {
   336  			pm.SetTxValidationResult(cc, 1, 0, nil)
   337  		},
   338  		func() {
   339  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   340  			resC <- sp
   341  			errC <- err
   342  		})
   343  
   344  	sp := <-resC
   345  	err := <-errC
   346  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   347  	assert.IsType(t, &ValidationParameterUpdatedError{}, err, "assert failure occurred with seed %d", seed)
   348  	assert.Nil(t, sp, "assert failure occurred with seed %d", seed)
   349  }
   350  
   351  func TestMultipleDependencyNoConflict(t *testing.T) {
   352  	t.Parallel()
   353  	seed := time.Now().Unix()
   354  
   355  	// Scenario: validation parameter is retrieved successfully
   356  	// for a ledger key for transaction (1,2) after waiting for
   357  	// the dependency introduced by transaction (1,0) and (1,1).
   358  	// Retrieval was successful because both were invalid and
   359  	// so we could safely retrieve the validation parameter from
   360  	// the ledger.
   361  
   362  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   363  	spe := policydsl.SignedByMspMember("foo")
   364  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   365  	ms := &mockStateFetcher{FetchStateRv: mr}
   366  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   367  
   368  	cc, coll, key := "cc", "", "key"
   369  
   370  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   371  
   372  	resC := make(chan []byte, 1)
   373  	errC := make(chan error, 1)
   374  	runFunctions(t, seed,
   375  		func() {
   376  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   377  		},
   378  		func() {
   379  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   380  		},
   381  		func() {
   382  			pm.ExtractValidationParameterDependency(1, 1, rwsetbytes)
   383  		},
   384  		func() {
   385  			pm.SetTxValidationResult(cc, 1, 1, errors.New(""))
   386  		},
   387  		func() {
   388  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 2)
   389  			resC <- sp
   390  			errC <- err
   391  		})
   392  
   393  	sp := <-resC
   394  	err := <-errC
   395  	assert.NoError(t, err, "assert failure occurred with seed %d", seed)
   396  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp, "assert failure occurred with seed %d", seed)
   397  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   398  }
   399  
   400  func TestMultipleDependencyConflict(t *testing.T) {
   401  	t.Parallel()
   402  	seed := time.Now().Unix()
   403  
   404  	// Scenario: validation parameter is retrieved
   405  	// for a ledger key for transaction (1,2) after waiting for
   406  	// the dependency introduced by transaction (1,0) and (1,1).
   407  	// Retrieval fails because transaction (1,1) is valid and so
   408  	// we cannot retrieve the validation parameter from the ledger,
   409  	// given that transaction (1,0) may or may not be valid according
   410  	// to the ledger component because of MVCC checks
   411  
   412  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   413  	spe := policydsl.SignedByMspMember("foo")
   414  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   415  	ms := &mockStateFetcher{FetchStateRv: mr}
   416  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   417  
   418  	cc, coll, key := "cc", "", "key"
   419  
   420  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   421  
   422  	resC := make(chan []byte, 1)
   423  	errC := make(chan error, 1)
   424  	runFunctions(t, seed,
   425  		func() {
   426  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   427  		},
   428  		func() {
   429  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   430  		},
   431  		func() {
   432  			pm.ExtractValidationParameterDependency(1, 1, rwsetbytes)
   433  		},
   434  		func() {
   435  			pm.SetTxValidationResult(cc, 1, 1, nil)
   436  		},
   437  		func() {
   438  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 2)
   439  			resC <- sp
   440  			errC <- err
   441  		})
   442  
   443  	sp := <-resC
   444  	err := <-errC
   445  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   446  	assert.IsType(t, &ValidationParameterUpdatedError{}, err, "assert failure occurred with seed %d", seed)
   447  	assert.Nil(t, sp, "assert failure occurred with seed %d", seed)
   448  }
   449  
   450  func TestPvtDependencyNoConflict(t *testing.T) {
   451  	t.Parallel()
   452  	seed := time.Now().Unix()
   453  
   454  	// Scenario: like TestDependencyNoConflict but for private data
   455  
   456  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   457  	spe := policydsl.SignedByMspMember("foo")
   458  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   459  	ms := &mockStateFetcher{FetchStateRv: mr}
   460  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   461  
   462  	cc, coll, key := "cc", "coll", "key"
   463  
   464  	rwsetBytes := pvtRwsetUpdatingMetadataFor(cc, coll, key)
   465  
   466  	resC := make(chan []byte, 1)
   467  	errC := make(chan error, 1)
   468  	runFunctions(t, seed,
   469  		func() {
   470  			pm.ExtractValidationParameterDependency(1, 0, rwsetBytes)
   471  		},
   472  		func() {
   473  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   474  		},
   475  		func() {
   476  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   477  			resC <- sp
   478  			errC <- err
   479  		})
   480  
   481  	sp := <-resC
   482  	err := <-errC
   483  	assert.NoError(t, err, "assert failure occurred with seed %d", seed)
   484  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp, "assert failure occurred with seed %d", seed)
   485  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   486  }
   487  
   488  func TestPvtDependencyConflict(t *testing.T) {
   489  	t.Parallel()
   490  	seed := time.Now().Unix()
   491  
   492  	// Scenario: like TestDependencyConflict but for private data
   493  
   494  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   495  	spe := policydsl.SignedByMspMember("foo")
   496  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   497  	ms := &mockStateFetcher{FetchStateRv: mr}
   498  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   499  
   500  	cc, coll, key := "cc", "coll", "key"
   501  
   502  	rwsetBytes := pvtRwsetUpdatingMetadataFor(cc, coll, key)
   503  
   504  	resC := make(chan []byte, 1)
   505  	errC := make(chan error, 1)
   506  	runFunctions(t, seed,
   507  		func() {
   508  			pm.ExtractValidationParameterDependency(1, 0, rwsetBytes)
   509  		},
   510  		func() {
   511  			pm.SetTxValidationResult(cc, 1, 0, nil)
   512  		},
   513  		func() {
   514  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   515  			resC <- sp
   516  			errC <- err
   517  		})
   518  
   519  	sp := <-resC
   520  	err := <-errC
   521  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   522  	assert.IsType(t, &ValidationParameterUpdatedError{}, err, "assert failure occurred with seed %d", seed)
   523  	assert.True(t, len(err.Error()) > 0, "assert failure occurred with seed %d", seed)
   524  	assert.Nil(t, sp, "assert failure occurred with seed %d", seed)
   525  }
   526  
   527  func TestBlockValidationTerminatesBeforeNewBlock(t *testing.T) {
   528  	t.Parallel()
   529  
   530  	// Scenario: due to a programming error, validation for
   531  	// transaction (1,0) is scheduled after that for transaction
   532  	// (2,0). This cannot happen and so we panic
   533  
   534  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   535  	spe := policydsl.SignedByMspMember("foo")
   536  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   537  	ms := &mockStateFetcher{FetchStateRv: mr}
   538  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   539  
   540  	cc, coll, key := "cc", "coll", "key"
   541  
   542  	rwsetBytes := pvtRwsetUpdatingMetadataFor(cc, coll, key)
   543  
   544  	pm.ExtractValidationParameterDependency(2, 0, rwsetBytes)
   545  	panickingFunc := func() {
   546  		pm.ExtractValidationParameterDependency(1, 0, rwsetBytes)
   547  	}
   548  	assert.Panics(t, panickingFunc)
   549  }
   550  
   551  func TestLedgerErrors(t *testing.T) {
   552  	t.Parallel()
   553  	seed := time.Now().Unix()
   554  
   555  	// Scenario: we check that if a ledger error occurs,
   556  	// GetValidationParameterForKey returns an error
   557  
   558  	mr := &mockState{
   559  		GetStateMetadataErr:             fmt.Errorf("Ledger error"),
   560  		GetPrivateDataMetadataByHashErr: fmt.Errorf("Ledger error"),
   561  	}
   562  	ms := &mockStateFetcher{FetchStateRv: mr, FetchStateErr: fmt.Errorf("Ledger error")}
   563  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   564  
   565  	cc, coll, key := "cc", "", "key"
   566  
   567  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   568  
   569  	errC := make(chan error, 1)
   570  	runFunctions(t, seed,
   571  		func() {
   572  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   573  		},
   574  		func() {
   575  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   576  		},
   577  		func() {
   578  			_, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   579  			errC <- err
   580  		})
   581  
   582  	err := <-errC
   583  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   584  
   585  	ms.FetchStateErr = nil
   586  
   587  	runFunctions(t, seed,
   588  		func() {
   589  			pm.ExtractValidationParameterDependency(2, 0, rwsetbytes)
   590  		},
   591  		func() {
   592  			pm.SetTxValidationResult(cc, 2, 0, errors.New(""))
   593  		},
   594  		func() {
   595  			_, err := pm.GetValidationParameterForKey(cc, coll, key, 2, 1)
   596  			errC <- err
   597  		})
   598  
   599  	err = <-errC
   600  	assert.Error(t, err)
   601  
   602  	cc, coll, key = "cc", "coll", "key"
   603  
   604  	rwsetbytes = pvtRwsetUpdatingMetadataFor(cc, coll, key)
   605  
   606  	runFunctions(t, seed,
   607  		func() {
   608  			pm.ExtractValidationParameterDependency(3, 0, rwsetbytes)
   609  		},
   610  		func() {
   611  			pm.SetTxValidationResult(cc, 3, 0, errors.New(""))
   612  		},
   613  		func() {
   614  			_, err = pm.GetValidationParameterForKey(cc, coll, key, 3, 1)
   615  			errC <- err
   616  		})
   617  
   618  	err = <-errC
   619  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   620  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   621  }
   622  
   623  func TestBadRwsetIsNoDependency(t *testing.T) {
   624  	t.Parallel()
   625  	seed := time.Now().Unix()
   626  
   627  	// Scenario: a transaction has a bogus read-write set.
   628  	// While the transaction will fail eventually, we check
   629  	// that our code doesn't break
   630  
   631  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   632  	spe := policydsl.SignedByMspMember("foo")
   633  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   634  	ms := &mockStateFetcher{FetchStateRv: mr}
   635  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   636  
   637  	cc, coll, key := "cc", "", "key"
   638  
   639  	resC := make(chan []byte, 1)
   640  	errC := make(chan error, 1)
   641  	runFunctions(t, seed,
   642  		func() {
   643  			pm.ExtractValidationParameterDependency(1, 0, []byte("barf"))
   644  		},
   645  		func() {
   646  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   647  		},
   648  		func() {
   649  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 1)
   650  			resC <- sp
   651  			errC <- err
   652  		})
   653  
   654  	sp := <-resC
   655  	err := <-errC
   656  	assert.NoError(t, err, "assert failure occurred with seed %d", seed)
   657  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp, "assert failure occurred with seed %d", seed)
   658  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   659  }
   660  
   661  func TestWritesIntoDifferentNamespaces(t *testing.T) {
   662  	t.Parallel()
   663  	seed := time.Now().Unix()
   664  
   665  	// Scenario: transaction (1,0) writes to namespace cc1.
   666  	// Transaction (1,1) attempts to retrieve validation
   667  	// parameters for cc. This does not constitute a dependency
   668  
   669  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   670  	spe := policydsl.SignedByMspMember("foo")
   671  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   672  	ms := &mockStateFetcher{FetchStateRv: mr}
   673  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   674  
   675  	cc, othercc, coll, key := "cc1", "cc", "", "key"
   676  
   677  	rwsetbytes := rwsetUpdatingMetadataFor(cc, key)
   678  
   679  	resC := make(chan []byte, 1)
   680  	errC := make(chan error, 1)
   681  	runFunctions(t, seed,
   682  		func() {
   683  			pm.SetTxValidationResult(cc, 1, 0, nil)
   684  		},
   685  		func() {
   686  			pm.ExtractValidationParameterDependency(1, 0, rwsetbytes)
   687  			sp, err := pm.GetValidationParameterForKey(othercc, coll, key, 1, 1)
   688  			resC <- sp
   689  			errC <- err
   690  		})
   691  
   692  	sp := <-resC
   693  	err := <-errC
   694  	assert.NoError(t, err, "assert failure occurred with seed %d", seed)
   695  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp, "assert failure occurred with seed %d", seed)
   696  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   697  }
   698  
   699  func TestCombinedCalls(t *testing.T) {
   700  	t.Parallel()
   701  	seed := time.Now().Unix()
   702  
   703  	// Scenario: transaction (1,3) requests validation parameters
   704  	// for different keys - one succeeds and one fails.
   705  
   706  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   707  	spe := policydsl.SignedByMspMember("foo")
   708  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   709  	ms := &mockStateFetcher{FetchStateRv: mr}
   710  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   711  
   712  	cc := "cc"
   713  	coll := ""
   714  	key1 := "key1"
   715  	key2 := "key2"
   716  
   717  	res1C := make(chan []byte, 1)
   718  	err1C := make(chan error, 1)
   719  	res2C := make(chan []byte, 1)
   720  	err2C := make(chan error, 1)
   721  	runFunctions(t, seed,
   722  		func() {
   723  			pm.ExtractValidationParameterDependency(1, 0, rwsetUpdatingMetadataFor(cc, key1))
   724  		},
   725  		func() {
   726  			pm.SetTxValidationResult(cc, 1, 0, errors.New(""))
   727  		},
   728  		func() {
   729  			pm.ExtractValidationParameterDependency(1, 1, rwsetUpdatingMetadataFor(cc, key2))
   730  		},
   731  		func() {
   732  			pm.SetTxValidationResult(cc, 1, 1, nil)
   733  		},
   734  		func() {
   735  			sp, err := pm.GetValidationParameterForKey(cc, coll, key1, 1, 2)
   736  			res1C <- sp
   737  			err1C <- err
   738  		},
   739  		func() {
   740  			sp, err := pm.GetValidationParameterForKey(cc, coll, key2, 1, 2)
   741  			res2C <- sp
   742  			err2C <- err
   743  		})
   744  
   745  	sp := <-res1C
   746  	err := <-err1C
   747  	assert.NoError(t, err, "assert failure occurred with seed %d", seed)
   748  	assert.Equal(t, protoutil.MarshalOrPanic(spe), sp, "assert failure occurred with seed %d", seed)
   749  
   750  	sp = <-res2C
   751  	err = <-err2C
   752  	assert.Errorf(t, err, "assert failure occurred with seed %d", seed)
   753  	assert.IsType(t, &ValidationParameterUpdatedError{}, err, "assert failure occurred with seed %d", seed)
   754  	assert.Nil(t, sp, "assert failure occurred with seed %d", seed)
   755  
   756  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   757  }
   758  
   759  func TestForRaces(t *testing.T) {
   760  	seed := time.Now().Unix()
   761  
   762  	// scenario to stress test the parallel validation
   763  	// this is an extended combined test
   764  	// run with go test -race
   765  
   766  	vpMetadataKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String()
   767  	spe := policydsl.SignedByMspMember("foo")
   768  	mr := &mockState{GetStateMetadataRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}, GetPrivateDataMetadataByHashRv: map[string][]byte{vpMetadataKey: protoutil.MarshalOrPanic(spe)}}
   769  	ms := &mockStateFetcher{FetchStateRv: mr}
   770  	pm := &KeyLevelValidationParameterManagerImpl{PolicyTranslator: &mockTranslator{}, StateFetcher: ms}
   771  
   772  	cc := "cc"
   773  	coll := ""
   774  
   775  	nRoutines := 1000
   776  	funcArray := make([]func(), nRoutines)
   777  	for i := 0; i < nRoutines; i++ {
   778  		txnum := i
   779  		funcArray[i] = func() {
   780  			key := strconv.Itoa(txnum)
   781  			pm.ExtractValidationParameterDependency(1, uint64(txnum), rwsetUpdatingMetadataFor(cc, key))
   782  
   783  			// we yield in an attempt to create a more varied scheduling pattern in the hope of unearthing races
   784  			runtime.Gosched()
   785  
   786  			pm.SetTxValidationResult(cc, 1, uint64(txnum), errors.New(""))
   787  
   788  			// we yield in an attempt to create a more varied scheduling pattern in the hope of unearthing races
   789  			runtime.Gosched()
   790  
   791  			sp, err := pm.GetValidationParameterForKey(cc, coll, key, 1, 2)
   792  			assert.Equal(t, protoutil.MarshalOrPanic(spe), sp)
   793  			assert.NoError(t, err)
   794  		}
   795  	}
   796  
   797  	runFunctions(t, seed, funcArray...)
   798  
   799  	assert.True(t, ms.DoneCalled(), "assert failure occurred with seed %d", seed)
   800  }