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 "generated/TcpSocketBufferDriver.h"
00025 #include "generated/SocketMock.h"
00026 #include "Imports.h"
00027
00028 namespace Protocols {
00029 namespace Generics {
00030 namespace Testing {
00031
00033 class WriteCallChecker
00034 {
00035 QByteArray bytes;
00036
00037 public:
00038 WriteCallChecker (const QByteArray &bytes_)
00039 : bytes (bytes_) {}
00040
00041 typedef qint64 (Function) (const char *, qint64);
00042
00043 bool check (const char *source, qint64 size)
00044 {
00045 QByteArray checkBytes = QByteArray::fromRawData (source, size);
00046 return checkBytes == bytes;
00047 }
00048 };
00049
00051 class ReadCallChecker
00052 {
00053 QByteArray bytes;
00054
00055 public:
00056 ReadCallChecker (const QByteArray &bytes_)
00057 : bytes (bytes_) {}
00058
00059 typedef qint64 (Function) (char *, qint64);
00060
00061 bool check (char *destination, qint64 size)
00062 {
00063
00064 if (size < bytes.size())
00065 return false;
00066 int count = std::min (static_cast <int> (size), bytes.size());
00067 memcpy (destination, bytes.constData(), count);
00068 return true;
00069 }
00070 };
00071
00073
00082 class TcpSocketBufferTest : public CppUnit::TestFixture
00083 {
00084 CPPUNIT_TEST_SUITE (TcpSocketBufferTest);
00085 CPPUNIT_TEST (testWritingZeroBytesAlwaysSucceeds);
00086 CPPUNIT_TEST (testWriteBufferSizeBytesAtOnce);
00087 CPPUNIT_TEST (testWriteBufferSizeBytesAtOnceTwoTimes);
00088 CPPUNIT_TEST (testWriteBufferSizeBytesAtTwoWrites);
00089 CPPUNIT_TEST (testWriteMoreThanBufferSize);
00090 CPPUNIT_TEST (testPartialWriteToSocket7of10);
00091 CPPUNIT_TEST (testPartialWriteToSocket0of10);
00092 CPPUNIT_TEST (testPartialWriteToSocket_1of10);
00093 CPPUNIT_TEST (testPartialWriteToSocketWithRotate3ofLast5);
00094 CPPUNIT_TEST (testPartialWriteToSocketWithRotate0ofLast5);
00095 CPPUNIT_TEST (testPartialWriteToSocketWithRotate_1ofLast5);
00096 CPPUNIT_TEST (testTryReadFromFillsBuffer);
00097 CPPUNIT_TEST (testTryReadFromReadsNothing);
00098 CPPUNIT_TEST (testReadingZeroBytesAlwaysSucceeds);
00099 CPPUNIT_TEST (testReadsWhatWasReadFrom5rotate5);
00100 CPPUNIT_TEST (testReadsWhatWasReadFrom5rotate0);
00101 CPPUNIT_TEST (testTryReadFromAtOnceSocketReadReturns_1NoDataLost);
00102 CPPUNIT_TEST (testTryReadFromAtTwoReadsSocketReadReturns_1NoDataLost);
00103 CPPUNIT_TEST (testTryReadFromOnceThemMultipleNormalReads);
00104 CPPUNIT_TEST (testReadAll);
00105 CPPUNIT_TEST (testPeekAndPeekAll);
00106 CPPUNIT_TEST (testPeekToAndReadTo);
00107 CPPUNIT_TEST (testPeekToAndReadToWhenSeparatorInTwoChunks);
00108 CPPUNIT_TEST (testCanRead);
00109 CPPUNIT_TEST (testCanWrite);
00110 CPPUNIT_TEST (testPeekAtMostThenReadAtMost);
00111 CPPUNIT_TEST_SUITE_END();
00112
00113 static const int ReadBufferSize = 20;
00114 static const int WriteBufferSize = 20;
00115
00116 auto_ptr <SocketMock> socket;
00117 auto_ptr <TcpSocketBuffer> buffer_real;
00118 auto_ptr <TcpSocketBufferDriver> buffer;
00119
00120 public:
00121 TcpSocketBufferTest() : socket(), buffer_real(), buffer()
00122 {
00123 }
00124
00125 void setUp()
00126 {
00127 socket.reset (new SocketMock);
00128 buffer_real.reset (new TcpSocketBuffer (ReadBufferSize,
00129 WriteBufferSize));
00130 buffer.reset (new TcpSocketBufferDriver (*buffer_real.get()));
00131 }
00132
00133 void tearDown()
00134 {
00135 buffer.reset();
00136 buffer_real.reset();
00137 socket.reset();
00138 }
00139
00141 void refWriteBytesFails (const QByteArray &bytes, bool flush = true)
00142 {
00143 call (buffer->write (bytes, flush))
00144 .willReturn (false);
00145 }
00146
00148 void refWriteBytesSucceeds (const QByteArray &bytes, bool flush = true)
00149 {
00150 call (buffer->write (bytes, flush))
00151 .willReturn (true);
00152 }
00153
00155 void testWritingZeroBytesAlwaysSucceeds()
00156 {
00157 refWriteBytesSucceeds (QByteArray(), true);
00158 refWriteBytesSucceeds (QByteArray(), false);
00159 }
00160
00162 void testWriteBufferSizeBytesAtOnce()
00163 {
00164 refWriteBytesSucceeds (QByteArray (WriteBufferSize, '1'));
00165 refWriteBytesFails (QByteArray (1, '1'));
00166 }
00167
00169 void testWriteBufferSizeBytesAtOnceTwoTimes()
00170 {
00171 testWriteBufferSizeBytesAtOnce();
00172 refWriteToSocketAtOnce (QByteArray (WriteBufferSize, '1'));
00173
00174 testWriteBufferSizeBytesAtOnce();
00175 }
00176
00178 void testWriteBufferSizeBytesAtTwoWrites()
00179 {
00180 refWriteBytesSucceeds (QByteArray (1, '1'));
00181 refWriteBytesSucceeds (QByteArray (WriteBufferSize - 1, '1'));
00182 refWriteBytesFails (QByteArray (1, '1'));
00183 }
00184
00186 void testWriteMoreThanBufferSize()
00187 {
00188 refWriteBytesFails (QByteArray (WriteBufferSize + 1, '1'));
00189 }
00190
00192 void refWriteToSocketAtOnce (const QByteArray &bytes)
00193 {
00194 refWriteToSocketAtOncePartially (bytes, bytes.count());
00195 }
00196
00198 void refWriteToSocketAtOncePartially (const QByteArray &bytes,
00199 int countWritten)
00200 {
00201 Q_ASSERT (countWritten <= bytes.size());
00202 call (buffer->tryWriteTo (*socket))
00203 .willCall (socket->write (checker (WriteCallChecker (bytes))))
00204 .willReturn (countWritten)
00205 .returns();
00206 }
00207
00209
00213 void refWriteToSocketAtTwoChunks (const QByteArray &bytes1,
00214 const QByteArray &bytes2)
00215 {
00216
00217 refWriteToSocketAtTwoChunksSecondPartially (bytes1, bytes2,
00218 bytes2.size());
00219 }
00220
00223 void refWriteToSocketAtTwoChunksSecondPartially (const QByteArray &bytes1,
00224 const QByteArray &bytes2,
00225 int countWrittenBytes2)
00226 {
00227 Q_ASSERT (countWrittenBytes2 <= bytes2.size());
00228 call (buffer->tryWriteTo (*socket))
00229 .willCall (socket->write (checker (WriteCallChecker (bytes1))))
00230 .willReturn (bytes1.size())
00231 .willCall (socket->write (checker (WriteCallChecker (bytes2))))
00232 .willReturn (countWrittenBytes2)
00233 .returns();
00234 }
00235
00237 void testRingBufferRotate()
00238 {
00239 refWriteBytesSucceeds (QByteArray (5, '1'));
00240 refWriteToSocketAtOnce (QByteArray (5, '1'));
00241
00242 refWriteBytesSucceeds (QByteArray (WriteBufferSize, '1'));
00243 refWriteToSocketAtTwoChunks (QByteArray (WriteBufferSize - 5, '1'),
00244 QByteArray (5, '1'));
00245 }
00246
00248
00252 void scenarioPartialWriteToSocketDoesNotLooseData (int countAll,
00253 int countWritten)
00254 {
00255 QByteArray bytes (countAll, '1');
00256 refWriteBytesSucceeds (bytes);
00257 refWriteToSocketAtOncePartially (bytes, countWritten);
00258
00259 refWriteToSocketAtOnce (bytes.mid (countWritten));
00260 }
00261
00263 void testPartialWriteToSocket7of10()
00264 {
00265 scenarioPartialWriteToSocketDoesNotLooseData (10, 7);
00266 }
00267
00269 void testPartialWriteToSocket0of10()
00270 {
00271 scenarioPartialWriteToSocketDoesNotLooseData (10, 0);
00272 }
00273
00275 void testPartialWriteToSocket_1of10()
00276 {
00277 scenarioPartialWriteToSocketDoesNotLooseData (10, -1);
00278 }
00279
00281
00292 void scenarioPartialWriteToSocketWithRotationDoesNotLoseData (int offset,
00293 int count)
00294 {
00295 Q_ASSERT (offset > 0);
00296 Q_ASSERT (offset <= WriteBufferSize);
00297 QByteArray bytes1 (offset, '1');
00298 QByteArray bytes2 (WriteBufferSize, '1');
00299 QByteArray bytes2chunk1 = bytes2.left (WriteBufferSize - offset);
00300 QByteArray bytes2chunk2 = bytes2.mid (WriteBufferSize - offset);
00301
00302 refWriteBytesSucceeds (bytes1);
00303 refWriteToSocketAtOnce (bytes1);
00304
00305 refWriteBytesSucceeds (bytes2);
00306 refWriteToSocketAtTwoChunksSecondPartially (bytes2chunk1, bytes2chunk2,
00307 count);
00308
00309 refWriteToSocketAtOnce (bytes2chunk2.mid (count));
00310 }
00311
00313 void testPartialWriteToSocketWithRotate3ofLast5()
00314 {
00315 scenarioPartialWriteToSocketWithRotationDoesNotLoseData (5, 3);
00316 }
00317
00319 void testPartialWriteToSocketWithRotate0ofLast5()
00320 {
00321 scenarioPartialWriteToSocketWithRotationDoesNotLoseData (5, 0);
00322 }
00323
00325 void testPartialWriteToSocketWithRotate_1ofLast5()
00326 {
00327 scenarioPartialWriteToSocketWithRotationDoesNotLoseData (5, -1);
00328 }
00329
00331 void refReadBytesSucceeds (const QByteArray &bytes)
00332 {
00333 call (buffer->read (bytes.count()))
00334 .willReturn (bytes);
00335 }
00336
00338 void refReadBytesFails (int count)
00339 {
00340 call (buffer->read (count))
00341 .willReturn (QByteArray());
00342 }
00343
00345 void refTryReadFromAtOnce (const QByteArray &bytes)
00346 {
00347 call (buffer->tryReadFrom (*socket))
00348 .willCall (socket->read (checker (ReadCallChecker (bytes))))
00349 .willReturn (bytes.size())
00350 .returns();
00351 }
00352
00354
00357 void refTryReadFromAtTwoReads (const QByteArray &bytes1,
00358 const QByteArray &bytes2)
00359 {
00360 call (buffer->tryReadFrom (*socket))
00361 .willCall (socket->read (checker (ReadCallChecker (bytes1))))
00362 .willReturn (bytes1.size())
00363 .willCall (socket->read (checker (ReadCallChecker (bytes2))))
00364 .willReturn (bytes2.size())
00365 .returns();
00366 }
00367
00369 void testTryReadFromFillsBuffer()
00370 {
00371 refTryReadFromAtOnce (QByteArray (ReadBufferSize, '1'));
00372 }
00373
00375 void testTryReadFromReadsNothing()
00376 {
00377 refTryReadFromAtOnce (QByteArray());
00378 }
00379
00381 void testReadingZeroBytesAlwaysSucceeds()
00382 {
00383
00384 refReadBytesSucceeds (QByteArray());
00385 refReadBytesFails (0);
00386
00387 testTryReadFromFillsBuffer();
00388 refReadBytesSucceeds (QByteArray());
00389 }
00390
00392
00398 void scenarioReadsWhatWasReadFrom (int offset, int secondSize)
00399 {
00400 Q_ASSERT (offset <= ReadBufferSize);
00401 QByteArray bytes1 (offset, '1');
00402 QByteArray bytes2 (ReadBufferSize - offset, '2');
00403 QByteArray bytes3 (secondSize, '2');
00404
00405 refTryReadFromAtOnce (bytes1);
00406 refReadBytesSucceeds (bytes1);
00407 refTryReadFromAtTwoReads (bytes2, bytes3);
00408 refReadBytesSucceeds (bytes2 + bytes3);
00409 }
00410
00412 void testReadsWhatWasReadFrom5rotate5()
00413 {
00414 scenarioReadsWhatWasReadFrom (5, 5);
00415 }
00416
00418 void testReadsWhatWasReadFrom5rotate0()
00419 {
00420 scenarioReadsWhatWasReadFrom (5, 0);
00421 }
00422
00424 void testTryReadFromAtOnceSocketReadReturns_1NoDataLost()
00425 {
00426 QByteArray bytes ("1234567890");
00427 refTryReadFromAtOnce (bytes);
00428
00429 call (buffer->tryReadFrom (*socket))
00430 .willCall (socket->read (checker (ReadCallChecker (QByteArray()))))
00431 .willReturn (-1)
00432 .returns();
00433
00434 refReadBytesSucceeds (bytes);
00435 }
00436
00438 void testTryReadFromAtTwoReadsSocketReadReturns_1NoDataLost()
00439 {
00440 QByteArray bytes1 (5, '1');
00441 QByteArray bytes2 (ReadBufferSize - 5, '1');
00442
00443 refTryReadFromAtOnce (bytes1);
00444 refReadBytesSucceeds (bytes1);
00445
00446 call (buffer->tryReadFrom (*socket))
00447 .willCall (socket->read (checker (ReadCallChecker (bytes2))))
00448 .willReturn (bytes2.size())
00449 .willCall (socket->read (checker (ReadCallChecker (QByteArray()))))
00450 .willReturn (-1)
00451 .returns();
00452 refReadBytesSucceeds (bytes2);
00453 }
00454
00456 void testTryReadFromOnceThemMultipleNormalReads()
00457 {
00458 QByteArray bytes ("1234567890");
00459 refTryReadFromAtOnce (bytes);
00460 refReadBytesSucceeds (bytes.left (3));
00461 refReadBytesSucceeds (bytes.mid (3, 3));
00462 refReadBytesSucceeds (bytes.mid (6));
00463 }
00464
00466 void testReadAll()
00467 {
00468
00469 QByteArray bytes1 (10, '1');
00470 refTryReadFromAtOnce (bytes1);
00471
00472 call (buffer->readAll())
00473 .willReturn (bytes1);
00474
00475
00476 QByteArray bytes2 (ReadBufferSize - bytes1.size(), '2');
00477 refTryReadFromAtTwoReads (bytes2, bytes1);
00478
00479 call (buffer->readAll())
00480 .willReturn (bytes2 + bytes1);
00481 }
00482
00484 void testPeekAndPeekAll()
00485 {
00486
00487 QByteArray bytes ("1234567890");
00488 refTryReadFromAtOnce (bytes);
00489
00490 call (buffer->peek (bytes.count()))
00491 .willReturn (bytes);
00492
00493 call (buffer->peekAll())
00494 .willReturn (bytes);
00495
00496 call (buffer->readAll())
00497 .willReturn (bytes);
00498 }
00499
00501 void refPeekToAndReadTo (const QByteArray &delimiter,
00502 const QByteArray &bytes)
00503 {
00504 call (buffer->peekTo (delimiter))
00505 .willReturn (bytes);
00506
00507 call (buffer->readTo (delimiter))
00508 .willReturn (bytes);
00509 }
00510
00512 void testPeekToAndReadTo()
00513 {
00514 QByteArray bytes ("1234567890cc12");
00515 refTryReadFromAtOnce (bytes);
00516 refPeekToAndReadTo ("cc", bytes.left (12));
00517 refReadBytesSucceeds (bytes.right (2));
00518 }
00519
00521 void testPeekToAndReadToWhenSeparatorInTwoChunks()
00522 {
00523 QByteArray bytes1 (5, '1');
00524 refTryReadFromAtOnce (bytes1);
00525 refReadBytesSucceeds (bytes1);
00526
00527
00528 QByteArray bytes2 (ReadBufferSize - bytes1.size() - 1, '2');
00529 QByteArray bytes3 (bytes1.size() - 1, '2');
00530 refTryReadFromAtTwoReads (bytes2 + "c", "c" + bytes3);
00531
00532 refPeekToAndReadTo ("cc", bytes2 + "cc");
00533 refReadBytesSucceeds (bytes3);
00534 }
00535
00536 void refCanRead (int count, bool canRead)
00537 {
00538 call (buffer->canRead (count))
00539 .willReturn (canRead);
00540 }
00541
00542 void testCanRead()
00543 {
00544
00545 refCanRead (0, true);
00546 refCanRead (1, false);
00547 refCanRead (ReadBufferSize, false);
00548
00549 refTryReadFromAtOnce (QByteArray (ReadBufferSize, '0'));
00550 refCanRead (0, true);
00551 refCanRead (1, true);
00552 refCanRead (ReadBufferSize, true);
00553 refCanRead (ReadBufferSize + 1, false);
00554 }
00555
00556 void refCanWrite (int count, bool canWrite)
00557 {
00558 call (buffer->canWrite (count))
00559 .willReturn (canWrite);
00560 }
00561
00562 void testCanWrite()
00563 {
00564 refCanWrite (0, true);
00565 refCanWrite (1, true);
00566 refCanWrite (10, true);
00567 refCanWrite (ReadBufferSize, true);
00568 refCanWrite (ReadBufferSize + 1, false);
00569
00570 refWriteBytesSucceeds (QByteArray (ReadBufferSize - 1, '0'));
00571 refCanWrite (0, true);
00572 refCanWrite (1, true);
00573 refCanWrite (2, false);
00574
00575 refWriteBytesSucceeds (QByteArray (1, '1'));
00576 refCanWrite (0, true);
00577 refCanWrite (1, false);
00578 }
00579
00580 void testPeekAtMostThenReadAtMost()
00581 {
00582 QByteArray bytes (ReadBufferSize / 2, '1');
00583 refTryReadFromAtOnce (bytes);
00584
00585 call (buffer->peekAtMost (ReadBufferSize))
00586 .willReturn (bytes);
00587
00588 call (buffer->readAtMost (ReadBufferSize))
00589 .willReturn (bytes);
00590
00591 refCanRead (0, true);
00592 refCanRead (1, false);
00593 }
00594 };
00595
00596 CPPUNIT_TEST_SUITE_REGISTRATION (TcpSocketBufferTest);
00597
00598 }
00599 }
00600 }