TransferSessionImplTest.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2006-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #include "Qt.h"
00024 #include "../TransferSessionImpl.h"
00025 #include "generated/TransferSessionImplDriver.h"
00026 #include "generated/TransferSessionImplMock.h" // because of clock \todo
00027 #include "generated/TransferSessionStatusMock.h"
00028 #include "Imports.cpp"
00029 
00030 namespace Protocols {
00031 namespace BitTorrent {
00032 namespace Transfers {
00033 namespace Testing {
00034 
00036 
00040 class TransferSessionImplTest : public CppUnit::TestFixture
00041 {
00042     CPPUNIT_TEST_SUITE (TransferSessionImplTest);
00043     CPPUNIT_TEST (testCorrectInitialState);
00044     CPPUNIT_TEST (testWeGetChoked);
00045     CPPUNIT_TEST (testWeGetUnchoked);
00046     CPPUNIT_TEST (testWeGetUnchokedAndThenChokedAgain);
00047     CPPUNIT_TEST (testChokePeer);
00048     CPPUNIT_TEST (testUnchokePeer);
00049     CPPUNIT_TEST (testUnchokePeerAndThenChokeItAgain);
00050     CPPUNIT_TEST (testWeGetInterested);
00051     CPPUNIT_TEST (testWeGetNotInterested);
00052     CPPUNIT_TEST (testWeGetInterestedAndThenNotInterestedAgain);
00053     CPPUNIT_TEST (testPeerGetsInterested);
00054     CPPUNIT_TEST (testPeerGetsNotInterested);
00055     CPPUNIT_TEST (testPeerGetsInterestedAndThenNotInterestedAgain);
00056     CPPUNIT_TEST (testOnlyReceivingPieceIncreasesTotalDownload);
00057     CPPUNIT_TEST (testOnlySendingPieceIncreasesTotalUpload);
00058     CPPUNIT_TEST (testClosingTransferSessionClosesGenericSession);
00059     CPPUNIT_TEST (testForwardsClosingAndClosedNotificationFromGenericSession);
00060     CPPUNIT_TEST (testCurrentDownloadSpeedIsMovingAverageMoveTimeout);
00061     CPPUNIT_TEST (testCurrentDownloadSpeedIsMovingAverageMoveEachSecond);
00062     CPPUNIT_TEST (testCurrentUploadSpeedIsMovingAverageMoveTimeout);
00063     CPPUNIT_TEST (testCurrentUploadSpeedIsMovingAverageMoveEachSecond);
00064     CPPUNIT_TEST (testWeAreSnubbedIfPeerIsUnchokedButDoesNotReciprocate);
00065     CPPUNIT_TEST (testPeerIsSnubbedIfWeAreUnchokedButDoNotReciprocate);
00066     CPPUNIT_TEST (testReceivingABadPacketClosesSession);
00067     CPPUNIT_TEST (testReceivingBitFieldSetsPeerPiecesAvailable);
00068     CPPUNIT_TEST (testReceivingASecondBitFieldClosesSession);
00069     CPPUNIT_TEST (testSendingBitFieldSetsWePiecesAvailable);
00070     CPPUNIT_TEST (testReceivingHaveAllSetsAllPeerPiecesAvailable);
00071     CPPUNIT_TEST (testReceivingASecondHaveAllClosesSession);
00072     CPPUNIT_TEST (testSendingHaveAllSetsAllWePiecesAvailable);
00073     CPPUNIT_TEST (testReceivingHaveNoneResetsAllPeerPiecesAvailable);
00074     CPPUNIT_TEST (testReceivingASecondHaveNoneClosesSession);
00075     CPPUNIT_TEST (testSendingHaveNoneResetsAllWePiecesAvailable);
00076     CPPUNIT_TEST (testReceivingHavePacketSetsAPiecesAvailableBit);
00077     CPPUNIT_TEST (testSendingHavePacketSetsAPiecesAvailableBit);
00078     CPPUNIT_TEST (testPeerIsSeederIfItHasAllPieces);
00079     CPPUNIT_TEST (testWeAreSeederIfItHaveAllPieces);
00080     CPPUNIT_TEST (testPeerIsSeederAfterReportingItHasAllPieces);
00081     CPPUNIT_TEST (testWeAreSeederAfterReportingWeHaveAllPieces);
00082     CPPUNIT_TEST_SUITE_END();
00083 
00084     static const int                        AverageLength = 20;
00085     static const int                        SnubbedTimeout = 60;
00086 
00087     auto_ptr <SessionMock>                  genericSession;
00088     auto_ptr <IntegerResetStopwatchMock>    downloadStopwatch;
00089     auto_ptr <IntegerResetStopwatchMock>    uploadStopwatch;
00090     auto_ptr <TransferSessionStatusMock>    sessionStatus;
00091     auto_ptr <TransferSessionImpl>          sessionReal;
00092     auto_ptr <TransferSessionImplDriver>    session;
00093 
00094     const Handshake                         handshake;
00095     const BadPacket                         badPacket;
00096     const Choke                             choke;
00097     const Unchoke                           unchoke;
00098     const Interested                        interested;
00099     const NotInterested                     notInterested;
00100     const Piece                             piece1;
00101     const Piece                             piece2;
00102     const Piece                             piece3;
00103     const BitField                          bitField;
00104     const HaveAll                           haveAll;
00105     const HaveNone                          haveNone;
00106     const Have                              have5;
00107     const Have                              have11;
00108     const QBitArray                         allPiecesAvailable;
00109     QBitArray                               piecesAvailable;
00110     const QBitArray                         noPiecesAvailable;
00111 
00112 public:
00113     TransferSessionImplTest()
00114      :  genericSession(), downloadStopwatch(), uploadStopwatch(),
00115         sessionStatus(), sessionReal(), session(),
00116         handshake(Handshake::ProtocolVersion1, true, QByteArray(), 12),
00117         badPacket(), choke(), unchoke(), interested(), notInterested(),
00118         piece1 (0, 0, "1234567890"),
00119         piece2 (1, 0, "12345"),
00120         piece3 (2, 0, QByteArray (20000, '\0')),
00121         bitField ("\xf1\x80"),
00122         haveAll(), haveNone(), have5 (5), have11 (11),
00123         allPiecesAvailable (12, true),
00124         piecesAvailable (12),
00125         noPiecesAvailable (12, false)
00126     {
00127         piecesAvailable.fill (true, 0, 4); // xf_
00128         piecesAvailable.fill (true, 7, 8); // x_1
00129         piecesAvailable.fill (true, 8, 9); // x8_
00130     }
00131 
00132     void setUp()
00133     {
00134         genericSession.reset (new SessionMock());
00135         downloadStopwatch.reset (new IntegerResetStopwatchMock());
00136         uploadStopwatch.reset (new IntegerResetStopwatchMock());
00137         sessionStatus.reset (new TransferSessionStatusMock());
00138         sessionReal.reset (new TransferSessionImpl (*genericSession,
00139                                                     handshake,
00140                                                     *downloadStopwatch,
00141                                                     *uploadStopwatch,
00142                                                     *sessionStatus));
00143         session.reset (new TransferSessionImplDriver (*sessionReal));
00144     }
00145 
00146     void tearDown()
00147     {
00148         session.reset();
00149         sessionReal.reset();
00150         sessionStatus.reset();
00151         uploadStopwatch.reset();
00152         downloadStopwatch.reset();
00153         genericSession.reset();
00154     }
00155 
00156     void refWeAreChoked (bool value)
00157     {
00158         call (session->areWeChoked())
00159         .willReturn (value);
00160     }
00161 
00162     void refWeAreInterested (bool value)
00163     {
00164         call (session->areWeInterested())
00165         .willReturn (value);
00166     }
00167 
00168     void refWeAreSnubbed (bool value, int secondsSinceLastReceived = 0)
00169     {
00170         call (session->areWeSnubbed())
00171             .willCall (downloadStopwatch->elapsedSeconds())
00172             .willReturn (secondsSinceLastReceived)
00173         .willReturn (value);
00174     }
00175 
00176     void refWeAreSeeder (bool isSeeder)
00177     {
00178         call (session->areWeSeeder())
00179         .willReturn (isSeeder);
00180     }
00181 
00182     void refPeerIsChoked (bool value)
00183     {
00184         call (session->isPeerChoked())
00185         .willReturn (value);
00186     }
00187 
00188     void refPeerIsInterested (bool value)
00189     {
00190         call (session->isPeerInterested())
00191         .willReturn (value);
00192     }
00193 
00194     void refPeerIsSnubbed (bool value, int secondsSinceLastSent = 0)
00195     {
00196         call (session->isPeerSnubbed())
00197             .willCall (uploadStopwatch->elapsedSeconds())
00198             .willReturn (secondsSinceLastSent)
00199         .willReturn (value);
00200     }
00201 
00202     void refPeerIsSeeder (bool isSeeder)
00203     {
00204         call (session->isPeerSeeder())
00205         .willReturn (isSeeder);
00206     }
00207 
00208     void refTotalDownloadedIs (qint64 count)
00209     {
00210         call (session->totalDownloaded())
00211         .willReturn (count);
00212     }
00213 
00214     void refTotalUploadedIs (qint64 count)
00215     {
00216         call (session->totalUploaded())
00217         .willReturn (count);
00218     }
00219 
00220     void refCurrentDownloadSpeedIs (qint64 speed,
00221                                     int secondsSinceLastReceive = 0)
00222     {
00223         call (session->currentDownloadSpeed())
00224             .willCall (downloadStopwatch->elapsedSeconds())
00225             .willReturn (secondsSinceLastReceive)
00226             .willCall (downloadStopwatch->reset())
00227             .returns()
00228         .willReturn (speed);
00229     }
00230 
00231     void refCurrentUploadSpeedIs (qint64 speed, int secondsSinceLastSend = 0)
00232     {
00233         call (session->currentUploadSpeed())
00234             .willCall (uploadStopwatch->elapsedSeconds())
00235             .willReturn (secondsSinceLastSend)
00236             .willCall (uploadStopwatch->reset())
00237             .returns()
00238         .willReturn (speed);
00239     }
00240 
00241     void refWePiecesAvailable (const QBitArray &pieces)
00242     {
00243         call (session->wePiecesAvailable())
00244         .willReturn (pieces);
00245     }
00246 
00247     void refPeerPiecesAvailable (const QBitArray &pieces)
00248     {
00249         call (session->peerPiecesAvailable())
00250         .willReturn (pieces);
00251     }
00252 
00253     void refReceivedPacketFromPeer (Packet packet,
00254                                     int secondsSinceLastReceive = 0)
00255     {
00256         CallDriver <BoundFunction <TransferSessionImpl,
00257                                    void (Session*, const Data &)> > foo
00258         = genericSession->calls (session->sessionReceivedData (*genericSession,
00259                                                                packet));
00260 
00261         foo
00262             .willCall (sessionStatus->transferSessionReceivedPacket (*session,
00263                                                                      packet))
00264             .returns();
00265             if (typeid (*packet) == typeid (Piece)) {
00266                 foo.willCall (downloadStopwatch->elapsedSeconds())
00267                 .willReturn (secondsSinceLastReceive)
00268                 .willCall (downloadStopwatch->reset())
00269                 .returns();
00270             }
00271         foo.returns();
00272     }
00273 
00274     void refReceivedPacketFromPeerClosesSession (Packet packet)
00275     {
00276         genericSession->calls (session->sessionReceivedData (*genericSession,
00277                                                              packet))
00278             .willCall (genericSession->close())
00279             .returns()
00280         .returns();
00281     }
00282 
00283 
00284 
00285     void refSentPacketToPeer (Packet packet,
00286                               int secondsSinceLastSend = 0)
00287     {
00288         CallDriver <BoundFunction <TransferSessionImpl,
00289                                    void (const Packet &)> > foo
00290         = call (session->sendPacket (packet));
00291 
00292         foo
00293             .willCall (sessionStatus->transferSessionSendingPacket (*session,
00294                                                                     packet))
00295             .returns()
00296             .willCall (genericSession->send (packet))
00297             .returns();
00298             if (typeid (*packet) == typeid (Piece)) {
00299                 foo.willCall (uploadStopwatch->elapsedSeconds())
00300                 .willReturn (secondsSinceLastSend)
00301                 .willCall (uploadStopwatch->reset())
00302                 .returns();
00303             }
00304         foo.returns();
00305     }
00306 
00307     void testCorrectInitialState()
00308     {
00309         refWeAreChoked (true);
00310         refPeerIsChoked (true);
00311         refWeAreInterested (false);
00312         refPeerIsInterested (false);
00313         refWeAreSnubbed (false);
00314         refPeerIsSnubbed (false);
00315         refWeAreSeeder (false);
00316         refPeerIsSeeder (false);
00317         refTotalDownloadedIs (0);
00318         refTotalUploadedIs (0);
00319         refCurrentDownloadSpeedIs (0);
00320         refCurrentUploadSpeedIs (0);
00321         refWePiecesAvailable (QBitArray(handshake.numberPieces));
00322         refPeerPiecesAvailable (QBitArray(handshake.numberPieces));
00323     }
00324 
00325     void testWeGetChoked()
00326     {
00327         testWeGetUnchoked();
00328         refReceivedPacketFromPeer (choke);
00329         refWeAreChoked (true);
00330     }
00331 
00332     void testWeGetUnchoked()
00333     {
00334         refReceivedPacketFromPeer (unchoke);
00335         refWeAreChoked (false);
00336     }
00337 
00338     void testWeGetUnchokedAndThenChokedAgain()
00339     {
00340         testWeGetChoked();
00341         testWeGetUnchoked();
00342     }
00343 
00344     void testChokePeer()
00345     {
00346         testUnchokePeer();
00347         refSentPacketToPeer (choke);
00348         refPeerIsChoked (true);
00349     }
00350 
00351     void testUnchokePeer()
00352     {
00353         refSentPacketToPeer (unchoke);
00354         refPeerIsChoked (false);
00355     }
00356 
00357     void testUnchokePeerAndThenChokeItAgain()
00358     {
00359         testUnchokePeer();
00360         testChokePeer();
00361     }
00362 
00363     void testWeGetInterested()
00364     {
00365         refSentPacketToPeer (interested);
00366         refWeAreInterested (true);
00367     }
00368 
00369     void testWeGetNotInterested()
00370     {
00371         refSentPacketToPeer (notInterested);
00372         refWeAreInterested (false);
00373     }
00374 
00375     void testWeGetInterestedAndThenNotInterestedAgain()
00376     {
00377         testWeGetInterested();
00378         testWeGetNotInterested();
00379     }
00380 
00381     void testPeerGetsInterested()
00382     {
00383         refReceivedPacketFromPeer (interested);
00384         refPeerIsInterested (true);
00385     }
00386 
00387     void testPeerGetsNotInterested()
00388     {
00389         refReceivedPacketFromPeer (notInterested);
00390         refPeerIsInterested (false);
00391     }
00392 
00393     void testPeerGetsInterestedAndThenNotInterestedAgain()
00394     {
00395         testPeerGetsInterested();
00396         testPeerGetsNotInterested();
00397     }
00398 
00399     void testOnlyReceivingPieceIncreasesTotalDownload()
00400     {
00401         refTotalDownloadedIs (0);
00402         refReceivedPacketFromPeer (choke);
00403         refReceivedPacketFromPeer (unchoke);
00404         refReceivedPacketFromPeer (interested);
00405         refReceivedPacketFromPeer (notInterested);
00406         // \todo add the rest of the packets!
00407         refTotalDownloadedIs (0);
00408         refReceivedPacketFromPeer (piece1);
00409         refTotalDownloadedIs (piece1.pieceBytes().length());
00410         refReceivedPacketFromPeer (piece2);
00411         refTotalDownloadedIs (piece1.pieceBytes().length()
00412                               + piece2.pieceBytes().length());
00413     }
00414 
00415     void testOnlySendingPieceIncreasesTotalUpload()
00416     {
00417         refTotalUploadedIs (0);
00418         refSentPacketToPeer (choke);
00419         refSentPacketToPeer (unchoke);
00420         refSentPacketToPeer (interested);
00421         refSentPacketToPeer (notInterested);
00422         refTotalUploadedIs (0);
00423         refSentPacketToPeer (piece1);
00424         refTotalUploadedIs (piece1.pieceBytes().length());
00425         refSentPacketToPeer (piece2);
00426         refTotalUploadedIs (piece1.pieceBytes().length()
00427                             + piece2.pieceBytes().length());
00428     }
00429 
00430     void testClosingTransferSessionClosesGenericSession()
00431     {
00432         call (session->close())
00433             .willCall (genericSession->close())
00434             .returns()
00435         .returns();
00436     }
00437 
00438     void testForwardsClosingAndClosedNotificationFromGenericSession()
00439     {
00440         genericSession->calls (session->sessionClosing (*genericSession))
00441             .willCall (sessionStatus->transferSessionClosing (*session))
00442             .returns()
00443         .returns();
00444 
00445         genericSession->calls (session->sessionClosed (*genericSession))
00446             .willCall (sessionStatus->transferSessionClosed (*session))
00447             .returns()
00448         .returns();
00449     }
00450 
00451     void testCurrentDownloadSpeedIsMovingAverageMoveTimeout()
00452     {
00453         int piece3length = piece3.pieceBytes().length();
00454         // Burst some bytes to gain speed:
00455         for (int i = 1; i <= 3; ++i) {
00456             refReceivedPacketFromPeer (piece3);
00457             refCurrentDownloadSpeedIs (i * piece3length / AverageLength);
00458         }
00459         // Receive again after the timeout, speed goes down:
00460         refReceivedPacketFromPeer (piece3, AverageLength);
00461         refCurrentDownloadSpeedIs (piece3length / AverageLength);
00462         // The download speed is zero after the timeout:
00463         refCurrentDownloadSpeedIs (0, AverageLength);
00464     }
00465 
00466     void testCurrentDownloadSpeedIsMovingAverageMoveEachSecond()
00467     {
00468         int piece3length = piece3.pieceBytes().length();
00469         // Feed it constantly with data to see the speed grow:
00470         for (int i = 1; i <= AverageLength; ++i) {
00471             refReceivedPacketFromPeer (piece3, 1);
00472             refCurrentDownloadSpeedIs (i * piece3length / AverageLength);
00473         }
00474         // The speed must become constant now:
00475         refReceivedPacketFromPeer (piece3, 1);
00476         refCurrentDownloadSpeedIs (piece3length);
00477         // Stop feeding data and see how the speed goes down:
00478         for (int i = AverageLength - 1; i >= 0; --i) {
00479             refCurrentDownloadSpeedIs (i * piece3length / AverageLength, 1);
00480             // Speed must stay the same if we query it without delay:
00481             refCurrentDownloadSpeedIs (i * piece3length / AverageLength, 0);
00482         }
00483     }
00484 
00485     void testCurrentUploadSpeedIsMovingAverageMoveTimeout()
00486     {
00487         int piece3length = piece3.pieceBytes().length();
00488         // Burst some bytes to gain speed:
00489         for (int i = 1; i <= 3; ++i) {
00490             refSentPacketToPeer (piece3);
00491             refCurrentUploadSpeedIs (i * piece3length / AverageLength);
00492         }
00493         // Receive again after the timeout, speed goes down:
00494         refSentPacketToPeer (piece3, AverageLength);
00495         refCurrentUploadSpeedIs (piece3length / AverageLength);
00496         // The download speed is zero after the timeout:
00497         refCurrentUploadSpeedIs (0, AverageLength);
00498     }
00499 
00500     void testCurrentUploadSpeedIsMovingAverageMoveEachSecond()
00501     {
00502         int piece3length = piece3.pieceBytes().length();
00503         // Feed it constantly with data to see the speed grow:
00504         for (int i = 1; i <= AverageLength; ++i) {
00505             refSentPacketToPeer (piece3, 1);
00506             refCurrentUploadSpeedIs (i * piece3length / AverageLength);
00507         }
00508         // The speed must become constant now:
00509         refSentPacketToPeer (piece3, 1);
00510         refCurrentUploadSpeedIs (piece3length);
00511         // Stop feeding data and see how the speed goes down:
00512         for (int i = AverageLength - 1; i >= 0; --i) {
00513             refCurrentUploadSpeedIs (i * piece3length / AverageLength, 1);
00514             // Speed must stay the same if we query it without delay:
00515             refCurrentUploadSpeedIs (i * piece3length / AverageLength, 0);
00516         }
00517     }
00518 
00520 
00528     void testWeAreSnubbedIfPeerIsUnchokedButDoesNotReciprocate()
00529     {
00530         // We do not get snubbed even after the timeout because we are choked:
00531         refWeAreSnubbed (false);
00532         refWeAreSnubbed (false, SnubbedTimeout);
00533         // After we get unchoked we can get snubbed after a timeout:
00534         refSentPacketToPeer (unchoke);
00535         refWeAreSnubbed (false);
00536         refWeAreSnubbed (true, SnubbedTimeout);
00537     }
00538 
00539     void testPeerIsSnubbedIfWeAreUnchokedButDoNotReciprocate()
00540     {
00541         // Peer is choked so it cannot get snubbed even after the timeout:
00542         refPeerIsSnubbed (false);
00543         refPeerIsSnubbed (false, SnubbedTimeout);
00544         // After we unchoke the peer it can get snubbed after a timeout:
00545         refReceivedPacketFromPeer (unchoke);
00546         refPeerIsSnubbed (false);
00547         refPeerIsSnubbed (true, SnubbedTimeout);
00548     }
00549 
00550     void testReceivingABadPacketClosesSession()
00551     {
00552         refReceivedPacketFromPeerClosesSession (badPacket);
00553     }
00554 
00555     void testReceivingBitFieldSetsPeerPiecesAvailable()
00556     {
00557         refReceivedPacketFromPeer (bitField);
00558         refPeerPiecesAvailable (piecesAvailable);
00559     }
00560 
00561     void testReceivingASecondBitFieldClosesSession()
00562     {
00563         testReceivingBitFieldSetsPeerPiecesAvailable();
00564         refReceivedPacketFromPeerClosesSession (bitField);
00565     }
00566 
00567     void testSendingBitFieldSetsWePiecesAvailable()
00568     {
00569         refSentPacketToPeer (bitField);
00570         refWePiecesAvailable (piecesAvailable);
00571     }
00572 
00573     void testReceivingHaveAllSetsAllPeerPiecesAvailable()
00574     {
00575         refReceivedPacketFromPeer (haveAll);
00576         refPeerPiecesAvailable (allPiecesAvailable);
00577     }
00578 
00579     void testReceivingASecondHaveAllClosesSession()
00580     {
00581         testReceivingHaveAllSetsAllPeerPiecesAvailable();
00582         refReceivedPacketFromPeerClosesSession (haveAll);
00583     }
00584 
00585     void testSendingHaveAllSetsAllWePiecesAvailable()
00586     {
00587         refSentPacketToPeer (haveAll);
00588         refWePiecesAvailable (allPiecesAvailable);
00589     }
00590 
00591     void testReceivingHaveNoneResetsAllPeerPiecesAvailable()
00592     {
00593         refReceivedPacketFromPeer (haveNone);
00594         refPeerPiecesAvailable (noPiecesAvailable);
00595     }
00596 
00597     void testReceivingASecondHaveNoneClosesSession()
00598     {
00599         testReceivingHaveNoneResetsAllPeerPiecesAvailable();
00600         refReceivedPacketFromPeerClosesSession (haveNone);
00601     }
00602 
00603     void testSendingHaveNoneResetsAllWePiecesAvailable()
00604     {
00605         refSentPacketToPeer (haveNone);
00606         refWePiecesAvailable (noPiecesAvailable);
00607     }
00608 
00609     void testReceivingHavePacketSetsAPiecesAvailableBit()
00610     {
00611         // Initialize the bit array with a BitField packet:
00612         testReceivingBitFieldSetsPeerPiecesAvailable();
00613         // Now receive additional Have packets:
00614         refReceivedPacketFromPeer (have5);
00615         piecesAvailable.setBit (5, true);
00616         refPeerPiecesAvailable (piecesAvailable);
00617         refReceivedPacketFromPeer (have11);
00618         piecesAvailable.setBit (11, true);
00619         refPeerPiecesAvailable (piecesAvailable);
00620     }
00621 
00622     void testSendingHavePacketSetsAPiecesAvailableBit()
00623     {
00624         // Initialize the bit array with a BitField packet:
00625         testSendingBitFieldSetsWePiecesAvailable();
00626         // Now send additional Have packets:
00627         refSentPacketToPeer (have5);
00628         piecesAvailable.setBit (5, true);
00629         refWePiecesAvailable (piecesAvailable);
00630         refSentPacketToPeer (have11);
00631         piecesAvailable.setBit (11, true);
00632         refWePiecesAvailable (piecesAvailable);
00633     }
00634 
00635     void testPeerIsSeederIfItHasAllPieces()
00636     {
00637         refPeerIsSeeder (false);
00638         testReceivingHaveAllSetsAllPeerPiecesAvailable();
00639         refPeerIsSeeder (true);
00640     }
00641 
00642     void testWeAreSeederIfItHaveAllPieces()
00643     {
00644         refWeAreSeeder (false);
00645         testSendingHaveAllSetsAllWePiecesAvailable();
00646         refWeAreSeeder (true);
00647     }
00648 
00649     void testPeerIsSeederAfterReportingItHasAllPieces()
00650     {
00651         testReceivingBitFieldSetsPeerPiecesAvailable();
00652         refPeerIsSeeder (false);
00653         // Receiving a single Have packet is not enough:
00654         refReceivedPacketFromPeer (Have (4));
00655         refPeerIsSeeder (false);
00656         // Receive Have packets for ALL missing pieces:
00657         refReceivedPacketFromPeer (Have (5));
00658         refReceivedPacketFromPeer (Have (6));
00659         refReceivedPacketFromPeer (Have (9));
00660         refReceivedPacketFromPeer (Have (10));
00661         refReceivedPacketFromPeer (Have (11));
00662         refPeerIsSeeder (true);
00663     }
00664 
00665     void testWeAreSeederAfterReportingWeHaveAllPieces()
00666     {
00667         testSendingBitFieldSetsWePiecesAvailable();
00668         refWeAreSeeder (false);
00669         // Receiving a single Have packet is not enough:
00670         refSentPacketToPeer (Have (4));
00671         refWeAreSeeder (false);
00672         // Receive Have packets for ALL missing pieces:
00673         refSentPacketToPeer (Have (5));
00674         refSentPacketToPeer (Have (6));
00675         refSentPacketToPeer (Have (9));
00676         refSentPacketToPeer (Have (10));
00677         refSentPacketToPeer (Have (11));
00678         refWeAreSeeder (true);
00679     }
00680 };
00681 
00682 CPPUNIT_TEST_SUITE_REGISTRATION(TransferSessionImplTest);
00683 
00684 } // namespace Testing
00685 } // namespace Transfers
00686 } // namespace BitTorrent
00687 } // namespace Protocols