BinaryWriterTest.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 "../BinaryWriter.h"
00025 #include "cppunit/extensions/HelperMacros.h"
00026 
00027 namespace Utils {
00028 namespace Encodings {
00029 
00031 
00038 class BinaryWriterTest : public CppUnit::TestFixture
00039 {
00040     CPPUNIT_TEST_SUITE(BinaryWriterTest);
00041     CPPUNIT_TEST(testCtors);
00042     CPPUNIT_TEST(testSetProperties);
00043     CPPUNIT_TEST(testWriteInts);
00044     CPPUNIT_TEST(testWriteBytes);
00045     CPPUNIT_TEST(testWriteStrings);
00046     CPPUNIT_TEST(testWritePastEnd);
00047     CPPUNIT_TEST(testReserveOnAutoGrowBuffer);
00048     CPPUNIT_TEST_SUITE_END();
00049 
00050 public:
00051     void setUp()
00052     {
00053     }
00054 
00055     void tearDown()
00056     {
00057     }
00058 
00059     void testCtors()
00060     {
00061         QByteArray emptyBuffer;
00062         {
00063             BinaryWriter writer (&emptyBuffer, BinaryWriter::LittleEndian);
00064             CPPUNIT_ASSERT (BinaryWriter::LittleEndian == writer.byteOrder());
00065             CPPUNIT_ASSERT (0 == writer.bytesWritten());
00066             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00067             CPPUNIT_ASSERT (emptyBuffer == writer.buffer());
00068         }
00069         {
00070             BinaryWriter writer (BinaryWriter::BigEndian);
00071             CPPUNIT_ASSERT (BinaryWriter::BigEndian == writer.byteOrder());
00072             CPPUNIT_ASSERT (0 == writer.bytesWritten());
00073             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00074             CPPUNIT_ASSERT (emptyBuffer == writer.buffer());
00075         }
00076         QByteArray nonEmtpyBuffer (4, '\0');
00077         {
00078             BinaryWriter writer (&nonEmtpyBuffer, BinaryWriter::LittleEndian);
00079             CPPUNIT_ASSERT (0 == writer.bytesWritten());
00080             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00081             CPPUNIT_ASSERT (nonEmtpyBuffer == writer.buffer());
00082         }
00083     }
00084 
00085     void testSetProperties()
00086     {
00087         BinaryWriter writer (BinaryWriter::LittleEndian);
00088         // Test byte order:
00089         writer.setByteOrder (BinaryWriter::BigEndian);
00090         CPPUNIT_ASSERT (BinaryWriter::BigEndian == writer.byteOrder());
00091         writer.setByteOrder (BinaryWriter::LittleEndian);
00092         CPPUNIT_ASSERT (BinaryWriter::LittleEndian == writer.byteOrder());
00093     }
00094 
00095     void testWriteInts()
00096     {
00097         char rawData[] = { 0x00, 0x01,
00098                            0x02, 0x03,
00099                            0x04, 0x05, 0x06, 0x07,
00100                            0x08, 0x09, 0x0A, 0x0B,
00101                            0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
00102                            0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B };
00103 
00104         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00105         { // Test little endian, write in self-allocated growable buffer:
00106             BinaryWriter writer (BinaryWriter::LittleEndian);
00107             writer.writeUInt16 (0x0100);
00108             writer.writeInt16 (0x0302);
00109             writer.writeUInt32 (0x07060504);
00110             writer.writeInt32 (0x0B0A0908);
00111             writer.writeUInt64 (Q_INT64_C (0x131211100F0E0D0C));
00112             writer.writeInt64 (Q_INT64_C (0x1B1A191817161514));
00113             CPPUNIT_ASSERT (28 == writer.bytesWritten());
00114             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00115             CPPUNIT_ASSERT (buffer == writer.buffer());
00116         }
00117         { // Test big endian, write in self-allocated growable buffer:
00118             BinaryWriter writer (BinaryWriter::BigEndian);
00119             writer.writeUInt16 (0x0001);
00120             writer.writeInt16 (0x0203);
00121             writer.writeUInt32 (0x04050607);
00122             writer.writeInt32 (0x08090A0B);
00123             writer.writeUInt64 (Q_INT64_C (0x0C0D0E0F10111213));
00124             writer.writeInt64 (Q_INT64_C (0x1415161718191A1B));
00125             CPPUNIT_ASSERT (28 == writer.bytesWritten());
00126             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00127             CPPUNIT_ASSERT (buffer == writer.buffer());
00128         }
00129         { // Test little endian, write in a given non-growable buffer:
00130             QByteArray givenBuffer (28, 0);
00131             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00132             writer.writeUInt16 (0x0100);
00133             writer.writeInt16 (0x0302);
00134             writer.writeUInt32 (0x07060504);
00135             writer.writeInt32 (0x0B0A0908);
00136             writer.writeUInt64 (Q_INT64_C (0x131211100F0E0D0C));
00137             writer.writeInt64 (Q_INT64_C (0x1B1A191817161514));
00138             CPPUNIT_ASSERT (28 == writer.bytesWritten());
00139             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00140             CPPUNIT_ASSERT (buffer == writer.buffer());
00141             // Now try writing past end:
00142             writer.writeUInt16 (0x3434);
00143             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00144             CPPUNIT_ASSERT (30 == writer.bytesWritten());
00145             CPPUNIT_ASSERT (28 == givenBuffer.size()); // Buffer was NOT grown.
00146         }
00147         { // Test big endian, write in a given non-growable buffer:
00148             QByteArray givenBuffer (28, 0);
00149             BinaryWriter writer (&givenBuffer, BinaryWriter::BigEndian);
00150             writer.writeUInt16 (0x0001);
00151             writer.writeInt16 (0x0203);
00152             writer.writeUInt32 (0x04050607);
00153             writer.writeInt32 (0x08090A0B);
00154             writer.writeUInt64 (Q_INT64_C (0x0C0D0E0F10111213));
00155             writer.writeInt64 (Q_INT64_C (0x1415161718191A1B));
00156             CPPUNIT_ASSERT (28 == writer.bytesWritten());
00157             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00158             CPPUNIT_ASSERT (buffer == writer.buffer());
00159             // Now try writing past end:
00160             writer.writeUInt16 (0x3434);
00161             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00162             CPPUNIT_ASSERT (30 == writer.bytesWritten());
00163             CPPUNIT_ASSERT (28 == givenBuffer.size()); // Buffer was NOT grown.
00164         }
00165     }
00166 
00167     void testWriteBytes()
00168     {
00169         char rawData[] = { 0x00,
00170                            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
00171                            0x08 };
00172 
00173         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00174         // Byte order MUST NOT matter:
00175         { // Try with big endian, growable buffer:
00176             BinaryWriter writer (BinaryWriter::BigEndian);
00177             // write single byte:
00178             writer.writeByte (0x00);
00179             // write multiple bytes:
00180             QByteArray writeBytes = QByteArray::fromRawData (rawData + 1, 7);
00181             writer.writeBytes (writeBytes);
00182             // write zero bytes:
00183             writer.writeBytes (QByteArray());
00184             // write the last byte:
00185             writer.writeByte (0x08);
00186             // Make sure all was written and not past end:
00187             CPPUNIT_ASSERT (9 == writer.bytesWritten());
00188             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00189             CPPUNIT_ASSERT (buffer == writer.buffer());
00190         }
00191         { // Try the exact same with little endian, growable buffer:
00192             BinaryWriter writer (BinaryWriter::LittleEndian);
00193             // write single byte:
00194             writer.writeByte (0x00);
00195             // write multiple bytes:
00196             QByteArray writeBytes = QByteArray::fromRawData (rawData + 1, 7);
00197             writer.writeBytes (writeBytes);
00198             // write zero bytes:
00199             writer.writeBytes (QByteArray());
00200             // write the last byte:
00201             writer.writeByte (0x08);
00202             // Make sure all was written and not past end:
00203             CPPUNIT_ASSERT (9 == writer.bytesWritten());
00204             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00205             CPPUNIT_ASSERT (buffer == writer.buffer());
00206         }
00207         { // Try with big endian, given non-growable buffer:
00208             QByteArray givenBuffer (9, 0);
00209             BinaryWriter writer (&givenBuffer, BinaryWriter::BigEndian);
00210             // write single byte:
00211             writer.writeByte (0x00);
00212             // write multiple bytes:
00213             QByteArray writeBytes = QByteArray::fromRawData (rawData + 1, 7);
00214             writer.writeBytes (writeBytes);
00215             // write zero bytes:
00216             writer.writeBytes (QByteArray());
00217             // write the last byte:
00218             writer.writeByte (0x08);
00219             // Make sure all was written and not past end:
00220             CPPUNIT_ASSERT (9 == writer.bytesWritten());
00221             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00222             CPPUNIT_ASSERT (buffer == writer.buffer());
00223             // Try writing past end:
00224             writer.writeBytes (writeBytes);
00225             CPPUNIT_ASSERT (16 == writer.bytesWritten());
00226             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00227         }
00228         { // Try the exact same with little endian, given non-growable buffer:
00229             QByteArray givenBuffer (9, 0);
00230             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00231             // write single byte:
00232             writer.writeByte (0x00);
00233             // write multiple bytes:
00234             QByteArray writeBytes = QByteArray::fromRawData (rawData + 1, 7);
00235             writer.writeBytes (writeBytes);
00236             // write zero bytes:
00237             writer.writeBytes (QByteArray());
00238             // write the last byte:
00239             writer.writeByte (0x08);
00240             // Make sure all was written and not past end:
00241             CPPUNIT_ASSERT (9 == writer.bytesWritten());
00242             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00243             CPPUNIT_ASSERT (buffer == writer.buffer());
00244             // Try writing past end:
00245             writer.writeBytes (writeBytes);
00246             CPPUNIT_ASSERT (16 == writer.bytesWritten());
00247             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00248         }
00249     }
00250 
00251     void testWriteStrings()
00252     {
00253         char rawData[] = "\0non empty\0"; // One more \0 IS PUT by the compiler!
00254 
00255         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00256         // Endianness MUST NOT matter:
00257         { // Little endian, growable:
00258             BinaryWriter writer (BinaryWriter::LittleEndian);
00259             // Write the first empty string:
00260             writer.writeString (QByteArray());
00261             // Write "non empty":
00262             writer.writeString (QByteArray (rawData + 1));
00263             // Write the last empty string:
00264             writer.writeString (QByteArray());
00265             CPPUNIT_ASSERT (sizeof (rawData) == writer.bytesWritten());
00266             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00267             CPPUNIT_ASSERT (buffer == writer.buffer());
00268         }
00269         { // Big endian, growable:
00270             BinaryWriter writer (BinaryWriter::BigEndian);
00271             // Write the first empty string:
00272             writer.writeString (QByteArray());
00273             // Write "non empty":
00274             writer.writeString (QByteArray (rawData + 1));
00275             // Write the last empty string:
00276             writer.writeString (QByteArray());
00277             CPPUNIT_ASSERT (sizeof (rawData) == writer.bytesWritten());
00278             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00279             CPPUNIT_ASSERT (buffer == writer.buffer());
00280         }
00281         { // Little endian, non-growable:
00282             QByteArray givenBuffer (12, 1);
00283             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00284             // Write the first empty string:
00285             writer.writeString (QByteArray());
00286             // Write "non empty":
00287             writer.writeString (QByteArray (rawData + 1));
00288             // Write the last empty string:
00289             writer.writeString (QByteArray());
00290             CPPUNIT_ASSERT (sizeof (rawData) == writer.bytesWritten());
00291             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00292             CPPUNIT_ASSERT (buffer == writer.buffer());
00293             // Try read past end:
00294             writer.writeString (QByteArray());
00295             CPPUNIT_ASSERT (sizeof (rawData) + 1 == writer.bytesWritten());
00296             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00297             CPPUNIT_ASSERT (buffer == writer.buffer());
00298         }
00299         { // Big endian, from end:
00300             QByteArray givenBuffer (12, 1);
00301             BinaryWriter writer (&givenBuffer, BinaryWriter::BigEndian);
00302             // Write the first empty string:
00303             writer.writeString (QByteArray());
00304             // Write "non empty":
00305             writer.writeString (QByteArray (rawData + 1));
00306             // Write the last empty string:
00307             writer.writeString (QByteArray());
00308             CPPUNIT_ASSERT (sizeof (rawData) == writer.bytesWritten());
00309             CPPUNIT_ASSERT (!writer.hasWrittenPastEnd());
00310             CPPUNIT_ASSERT (buffer == writer.buffer());
00311             // Try read past end:
00312             writer.writeString (QByteArray());
00313             CPPUNIT_ASSERT (sizeof (rawData) + 1 == writer.bytesWritten());
00314             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00315             CPPUNIT_ASSERT (buffer == writer.buffer());
00316         }
00317     }
00318 
00319     void testWritePastEnd()
00320     {
00321         // We already tested writing past the end after the complete buffer
00322         // was written completely. Here we will test when half of the integer,
00323         // for example, is within bounds and the rest is past the bounds.
00324         char rawData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
00325         QByteArray buffer = QByteArray::fromRawData (rawData, sizeof (rawData));
00326         {
00327             QByteArray givenBuffer (8, 0);
00328             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00329             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00330             writer.writeUInt16 (0x1111);
00331             CPPUNIT_ASSERT (9 == writer.bytesWritten());
00332             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00333         }
00334         {
00335             QByteArray givenBuffer (8, 0);
00336             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00337             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00338             writer.writeInt16 (0);
00339             CPPUNIT_ASSERT (9 == writer.bytesWritten());
00340             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00341         }
00342         {
00343             QByteArray givenBuffer (8, 0);
00344             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00345             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00346             writer.writeUInt32 (0);
00347             CPPUNIT_ASSERT (11 == writer.bytesWritten());
00348             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00349         }
00350         {
00351             QByteArray givenBuffer (8, 0);
00352             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00353             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00354             writer.writeInt32 (0);
00355             CPPUNIT_ASSERT (11 == writer.bytesWritten());
00356             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00357         }
00358         {
00359             QByteArray givenBuffer (8, 0);
00360             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00361             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00362             writer.writeUInt64 (0);
00363             CPPUNIT_ASSERT (15 == writer.bytesWritten());
00364             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00365         }
00366         {
00367             QByteArray givenBuffer (8, 0);
00368             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00369             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00370             writer.writeInt64 (0);
00371             CPPUNIT_ASSERT (15 == writer.bytesWritten());
00372             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00373         }
00374         {
00375             QByteArray givenBuffer (8, 0);
00376             BinaryWriter writer (&givenBuffer, BinaryWriter::LittleEndian);
00377             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00378             writer.writeBytes (QByteArray::fromRawData (rawData, 7));
00379             CPPUNIT_ASSERT (14 == writer.bytesWritten());
00380             CPPUNIT_ASSERT (writer.hasWrittenPastEnd());
00381         }
00382     }
00383 
00385     void testReserveOnAutoGrowBuffer()
00386     {
00387         BinaryWriter writer (BinaryWriter::BigEndian, true);
00388         writer.reserve (10);
00389         writer.writeUInt64 (0); // write 8 bytes
00390         CPPUNIT_ASSERT (writer.hasWrittenAll() == false);
00391         CPPUNIT_ASSERT (writer.hasWrittenPastEnd() == false);
00392         writer.writeUInt64 (0); // write 8 more => 16 > 10, but no grow, so:
00393         CPPUNIT_ASSERT (writer.hasWrittenAll() == true);
00394         CPPUNIT_ASSERT (writer.hasWrittenPastEnd() == true);
00395     }
00396 };
00397 
00398 CPPUNIT_TEST_SUITE_REGISTRATION(BinaryWriterTest);
00399 
00400 } // namespace Codings
00401 } // namespace Utils