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