github.com/klaytn/klaytn@v1.10.2/consensus/istanbul/backend/handler_test.go (about)

     1  // Copyright 2020 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package backend
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  
    25  	lru "github.com/hashicorp/golang-lru"
    26  	"github.com/klaytn/klaytn/common"
    27  	"github.com/klaytn/klaytn/consensus/istanbul"
    28  	"github.com/klaytn/klaytn/networks/p2p"
    29  	"github.com/klaytn/klaytn/rlp"
    30  )
    31  
    32  func TestBackend_HandleMsg(t *testing.T) {
    33  	_, backend := newBlockChain(1)
    34  	defer backend.Stop()
    35  	eventSub := backend.istanbulEventMux.Subscribe(istanbul.MessageEvent{})
    36  
    37  	addr := common.StringToAddress("test addr")
    38  	data := &istanbul.ConsensusMsg{
    39  		PrevHash: common.HexToHash("0x1234"),
    40  		Payload:  []byte("test data"),
    41  	}
    42  	hash := istanbul.RLPHash(data.Payload)
    43  	size, payload, _ := rlp.EncodeToReader(data)
    44  
    45  	// Success case
    46  	{
    47  		msg := p2p.Msg{
    48  			Code:    IstanbulMsg,
    49  			Size:    uint32(size),
    50  			Payload: payload,
    51  		}
    52  		isHandled, err := backend.HandleMsg(addr, msg)
    53  		assert.Nil(t, err)
    54  		assert.True(t, isHandled)
    55  
    56  		if err != nil {
    57  			t.Fatalf("handle message failed: %v", err)
    58  		}
    59  
    60  		recentMsg, ok := backend.recentMessages.Get(addr)
    61  		assert.True(t, ok)
    62  
    63  		cachedMsg, ok := recentMsg.(*lru.ARCCache)
    64  		assert.True(t, ok)
    65  
    66  		value, ok := cachedMsg.Get(hash)
    67  		assert.True(t, ok)
    68  		assert.True(t, value.(bool))
    69  
    70  		value, ok = backend.knownMessages.Get(hash)
    71  		assert.True(t, ok)
    72  		assert.True(t, value.(bool))
    73  
    74  		evTimer := time.NewTimer(3 * time.Second)
    75  		defer evTimer.Stop()
    76  
    77  		select {
    78  		case event := <-eventSub.Chan():
    79  			switch ev := event.Data.(type) {
    80  			case istanbul.MessageEvent:
    81  				assert.Equal(t, data.Payload, ev.Payload)
    82  				assert.Equal(t, data.PrevHash, ev.Hash)
    83  			default:
    84  				t.Fatal("unexpected message type")
    85  			}
    86  		case <-evTimer.C:
    87  			t.Fatal("failed to subscribe istanbul message event")
    88  		}
    89  	}
    90  
    91  	// Failure case - undefined message code
    92  	{
    93  		msg := p2p.Msg{
    94  			Code:    0x99,
    95  			Size:    uint32(size),
    96  			Payload: payload,
    97  		}
    98  		isHandled, err := backend.HandleMsg(addr, msg)
    99  		assert.Equal(t, nil, err)
   100  		assert.False(t, isHandled)
   101  	}
   102  
   103  	// Failure case - invalid message data
   104  	{
   105  		size, payload, _ := rlp.EncodeToReader([]byte{0x1, 0x2})
   106  		msg := p2p.Msg{
   107  			Code:    IstanbulMsg,
   108  			Size:    uint32(size),
   109  			Payload: payload,
   110  		}
   111  		isHandled, err := backend.HandleMsg(addr, msg)
   112  		assert.Equal(t, errDecodeFailed, err)
   113  		assert.True(t, isHandled)
   114  	}
   115  
   116  	// Failure case - stopped istanbul engine
   117  	{
   118  		msg := p2p.Msg{
   119  			Code:    IstanbulMsg,
   120  			Size:    uint32(size),
   121  			Payload: payload,
   122  		}
   123  		_ = backend.Stop()
   124  		isHandled, err := backend.HandleMsg(addr, msg)
   125  		assert.Equal(t, istanbul.ErrStoppedEngine, err)
   126  		assert.True(t, isHandled)
   127  	}
   128  }
   129  
   130  func TestBackend_Protocol(t *testing.T) {
   131  	backend := newTestBackend()
   132  	assert.Equal(t, IstanbulProtocol, backend.Protocol())
   133  }
   134  
   135  func TestBackend_ValidatePeerType(t *testing.T) {
   136  	_, backend := newBlockChain(1)
   137  	defer backend.Stop()
   138  
   139  	// Return nil if the input address is a validator
   140  	{
   141  		err := backend.ValidatePeerType(backend.address)
   142  		assert.Nil(t, err)
   143  	}
   144  
   145  	// Return an error if the input address is invalid
   146  	{
   147  		err := backend.ValidatePeerType(common.Address{})
   148  		assert.Equal(t, errInvalidPeerAddress, err)
   149  	}
   150  
   151  	// Return an error if backend.chain is not set
   152  	{
   153  		backend.chain = nil
   154  		err := backend.ValidatePeerType(backend.address)
   155  		assert.Equal(t, errNoChainReader, err)
   156  	}
   157  }