]> Sergey Matveev's repositories - btrtrc.git/blob - request-strategy/order_test.go
New tests and fixes for them
[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         qt "github.com/frankban/quicktest"
9 )
10
11 func r(i pieceIndex, begin int) Request {
12         return Request{pp.Integer(i), ChunkSpec{pp.Integer(begin), 1}}
13 }
14
15 func chunkIter(offsets ...int) func(func(ChunkSpec)) {
16         return func(f func(ChunkSpec)) {
17                 for _, offset := range offsets {
18                         f(ChunkSpec{pp.Integer(offset), 1})
19                 }
20         }
21 }
22
23 func requestSetFromSlice(rs ...Request) (ret map[Request]struct{}) {
24         ret = make(map[Request]struct{}, len(rs))
25         for _, r := range rs {
26                 ret[r] = struct{}{}
27         }
28         return
29 }
30
31 type intPeerId int
32
33 func (i intPeerId) Uintptr() uintptr {
34         return uintptr(i)
35 }
36
37 func TestStealingFromSlowerPeer(t *testing.T) {
38         c := qt.New(t)
39         order := ClientPieceOrder{}
40         basePeer := Peer{
41                 HasPiece: func(i pieceIndex) bool {
42                         return true
43                 },
44                 MaxRequests:  math.MaxInt16,
45                 DownloadRate: 2,
46         }
47         // Slower than the stealers, but has all requests already.
48         stealee := basePeer
49         stealee.DownloadRate = 1
50         stealee.HasExistingRequest = func(r Request) bool {
51                 return true
52         }
53         stealee.Id = intPeerId(1)
54         firstStealer := basePeer
55         firstStealer.Id = intPeerId(2)
56         secondStealer := basePeer
57         secondStealer.Id = intPeerId(3)
58         results := order.DoRequests([]*Torrent{{
59                 Pieces: []Piece{{
60                         Request:           true,
61                         NumPendingChunks:  5,
62                         IterPendingChunks: chunkIter(0, 1, 2, 3, 4),
63                 }},
64                 Peers: []Peer{
65                         stealee,
66                         firstStealer,
67                         secondStealer,
68                 },
69         }})
70         c.Assert(results, qt.HasLen, 3)
71         check := func(p PeerId, l int) {
72                 c.Check(results[p].Requests, qt.HasLen, l)
73                 c.Check(results[p].Interested, qt.Equals, l > 0)
74         }
75         check(stealee.Id, 1)
76         check(firstStealer.Id, 2)
77         check(secondStealer.Id, 2)
78 }
79
80 func TestStealingFromSlowerPeersBasic(t *testing.T) {
81         c := qt.New(t)
82         order := ClientPieceOrder{}
83         basePeer := Peer{
84                 HasPiece: func(i pieceIndex) bool {
85                         return true
86                 },
87                 MaxRequests:  math.MaxInt16,
88                 DownloadRate: 2,
89         }
90         stealee := basePeer
91         stealee.DownloadRate = 1
92         stealee.HasExistingRequest = func(r Request) bool {
93                 return true
94         }
95         stealee.Id = intPeerId(1)
96         firstStealer := basePeer
97         firstStealer.Id = intPeerId(2)
98         secondStealer := basePeer
99         secondStealer.Id = intPeerId(3)
100         c.Assert(order.DoRequests([]*Torrent{{
101                 Pieces: []Piece{{
102                         Request:           true,
103                         NumPendingChunks:  2,
104                         IterPendingChunks: chunkIter(0, 1),
105                 }},
106                 Peers: []Peer{
107                         stealee,
108                         firstStealer,
109                         secondStealer,
110                 },
111         }}), qt.ContentEquals, map[PeerId]PeerNextRequestState{
112                 intPeerId(2): {
113                         Interested: true,
114                         Requests:   requestSetFromSlice(r(0, 0)),
115                 },
116                 intPeerId(3): {
117                         Interested: true,
118                         Requests:   requestSetFromSlice(r(0, 1)),
119                 },
120                 stealee.Id: {
121                         Interested: false,
122                         Requests:   requestSetFromSlice(),
123                 },
124         })
125 }
126
127 func TestPeerKeepsExistingIfReasonable(t *testing.T) {
128         c := qt.New(t)
129         order := ClientPieceOrder{}
130         basePeer := Peer{
131                 HasPiece: func(i pieceIndex) bool {
132                         return true
133                 },
134                 MaxRequests:  math.MaxInt16,
135                 DownloadRate: 2,
136         }
137         // Slower than the stealers, but has all requests already.
138         stealee := basePeer
139         stealee.DownloadRate = 1
140         keepReq := r(0, 0)
141         stealee.HasExistingRequest = func(r Request) bool {
142                 return r == keepReq
143         }
144         stealee.Id = intPeerId(1)
145         firstStealer := basePeer
146         firstStealer.Id = intPeerId(2)
147         secondStealer := basePeer
148         secondStealer.Id = intPeerId(3)
149         results := order.DoRequests([]*Torrent{{
150                 Pieces: []Piece{{
151                         Request:           true,
152                         NumPendingChunks:  4,
153                         IterPendingChunks: chunkIter(0, 1, 3, 4),
154                 }},
155                 Peers: []Peer{
156                         stealee,
157                         firstStealer,
158                         secondStealer,
159                 },
160         }})
161         c.Assert(results, qt.HasLen, 3)
162         check := func(p PeerId, l int) {
163                 c.Check(results[p].Requests, qt.HasLen, l)
164                 c.Check(results[p].Interested, qt.Equals, l > 0)
165         }
166         check(firstStealer.Id, 2)
167         check(secondStealer.Id, 1)
168         c.Check(results[stealee.Id], qt.ContentEquals, PeerNextRequestState{
169                 Interested: true,
170                 Requests:   requestSetFromSlice(keepReq),
171         })
172 }