aboutsummaryrefslogblamecommitdiffstats
path: root/dex/cache_test.go
blob: 536e015f0c3935cd46ca013c0acaeced15baed86 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                    
  
                                                                        



                                                                               
                                                                         




                                                                           
                                                      




                                  
                   

                 

                 
                                                                       
                                                                    
                                                                          

 













                                                                                    
                                  
                                          



                                






                                   



                                                              

                                 



                                                              

                                 



                                                              

                                 



                                                              





                                  




                                                      


                                                                          

                                                                                      
         

                                                                                      

                                 
                                









                                                                             

                                



                                                                          




                                                     


                                                                          

                                                                                      
         

                                                                                      



                                   
                                          



                                

















                                                                                       


                                





























                                                                                     



                                                 
                                                    









                                                                                        
 
























































































                                                                                                       
// Copyright 2018 The dexon-consensus Authors
// This file is part of the dexon-consensus library.
//
// The dexon-consensus library is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// The dexon-consensus library is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
// General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.

package dex

import (
    "math/rand"
    "sort"
    "strings"
    "testing"

    coreCommon "github.com/dexon-foundation/dexon-consensus/common"
    coreDb "github.com/dexon-foundation/dexon-consensus/core/db"
    coreTypes "github.com/dexon-foundation/dexon-consensus/core/types"
)

type byHash []*coreTypes.Vote

func (v byHash) Len() int {
    return len(v)
}

func (v byHash) Less(i int, j int) bool {
    return strings.Compare(v[i].BlockHash.String(), v[j].BlockHash.String()) < 0
}

func (v byHash) Swap(i int, j int) {
    v[i], v[j] = v[j], v[i]
}

func TestCacheVote(t *testing.T) {
    db, err := coreDb.NewMemBackedDB()
    if err != nil {
        panic(err)
    }
    cache := newCache(3, db)
    pos0 := coreTypes.Position{
        Height: uint64(0),
    }
    pos1 := coreTypes.Position{
        Height: uint64(1),
    }
    vote1 := &coreTypes.Vote{
        VoteHeader: coreTypes.VoteHeader{
            BlockHash: coreCommon.NewRandomHash(),
            Position:  pos0,
        },
    }
    vote2 := &coreTypes.Vote{
        VoteHeader: coreTypes.VoteHeader{
            BlockHash: coreCommon.NewRandomHash(),
            Position:  pos0,
        },
    }
    vote3 := &coreTypes.Vote{
        VoteHeader: coreTypes.VoteHeader{
            BlockHash: coreCommon.NewRandomHash(),
            Position:  pos1,
        },
    }
    vote4 := &coreTypes.Vote{
        VoteHeader: coreTypes.VoteHeader{
            BlockHash: coreCommon.NewRandomHash(),
            Position:  pos1,
        },
    }
    cache.addVote(vote1)
    cache.addVote(vote2)
    cache.addVote(vote3)

    votes := cache.votes(pos0)
    sort.Sort(byHash(votes))

    resultVotes := []*coreTypes.Vote{vote1, vote2}
    sort.Sort(byHash(resultVotes))

    if len(votes) != 2 {
        t.Errorf("fail to get votes: have %d, want 2", len(votes))
    }
    if !votes[0].BlockHash.Equal(resultVotes[0].BlockHash) {
        t.Errorf("get wrong vote: have %s, want %s", votes[0], resultVotes[0])
    }
    if !votes[1].BlockHash.Equal(resultVotes[1].BlockHash) {
        t.Errorf("get wrong vote: have %s, want %s", votes[1], resultVotes[1])
    }
    votes = cache.votes(pos1)
    sort.Sort(byHash(votes))
    if len(votes) != 1 {
        t.Errorf("fail to get votes: have %d, want 1", len(votes))
    }
    if !votes[0].BlockHash.Equal(vote3.BlockHash) {
        t.Errorf("get wrong vote: have %s, want %s", votes[0], vote3)
    }

    cache.addVote(vote4)

    votes = cache.votes(pos0)
    sort.Sort(byHash(votes))

    if len(votes) != 0 {
        t.Errorf("fail to get votes: have %d, want 0", len(votes))
    }
    votes = cache.votes(pos1)
    sort.Sort(byHash(votes))

    resultVotes = []*coreTypes.Vote{vote3, vote4}
    sort.Sort(byHash(resultVotes))

    if len(votes) != 2 {
        t.Errorf("fail to get votes: have %d, want 1", len(votes))
    }
    if !votes[0].BlockHash.Equal(resultVotes[0].BlockHash) {
        t.Errorf("get wrong vote: have %s, want %s", votes[0], resultVotes[0])
    }
    if !votes[1].BlockHash.Equal(resultVotes[1].BlockHash) {
        t.Errorf("get wrong vote: have %s, want %s", votes[1], resultVotes[1])
    }
}

