DataSerializerTest.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 "../DataSerializer.h"
00025 #include "../BodyEnd.h"
00026 #include "generated/BodyReaderMock.h"
00027 #include "generated/BodyWriterMock.h"
00028 #include "generated/DataSerializerDriver.h"
00029 #include "generated/ProtocolMock.h"
00030 #include "Imports.cpp"
00031 
00032 namespace Protocols {
00033 namespace Http {
00034 namespace Testing {
00035 
00037 
00073 class DataSerializerTest : public CppUnit::TestFixture
00074 {
00075     CPPUNIT_TEST_SUITE (DataSerializerTest);
00076     CPPUNIT_TEST (testReadHeaderFails);
00077     CPPUNIT_TEST (testReadHeader);
00078     CPPUNIT_TEST (testReadHeaderLfLfTerminated);
00079     CPPUNIT_TEST (testReadBodyOfOneChunk);
00080     CPPUNIT_TEST (testReadTwoMessages);
00081     CPPUNIT_TEST (testReadMessageWithInterrupts);
00082     CPPUNIT_TEST (testWriteHeaderFails);
00083     CPPUNIT_TEST (testWriteHeaderOK);
00084     CPPUNIT_TEST (testWriteBodyOfOneChunk);
00085     CPPUNIT_TEST (testWriteBodyOfMultipleChunksWithDelays);
00086     CPPUNIT_TEST (writeTwoMessages);
00087     CPPUNIT_TEST_SUITE_END();
00088 
00089     auto_ptr <TransportMock>            transport;
00090     auto_ptr <ProtocolMock>             protocol;
00091     auto_ptr <BodyReaderMock>           bodyReader;
00092     auto_ptr <BodyWriterMock>           bodyWriter;
00093     auto_ptr <DataSerializer>           serializerReal;
00094     auto_ptr <DataSerializerDriver>     serializer;
00095 
00096     HeaderBase                          header;
00097     BodyEnd                             bodyEnd;
00098     QList <Data>                        chunks;
00099 
00100 public:
00101     void setUp()
00102     {
00103         transport.reset (new TransportMock);
00104         protocol.reset (new ProtocolMock);
00105         bodyReader.reset (new BodyReaderMock);
00106         bodyWriter.reset (new BodyWriterMock);
00107         serializerReal.reset (new DataSerializer (*protocol));
00108         serializer.reset (new DataSerializerDriver (*serializerReal));
00109 
00110         header = HeaderBase();
00111         header.setFieldValue ("Transfer-Encoding", "identity");
00112         header.setFieldValue ("Content-Length", "10");
00113         bodyEnd = BodyEnd();
00114         bodyEnd.setFieldValue ("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ==");
00115         chunks = QList <Data>();
00116     }
00117 
00118     void tearDown()
00119     {
00120         serializer.reset();
00121         serializerReal.reset();
00122         bodyWriter.reset();
00123         bodyReader.reset();
00124         protocol.reset();
00125         transport.reset();
00126     }
00127 
00129 
00134     void refReadHeaderFails()
00135     {
00136         Data readHeader;
00137         call (serializer->read (readHeader, *transport))
00138             .willCall (transport->readTo ("\r\n\r\n"))
00139             .willReturn (QByteArray())
00140             .willCall (transport->readTo ("\n\n"))
00141             .willReturn (QByteArray())
00142         .willReturn (false);
00143 
00144         willBeEqual (readHeader, Data());
00145     }
00146 
00148     void refReadHeaderOK (const Header &header)
00149     {
00150         Data readHeader;
00151         call (serializer->read (readHeader, *transport))
00152             .willCall (transport->readTo ("\r\n\r\n"))
00153             .willReturn (header->toRawBytes())
00154             .willCall (protocol->createHeader (header->toRawBytes()))
00155             .willReturn (header)
00156             .willCall (protocol->createBodyReader (header))
00157             .willReturn (*bodyReader)
00158         .willReturn (true);
00159 
00160         willBeEqual (readHeader, Data (header));
00161     }
00162 
00164     void refReadLfTerminatedHeaderOK (const Header &header)
00165     {
00166         QByteArray rawHeader = header->toRawBytes().replace ("\r\n", "\n");
00167         Data readHeader;
00168         call (serializer->read (readHeader, *transport))
00169             .willCall (transport->readTo ("\r\n\r\n"))
00170             .willReturn (QByteArray())
00171             .willCall (transport->readTo ("\n\n"))
00172             .willReturn (rawHeader)
00173             .willCall (protocol->createHeader (rawHeader))
00174             .willReturn (header)
00175             .willCall (protocol->createBodyReader (header))
00176             .willReturn (*bodyReader)
00177         .willReturn (true);
00178 
00179         willBeEqual (readHeader, Data (header));
00180     }
00181 
00183     void refReadBodyChunk (const Data &chunk)
00184     {
00185         Data readBodyChunk;
00186         call (serializer->read (readBodyChunk, *transport))
00187             .willCall (bodyReader->read (*transport))
00188             .willReturn (chunk)
00189         .willReturn (true);
00190 
00191         willBeEqual (chunk, readBodyChunk);
00192     }
00193 
00195     void refReadBodyChunkFails()
00196     {
00197         Data readBodyChunk;
00198         call (serializer->read (readBodyChunk, *transport))
00199             .willCall (bodyReader->read (*transport))
00200             .willReturn (Data())
00201         .willReturn (false);
00202 
00203         willBeEqual (Data(), readBodyChunk);
00204     }
00205 
00207     void refReadBodyEnd()
00208     {
00209         Data readBodyChunk;
00210         call (serializer->read (readBodyChunk, *transport))
00211             .willCall (bodyReader->read (*transport))
00212             .willReturn (bodyEnd)
00213             .willCall (protocol->destroyBodyReader (*bodyReader))
00214             .returns()
00215         .willReturn (true);
00216 
00217         willBeEqual (Data (bodyEnd), readBodyChunk);
00218     }
00219 
00220     void stateReadingHeader()
00221     {
00222         refReadHeaderFails();
00223     }
00224 
00225     void stateReadingBody (const Header &header)
00226     {
00227         refReadHeaderOK (header);
00228     }
00229 
00230     void postStateReadingHeader()
00231     {
00232         refReadHeaderFails();
00233     }
00234 
00235     void postStateReadingBody()
00236     {
00237         refReadBodyChunkFails();
00238     }
00239 
00241     void scenarioReadHeaderFails()
00242     {
00243         stateReadingHeader();
00244         refReadHeaderFails();
00245         postStateReadingHeader();
00246     }
00247 
00249     void scenarioReadHeaderOK (const Header &header, bool lfTerminated = false)
00250     {
00251         stateReadingHeader();
00252         if (!lfTerminated)
00253             refReadHeaderOK (header);
00254         else
00255             refReadLfTerminatedHeaderOK (header);
00256         postStateReadingBody();
00257     }
00258 
00260     void scenarioReadBody (const Header &header,
00261                            const QList <Data> &bodyChunks)
00262     {
00263         stateReadingBody (header);
00264 
00265         foreach (Data bodyChunk, bodyChunks) {
00266             if (bodyChunk != Data())
00267                 refReadBodyChunk (bodyChunk);
00268             else
00269                 refReadBodyChunkFails();
00270         }
00271         refReadBodyEnd();
00272 
00273         postStateReadingHeader();
00274     }
00275 
00276     void testReadHeaderFails()
00277     {
00278         scenarioReadHeaderFails();
00279     }
00280 
00281     void testReadHeader()
00282     {
00283         scenarioReadHeaderOK (header);
00284     }
00285 
00286     void testReadHeaderLfLfTerminated()
00287     {
00288         scenarioReadHeaderOK (header, true);
00289     }
00290 
00291     void testReadBodyOfOneChunk()
00292     {
00293         chunks += RawData (QByteArray (40, '1'));
00294         scenarioReadBody (header, chunks);
00295     }
00296 
00297     void testReadTwoMessages()
00298     {
00299         testReadBodyOfOneChunk();
00300         testReadBodyOfOneChunk();
00301     }
00302 
00303     void testReadMessageWithInterrupts()
00304     {
00305         chunks += RawData (QByteArray (40, '1'));
00306         chunks += Data(); // The interruption of body chunks.
00307         chunks += RawData (QByteArray (10, '2'));
00308         scenarioReadBody (header, chunks);
00309     }
00310 
00312     void refWriteHeaderSucceeds (const Header &header)
00313     {
00314         call (serializer->write (header, *transport))
00315             .willCall (transport->write (header->toRawBytes()))
00316             .willReturn (true)
00317             .willCall (protocol->createBodyWriter (header))
00318             .willReturn (*bodyWriter)
00319         .willReturn (true);
00320     }
00321 
00323     void refWriteHeaderFails (const Header &header)
00324     {
00325         call (serializer->write (header, *transport))
00326             .willCall (transport->write (header->toRawBytes()))
00327             .willReturn (false)
00328         .willReturn (false);
00329     }
00330 
00332     void refWriteBodyChunk (const Data &chunk, bool willSucceed)
00333     {
00334         call (serializer->write (chunk, *transport))
00335             .willCall (bodyWriter->write (chunk, *transport))
00336             .willReturn (willSucceed)
00337         .willReturn (willSucceed);
00338     }
00339 
00340     void stateWritingHeader()
00341     {
00342         refWriteHeaderFails (Header());
00343     }
00344 
00345     void stateWritingBody (const Header &header)
00346     {
00347         refWriteHeaderSucceeds (header);
00348     }
00349 
00350     void postStateWritingHeader()
00351     {
00352         refWriteHeaderFails (Header());
00353     }
00354 
00355     void postStateWritingBody()
00356     {
00357         refWriteBodyChunk (RawData(), true);
00358     }
00359 
00361 
00366     void scenarioWriteHeaderFails (const Header &header)
00367     {
00368         stateWritingHeader();
00369         refWriteHeaderFails (header);
00370         postStateWritingHeader();
00371     }
00372 
00374 
00379     void scenarioWriteHeaderOK (const Header &header)
00380     {
00381         stateWritingHeader();
00382         refWriteHeaderSucceeds (header);
00383         postStateWritingBody();
00384     }
00385 
00387 
00397     void scenarioWriteBody (const Header &header, const QList <Data> &chunks)
00398     {
00399         stateWritingBody (header);
00400 
00401         foreach (Data chunk, chunks) {
00402             refWriteBodyChunk (chunk, false); // Optional in reality...
00403             refWriteBodyChunk (chunk, true);
00404         }
00405         refWriteBodyChunk (bodyEnd, false); // Optional in reality...
00406         call (serializer->write (bodyEnd, *transport))
00407             .willCall (bodyWriter->write (bodyEnd, *transport))
00408             .willReturn (true)
00409             .willCall (protocol->destroyBodyWriter (*bodyWriter))
00410             .returns()
00411         .willReturn (true);
00412 
00413         postStateWritingHeader();
00414     }
00415 
00416     void testWriteHeaderFails()
00417     {
00418         scenarioWriteHeaderFails (header);
00419     }
00420 
00421     void testWriteHeaderOK()
00422     {
00423         scenarioWriteHeaderOK (header);
00424     }
00425 
00426     void testWriteBodyOfOneChunk()
00427     {
00428         chunks += RawData (QByteArray (20, '2'));
00429         scenarioWriteBody (header, chunks);
00430     }
00431 
00432     void testWriteBodyOfMultipleChunksWithDelays()
00433     {
00434         chunks += RawData (QByteArray (20, '1'));
00435         chunks += Data();
00436         chunks += RawData (QByteArray (20, '3'));
00437         scenarioWriteBody (header, chunks);
00438     }
00439 
00440     void writeTwoMessages()
00441     {
00442         testWriteBodyOfMultipleChunksWithDelays();
00443         testWriteBodyOfMultipleChunksWithDelays();
00444     }
00445 };
00446 
00447 CPPUNIT_TEST_SUITE_REGISTRATION (DataSerializerTest);
00448 
00449 } // namespace Testing
00450 } // namespace Http
00451 } // namespace Protocols