github.com/iotexproject/iotex-core@v1.14.1-rc1/consensus/scheme/rolldpos/endorsementmanager_test.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package rolldpos
     7  
     8  import (
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/golang/mock/gomock"
    13  	"github.com/iotexproject/iotex-core/blockchain/block"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/iotexproject/iotex-core/endorsement"
    17  	"github.com/iotexproject/iotex-core/pkg/log"
    18  	"github.com/iotexproject/iotex-core/test/identityset"
    19  )
    20  
    21  func TestEndorserEndorsementCollection(t *testing.T) {
    22  	require := require.New(t)
    23  	ctrl := gomock.NewController(t)
    24  	defer ctrl.Finish()
    25  	now := time.Now()
    26  	priKey := identityset.PrivateKey(0)
    27  	mockProposal := endorsement.NewEndorsement(
    28  		now.Add(-2*time.Second),
    29  		priKey.PublicKey(),
    30  		[]byte{},
    31  	)
    32  	mockLock := endorsement.NewEndorsement(
    33  		now.Add(-2*time.Second),
    34  		priKey.PublicKey(),
    35  		[]byte{},
    36  	)
    37  	mockCommit := endorsement.NewEndorsement(
    38  		now.Add(-2*time.Second),
    39  		priKey.PublicKey(),
    40  		[]byte{},
    41  	)
    42  	eec := newEndorserEndorsementCollection()
    43  	require.NoError(eec.AddEndorsement(PROPOSAL, mockProposal))
    44  	require.NoError(eec.AddEndorsement(LOCK, mockLock))
    45  	require.NoError(eec.AddEndorsement(COMMIT, mockCommit))
    46  	t.Run("read", func(t *testing.T) {
    47  		require.Equal(mockProposal, eec.Endorsement(PROPOSAL))
    48  		require.Equal(mockLock, eec.Endorsement(LOCK))
    49  		require.Equal(mockCommit, eec.Endorsement(COMMIT))
    50  	})
    51  	t.Run("cleanup", func(t *testing.T) {
    52  		cleaned := eec.Cleanup(now)
    53  		require.Nil(cleaned.Endorsement(PROPOSAL))
    54  		require.Nil(cleaned.Endorsement(LOCK))
    55  		require.NotNil(cleaned.Endorsement(COMMIT))
    56  	})
    57  	t.Run("failure-to-replace", func(t *testing.T) {
    58  		mockProposal2 := endorsement.NewEndorsement(
    59  			now.Add(-3*time.Second),
    60  			priKey.PublicKey(),
    61  			[]byte{},
    62  		)
    63  		require.Error(eec.AddEndorsement(PROPOSAL, mockProposal2))
    64  	})
    65  	t.Run("success-to-replace", func(t *testing.T) {
    66  		mockProposal2 := endorsement.NewEndorsement(
    67  			now.Add(-2*time.Second),
    68  			priKey.PublicKey(),
    69  			[]byte{},
    70  		)
    71  		require.NoError(eec.AddEndorsement(PROPOSAL, mockProposal2))
    72  	})
    73  }
    74  
    75  func TestBlockEndorsementCollection(t *testing.T) {
    76  	require := require.New(t)
    77  	b := getBlock(t)
    78  	ec := newBlockEndorsementCollection(&b)
    79  	require.NotNil(ec)
    80  	require.NoError(ec.SetBlock(&b))
    81  	require.Equal(&b, ec.Block())
    82  	end := endorsement.NewEndorsement(time.Now(), b.PublicKey(), []byte("123"))
    83  
    84  	require.NoError(ec.AddEndorsement(PROPOSAL, end))
    85  	require.Equal(end, ec.Endorsement(b.PublicKey().HexString(), PROPOSAL))
    86  	ends := ec.Endorsements([]ConsensusVoteTopic{PROPOSAL})
    87  	require.Equal(1, len(ends))
    88  	require.Equal(end, ends[0])
    89  
    90  	ec = ec.Cleanup(time.Now().Add(time.Second * 10 * -1))
    91  	require.Equal(1, len(ec.endorsers))
    92  	require.Equal(1, len(ec.endorsers[b.PublicKey().HexString()].endorsements))
    93  	require.Equal(end, ec.endorsers[b.PublicKey().HexString()].Endorsement(PROPOSAL))
    94  }
    95  
    96  func TestEndorsementManager(t *testing.T) {
    97  	require := require.New(t)
    98  
    99  	em, err := newEndorsementManager(nil, block.NewDeserializer(0))
   100  	require.NoError(err)
   101  	require.NotNil(em)
   102  	require.Equal(0, em.Size())
   103  	require.Equal(0, em.SizeWithBlock())
   104  
   105  	b := getBlock(t)
   106  
   107  	require.NoError(em.RegisterBlock(&b))
   108  
   109  	require.Panics(func() {
   110  		em.AddVoteEndorsement(nil, nil)
   111  	}, "vote is nil")
   112  	blkHash := b.HashBlock()
   113  	cv := NewConsensusVote(blkHash[:], PROPOSAL)
   114  	require.NotNil(cv)
   115  
   116  	require.Panics(func() {
   117  		em.AddVoteEndorsement(cv, nil)
   118  	}, "endorsement is nil")
   119  
   120  	timestamp := time.Now()
   121  	end := endorsement.NewEndorsement(timestamp, b.PublicKey(), []byte("123"))
   122  	require.NoError(em.AddVoteEndorsement(cv, end))
   123  
   124  	require.Panics(func() {
   125  		em.Log(nil, nil)
   126  	}, "logger is nil")
   127  	l := em.Log(log.L(), nil)
   128  	require.NotNil(l)
   129  	l.Info("test output")
   130  
   131  	cv2 := NewConsensusVote(blkHash[:], LOCK)
   132  	require.NotNil(cv2)
   133  	end2 := endorsement.NewEndorsement(timestamp.Add(time.Second*10), b.PublicKey(), []byte("456"))
   134  	require.NoError(em.AddVoteEndorsement(cv2, end2))
   135  	l.Info("test output2")
   136  
   137  	encoded := encodeToString(cv.BlockHash())
   138  	require.Equal(1, len(em.collections[encoded].endorsers))
   139  	collection := em.collections[encoded].endorsers[end.Endorser().HexString()]
   140  	require.Equal(2, len(collection.endorsements))
   141  	require.Equal(end, collection.endorsements[PROPOSAL])
   142  	require.Equal(end2, collection.endorsements[LOCK])
   143  
   144  	//cleanup
   145  	require.NoError(em.Cleanup(timestamp.Add(time.Second * 2)))
   146  	require.NotNil(em)
   147  	require.Equal(1, len(em.collections))
   148  	require.Equal(1, len(em.collections[encoded].endorsers))
   149  
   150  	collection = em.collections[encoded].endorsers[end.Endorser().HexString()] //ee
   151  	require.Equal(1, len(collection.endorsements))
   152  	require.Equal(end2, collection.endorsements[LOCK])
   153  
   154  	//when the time is zero, it should generate empty eManager
   155  	zerotime := time.Time{}
   156  	require.Equal(zerotime.IsZero(), true)
   157  	require.NoError(em.Cleanup(zerotime))
   158  	require.Equal(0, len(em.collections))
   159  
   160  	// test for cachedMintedBlock
   161  	require.NoError(em.SetMintedBlock(&b))
   162  	require.Equal(&b, em.CachedMintedBlock())
   163  
   164  	blkTimestamp := b.Timestamp()
   165  	require.NoError(em.Cleanup(blkTimestamp)) // if roundStartTime is same or ealier than blockTimestamp
   166  	require.NotNil(em)
   167  	require.NotNil(em.CachedMintedBlock()) // not clean up
   168  	require.Equal(&b, em.CachedMintedBlock())
   169  
   170  	require.NoError(em.Cleanup(blkTimestamp.Add(time.Second * 2))) // if roundStartTime is after than blockTimestamp (old block)
   171  	require.Nil(em.CachedMintedBlock())                            // clean up
   172  
   173  	require.NoError(em.SetMintedBlock(&b))
   174  	require.Equal(&b, em.CachedMintedBlock())
   175  
   176  	require.NoError(em.Cleanup(zerotime)) // if it is clean up with zero time
   177  	require.Nil(em.CachedMintedBlock())   // clean up
   178  }
   179  
   180  func TestEndorsementManagerProto(t *testing.T) {
   181  	require := require.New(t)
   182  	em, err := newEndorsementManager(nil, block.NewDeserializer(0))
   183  	require.NoError(err)
   184  	require.NotNil(em)
   185  
   186  	b := getBlock(t)
   187  
   188  	require.NoError(em.RegisterBlock(&b))
   189  	blkHash := b.HashBlock()
   190  	cv := NewConsensusVote(blkHash[:], PROPOSAL)
   191  	require.NotNil(cv)
   192  	end := endorsement.NewEndorsement(time.Now(), b.PublicKey(), []byte("123"))
   193  	require.NoError(em.AddVoteEndorsement(cv, end))
   194  	require.Nil(em.cachedMintedBlk)
   195  	require.NoError(em.SetMintedBlock(&b))
   196  
   197  	//test converting endorsement pb
   198  	endProto, err := end.Proto()
   199  	require.NoError(err)
   200  	end2 := &endorsement.Endorsement{}
   201  	require.NoError(end2.LoadProto(endProto))
   202  	require.Equal(end, end2)
   203  
   204  	//test converting emanager pb
   205  	emProto, err := em.toProto()
   206  	require.NoError(err)
   207  	em2, err := newEndorsementManager(nil, block.NewDeserializer(0))
   208  	require.NoError(err)
   209  	require.NoError(em2.fromProto(emProto, block.NewDeserializer(0)))
   210  
   211  	require.Equal(len(em.collections), len(em2.collections))
   212  	encoded := encodeToString(cv.BlockHash())
   213  	require.Equal(em.collections[encoded].endorsers, em2.collections[encoded].endorsers)
   214  	require.Equal(em.cachedMintedBlk.HashBlock(), em2.cachedMintedBlk.HashBlock())
   215  }