3 Copyright (c) 2008, Arvid Norberg
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #include "libtorrent/piece_picker.hpp"
34 #include "libtorrent/policy.hpp"
35 #include "libtorrent/bitfield.hpp"
36 #include <boost/shared_ptr.hpp>
37 #include <boost/bind.hpp>
44 using namespace libtorrent
;
46 const int blocks_per_piece
= 4;
48 bitfield
string2vec(char const* have_str
)
50 const int num_pieces
= strlen(have_str
);
51 bitfield
have(num_pieces
, false);
52 for (int i
= 0; i
< num_pieces
; ++i
)
53 if (have_str
[i
] != ' ') have
.set_bit(i
);
57 // availability is a string where each character is the
58 // availability of that piece, '1', '2' etc.
59 // have_str is a string where each character represents a
60 // piece, ' ' means we don't have the piece and any other
61 // character means we have it
62 boost::shared_ptr
<piece_picker
> setup_picker(
63 char const* availability
64 , char const* have_str
65 , char const* priority
66 , char const* partial
)
68 const int num_pieces
= strlen(availability
);
69 assert(int(strlen(have_str
)) == num_pieces
);
71 boost::shared_ptr
<piece_picker
> p(new piece_picker
);
72 p
->init(blocks_per_piece
, num_pieces
* blocks_per_piece
);
74 bitfield have
= string2vec(have_str
);
76 for (int i
= 0; i
< num_pieces
; ++i
)
78 if (partial
[i
] == 0) break;
80 if (partial
[i
] == ' ') continue;
83 if (partial
[i
] >= '0' && partial
[i
] <= '9')
84 blocks
= partial
[i
] - '0';
86 blocks
= partial
[i
] - 'a' + 10;
92 p
->mark_as_finished(piece_block(i
, 0), 0);
97 p
->mark_as_finished(piece_block(i
, 1), 0);
102 p
->mark_as_finished(piece_block(i
, 2), 0);
107 p
->mark_as_finished(piece_block(i
, 3), 0);
110 piece_picker::downloading_piece st
;
111 p
->piece_info(i
, st
);
112 TEST_CHECK(st
.writing
== 0);
113 TEST_CHECK(st
.requested
== 0);
114 TEST_CHECK(st
.index
== i
);
116 TEST_CHECK(st
.finished
== counter
);
119 for (int i
= 0; i
< num_pieces
; ++i
)
121 if (priority
[i
] == 0) break;
122 const int prio
= priority
[i
] - '0';
124 p
->set_piece_priority(i
, prio
);
126 TEST_CHECK(p
->piece_priority(i
) == prio
);
129 for (int i
= 0; i
< num_pieces
; ++i
)
131 if (!have
[i
]) continue;
133 for (int j
= 0; j
< blocks_per_piece
; ++j
)
134 TEST_CHECK(p
->is_finished(piece_block(i
, j
)));
137 for (int i
= 0; i
< num_pieces
; ++i
)
139 const int avail
= availability
[i
] - '0';
142 for (int j
= 0; j
< avail
; ++j
) p
->inc_refcount(i
);
145 std::vector
<int> availability_vec
;
146 p
->get_availability(availability_vec
);
147 for (int i
= 0; i
< num_pieces
; ++i
)
149 const int avail
= availability
[i
] - '0';
151 TEST_CHECK(avail
== availability_vec
[i
]);
155 p
->check_invariant();
160 bool verify_pick(boost::shared_ptr
<piece_picker
> p
161 , std::vector
<piece_block
> const& picked
)
164 p
->check_invariant();
166 for (std::vector
<piece_block
>::const_iterator i
= picked
.begin()
167 , end(picked
.end()); i
!= end
; ++i
)
169 if (p
->num_peers(*i
) > 0) return false;
172 // make sure there are no duplicated
173 std::set
<piece_block
> blocks
;
174 std::copy(picked
.begin(), picked
.end(), std::insert_iterator
<std::set
<piece_block
> >(blocks
, blocks
.end()));
175 return picked
.size() == blocks
.size();
178 void print_pick(std::vector
<piece_block
> const& picked
)
180 for (int i
= 0; i
< int(picked
.size()); ++i
)
182 std::cout
<< "(" << picked
[i
].piece_index
<< ", " << picked
[i
].block_index
<< ") ";
184 std::cout
<< std::endl
;
187 void print_title(char const* name
)
189 std::cerr
<< "==== " << name
<< " ====\n";
192 int test_pick(boost::shared_ptr
<piece_picker
> const& p
)
194 std::vector
<piece_block
> picked
;
195 const std::vector
<int> empty_vector
;
196 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
198 TEST_CHECK(verify_pick(p
, picked
));
199 TEST_CHECK(int(picked
.size()) == 1);
200 return picked
[0].piece_index
;
207 policy::peer
peer_struct(endp
, policy::peer::connectable
, 0);
208 std::vector
<piece_block
> picked
;
209 boost::shared_ptr
<piece_picker
> p
;
210 const std::vector
<int> empty_vector
;
212 // make sure the block that is picked is from piece 1, since it
213 // it is the piece with the lowest availability
214 print_title("test pick lowest availability");
215 p
= setup_picker("2223333", "* * * ", "", "");
217 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
218 TEST_CHECK(verify_pick(p
, picked
));
219 TEST_CHECK(int(picked
.size()) > 0);
220 TEST_CHECK(picked
.front().piece_index
== 1);
222 // ========================================================
224 // make sure the block that is picked is from piece 5, since it
225 // has the highest priority among the available pieces
226 print_title("test pick highest priority");
227 p
= setup_picker("1111111", "* * * ", "1111122", "");
229 p
->pick_pieces(string2vec("****** "), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
230 TEST_CHECK(verify_pick(p
, picked
));
231 TEST_CHECK(int(picked
.size()) > 0);
232 TEST_CHECK(picked
.front().piece_index
== 5);
234 // ========================================================
236 // make sure the 4 blocks are picked from the same piece if
237 // whole pieces are preferred. The only whole piece is 1.
238 print_title("test pick whole pieces");
239 p
= setup_picker("1111111", " ", "1111111", "1023460");
241 p
->pick_pieces(string2vec("****** "), picked
, 1, 1, &peer_struct
, piece_picker::fast
, true, true, empty_vector
);
242 TEST_CHECK(verify_pick(p
, picked
));
243 TEST_CHECK(int(picked
.size()) >= blocks_per_piece
);
244 for (int i
= 0; i
< blocks_per_piece
&& i
< int(picked
.size()); ++i
)
245 TEST_CHECK(picked
[i
].piece_index
== 1);
247 // ========================================================
249 // test the distributed copies function. It should include ourself
250 // in the availability. i.e. piece 0 has availability 2.
251 // there are 2 pieces with availability 2 and 5 with availability 3
252 print_title("test distributed copies");
253 p
= setup_picker("1233333", "* ", "", "");
254 float dc
= p
->distributed_copies();
255 TEST_CHECK(fabs(dc
- (2.f
+ 5.f
/ 7.f
)) < 0.01f
);
257 // ========================================================
259 // make sure filtered pieces are ignored
260 print_title("test filtered pieces");
261 p
= setup_picker("1111111", " ", "0010000", "");
263 p
->pick_pieces(string2vec("*** ** "), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
264 TEST_CHECK(verify_pick(p
, picked
));
265 TEST_CHECK(int(picked
.size()) > 0);
266 TEST_CHECK(picked
.front().piece_index
== 2);
268 // ========================================================
270 // make sure we_dont_have works
271 print_title("test we_dont_have");
272 p
= setup_picker("1111111", "*******", "0100000", "");
276 p
->pick_pieces(string2vec("*** ** "), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
277 TEST_CHECK(verify_pick(p
, picked
));
278 TEST_CHECK(int(picked
.size()) > 0);
279 TEST_CHECK(picked
.front().piece_index
== 1);
281 // ========================================================
283 // make sure requested blocks aren't picked
284 print_title("test don't pick requested blocks");
285 p
= setup_picker("1234567", " ", "", "");
287 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
288 TEST_CHECK(verify_pick(p
, picked
));
289 TEST_CHECK(int(picked
.size()) > 0);
290 TEST_CHECK(picked
.front().piece_index
== 0);
291 piece_block first
= picked
.front();
292 p
->mark_as_downloading(picked
.front(), &peer_struct
, piece_picker::fast
);
293 TEST_CHECK(p
->num_peers(picked
.front()) == 1);
295 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
296 TEST_CHECK(verify_pick(p
, picked
));
297 TEST_CHECK(int(picked
.size()) > 0);
298 TEST_CHECK(picked
.front() != first
);
299 TEST_CHECK(picked
.front().piece_index
== 0);
301 // ========================================================
303 // test sequenced download
304 p = setup_picker("7654321", " ", "", "");
306 p->set_sequenced_download_threshold(3);
307 p->pick_pieces(string2vec("***** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, true, false, empty_vector);
309 TEST_CHECK(verify_pick(p, picked));
310 TEST_CHECK(int(picked.size()) == 5 * blocks_per_piece);
311 for (int i = 0; i < 5 * blocks_per_piece && i < int(picked.size()); ++i)
312 TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
315 p->set_sequenced_download_threshold(4);
316 p->pick_pieces(string2vec("**** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, true, false, empty_vector);
318 TEST_CHECK(verify_pick(p, picked));
319 TEST_CHECK(int(picked.size()) == 4 * blocks_per_piece);
320 for (int i = 0; i < 4 * blocks_per_piece && i < int(picked.size()); ++i)
321 TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
324 p->set_sequenced_download_threshold(2);
325 p->pick_pieces(string2vec("****** "), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true, false, empty_vector);
327 TEST_CHECK(verify_pick(p, picked));
328 TEST_CHECK(int(picked.size()) == 6 * blocks_per_piece);
329 for (int i = 0; i < 6 * blocks_per_piece && i < int(picked.size()); ++i)
330 TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
333 p->set_piece_priority(0, 0);
334 p->pick_pieces(string2vec("****** "), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true, false, empty_vector);
336 TEST_CHECK(verify_pick(p, picked));
337 TEST_CHECK(int(picked.size()) == 5 * blocks_per_piece);
338 for (int i = 0; i < 5 * blocks_per_piece && i < int(picked.size()); ++i)
339 TEST_CHECK(picked[i].piece_index == i / blocks_per_piece + 1);
342 p->set_piece_priority(0, 1);
343 p->pick_pieces(string2vec("****** "), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true, false, empty_vector);
345 TEST_CHECK(verify_pick(p, picked));
346 TEST_CHECK(int(picked.size()) == 6 * blocks_per_piece);
347 for (int i = 0; i < 6 * blocks_per_piece && i < int(picked.size()); ++i)
348 TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
350 // ========================================================
352 // test piece priorities
353 print_title("test piece priorities");
354 p
= setup_picker("5555555", " ", "3214576", "");
355 TEST_CHECK(p
->num_filtered() == 0);
356 TEST_CHECK(p
->num_have_filtered() == 0);
357 p
->set_piece_priority(0, 0);
358 TEST_CHECK(p
->num_filtered() == 1);
359 TEST_CHECK(p
->num_have_filtered() == 0);
360 p
->mark_as_finished(piece_block(0,0), 0);
362 TEST_CHECK(p
->num_filtered() == 0);
363 TEST_CHECK(p
->num_have_filtered() == 1);
366 p
->pick_pieces(string2vec("*******"), picked
, 6 * blocks_per_piece
, false, 0, piece_picker::fast
, true, false, empty_vector
);
368 TEST_CHECK(verify_pick(p
, picked
));
369 TEST_CHECK(int(picked
.size()) == 6 * blocks_per_piece
);
370 TEST_CHECK(picked
[0 * blocks_per_piece
].piece_index
== 5);
371 // priority 5 and 6 is currently the same
372 TEST_CHECK(picked
[1 * blocks_per_piece
].piece_index
== 6 || picked
[1 * blocks_per_piece
].piece_index
== 4);
373 TEST_CHECK(picked
[2 * blocks_per_piece
].piece_index
== 6 || picked
[2 * blocks_per_piece
].piece_index
== 4);
374 TEST_CHECK(picked
[3 * blocks_per_piece
].piece_index
== 3);
375 TEST_CHECK(picked
[4 * blocks_per_piece
].piece_index
== 1);
376 TEST_CHECK(picked
[5 * blocks_per_piece
].piece_index
== 2);
378 std::vector
<int> prios
;
379 p
->piece_priorities(prios
);
380 TEST_CHECK(prios
.size() == 7);
381 int prio_comp
[] = {0, 2, 1, 4, 5, 7, 6};
382 TEST_CHECK(std::equal(prios
.begin(), prios
.end(), prio_comp
));
384 // ========================================================
386 // test restore_piece
387 print_title("test restore piece");
388 p
= setup_picker("1234567", " ", "", "");
389 p
->mark_as_finished(piece_block(0,0), 0);
390 p
->mark_as_finished(piece_block(0,1), 0);
391 p
->mark_as_finished(piece_block(0,2), 0);
392 p
->mark_as_finished(piece_block(0,3), 0);
395 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
397 TEST_CHECK(verify_pick(p
, picked
));
398 TEST_CHECK(int(picked
.size()) >= 1);
399 TEST_CHECK(picked
.front().piece_index
== 1);
403 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
405 TEST_CHECK(verify_pick(p
, picked
));
406 TEST_CHECK(int(picked
.size()) >= 1);
407 TEST_CHECK(picked
.front().piece_index
== 0);
409 p
->mark_as_finished(piece_block(0,0), 0);
410 p
->mark_as_finished(piece_block(0,1), 0);
411 p
->mark_as_finished(piece_block(0,2), 0);
412 p
->mark_as_finished(piece_block(0,3), 0);
413 p
->set_piece_priority(0, 0);
416 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
418 TEST_CHECK(verify_pick(p
, picked
));
419 TEST_CHECK(int(picked
.size()) >= 1);
420 TEST_CHECK(picked
.front().piece_index
== 1);
424 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
426 TEST_CHECK(verify_pick(p
, picked
));
427 TEST_CHECK(int(picked
.size()) >= 1);
428 TEST_CHECK(picked
.front().piece_index
== 1);
430 p
->set_piece_priority(0, 1);
432 p
->pick_pieces(string2vec("*******"), picked
, 1, false, 0, piece_picker::fast
, true, false, empty_vector
);
434 TEST_CHECK(verify_pick(p
, picked
));
435 TEST_CHECK(int(picked
.size()) >= 1);
436 TEST_CHECK(picked
.front().piece_index
== 0);
438 // ========================================================
440 // test non-rarest-first mode
441 print_title("test not rarest first");
442 p
= setup_picker("1234567", "* * * ", "1111122", "");
444 p
->pick_pieces(string2vec("****** "), picked
, 5 * blocks_per_piece
, false, 0, piece_picker::fast
, false, false, empty_vector
);
446 TEST_CHECK(verify_pick(p
, picked
));
447 TEST_CHECK(int(picked
.size()) == 3 * blocks_per_piece
);
449 for (int i
= 0; i
< 4 * blocks_per_piece
&& i
< int(picked
.size()); ++i
)
451 TEST_CHECK(picked
[i
].piece_index
!= 0);
452 TEST_CHECK(picked
[i
].piece_index
!= 2);
453 TEST_CHECK(picked
[i
].piece_index
!= 4);
456 // ========================================================
458 // test have_all and have_none
459 print_title("test have_all and have_none");
460 p
= setup_picker("0123333", "* ", "", "");
461 dc
= p
->distributed_copies();
462 std::cout
<< "distributed copies: " << dc
<< std::endl
;
463 TEST_CHECK(fabs(dc
- (1.f
+ 5.f
/ 7.f
)) < 0.01f
);
464 p
->inc_refcount_all();
465 dc
= p
->distributed_copies();
466 std::cout
<< "distributed copies: " << dc
<< std::endl
;
467 TEST_CHECK(fabs(dc
- (2.f
+ 5.f
/ 7.f
)) < 0.01f
);
468 p
->dec_refcount_all();
469 dc
= p
->distributed_copies();
470 std::cout
<< "distributed copies: " << dc
<< std::endl
;
471 TEST_CHECK(fabs(dc
- (1.f
+ 5.f
/ 7.f
)) < 0.01f
);
473 p
->dec_refcount_all();
474 dc
= p
->distributed_copies();
475 std::cout
<< "distributed copies: " << dc
<< std::endl
;
476 TEST_CHECK(fabs(dc
- (0.f
+ 6.f
/ 7.f
)) < 0.01f
);
477 TEST_CHECK(test_pick(p
) == 2);
479 // ========================================================
481 // test have_all and have_none with sequential download
482 print_title("test have_all and have_none with sequential download");
483 p
= setup_picker("0123333", "* ", "", "");
484 dc
= p
->distributed_copies();
485 std::cout
<< "distributed copies: " << dc
<< std::endl
;
486 TEST_CHECK(fabs(dc
- (1.f
+ 5.f
/ 7.f
)) < 0.01f
);
487 p
->inc_refcount_all();
488 dc
= p
->distributed_copies();
489 std::cout
<< "distributed copies: " << dc
<< std::endl
;
490 TEST_CHECK(fabs(dc
- (2.f
+ 5.f
/ 7.f
)) < 0.01f
);
491 p
->sequential_download(true);
492 p
->dec_refcount_all();
493 dc
= p
->distributed_copies();
494 std::cout
<< "distributed copies: " << dc
<< std::endl
;
495 TEST_CHECK(fabs(dc
- (1.f
+ 5.f
/ 7.f
)) < 0.01f
);
497 p
->dec_refcount_all();
498 dc
= p
->distributed_copies();
499 std::cout
<< "distributed copies: " << dc
<< std::endl
;
500 TEST_CHECK(fabs(dc
- (0.f
+ 6.f
/ 7.f
)) < 0.01f
);
502 TEST_CHECK(test_pick(p
) == 1);
504 // ========================================================
506 // test inc_ref and dec_ref
507 print_title("test inc_ref dec_ref");
508 p
= setup_picker("1233333", " * ", "", "");
509 TEST_CHECK(test_pick(p
) == 0);
512 TEST_CHECK(test_pick(p
) == 1);
516 TEST_CHECK(test_pick(p
) == 4);
518 // decrease refcount on something that's not in the piece list
524 TEST_CHECK(test_pick(p
) == 0);
526 // ========================================================
528 // test have_all and have_none, with a sequenced download threshold
529 p = setup_picker("1233333", "* ", "", "");
530 p->set_sequenced_download_threshold(3);
531 p->inc_refcount_all();
532 dc = p->distributed_copies();
533 TEST_CHECK(fabs(dc - (3.f + 5.f / 7.f)) < 0.01f);
534 p->dec_refcount_all();
535 dc = p->distributed_copies();
536 TEST_CHECK(fabs(dc - (2.f + 5.f / 7.f)) < 0.01f);
538 dc = p->distributed_copies();
539 TEST_CHECK(fabs(dc - (2.f + 4.f / 7.f)) < 0.01f);
540 p->mark_as_downloading(piece_block(1,0), &peer_struct, piece_picker::fast);
541 p->mark_as_downloading(piece_block(1,1), &peer_struct, piece_picker::fast);
543 dc = p->distributed_copies();
544 TEST_CHECK(fabs(dc - (2.f + 5.f / 7.f)) < 0.01f);
546 // make sure it won't pick the piece we just got
547 p->pick_pieces(string2vec(" * ****"), picked, 100, false, 0, piece_picker::fast, true, false, empty_vector);
549 TEST_CHECK(verify_pick(p, picked));
550 TEST_CHECK(int(picked.size()) >= 4 * blocks_per_piece);
551 TEST_CHECK(picked[0 * blocks_per_piece].piece_index == 3);
552 TEST_CHECK(picked[1 * blocks_per_piece].piece_index == 4);
553 TEST_CHECK(picked[2 * blocks_per_piece].piece_index == 5);
554 TEST_CHECK(picked[3 * blocks_per_piece].piece_index == 6);
556 // ========================================================
558 // test unverified_blocks, marking blocks and get_downloader
559 print_title("test unverified blocks");
560 p
= setup_picker("1111111", " ", "", "0300700");
561 TEST_CHECK(p
->unverified_blocks() == 2 + 3);
562 TEST_CHECK(p
->get_downloader(piece_block(4, 0)) == 0);
563 TEST_CHECK(p
->get_downloader(piece_block(4, 1)) == 0);
564 TEST_CHECK(p
->get_downloader(piece_block(4, 2)) == 0);
565 TEST_CHECK(p
->get_downloader(piece_block(4, 3)) == 0);
566 p
->mark_as_downloading(piece_block(4, 3), &peer_struct
, piece_picker::fast
);
567 TEST_CHECK(p
->get_downloader(piece_block(4, 3)) == &peer_struct
);
568 piece_picker::downloading_piece st
;
569 p
->piece_info(4, st
);
570 TEST_CHECK(st
.requested
== 1);
571 TEST_CHECK(st
.writing
== 0);
572 TEST_CHECK(st
.finished
== 3);
573 TEST_CHECK(p
->unverified_blocks() == 2 + 3);
574 p
->mark_as_writing(piece_block(4, 3), &peer_struct
);
575 TEST_CHECK(p
->get_downloader(piece_block(4, 3)) == &peer_struct
);
576 p
->piece_info(4, st
);
577 TEST_CHECK(st
.requested
== 0);
578 TEST_CHECK(st
.writing
== 1);
579 TEST_CHECK(st
.finished
== 3);
580 TEST_CHECK(p
->unverified_blocks() == 2 + 3);
581 p
->mark_as_finished(piece_block(4, 3), &peer_struct
);
582 TEST_CHECK(p
->get_downloader(piece_block(4, 3)) == &peer_struct
);
583 p
->piece_info(4, st
);
584 TEST_CHECK(st
.requested
== 0);
585 TEST_CHECK(st
.writing
== 0);
586 TEST_CHECK(st
.finished
== 4);
587 TEST_CHECK(p
->unverified_blocks() == 2 + 4);
589 p
->piece_info(4, st
);
590 TEST_CHECK(st
.requested
== 0);
591 TEST_CHECK(st
.writing
== 0);
592 TEST_CHECK(st
.finished
== 4);
593 TEST_CHECK(p
->get_downloader(piece_block(4, 3)) == 0);
594 TEST_CHECK(p
->unverified_blocks() == 2);
596 // ========================================================
598 // test prefer_whole_pieces
599 print_title("test prefer whole pieces");
600 p
= setup_picker("1111111", " ", "", "");
602 p
->pick_pieces(string2vec("*******"), picked
, 1, 3, 0, piece_picker::fast
, true, false, empty_vector
);
604 TEST_CHECK(verify_pick(p
, picked
));
605 TEST_CHECK(int(picked
.size()) >= 3 * blocks_per_piece
);
606 piece_block b
= picked
.front();
607 for (int i
= 1; i
< int(picked
.size()); ++i
)
609 TEST_CHECK(picked
[i
].piece_index
* blocks_per_piece
+ picked
[i
].block_index
610 == b
.piece_index
* blocks_per_piece
+ b
.block_index
+ 1);
615 p
->pick_pieces(string2vec("*******"), picked
, 1, 3, 0, piece_picker::fast
, false, false, empty_vector
);
617 TEST_CHECK(verify_pick(p
, picked
));
618 TEST_CHECK(int(picked
.size()) >= 3 * blocks_per_piece
);
620 for (int i
= 1; i
< int(picked
.size()); ++i
)
622 TEST_CHECK(picked
[i
].piece_index
* blocks_per_piece
+ picked
[i
].block_index
623 == b
.piece_index
* blocks_per_piece
+ b
.block_index
+ 1);
627 // ========================================================
630 print_title("test parole mode");
631 p
= setup_picker("3333133", " ", "", "");
632 p
->mark_as_finished(piece_block(0, 0), 0);
634 p
->pick_pieces(string2vec("*******"), picked
, 1, 1, 0, piece_picker::fast
, true, true, empty_vector
);
636 TEST_CHECK(verify_pick(p
, picked
));
637 TEST_CHECK(int(picked
.size()) >= blocks_per_piece
- 1);
638 for (int i
= 1; i
< int(picked
.size()); ++i
)
640 TEST_CHECK(picked
[i
].piece_index
== 0);
641 TEST_CHECK(picked
[i
].block_index
== i
+ 1);
644 // make sure that the partial piece is not picked by a
645 // peer that is has not downloaded/requested the other blocks
647 p
->pick_pieces(string2vec("*******"), picked
, 1, 1, &peer_struct
, piece_picker::fast
, true, true, empty_vector
);
649 TEST_CHECK(int(picked
.size()) >= blocks_per_piece
);
650 for (int i
= 1; i
< int(picked
.size()); ++i
)
652 TEST_CHECK(picked
[i
].piece_index
== 4);
653 TEST_CHECK(picked
[i
].block_index
== i
);
656 // ========================================================
658 // test suggested pieces
659 print_title("test suggested pieces");
660 p
= setup_picker("1111222233334444", " ", "", "");
662 std::vector
<int> suggested_pieces(v
, v
+ 2);
665 p
->pick_pieces(string2vec("****************"), picked
, 1, 1, 0, piece_picker::fast
, true, true, suggested_pieces
);
667 TEST_CHECK(verify_pick(p
, picked
));
668 TEST_CHECK(int(picked
.size()) >= blocks_per_piece
);
669 for (int i
= 1; i
< int(picked
.size()); ++i
)
671 TEST_CHECK(picked
[i
].piece_index
== 1);
672 TEST_CHECK(picked
[i
].block_index
== i
);
674 p
->set_piece_priority(0, 0);
675 p
->set_piece_priority(1, 0);
676 p
->set_piece_priority(2, 0);
677 p
->set_piece_priority(3, 0);
680 p
->pick_pieces(string2vec("****************"), picked
, 1, 1, 0, piece_picker::fast
, true, true, suggested_pieces
);
682 TEST_CHECK(verify_pick(p
, picked
));
683 TEST_CHECK(int(picked
.size()) >= blocks_per_piece
);
684 for (int i
= 1; i
< int(picked
.size()); ++i
)
686 TEST_CHECK(picked
[i
].piece_index
== 5);
687 TEST_CHECK(picked
[i
].block_index
== i
);
690 p
= setup_picker("1111222233334444", "**** ", "", "");
692 p
->pick_pieces(string2vec("****************"), picked
, 1, 1, 0, piece_picker::fast
, true, true, suggested_pieces
);
694 TEST_CHECK(verify_pick(p
, picked
));
695 TEST_CHECK(int(picked
.size()) >= blocks_per_piece
);
696 for (int i
= 1; i
< int(picked
.size()); ++i
)
698 TEST_CHECK(picked
[i
].piece_index
== 5);
699 TEST_CHECK(picked
[i
].block_index
== i
);
703 // 2. inc_ref() from 0 to 1 while sequenced download threshold is 1
704 // 4. filtered_pieces
706 // 6. pick_pieces with prefer whole pieces
709 // 9. get_downloaders
710 // 10. abort_download
714 p.pick_pieces(peer1, picked, 1, false, 0, piece_picker::fast, true);
715 TEST_CHECK(int(picked.size()) == 1);
716 TEST_CHECK(picked.front().piece_index == 2);
718 // now pick a piece from peer2. The block is supposed to be
719 // from piece 3, since it is the rarest piece that peer has.
721 p.pick_pieces(peer2, picked, 1, false, 0, piece_picker::fast, true);
722 TEST_CHECK(int(picked.size()) == 1);
723 TEST_CHECK(picked.front().piece_index == 3);
725 // same thing for peer3.
728 p.pick_pieces(peer3, picked, 1, false, 0, piece_picker::fast, true);
729 TEST_CHECK(int(picked.size()) == 1);
730 TEST_CHECK(picked.front().piece_index == 5);
732 // now, if all peers would have piece 1 (the piece we have partially)
733 // it should be prioritized over picking a completely new piece.
738 p.pick_pieces(peer3, picked, 1, false, 0, piece_picker::fast, true);
739 TEST_CHECK(int(picked.size()) == 1);
740 TEST_CHECK(picked.front().piece_index == 1);
741 // and the block picked should not be 0 or 2
742 // since we already have those blocks
744 TEST_CHECK(picked.front().block_index != 0);
745 TEST_CHECK(picked.front().block_index != 2);
747 // now, if we mark piece 1 and block 0 in piece 2
748 // as being downloaded and picks a block from peer1,
749 // it should pick a block from piece 2. But since
750 // block 0 is marked as requested from another peer,
751 // the piece_picker will continue to pick blocks
752 // until it can return at least 1 block (since we
753 // tell it we want one block) that is not being
754 // downloaded from anyone else. This is to make it
755 // possible for us to determine if we want to request
756 // the block from more than one peer.
757 // Both piece 1 and 2 are partial pieces, but pice
758 // 2 is the rarest, so that's why it is picked.
760 // we have block 0 and 2 already, so we can't mark
761 // them as begin downloaded.
762 p.mark_as_downloading(piece_block(1, 1), &peer_struct, piece_picker::fast);
763 p.mark_as_downloading(piece_block(1, 3), &peer_struct, piece_picker::fast);
764 p.mark_as_downloading(piece_block(2, 0), &peer_struct, piece_picker::fast);
766 std::vector<piece_picker::downloading_piece> const& downloads = p.get_download_queue();
767 TEST_CHECK(downloads.size() == 2);
768 TEST_CHECK(downloads[0].index == 1);
769 TEST_CHECK(downloads[0].info[0].state == piece_picker::block_info::state_finished);
770 TEST_CHECK(downloads[0].info[1].state == piece_picker::block_info::state_requested);
771 TEST_CHECK(downloads[0].info[2].state == piece_picker::block_info::state_finished);
772 TEST_CHECK(downloads[0].info[3].state == piece_picker::block_info::state_requested);
774 TEST_CHECK(downloads[1].index == 2);
775 TEST_CHECK(downloads[1].info[0].state == piece_picker::block_info::state_requested);
776 TEST_CHECK(downloads[1].info[1].state == piece_picker::block_info::state_none);
777 TEST_CHECK(downloads[1].info[2].state == piece_picker::block_info::state_none);
778 TEST_CHECK(downloads[1].info[3].state == piece_picker::block_info::state_none);
780 TEST_CHECK(p.is_requested(piece_block(1, 1)));
781 TEST_CHECK(p.is_requested(piece_block(1, 3)));
782 TEST_CHECK(p.is_requested(piece_block(2, 0)));
783 TEST_CHECK(!p.is_requested(piece_block(2, 1)));
786 p.pick_pieces(peer1, picked, 1, false, 0, piece_picker::fast, true);
787 TEST_CHECK(int(picked.size()) == 2);
789 piece_block expected3[] = { piece_block(2, 0), piece_block(2, 1) };
790 TEST_CHECK(std::equal(picked.begin()
791 , picked.end(), expected3));
793 // now, if we assume we're downloading at such a speed that
794 // we might prefer to download whole pieces at a time from
795 // this peer. It should not pick piece 1 or 2 (since those are
796 // partially selected)
799 p.pick_pieces(peer1, picked, 1, true, 0, piece_picker::fast, true);
801 // it will pick 4 blocks, since we said we
802 // wanted whole pieces.
803 TEST_CHECK(int(picked.size()) == 4);
805 piece_block expected4[] =
807 piece_block(3, 0), piece_block(3, 1)
808 , piece_block(3, 2), piece_block(3, 3)
811 TEST_CHECK(std::equal(picked.begin()
812 , picked.end(), expected4));
814 // now, try the same thing, but pick as many pieces as possible
815 // to make sure it can still fall back on partial pieces
818 p.pick_pieces(peer1, picked, 100, true, 0, piece_picker::fast, true);
820 TEST_CHECK(int(picked.size()) == 12);
822 piece_block expected5[] =
824 piece_block(3, 0), piece_block(3, 1)
825 , piece_block(3, 2), piece_block(3, 3)
826 , piece_block(5, 0), piece_block(5, 1)
827 , piece_block(5, 2), piece_block(5, 3)
828 , piece_block(2, 0), piece_block(2, 1)
829 , piece_block(2, 2), piece_block(2, 3)
832 TEST_CHECK(std::equal(picked.begin()
833 , picked.end(), expected5));
835 // now, try the same thing, but pick as many pieces as possible
836 // to make sure it can still fall back on partial pieces
839 p.pick_pieces(peer1, picked, 100, true, &peer_struct, piece_picker::fast, true);
841 TEST_CHECK(int(picked.size()) == 11);
843 piece_block expected6[] =
845 piece_block(2, 1), piece_block(2, 2)
847 , piece_block(3, 0), piece_block(3, 1)
848 , piece_block(3, 2), piece_block(3, 3)
849 , piece_block(5, 0), piece_block(5, 1)
850 , piece_block(5, 2), piece_block(5, 3)
853 TEST_CHECK(std::equal(picked.begin()
854 , picked.end(), expected6));
856 // make sure the piece picker allows filtered pieces
857 // to become available
858 p.mark_as_finished(piece_block(4, 2), 0);