BinaryReaderTest.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 "../BinaryReader.h"
00025 #include "cppunit/extensions/HelperMacros.h"
00026 
00027 namespace Utils {
00028 namespace Encodings {
00029 
00030 class BinaryReaderTest : public CppUnit::TestFixture
00031 {
00032     CPPUNIT_TEST_SUITE(BinaryReaderTest);
00033     CPPUNIT_TEST(testCtors);
00034     CPPUNIT_TEST(testSetProperties);
00035     CPPUNIT_TEST(testReadInts);
00036     CPPUNIT_TEST(testReadBytes);
00037     CPPUNIT_TEST(testReadStrings);
00038     CPPUNIT_TEST(testReadPastEnd);
00039     CPPUNIT_TEST_SUITE_END();
00040 
00041 public:
00042     void setUp()
00043     {
00044     }
00045 
00046     void tearDown()
00047     {
00048     }
00049 
00050     void testCtors()
00051     {
00052         QByteArray emptyBuffer;
00053         {
00054             BinaryReader reader (emptyBuffer, BinaryReader::LittleEndian);
00055             CPPUNIT_ASSERT (BinaryReader::LittleEndian == reader.byteOrder());
00056             CPPUNIT_ASSERT (BinaryReader::ReadFromStart == reader.readOrigin());
00057             CPPUNIT_ASSERT (reader.hasReadAll());
00058             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00059         }
00060         {
00061             BinaryReader reader (emptyBuffer, BinaryReader::BigEndian);
00062             CPPUNIT_ASSERT (BinaryReader::BigEndian == reader.byteOrder());
00063             CPPUNIT_ASSERT (BinaryReader::ReadFromStart == reader.readOrigin());
00064             CPPUNIT_ASSERT (reader.hasReadAll());
00065             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00066             CPPUNIT_ASSERT (reader.canRead(0));
00067             CPPUNIT_ASSERT (!reader.canRead(1));
00068 
00069         }
00070         QByteArray nonEmtpyBuffer (4, '\0');
00071         {
00072             BinaryReader reader (nonEmtpyBuffer, BinaryReader::LittleEndian);
00073             CPPUNIT_ASSERT (!reader.hasReadAll());
00074             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00075             CPPUNIT_ASSERT (reader.canRead(0));
00076             CPPUNIT_ASSERT (reader.canRead(1));
00077             CPPUNIT_ASSERT (reader.canRead(2));
00078             CPPUNIT_ASSERT (reader.canRead(4));
00079             CPPUNIT_ASSERT (!reader.canRead(5));
00080         }
00081     }
00082 
00083     void testSetProperties()
00084     {
00085         QByteArray emptyBuffer;
00086         BinaryReader reader (emptyBuffer, BinaryReader::LittleEndian);
00087         // Test byte order:
00088         reader.setByteOrder (BinaryReader::BigEndian);
00089         CPPUNIT_ASSERT (BinaryReader::BigEndian == reader.byteOrder());
00090         reader.setByteOrder (BinaryReader::LittleEndian);
00091         CPPUNIT_ASSERT (BinaryReader::LittleEndian == reader.byteOrder());
00092         // Test read origin:
00093         reader.setReadOrigin (BinaryReader::ReadFromEnd);
00094         CPPUNIT_ASSERT (BinaryReader::ReadFromEnd == reader.readOrigin());
00095         reader.setReadOrigin (BinaryReader::ReadFromStart);
00096         CPPUNIT_ASSERT (BinaryReader::ReadFromStart == reader.readOrigin());
00097     }
00098 
00099     void testReadInts()
00100     {
00101         char rawData[] = { 0x00, 0x01,
00102                            0x02, 0x03,
00103                            0x04, 0x05, 0x06, 0x07,
00104                            0x08, 0x09, 0x0A, 0x0B,
00105                            0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
00106                            0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B };
00107 
00108         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00109         { // Test little endian reading form start:
00110             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00111             CPPUNIT_ASSERT (0x0100 == reader.readUInt16());
00112             CPPUNIT_ASSERT (0x0302 == reader.readInt16());
00113             CPPUNIT_ASSERT (0x04   == reader.lookAhead(1));
00114             CPPUNIT_ASSERT (0x05   == reader.lookAhead(2));
00115             CPPUNIT_ASSERT (0x0D   == reader.lookAhead(10));
00116             CPPUNIT_ASSERT (reader.canRead(24));
00117             CPPUNIT_ASSERT (0x1B   == reader.lookAhead(24));
00118             CPPUNIT_ASSERT (!reader.canRead(25));
00119             CPPUNIT_ASSERT (0x00   == reader.lookAhead(25));
00120             CPPUNIT_ASSERT (0x07060504 == reader.readUInt32());
00121             CPPUNIT_ASSERT (0x0B0A0908 == reader.readInt32());
00122             CPPUNIT_ASSERT (Q_INT64_C (0x131211100F0E0D0C) == reader.readUInt64());
00123             CPPUNIT_ASSERT (Q_INT64_C (0x1B1A191817161514) == reader.readInt64());
00124             CPPUNIT_ASSERT (reader.hasReadAll());
00125             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00126             // Try reading past end:
00127             CPPUNIT_ASSERT (0 == reader.readUInt16());
00128             CPPUNIT_ASSERT (reader.hasReadAll());
00129             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00130         }
00131         { // Test big endian reading from start:
00132             BinaryReader reader (buffer, BinaryReader::BigEndian);
00133             CPPUNIT_ASSERT (0x0001 == reader.readUInt16());
00134             CPPUNIT_ASSERT (0x0203 == reader.readInt16());
00135             CPPUNIT_ASSERT (0x04   == reader.lookAhead(1));
00136             CPPUNIT_ASSERT (0x05   == reader.lookAhead(2));
00137             CPPUNIT_ASSERT (0x0D   == reader.lookAhead(10));
00138             CPPUNIT_ASSERT (0x04050607 == reader.readUInt32());
00139             CPPUNIT_ASSERT (0x08090A0B == reader.readInt32());
00140             CPPUNIT_ASSERT (Q_INT64_C (0x0C0D0E0F10111213) == reader.readUInt64());
00141             CPPUNIT_ASSERT (Q_INT64_C (0x1415161718191A1B) == reader.readInt64());
00142             CPPUNIT_ASSERT (reader.hasReadAll());
00143             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00144             // Try reading past end:
00145             CPPUNIT_ASSERT (0 == reader.readUInt16());
00146             CPPUNIT_ASSERT (reader.hasReadAll());
00147             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00148         }
00149         { // Test little endian reading from end:
00150             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00151             reader.setReadOrigin (BinaryReader::ReadFromEnd);
00152             CPPUNIT_ASSERT (Q_INT64_C (0x1B1A191817161514) == reader.readInt64());
00153             CPPUNIT_ASSERT (Q_INT64_C (0x131211100F0E0D0C) == reader.readUInt64());
00154             CPPUNIT_ASSERT (0x0B   == reader.lookAhead(1));
00155             CPPUNIT_ASSERT (0x0A   == reader.lookAhead(2));
00156             CPPUNIT_ASSERT (0x02   == reader.lookAhead(10));
00157             CPPUNIT_ASSERT (0x0B0A0908 == reader.readInt32());
00158             CPPUNIT_ASSERT (0x07060504 == reader.readUInt32());
00159             CPPUNIT_ASSERT (0x0302 == reader.readInt16());
00160             CPPUNIT_ASSERT (0x0100 == reader.readUInt16());
00161             CPPUNIT_ASSERT (reader.hasReadAll());
00162             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00163             // Try reading past end:
00164             CPPUNIT_ASSERT (0 == reader.readUInt16());
00165             CPPUNIT_ASSERT (reader.hasReadAll());
00166             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00167         }
00168         { // Test big endian readinf from end:
00169             BinaryReader reader (buffer, BinaryReader::BigEndian);
00170             reader.setReadOrigin (BinaryReader::ReadFromEnd);
00171             CPPUNIT_ASSERT (Q_INT64_C (0x1415161718191A1B) == reader.readInt64());
00172             CPPUNIT_ASSERT (Q_INT64_C (0x0C0D0E0F10111213) == reader.readUInt64());
00173             CPPUNIT_ASSERT (0x0B   == reader.lookAhead(1));
00174             CPPUNIT_ASSERT (0x0A   == reader.lookAhead(2));
00175             CPPUNIT_ASSERT (0x02   == reader.lookAhead(10));
00176             CPPUNIT_ASSERT (0x00   == reader.lookAhead(12));
00177             CPPUNIT_ASSERT (0x00   == reader.lookAhead(13));
00178             CPPUNIT_ASSERT (0x08090A0B == reader.readInt32());
00179             CPPUNIT_ASSERT (0x04050607 == reader.readUInt32());
00180             CPPUNIT_ASSERT (0x0203 == reader.readInt16());
00181             CPPUNIT_ASSERT (0x0001 == reader.readUInt16());
00182             CPPUNIT_ASSERT (reader.hasReadAll());
00183             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00184             // Try reading past end:
00185             CPPUNIT_ASSERT (0 == reader.readUInt16());
00186             CPPUNIT_ASSERT (reader.hasReadAll());
00187             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00188         }
00189     }
00190 
00191     void testReadBytes()
00192     {
00193         char rawData[] = { 0x00,
00194                            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
00195                            0x08 };
00196 
00197         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00198         // Byte order MUST NOT matter:
00199         { // Try with big endian, read from start:
00200             BinaryReader reader (buffer, BinaryReader::BigEndian);
00201             // default read origin MUST be from start
00202             // read single byte:
00203             CPPUNIT_ASSERT (0x00 == reader.readByte());
00204             // read multiple bytes:
00205             QByteArray readBytes = reader.readBytes (7);
00206             CPPUNIT_ASSERT (readBytes.size() == 7);
00207             CPPUNIT_ASSERT (memcmp (rawData + 1, readBytes.constData(), 7) == 0);
00208             // read zero bytes:
00209             readBytes = reader.readBytes (0);
00210             CPPUNIT_ASSERT (readBytes.size() == 0);
00211             // read the last byte:
00212             CPPUNIT_ASSERT (0x08 == reader.readByte());
00213             // Make sure all was read and not past end:
00214             CPPUNIT_ASSERT (reader.hasReadAll());
00215             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00216             // Try reading past end:
00217             readBytes = reader.readBytes (6);
00218             CPPUNIT_ASSERT (6 == readBytes.size());
00219             CPPUNIT_ASSERT (reader.hasReadAll());
00220             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00221         }
00222         { // Try the exact same test with little endian, read from start:
00223             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00224             // read single byte:
00225             CPPUNIT_ASSERT (0x00 == reader.readByte());
00226             // read multiple bytes:
00227             QByteArray readBytes = reader.readBytes (7);
00228             CPPUNIT_ASSERT (readBytes.size() == 7);
00229             CPPUNIT_ASSERT (memcmp (rawData + 1, readBytes.constData(), 7) == 0);
00230             // read zero bytes:
00231             readBytes = reader.readBytes (0);
00232             CPPUNIT_ASSERT (readBytes.size() == 0);
00233             // read the last byte:
00234             CPPUNIT_ASSERT (0x08 == reader.readByte());
00235             // Make sure all was read and not past end:
00236             CPPUNIT_ASSERT (reader.hasReadAll());
00237             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00238             // Try reading past end:
00239             readBytes = reader.readBytes (6);
00240             CPPUNIT_ASSERT (6 == readBytes.size());
00241             CPPUNIT_ASSERT (reader.hasReadAll());
00242             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00243         }
00244         { // Try with big endian, read from start:
00245             BinaryReader reader (buffer, BinaryReader::BigEndian);
00246             reader.setReadOrigin (BinaryReader::ReadFromEnd);
00247             // read single byte:
00248             CPPUNIT_ASSERT (0x08 == reader.readByte());
00249             // read multiple bytes:
00250             QByteArray readBytes = reader.readBytes (7);
00251             CPPUNIT_ASSERT (readBytes.size() == 7);
00252             CPPUNIT_ASSERT (memcmp (rawData + 1, readBytes.constData(), 7) == 0);
00253             // read zero bytes:
00254             readBytes = reader.readBytes (0);
00255             CPPUNIT_ASSERT (readBytes.size() == 0);
00256             // read the last byte:
00257             CPPUNIT_ASSERT (0x00 == reader.readByte());
00258             // Make sure all was read and not past end:
00259             CPPUNIT_ASSERT (reader.hasReadAll());
00260             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00261             // Try reading past end:
00262             readBytes = reader.readBytes (6);
00263             CPPUNIT_ASSERT (6 == readBytes.size());
00264             CPPUNIT_ASSERT (reader.hasReadAll());
00265             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00266         }
00267         { // Try the exact same test with little endian, read from start:
00268             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00269             reader.setReadOrigin (BinaryReader::ReadFromEnd);
00270             // read single byte:
00271             CPPUNIT_ASSERT (0x08 == reader.readByte());
00272             // read multiple bytes:
00273             QByteArray readBytes = reader.readBytes (7);
00274             CPPUNIT_ASSERT (readBytes.size() == 7);
00275             CPPUNIT_ASSERT (memcmp (rawData + 1, readBytes.constData(), 7) == 0);
00276             // read zero bytes:
00277             readBytes = reader.readBytes (0);
00278             CPPUNIT_ASSERT (0 == readBytes.size());
00279             // read the last byte:
00280             CPPUNIT_ASSERT (0x00 == reader.readByte());
00281             // Make sure all was read and not past end:
00282             CPPUNIT_ASSERT (reader.hasReadAll());
00283             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00284             // Try reading past end:
00285             readBytes = reader.readBytes (6);
00286             CPPUNIT_ASSERT (6 == readBytes.size());
00287             CPPUNIT_ASSERT (reader.hasReadAll());
00288             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00289         }
00290         {
00291             BinaryReader reader (buffer, BinaryReader::BigEndian);
00292             CPPUNIT_ASSERT (buffer == reader.readAll());
00293             // Should not be able to read all bytes again:
00294             CPPUNIT_ASSERT (QByteArray() == reader.readAll());
00295         }
00296     }
00297 
00298     void testReadStrings()
00299     {
00300         char rawData[] = "\0non empty\0"; // One more \0 IS PUT by the compiler!
00301 
00302         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00303         // Endianness MUST NOT matter:
00304         { // Little endian, from start:
00305             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00306             QByteArray string = reader.readString();
00307             CPPUNIT_ASSERT (0 == string.length());
00308             string = reader.readString();
00309             CPPUNIT_ASSERT (string == "non empty");
00310             string = reader.readString();
00311             CPPUNIT_ASSERT (0 == string.length());
00312             CPPUNIT_ASSERT (reader.hasReadAll());
00313             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00314             // Try read past end:
00315             string = reader.readString();
00316             CPPUNIT_ASSERT (0 == string.length());
00317             CPPUNIT_ASSERT (reader.hasReadAll());
00318             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00319         }
00320         { // Big endian, from start:
00321             BinaryReader reader (buffer, BinaryReader::BigEndian);
00322             QByteArray string = reader.readString();
00323             CPPUNIT_ASSERT (0 == string.length());
00324             string = reader.readString();
00325             CPPUNIT_ASSERT (string == "non empty");
00326             string = reader.readString();
00327             CPPUNIT_ASSERT (0 == string.length());
00328             CPPUNIT_ASSERT (reader.hasReadAll());
00329             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00330             // Try read past end:
00331             string = reader.readString();
00332             CPPUNIT_ASSERT (0 == string.length());
00333             CPPUNIT_ASSERT (reader.hasReadAll());
00334             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00335         }
00336         { // Little endian, from end:
00337             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00338             reader.setReadOrigin (BinaryReader::ReadFromEnd);
00339             QByteArray string = reader.readString();
00340             CPPUNIT_ASSERT (0 == string.length());
00341             string = reader.readString();
00342             CPPUNIT_ASSERT (0 == string.length());
00343             string = reader.readString();
00344             CPPUNIT_ASSERT (string == "non empty");
00345             CPPUNIT_ASSERT (reader.hasReadAll());
00346             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00347             // Try read past end:
00348             string = reader.readString();
00349             CPPUNIT_ASSERT (0 == string.length());
00350             CPPUNIT_ASSERT (reader.hasReadAll());
00351             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00352         }
00353         { // Big endian, from end:
00354             BinaryReader reader (buffer, BinaryReader::BigEndian);
00355             reader.setReadOrigin (BinaryReader::ReadFromEnd);
00356             QByteArray string = reader.readString();
00357             CPPUNIT_ASSERT (0 == string.length());
00358             string = reader.readString();
00359             CPPUNIT_ASSERT (0 == string.length());
00360             string = reader.readString();
00361             CPPUNIT_ASSERT (string == "non empty");
00362             CPPUNIT_ASSERT (reader.hasReadAll());
00363             CPPUNIT_ASSERT (!reader.hasReadPastEnd());
00364             // Try read past end:
00365             string = reader.readString();
00366             CPPUNIT_ASSERT (0 == string.length());
00367             CPPUNIT_ASSERT (reader.hasReadAll());
00368             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00369         }
00370     }
00371 
00372     void testReadPastEnd()
00373     {
00374         // We already tested reading past the end after the complete buffer
00375         // was read completely. Here we will test when half of the integer,
00376         // for example, is within bounds and the rest is past the bounds.
00377         char rawData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
00378         QByteArray buffer (rawData, sizeof (rawData));
00379         {
00380             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00381             reader.readBytes (7);
00382             CPPUNIT_ASSERT (0 == reader.readUInt16());
00383             CPPUNIT_ASSERT (reader.hasReadAll());
00384             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00385         }
00386         {
00387             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00388             reader.readBytes (7);
00389             CPPUNIT_ASSERT (0 == reader.readInt16());
00390             CPPUNIT_ASSERT (reader.hasReadAll());
00391             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00392         }
00393         {
00394             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00395             reader.readBytes (7);
00396             CPPUNIT_ASSERT (0 == reader.readUInt32());
00397             CPPUNIT_ASSERT (reader.hasReadAll());
00398             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00399         }
00400         {
00401             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00402             reader.readBytes (7);
00403             CPPUNIT_ASSERT (0 == reader.readInt32());
00404             CPPUNIT_ASSERT (reader.hasReadAll());
00405             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00406         }
00407         {
00408             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00409             reader.readBytes (7);
00410             CPPUNIT_ASSERT (0 == reader.readUInt64());
00411             CPPUNIT_ASSERT (reader.hasReadAll());
00412             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00413         }
00414         {
00415             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00416             reader.readBytes (7);
00417             CPPUNIT_ASSERT (0 == reader.readInt64());
00418             CPPUNIT_ASSERT (reader.hasReadAll());
00419             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00420         }
00421         {
00422             BinaryReader reader (buffer, BinaryReader::LittleEndian);
00423             reader.readBytes (7);
00424             QByteArray readBytes = reader.readBytes (4);
00425             CPPUNIT_ASSERT (4 == readBytes.size());
00426             CPPUNIT_ASSERT (reader.hasReadAll());
00427             CPPUNIT_ASSERT (reader.hasReadPastEnd());
00428         }
00429     }
00430 };
00431 
00432 CPPUNIT_TEST_SUITE_REGISTRATION(BinaryReaderTest);
00433 
00434 } // namespace Codings
00435 } // namespace Utils