GenericSessionTest.cpp
Go to the documentation of this file.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 "../BadPacket.h"
00025 #include "generated/DataSerializerMock.h"
00026 #include "generated/DataQueueMock.h"
00027 #include "generated/GenericSessionDriver.h"
00028 #include "generated/SessionMock.h"
00029 #include "generated/SessionStatusMock.h"
00030 #include "generated/TransportMock.h"
00031 #include "Imports.cpp"
00032
00033 namespace Protocols {
00034 namespace Generics {
00035 namespace Testing {
00036
00037 class DataChecker
00038 {
00039 Data data;
00040 Transport &transport;
00041
00042 public:
00043 DataChecker (const Data &d, Transport *t) : data (d), transport (*t) {}
00044
00045 typedef bool (Function) (Data &, Transport *);
00046
00047 bool check (Data &d, Transport *t)
00048 {
00049 if (t != &transport)
00050 return false;
00051 d = data;
00052 return true;
00053 }
00054 };
00055
00057
00061 class GenericSessionTest : public CppUnit::TestFixture
00062 {
00063 CPPUNIT_TEST_SUITE(GenericSessionTest);
00064 CPPUNIT_TEST (testOpenSessionStartsReading);
00065 CPPUNIT_TEST (testSentDataSerializedDirectly);
00066 CPPUNIT_TEST (testSentDataCannotBeSerializedMustBeQueued);
00067 CPPUNIT_TEST (testSentDataIsBufferedDirectly);
00068 CPPUNIT_TEST (testSentTwoDatasThatGetQueued);
00069 CPPUNIT_TEST (testWriteQueuedDataOnReadyWrite);
00070 CPPUNIT_TEST (testWriteTwoQueuedDatasOnReadyWrite);
00071 CPPUNIT_TEST (testWriteQueuedDataOnReadyWriteFails);
00072 CPPUNIT_TEST (testWriteTwoQueuedDatasOnReadyWriteSecondFails);
00073 CPPUNIT_TEST (testCannotReadPacketOnReadyRead);
00074 CPPUNIT_TEST (testReadTwoPacketsOnReadyRead);
00075 CPPUNIT_TEST (testCloseSessionDisconnectsTransportOnlyIfNothingToWrite);
00076 CPPUNIT_TEST (testCloseSessionDisconnectsTransportOnlyAfterQueueGetsEmpty);
00077 CPPUNIT_TEST (testAbortSessionAbortsTransportAndClosesSession);
00078 CPPUNIT_TEST (testCloseSessionFromSessionDataReceivedNotificationDisconnectDeferred);
00079 CPPUNIT_TEST (testAbortSessionFromSessionDataReceivedNotification);
00080 CPPUNIT_TEST_SUITE_END();
00081
00082 auto_ptr <TransportMock> transport;
00083 auto_ptr <DataSerializerMock> serializer;
00084 auto_ptr <SessionStatusMock> status;
00085 auto_ptr <DataQueueMock> queue;
00086 auto_ptr <GenericSession> sessionReal;
00087 auto_ptr <GenericSessionDriver> session;
00088
00089 const Data data1;
00090 const Data data2;
00091
00092 public:
00093 GenericSessionTest()
00094 : transport(), serializer(), status(), queue(), sessionReal(), session(),
00095 data1 (BadPacket ("header1", "payload1")),
00096 data2 (BadPacket ("header2", "payload2"))
00097 {
00098 }
00099
00100 void setUp()
00101 {
00102 transport.reset (new TransportMock);
00103 serializer.reset (new DataSerializerMock);
00104 status.reset (new SessionStatusMock);
00105 queue.reset (new DataQueueMock);
00106 sessionReal.reset (new GenericSession (*transport,
00107 *serializer,
00108 *queue,
00109 *status));
00110 session.reset (new GenericSessionDriver (*sessionReal.get()));
00111 }
00112
00113 void tearDown()
00114 {
00115 session.reset();
00116 sessionReal.reset();
00117 status.reset();
00118 queue.reset();
00119 serializer.reset();
00120 transport.reset();
00121 }
00122
00124
00131 void testOpenSessionStartsReading()
00132 {
00133 call (session->open())
00134
00135
00136 .willCall (serializer->read (checker (DataChecker (data1, *transport))))
00137 .willReturn (false)
00138 .returns();
00139 }
00140
00141 void stateSessionOpened()
00142 {
00143 testOpenSessionStartsReading();
00144 }
00145
00147 void refSentDataSerializedDirectly (const Data &data)
00148 {
00149 call (session->send (data))
00150 .willCall (status->sessionSendingData (*session, data))
00151 .returns()
00152 .willCall (queue->isEmpty())
00153 .willReturn (true)
00154 .willCall (serializer->write (data, *transport))
00155 .willReturn (true)
00156 .returns();
00157 }
00158
00159 void testSentDataSerializedDirectly()
00160 {
00161 stateSessionOpened();
00162 refSentDataSerializedDirectly (data1);
00163 }
00164
00169 void refSentDataCannotBeSerializedMustBeQueued (const Data &data)
00170 {
00171 call (session->send (data))
00172 .willCall (status->sessionSendingData (*session, data))
00173 .returns()
00174 .willCall (queue->isEmpty())
00175 .willReturn (true)
00176 .willCall (serializer->write (data, *transport))
00177 .willReturn (false)
00178 .willCall (queue->enqueue (data))
00179 .returns()
00180 .returns();
00181 }
00182
00183 void testSentDataCannotBeSerializedMustBeQueued()
00184 {
00185 stateSessionOpened();
00186 refSentDataCannotBeSerializedMustBeQueued (data1);
00187 }
00188
00190
00195 void refSentDataIsBufferedDirectly (const Data &data)
00196 {
00197 call (session->send (data))
00198 .willCall (status->sessionSendingData (*session, data))
00199 .returns()
00200 .willCall (queue->isEmpty())
00201 .willReturn (false)
00202 .willCall (queue->enqueue (data))
00203 .returns()
00204 .returns();
00205 }
00206
00207 void testSentDataIsBufferedDirectly()
00208 {
00209 stateSessionOpened();
00210 refSentDataIsBufferedDirectly (data1);
00211 }
00212
00213 void testSentTwoDatasThatGetQueued()
00214 {
00215 stateSessionOpened();
00216 refSentDataIsBufferedDirectly (data1);
00217 refSentDataIsBufferedDirectly (data2);
00218 }
00219
00220 void refWriteQueuedDatasOnReadyWrite (const QList <Data> &datas)
00221 {
00222 CallDriver <BoundFunction <GenericSession, void (Transport*)> > foo =
00223 call (session->transportReadyWrite (*transport));
00224
00225 bool wroteAll = true;
00226 foreach (const Data &data, datas) {
00227 foo
00228 .willCall (queue->isEmpty())
00229 .willReturn (false)
00230 .willCall (queue->next())
00231 .willReturn (data);
00232 if (data != Data()) {
00233 foo .willCall (serializer->write (data, *transport))
00234 .willReturn (true)
00235 .willCall (queue->dequeue())
00236 .returns();
00237 } else {
00238 foo .willCall (serializer->write (data, *transport))
00239 .willReturn (false);
00240 wroteAll = false;
00241 break;
00242 }
00243 }
00244 if (wroteAll) {
00245
00246 foo
00247 .willCall (queue->isEmpty())
00248 .willReturn (true);
00249 }
00250 foo.returns();
00251 }
00252
00253 void testWriteQueuedDataOnReadyWrite()
00254 {
00255 stateSessionOpened();
00256 refWriteQueuedDatasOnReadyWrite (QList <Data>() += data1);
00257 }
00258
00259 void testWriteTwoQueuedDatasOnReadyWrite()
00260 {
00261 stateSessionOpened();
00262 refWriteQueuedDatasOnReadyWrite ((QList <Data>() += data1) += data2);
00263 }
00264
00265 void testWriteQueuedDataOnReadyWriteFails()
00266 {
00267 stateSessionOpened();
00268 refWriteQueuedDatasOnReadyWrite (QList <Data>() += Data());
00269 }
00270
00271 void testWriteTwoQueuedDatasOnReadyWriteSecondFails()
00272 {
00273 stateSessionOpened();
00274 refWriteQueuedDatasOnReadyWrite ((QList <Data>() += data1) += Data());
00275 }
00276
00277 void refReadDatasOnReadyRead (const QList <Data> &datas)
00278 {
00279 CallDriver <BoundFunction <GenericSession, void (Transport*)> > foo =
00280 call (session->transportReadyRead (*transport));
00281
00282 foreach (const Data &data, datas) {
00283 foo
00284 .willCall (serializer->read (
00285 checker (DataChecker (data, *transport))))
00286 .willReturn (true)
00287 .willCall (status->sessionReceivedData (*session, data))
00288 .returns();
00289 }
00290
00291 Data data;
00292 foo
00293 .willCall (serializer->read (
00294 checker (DataChecker (data, *transport))))
00295 .willReturn (false)
00296 .returns();
00297 }
00298
00299 void testCannotReadPacketOnReadyRead()
00300 {
00301 stateSessionOpened();
00302 refReadDatasOnReadyRead (QList <Data>());
00303 }
00304
00305 void testReadTwoPacketsOnReadyRead()
00306 {
00307 stateSessionOpened();
00308 refReadDatasOnReadyRead ((QList <Data>() += data1) += data2);
00309 }
00310
00312 void refCloseSessionDisconnectsTransportImmediately()
00313 {
00314 call (session->close())
00315 .willCall (queue->isEmpty())
00316 .willReturn (true)
00317 .willCall (status->sessionClosing (*session))
00318 .returns()
00319 .willCall (transport->disconnectFromNode())
00320 .returns()
00321 .returns();
00322 }
00323
00324 void refCloseSessionDoesNotDisconnectTransportWhenQueueIsNotEmpty()
00325 {
00326 call (session->close())
00327 .willCall (queue->isEmpty())
00328 .willReturn (false)
00329 .willCall (status->sessionClosing (*session))
00330 .returns()
00331 .returns();
00332 }
00333
00334 void refTransportDisconnectedClosesTheSessionCompletely()
00335 {
00336 call (session->transportDisconnected (*transport))
00337 .willCall (status->sessionClosed (*session))
00338 .returns()
00339 .returns();
00340 }
00341
00342 void refTransportReadyWriteDisconnectsTransportWhenEmptyQueueAndClosing()
00343 {
00344 call (session->transportReadyWrite (*transport))
00345
00346 .willCall (queue->isEmpty())
00347 .willReturn (true)
00348
00349 .willCall (transport->disconnectFromNode())
00350 .returns()
00351 .returns();
00352 }
00353
00355 void testCloseSessionDisconnectsTransportOnlyIfNothingToWrite()
00356 {
00357 stateSessionOpened();
00358 refCloseSessionDisconnectsTransportImmediately();
00359 refTransportDisconnectedClosesTheSessionCompletely();
00360 }
00361
00363 void testCloseSessionDisconnectsTransportOnlyAfterQueueGetsEmpty()
00364 {
00365 stateSessionOpened();
00366 refCloseSessionDoesNotDisconnectTransportWhenQueueIsNotEmpty();
00367 refTransportReadyWriteDisconnectsTransportWhenEmptyQueueAndClosing();
00368 refTransportDisconnectedClosesTheSessionCompletely();
00369 }
00370
00371 void testAbortSessionAbortsTransportAndClosesSession()
00372 {
00373 call (session->abort())
00374 .willCall (status->sessionClosing (*session))
00375
00376
00377 .returns()
00378 .willCall (transport->abort())
00379 .willCall (session->transportDisconnected (*transport))
00380 .willCall (status->sessionClosed (*session))
00381 .returns()
00382 .returns()
00383 .returns()
00384 .returns();
00385 }
00386
00388
00393 void testCloseSessionFromSessionDataReceivedNotificationDisconnectDeferred()
00394 {
00395 stateSessionOpened();
00396
00397 call (session->transportReadyRead (*transport))
00398 .willCall (serializer->read (
00399 checker (DataChecker (data1, *transport))))
00400 .willReturn (true)
00401 .willCall (status->sessionReceivedData (*session, data1))
00402 .willCall (session->close())
00403 .willCall (status->sessionClosing (*session))
00404 .returns()
00405 .willCall (queue->isEmpty())
00406 .willReturn (false)
00407 .returns()
00408 .returns()
00409 .willCall (serializer->read (
00410 checker (DataChecker (Data(), *transport))))
00411 .willReturn (false)
00412 .returns();
00413 }
00414
00415 void testAbortSessionFromSessionDataReceivedNotification()
00416 {
00417 stateSessionOpened();
00418
00419 call (session->transportReadyRead (*transport))
00420 .willCall (serializer->read (
00421 checker (DataChecker (data1, *transport))))
00422 .willReturn (true)
00423 .willCall (status->sessionReceivedData (*session, data1))
00424 .willCall (session->abort())
00425 .willCall (status->sessionClosing (*session))
00426
00427
00428 .returns()
00429 .willCall (transport->abort())
00430 .willCall (session->transportDisconnected (*transport))
00431 .willCall (status->sessionClosed (*session))
00432 .returns()
00433 .returns()
00434 .returns()
00435 .returns()
00436 .returns()
00437 .returns();
00438 }
00439 };
00440
00441 CPPUNIT_TEST_SUITE_REGISTRATION (GenericSessionTest);
00442
00443 }
00444 }
00445 }