swarm/netowrk/stream: create client on first offered hashes msg

Store client init params in a dedicated Peer map and construct
client only on the first offered hashes message.

Update tests and fix issues with shared variables in testClient
This commit is contained in:
Janos Guljas 2018-02-13 17:21:46 +01:00
parent 6807d4d2ed
commit afe2f02efc
5 changed files with 322 additions and 138 deletions

View file

@ -174,9 +174,8 @@ func TestStreamerUpstreamRetrieveRequestMsgExchange(t *testing.T) {
Hashes: hash, Hashes: hash,
From: 0, From: 0,
// TODO: why is this 32??? // TODO: why is this 32???
To: 32, To: 32,
Stream: NewStream(swarmChunkServerStreamName, nil, false), Stream: NewStream(swarmChunkServerStreamName, nil, false),
Initial: true,
}, },
Peer: peerID, Peer: peerID,
}, },

View file

@ -23,7 +23,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
bv "github.com/ethereum/go-ethereum/swarm/network/bitvector" bv "github.com/ethereum/go-ethereum/swarm/network/bitvector"
"github.com/ethereum/go-ethereum/swarm/network/stream/intervals"
"github.com/ethereum/go-ethereum/swarm/storage" "github.com/ethereum/go-ethereum/swarm/storage"
) )
@ -58,8 +57,8 @@ func (s Stream) String() string {
// SubcribeMsg is the protocol msg for requesting a stream(section) // SubcribeMsg is the protocol msg for requesting a stream(section)
type SubscribeMsg struct { type SubscribeMsg struct {
Stream Stream Stream Stream
History *Range History *Range `rlp:"nil"`
Priority uint8 // delivered on priority channel Priority uint8 // delivered on priority channel
} }
func (p *Peer) handleSubscribeMsg(req *SubscribeMsg) (err error) { func (p *Peer) handleSubscribeMsg(req *SubscribeMsg) (err error) {
@ -97,7 +96,7 @@ func (p *Peer) handleSubscribeMsg(req *SubscribeMsg) (err error) {
} }
go func() { go func() {
if err := p.SendOfferedHashes(os, from, to, true); err != nil { if err := p.SendOfferedHashes(os, from, to); err != nil {
p.Drop(err) p.Drop(err)
} }
}() }()
@ -108,18 +107,13 @@ func (p *Peer) handleSubscribeMsg(req *SubscribeMsg) (err error) {
if err != nil { if err != nil {
return err return err
} }
historyStream := NewStream(req.Stream.Name, req.Stream.Key, false)
priority := req.Priority os, err := p.setServer(getHistoryStream(req.Stream), s, getHistoryPriority(req.Priority))
if priority > 0 {
// decrement history stream priority
priority--
}
os, err := p.setServer(historyStream, s, priority)
if err != nil { if err != nil {
return err return err
} }
go func() { go func() {
if err := p.SendOfferedHashes(os, req.History.From, req.History.To, true); err != nil { if err := p.SendOfferedHashes(os, req.History.From, req.History.To); err != nil {
p.Drop(err) p.Drop(err)
} }
}() }()
@ -151,8 +145,7 @@ type OfferedHashesMsg struct {
Stream Stream // name of Stream Stream Stream // name of Stream
From, To uint64 // peer and db-specific entry count From, To uint64 // peer and db-specific entry count
Hashes []byte // stream of hashes (128) Hashes []byte // stream of hashes (128)
Initial bool *HandoverProof // HandoverProof
*HandoverProof // HandoverProof
} }
// String pretty prints OfferedHashesMsg // String pretty prints OfferedHashesMsg
@ -163,7 +156,7 @@ func (m OfferedHashesMsg) String() string {
// handleOfferedHashesMsg protocol msg handler calls the incoming streamer interface // handleOfferedHashesMsg protocol msg handler calls the incoming streamer interface
// Filter method // Filter method
func (p *Peer) handleOfferedHashesMsg(req *OfferedHashesMsg) error { func (p *Peer) handleOfferedHashesMsg(req *OfferedHashesMsg) error {
c, err := p.getClient(req.Stream) c, _, err := p.getOrSetClient(req.Stream, req.From, req.To)
if err != nil { if err != nil {
return err return err
} }
@ -207,12 +200,6 @@ func (p *Peer) handleOfferedHashesMsg(req *OfferedHashesMsg) error {
// except // except
if c.stream.Live { if c.stream.Live {
c.sessionAt = req.From c.sessionAt = req.From
if req.Initial {
// create initial intervals for live stream starting from the first From value
if err := c.intervalsStore.Put(peerStreamIntervalsKey(p, req.Stream), intervals.NewIntervals(req.From)); err != nil {
return err
}
}
} }
from, to := c.nextBatch(req.To) from, to := c.nextBatch(req.To)
log.Trace("received offered batch", "peer", p.ID(), "stream", req.Stream, "from", req.From, "to", req.To) log.Trace("received offered batch", "peer", p.ID(), "stream", req.Stream, "from", req.From, "to", req.To)
@ -271,7 +258,7 @@ func (p *Peer) handleWantedHashesMsg(req *WantedHashesMsg) error {
hashes := s.currentBatch hashes := s.currentBatch
// launch in go routine since GetBatch blocks until new hashes arrive // launch in go routine since GetBatch blocks until new hashes arrive
go func() { go func() {
if err := p.SendOfferedHashes(s, req.From, req.To, false); err != nil { if err := p.SendOfferedHashes(s, req.From, req.To); err != nil {
p.Drop(err) p.Drop(err)
} }
}() }()

View file

@ -33,31 +33,38 @@ import (
var sendTimeout = 5 * time.Second var sendTimeout = 5 * time.Second
var ( var (
errServerNotFound = errors.New("server not found") errServerNotFound = errors.New("server not found")
errClientNotFound = errors.New("client not found") errClientNotFound = errors.New("client not found")
errClientParamsNotFound = errors.New("client params not found")
) )
// Peer is the Peer extention for the streaming protocol // Peer is the Peer extention for the streaming protocol
type Peer struct { type Peer struct {
*protocols.Peer *protocols.Peer
streamer *Registry streamer *Registry
pq *pq.PriorityQueue pq *pq.PriorityQueue
serverMu sync.RWMutex serverMu sync.RWMutex
clientMu sync.RWMutex clientMu sync.RWMutex
servers map[string]*server clientParamsMu sync.RWMutex
clients map[string]*client servers map[string]*server
quit chan struct{} clients map[string]*client
// clientParams map keeps required client arguments
// that are set on Registry.Subscribe and used
// on creating a new client in offered hashes handler.
clientParams map[string]*clientParams
quit chan struct{}
} }
// NewPeer is the constructor for Peer // NewPeer is the constructor for Peer
func NewPeer(peer *protocols.Peer, streamer *Registry) *Peer { func NewPeer(peer *protocols.Peer, streamer *Registry) *Peer {
p := &Peer{ p := &Peer{
Peer: peer, Peer: peer,
pq: pq.New(int(PriorityQueue), PriorityQueueCap), pq: pq.New(int(PriorityQueue), PriorityQueueCap),
streamer: streamer, streamer: streamer,
servers: make(map[string]*server), servers: make(map[string]*server),
clients: make(map[string]*client), clients: make(map[string]*client),
quit: make(chan struct{}), clientParams: make(map[string]*clientParams),
quit: make(chan struct{}),
} }
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
go p.pq.Run(ctx, func(i interface{}) { p.Send(i) }) go p.pq.Run(ctx, func(i interface{}) { p.Send(i) })
@ -85,7 +92,7 @@ func (p *Peer) SendPriority(msg interface{}, priority uint8) error {
} }
// SendOfferedHashes sends OfferedHashesMsg protocol msg // SendOfferedHashes sends OfferedHashesMsg protocol msg
func (p *Peer) SendOfferedHashes(s *server, f, t uint64, initial bool) error { func (p *Peer) SendOfferedHashes(s *server, f, t uint64) error {
hashes, from, to, proof, err := s.SetNextBatch(f, t) hashes, from, to, proof, err := s.SetNextBatch(f, t)
if err != nil { if err != nil {
return err return err
@ -106,7 +113,6 @@ func (p *Peer) SendOfferedHashes(s *server, f, t uint64, initial bool) error {
From: from, From: from,
To: to, To: to,
Stream: s.stream, Stream: s.stream,
Initial: initial,
} }
log.Trace("Swarm syncer offer batch", "peer", p.ID(), "stream", s.stream, "len", len(hashes), "from", from, "to", to) log.Trace("Swarm syncer offer batch", "peer", p.ID(), "stream", s.stream, "len", len(hashes), "from", from, "to", to)
return p.SendPriority(msg, s.priority) return p.SendPriority(msg, s.priority)
@ -123,17 +129,6 @@ func (p *Peer) getServer(s Stream) (*server, error) {
return server, nil return server, nil
} }
func (p *Peer) getClient(s Stream) (*client, error) {
p.clientMu.RLock()
defer p.clientMu.RUnlock()
client := p.clients[s.String()]
if client == nil {
return nil, fmt.Errorf("client '%v' not provided to peer %v", s, p.ID())
}
return client, nil
}
func (p *Peer) setServer(s Stream, o Server, priority uint8) (*server, error) { func (p *Peer) setServer(s Stream, o Server, priority uint8) (*server, error) {
p.serverMu.Lock() p.serverMu.Lock()
defer p.serverMu.Unlock() defer p.serverMu.Unlock()
@ -165,7 +160,18 @@ func (p *Peer) removeServer(s Stream) error {
return nil return nil
} }
func (p *Peer) setClient(s Stream, i Client, priority uint8, intervalsStore intervals.Store) error { func (p *Peer) getClient(s Stream) (*client, error) {
p.clientMu.RLock()
defer p.clientMu.RUnlock()
client := p.clients[s.String()]
if client == nil {
return nil, fmt.Errorf("client '%v' not provided to peer %v", s, p.ID())
}
return client, nil
}
func (p *Peer) setClient(s Stream, from, to uint64) error {
p.clientMu.Lock() p.clientMu.Lock()
defer p.clientMu.Unlock() defer p.clientMu.Unlock()
@ -174,18 +180,45 @@ func (p *Peer) setClient(s Stream, i Client, priority uint8, intervalsStore inte
return fmt.Errorf("client %v already registered", sk) return fmt.Errorf("client %v already registered", sk)
} }
_, err := p.setClientNolock(s, from, to)
return err
}
func (p *Peer) setClientNolock(s Stream, from, to uint64) (c *client, err error) {
f, err := p.streamer.GetClientFunc(s.Name)
if err != nil {
return nil, err
}
is, err := f(p, s.Key, s.Live)
if err != nil {
return nil, err
}
cp, err := p.getClientParams(s)
if err != nil {
return nil, err
}
defer func() {
if err == nil {
if err := p.removeClientParams(s); err != nil {
log.Error("stream set client: remove client params", "stream", s, "peer", p, "err", err)
}
}
}()
intervalsKey := peerStreamIntervalsKey(p, s) intervalsKey := peerStreamIntervalsKey(p, s)
if s.Live { if s.Live {
// try to find previous history and live intervals and merge live into history // try to find previous history and live intervals and merge live into history
historyKey := peerStreamIntervalsKey(p, NewStream(s.Name, s.Key, false)) historyKey := peerStreamIntervalsKey(p, NewStream(s.Name, s.Key, false))
historyIntervals, err := intervalsStore.Get(historyKey) historyIntervals, err := p.streamer.intervalsStore.Get(historyKey)
switch err { switch err {
case nil: case nil:
liveIntervals, err := intervalsStore.Get(intervalsKey) liveIntervals, err := p.streamer.intervalsStore.Get(intervalsKey)
switch err { switch err {
case nil: case nil:
historyIntervals.Merge(liveIntervals) historyIntervals.Merge(liveIntervals)
if err := intervalsStore.Put(historyKey, historyIntervals); err != nil { if err := p.streamer.intervalsStore.Put(historyKey, historyIntervals); err != nil {
log.Error("stream set client: put history intervals", "stream", s, "peer", p, "err", err) log.Error("stream set client: put history intervals", "stream", s, "peer", p, "err", err)
} }
case intervals.ErrNotFound: case intervals.ErrNotFound:
@ -196,25 +229,40 @@ func (p *Peer) setClient(s Stream, i Client, priority uint8, intervalsStore inte
default: default:
log.Error("stream set client: get history intervals", "stream", s, "peer", p, "err", err) log.Error("stream set client: get history intervals", "stream", s, "peer", p, "err", err)
} }
} else { }
// create intervals for history stream
// live stream can create intervals when the first sessionAt is known if err := p.streamer.intervalsStore.Put(intervalsKey, intervals.NewIntervals(from)); err != nil {
if err := intervalsStore.Put(intervalsKey, intervals.NewIntervals(0)); err != nil { return nil, err
return err
}
} }
next := make(chan error, 1) next := make(chan error, 1)
p.clients[sk] = &client{ c = &client{
Client: i, Client: is,
stream: s, stream: s,
priority: priority, priority: cp.priority,
next: next, next: next,
intervalsStore: intervalsStore, intervalsStore: p.streamer.intervalsStore,
intervalsKey: intervalsKey, intervalsKey: intervalsKey,
} }
p.clients[s.String()] = c
next <- nil // this is to allow wantedKeysMsg before first batch arrives next <- nil // this is to allow wantedKeysMsg before first batch arrives
return nil return c, nil
}
func (p *Peer) getOrSetClient(s Stream, from, to uint64) (c *client, created bool, err error) {
p.clientMu.RLock()
defer p.clientMu.RUnlock()
c = p.clients[s.String()]
if c != nil {
return c, false, nil
}
c, err = p.setClientNolock(s, from, to)
if err != nil {
return nil, false, err
}
return c, true, nil
} }
func (p *Peer) removeClient(s Stream) error { func (p *Peer) removeClient(s Stream) error {
@ -229,6 +277,42 @@ func (p *Peer) removeClient(s Stream) error {
return nil return nil
} }
func (p *Peer) getClientParams(s Stream) (*clientParams, error) {
p.clientParamsMu.RLock()
defer p.clientParamsMu.RUnlock()
params := p.clientParams[s.String()]
if params == nil {
return nil, fmt.Errorf("client params '%v' not provided to peer %v", s, p.ID())
}
return params, nil
}
func (p *Peer) setClientParams(s Stream, params *clientParams) error {
p.clientParamsMu.Lock()
defer p.clientParamsMu.Unlock()
sk := s.String()
if p.clientParams[sk] != nil {
return fmt.Errorf("client params %v already set", sk)
}
p.clientParams[sk] = params
return nil
}
func (p *Peer) removeClientParams(s Stream) error {
p.clientParamsMu.Lock()
defer p.clientParamsMu.Unlock()
sk := s.String()
_, ok := p.clientParams[sk]
if !ok {
return errClientParamsNotFound
}
delete(p.clientParams, sk)
return nil
}
func (p *Peer) close() { func (p *Peer) close() {
for _, s := range p.servers { for _, s := range p.servers {
s.Close() s.Close()

View file

@ -125,8 +125,8 @@ func (r *Registry) GetServerFunc(stream string) (func(*Peer, []byte, bool) (Serv
// Subscribe initiates the streamer // Subscribe initiates the streamer
func (r *Registry) Subscribe(peerId discover.NodeID, s Stream, h *Range, priority uint8) error { func (r *Registry) Subscribe(peerId discover.NodeID, s Stream, h *Range, priority uint8) error {
f, err := r.GetClientFunc(s.Name) // check if the stream is registered
if err != nil { if _, err := r.GetClientFunc(s.Name); err != nil {
return err return err
} }
@ -135,27 +135,18 @@ func (r *Registry) Subscribe(peerId discover.NodeID, s Stream, h *Range, priorit
return fmt.Errorf("peer not found %v", peerId) return fmt.Errorf("peer not found %v", peerId)
} }
is, err := f(peer, s.Key, s.Live) err := peer.setClientParams(s, &clientParams{priority: priority})
if err != nil {
return err
}
err = peer.setClient(s, is, priority, r.intervalsStore)
if err != nil { if err != nil {
return err return err
} }
if s.Live && h != nil { if s.Live && h != nil {
is, err := f(peer, s.Key, false) if err := peer.setClientParams(
if err != nil { getHistoryStream(s),
return err &clientParams{
} priority: getHistoryPriority(priority),
p := priority },
if p > 0 { ); err != nil {
p--
}
historyStream := NewStream(s.Name, s.Key, false)
err = peer.setClient(historyStream, is, p, r.intervalsStore)
if err != nil {
return err return err
} }
} }
@ -367,6 +358,12 @@ func (c *client) close() {
c.Close() c.Close()
} }
// clientParams store parameters for the new client
// between a subscription and initial offered hashes request handling.
type clientParams struct {
priority uint8
}
// Spec is the spec of the streamer protocol // Spec is the spec of the streamer protocol
var Spec = &protocols.Spec{ var Spec = &protocols.Spec{
Name: "stream", Name: "stream",
@ -422,6 +419,17 @@ type Range struct {
From, To uint64 From, To uint64
} }
func getHistoryPriority(priority uint8) uint8 {
if priority == 0 {
return 0
}
return priority - 1
}
func getHistoryStream(s Stream) Stream {
return NewStream(s.Name, s.Key, false)
}
type API struct { type API struct {
streamer *Registry streamer *Registry
dpa *storage.DPA dpa *storage.DPA

View file

@ -40,41 +40,57 @@ func TestStreamerSubscribe(t *testing.T) {
} }
var ( var (
hash0 = sha3.Sum256([]byte{0}) hash0 = sha3.Sum256([]byte{0})
hash1 = sha3.Sum256([]byte{1}) hash1 = sha3.Sum256([]byte{1})
hash2 = sha3.Sum256([]byte{2}) hash2 = sha3.Sum256([]byte{2})
hashesTmp = append(hash0[:], hash1[:]...) hashesTmp = append(hash0[:], hash1[:]...)
hashes = append(hashesTmp, hash2[:]...) hashes = append(hashesTmp, hash2[:]...)
receivedHashes map[string][]byte = make(map[string][]byte)
wait0 = make(chan bool)
wait2 = make(chan bool)
batchDone = make(chan bool)
) )
type testClient struct { type testClient struct {
t []byte t []byte
wait0 chan bool
wait2 chan bool
batchDone chan bool
receivedHashes map[string][]byte
}
func newTestClient(t []byte) *testClient {
return &testClient{
t: t,
wait0: make(chan bool),
wait2: make(chan bool),
batchDone: make(chan bool),
receivedHashes: make(map[string][]byte),
}
} }
type testServer struct { type testServer struct {
t []byte t []byte
} }
func newTestServer(t []byte) *testServer {
return &testServer{
t: t,
}
}
func (self *testClient) NeedData(hash []byte) func() { func (self *testClient) NeedData(hash []byte) func() {
receivedHashes[string(hash)] = hash self.receivedHashes[string(hash)] = hash
if bytes.Equal(hash, hash0[:]) { if bytes.Equal(hash, hash0[:]) {
return func() { return func() {
<-wait0 <-self.wait0
} }
} else if bytes.Equal(hash, hash2[:]) { } else if bytes.Equal(hash, hash2[:]) {
return func() { return func() {
<-wait2 <-self.wait2
} }
} }
return nil return nil
} }
func (self *testClient) BatchDone(Stream, uint64, []byte, []byte) func() (*TakeoverProof, error) { func (self *testClient) BatchDone(Stream, uint64, []byte, []byte) func() (*TakeoverProof, error) {
close(batchDone) close(self.batchDone)
return nil return nil
} }
@ -99,9 +115,7 @@ func TestStreamerDownstreamSubscribeUnsubscribeMsgExchange(t *testing.T) {
} }
streamer.RegisterClientFunc("foo", func(p *Peer, t []byte, live bool) (Client, error) { streamer.RegisterClientFunc("foo", func(p *Peer, t []byte, live bool) (Client, error) {
return &testClient{ return newTestClient(t), nil
t: t,
}, nil
}) })
peerID := tester.IDs[0] peerID := tester.IDs[0]
@ -112,24 +126,56 @@ func TestStreamerDownstreamSubscribeUnsubscribeMsgExchange(t *testing.T) {
t.Fatalf("Expected no error, got %v", err) t.Fatalf("Expected no error, got %v", err)
} }
err = tester.TestExchanges(p2ptest.Exchange{ err = tester.TestExchanges(
Label: "Subscribe message", p2ptest.Exchange{
Expects: []p2ptest.Expect{ Label: "Subscribe message",
p2ptest.Expect{ Expects: []p2ptest.Expect{
Code: 4, {
Msg: &SubscribeMsg{ Code: 4,
Stream: stream, Msg: &SubscribeMsg{
History: &Range{ Stream: stream,
From: 5, History: &Range{
To: 8, From: 5,
To: 8,
},
Priority: Top,
}, },
Priority: Top, Peer: peerID,
}, },
Peer: peerID,
}, },
}, },
}) // trigger OfferedHashesMsg to actually create the client
p2ptest.Exchange{
Label: "OfferedHashes message",
Triggers: []p2ptest.Trigger{
{
Code: 1,
Msg: &OfferedHashesMsg{
HandoverProof: &HandoverProof{
Handover: &Handover{},
},
Hashes: hashes,
From: 5,
To: 8,
Stream: stream,
},
Peer: peerID,
},
},
Expects: []p2ptest.Expect{
{
Code: 2,
Msg: &WantedHashesMsg{
Stream: stream,
Want: []byte{5},
From: 8,
To: 0,
},
Peer: peerID,
},
},
},
)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -167,9 +213,7 @@ func TestStreamerUpstreamSubscribeUnsubscribeMsgExchange(t *testing.T) {
stream := NewStream("foo", nil, false) stream := NewStream("foo", nil, false)
streamer.RegisterServerFunc("foo", func(p *Peer, t []byte, live bool) (Server, error) { streamer.RegisterServerFunc("foo", func(p *Peer, t []byte, live bool) (Server, error) {
return &testServer{ return newTestServer(t), nil
t: t,
}, nil
}) })
peerID := tester.IDs[0] peerID := tester.IDs[0]
@ -198,10 +242,9 @@ func TestStreamerUpstreamSubscribeUnsubscribeMsgExchange(t *testing.T) {
HandoverProof: &HandoverProof{ HandoverProof: &HandoverProof{
Handover: &Handover{}, Handover: &Handover{},
}, },
Hashes: make([]byte, HashSize), Hashes: make([]byte, HashSize),
From: 6, From: 6,
To: 9, To: 9,
Initial: true,
}, },
Peer: peerID, Peer: peerID,
}, },
@ -230,6 +273,72 @@ func TestStreamerUpstreamSubscribeUnsubscribeMsgExchange(t *testing.T) {
} }
} }
func TestStreamerUpstreamSubscribeUnsubscribeMsgExchangeLive(t *testing.T) {
tester, streamer, _, teardown, err := newStreamerTester(t)
defer teardown()
if err != nil {
t.Fatal(err)
}
stream := NewStream("foo", nil, true)
streamer.RegisterServerFunc("foo", func(p *Peer, t []byte, live bool) (Server, error) {
return newTestServer(t), nil
})
peerID := tester.IDs[0]
err = tester.TestExchanges(p2ptest.Exchange{
Label: "Subscribe message",
Triggers: []p2ptest.Trigger{
{
Code: 4,
Msg: &SubscribeMsg{
Stream: stream,
Priority: Top,
},
Peer: peerID,
},
},
Expects: []p2ptest.Expect{
{
Code: 1,
Msg: &OfferedHashesMsg{
Stream: stream,
HandoverProof: &HandoverProof{
Handover: &Handover{},
},
Hashes: make([]byte, HashSize),
From: 1,
To: 1,
},
Peer: peerID,
},
},
})
if err != nil {
t.Fatal(err)
}
err = tester.TestExchanges(p2ptest.Exchange{
Label: "unsubscribe message",
Triggers: []p2ptest.Trigger{
{
Code: 0,
Msg: &UnsubscribeMsg{
Stream: stream,
},
Peer: peerID,
},
},
})
if err != nil {
t.Fatal(err)
}
}
func TestStreamerUpstreamSubscribeErrorMsgExchange(t *testing.T) { func TestStreamerUpstreamSubscribeErrorMsgExchange(t *testing.T) {
tester, streamer, _, teardown, err := newStreamerTester(t) tester, streamer, _, teardown, err := newStreamerTester(t)
defer teardown() defer teardown()
@ -238,9 +347,7 @@ func TestStreamerUpstreamSubscribeErrorMsgExchange(t *testing.T) {
} }
streamer.RegisterServerFunc("foo", func(p *Peer, t []byte, live bool) (Server, error) { streamer.RegisterServerFunc("foo", func(p *Peer, t []byte, live bool) (Server, error) {
return &testServer{ return newTestServer(t), nil
t: t,
}, nil
}) })
stream := NewStream("bar", nil, true) stream := NewStream("bar", nil, true)
@ -325,7 +432,6 @@ func TestStreamerUpstreamSubscribeErrorMsgExchange(t *testing.T) {
// Hashes: make([]byte, HashSize), // Hashes: make([]byte, HashSize),
// From: 6, // From: 6,
// To: 9, // To: 9,
// Initial: true,
// }, // },
// Peer: peerID, // Peer: peerID,
// }, // },
@ -339,7 +445,6 @@ func TestStreamerUpstreamSubscribeErrorMsgExchange(t *testing.T) {
// From: 1, // From: 1,
// To: 1, // To: 1,
// Hashes: make([]byte, HashSize), // Hashes: make([]byte, HashSize),
// Initial: true,
// }, // },
// Peer: peerID, // Peer: peerID,
// }, // },
@ -360,10 +465,11 @@ func TestStreamerDownstreamOfferedHashesMsgExchange(t *testing.T) {
stream := NewStream("foo", nil, true) stream := NewStream("foo", nil, true)
var tc *testClient
streamer.RegisterClientFunc("foo", func(p *Peer, t []byte, live bool) (Client, error) { streamer.RegisterClientFunc("foo", func(p *Peer, t []byte, live bool) (Client, error) {
return &testClient{ tc = newTestClient(t)
t: t, return tc, nil
}, nil
}) })
peerID := tester.IDs[0] peerID := tester.IDs[0]
@ -424,28 +530,28 @@ func TestStreamerDownstreamOfferedHashesMsgExchange(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if len(receivedHashes) != 3 { if len(tc.receivedHashes) != 3 {
t.Fatalf("Expected number of received hashes %v, got %v", 3, len(receivedHashes)) t.Fatalf("Expected number of received hashes %v, got %v", 3, len(tc.receivedHashes))
} }
close(wait0) close(tc.wait0)
timeout := time.NewTimer(100 * time.Millisecond) timeout := time.NewTimer(100 * time.Millisecond)
defer timeout.Stop() defer timeout.Stop()
select { select {
case <-batchDone: case <-tc.batchDone:
t.Fatal("batch done early") t.Fatal("batch done early")
case <-timeout.C: case <-timeout.C:
} }
close(wait2) close(tc.wait2)
timeout2 := time.NewTimer(10000 * time.Millisecond) timeout2 := time.NewTimer(10000 * time.Millisecond)
defer timeout2.Stop() defer timeout2.Stop()
select { select {
case <-batchDone: case <-tc.batchDone:
case <-timeout2.C: case <-timeout2.C:
t.Fatal("timeout waiting batchdone call") t.Fatal("timeout waiting batchdone call")
} }