github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/net/conn/secure_conn_test.go (about)

     1  package conn
     2  
     3  import (
     4  	"bytes"
     5  	"runtime"
     6  	"sync"
     7  	"testing"
     8  	"time"
     9  
    10  	ic "github.com/ipfs/go-ipfs/p2p/crypto"
    11  	travis "github.com/ipfs/go-ipfs/util/testutil/ci/travis"
    12  
    13  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    14  )
    15  
    16  func upgradeToSecureConn(t *testing.T, ctx context.Context, sk ic.PrivKey, c Conn) (Conn, error) {
    17  	if c, ok := c.(*secureConn); ok {
    18  		return c, nil
    19  	}
    20  
    21  	// shouldn't happen, because dial + listen already return secure conns.
    22  	s, err := newSecureConn(ctx, sk, c)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	// need to read + write, as that's what triggers the handshake.
    28  	h := []byte("hello")
    29  	if _, err := s.Write(h); err != nil {
    30  		return nil, err
    31  	}
    32  	if _, err := s.Read(h); err != nil {
    33  		return nil, err
    34  	}
    35  	return s, nil
    36  }
    37  
    38  func secureHandshake(t *testing.T, ctx context.Context, sk ic.PrivKey, c Conn, done chan error) {
    39  	_, err := upgradeToSecureConn(t, ctx, sk, c)
    40  	done <- err
    41  }
    42  
    43  func TestSecureSimple(t *testing.T) {
    44  	// t.Skip("Skipping in favor of another test")
    45  
    46  	numMsgs := 100
    47  	if testing.Short() {
    48  		numMsgs = 10
    49  	}
    50  
    51  	ctx := context.Background()
    52  	c1, c2, p1, p2 := setupSingleConn(t, ctx)
    53  
    54  	done := make(chan error)
    55  	go secureHandshake(t, ctx, p1.PrivKey, c1, done)
    56  	go secureHandshake(t, ctx, p2.PrivKey, c2, done)
    57  
    58  	for i := 0; i < 2; i++ {
    59  		if err := <-done; err != nil {
    60  			t.Fatal(err)
    61  		}
    62  	}
    63  
    64  	for i := 0; i < numMsgs; i++ {
    65  		testOneSendRecv(t, c1, c2)
    66  		testOneSendRecv(t, c2, c1)
    67  	}
    68  
    69  	c1.Close()
    70  	c2.Close()
    71  }
    72  
    73  func TestSecureClose(t *testing.T) {
    74  	// t.Skip("Skipping in favor of another test")
    75  
    76  	ctx := context.Background()
    77  	c1, c2, p1, p2 := setupSingleConn(t, ctx)
    78  
    79  	done := make(chan error)
    80  	go secureHandshake(t, ctx, p1.PrivKey, c1, done)
    81  	go secureHandshake(t, ctx, p2.PrivKey, c2, done)
    82  
    83  	for i := 0; i < 2; i++ {
    84  		if err := <-done; err != nil {
    85  			t.Fatal(err)
    86  		}
    87  	}
    88  
    89  	testOneSendRecv(t, c1, c2)
    90  
    91  	c1.Close()
    92  	testNotOneSendRecv(t, c1, c2)
    93  
    94  	c2.Close()
    95  	testNotOneSendRecv(t, c1, c2)
    96  	testNotOneSendRecv(t, c2, c1)
    97  
    98  }
    99  
   100  func TestSecureCancelHandshake(t *testing.T) {
   101  	// t.Skip("Skipping in favor of another test")
   102  
   103  	ctx, cancel := context.WithCancel(context.Background())
   104  	c1, c2, p1, p2 := setupSingleConn(t, ctx)
   105  
   106  	done := make(chan error)
   107  	go secureHandshake(t, ctx, p1.PrivKey, c1, done)
   108  	<-time.After(time.Millisecond)
   109  	cancel() // cancel ctx
   110  	go secureHandshake(t, ctx, p2.PrivKey, c2, done)
   111  
   112  	for i := 0; i < 2; i++ {
   113  		if err := <-done; err == nil {
   114  			t.Error("cancel should've errored out")
   115  		}
   116  	}
   117  }
   118  
   119  func TestSecureHandshakeFailsWithWrongKeys(t *testing.T) {
   120  	// t.Skip("Skipping in favor of another test")
   121  
   122  	ctx, cancel := context.WithCancel(context.Background())
   123  	defer cancel()
   124  	c1, c2, p1, p2 := setupSingleConn(t, ctx)
   125  
   126  	done := make(chan error)
   127  	go secureHandshake(t, ctx, p2.PrivKey, c1, done)
   128  	go secureHandshake(t, ctx, p1.PrivKey, c2, done)
   129  
   130  	for i := 0; i < 2; i++ {
   131  		if err := <-done; err == nil {
   132  			t.Fatal("wrong keys should've errored out.")
   133  		}
   134  	}
   135  }
   136  
   137  func TestSecureCloseLeak(t *testing.T) {
   138  	// t.Skip("Skipping in favor of another test")
   139  
   140  	if testing.Short() {
   141  		t.SkipNow()
   142  	}
   143  	if travis.IsRunning() {
   144  		t.Skip("this doesn't work well on travis")
   145  	}
   146  
   147  	runPair := func(c1, c2 Conn, num int) {
   148  		log.Debugf("runPair %d", num)
   149  
   150  		for i := 0; i < num; i++ {
   151  			log.Debugf("runPair iteration %d", i)
   152  			b1 := []byte("beep")
   153  			c1.WriteMsg(b1)
   154  			b2, err := c2.ReadMsg()
   155  			if err != nil {
   156  				panic(err)
   157  			}
   158  			if !bytes.Equal(b1, b2) {
   159  				panic("bytes not equal")
   160  			}
   161  
   162  			b2 = []byte("beep")
   163  			c2.WriteMsg(b2)
   164  			b1, err = c1.ReadMsg()
   165  			if err != nil {
   166  				panic(err)
   167  			}
   168  			if !bytes.Equal(b1, b2) {
   169  				panic("bytes not equal")
   170  			}
   171  
   172  			<-time.After(time.Microsecond * 5)
   173  		}
   174  	}
   175  
   176  	var cons = 5
   177  	var msgs = 50
   178  	log.Debugf("Running %d connections * %d msgs.\n", cons, msgs)
   179  
   180  	var wg sync.WaitGroup
   181  	for i := 0; i < cons; i++ {
   182  		wg.Add(1)
   183  
   184  		ctx, cancel := context.WithCancel(context.Background())
   185  		c1, c2, _, _ := setupSecureConn(t, ctx)
   186  		go func(c1, c2 Conn) {
   187  
   188  			defer func() {
   189  				c1.Close()
   190  				c2.Close()
   191  				cancel()
   192  				wg.Done()
   193  			}()
   194  
   195  			runPair(c1, c2, msgs)
   196  		}(c1, c2)
   197  	}
   198  
   199  	log.Debugf("Waiting...\n")
   200  	wg.Wait()
   201  	// done!
   202  
   203  	<-time.After(time.Millisecond * 150)
   204  	if runtime.NumGoroutine() > 20 {
   205  		// panic("uncomment me to debug")
   206  		t.Fatal("leaking goroutines:", runtime.NumGoroutine())
   207  	}
   208  }