10 "github.com/anacrolix/missinggo/pubsub"
11 "github.com/bradfitz/iter"
12 "github.com/stretchr/testify/require"
14 "github.com/anacrolix/torrent/metainfo"
15 pp "github.com/anacrolix/torrent/peer_protocol"
16 "github.com/anacrolix/torrent/storage"
19 // Ensure that no race exists between sending a bitfield, and a subsequent
20 // Have that would potentially alter it.
21 func TestSendBitfieldThenHave(t *testing.T) {
23 config: TestingConfig(),
26 c := cl.newConnection(nil, false, nil, "", "")
27 c.setTorrent(cl.newTorrent(metainfo.Hash{}, nil))
28 c.t.setInfo(&metainfo.Info{
29 Pieces: make([]byte, metainfo.HashSize*3),
34 go c.writer(time.Minute)
36 c.t._completedPieces.Add(1)
37 c.postBitfield( /*[]bool{false, true, false}*/ )
43 n, err := io.ReadFull(r, b)
45 // This will cause connection.writer to terminate.
48 require.NoError(t, err)
49 require.EqualValues(t, 15, n)
50 // Here we see that the bitfield doesn't have piece 2 set, as that should
51 // arrive in the following Have message.
52 require.EqualValues(t, "\x00\x00\x00\x02\x05@\x00\x00\x00\x05\x04\x00\x00\x00\x02", string(b))
55 type torrentStorage struct {
59 func (me *torrentStorage) Close() error { return nil }
61 func (me *torrentStorage) Piece(mp metainfo.Piece) storage.PieceImpl {
65 func (me *torrentStorage) Completion() storage.Completion {
66 return storage.Completion{}
69 func (me *torrentStorage) MarkComplete() error {
73 func (me *torrentStorage) MarkNotComplete() error {
77 func (me *torrentStorage) ReadAt([]byte, int64) (int, error) {
78 panic("shouldn't be called")
81 func (me *torrentStorage) WriteAt(b []byte, _ int64) (int, error) {
82 if len(b) != defaultChunkSize {
89 func BenchmarkConnectionMainReadLoop(b *testing.B) {
91 config: &ClientConfig{
92 DownloadRateLimiter: unlimited,
96 ts := &torrentStorage{}
99 storage: &storage.Torrent{TorrentImpl: ts},
100 pieceStateChanges: pubsub.NewPubSub(),
102 require.NoError(b, t.setInfo(&metainfo.Info{
103 Pieces: make([]byte, 20),
105 PieceLength: 1 << 20,
107 t.setChunkSize(defaultChunkSize)
108 t._pendingPieces.Set(0, PiecePriorityNormal.BitmapPriority())
110 cn := cl.newConnection(r, true, nil, "", "")
112 mrlErr := make(chan error)
115 Piece: make([]byte, defaultChunkSize),
119 err := cn.mainReadLoop()
125 wb := msg.MustMarshalBinary()
126 b.SetBytes(int64(len(msg.Piece)))
130 for range iter.N(b.N) {
132 // The chunk must be written to storage everytime, to ensure the
133 // writeSem is unlocked.
134 t.pieces[0]._dirtyChunks.Clear()
135 cn.validReceiveChunks = map[request]int{newRequestFromMessage(&msg): 1}
137 n, err := w.Write(wb)
138 require.NoError(b, err)
139 require.EqualValues(b, len(wb), n)
143 require.NoError(b, <-mrlErr)
144 require.EqualValues(b, b.N, cn._stats.ChunksReadUseful.Int64())
147 func TestConnPexPeerFlags(t *testing.T) {
149 tcpAddr = &net.TCPAddr{IP: net.IPv6loopback, Port: 4848}
150 udpAddr = &net.UDPAddr{IP: net.IPv6loopback, Port: 4848}
152 var testcases = []struct {
156 {&PeerConn{outgoing: false, PeerPrefersEncryption: false}, 0},
157 {&PeerConn{outgoing: false, PeerPrefersEncryption: true}, pp.PexPrefersEncryption},
158 {&PeerConn{outgoing: true, PeerPrefersEncryption: false}, pp.PexOutgoingConn},
159 {&PeerConn{outgoing: true, PeerPrefersEncryption: true}, pp.PexOutgoingConn | pp.PexPrefersEncryption},
160 {&PeerConn{remoteAddr: udpAddr}, pp.PexSupportsUtp},
161 {&PeerConn{remoteAddr: udpAddr, outgoing: true}, pp.PexOutgoingConn | pp.PexSupportsUtp},
162 {&PeerConn{remoteAddr: tcpAddr, outgoing: true}, pp.PexOutgoingConn},
163 {&PeerConn{remoteAddr: tcpAddr}, 0},
165 for i, tc := range testcases {
166 f := tc.conn.pexPeerFlags()
167 require.EqualValues(t, tc.f, f, i)
171 func TestConnPexEvent(t *testing.T) {
173 udpAddr = &net.UDPAddr{IP: net.IPv6loopback, Port: 4848}
174 tcpAddr = &net.TCPAddr{IP: net.IPv6loopback, Port: 4848}
175 dialTcpAddr = &net.TCPAddr{IP: net.IPv6loopback, Port: 4747}
176 dialUdpAddr = &net.UDPAddr{IP: net.IPv6loopback, Port: 4747}
178 var testcases = []struct {
185 &PeerConn{remoteAddr: udpAddr},
186 pexEvent{pexAdd, udpAddr, pp.PexSupportsUtp},
190 &PeerConn{remoteAddr: tcpAddr, outgoing: true, PeerListenPort: dialTcpAddr.Port},
191 pexEvent{pexDrop, tcpAddr, pp.PexOutgoingConn},
195 &PeerConn{remoteAddr: tcpAddr, PeerListenPort: dialTcpAddr.Port},
196 pexEvent{pexAdd, dialTcpAddr, 0},
200 &PeerConn{remoteAddr: udpAddr, PeerListenPort: dialUdpAddr.Port},
201 pexEvent{pexDrop, dialUdpAddr, pp.PexSupportsUtp},
204 for i, tc := range testcases {
205 e := tc.c.pexEvent(tc.t)
206 require.EqualValues(t, tc.e, e, i)