github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/util/testutil/gen.go (about)

     1  package testutil
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"sync"
     9  	"testing"
    10  
    11  	ci "github.com/ipfs/go-ipfs/p2p/crypto"
    12  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    13  	u "github.com/ipfs/go-ipfs/util"
    14  
    15  	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
    16  )
    17  
    18  // ZeroLocalTCPAddress is the "zero" tcp local multiaddr. This means:
    19  //   /ip4/127.0.0.1/tcp/0
    20  var ZeroLocalTCPAddress ma.Multiaddr
    21  
    22  func init() {
    23  	// initialize ZeroLocalTCPAddress
    24  	maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
    25  	if err != nil {
    26  		panic(err)
    27  	}
    28  	ZeroLocalTCPAddress = maddr
    29  }
    30  
    31  func RandTestKeyPair(bits int) (ci.PrivKey, ci.PubKey, error) {
    32  	return ci.GenerateKeyPairWithReader(ci.RSA, bits, u.NewTimeSeededRand())
    33  }
    34  
    35  func SeededTestKeyPair(seed int64) (ci.PrivKey, ci.PubKey, error) {
    36  	return ci.GenerateKeyPairWithReader(ci.RSA, 512, u.NewSeededRand(seed))
    37  }
    38  
    39  // RandPeerID generates random "valid" peer IDs. it does not NEED to generate
    40  // keys because it is as if we lost the key right away. fine to read randomness
    41  // and hash it. to generate proper keys and corresponding PeerID, use:
    42  //  sk, pk, _ := testutil.RandKeyPair()
    43  //  id, _ := peer.IDFromPublicKey(pk)
    44  func RandPeerID() (peer.ID, error) {
    45  	buf := make([]byte, 16)
    46  	if _, err := io.ReadFull(u.NewTimeSeededRand(), buf); err != nil {
    47  		return "", err
    48  	}
    49  	h := u.Hash(buf)
    50  	return peer.ID(h), nil
    51  }
    52  
    53  func RandPeerIDFatal(t testing.TB) peer.ID {
    54  	p, err := RandPeerID()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	return p
    59  }
    60  
    61  // RandLocalTCPAddress returns a random multiaddr. it suppresses errors
    62  // for nice composability-- do check the address isn't nil.
    63  //
    64  // Note: for real network tests, use ZeroLocalTCPAddress so the kernel
    65  // assigns an unused TCP port. otherwise you may get clashes. This
    66  // function remains here so that p2p/net/mock (which does not touch the
    67  // real network) can assign different addresses to peers.
    68  func RandLocalTCPAddress() ma.Multiaddr {
    69  
    70  	// chances are it will work out, but it **might** fail if the port is in use
    71  	// most ports above 10000 aren't in use by long running processes, so yay.
    72  	// (maybe there should be a range of "loopback" ports that are guaranteed
    73  	// to be open for the process, but naturally can only talk to self.)
    74  
    75  	lastPort.Lock()
    76  	if lastPort.port == 0 {
    77  		lastPort.port = 10000 + SeededRand.Intn(50000)
    78  	}
    79  	port := lastPort.port
    80  	lastPort.port++
    81  	lastPort.Unlock()
    82  
    83  	addr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port)
    84  	maddr, _ := ma.NewMultiaddr(addr)
    85  	return maddr
    86  }
    87  
    88  var lastPort = struct {
    89  	port int
    90  	sync.Mutex
    91  }{}
    92  
    93  // PeerNetParams is a struct to bundle together the four things
    94  // you need to run a connection with a peer: id, 2keys, and addr.
    95  type PeerNetParams struct {
    96  	ID      peer.ID
    97  	PrivKey ci.PrivKey
    98  	PubKey  ci.PubKey
    99  	Addr    ma.Multiaddr
   100  }
   101  
   102  func (p *PeerNetParams) checkKeys() error {
   103  	if !p.ID.MatchesPrivateKey(p.PrivKey) {
   104  		return errors.New("p.ID does not match p.PrivKey")
   105  	}
   106  
   107  	if !p.ID.MatchesPublicKey(p.PubKey) {
   108  		return errors.New("p.ID does not match p.PubKey")
   109  	}
   110  
   111  	buf := new(bytes.Buffer)
   112  	buf.Write([]byte("hello world. this is me, I swear."))
   113  	b := buf.Bytes()
   114  
   115  	sig, err := p.PrivKey.Sign(b)
   116  	if err != nil {
   117  		return fmt.Errorf("sig signing failed: %s", err)
   118  	}
   119  
   120  	sigok, err := p.PubKey.Verify(b, sig)
   121  	if err != nil {
   122  		return fmt.Errorf("sig verify failed: %s", err)
   123  	}
   124  	if !sigok {
   125  		return fmt.Errorf("sig verify failed: sig invalid")
   126  	}
   127  
   128  	return nil // ok. move along.
   129  }
   130  
   131  func RandPeerNetParamsOrFatal(t *testing.T) PeerNetParams {
   132  	p, err := RandPeerNetParams()
   133  	if err != nil {
   134  		t.Fatal(err)
   135  		return PeerNetParams{} // TODO return nil
   136  	}
   137  	return *p
   138  }
   139  
   140  func RandPeerNetParams() (*PeerNetParams, error) {
   141  	var p PeerNetParams
   142  	var err error
   143  	p.Addr = ZeroLocalTCPAddress
   144  	p.PrivKey, p.PubKey, err = RandTestKeyPair(512)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  	p.ID, err = peer.IDFromPublicKey(p.PubKey)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  	if err := p.checkKeys(); err != nil {
   153  		return nil, err
   154  	}
   155  	return &p, nil
   156  }