func TestCacheBlock(t *testing.T) {
    db, err := coreDb.NewMemBackedDB()
    if err != nil {
        panic(err)
    }
    cache := newCache(3, db)
    block1 := &coreTypes.Block{
        Hash: coreCommon.NewRandomHash(),
    }
    block2 := &coreTypes.Block{
        Hash: coreCommon.NewRandomHash(),
    }
    block3 := &coreTypes.Block{
        Hash: coreCommon.NewRandomHash(),
    }
    block4 := &coreTypes.Block{
        Hash: coreCommon.NewRandomHash(),
    }
    cache.addBlock(block1)
    cache.addBlock(block2)
    cache.addBlock(block3)

    hashes := coreCommon.Hashes{block1.Hash, block2.Hash, block3.Hash, block4.Hash}
    hashMap := map[coreCommon.Hash]struct{}{
        block1.Hash: {},
        block2.Hash: {},
        block3.Hash: {},
    }
    blocks := cache.blocks(hashes)
    if len(blocks) != 3 {
        t.Errorf("fail to get blocks: have %d, want 3", len(blocks))
    }
    for _, block := range blocks {
        if _, exist := hashMap[block.Hash]; !exist {
            t.Errorf("get wrong block: have %s, want %v", block, hashMap)
        }
    }

    cache.addBlock(block4)

    blocks = cache.blocks(hashes)
    hashMap[block4.Hash] = struct{}{}
    if len(blocks) != 3 {
        t.Errorf("fail to get blocks: have %d, want 3", len(blocks))
    }
    hasNewBlock := false
    for _, block := range blocks {
        if _, exist := hashMap[block.Hash]; !exist {
            t.Errorf("get wrong block: have %s, want %v", block, hashMap)
        }
        if block.Hash.Equal(block4.Hash) {
            hasNewBlock = true
        }
    }
    if !hasNewBlock {
        t.Errorf("expect block %s in cache, have %v", block4, blocks)
    }

    block5 := &coreTypes.Block{
        Hash: coreCommon.NewRandomHash(),
    }
    if err := db.PutBlock(*block5); err != nil {
        panic(err)
    }
    blocks = cache.blocks(coreCommon.Hashes{block5.Hash})
    if len(blocks) != 1 {
        t.Errorf("fail to get blocks: have %d, want 1", len(blocks))
    } else {
        if !blocks[0].Hash.Equal(block5.Hash) {
            t.Errorf("get wrong block: have %s, want %s", blocks[0], block5)
        }
    }
}

func randomBytes() []byte {
    bytes := make([]byte, 32)
    for i := range bytes {
        bytes[i] = byte(rand.Int() % 256)
    }
    return bytes
}

func TestCacheRandomness(t *testing.T) {
    db, err := coreDb.NewMemBackedDB()
    if err != nil {
        panic(err)
    }
    cache := newCache(3, db)
    rand1 := &coreTypes.BlockRandomnessResult{
        BlockHash:  coreCommon.NewRandomHash(),
        Randomness: randomBytes(),
    }
    rand2 := &coreTypes.BlockRandomnessResult{
        BlockHash:  coreCommon.NewRandomHash(),
        Randomness: randomBytes(),
    }
    rand3 := &coreTypes.BlockRandomnessResult{
        BlockHash:  coreCommon.NewRandomHash(),
        Randomness: randomBytes(),
    }
    rand4 := &coreTypes.BlockRandomnessResult{
        BlockHash:  coreCommon.NewRandomHash(),
        Randomness: randomBytes(),
    }
    cache.addRandomness(rand1)
    cache.addRandomness(rand2)
    cache.addRandomness(rand3)

    hashes := coreCommon.Hashes{rand1.BlockHash, rand2.BlockHash, rand3.BlockHash, rand4.BlockHash}
    hashMap := map[coreCommon.Hash]struct{}{
        rand1.BlockHash: {},
        rand2.BlockHash: {},
        rand3.BlockHash: {},
    }
    rands := cache.randomness(hashes)
    if len(rands) != 3 {
        t.Errorf("fail to get rands: have %d, want 3", len(rands))
    }
    for _, rand := range rands {
        if _, exist := hashMap[rand.BlockHash]; !exist {
            t.Errorf("get wrong rand: have %s, want %v", rand, hashMap)
        }
    }

    cache.addRandomness(rand4)

    rands = cache.randomness(hashes)
    hashMap[rand4.BlockHash] = struct{}{}
    if len(rands) != 3 {
        t.Errorf("fail to get rands: have %d, want 3", len(rands))
    }
    hasNewRandomness := false
    for _, rand := range rands {
        if _, exist := hashMap[rand.BlockHash]; !exist {
            t.Errorf("get wrong rand: have %s, want %v", rand, hashMap)
        }
        if rand.BlockHash.Equal(rand4.BlockHash) {
            hasNewRandomness = true
        }
    }
    if !hasNewRandomness {
        t.Errorf("expect rand %s in cache, have %v", rand4, rands)
    }

    block := &coreTypes.Block{
        Hash: coreCommon.NewRandomHash(),
        Finalization: coreTypes.FinalizationResult{
            Randomness: randomBytes(),
        },
    }
    if err := db.PutBlock(*block); err != nil {
        panic(err)
    }
    rands = cache.randomness(coreCommon.Hashes{block.Hash})
    if len(rands) != 1 {
        t.Errorf("fail to get rands: have %d, want 1", len(rands))
    } else {
        if !rands[0].BlockHash.Equal(block.Hash) {
            t.Errorf("get wrong rand: have %s, want %s", rands[0], block)
        }
    }
}