]> Sergey Matveev's repositories - btrtrc.git/blob - request-strategy/order_test.go
Add client-level max unverified bytes
[btrtrc.git] / request-strategy / order_test.go
1 package request_strategy
2
3 import (
4         "math"
5         "testing"
6
7         pp "github.com/anacrolix/torrent/peer_protocol"
8         "github.com/bradfitz/iter"
9         qt "github.com/frankban/quicktest"
10 )
11
12 func r(i pieceIndex, begin int) Request {
13         return Request{pp.Integer(i), ChunkSpec{pp.Integer(begin), 1}}
14 }
15
16 func chunkIterRange(end int) func(func(ChunkSpec)) {
17         return func(f func(ChunkSpec)) {
18                 for offset := range iter.N(end) {
19                         f(ChunkSpec{pp.Integer(offset), 1})
20                 }
21         }
22 }
23
24 func chunkIter(offsets ...int) func(func(ChunkSpec)) {
25         return func(f func(ChunkSpec)) {
26                 for _, offset := range offsets {
27                         f(ChunkSpec{pp.Integer(offset), 1})
28                 }
29         }
30 }
31
32 func requestSetFromSlice(rs ...Request) (ret map[Request]struct{}) {
33         ret = make(map[Request]struct{}, len(rs))
34         for _, r := range rs {
35                 ret[r] = struct{}{}
36         }
37         return
38 }
39
40 type intPeerId int
41
42 func (i intPeerId) Uintptr() uintptr {
43         return uintptr(i)
44 }
45
46 func TestStealingFromSlowerPeer(t *testing.T) {
47         c := qt.New(t)
48         basePeer := Peer{
49                 HasPiece: func(i pieceIndex) bool {
50                         return true
51                 },
52                 MaxRequests:  math.MaxInt16,
53                 DownloadRate: 2,
54         }
55         // Slower than the stealers, but has all requests already.
56         stealee := basePeer
57         stealee.DownloadRate = 1
58         stealee.HasExistingRequest = func(r Request) bool {
59                 return true
60         }
61         stealee.Id = intPeerId(1)
62         firstStealer := basePeer
63         firstStealer.Id = intPeerId(2)
64         secondStealer := basePeer
65         secondStealer.Id = intPeerId(3)
66         results := Run(Input{Torrents: []Torrent{{
67                 Pieces: []Piece{{
68                         Request:           true,
69                         NumPendingChunks:  5,
70                         IterPendingChunks: chunkIterRange(5),
71                 }},
72                 Peers: []Peer{
73                         stealee,
74                         firstStealer,
75                         secondStealer,
76                 },
77         }}})
78
79         c.Assert(results, qt.HasLen, 3)
80         check := func(p PeerId, l int) {
81                 c.Check(results[p].Requests, qt.HasLen, l)
82                 c.Check(results[p].Interested, qt.Equals, l > 0)
83         }
84         check(stealee.Id, 1)
85         check(firstStealer.Id, 2)
86         check(secondStealer.Id, 2)
87 }
88
89 func checkNumRequestsAndInterest(c *qt.C, next PeerNextRequestState, num int, interest bool) {
90         c.Check(next.Requests, qt.HasLen, num)
91         c.Check(next.Interested, qt.Equals, interest)
92 }
93
94 func TestStealingFromSlowerPeersBasic(t *testing.T) {
95         c := qt.New(t)
96         basePeer := Peer{
97                 HasPiece: func(i pieceIndex) bool {
98                         return true
99                 },
100                 MaxRequests:  math.MaxInt16,
101                 DownloadRate: 2,
102         }
103         stealee := basePeer
104         stealee.DownloadRate = 1
105         stealee.HasExistingRequest = func(r Request) bool {
106                 return true
107         }
108         stealee.Id = intPeerId(1)
109         firstStealer := basePeer
110         firstStealer.Id = intPeerId(2)
111         secondStealer := basePeer
112         secondStealer.Id = intPeerId(3)
113         results := Run(Input{Torrents: []Torrent{{
114                 Pieces: []Piece{{
115                         Request:           true,
116                         NumPendingChunks:  2,
117                         IterPendingChunks: chunkIter(0, 1),
118                 }},
119                 Peers: []Peer{
120                         stealee,
121                         firstStealer,
122                         secondStealer,
123                 },
124         }}})
125
126         checkNumRequestsAndInterest(c, results[firstStealer.Id], 1, true)
127         checkNumRequestsAndInterest(c, results[secondStealer.Id], 1, true)
128         checkNumRequestsAndInterest(c, results[stealee.Id], 0, false)
129 }
130
131 func TestPeerKeepsExistingIfReasonable(t *testing.T) {
132         c := qt.New(t)
133         basePeer := Peer{
134                 HasPiece: func(i pieceIndex) bool {
135                         return true
136                 },
137                 MaxRequests:  math.MaxInt16,
138                 DownloadRate: 2,
139         }
140         // Slower than the stealers, but has all requests already.
141         stealee := basePeer
142         stealee.DownloadRate = 1
143         keepReq := r(0, 0)
144         stealee.HasExistingRequest = func(r Request) bool {
145                 return r == keepReq
146         }
147         stealee.Id = intPeerId(1)
148         firstStealer := basePeer
149         firstStealer.Id = intPeerId(2)
150         secondStealer := basePeer
151         secondStealer.Id = intPeerId(3)
152         results := Run(Input{Torrents: []Torrent{{
153                 Pieces: []Piece{{
154                         Request:           true,
155                         NumPendingChunks:  4,
156                         IterPendingChunks: chunkIter(0, 1, 3, 4),
157                 }},
158                 Peers: []Peer{
159                         stealee,
160                         firstStealer,
161                         secondStealer,
162                 },
163         }}})
164
165         c.Assert(results, qt.HasLen, 3)
166         check := func(p PeerId, l int) {
167                 c.Check(results[p].Requests, qt.HasLen, l)
168                 c.Check(results[p].Interested, qt.Equals, l > 0)
169         }
170         check(firstStealer.Id, 2)
171         check(secondStealer.Id, 1)
172         c.Check(results[stealee.Id], qt.ContentEquals, PeerNextRequestState{
173                 Interested: true,
174                 Requests:   requestSetFromSlice(keepReq),
175         })
176 }
177
178 func TestDontStealUnnecessarily(t *testing.T) {
179         c := qt.New(t)
180         basePeer := Peer{
181                 HasPiece: func(i pieceIndex) bool {
182                         return true
183                 },
184                 MaxRequests:  math.MaxInt16,
185                 DownloadRate: 2,
186         }
187         // Slower than the stealers, but has all requests already.
188         stealee := basePeer
189         stealee.DownloadRate = 1
190         keepReqs := requestSetFromSlice(r(0, 0), r(0, 1), r(0, 2))
191         stealee.HasExistingRequest = func(r Request) bool {
192                 _, ok := keepReqs[r]
193                 return ok
194         }
195         stealee.Id = intPeerId(1)
196         firstStealer := basePeer
197         firstStealer.Id = intPeerId(2)
198         secondStealer := basePeer
199         secondStealer.Id = intPeerId(3)
200         results := Run(Input{Torrents: []Torrent{{
201                 Pieces: []Piece{{
202                         Request:           true,
203                         NumPendingChunks:  9,
204                         IterPendingChunks: chunkIterRange(9),
205                 }},
206                 Peers: []Peer{
207                         firstStealer,
208                         stealee,
209                         secondStealer,
210                 },
211         }}})
212
213         c.Assert(results, qt.HasLen, 3)
214         check := func(p PeerId, l int) {
215                 c.Check(results[p].Requests, qt.HasLen, l)
216                 c.Check(results[p].Interested, qt.Equals, l > 0)
217         }
218         check(firstStealer.Id, 3)
219         check(secondStealer.Id, 3)
220         c.Check(results[stealee.Id], qt.ContentEquals, PeerNextRequestState{
221                 Interested: true,
222                 Requests:   keepReqs,
223         })
224 }