github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/comm/comm_test.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 comm
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/hmac"
    22  	"crypto/sha256"
    23  	"crypto/tls"
    24  	"fmt"
    25  	"math/rand"
    26  	"net"
    27  	"os"
    28  	"strings"
    29  	"sync"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/hyperledger/fabric/bccsp/factory"
    34  	"github.com/hyperledger/fabric/core/config"
    35  	"github.com/hyperledger/fabric/gossip/api"
    36  	"github.com/hyperledger/fabric/gossip/common"
    37  	"github.com/hyperledger/fabric/gossip/identity"
    38  	"github.com/hyperledger/fabric/gossip/util"
    39  	proto "github.com/hyperledger/fabric/protos/gossip"
    40  	"github.com/spf13/viper"
    41  	"github.com/stretchr/testify/assert"
    42  	"golang.org/x/net/context"
    43  	"google.golang.org/grpc"
    44  	"google.golang.org/grpc/credentials"
    45  )
    46  
    47  func init() {
    48  	util.SetupTestLogging()
    49  	rand.Seed(time.Now().UnixNano())
    50  	factory.InitFactories(nil)
    51  }
    52  
    53  func acceptAll(msg interface{}) bool {
    54  	return true
    55  }
    56  
    57  var (
    58  	naiveSec = &naiveSecProvider{}
    59  	hmacKey  = []byte{0, 0, 0}
    60  )
    61  
    62  type naiveSecProvider struct {
    63  }
    64  
    65  func (*naiveSecProvider) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
    66  	return nil
    67  }
    68  
    69  // GetPKIidOfCert returns the PKI-ID of a peer's identity
    70  func (*naiveSecProvider) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
    71  	return common.PKIidType(peerIdentity)
    72  }
    73  
    74  // VerifyBlock returns nil if the block is properly signed,
    75  // else returns error
    76  func (*naiveSecProvider) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
    77  	return nil
    78  }
    79  
    80  // Sign signs msg with this peer's signing key and outputs
    81  // the signature if no error occurred.
    82  func (*naiveSecProvider) Sign(msg []byte) ([]byte, error) {
    83  	mac := hmac.New(sha256.New, hmacKey)
    84  	mac.Write(msg)
    85  	return mac.Sum(nil), nil
    86  }
    87  
    88  // Verify checks that signature is a valid signature of message under a peer's verification key.
    89  // If the verification succeeded, Verify returns nil meaning no error occurred.
    90  // If peerCert is nil, then the signature is verified against this peer's verification key.
    91  func (*naiveSecProvider) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
    92  	mac := hmac.New(sha256.New, hmacKey)
    93  	mac.Write(message)
    94  	expected := mac.Sum(nil)
    95  	if !bytes.Equal(signature, expected) {
    96  		return fmt.Errorf("Wrong certificate:%v, %v", signature, message)
    97  	}
    98  	return nil
    99  }
   100  
   101  // VerifyByChannel verifies a peer's signature on a message in the context
   102  // of a specific channel
   103  func (*naiveSecProvider) VerifyByChannel(_ common.ChainID, _ api.PeerIdentityType, _, _ []byte) error {
   104  	return nil
   105  }
   106  
   107  func newCommInstance(port int, sec api.MessageCryptoService) (Comm, error) {
   108  	endpoint := fmt.Sprintf("localhost:%d", port)
   109  	id := []byte(endpoint)
   110  	inst, err := NewCommInstanceWithServer(port, identity.NewIdentityMapper(sec, id), id, nil)
   111  	return inst, err
   112  }
   113  
   114  type msgMutator func(*proto.SignedGossipMessage) *proto.SignedGossipMessage
   115  
   116  type tlsType int
   117  
   118  const (
   119  	none tlsType = iota
   120  	oneWayTLS
   121  	mutualTLS
   122  )
   123  
   124  func handshaker(endpoint string, comm Comm, t *testing.T, connMutator msgMutator, connType tlsType) <-chan proto.ReceivedMessage {
   125  	c := &commImpl{}
   126  	cert := GenerateCertificatesOrPanic()
   127  	tlsCfg := &tls.Config{
   128  		InsecureSkipVerify: true,
   129  	}
   130  	if connType == mutualTLS {
   131  		tlsCfg.Certificates = []tls.Certificate{cert}
   132  	}
   133  	ta := credentials.NewTLS(tlsCfg)
   134  	secureOpts := grpc.WithTransportCredentials(ta)
   135  	if connType == none {
   136  		secureOpts = grpc.WithInsecure()
   137  	}
   138  	acceptChan := comm.Accept(acceptAll)
   139  	conn, err := grpc.Dial("localhost:9611", secureOpts, grpc.WithBlock(), grpc.WithTimeout(time.Second))
   140  	assert.NoError(t, err, "%v", err)
   141  	if err != nil {
   142  		return nil
   143  	}
   144  	cl := proto.NewGossipClient(conn)
   145  	stream, err := cl.GossipStream(context.Background())
   146  	assert.NoError(t, err, "%v", err)
   147  	if err != nil {
   148  		return nil
   149  	}
   150  
   151  	var clientCertHash []byte
   152  	if len(tlsCfg.Certificates) > 0 {
   153  		clientCertHash = certHashFromRawCert(tlsCfg.Certificates[0].Certificate[0])
   154  	}
   155  
   156  	pkiID := common.PKIidType(endpoint)
   157  	assert.NoError(t, err, "%v", err)
   158  	msg, _ := c.createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) {
   159  		mac := hmac.New(sha256.New, hmacKey)
   160  		mac.Write(msg)
   161  		return mac.Sum(nil), nil
   162  	})
   163  	// Mutate connection message to test negative paths
   164  	msg = connMutator(msg)
   165  	// Send your own connection message
   166  	stream.Send(msg.Envelope)
   167  	// Wait for connection message from the other side
   168  	envelope, err := stream.Recv()
   169  	if err != nil {
   170  		return acceptChan
   171  	}
   172  	assert.NoError(t, err, "%v", err)
   173  	msg, err = envelope.ToGossipMessage()
   174  	assert.NoError(t, err, "%v", err)
   175  	assert.Equal(t, []byte("localhost:9611"), msg.GetConn().PkiId)
   176  	assert.Equal(t, extractCertificateHashFromContext(stream.Context()), msg.GetConn().TlsCertHash)
   177  	msg2Send := createGossipMsg()
   178  	nonce := uint64(rand.Int())
   179  	msg2Send.Nonce = nonce
   180  	go stream.Send(msg2Send.Envelope)
   181  	return acceptChan
   182  }
   183  
   184  func TestViperConfig(t *testing.T) {
   185  	viper.SetConfigName("core")
   186  	viper.SetEnvPrefix("CORE")
   187  	config.AddDevConfigPath(nil)
   188  	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
   189  	viper.AutomaticEnv()
   190  	err := viper.ReadInConfig()
   191  	if err != nil { // Handle errors reading the config file
   192  		panic(fmt.Errorf("fatal error config file: %s", err))
   193  	}
   194  
   195  	assert.Equal(t, time.Duration(2)*time.Second, util.GetDurationOrDefault("peer.gossip.connTimeout", 0))
   196  	assert.Equal(t, time.Duration(300)*time.Millisecond, util.GetDurationOrDefault("peer.gossip.dialTimeout", 0))
   197  	assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.recvBuffSize", 0))
   198  	assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.sendBuffSize", 0))
   199  }
   200  
   201  func TestHandshake(t *testing.T) {
   202  	t.Parallel()
   203  	signer := func(msg []byte) ([]byte, error) {
   204  		mac := hmac.New(sha256.New, hmacKey)
   205  		mac.Write(msg)
   206  		return mac.Sum(nil), nil
   207  	}
   208  	mutator := func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   209  		return msg
   210  	}
   211  	assertPositivePath := func(msg proto.ReceivedMessage, endpoint string) {
   212  		expectedPKIID := common.PKIidType(endpoint)
   213  		assert.Equal(t, expectedPKIID, msg.GetConnectionInfo().ID)
   214  		assert.Equal(t, api.PeerIdentityType(endpoint), msg.GetConnectionInfo().Identity)
   215  		assert.NotNil(t, msg.GetConnectionInfo().Auth)
   216  		assert.True(t, msg.GetConnectionInfo().IsAuthenticated())
   217  		sig, _ := (&naiveSecProvider{}).Sign(msg.GetConnectionInfo().Auth.SignedData)
   218  		assert.Equal(t, sig, msg.GetConnectionInfo().Auth.Signature)
   219  	}
   220  
   221  	// Positive path 1 - check authentication without TLS
   222  	ll, err := net.Listen("tcp", fmt.Sprintf("%s:%d", "", 9611))
   223  	assert.NoError(t, err)
   224  	s := grpc.NewServer()
   225  	go s.Serve(ll)
   226  
   227  	id := []byte("localhost:9611")
   228  	idMapper := identity.NewIdentityMapper(naiveSec, id)
   229  	inst, err := NewCommInstance(s, nil, idMapper, api.PeerIdentityType("localhost:9611"), func() []grpc.DialOption {
   230  		return []grpc.DialOption{grpc.WithInsecure()}
   231  	})
   232  	assert.NoError(t, err)
   233  	var msg proto.ReceivedMessage
   234  
   235  	acceptChan := handshaker("localhost:9608", inst, t, mutator, none)
   236  	select {
   237  	case <-time.After(time.Duration(time.Second * 4)):
   238  		assert.FailNow(t, "Didn't receive a message, seems like handshake failed")
   239  	case msg = <-acceptChan:
   240  	}
   241  	assert.Equal(t, common.PKIidType("localhost:9608"), msg.GetConnectionInfo().ID)
   242  	assert.Equal(t, api.PeerIdentityType("localhost:9608"), msg.GetConnectionInfo().Identity)
   243  	assert.Nil(t, msg.GetConnectionInfo().Auth)
   244  	assert.False(t, msg.GetConnectionInfo().IsAuthenticated())
   245  
   246  	inst.Stop()
   247  	s.Stop()
   248  	ll.Close()
   249  	time.Sleep(time.Second)
   250  
   251  	comm, err := newCommInstance(9611, naiveSec)
   252  	assert.NoError(t, err)
   253  	defer comm.Stop()
   254  	// Positive path 2: initiating peer sends its own certificate
   255  	acceptChan = handshaker("localhost:9609", comm, t, mutator, mutualTLS)
   256  
   257  	select {
   258  	case <-time.After(time.Second * 2):
   259  		assert.FailNow(t, "Didn't receive a message, seems like handshake failed")
   260  	case msg = <-acceptChan:
   261  	}
   262  	assertPositivePath(msg, "localhost:9609")
   263  
   264  	// Negative path: initiating peer doesn't send its own certificate
   265  	acceptChan = handshaker("localhost:9610", comm, t, mutator, oneWayTLS)
   266  	time.Sleep(time.Second)
   267  	assert.Equal(t, 0, len(acceptChan))
   268  	// Negative path, signature is wrong
   269  	mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   270  		msg.Signature = append(msg.Signature, 0)
   271  		return msg
   272  	}
   273  	acceptChan = handshaker("localhost:9612", comm, t, mutator, mutualTLS)
   274  	time.Sleep(time.Second)
   275  	assert.Equal(t, 0, len(acceptChan))
   276  
   277  	// Negative path, the PKIid doesn't match the identity
   278  	mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   279  		msg.GetConn().PkiId = []byte("localhost:9650")
   280  		// Sign the message again
   281  		msg.Sign(signer)
   282  		return msg
   283  	}
   284  	acceptChan = handshaker("localhost:9613", comm, t, mutator, mutualTLS)
   285  	time.Sleep(time.Second)
   286  	assert.Equal(t, 0, len(acceptChan))
   287  
   288  	// Negative path, the cert hash isn't what is expected
   289  	mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   290  		msg.GetConn().TlsCertHash = append(msg.GetConn().TlsCertHash, 0)
   291  		msg.Sign(signer)
   292  		return msg
   293  	}
   294  	acceptChan = handshaker("localhost:9615", comm, t, mutator, mutualTLS)
   295  	time.Sleep(time.Second)
   296  	assert.Equal(t, 0, len(acceptChan))
   297  
   298  	// Negative path, no PKI-ID was sent
   299  	mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   300  		msg.GetConn().PkiId = nil
   301  		msg.Sign(signer)
   302  		return msg
   303  	}
   304  	acceptChan = handshaker("localhost:9616", comm, t, mutator, mutualTLS)
   305  	time.Sleep(time.Second)
   306  	assert.Equal(t, 0, len(acceptChan))
   307  
   308  	// Negative path, connection message is of a different type
   309  	mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   310  		msg.Content = &proto.GossipMessage_Empty{
   311  			Empty: &proto.Empty{},
   312  		}
   313  		msg.Sign(signer)
   314  		return msg
   315  	}
   316  	acceptChan = handshaker("localhost:9617", comm, t, mutator, mutualTLS)
   317  	time.Sleep(time.Second)
   318  	assert.Equal(t, 0, len(acceptChan))
   319  
   320  	// Negative path, the peer didn't respond to the handshake in due time
   321  	mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage {
   322  		time.Sleep(time.Second * 5)
   323  		return msg
   324  	}
   325  	acceptChan = handshaker("localhost:9618", comm, t, mutator, mutualTLS)
   326  	time.Sleep(time.Second)
   327  	assert.Equal(t, 0, len(acceptChan))
   328  }
   329  
   330  func TestBasic(t *testing.T) {
   331  	t.Parallel()
   332  	comm1, _ := newCommInstance(2000, naiveSec)
   333  	comm2, _ := newCommInstance(3000, naiveSec)
   334  	comm1.(*commImpl).SetDialOpts()
   335  	comm2.(*commImpl).SetDialOpts()
   336  	defer comm1.Stop()
   337  	defer comm2.Stop()
   338  	m1 := comm1.Accept(acceptAll)
   339  	m2 := comm2.Accept(acceptAll)
   340  	out := make(chan uint64, 2)
   341  	reader := func(ch <-chan proto.ReceivedMessage) {
   342  		m := <-ch
   343  		out <- m.GetGossipMessage().Nonce
   344  	}
   345  	go reader(m1)
   346  	go reader(m2)
   347  	comm1.Send(createGossipMsg(), remotePeer(3000))
   348  	time.Sleep(time.Second)
   349  	comm2.Send(createGossipMsg(), remotePeer(2000))
   350  	waitForMessages(t, out, 2, "Didn't receive 2 messages")
   351  }
   352  
   353  func TestProdConstructor(t *testing.T) {
   354  	t.Parallel()
   355  	peerIdentity := GenerateCertificatesOrPanic()
   356  	srv, lsnr, dialOpts, certHash := createGRPCLayer(20000)
   357  	defer srv.Stop()
   358  	defer lsnr.Close()
   359  	id := []byte("localhost:20000")
   360  	comm1, _ := NewCommInstance(srv, &peerIdentity, identity.NewIdentityMapper(naiveSec, id), id, dialOpts)
   361  	comm1.(*commImpl).selfCertHash = certHash
   362  	go srv.Serve(lsnr)
   363  
   364  	peerIdentity = GenerateCertificatesOrPanic()
   365  	srv, lsnr, dialOpts, certHash = createGRPCLayer(30000)
   366  	defer srv.Stop()
   367  	defer lsnr.Close()
   368  	id = []byte("localhost:30000")
   369  	comm2, _ := NewCommInstance(srv, &peerIdentity, identity.NewIdentityMapper(naiveSec, id), id, dialOpts)
   370  	comm2.(*commImpl).selfCertHash = certHash
   371  	go srv.Serve(lsnr)
   372  	defer comm1.Stop()
   373  	defer comm2.Stop()
   374  	m1 := comm1.Accept(acceptAll)
   375  	m2 := comm2.Accept(acceptAll)
   376  	out := make(chan uint64, 2)
   377  	reader := func(ch <-chan proto.ReceivedMessage) {
   378  		m := <-ch
   379  		out <- m.GetGossipMessage().Nonce
   380  	}
   381  	go reader(m1)
   382  	go reader(m2)
   383  	comm1.Send(createGossipMsg(), remotePeer(30000))
   384  	time.Sleep(time.Second)
   385  	comm2.Send(createGossipMsg(), remotePeer(20000))
   386  	waitForMessages(t, out, 2, "Didn't receive 2 messages")
   387  }
   388  
   389  func TestGetConnectionInfo(t *testing.T) {
   390  	t.Parallel()
   391  	comm1, _ := newCommInstance(6000, naiveSec)
   392  	comm2, _ := newCommInstance(7000, naiveSec)
   393  	defer comm1.Stop()
   394  	defer comm2.Stop()
   395  	m1 := comm1.Accept(acceptAll)
   396  	comm2.Send(createGossipMsg(), remotePeer(6000))
   397  	select {
   398  	case <-time.After(time.Second * 10):
   399  		t.Fatal("Didn't receive a message in time")
   400  	case msg := <-m1:
   401  		assert.Equal(t, comm2.GetPKIid(), msg.GetConnectionInfo().ID)
   402  		assert.NotNil(t, msg.GetSourceEnvelope())
   403  	}
   404  }
   405  
   406  func TestCloseConn(t *testing.T) {
   407  	t.Parallel()
   408  	comm1, _ := newCommInstance(1611, naiveSec)
   409  	defer comm1.Stop()
   410  	acceptChan := comm1.Accept(acceptAll)
   411  
   412  	cert := GenerateCertificatesOrPanic()
   413  	tlsCfg := &tls.Config{
   414  		InsecureSkipVerify: true,
   415  		Certificates:       []tls.Certificate{cert},
   416  	}
   417  	ta := credentials.NewTLS(tlsCfg)
   418  
   419  	conn, err := grpc.Dial("localhost:1611", grpc.WithTransportCredentials(ta), grpc.WithBlock(), grpc.WithTimeout(time.Second))
   420  	assert.NoError(t, err, "%v", err)
   421  	cl := proto.NewGossipClient(conn)
   422  	stream, err := cl.GossipStream(context.Background())
   423  	assert.NoError(t, err, "%v", err)
   424  	c := &commImpl{}
   425  	tlsCertHash := certHashFromRawCert(tlsCfg.Certificates[0].Certificate[0])
   426  	connMsg, _ := c.createConnectionMsg(common.PKIidType("pkiID"), tlsCertHash, api.PeerIdentityType("pkiID"), func(msg []byte) ([]byte, error) {
   427  		mac := hmac.New(sha256.New, hmacKey)
   428  		mac.Write(msg)
   429  		return mac.Sum(nil), nil
   430  	})
   431  	assert.NoError(t, stream.Send(connMsg.Envelope))
   432  	stream.Send(createGossipMsg().Envelope)
   433  	select {
   434  	case <-acceptChan:
   435  	case <-time.After(time.Second):
   436  		assert.Fail(t, "Didn't receive a message within a timely period")
   437  	}
   438  	comm1.CloseConn(&RemotePeer{PKIID: common.PKIidType("pkiID")})
   439  	time.Sleep(time.Second * 10)
   440  	gotErr := false
   441  	msg2Send := createGossipMsg()
   442  	msg2Send.GetDataMsg().Payload = &proto.Payload{
   443  		Data: make([]byte, 1024*1024),
   444  	}
   445  	msg2Send.NoopSign()
   446  	for i := 0; i < defRecvBuffSize; i++ {
   447  		err := stream.Send(msg2Send.Envelope)
   448  		if err != nil {
   449  			gotErr = true
   450  			break
   451  		}
   452  	}
   453  	assert.True(t, gotErr, "Should have failed because connection is closed")
   454  }
   455  
   456  func TestParallelSend(t *testing.T) {
   457  	t.Parallel()
   458  	comm1, _ := newCommInstance(5411, naiveSec)
   459  	comm2, _ := newCommInstance(5412, naiveSec)
   460  	defer comm1.Stop()
   461  	defer comm2.Stop()
   462  
   463  	messages2Send := util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize)
   464  
   465  	wg := sync.WaitGroup{}
   466  	go func() {
   467  		for i := 0; i < messages2Send; i++ {
   468  			wg.Add(1)
   469  			emptyMsg := createGossipMsg()
   470  			go func() {
   471  				defer wg.Done()
   472  				comm1.Send(emptyMsg, remotePeer(5412))
   473  			}()
   474  		}
   475  		wg.Wait()
   476  	}()
   477  
   478  	c := 0
   479  	waiting := true
   480  	ticker := time.NewTicker(time.Duration(5) * time.Second)
   481  	ch := comm2.Accept(acceptAll)
   482  	for waiting {
   483  		select {
   484  		case <-ch:
   485  			c++
   486  			if c == messages2Send {
   487  				waiting = false
   488  			}
   489  		case <-ticker.C:
   490  			waiting = false
   491  		}
   492  	}
   493  	assert.Equal(t, messages2Send, c)
   494  }
   495  
   496  func TestResponses(t *testing.T) {
   497  	t.Parallel()
   498  	comm1, _ := newCommInstance(8611, naiveSec)
   499  	comm2, _ := newCommInstance(8612, naiveSec)
   500  
   501  	defer comm1.Stop()
   502  	defer comm2.Stop()
   503  
   504  	wg := sync.WaitGroup{}
   505  
   506  	msg := createGossipMsg()
   507  	wg.Add(1)
   508  	go func() {
   509  		inChan := comm1.Accept(acceptAll)
   510  		wg.Done()
   511  		for m := range inChan {
   512  			reply := createGossipMsg()
   513  			reply.Nonce = m.GetGossipMessage().Nonce + 1
   514  			m.Respond(reply.GossipMessage)
   515  		}
   516  	}()
   517  	expectedNOnce := uint64(msg.Nonce + 1)
   518  	responsesFromComm1 := comm2.Accept(acceptAll)
   519  
   520  	ticker := time.NewTicker(10 * time.Second)
   521  	wg.Wait()
   522  	comm2.Send(msg, remotePeer(8611))
   523  
   524  	select {
   525  	case <-ticker.C:
   526  		assert.Fail(t, "Haven't got response from comm1 within a timely manner")
   527  		break
   528  	case resp := <-responsesFromComm1:
   529  		ticker.Stop()
   530  		assert.Equal(t, expectedNOnce, resp.GetGossipMessage().Nonce)
   531  		break
   532  	}
   533  }
   534  
   535  func TestAccept(t *testing.T) {
   536  	t.Parallel()
   537  	comm1, _ := newCommInstance(7611, naiveSec)
   538  	comm2, _ := newCommInstance(7612, naiveSec)
   539  
   540  	evenNONCESelector := func(m interface{}) bool {
   541  		return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 == 0
   542  	}
   543  
   544  	oddNONCESelector := func(m interface{}) bool {
   545  		return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 != 0
   546  	}
   547  
   548  	evenNONCES := comm1.Accept(evenNONCESelector)
   549  	oddNONCES := comm1.Accept(oddNONCESelector)
   550  
   551  	var evenResults []uint64
   552  	var oddResults []uint64
   553  
   554  	out := make(chan uint64, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize))
   555  	sem := make(chan struct{}, 0)
   556  
   557  	readIntoSlice := func(a *[]uint64, ch <-chan proto.ReceivedMessage) {
   558  		for m := range ch {
   559  			*a = append(*a, m.GetGossipMessage().Nonce)
   560  			out <- m.GetGossipMessage().Nonce
   561  		}
   562  		sem <- struct{}{}
   563  	}
   564  
   565  	go readIntoSlice(&evenResults, evenNONCES)
   566  	go readIntoSlice(&oddResults, oddNONCES)
   567  
   568  	for i := 0; i < util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize); i++ {
   569  		comm2.Send(createGossipMsg(), remotePeer(7611))
   570  	}
   571  
   572  	waitForMessages(t, out, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize), "Didn't receive all messages sent")
   573  
   574  	comm1.Stop()
   575  	comm2.Stop()
   576  
   577  	<-sem
   578  	<-sem
   579  
   580  	assert.NotEmpty(t, evenResults)
   581  	assert.NotEmpty(t, oddResults)
   582  
   583  	remainderPredicate := func(a []uint64, rem uint64) {
   584  		for _, n := range a {
   585  			assert.Equal(t, n%2, rem)
   586  		}
   587  	}
   588  
   589  	remainderPredicate(evenResults, 0)
   590  	remainderPredicate(oddResults, 1)
   591  }
   592  
   593  func TestReConnections(t *testing.T) {
   594  	t.Parallel()
   595  	comm1, _ := newCommInstance(3611, naiveSec)
   596  	comm2, _ := newCommInstance(3612, naiveSec)
   597  
   598  	reader := func(out chan uint64, in <-chan proto.ReceivedMessage) {
   599  		for {
   600  			msg := <-in
   601  			if msg == nil {
   602  				return
   603  			}
   604  			out <- msg.GetGossipMessage().Nonce
   605  		}
   606  	}
   607  
   608  	out1 := make(chan uint64, 10)
   609  	out2 := make(chan uint64, 10)
   610  
   611  	go reader(out1, comm1.Accept(acceptAll))
   612  	go reader(out2, comm2.Accept(acceptAll))
   613  
   614  	// comm1 connects to comm2
   615  	comm1.Send(createGossipMsg(), remotePeer(3612))
   616  	waitForMessages(t, out2, 1, "Comm2 didn't receive a message from comm1 in a timely manner")
   617  	time.Sleep(time.Second)
   618  	// comm2 sends to comm1
   619  	comm2.Send(createGossipMsg(), remotePeer(3611))
   620  	waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner")
   621  
   622  	comm1.Stop()
   623  	comm1, _ = newCommInstance(3611, naiveSec)
   624  	time.Sleep(time.Second)
   625  	out1 = make(chan uint64, 1)
   626  	go reader(out1, comm1.Accept(acceptAll))
   627  	comm2.Send(createGossipMsg(), remotePeer(3611))
   628  	waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner")
   629  }
   630  
   631  func TestProbe(t *testing.T) {
   632  	t.Parallel()
   633  	comm1, _ := newCommInstance(6611, naiveSec)
   634  	defer comm1.Stop()
   635  	comm2, _ := newCommInstance(6612, naiveSec)
   636  	time.Sleep(time.Duration(1) * time.Second)
   637  	assert.NoError(t, comm1.Probe(remotePeer(6612)))
   638  	_, err := comm1.Handshake(remotePeer(6612))
   639  	assert.NoError(t, err)
   640  	assert.Error(t, comm1.Probe(remotePeer(9012)))
   641  	_, err = comm1.Handshake(remotePeer(9012))
   642  	assert.Error(t, err)
   643  	comm2.Stop()
   644  	time.Sleep(time.Second)
   645  	assert.Error(t, comm1.Probe(remotePeer(6612)))
   646  	_, err = comm1.Handshake(remotePeer(6612))
   647  	assert.Error(t, err)
   648  	comm2, _ = newCommInstance(6612, naiveSec)
   649  	defer comm2.Stop()
   650  	time.Sleep(time.Duration(1) * time.Second)
   651  	assert.NoError(t, comm2.Probe(remotePeer(6611)))
   652  	_, err = comm2.Handshake(remotePeer(6611))
   653  	assert.NoError(t, err)
   654  	assert.NoError(t, comm1.Probe(remotePeer(6612)))
   655  	_, err = comm1.Handshake(remotePeer(6612))
   656  	assert.NoError(t, err)
   657  	// Now try a deep probe with an expected PKI-ID that doesn't match
   658  	wrongRemotePeer := remotePeer(6612)
   659  	if wrongRemotePeer.PKIID[0] == 0 {
   660  		wrongRemotePeer.PKIID[0] = 1
   661  	} else {
   662  		wrongRemotePeer.PKIID[0] = 0
   663  	}
   664  	_, err = comm1.Handshake(wrongRemotePeer)
   665  	assert.Error(t, err)
   666  	// Try a deep probe with a nil PKI-ID
   667  	id, err := comm1.Handshake(&RemotePeer{Endpoint: "localhost:6612"})
   668  	assert.NoError(t, err)
   669  	assert.Equal(t, api.PeerIdentityType("localhost:6612"), id)
   670  }
   671  
   672  func TestPresumedDead(t *testing.T) {
   673  	t.Parallel()
   674  	comm1, _ := newCommInstance(4611, naiveSec)
   675  	comm2, _ := newCommInstance(4612, naiveSec)
   676  
   677  	wg := sync.WaitGroup{}
   678  	wg.Add(1)
   679  	go func() {
   680  		wg.Wait()
   681  		comm1.Send(createGossipMsg(), remotePeer(4612))
   682  	}()
   683  
   684  	ticker := time.NewTicker(time.Duration(10) * time.Second)
   685  	acceptCh := comm2.Accept(acceptAll)
   686  	wg.Done()
   687  	select {
   688  	case <-acceptCh:
   689  		ticker.Stop()
   690  	case <-ticker.C:
   691  		assert.Fail(t, "Didn't get first message")
   692  	}
   693  
   694  	comm2.Stop()
   695  	go func() {
   696  		for i := 0; i < 5; i++ {
   697  			comm1.Send(createGossipMsg(), remotePeer(4612))
   698  			time.Sleep(time.Millisecond * 200)
   699  		}
   700  	}()
   701  
   702  	ticker = time.NewTicker(time.Second * time.Duration(3))
   703  	select {
   704  	case <-ticker.C:
   705  		assert.Fail(t, "Didn't get a presumed dead message within a timely manner")
   706  		break
   707  	case <-comm1.PresumedDead():
   708  		ticker.Stop()
   709  		break
   710  	}
   711  }
   712  
   713  func createGossipMsg() *proto.SignedGossipMessage {
   714  	msg, _ := (&proto.GossipMessage{
   715  		Tag:   proto.GossipMessage_EMPTY,
   716  		Nonce: uint64(rand.Int()),
   717  		Content: &proto.GossipMessage_DataMsg{
   718  			DataMsg: &proto.DataMessage{},
   719  		},
   720  	}).NoopSign()
   721  	return msg
   722  }
   723  
   724  func remotePeer(port int) *RemotePeer {
   725  	endpoint := fmt.Sprintf("localhost:%d", port)
   726  	return &RemotePeer{Endpoint: endpoint, PKIID: []byte(endpoint)}
   727  }
   728  
   729  func waitForMessages(t *testing.T, msgChan chan uint64, count int, errMsg string) {
   730  	c := 0
   731  	waiting := true
   732  	ticker := time.NewTicker(time.Duration(10) * time.Second)
   733  	for waiting {
   734  		select {
   735  		case <-msgChan:
   736  			c++
   737  			if c == count {
   738  				waiting = false
   739  			}
   740  		case <-ticker.C:
   741  			waiting = false
   742  		}
   743  	}
   744  	assert.Equal(t, count, c, errMsg)
   745  }
   746  
   747  func TestMain(m *testing.M) {
   748  	SetDialTimeout(time.Duration(300) * time.Millisecond)
   749  
   750  	ret := m.Run()
   751  	os.Exit(ret)
   752  }