00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "Qt.h"
00024 #include "../SingleTrackerRequestSession.h"
00025 #include "../TrackerResponseParser.h"
00026 #include "generated/HttpRequestSessionMock.h"
00027 #include "generated/SingleTrackerRequestSessionDriver.h"
00028 #include "generated/TrackerRequestSessionMock.h"
00029 #include "Imports.cpp"
00030
00031 namespace Protocols {
00032 namespace BitTorrent {
00033 namespace Trackers {
00034 namespace Testing {
00035
00037
00039 class SingleTrackerRequestSessionTest : public CppUnit::TestFixture
00040 {
00041 CPPUNIT_TEST_SUITE (SingleTrackerRequestSessionTest);
00042 CPPUNIT_TEST (testOpenClosedSession);
00043 CPPUNIT_TEST (testHttpRequestSessionGetsEstablished);
00044 CPPUNIT_TEST (testSendRequest);
00045 CPPUNIT_TEST (testRecieveResponseHttp200AndValidMessageBody);
00046 CPPUNIT_TEST (testRecieveResponseHttp206AndValidMessageBody);
00047 CPPUNIT_TEST (testHttpErrorHttp100);
00048 CPPUNIT_TEST (testHttpErrorHttp101);
00049 CPPUNIT_TEST (testHttpErrorHttp300);
00050 CPPUNIT_TEST (testHttpErrorHttp307);
00051 CPPUNIT_TEST (testHttpErrorHttp400);
00052 CPPUNIT_TEST (testHttpErrorHttp417);
00053 CPPUNIT_TEST (testHttpErrorHttp500);
00054 CPPUNIT_TEST (testHttpErrorHttp505);
00055 CPPUNIT_TEST (testTrackerErrorHttp200AndInvalidResponseBody);
00056 CPPUNIT_TEST (testTrackerErrorHttp200AndFailureResponseBody);
00057 CPPUNIT_TEST (testCloseClosedSession);
00058 CPPUNIT_TEST (testCloseSessionCompletelyAfterItsEstablished);
00059 CPPUNIT_TEST (testCloseSessionCompletelyWhileWaitingForResponse);
00060 CPPUNIT_TEST (testCloseSessionCompletelyAfterHandledResponseHeader);
00061 CPPUNIT_TEST (testCloseSessionWhileClosing);
00062 CPPUNIT_TEST (testAbortClosedSession);
00063 CPPUNIT_TEST (testAbortSessionAfterItsEstablished);
00064 CPPUNIT_TEST (testAbortSessionWhileWaitingForResponse);
00065 CPPUNIT_TEST (testAbortSessionAfterHandledResponseHeader);
00066 CPPUNIT_TEST (testAbortSessionWhileClosing);
00067 CPPUNIT_TEST (testHttpRequestSessionErrorWhileEstablishingSession);
00068 CPPUNIT_TEST (testHttpRequestSessionErrorAfterSessionIsEstablished);
00069 CPPUNIT_TEST (testHttpRequestSessionErrorWhileWaitingForResponse);
00070 CPPUNIT_TEST (testHttpRequestSessionErrorAfterHandledResponseHeader);
00071 CPPUNIT_TEST (testHttpRequestSessionErrorWhileClosing);
00072 CPPUNIT_TEST_SUITE_END();
00073
00074 auto_ptr <HttpRequestSessionMock> httpRequestSession;
00075 auto_ptr <TrackerRequestSessionStatusMock> sessionStatus;
00076 auto_ptr <SingleTrackerRequestSession> sessionReal;
00077 auto_ptr <SingleTrackerRequestSessionDriver> session;
00078
00079 const Uri ValidAnnounceUrl;
00080 const TrackerRequest ValidTrackerRequest;
00081 const Uri ValidTrackerRequestUrl;
00082 const QByteArray ValidResponseBody;
00083 const QByteArray InvalidResponseBody;
00084 const QByteArray FailureResponseBody;
00085 const TrackerResponse ValidTrackerResponse;
00086
00088
00092 TrackerResponse createValidTrackerResponse() const
00093 {
00094 TrackerResponse response;
00095 TrackerResponseParser::parseAndLoadTrackerResponse (ValidResponseBody,
00096 response);
00097 return response;
00098 }
00099
00100 public:
00101 SingleTrackerRequestSessionTest();
00102
00103 void setUp()
00104 {
00105 httpRequestSession.reset (new HttpRequestSessionMock());
00106 sessionStatus.reset (new TrackerRequestSessionStatusMock());
00107 sessionReal.reset (new SingleTrackerRequestSession (
00108 &httpRequestSession->imp, ValidAnnounceUrl, &sessionStatus->imp));
00109 session.reset (new SingleTrackerRequestSessionDriver (
00110 *sessionReal.get()));
00111 }
00112
00113 void tearDown()
00114 {
00115 session.reset();
00116 sessionReal.reset();
00117 sessionStatus.reset();
00118 httpRequestSession.reset();
00119 }
00120
00122 void testOpenClosedSession()
00123 {
00124 call (session->open())
00125 .willCall (httpRequestSession->open (ValidAnnounceUrl))
00126 .returns()
00127 .returns();
00128 }
00129
00134 void stateSessionIsOpened()
00135 {
00136 testOpenClosedSession();
00137 }
00138
00140 void testHttpRequestSessionGetsEstablished()
00141 {
00142 call (session->httpRequestSessionEstablished())
00143 .willCall (sessionStatus->trackerRequestSessionEstablished (
00144 sessionReal.get()))
00145 .returns()
00146 .returns();
00147 }
00148
00153 void stateSessionIsEstablished()
00154 {
00155 testHttpRequestSessionGetsEstablished();
00156 }
00157
00162 void testSendRequest()
00163 {
00164 stateSessionIsEstablished();
00165
00166 call (session->sendRequest (ValidTrackerRequest))
00167 .willCall (httpRequestSession->get (ValidTrackerRequestUrl))
00168 .returns()
00169 .returns();
00170 }
00171
00176 void stateWaitingForResponse()
00177 {
00178 testSendRequest();
00179 }
00180
00182
00185 void refHandleResponseHeaderSuccessfully (const ResponseHeader &responseHeader)
00186 {
00187 call (session->httpRequestSessionResponseHeaderRecieved (responseHeader))
00188 .returns();
00189 }
00190
00192
00198 void scenarioRecieveResponse (const ResponseHeader &responseHeader,
00199 const QByteArray &responseBody,
00200 const TrackerResponse &trackerResponse)
00201 {
00202 stateWaitingForResponse();
00203
00204 refHandleResponseHeaderSuccessfully (responseHeader);
00205
00206 call (session->httpRequestSessionResponseBodyRecieved (responseBody))
00207 .willCall (sessionStatus->trackerRequestSessionResponseRecieved (
00208 sessionReal.get(), trackerResponse))
00209 .returns()
00210 .returns();
00211 }
00212
00214 void testRecieveResponseHttp200AndValidMessageBody()
00215 {
00216 scenarioRecieveResponse (ResponseHeader ("HTTP/1.1 200 OK\r\n\r\n"),
00217 ValidResponseBody, ValidTrackerResponse);
00218 }
00219
00221 void testRecieveResponseHttp206AndValidMessageBody()
00222 {
00223 scenarioRecieveResponse (ResponseHeader ("HTTP/1.1 206 Partial Content\r\n\r\n"),
00224 ValidResponseBody, ValidTrackerResponse);
00225 }
00226
00228
00233 void scenarioHttpError (const ResponseHeader &responseHeader,
00234 const QString &httpErrorMessage)
00235 {
00236 stateWaitingForResponse();
00237
00238 call (session->httpRequestSessionResponseHeaderRecieved (responseHeader))
00239 .willCall (sessionStatus->trackerRequestSessionError (
00240 sessionReal.get(), httpErrorMessage))
00241 .returns()
00242 .returns();
00243 }
00244
00246 void testHttpErrorHttp100()
00247 {
00248 scenarioHttpError (ResponseHeader ("HTTP/1.1 100 Continue\r\n\r\n"),
00249 QString ("HTTP error: 100 Continue"));
00250 }
00251
00253 void testHttpErrorHttp101()
00254 {
00255 scenarioHttpError (ResponseHeader ("HTTP/1.1 101 Switching Protocols\r\n\r\n"),
00256 QString ("HTTP error: 101 Switching Protocols"));
00257 }
00258
00260 void testHttpErrorHttp300()
00261 {
00262 scenarioHttpError (ResponseHeader ("HTTP/1.1 300 Multiple Choices\r\n\r\n"),
00263 QString ("HTTP error: 300 Multiple Choices"));
00264 }
00265
00267 void testHttpErrorHttp307()
00268 {
00269 scenarioHttpError (ResponseHeader ("HTTP/1.1 307 Temporary Redirect\r\n\r\n"),
00270 QString ("HTTP error: 307 Temporary Redirect"));
00271 }
00272
00274 void testHttpErrorHttp400()
00275 {
00276 scenarioHttpError (ResponseHeader ("HTTP/1.1 400 Bad Request\r\n\r\n"),
00277 QString ("HTTP error: 400 Bad Request"));
00278 }
00279
00281 void testHttpErrorHttp417()
00282 {
00283 scenarioHttpError (ResponseHeader ("HTTP/1.1 417 Expectation Failed\r\n\r\n"),
00284 QString ("HTTP error: 417 Expectation Failed"));
00285 }
00286
00288 void testHttpErrorHttp500()
00289 {
00290 scenarioHttpError (ResponseHeader ("HTTP/1.1 500 Internal Server Error\r\n\r\n"),
00291 QString ("HTTP error: 500 Internal Server Error"));
00292 }
00293
00295 void testHttpErrorHttp505()
00296 {
00297 scenarioHttpError (ResponseHeader ("HTTP/1.1 505 HTTP Version Not Supported\r\n\r\n"),
00298 QString ("HTTP error: 505 HTTP Version Not Supported"));
00299 }
00300
00302
00308 void scenarioTrackerError (const ResponseHeader &responseHeader,
00309 const QByteArray &responseBody,
00310 const QString &trackerErrorMessage)
00311 {
00312 stateWaitingForResponse();
00313
00314 refHandleResponseHeaderSuccessfully (responseHeader);
00315
00316 call (session->httpRequestSessionResponseBodyRecieved (responseBody))
00317 .willCall (sessionStatus->trackerRequestSessionError (
00318 sessionReal.get(), trackerErrorMessage))
00319 .returns()
00320 .returns();
00321 }
00322
00324 void testTrackerErrorHttp200AndInvalidResponseBody()
00325 {
00326 scenarioTrackerError (ResponseHeader ("HTTP/1.1 200 OK\r\n\r\n"),
00327 InvalidResponseBody, QString ("Tracker error: Tracker response could not be parsed"));
00328 }
00329
00331 void testTrackerErrorHttp200AndFailureResponseBody()
00332 {
00333 scenarioTrackerError (ResponseHeader ("HTTP/1.1 200 OK\r\n\r\n"),
00334 FailureResponseBody, QString ("Tracker error: Unknown info_hash"));
00335 }
00336
00341 void stateResponseHeaderHandledSuccessfully()
00342 {
00343 stateWaitingForResponse();
00344
00345 refHandleResponseHeaderSuccessfully (
00346 ResponseHeader ("HTTP/1.1 200 OK\r\n\r\n"));
00347 }
00348
00350 void refCloseSessionAfterHttpRequestSessionIsClosed()
00351 {
00352 call (session->httpRequestSessionClosed())
00353 .willCall (sessionStatus->trackerRequestSessionClosed (
00354 sessionReal.get()))
00355 .returns()
00356 .returns();
00357 }
00358
00360 void refCloseEstablishedSession()
00361 {
00362 call (session->close())
00363 .willCall (sessionStatus->trackerRequestSessionClosing (
00364 sessionReal.get()))
00365 .returns()
00366 .willCall (httpRequestSession->close())
00367 .returns()
00368 .returns();
00369 }
00370
00372 void refCloseEstablishedSessionCompletely()
00373 {
00374 refCloseEstablishedSession();
00375 refCloseSessionAfterHttpRequestSessionIsClosed();
00376 }
00377
00379 void refCloseClosedOrClosingSession()
00380 {
00381 call (session->close())
00382 .returns();
00383 }
00384
00388 void stateSessionIsClosing()
00389 {
00390 stateSessionIsEstablished();
00391
00392 refCloseEstablishedSession();
00393 }
00394
00396 void testCloseClosedSession()
00397 {
00398 refCloseClosedOrClosingSession();
00399 }
00400
00402 void testCloseSessionCompletelyAfterItsEstablished()
00403 {
00404 stateSessionIsEstablished();
00405
00406 refCloseEstablishedSessionCompletely();
00407 }
00408
00410 void testCloseSessionCompletelyWhileWaitingForResponse()
00411 {
00412 stateWaitingForResponse();
00413
00414 refCloseEstablishedSessionCompletely();
00415 }
00416
00418 void testCloseSessionCompletelyAfterHandledResponseHeader()
00419 {
00420 stateResponseHeaderHandledSuccessfully();
00421
00422 refCloseEstablishedSessionCompletely();
00423 }
00424
00426 void testCloseSessionWhileClosing()
00427 {
00428 stateSessionIsClosing();
00429
00430 refCloseClosedOrClosingSession();
00431 }
00432
00434 void refAbortEstablishedSession()
00435 {
00436 call (session->abort())
00437 .willCall (httpRequestSession->abort())
00438 .returns()
00439 .willCall (sessionStatus->trackerRequestSessionClosed (
00440 sessionReal.get()))
00441 .returns()
00442 .returns();
00443 }
00444
00446 void testAbortClosedSession()
00447 {
00448 call (session->abort())
00449 .returns();
00450 }
00451
00453 void testAbortSessionAfterItsEstablished()
00454 {
00455 stateSessionIsEstablished();
00456
00457 refAbortEstablishedSession();
00458 }
00459
00461 void testAbortSessionWhileWaitingForResponse()
00462 {
00463 stateWaitingForResponse();
00464
00465 refAbortEstablishedSession();
00466 }
00467
00469 void testAbortSessionAfterHandledResponseHeader()
00470 {
00471 stateResponseHeaderHandledSuccessfully();
00472
00473 refAbortEstablishedSession();
00474 }
00475
00477 void testAbortSessionWhileClosing()
00478 {
00479 stateSessionIsClosing();
00480
00481 refAbortEstablishedSession();
00482 }
00483
00485 void refHandleHttpRequestSessionError (const QString &errorMessage)
00486 {
00487 call (session->httpRequestSessionError (errorMessage))
00488 .willCall (sessionStatus->trackerRequestSessionError (
00489 sessionReal.get(), QString ("HTTP request session error: " +
00490 errorMessage)))
00491 .returns()
00492 .returns();
00493 }
00494
00496 void testHttpRequestSessionErrorWhileEstablishingSession()
00497 {
00498 stateSessionIsOpened();
00499
00500 refHandleHttpRequestSessionError (QString ("Connection failed"));
00501 }
00502
00504 void testHttpRequestSessionErrorAfterSessionIsEstablished()
00505 {
00506 stateSessionIsEstablished();
00507
00508 refHandleHttpRequestSessionError (QString ("Connection lost"));
00509 }
00510
00512 void testHttpRequestSessionErrorWhileWaitingForResponse()
00513 {
00514 stateWaitingForResponse();
00515
00516 refHandleHttpRequestSessionError (QString ("Connection lost"));
00517 }
00518
00520 void testHttpRequestSessionErrorAfterHandledResponseHeader()
00521 {
00522 stateResponseHeaderHandledSuccessfully();
00523
00524 refHandleHttpRequestSessionError (QString ("Connection lost"));
00525 }
00526
00528 void testHttpRequestSessionErrorWhileClosing()
00529 {
00530 stateSessionIsClosing();
00531
00532 refHandleHttpRequestSessionError (QString ("Closing problem"));
00533 }
00534 };
00535
00536 CPPUNIT_TEST_SUITE_REGISTRATION(SingleTrackerRequestSessionTest);
00537
00539 SingleTrackerRequestSessionTest::SingleTrackerRequestSessionTest()
00540 : httpRequestSession(),
00541 sessionStatus(),
00542 sessionReal(),
00543 session(),
00544 ValidAnnounceUrl (Uri::fromUnencoded ("http://localhost/announce.php")),
00545 ValidTrackerRequest (
00546 ValidAnnounceUrl,
00547 PeerInfo ("0.0.0.0", 6881, PeerInfo::PeerId ("-CA0610-574938205849")),
00548 Torrent::InfoHash ("z53bf64bd05hfn2daqml"),
00549 4096,
00550 2048,
00551 63488,
00552 false),
00553 ValidTrackerRequestUrl (Uri::fromUnencoded (
00554 ValidAnnounceUrl.unencoded() +
00555 "?info_hash=z53bf64bd05hfn2daqml"
00556 "&peer_id=-CA0610-574938205849"
00557 "&port=6881"
00558 "&uploaded=4096"
00559 "&downloaded=2048"
00560 "&left=63488"
00561 "&compact=0"
00562 "&event=empty"
00563 "&numwant=0")),
00564 ValidResponseBody (
00565 "d"
00566 "8:intervali300e"
00567 "5:peersle"
00568 "e"),
00569 InvalidResponseBody (
00570 "d"
00571 "1:too-long-key-namei467e"
00572 "e"),
00573 FailureResponseBody (
00574 "d"
00575 "14:failure reason17:Unknown info_hash"
00576 "e"),
00577 ValidTrackerResponse (createValidTrackerResponse())
00578 {
00579 }
00580
00581 }
00582 }
00583 }
00584 }