10 "github.com/anacrolix/missinggo/pubsub"
11 "github.com/bradfitz/iter"
12 "github.com/stretchr/testify/assert"
13 "github.com/stretchr/testify/require"
15 "github.com/anacrolix/torrent/metainfo"
16 pp "github.com/anacrolix/torrent/peer_protocol"
17 "github.com/anacrolix/torrent/storage"
20 // Ensure that no race exists between sending a bitfield, and a subsequent
21 // Have that would potentially alter it.
22 func TestSendBitfieldThenHave(t *testing.T) {
26 c := cl.newConnection(nil)
27 c.setTorrent(cl.newTorrent(metainfo.Hash{}, nil))
28 c.t.setInfo(&metainfo.Info{
29 Pieces: make([]byte, metainfo.HashSize*3),
33 go c.writer(time.Minute)
35 c.t.completedPieces.Add(1)
36 c.PostBitfield( /*[]bool{false, true, false}*/ )
42 n, err := io.ReadFull(r, b)
44 // This will cause connection.writer to terminate.
47 require.NoError(t, err)
48 require.EqualValues(t, 15, n)
49 // Here we see that the bitfield doesn't have piece 2 set, as that should
50 // arrive in the following Have message.
51 require.EqualValues(t, "\x00\x00\x00\x02\x05@\x00\x00\x00\x05\x04\x00\x00\x00\x02", string(b))
54 type torrentStorage struct {
58 func (me *torrentStorage) Close() error { return nil }
60 func (me *torrentStorage) Piece(mp metainfo.Piece) storage.PieceImpl {
64 func (me *torrentStorage) Completion() storage.Completion {
65 return storage.Completion{}
68 func (me *torrentStorage) MarkComplete() error {
72 func (me *torrentStorage) MarkNotComplete() error {
76 func (me *torrentStorage) ReadAt([]byte, int64) (int, error) {
77 panic("shouldn't be called")
80 func (me *torrentStorage) WriteAt(b []byte, _ int64) (int, error) {
81 if len(b) != defaultChunkSize {
88 func BenchmarkConnectionMainReadLoop(b *testing.B) {
90 downloadLimit: unlimited,
92 ts := &torrentStorage{}
95 storage: &storage.Torrent{ts},
96 pieceStateChanges: pubsub.NewPubSub(),
98 require.NoError(b, t.setInfo(&metainfo.Info{
99 Pieces: make([]byte, 20),
101 PieceLength: 1 << 20,
103 t.setChunkSize(defaultChunkSize)
104 t.pendingPieces.Set(0, PiecePriorityNormal.BitmapPriority())
106 cn := cl.newConnection(r)
108 mrlErr := make(chan error)
111 err := cn.mainReadLoop()
119 Piece: make([]byte, defaultChunkSize),
121 wb, err := msg.MarshalBinary()
122 require.NoError(b, err)
123 b.SetBytes(int64(len(msg.Piece)))
125 for range iter.N(b.N) {
127 t.pieces[0].dirtyChunks.Clear()
129 n, err := w.Write(wb)
130 require.NoError(b, err)
131 require.EqualValues(b, len(wb), n)
135 require.NoError(b, <-mrlErr)
136 require.EqualValues(b, b.N, cn.stats.ChunksReadUseful)
139 func TestConnectionReceiveBadChunkIndex(t *testing.T) {
143 require.False(t, cn.t.haveInfo())
144 assert.NotPanics(t, func() { cn.receiveChunk(&pp.Message{Type: pp.Piece}) })
145 cn.t.info = &metainfo.Info{}
146 require.True(t, cn.t.haveInfo())
147 assert.NotPanics(t, func() { cn.receiveChunk(&pp.Message{Type: pp.Piece}) })