github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/gossip/comm/mock/mock_comm.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mock
    18  
    19  import (
    20  	"github.com/inklabsfoundation/inkchain/gossip/api"
    21  	"github.com/inklabsfoundation/inkchain/gossip/comm"
    22  	"github.com/inklabsfoundation/inkchain/gossip/common"
    23  	"github.com/inklabsfoundation/inkchain/gossip/util"
    24  	proto "github.com/inklabsfoundation/inkchain/protos/gossip"
    25  )
    26  
    27  // Mock which aims to simulate socket
    28  type socketMock struct {
    29  	// socket endpoint
    30  	endpoint string
    31  
    32  	// To simulate simple tcp socket
    33  	socket chan interface{}
    34  }
    35  
    36  // Mock of primitive tcp packet structure
    37  type packetMock struct {
    38  	// Sender channel message sent from
    39  	src *socketMock
    40  
    41  	// Destination channel sent to
    42  	dst *socketMock
    43  
    44  	msg interface{}
    45  }
    46  
    47  type channelMock struct {
    48  	accept common.MessageAcceptor
    49  
    50  	channel chan proto.ReceivedMessage
    51  }
    52  
    53  type commMock struct {
    54  	id string
    55  
    56  	members map[string]*socketMock
    57  
    58  	acceptors []*channelMock
    59  
    60  	deadChannel chan common.PKIidType
    61  
    62  	done chan struct{}
    63  }
    64  
    65  var logger = util.GetLogger(util.LoggingMockModule, "")
    66  
    67  // NewCommMock creates mocked communication object
    68  func NewCommMock(id string, members map[string]*socketMock) comm.Comm {
    69  	res := &commMock{
    70  		id: id,
    71  
    72  		members: members,
    73  
    74  		acceptors: make([]*channelMock, 0),
    75  
    76  		done: make(chan struct{}),
    77  
    78  		deadChannel: make(chan common.PKIidType),
    79  	}
    80  	// Start communication service
    81  	go res.start()
    82  
    83  	return res
    84  }
    85  
    86  // Respond sends a GossipMessage to the origin from which this ReceivedMessage was sent from
    87  func (packet *packetMock) Respond(msg *proto.GossipMessage) {
    88  	sMsg, _ := msg.NoopSign()
    89  	packet.src.socket <- &packetMock{
    90  		src: packet.dst,
    91  		dst: packet.src,
    92  		msg: sMsg,
    93  	}
    94  }
    95  
    96  // GetSourceEnvelope Returns the Envelope the ReceivedMessage was
    97  // constructed with
    98  func (packet *packetMock) GetSourceEnvelope() *proto.Envelope {
    99  	return nil
   100  }
   101  
   102  // GetGossipMessage returns the underlying GossipMessage
   103  func (packet *packetMock) GetGossipMessage() *proto.SignedGossipMessage {
   104  	return packet.msg.(*proto.SignedGossipMessage)
   105  }
   106  
   107  // GetConnectionInfo returns information about the remote peer
   108  // that sent the message
   109  func (packet *packetMock) GetConnectionInfo() *proto.ConnectionInfo {
   110  	return nil
   111  }
   112  
   113  func (mock *commMock) start() {
   114  	logger.Debug("Starting communication mock module...")
   115  	for {
   116  		select {
   117  		case <-mock.done:
   118  			{
   119  				// Got final signal, exiting...
   120  				logger.Debug("Exiting...")
   121  				return
   122  			}
   123  		case msg := <-mock.members[mock.id].socket:
   124  			{
   125  				logger.Debug("Got new message", msg)
   126  				packet := msg.(*packetMock)
   127  				for _, channel := range mock.acceptors {
   128  					// if message acceptor agrees to get
   129  					// new message forward it to the received
   130  					// messages channel
   131  					if channel.accept(packet) {
   132  						channel.channel <- packet
   133  					}
   134  				}
   135  			}
   136  		}
   137  	}
   138  }
   139  
   140  // GetPKIid returns this instance's PKI id
   141  func (mock *commMock) GetPKIid() common.PKIidType {
   142  	return common.PKIidType(mock.id)
   143  }
   144  
   145  // Send sends a message to remote peers
   146  func (mock *commMock) Send(msg *proto.SignedGossipMessage, peers ...*comm.RemotePeer) {
   147  	for _, peer := range peers {
   148  		logger.Debug("Sending message to peer ", peer.Endpoint, "from ", mock.id)
   149  		mock.members[peer.Endpoint].socket <- &packetMock{
   150  			src: mock.members[mock.id],
   151  			dst: mock.members[peer.Endpoint],
   152  			msg: msg,
   153  		}
   154  	}
   155  }
   156  
   157  // Probe probes a remote node and returns nil if its responsive,
   158  // and an error if it's not.
   159  func (mock *commMock) Probe(peer *comm.RemotePeer) error {
   160  	return nil
   161  }
   162  
   163  // Handshake authenticates a remote peer and returns
   164  // (its identity, nil) on success and (nil, error)
   165  func (mock *commMock) Handshake(peer *comm.RemotePeer) (api.PeerIdentityType, error) {
   166  	return nil, nil
   167  }
   168  
   169  // Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate.
   170  // Each message from the channel can be used to send a reply back to the sender
   171  func (mock *commMock) Accept(accept common.MessageAcceptor) <-chan proto.ReceivedMessage {
   172  	ch := make(chan proto.ReceivedMessage)
   173  	mock.acceptors = append(mock.acceptors, &channelMock{accept, ch})
   174  	return ch
   175  }
   176  
   177  // PresumedDead returns a read-only channel for node endpoints that are suspected to be offline
   178  func (mock *commMock) PresumedDead() <-chan common.PKIidType {
   179  	return mock.deadChannel
   180  }
   181  
   182  // CloseConn closes a connection to a certain endpoint
   183  func (mock *commMock) CloseConn(peer *comm.RemotePeer) {
   184  	// NOOP
   185  }
   186  
   187  // Stop stops the module
   188  func (mock *commMock) Stop() {
   189  	logger.Debug("Stopping communication module, closing all accepting channels.")
   190  	for _, accept := range mock.acceptors {
   191  		close(accept.channel)
   192  	}
   193  	logger.Debug("[XXX]: Sending done signal to close the module.")
   194  	mock.done <- struct{}{}
   195  }