Commit 0f3ffb2d authored by Jeromy's avatar Jeromy
Browse files

extract conn, addr-util, and testutil

parent 0aaec876
package swarm package swarm
import ( import (
conn "github.com/libp2p/go-libp2p/p2p/net/conn"
addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
addrutil "github.com/libp2p/go-addr-util"
conn "github.com/libp2p/go-libp2p-conn"
) )
// ListenAddresses returns a list of addresses at which this swarm listens. // ListenAddresses returns a list of addresses at which this swarm listens.
......
package swarm package swarm
import ( import (
"context"
"testing" "testing"
metrics "github.com/libp2p/go-libp2p/p2p/metrics" metrics "github.com/libp2p/go-libp2p/p2p/metrics"
addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr"
testutil "github.com/libp2p/go-libp2p/testutil"
"context"
pstore "github.com/ipfs/go-libp2p-peerstore" pstore "github.com/ipfs/go-libp2p-peerstore"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
addrutil "github.com/libp2p/go-addr-util"
testutil "github.com/libp2p/go-testutil"
) )
func TestFilterAddrs(t *testing.T) { func TestFilterAddrs(t *testing.T) {
......
package swarm package swarm
import ( import (
"context"
"fmt" "fmt"
inet "github.com/libp2p/go-libp2p/p2p/net" inet "github.com/libp2p/go-libp2p/p2p/net"
conn "github.com/libp2p/go-libp2p/p2p/net/conn"
"context"
ic "github.com/ipfs/go-libp2p-crypto" ic "github.com/ipfs/go-libp2p-crypto"
peer "github.com/ipfs/go-libp2p-peer" peer "github.com/ipfs/go-libp2p-peer"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
ps "github.com/jbenet/go-peerstream" ps "github.com/jbenet/go-peerstream"
conn "github.com/libp2p/go-libp2p-conn"
) )
// Conn is a simple wrapper around a ps.Conn that also exposes // Conn is a simple wrapper around a ps.Conn that also exposes
......
...@@ -10,8 +10,8 @@ import ( ...@@ -10,8 +10,8 @@ import (
lgbl "github.com/ipfs/go-libp2p-loggables" lgbl "github.com/ipfs/go-libp2p-loggables"
peer "github.com/ipfs/go-libp2p-peer" peer "github.com/ipfs/go-libp2p-peer"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
conn "github.com/libp2p/go-libp2p/p2p/net/conn" addrutil "github.com/libp2p/go-addr-util"
addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" conn "github.com/libp2p/go-libp2p-conn"
) )
// Diagram of dial sync: // Diagram of dial sync:
......
package swarm package swarm
import ( import (
"context"
"fmt" "fmt"
"context" inet "github.com/libp2p/go-libp2p/p2p/net"
lgbl "github.com/ipfs/go-libp2p-loggables" lgbl "github.com/ipfs/go-libp2p-loggables"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
ps "github.com/jbenet/go-peerstream" ps "github.com/jbenet/go-peerstream"
conn "github.com/libp2p/go-libp2p-conn"
transport "github.com/libp2p/go-libp2p-transport" transport "github.com/libp2p/go-libp2p-transport"
mconn "github.com/libp2p/go-libp2p/p2p/metrics/conn" mconn "github.com/libp2p/go-libp2p/p2p/metrics/conn"
inet "github.com/libp2p/go-libp2p/p2p/net"
conn "github.com/libp2p/go-libp2p/p2p/net/conn"
) )
func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { func (s *Swarm) AddListenAddr(a ma.Multiaddr) error {
......
...@@ -2,6 +2,7 @@ package swarm ...@@ -2,6 +2,7 @@ package swarm
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"io" "io"
"net" "net"
...@@ -11,12 +12,11 @@ import ( ...@@ -11,12 +12,11 @@ import (
metrics "github.com/libp2p/go-libp2p/p2p/metrics" metrics "github.com/libp2p/go-libp2p/p2p/metrics"
inet "github.com/libp2p/go-libp2p/p2p/net" inet "github.com/libp2p/go-libp2p/p2p/net"
testutil "github.com/libp2p/go-libp2p/testutil"
"context"
peer "github.com/ipfs/go-libp2p-peer" peer "github.com/ipfs/go-libp2p-peer"
pstore "github.com/ipfs/go-libp2p-peerstore" pstore "github.com/ipfs/go-libp2p-peerstore"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
testutil "github.com/libp2p/go-testutil"
) )
func EchoStreamHandler(stream inet.Stream) { func EchoStreamHandler(stream inet.Stream) {
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
ic "github.com/ipfs/go-libp2p-crypto" ic "github.com/ipfs/go-libp2p-crypto"
peer "github.com/ipfs/go-libp2p-peer" peer "github.com/ipfs/go-libp2p-peer"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
testutil "github.com/libp2p/go-libp2p/testutil" testutil "github.com/libp2p/go-testutil"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
) )
......
package testutil package testutil
import ( import (
"context"
"testing" "testing"
pstore "github.com/ipfs/go-libp2p-peerstore"
bhost "github.com/libp2p/go-libp2p/p2p/host/basic" bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
metrics "github.com/libp2p/go-libp2p/p2p/metrics" metrics "github.com/libp2p/go-libp2p/p2p/metrics"
inet "github.com/libp2p/go-libp2p/p2p/net" inet "github.com/libp2p/go-libp2p/p2p/net"
swarm "github.com/libp2p/go-libp2p/p2p/net/swarm" swarm "github.com/libp2p/go-libp2p/p2p/net/swarm"
tu "github.com/libp2p/go-libp2p/testutil"
"context" pstore "github.com/ipfs/go-libp2p-peerstore"
ma "github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-multiaddr"
tu "github.com/libp2p/go-testutil"
) )
func GenSwarmNetwork(t *testing.T, ctx context.Context) *swarm.Network { func GenSwarmNetwork(t *testing.T, ctx context.Context) *swarm.Network {
......
...@@ -200,6 +200,24 @@ ...@@ -200,6 +200,24 @@
"hash": "QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN", "hash": "QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN",
"name": "go-libp2p-protocol", "name": "go-libp2p-protocol",
"version": "1.0.0" "version": "1.0.0"
},
{
"author": "whyrusleeping",
"hash": "QmT6RvBdXJ6xfPgEMT7LAmFcTEbs9Ggh2N3fYGfR1xN3HX",
"name": "go-addr-util",
"version": "1.0.0"
},
{
"author": "whyrusleeping",
"hash": "QmYpVUnnedgGrp6cX2pBii5HRQgcSr778FiKVe7o7nF5Z3",
"name": "go-testutil",
"version": "1.0.2"
},
{
"author": "whyrusleeping",
"hash": "QmTaW4q1AbqMkpfDLUYzW18nW62GsrnFvtVcvR1pnaURm6",
"name": "go-libp2p-conn",
"version": "1.0.0"
} }
], ],
"gxVersion": "0.4.0", "gxVersion": "0.4.0",
......
// Package ci implements some helper functions to use during
// tests. Many times certain facilities are not available, or tests
// must run differently.
package ci
import (
"os"
jenkins "github.com/libp2p/go-libp2p/testutil/ci/jenkins"
travis "github.com/libp2p/go-libp2p/testutil/ci/travis"
)
// EnvVar is a type to use travis-only env var names with
// the type system.
type EnvVar string
// Environment variables that TravisCI uses.
const (
VarCI EnvVar = "CI"
VarNoFuse EnvVar = "TEST_NO_FUSE"
VarVerbose EnvVar = "TEST_VERBOSE"
)
// IsRunning attempts to determine whether this process is
// running on CI. This is done by checking any of:
//
// CI=true
// travis.IsRunning()
// jenkins.IsRunning()
//
func IsRunning() bool {
if os.Getenv(string(VarCI)) == "true" {
return true
}
return travis.IsRunning() || jenkins.IsRunning()
}
// Env returns the value of a CI env variable.
func Env(v EnvVar) string {
return os.Getenv(string(v))
}
// Returns whether FUSE is explicitly disabled wiht TEST_NO_FUSE.
func NoFuse() bool {
return os.Getenv(string(VarNoFuse)) == "1"
}
// Returns whether TEST_VERBOSE is enabled.
func Verbose() bool {
return os.Getenv(string(VarVerbose)) == "1"
}
// Package jenkins implements some helper functions to use during
// tests. Many times certain facilities are not available, or tests
// must run differently.
package jenkins
import (
"os"
"strings"
)
// EnvVar is a type to use travis-only env var names with
// the type system.
type EnvVar string
// Environment variables that Jenkins uses.
const (
VarBuildNumber EnvVar = "BUILD_NUMBER"
VarBuildId EnvVar = "BUILD_ID"
VarBuildUrl EnvVar = "BUILD_URL"
VarNodeName EnvVar = "NODE_NAME"
VarJobName EnvVar = "JOB_NAME"
VarBuildTag EnvVar = "BUILD_TAG"
VarJenkinsUrl EnvVar = "JENKINS_URL"
VarExecutorNumber EnvVar = "EXECUTOR_NUMBER"
VarJavaHome EnvVar = "JAVA_HOME"
VarWorkspace EnvVar = "WORKSPACE"
VarSvnRevision EnvVar = "SVN_REVISION"
VarCvsBranch EnvVar = "CVS_BRANCH"
VarGitCommit EnvVar = "GIT_COMMIT"
VarGitUrl EnvVar = "GIT_URL"
VarGitBranch EnvVar = "GIT_BRANCH"
)
// IsRunning attempts to determine whether this process is
// running on Jenkins CI. This is done by checking any of the
// following:
//
// JENKINS_URL is set
// BuildTag has prefix "jenkins-"
//
func IsRunning() bool {
return len(Env(VarJenkinsUrl)) > 0 || strings.HasPrefix(Env(VarBuildTag), "jenkins-")
}
// Env returns the value of a travis env variable.
func Env(v EnvVar) string {
return os.Getenv(string(v))
}
// JobName returns the jenkins JOB_NAME of this build.
func JobName() string {
return Env(VarJobName)
}
// BuildTag returns the jenkins BUILD_TAG.
func BuildTag() string {
return Env(VarBuildTag)
}
package jenkins
import (
"os"
"strings"
"testing"
)
func TestIsRunning(t *testing.T) {
hasPrefix := strings.HasPrefix(os.Getenv("BUILD_TAG"), "jenkins-")
tr := len(os.Getenv("JENKINS_URL")) > 0 || hasPrefix
if tr != IsRunning() {
t.Error("IsRunning() does not match TRAVIS && CI env var check")
}
}
// Package travis implements some helper functions to use during
// tests. Many times certain facilities are not available, or tests
// must run differently.
package travis
import "os"
// EnvVar is a type to use travis-only env var names with
// the type system.
type EnvVar string
// Environment variables that TravisCI uses.
const (
VarCI EnvVar = "CI"
VarTravis EnvVar = "TRAVIS"
VarBranch EnvVar = "TRAVIS_BRANCH"
VarBuildDir EnvVar = "TRAVIS_BUILD_DIR"
VarBuildId EnvVar = "TRAVIS_BUILD_ID"
VarBuildNumber EnvVar = "TRAVIS_BUILD_NUMBER"
VarCommit EnvVar = "TRAVIS_COMMIT"
VarCommitRange EnvVar = "TRAVIS_COMMIT_RANGE"
VarJobId EnvVar = "TRAVIS_JOB_ID"
VarJobNumber EnvVar = "TRAVIS_JOB_NUMBER"
VarPullRequest EnvVar = "TRAVIS_PULL_REQUEST"
VarSecureEnvVars EnvVar = "TRAVIS_SECURE_ENV_VARS"
VarRepoSlug EnvVar = "TRAVIS_REPO_SLUG"
VarOsName EnvVar = "TRAVIS_OS_NAME"
VarTag EnvVar = "TRAVIS_TAG"
VarGoVersion EnvVar = "TRAVIS_GO_VERSION"
)
// IsRunning attempts to determine whether this process is
// running on Travis-CI. This is done by checking ALL of the
// following env vars are set:
//
// CI=true
// TRAVIS=true
//
// Note: cannot just check CI.
func IsRunning() bool {
return Env(VarCI) == "true" && Env(VarTravis) == "true"
}
// Env returns the value of a travis env variable.
func Env(v EnvVar) string {
return os.Getenv(string(v))
}
// JobId returns the travis JOB_ID of this build.
func JobId() string {
return Env(VarJobId)
}
// JobNumber returns the travis JOB_NUMBER of this build.
func JobNumber() string {
return Env(VarJobNumber)
}
package travis
import (
"os"
"testing"
)
func TestIsRunning(t *testing.T) {
tr := os.Getenv("TRAVIS") == "true" && os.Getenv("CI") == "true"
if tr != IsRunning() {
t.Error("IsRunning() does not match TRAVIS && CI env var check")
}
}
package testutil
import (
"bytes"
"errors"
"fmt"
"io"
"sync"
"testing"
u "github.com/ipfs/go-ipfs-util"
ci "github.com/ipfs/go-libp2p-crypto"
peer "github.com/ipfs/go-libp2p-peer"
ma "github.com/jbenet/go-multiaddr"
)
// ZeroLocalTCPAddress is the "zero" tcp local multiaddr. This means:
// /ip4/127.0.0.1/tcp/0
var ZeroLocalTCPAddress ma.Multiaddr
func init() {
// initialize ZeroLocalTCPAddress
maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
if err != nil {
panic(err)
}
ZeroLocalTCPAddress = maddr
}
func RandTestKeyPair(bits int) (ci.PrivKey, ci.PubKey, error) {
return ci.GenerateKeyPairWithReader(ci.RSA, bits, u.NewTimeSeededRand())
}
func SeededTestKeyPair(seed int64) (ci.PrivKey, ci.PubKey, error) {
return ci.GenerateKeyPairWithReader(ci.RSA, 512, u.NewSeededRand(seed))
}
// RandPeerID generates random "valid" peer IDs. it does not NEED to generate
// keys because it is as if we lost the key right away. fine to read randomness
// and hash it. to generate proper keys and corresponding PeerID, use:
// sk, pk, _ := testutil.RandKeyPair()
// id, _ := peer.IDFromPublicKey(pk)
func RandPeerID() (peer.ID, error) {
buf := make([]byte, 16)
if _, err := io.ReadFull(u.NewTimeSeededRand(), buf); err != nil {
return "", err
}
h := u.Hash(buf)
return peer.ID(h), nil
}
func RandPeerIDFatal(t testing.TB) peer.ID {
p, err := RandPeerID()
if err != nil {
t.Fatal(err)
}
return p
}
// RandLocalTCPAddress returns a random multiaddr. it suppresses errors
// for nice composability-- do check the address isn't nil.
//
// Note: for real network tests, use ZeroLocalTCPAddress so the kernel
// assigns an unused TCP port. otherwise you may get clashes. This
// function remains here so that p2p/net/mock (which does not touch the
// real network) can assign different addresses to peers.
func RandLocalTCPAddress() ma.Multiaddr {
// chances are it will work out, but it **might** fail if the port is in use
// most ports above 10000 aren't in use by long running processes, so yay.
// (maybe there should be a range of "loopback" ports that are guaranteed
// to be open for the process, but naturally can only talk to self.)
lastPort.Lock()
if lastPort.port == 0 {
lastPort.port = 10000 + SeededRand.Intn(50000)
}
port := lastPort.port
lastPort.port++
lastPort.Unlock()
addr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port)
maddr, _ := ma.NewMultiaddr(addr)
return maddr
}
var lastPort = struct {
port int
sync.Mutex
}{}
// PeerNetParams is a struct to bundle together the four things
// you need to run a connection with a peer: id, 2keys, and addr.
type PeerNetParams struct {
ID peer.ID
PrivKey ci.PrivKey
PubKey ci.PubKey
Addr ma.Multiaddr
}
func (p *PeerNetParams) checkKeys() error {
if !p.ID.MatchesPrivateKey(p.PrivKey) {
return errors.New("p.ID does not match p.PrivKey")
}
if !p.ID.MatchesPublicKey(p.PubKey) {
return errors.New("p.ID does not match p.PubKey")
}
buf := new(bytes.Buffer)
buf.Write([]byte("hello world. this is me, I swear."))
b := buf.Bytes()
sig, err := p.PrivKey.Sign(b)
if err != nil {
return fmt.Errorf("sig signing failed: %s", err)
}
sigok, err := p.PubKey.Verify(b, sig)
if err != nil {
return fmt.Errorf("sig verify failed: %s", err)
}
if !sigok {
return fmt.Errorf("sig verify failed: sig invalid")
}
return nil // ok. move along.
}
func RandPeerNetParamsOrFatal(t *testing.T) PeerNetParams {
p, err := RandPeerNetParams()
if err != nil {
t.Fatal(err)
return PeerNetParams{} // TODO return nil
}
return *p
}
func RandPeerNetParams() (*PeerNetParams, error) {
var p PeerNetParams
var err error
p.Addr = ZeroLocalTCPAddress
p.PrivKey, p.PubKey, err = RandTestKeyPair(512)
if err != nil {
return nil, err
}
p.ID, err = peer.IDFromPublicKey(p.PubKey)
if err != nil {
return nil, err
}
if err := p.checkKeys(); err != nil {
return nil, err
}
return &p, nil
}
package testutil
import (
"testing"
ci "github.com/ipfs/go-libp2p-crypto"
peer "github.com/ipfs/go-libp2p-peer"
ma "github.com/jbenet/go-multiaddr"
)
type Identity interface {
Address() ma.Multiaddr
ID() peer.ID
PrivateKey() ci.PrivKey
PublicKey() ci.PubKey
}
// TODO add a cheaper way to generate identities
func RandIdentity() (Identity, error) {
p, err := RandPeerNetParams()
if err != nil {
return nil, err
}
return &identity{*p}, nil
}
func RandIdentityOrFatal(t *testing.T) Identity {
p, err := RandPeerNetParams()
if err != nil {
t.Fatal(err)
}
return &identity{*p}
}
// identity is a temporary shim to delay binding of PeerNetParams.
type identity struct {
PeerNetParams
}
func (p *identity) ID() peer.ID {
return p.PeerNetParams.ID
}
func (p *identity) Address() ma.Multiaddr {
return p.Addr
}
func (p *identity) PrivateKey() ci.PrivKey {
return p.PrivKey
}
func (p *identity) PublicKey() ci.PubKey {
return p.PubKey
}
package testutil
import "time"
type LatencyConfig struct {
BlockstoreLatency time.Duration
NetworkLatency time.Duration
RoutingLatency time.Duration
}
func (c LatencyConfig) AllInstantaneous() LatencyConfig {
// Could use a zero value but whatever. Consistency of interface
c.NetworkLatency = 0
c.RoutingLatency = 0
c.BlockstoreLatency = 0
return c
}
func (c LatencyConfig) NetworkNYtoSF() LatencyConfig {
c.NetworkLatency = 20 * time.Millisecond
return c
}
func (c LatencyConfig) NetworkIntraDatacenter2014() LatencyConfig {
c.NetworkLatency = 250 * time.Microsecond
return c
}
func (c LatencyConfig) BlockstoreFastSSD2014() LatencyConfig {
const iops = 100000
c.BlockstoreLatency = (1 / iops) * time.Second
return c
}
func (c LatencyConfig) BlockstoreSlowSSD2014() LatencyConfig {
c.BlockstoreLatency = 150 * time.Microsecond
return c
}
func (c LatencyConfig) Blockstore7200RPM() LatencyConfig {
c.BlockstoreLatency = 8 * time.Millisecond
return c
}
func (c LatencyConfig) RoutingSlow() LatencyConfig {
c.RoutingLatency = 200 * time.Millisecond
return c
}
package testutil
import (
"math/rand"
"sync"
"time"
)
var SeededRand *rand.Rand
func init() {
SeededRand = NewSeededRand(time.Now().UTC().UnixNano())
}
func NewSeededRand(seed int64) *rand.Rand {
src := rand.NewSource(seed)
return rand.New(&LockedRandSource{src: src})
}
type LockedRandSource struct {
lk sync.Mutex
src rand.Source
}
func (r *LockedRandSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}
func (r *LockedRandSource) Seed(seed int64) {
r.lk.Lock()
r.src.Seed(seed)
r.lk.Unlock()
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment