github.com/evdatsion/aphelion-dpos-bft@v0.32.1/lite/provider_test.go (about)

     1  package lite
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	dbm "github.com/evdatsion/aphelion-dpos-bft/libs/db"
    11  	log "github.com/evdatsion/aphelion-dpos-bft/libs/log"
    12  	lerr "github.com/evdatsion/aphelion-dpos-bft/lite/errors"
    13  	"github.com/evdatsion/aphelion-dpos-bft/types"
    14  )
    15  
    16  // missingProvider doesn't store anything, always a miss.
    17  // Designed as a mock for testing.
    18  type missingProvider struct{}
    19  
    20  // NewMissingProvider returns a provider which does not store anything and always misses.
    21  func NewMissingProvider() PersistentProvider {
    22  	return missingProvider{}
    23  }
    24  
    25  func (missingProvider) SaveFullCommit(FullCommit) error { return nil }
    26  func (missingProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (FullCommit, error) {
    27  	return FullCommit{}, lerr.ErrCommitNotFound()
    28  }
    29  func (missingProvider) ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error) {
    30  	return nil, errors.New("missing validator set")
    31  }
    32  func (missingProvider) SetLogger(_ log.Logger) {}
    33  
    34  func TestMemProvider(t *testing.T) {
    35  	p := NewDBProvider("mem", dbm.NewMemDB())
    36  	checkProvider(t, p, "test-mem", "empty")
    37  }
    38  
    39  func TestMultiProvider(t *testing.T) {
    40  	p := NewMultiProvider(
    41  		NewMissingProvider(),
    42  		NewDBProvider("mem", dbm.NewMemDB()),
    43  		NewMissingProvider(),
    44  	)
    45  	checkProvider(t, p, "test-cache", "kjfhekfhkewhgit")
    46  }
    47  
    48  func checkProvider(t *testing.T, p PersistentProvider, chainID, app string) {
    49  	assert, require := assert.New(t), require.New(t)
    50  	appHash := []byte(app)
    51  	keys := genPrivKeys(5)
    52  	count := 10
    53  
    54  	// Make a bunch of full commits.
    55  	fcz := make([]FullCommit, count)
    56  	for i := 0; i < count; i++ {
    57  		vals := keys.ToValidators(10, int64(count/2))
    58  		h := int64(20 + 10*i)
    59  		fcz[i] = keys.GenFullCommit(chainID, h, nil, vals, vals, appHash, []byte("params"), []byte("results"), 0, 5)
    60  	}
    61  
    62  	// Check that provider is initially empty.
    63  	fc, err := p.LatestFullCommit(chainID, 1, 1<<63-1)
    64  	require.NotNil(err)
    65  	assert.True(lerr.IsErrCommitNotFound(err))
    66  
    67  	// Save all full commits to the provider.
    68  	for _, fc := range fcz {
    69  		err = p.SaveFullCommit(fc)
    70  		require.Nil(err)
    71  		// Make sure we can get it back.
    72  		fc2, err := p.LatestFullCommit(chainID, fc.Height(), fc.Height())
    73  		assert.Nil(err)
    74  		assert.Equal(fc.SignedHeader, fc2.SignedHeader)
    75  		assert.Equal(fc.Validators, fc2.Validators)
    76  		assert.Equal(fc.NextValidators, fc2.NextValidators)
    77  	}
    78  
    79  	// Make sure we get the last hash if we overstep.
    80  	fc, err = p.LatestFullCommit(chainID, 1, 5000)
    81  	if assert.Nil(err) {
    82  		assert.Equal(fcz[count-1].Height(), fc.Height())
    83  		assert.Equal(fcz[count-1], fc)
    84  	}
    85  
    86  	// ... and middle ones as well.
    87  	fc, err = p.LatestFullCommit(chainID, 1, 47)
    88  	if assert.Nil(err) {
    89  		// we only step by 10, so 40 must be the one below this
    90  		assert.EqualValues(40, fc.Height())
    91  	}
    92  
    93  }
    94  
    95  // This will make a get height, and if it is good, set the data as well.
    96  func checkLatestFullCommit(t *testing.T, p PersistentProvider, chainID string, ask, expect int64) {
    97  	fc, err := p.LatestFullCommit(chainID, 1, ask)
    98  	require.Nil(t, err)
    99  	if assert.Equal(t, expect, fc.Height()) {
   100  		err = p.SaveFullCommit(fc)
   101  		require.Nil(t, err)
   102  	}
   103  }
   104  
   105  func TestMultiLatestFullCommit(t *testing.T) {
   106  	require := require.New(t)
   107  
   108  	// We will write data to the second level of the cache (p2), and see what
   109  	// gets cached/stored in.
   110  	p := NewDBProvider("mem1", dbm.NewMemDB())
   111  	p2 := NewDBProvider("mem2", dbm.NewMemDB())
   112  	cp := NewMultiProvider(p, p2)
   113  
   114  	chainID := "cache-best-height"
   115  	appHash := []byte("01234567")
   116  	keys := genPrivKeys(5)
   117  	count := 10
   118  
   119  	// Set a bunch of full commits.
   120  	for i := 0; i < count; i++ {
   121  		vals := keys.ToValidators(10, int64(count/2))
   122  		h := int64(10 * (i + 1))
   123  		fc := keys.GenFullCommit(chainID, h, nil, vals, vals, appHash, []byte("params"), []byte("results"), 0, 5)
   124  		err := p2.SaveFullCommit(fc)
   125  		require.NoError(err)
   126  	}
   127  
   128  	// Get a few heights from the cache and set them proper.
   129  	checkLatestFullCommit(t, cp, chainID, 57, 50)
   130  	checkLatestFullCommit(t, cp, chainID, 33, 30)
   131  
   132  	// make sure they are set in p as well (but nothing else)
   133  	checkLatestFullCommit(t, p, chainID, 44, 30)
   134  	checkLatestFullCommit(t, p, chainID, 50, 50)
   135  	checkLatestFullCommit(t, p, chainID, 99, 50)
   136  
   137  	// now, query the cache for a higher value
   138  	checkLatestFullCommit(t, p2, chainID, 99, 90)
   139  	checkLatestFullCommit(t, cp, chainID, 99, 90)
   140  }