prysm-pulse/beacon-chain/p2p/testing/p2p.go
Preston Van Loon 81f868bd48
Regular Sync - First Pass (#3201)
* checkpoint

* checkpoint

* varint prefix for ssz

* move the encoding API around a little bit to support reader writer

* add a simple test for the happy path subscribe

* move wait timeout to testutil

* Add inverted topic mapping

* Add varint prefixing to ssz network encoder

* fix spacing

* fix comments

* fix comments

* make anon methods more clear

* clean up log fields

* move topic mapping, reformat TODOs, get ready for brutal team review

* lint

* lint

* lint

* Update beacon-chain/p2p/gossip_topic_mappings.go

Co-Authored-By: Nishant Das <nishdas93@gmail.com>

* PR feedback

* PR feedback

* PR feedback

* PR feedback

* PR feedback

* Update WORKSPACE

* Update WORKSPACE
2019-08-16 13:13:04 -04:00

129 lines
3.5 KiB
Go

package testing
import (
"bytes"
"context"
"testing"
"time"
"github.com/gogo/protobuf/proto"
bhost "github.com/libp2p/go-libp2p-blankhost"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/protocol"
pubsub "github.com/libp2p/go-libp2p-pubsub"
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
)
var _ = p2p.P2P(&TestP2P{})
// TestP2P represents a p2p implementation that can be used for testing.
type TestP2P struct {
t *testing.T
host host.Host
pubsub *pubsub.PubSub
}
// NewTestP2P initializes a new p2p test service.
func NewTestP2P(t *testing.T) *TestP2P {
ctx := context.Background()
h := bhost.NewBlankHost(swarmt.GenSwarm(t, ctx))
ps, err := pubsub.NewFloodSub(ctx, h,
pubsub.WithMessageSigning(false),
pubsub.WithStrictSignatureVerification(false),
)
if err != nil {
t.Fatal(err)
}
return &TestP2P{
t: t,
host: h,
pubsub: ps,
}
}
// Connect two test peers together.
func (p *TestP2P) Connect(b *TestP2P) {
if err := connect(p.host, b.host); err != nil {
p.t.Fatal(err)
}
}
func connect(a, b host.Host) error {
pinfo := a.Peerstore().PeerInfo(a.ID())
return b.Connect(context.Background(), pinfo)
}
// ReceiveRPC simulates an incoming RPC.
func (p *TestP2P) ReceiveRPC(topic string, msg proto.Message) {
h := bhost.NewBlankHost(swarmt.GenSwarm(p.t, context.Background()))
if err := connect(h, p.host); err != nil {
p.t.Fatalf("Failed to connect two peers for RPC: %v", err)
}
s, err := h.NewStream(context.Background(), p.host.ID(), protocol.ID(topic+p.Encoding().ProtocolSuffix()))
if err != nil {
p.t.Fatalf("Failed to open stream %v", err)
}
defer s.Close()
n, err := p.Encoding().Encode(s, msg)
if err != nil {
p.t.Fatalf("Failed to encode message: %v", err)
}
p.t.Logf("Wrote %d bytes", n)
}
// ReceivePubSub simulates an incoming message over pubsub on a given topic.
func (p *TestP2P) ReceivePubSub(topic string, msg proto.Message) {
h := bhost.NewBlankHost(swarmt.GenSwarm(p.t, context.Background()))
ps, err := pubsub.NewFloodSub(context.Background(), h,
pubsub.WithMessageSigning(false),
pubsub.WithStrictSignatureVerification(false),
)
if err != nil {
p.t.Fatalf("Failed to create flood sub: %v", err)
}
if err := connect(h, p.host); err != nil {
p.t.Fatalf("Failed to connect two peers for RPC: %v", err)
}
// PubSub requires some delay after connecting for the (*PubSub).processLoop method to
// pick up the newly connected peer.
time.Sleep(time.Millisecond * 100)
buf := new(bytes.Buffer)
if _, err := p.Encoding().Encode(buf, msg); err != nil {
p.t.Fatalf("Failed to encode message: %v", err)
}
if err := ps.Publish(topic+p.Encoding().ProtocolSuffix(), buf.Bytes()); err != nil {
p.t.Fatalf("Failed to publish message; %v", err)
}
}
// Broadcast a message.
func (p *TestP2P) Broadcast(msg proto.Message) {
// TODO(3147): implement
}
// SetStreamHandler for RPC.
func (p *TestP2P) SetStreamHandler(topic string, handler network.StreamHandler) {
p.host.SetStreamHandler(protocol.ID(topic), handler)
}
// Encoding returns ssz encoding.
func (p *TestP2P) Encoding() encoder.NetworkEncoding {
return &encoder.SszNetworkEncoder{}
}
// PubSub returns reference underlying floodsub. This test library uses floodsub
// to ensure all connected peers receive the message.
func (p *TestP2P) PubSub() *pubsub.PubSub {
return p.pubsub
}