SocketTransportTest.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 "../SocketTransport.h"
00025 #include "generated/TransportStatusMock.h"
00026 #include "generated/SocketBufferMock.h"
00027 #include "generated/SocketMock.h"
00028 #include "generated/SocketTransportDriver.h"
00029 #include "Imports.cpp"
00030 
00031 namespace Protocols {
00032 namespace Generics {
00033 namespace Testing {
00034 
00036 
00038 class SocketTransportTest : public CppUnit::TestFixture
00039 {
00040     CPPUNIT_TEST_SUITE (SocketTransportTest);
00041     CPPUNIT_TEST (testStartConnecting);
00042     CPPUNIT_TEST (testConnectionEstablished);
00043     CPPUNIT_TEST (testConnectionRejected);
00044     CPPUNIT_TEST (testAbortConnectionAttempt);
00045     CPPUNIT_TEST (testStartDisconnecting);
00046     CPPUNIT_TEST (testDisconnectingCompletes);
00047     CPPUNIT_TEST (testAbortWhileDisconnecting);
00048     CPPUNIT_TEST (testConnectionDisconnectedBySocket);
00049     CPPUNIT_TEST (testAbortDueToSocketError);
00050     CPPUNIT_TEST (testSocketConnectedTwice);
00051     CPPUNIT_TEST (testSocketDisconnectedTwice);
00052     CPPUNIT_TEST (testSocketErrorTwice);
00053     CPPUNIT_TEST (testSocketErrorSocketDisconnected);
00054     CPPUNIT_TEST (testSocketDisconnectedSocketError);
00055     CPPUNIT_TEST (testWriteDelegatesToSocketBufferAndTriesToWriteToSocket);
00056     CPPUNIT_TEST (testReadsDelegateToSocketBufferThenTriesToReadMoreFromSocket);
00057     CPPUNIT_TEST (testPeeksDelegateToSocketBuffer);
00058     CPPUNIT_TEST (testCanReadCanWriteDelegateToSocketBuffer);
00059     CPPUNIT_TEST (testSocketReadMakesBufferToReadFromSocketAndEmitsReadyRead);
00060     CPPUNIT_TEST (testSocketWrittenMakesBufferToWriteToSocketAndEmitsReadyWrite);
00061     CPPUNIT_TEST (testSocketWrittenReadyWriteNotCalledRecursively);
00062     CPPUNIT_TEST (testReadyWriteNotCalledFromWrite);
00063     CPPUNIT_TEST (testSocketWrittenDoesNotCallTryWriteToRecursively);
00064     CPPUNIT_TEST (testSocketReadReadyReadNofCalledRecursively);
00065     CPPUNIT_TEST (testReadyReadNotCalledFromRead);
00066     CPPUNIT_TEST (testSocketReadDoesNotCallTryReadFromRecursively);
00067     CPPUNIT_TEST_SUITE_END();
00068 
00069     auto_ptr <SocketMock>               socket;
00070     auto_ptr <SocketBufferMock>         buffer;
00071     auto_ptr <TransportStatusMock>      status;
00072     auto_ptr <SocketTransport>          transport_real;
00073     auto_ptr <SocketTransportDriver>    transport;
00074 
00075 public:
00076     SocketTransportTest()
00077      :  socket(), buffer(), status(), transport_real(), transport()
00078     {
00079     }
00080 
00081     void setUp()
00082     {
00083         socket.reset (new SocketMock);
00084         buffer.reset (new SocketBufferMock);
00085         status.reset (new TransportStatusMock);
00086         transport_real.reset (new SocketTransport (*socket, *buffer, *status));
00087         transport.reset (new SocketTransportDriver (*transport_real.get()));
00088     }
00089 
00090     void tearDown()
00091     {
00092         transport.reset();
00093         transport_real.reset();
00094         status.reset();
00095         buffer.reset();
00096         socket.reset();
00097     }
00098 
00103     void stateDisconnected()
00104     {
00105     }
00106 
00108     void testStartConnecting()
00109     {
00110         stateDisconnected();
00111 
00112         Uri connectAddress = Uri::fromUnencoded ("//127.0.0.1:1000");
00113         call (transport->connectToNode (connectAddress))
00114             .willCall (socket->connectToHost (QHostAddress ("127.0.0.1"), 1000))
00115             .returns()
00116         .returns();
00117     }
00118 
00119     void stateConnecting()
00120     {
00121         testStartConnecting();
00122     }
00123 
00125     void testConnectionEstablished()
00126     {
00127         stateConnecting();
00128 
00129         socket->calls (transport->socketConnected())
00130             .willCall (status->transportConnected (*transport))
00131             .returns()
00132         .returns();
00133     }
00134 
00135     void stateConnected()
00136     {
00137         testConnectionEstablished();
00138     }
00139 
00141 
00146     void testConnectionRejected()
00147     {
00148         stateConnecting();
00149 
00150         socket->calls (transport->socketError())
00151             .willCall (socket->abort())
00152                 .willCall (transport->socketDisconnected())
00153                     .willCall (status->transportDisconnected (*transport))
00154                     .returns()
00155                 .returns()
00156             .returns()
00157         .returns();
00158     }
00159 
00161 
00164     void testAbortConnectionAttempt()
00165     {
00166         stateConnecting();
00167 
00168         call (transport->abort())
00169             .willCall (socket->abort())
00170                 .willCall (transport->socketDisconnected())
00171                     .willCall (status->transportDisconnected (*transport))
00172                     .returns()
00173                 .returns()
00174             .returns()
00175         .returns();
00176     }
00177 
00178     void refStartDisconnecting()
00179     {
00180         call (transport->disconnectFromNode())
00181             .willCall (socket->disconnectFromHost())
00182             .returns()
00183         .returns();
00184     }
00185 
00187     void testStartDisconnecting()
00188     {
00189         stateConnected();
00190         refStartDisconnecting();
00191     }
00192 
00193     void stateDisconnecting()
00194     {
00195         testStartDisconnecting();
00196     }
00197 
00199     void testDisconnectingCompletes()
00200     {
00201         stateDisconnecting();
00202 
00203         socket->calls (transport->socketDisconnected())
00204             .willCall (status->transportDisconnected (*transport))
00205             .returns()
00206         .returns();
00207     }
00208 
00210     void testAbortWhileDisconnecting()
00211     {
00212         stateDisconnecting();
00213 
00214         socket->calls (transport->abort())
00215             .willCall (socket->abort())
00216                 .willCall (transport->socketDisconnected())
00217                     .willCall (status->transportDisconnected (*transport))
00218                     .returns()
00219                 .returns()
00220             .returns()
00221         .returns();
00222     }
00223 
00225     void testConnectionDisconnectedBySocket()
00226     {
00227         stateConnected();
00228 
00229         socket->calls (transport->socketDisconnected())
00230             .willCall (status->transportDisconnected (*transport))
00231             .returns()
00232         .returns();
00233     }
00234 
00236     void testAbortDueToSocketError()
00237     {
00238         stateConnected();
00239 
00240         socket->calls (transport->socketError())
00241             .willCall (socket->abort())
00242                 .willCall (transport->socketDisconnected())
00243                     .willCall (status->transportDisconnected (*transport))
00244                     .returns()
00245                 .returns()
00246             .returns()
00247         .returns();
00248     }
00249 
00251     void testSocketConnectedTwice()
00252     {
00253         stateConnected();
00254 
00255         socket->calls (transport->socketConnected())
00256         .returns();
00257     }
00258 
00260     void testSocketDisconnectedTwice()
00261     {
00262         stateDisconnected();
00263 
00264         socket->calls (transport->socketDisconnected())
00265         .returns();
00266     }
00267 
00269     void testSocketErrorTwice()
00270     {
00271         testAbortDueToSocketError();
00272 
00273         socket->calls (transport->socketError())
00274         .returns();
00275     }
00276 
00278     void testSocketErrorSocketDisconnected()
00279     {
00280         testAbortDueToSocketError();
00281 
00282         socket->calls (transport->socketDisconnected())
00283         .returns();
00284     }
00285 
00287     void testSocketDisconnectedSocketError()
00288     {
00289         testConnectionDisconnectedBySocket();
00290 
00291         socket->calls (transport->socketError())
00292         .returns();
00293     }
00294 
00296 
00303     void refWriteBytes (const QByteArray &bytes, bool flush, bool succeeds)
00304     {
00305         call (transport->write (bytes, flush))
00306             .willCall (buffer->write (bytes, flush))
00307             .willReturn (succeeds)
00308             .willCall (buffer->tryWriteTo (*socket))
00309             .returns()
00310         .willReturn (succeeds);
00311     }
00312 
00314 
00318     void testWriteDelegatesToSocketBufferAndTriesToWriteToSocket()
00319     {
00320         stateConnected();
00321 
00322         refWriteBytes (QByteArray ("123"), false, true);
00323         refWriteBytes (QByteArray(), true, true);
00324         refWriteBytes (QByteArray ("123"), false, false);
00325         refWriteBytes (QByteArray(), true, false);
00326     }
00327 
00328     void refReadsDelegateToBuffer()
00329     {
00330         call (transport->readAll())
00331             .willCall (buffer->readAll())
00332             .willReturn (QByteArray ("123"))
00333             .willCall (buffer->tryReadFrom (*socket))
00334             .returns()
00335         .willReturn (QByteArray ("123"));
00336 
00337         call (transport->readTo (QByteArray ("ee")))
00338             .willCall (buffer->readTo (QByteArray ("ee")))
00339             .willReturn (QByteArray ("123"))
00340             .willCall (buffer->tryReadFrom (*socket))
00341             .returns()
00342         .willReturn (QByteArray ("123"));
00343 
00344         call (transport->read (10))
00345             .willCall (buffer->read (10))
00346             .willReturn (QByteArray (10, '1'))
00347             .willCall (buffer->tryReadFrom (*socket))
00348             .returns()
00349         .willReturn (QByteArray (10, '1'));
00350 
00351         call (transport->readAtMost (10))
00352             .willCall (buffer->readAtMost (10))
00353             .willReturn (QByteArray (5, '1'))
00354             .willCall (buffer->tryReadFrom (*socket))
00355             .returns()
00356         .willReturn (QByteArray (5, '1'));
00357     }
00358 
00360 
00369     void testReadsDelegateToSocketBufferThenTriesToReadMoreFromSocket()
00370     {
00371         stateConnected();
00372         refReadsDelegateToBuffer();
00373         refStartDisconnecting();
00374         refReadsDelegateToBuffer();
00375     }
00376 
00377     void refPeedsDelegateToSocketBuffer()
00378     {
00379         call (transport->peekAll())
00380             .willCall (buffer->peekAll())
00381             .willReturn (QByteArray ("123"))
00382         .willReturn (QByteArray ("123"));
00383 
00384         call (transport->peekTo (QByteArray ("ee")))
00385             .willCall (buffer->peekTo (QByteArray ("ee")))
00386             .willReturn (QByteArray ("123"))
00387         .willReturn (QByteArray ("123"));
00388 
00389         call (transport->peek (10))
00390             .willCall (buffer->peek (10))
00391             .willReturn (QByteArray (10, '1'))
00392         .willReturn (QByteArray (10, '1'));
00393 
00394         call (transport->peekAtMost (10))
00395             .willCall (buffer->peekAtMost (10))
00396             .willReturn (QByteArray (5, '1'))
00397         .willReturn (QByteArray (5, '1'));
00398     }
00399 
00401 
00406     void testPeeksDelegateToSocketBuffer()
00407     {
00408         stateConnected();
00409         refPeedsDelegateToSocketBuffer();
00410         refStartDisconnecting();
00411         refPeedsDelegateToSocketBuffer();
00412     }
00413 
00414     void refCanReadDelegatesToBuffer (int count, bool canRead)
00415     {
00416         call (transport->canRead (count))
00417             .willCall (buffer->canRead (count))
00418             .willReturn (canRead)
00419         .willReturn (canRead);
00420     }
00421 
00422     void refCanWriteDelegatesToBuffer (int count, bool canWrite)
00423     {
00424         call (transport->canWrite (count))
00425             .willCall (buffer->canWrite (count))
00426             .willReturn (canWrite)
00427         .willReturn (canWrite);
00428     }
00429 
00431 
00435     void testCanReadCanWriteDelegateToSocketBuffer()
00436     {
00437         stateConnected();
00438 
00439         refCanReadDelegatesToBuffer (10, true);
00440         refCanReadDelegatesToBuffer (10, false);
00441 
00442         refCanWriteDelegatesToBuffer (10, true);
00443         refCanWriteDelegatesToBuffer (10, false);
00444 
00445         refStartDisconnecting();
00446 
00447         refCanReadDelegatesToBuffer (10, true);
00448         refCanReadDelegatesToBuffer (10, false);
00449     }
00450 
00452     void testSocketReadMakesBufferToReadFromSocketAndEmitsReadyRead()
00453     {
00454         stateConnected();
00455 
00456         call (transport->socketRead())
00457             .willCall (buffer->tryReadFrom (*socket))
00458             .returns()
00459             .willCall (status->transportReadyRead (*transport))
00460             .returns()
00461         .returns();
00462     }
00463 
00465     void testSocketWrittenMakesBufferToWriteToSocketAndEmitsReadyWrite()
00466     {
00467         stateConnected();
00468 
00469         call (transport->socketWritten())
00470             .willCall (buffer->tryWriteTo (*socket))
00471             .returns()
00472             .willCall (status->transportReadyWrite (*transport))
00473             .returns()
00474         .returns();
00475     }
00476 
00478 
00483     void testSocketWrittenReadyWriteNotCalledRecursively()
00484     {
00485         stateConnected();
00486 
00487         call (transport->socketWritten())
00488             .willCall (buffer->tryWriteTo (*socket))
00489             .returns()
00490             .willCall (status->transportReadyWrite (*transport))
00491                 .willCall (transport->write (QByteArray(), true))
00492                     .willCall (buffer->write (QByteArray(), true))
00493                     .willReturn (true)
00494                     .willCall (buffer->tryWriteTo (*socket))
00495                         .willCall (transport->socketWritten())
00496                         .returns()
00497                     .returns()
00498                 .willReturn (true)
00499             .returns()
00500         .returns();
00501     }
00502 
00504 
00509     void testReadyWriteNotCalledFromWrite()
00510     {
00511         stateConnected();
00512 
00513         call (transport->write (QByteArray(), true))
00514             .willCall (buffer->write (QByteArray(), true))
00515             .willReturn (true)
00516             .willCall (buffer->tryWriteTo (*socket))
00517                 .willCall (transport->socketWritten())
00518                 .returns()
00519             .returns()
00520         .willReturn (true);
00521     }
00522 
00524     void testSocketWrittenDoesNotCallTryWriteToRecursively()
00525     {
00526         stateConnected();
00527 
00528         call (transport->socketWritten())
00529             .willCall (buffer->tryWriteTo (*socket))
00530                 .willCall (transport->socketWritten())
00531                 .returns()
00532             .returns()
00533             .willCall (status->transportReadyWrite (*transport))
00534             .returns()
00535         .returns();
00536     }
00537 
00539 
00547     void testSocketReadReadyReadNofCalledRecursively()
00548     {
00549         stateConnected();
00550 
00551         call (transport->socketRead())
00552             .willCall (buffer->tryReadFrom (*socket))
00553             .returns()
00554             .willCall (status->transportReadyRead (*transport))
00555                 .willCall (transport->read (0))
00556                     .willCall (buffer->read (0))
00557                     .willReturn (QByteArray())
00558                     .willCall (buffer->tryReadFrom (*socket))
00559                         .willCall (transport->socketRead())
00560                         .returns()
00561                     .returns()
00562                 .willReturn (QByteArray())
00563             .returns()
00564         .returns();
00565     }
00566 
00568 
00572     void testReadyReadNotCalledFromRead()
00573     {
00574         stateConnected();
00575 
00576         call (transport->read (0))
00577             .willCall (buffer->read (0))
00578             .willReturn (QByteArray())
00579             .willCall (buffer->tryReadFrom (*socket))
00580             .returns()
00581         .willReturn (QByteArray());
00582     }
00583 
00585     void testSocketReadDoesNotCallTryReadFromRecursively()
00586     {
00587         stateConnected();
00588 
00589         call (transport->socketRead())
00590             .willCall (buffer->tryReadFrom (*socket))
00591                 .willCall (transport->socketRead())
00592                 .returns()
00593             .returns()
00594             .willCall (status->transportReadyRead (*transport))
00595             .returns()
00596         .returns();
00597     }
00598 };
00599 
00600 CPPUNIT_TEST_SUITE_REGISTRATION (SocketTransportTest);
00601 
00602 } // namespace Testing
00603 } // namespace Generics
00604 } // namespace Protocols