TupleTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/test/TupleTest.cpp#23 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2005-2009 SQLstream, Inc.
00006 // Copyright (C) 2005-2009 LucidEra, Inc.
00007 // Portions Copyright (C) 1999-2009 John V. Sichi
00008 //
00009 // This program is free software; you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by the Free
00011 // Software Foundation; either version 2 of the License, or (at your option)
00012 // any later version approved by The Eigenbase Project.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/test/TestBase.h"
00026 #include "fennel/tuple/TupleDescriptor.h"
00027 #include "fennel/tuple/TupleData.h"
00028 #include "fennel/tuple/TupleAccessor.h"
00029 #include "fennel/tuple/TuplePrinter.h"
00030 #include "fennel/tuple/AttributeAccessor.h"
00031 #include "fennel/tuple/UnalignedAttributeAccessor.h"
00032 #include "fennel/tuple/StandardTypeDescriptor.h"
00033 #include "fennel/common/TraceSource.h"
00034 
00035 #include <boost/test/test_tools.hpp>
00036 #include <boost/scoped_array.hpp>
00037 #include <limits>
00038 
00039 using namespace fennel;
00040 
00041 class TupleTest : virtual public TestBase, public TraceSource
00042 {
00043     static const uint MAX_WIDTH = 512;
00044 
00045     TupleDescriptor tupleDesc;
00046     TupleAccessor tupleAccessor;
00047 
00048     void writeMinData(TupleDatum &datum,uint typeOrdinal);
00049     void writeMaxData(TupleDatum &datum,uint typeOrdinal);
00050     void writeSampleData(TupleDatum &datum,uint typeOrdinal);
00051     uint testMarshal(TupleData const &tupleDataFixed);
00052     void checkData(TupleData const &tupleData1,TupleData const &tupleData2);
00053     void checkAlignment(
00054         TupleAttributeDescriptor const &desc, PConstBuffer pBuf);
00055 
00056     void testStandardTypesNullable();
00057     void testStandardTypesNotNull();
00058     void testStandardTypesNetworkNullable();
00059     void testStandardTypesNetworkNotNull();
00060     void testStandardTypes(TupleFormat,bool nullable);
00061     void testZeroByteTuple();
00062     void testDebugAccess();
00063     void testLoadStoreUnaligned();
00064     void loadStore8ByteInts(int64_t initialValue, uint8_t nextByte);
00065     void loadAndStore8ByteInt(int64_t intVal);
00066     void loadStore2ByteLenData(uint dataLen);
00067     void loadStoreNullData(uint typeOrdinal, uint len);
00068 
00069     void traceTuple(TupleData const &tupleData)
00070     {
00071         std::ostringstream oss;
00072         TuplePrinter tuplePrinter;
00073         tuplePrinter.print(oss,tupleDesc,tupleData);
00074         std::string s = oss.str();
00075         FENNEL_TRACE(TRACE_FINE,s);
00076     }
00077 
00078 public:
00079     explicit TupleTest()
00080         : TraceSource(shared_from_this(),"TupleTest")
00081     {
00082         FENNEL_UNIT_TEST_CASE(TupleTest,testStandardTypesNotNull);
00083         FENNEL_UNIT_TEST_CASE(TupleTest,testStandardTypesNullable);
00084         FENNEL_UNIT_TEST_CASE(TupleTest,testStandardTypesNetworkNotNull);
00085         FENNEL_UNIT_TEST_CASE(TupleTest,testStandardTypesNetworkNullable);
00086         FENNEL_UNIT_TEST_CASE(TupleTest,testZeroByteTuple);
00087         FENNEL_UNIT_TEST_CASE(TupleTest,testLoadStoreUnaligned);
00088 
00089         // This one should fail when TupleAccessor.cpp's DEBUG_TUPLE_ACCESS
00090         // is set to 1.
00091         FENNEL_EXTRA_UNIT_TEST_CASE(TupleTest,testDebugAccess);
00092     }
00093 
00094     virtual ~TupleTest()
00095     {
00096     }
00097 };
00098 
00099 void TupleTest::testStandardTypesNullable()
00100 {
00101     testStandardTypes(TUPLE_FORMAT_STANDARD,true);
00102 }
00103 
00104 void TupleTest::testStandardTypesNotNull()
00105 {
00106     testStandardTypes(TUPLE_FORMAT_STANDARD,false);
00107 }
00108 
00109 void TupleTest::testStandardTypesNetworkNullable()
00110 {
00111     testStandardTypes(TUPLE_FORMAT_NETWORK,true);
00112 }
00113 
00114 void TupleTest::testStandardTypesNetworkNotNull()
00115 {
00116     testStandardTypes(TUPLE_FORMAT_NETWORK,false);
00117 }
00118 
00119 void TupleTest::testStandardTypes(
00120     TupleFormat format,bool nullable)
00121 {
00122     StandardTypeDescriptorFactory typeFactory;
00123     uint cbMin = 0;
00124     tupleDesc.clear();
00125     for (uint i = STANDARD_TYPE_MIN; i < STANDARD_TYPE_END; ++i) {
00126         StoredTypeDescriptor const &typeDesc = typeFactory.newDataType(i);
00127         uint cbFixed = typeDesc.getFixedByteCount();
00128         if (cbFixed) {
00129             cbMin += cbFixed;
00130         } else {
00131             cbMin += typeDesc.getMinByteCount(MAX_WIDTH);
00132         }
00133         tupleDesc.push_back(
00134             TupleAttributeDescriptor(
00135                 typeDesc,
00136                 nullable,
00137                 cbFixed ? 0 : MAX_WIDTH));
00138     }
00139 
00140     tupleAccessor.compute(tupleDesc,format);
00141     BOOST_CHECK(tupleAccessor.getMinByteCount() >= cbMin);
00142     BOOST_CHECK(tupleAccessor.getMaxByteCount() > cbMin);
00143 
00144     TupleAccessor tupleAccessorFixed;
00145     tupleAccessorFixed.compute(
00146         tupleDesc,
00147         TUPLE_FORMAT_ALL_FIXED);
00148 
00149     boost::scoped_array<FixedBuffer> pTupleBufFixed(
00150         new FixedBuffer[tupleAccessor.getMaxByteCount()]);
00151     tupleAccessorFixed.setCurrentTupleBuf(pTupleBufFixed.get(), false);
00152 
00153     TupleData tupleDataFixed(tupleDesc);
00154     tupleAccessorFixed.unmarshal(tupleDataFixed);
00155 
00156     TupleData::iterator pDatum = tupleDataFixed.begin();
00157     for (uint i = STANDARD_TYPE_MIN; i < STANDARD_TYPE_END; ++i) {
00158         writeMinData(*pDatum,i);
00159         ++pDatum;
00160     }
00161     FENNEL_TRACE(TRACE_FINE,"testMarshal(MinData)");
00162     uint cbMinData = testMarshal(tupleDataFixed);
00163     BOOST_CHECK(cbMinData >= tupleAccessor.getMinByteCount());
00164     BOOST_CHECK(cbMinData < tupleAccessor.getMaxByteCount());
00165 
00166     pDatum = tupleDataFixed.begin();
00167     for (uint i = STANDARD_TYPE_MIN; i < STANDARD_TYPE_END; ++i) {
00168         writeMaxData(*pDatum,i);
00169         ++pDatum;
00170     }
00171     FENNEL_TRACE(TRACE_FINE,"testMarshal(MaxData)");
00172     uint cbMaxData = testMarshal(tupleDataFixed);
00173     BOOST_CHECK(cbMaxData > cbMinData);
00174     BOOST_CHECK(cbMaxData <= tupleAccessor.getMaxByteCount());
00175 
00176     pDatum = tupleDataFixed.begin();
00177     for (uint i = STANDARD_TYPE_MIN; i < STANDARD_TYPE_END; ++i) {
00178         writeSampleData(*pDatum,i);
00179         ++pDatum;
00180     }
00181     FENNEL_TRACE(TRACE_FINE,"testMarshal(SampleData)");
00182     uint cbSampleData = testMarshal(tupleDataFixed);
00183     BOOST_CHECK(cbSampleData >= tupleAccessor.getMinByteCount());
00184     BOOST_CHECK(cbSampleData <= tupleAccessor.getMaxByteCount());
00185 
00186     if (nullable) {
00187         pDatum = tupleDataFixed.begin();
00188         for (uint i = STANDARD_TYPE_MIN; i < STANDARD_TYPE_END; ++i) {
00189             pDatum->pData = NULL;
00190             ++pDatum;
00191         }
00192         FENNEL_TRACE(TRACE_FINE,"testMarshal(NullData)");
00193         uint cbNullData = testMarshal(tupleDataFixed);
00194         BOOST_CHECK(cbNullData >= tupleAccessor.getMinByteCount());
00195         BOOST_CHECK(cbNullData < tupleAccessor.getMaxByteCount());
00196     }
00197 }
00198 
00199 uint TupleTest::testMarshal(TupleData const &tupleDataFixed)
00200 {
00201     FENNEL_TRACE(TRACE_FINE,"reference tuple:");
00202     traceTuple(tupleDataFixed);
00203     boost::scoped_array<FixedBuffer> pTupleBufVar(
00204         new FixedBuffer[tupleAccessor.getMaxByteCount()]);
00205 
00206     uint cbTuple = tupleAccessor.getByteCount(tupleDataFixed);
00207     tupleAccessor.marshal(tupleDataFixed,pTupleBufVar.get());
00208     BOOST_CHECK_EQUAL(cbTuple,tupleAccessor.getCurrentByteCount());
00209 
00210     TupleData tupleDataTogether(tupleDesc);
00211     tupleAccessor.unmarshal(tupleDataTogether);
00212     FENNEL_TRACE(TRACE_FINE,"unmarshalled tuple (together):");
00213     traceTuple(tupleDataTogether);
00214     BOOST_CHECK_EQUAL(cbTuple,tupleAccessor.getByteCount(tupleDataTogether));
00215     checkData(tupleDataFixed,tupleDataTogether);
00216 
00217     TupleData tupleDataIndividual(tupleDesc);
00218     for (uint i = 0; i < tupleDataIndividual.size(); ++i) {
00219         tupleAccessor.getAttributeAccessor(i).unmarshalValue(
00220             tupleAccessor,tupleDataIndividual[i]);
00221     }
00222     FENNEL_TRACE(TRACE_FINE,"unmarshalled tuple (individual):");
00223     traceTuple(tupleDataIndividual);
00224     BOOST_CHECK_EQUAL(cbTuple,tupleAccessor.getByteCount(tupleDataIndividual));
00225     checkData(tupleDataFixed,tupleDataIndividual);
00226 
00227     return tupleAccessor.getCurrentByteCount();
00228 }
00229 
00230 void TupleTest::checkData(
00231     TupleData const &tupleData1,TupleData const &tupleData2)
00232 {
00233     for (uint i = 0; i < tupleData1.size(); ++i) {
00234         TupleDatum const &datum1 = tupleData1[i];
00235         TupleDatum const &datum2 = tupleData2[i];
00236         if (!datum1.pData || !datum2.pData) {
00237             BOOST_CHECK_EQUAL(
00238                 static_cast<void const *>(datum1.pData),
00239                 static_cast<void const *>(datum2.pData));
00240             continue;
00241         }
00242         checkAlignment(tupleDesc[i], datum1.pData);
00243         checkAlignment(tupleDesc[i], datum2.pData);
00244         BOOST_CHECK_EQUAL(datum1.cbData,datum2.cbData);
00245         BOOST_CHECK_EQUAL_COLLECTIONS(
00246             datum1.pData,
00247             datum1.pData + datum1.cbData,
00248             datum2.pData,
00249             datum2.pData + datum2.cbData);
00250     }
00251 }
00252 
00253 void TupleTest::checkAlignment(
00254     TupleAttributeDescriptor const &desc, PConstBuffer pBuf)
00255 {
00256     uint iAlign = desc.pTypeDescriptor->getAlignmentByteCount(
00257         desc.cbStorage);
00258     switch (iAlign) {
00259     case 1:
00260         return;
00261     case 2:
00262         BOOST_CHECK_EQUAL(0, uintptr_t(pBuf) & 1);
00263         break;
00264     case 4:
00265         BOOST_CHECK_EQUAL(0, uintptr_t(pBuf) & 3);
00266         break;
00267     case 8:
00268         BOOST_CHECK_EQUAL(0, uintptr_t(pBuf) & 7);
00269         break;
00270     }
00271 }
00272 
00273 void TupleTest::writeMinData(TupleDatum &datum,uint typeOrdinal)
00274 {
00275     PBuffer pData = const_cast<PBuffer>(datum.pData);
00276     switch (typeOrdinal) {
00277     case STANDARD_TYPE_BOOL:
00278         *(reinterpret_cast<bool *>(pData)) = false;
00279         break;
00280     case STANDARD_TYPE_INT_8:
00281         *(reinterpret_cast<int8_t *>(pData)) =
00282             std::numeric_limits<int8_t>::min();
00283         break;
00284     case STANDARD_TYPE_UINT_8:
00285         *(reinterpret_cast<uint8_t *>(pData)) =
00286             std::numeric_limits<uint8_t>::min();
00287         break;
00288     case STANDARD_TYPE_INT_16:
00289         *(reinterpret_cast<int16_t *>(pData)) =
00290             std::numeric_limits<int16_t>::min();
00291         break;
00292     case STANDARD_TYPE_UINT_16:
00293         *(reinterpret_cast<uint16_t *>(pData)) =
00294             std::numeric_limits<uint16_t>::min();
00295         break;
00296     case STANDARD_TYPE_INT_32:
00297         *(reinterpret_cast<int32_t *>(pData)) =
00298             std::numeric_limits<int32_t>::min();
00299         break;
00300     case STANDARD_TYPE_UINT_32:
00301         *(reinterpret_cast<uint32_t *>(pData)) =
00302             std::numeric_limits<uint32_t>::min();
00303         break;
00304     case STANDARD_TYPE_INT_64:
00305         *(reinterpret_cast<int64_t *>(pData)) =
00306             std::numeric_limits<int64_t>::min();
00307         break;
00308     case STANDARD_TYPE_UINT_64:
00309         *(reinterpret_cast<uint64_t *>(pData)) =
00310             std::numeric_limits<uint64_t>::min();
00311         break;
00312     case STANDARD_TYPE_REAL:
00313         *(reinterpret_cast<float *>(pData)) =
00314             std::numeric_limits<float>::min();
00315         break;
00316     case STANDARD_TYPE_DOUBLE:
00317         *(reinterpret_cast<double *>(pData)) =
00318             std::numeric_limits<double>::min();
00319         break;
00320     case STANDARD_TYPE_BINARY:
00321         memset(pData,0,datum.cbData);
00322         break;
00323     case STANDARD_TYPE_CHAR:
00324         memset(pData,'A',datum.cbData);
00325         break;
00326     case STANDARD_TYPE_UNICODE_CHAR:
00327         {
00328             Ucs2Buffer pStr =
00329                 reinterpret_cast<Ucs2Buffer>(pData);
00330             uint nChars = (datum.cbData >> 1);
00331             for (uint i = 0; i < nChars; ++i) {
00332                 pStr[i] = 'A';
00333             }
00334         }
00335         break;
00336     case STANDARD_TYPE_VARCHAR:
00337     case STANDARD_TYPE_VARBINARY:
00338     case STANDARD_TYPE_UNICODE_VARCHAR:
00339         datum.cbData = 0;
00340         break;
00341     default:
00342         permAssert(false);
00343     }
00344 }
00345 
00346 void TupleTest::writeMaxData(TupleDatum &datum,uint typeOrdinal)
00347 {
00348     PBuffer pData = const_cast<PBuffer>(datum.pData);
00349     switch (typeOrdinal) {
00350     case STANDARD_TYPE_BOOL:
00351         *(reinterpret_cast<bool *>(pData)) = true;
00352         break;
00353     case STANDARD_TYPE_INT_8:
00354         *(reinterpret_cast<int8_t *>(pData)) =
00355             std::numeric_limits<int8_t>::max();
00356         break;
00357     case STANDARD_TYPE_UINT_8:
00358         *(reinterpret_cast<uint8_t *>(pData)) =
00359             std::numeric_limits<uint8_t>::max();
00360         break;
00361     case STANDARD_TYPE_INT_16:
00362         *(reinterpret_cast<int16_t *>(pData)) =
00363             std::numeric_limits<int16_t>::max();
00364         break;
00365     case STANDARD_TYPE_UINT_16:
00366         *(reinterpret_cast<uint16_t *>(pData)) =
00367             std::numeric_limits<uint16_t>::max();
00368         break;
00369     case STANDARD_TYPE_INT_32:
00370         *(reinterpret_cast<int32_t *>(pData)) =
00371             std::numeric_limits<int32_t>::max();
00372         break;
00373     case STANDARD_TYPE_UINT_32:
00374         *(reinterpret_cast<uint32_t *>(pData)) =
00375             std::numeric_limits<uint32_t>::max();
00376         break;
00377     case STANDARD_TYPE_INT_64:
00378         *(reinterpret_cast<int64_t *>(pData)) =
00379             std::numeric_limits<int64_t>::max();
00380         break;
00381     case STANDARD_TYPE_UINT_64:
00382         *(reinterpret_cast<uint64_t *>(pData)) =
00383             std::numeric_limits<uint64_t>::max();
00384         break;
00385     case STANDARD_TYPE_REAL:
00386         *(reinterpret_cast<float *>(pData)) =
00387             std::numeric_limits<float>::max();
00388         break;
00389     case STANDARD_TYPE_DOUBLE:
00390         *(reinterpret_cast<double *>(pData)) =
00391             std::numeric_limits<double>::max();
00392         break;
00393     case STANDARD_TYPE_UNICODE_CHAR:
00394     case STANDARD_TYPE_BINARY:
00395         memset(pData,0xFF,datum.cbData);
00396         break;
00397     case STANDARD_TYPE_CHAR:
00398         memset(pData,'z',datum.cbData);
00399         break;
00400     case STANDARD_TYPE_VARCHAR:
00401         datum.cbData = MAX_WIDTH;
00402         memset(pData,'z',datum.cbData);
00403         break;
00404     case STANDARD_TYPE_UNICODE_VARCHAR:
00405     case STANDARD_TYPE_VARBINARY:
00406         datum.cbData = MAX_WIDTH;
00407         memset(pData,0xFF,datum.cbData);
00408         break;
00409     default:
00410         permAssert(false);
00411     }
00412 }
00413 
00414 void TupleTest::writeSampleData(TupleDatum &datum,uint typeOrdinal)
00415 {
00416     /* Some sample data that's between min and max */
00417     std::subtractive_rng randomNumberGenerator(time(NULL));
00418     PBuffer pData = const_cast<PBuffer>(datum.pData);
00419     switch (typeOrdinal) {
00420     case STANDARD_TYPE_BOOL:
00421         if (randomNumberGenerator(2)) {
00422             *(reinterpret_cast<bool *>(pData)) = true;
00423         } else {
00424             *(reinterpret_cast<bool *>(pData)) = false;
00425         }
00426         break;
00427     case STANDARD_TYPE_INT_8:
00428         *(reinterpret_cast<int8_t *>(pData)) =  0x28;
00429         break;
00430     case STANDARD_TYPE_UINT_8:
00431         *(reinterpret_cast<uint8_t *>(pData)) = 0x54;
00432         break;
00433     case STANDARD_TYPE_INT_16:
00434         *(reinterpret_cast<int16_t *>(pData)) = 0xfedc;
00435         break;
00436     case STANDARD_TYPE_UINT_16:
00437         *(reinterpret_cast<uint16_t *>(pData)) = 0x1234;
00438         break;
00439     case STANDARD_TYPE_INT_32:
00440         *(reinterpret_cast<int32_t *>(pData)) = 0xfedcba98;
00441         break;
00442     case STANDARD_TYPE_REAL:
00443     case STANDARD_TYPE_UINT_32:
00444         *(reinterpret_cast<uint32_t *>(pData)) = 0x12345678;
00445         break;
00446     case STANDARD_TYPE_INT_64:
00447         *(reinterpret_cast<int64_t *>(pData)) = 0xfedcba0987654321LL;
00448         break;
00449     case STANDARD_TYPE_DOUBLE:
00450     case STANDARD_TYPE_UINT_64:
00451         *(reinterpret_cast<uint64_t *>(pData)) = 0x1234567890abcdefLL;
00452         break;
00453     case STANDARD_TYPE_UNICODE_CHAR:
00454     case STANDARD_TYPE_BINARY:
00455         for (int i = 0; i < datum.cbData; i++) {
00456             pData[i] = i % 256;
00457         }
00458         break;
00459     case STANDARD_TYPE_CHAR:
00460         for (int i = 0; i < datum.cbData; i++) {
00461             pData[i] = i % ('z' - ' ') + ' ';
00462         }
00463         break;
00464     case STANDARD_TYPE_VARCHAR:
00465         datum.cbData = randomNumberGenerator(MAX_WIDTH);
00466         for (int i = 0; i < datum.cbData; i++) {
00467             pData[i] = i % ('z' - ' ') + ' ';
00468         }
00469         break;
00470     case STANDARD_TYPE_UNICODE_VARCHAR:
00471     case STANDARD_TYPE_VARBINARY:
00472         datum.cbData = randomNumberGenerator(MAX_WIDTH);
00473         if (typeOrdinal == STANDARD_TYPE_UNICODE_VARCHAR) {
00474             if (datum.cbData & 1) {
00475                 // need an even number of bytes for doublebyte characters
00476                 datum.cbData--;
00477             }
00478         }
00479         for (int i = 0; i < datum.cbData; i++) {
00480             pData[i] = i % 256;
00481         }
00482         break;
00483     default:
00484         assert(false);
00485     }
00486 }
00487 
00488 void TupleTest::testDebugAccess()
00489 {
00490     StandardTypeDescriptorFactory typeFactory;
00491 
00492     // Just to set up tupleAccessor
00493     testStandardTypesNullable();
00494 
00495     boost::scoped_array<FixedBuffer> buf(
00496         new FixedBuffer[tupleAccessor.getMaxByteCount()]);
00497     memset(buf.get(), 0, tupleAccessor.getMaxByteCount());
00498 
00499     // This should cause an assertion failure when TupleAccessor.cpp's
00500     // DEBUG_TUPLE_ACCESS is set to 1.
00501     tupleAccessor.setCurrentTupleBuf(buf.get());
00502 }
00503 
00504 void TupleTest::testZeroByteTuple()
00505 {
00506     StandardTypeDescriptorFactory typeFactory;
00507     tupleDesc.clear();
00508     tupleDesc.push_back(
00509         TupleAttributeDescriptor(
00510             typeFactory.newDataType(STANDARD_TYPE_CHAR),
00511             false,
00512             0));
00513     TupleAccessor tupleAccessor;
00514     tupleAccessor.compute(tupleDesc);
00515 
00516     // verify that we didn't end up with a 0-byte tuple layout,
00517     // and that the min and max are equal since it's fixed-width
00518     BOOST_CHECK(tupleAccessor.getMinByteCount());
00519     BOOST_CHECK(tupleAccessor.getMaxByteCount());
00520     BOOST_CHECK_EQUAL(
00521         tupleAccessor.getMinByteCount(),
00522         tupleAccessor.getMaxByteCount());
00523 }
00524 
00525 void TupleTest::testLoadStoreUnaligned()
00526 {
00527     // test compression of 8-byte integers
00528     loadStore8ByteInts(0, 0xff);
00529     loadStore8ByteInts(0x80, 0);
00530 
00531     // make sure zero is handled correctly
00532     loadAndStore8ByteInt(0);
00533 
00534     // test data that requires a 2-byte storage length
00535     loadStore2ByteLenData(128);
00536     loadStore2ByteLenData(129);
00537     loadStore2ByteLenData(255);
00538     loadStore2ByteLenData(256);
00539     loadStore2ByteLenData(257);
00540     loadStore2ByteLenData(510);
00541     loadStore2ByteLenData(511);
00542     loadStore2ByteLenData(512);
00543 
00544     // test special case of empty string
00545     loadStore2ByteLenData(0);
00546 
00547     // test null data
00548     loadStoreNullData(STANDARD_TYPE_INT_64, 8);
00549     loadStoreNullData(STANDARD_TYPE_INT_32, 4);
00550 
00551     // test fixed width data
00552     TupleDatum tupleDatum;
00553     tupleDatum.cbData = 2;
00554     int16_t intVal = 43981;
00555     tupleDatum.pData = (PConstBuffer) &intVal;
00556     FixedBuffer storageBuf[4];
00557     StandardTypeDescriptorFactory stdTypeFactory;
00558     TupleAttributeDescriptor attrDesc_int16(
00559         stdTypeFactory.newDataType(STANDARD_TYPE_INT_16));
00560     UnalignedAttributeAccessor accessor_int16(attrDesc_int16);
00561     accessor_int16.storeValue(tupleDatum, storageBuf);
00562     uint len = accessor_int16.getStoredByteCount(storageBuf);
00563     BOOST_REQUIRE(len == 2);
00564 
00565     FixedBuffer loadBuf[4];
00566     tupleDatum.cbData = 0xff;
00567     tupleDatum.pData = loadBuf;
00568     accessor_int16.loadValue(tupleDatum, storageBuf);
00569 
00570     BOOST_REQUIRE(tupleDatum.cbData == 2);
00571     bool rc = (intVal == *reinterpret_cast<int16_t const *> (tupleDatum.pData));
00572     BOOST_REQUIRE(rc);
00573 
00574     // test data with 1-byte storage length
00575     tupleDatum.cbData = 3;
00576     FixedBuffer data[3];
00577     data[0] = 0xba;
00578     data[0] = 0xdc;
00579     data[0] = 0xfe;
00580     tupleDatum.pData = data;
00581     TupleAttributeDescriptor attrDesc_varBinary(
00582         stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY),
00583         true,
00584         4);
00585     UnalignedAttributeAccessor accessor_varBinary(attrDesc_varBinary);
00586     accessor_varBinary.storeValue(tupleDatum, storageBuf);
00587     len = accessor_varBinary.getStoredByteCount(storageBuf);
00588     BOOST_REQUIRE(len == 4);
00589 
00590     tupleDatum.cbData = 0xff;
00591     tupleDatum.pData = loadBuf;
00592     accessor_varBinary.loadValue(tupleDatum, storageBuf);
00593 
00594     BOOST_REQUIRE(tupleDatum.cbData == 3);
00595     BOOST_REQUIRE(memcmp(tupleDatum.pData, data, 3) == 0);
00596 }
00597 
00598 void TupleTest::loadStore8ByteInts(int64_t initialValue, uint8_t nextByte)
00599 {
00600     // Take the intial value, shift it to the left and OR the nextByte value
00601     // to generate the different test values.  Do this 8 times.  For each
00602     // value, try the value, value - 1, value + 1, as well as the negative of
00603     // each of those three values.
00604 
00605     int64_t intVal = initialValue;
00606     for (int i = 0; i < 8; i++) {
00607         intVal <<= 8;
00608         intVal |= nextByte;
00609 
00610         intVal--;
00611         loadAndStore8ByteInt(intVal);
00612         loadAndStore8ByteInt(-intVal);
00613 
00614         intVal++;
00615         loadAndStore8ByteInt(intVal);
00616         loadAndStore8ByteInt(-intVal);
00617 
00618         intVal++;
00619         loadAndStore8ByteInt(intVal);
00620         loadAndStore8ByteInt(-intVal);
00621 
00622         intVal--;
00623     }
00624 }
00625 
00626 void TupleTest::loadAndStore8ByteInt(int64_t intVal)
00627 {
00628     TupleDatum tupleDatum;
00629     // need 8+1 bytes in buffer; +1 for the length byte
00630     FixedBuffer storageBuf[9];
00631     FixedBuffer loadBuf[9];
00632 
00633     // compress and uncompress various 8-byte integers; verify the data
00634     // by storing the original value, loading the stored value and then
00635     // checking that it's the same as the original value
00636     tupleDatum.cbData = 8;
00637     tupleDatum.pData = (PConstBuffer) &intVal;
00638     StandardTypeDescriptorFactory stdTypeFactory;
00639     TupleAttributeDescriptor attrDesc(
00640         stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
00641     UnalignedAttributeAccessor accessor(attrDesc);
00642     accessor.storeValue(tupleDatum, storageBuf);
00643 
00644     // load the data into a different buffer so we're sure we're not reusing
00645     // the original stored value
00646     tupleDatum.cbData = 0;
00647     tupleDatum.pData = loadBuf;
00648     accessor.loadValue(tupleDatum, storageBuf);
00649     bool rc = (intVal == *reinterpret_cast<int64_t const *> (tupleDatum.pData));
00650     BOOST_REQUIRE(rc);
00651     BOOST_REQUIRE(tupleDatum.cbData == 8);
00652 }
00653 
00654 void TupleTest::loadStore2ByteLenData(uint dataLen)
00655 {
00656     // initialize the source TupleDatum
00657     TupleDatum tupleDatum;
00658     tupleDatum.cbData = dataLen;
00659     boost::scoped_array<FixedBuffer> dataBuf(new FixedBuffer[dataLen + 2]);
00660     for (int i = 0; i < dataLen; i++) {
00661         dataBuf[i] = i;
00662     }
00663     tupleDatum.pData = dataBuf.get();
00664 
00665     // store it and verify the storage length
00666     boost::scoped_array<FixedBuffer> storageBuf(new FixedBuffer[dataLen + 2]);
00667     StandardTypeDescriptorFactory stdTypeFactory;
00668     TupleAttributeDescriptor attrDesc(
00669         stdTypeFactory.newDataType(STANDARD_TYPE_BINARY), true, dataLen);
00670     UnalignedAttributeAccessor accessor(attrDesc);
00671     accessor.storeValue(tupleDatum, storageBuf.get());
00672     uint len = accessor.getStoredByteCount(storageBuf.get());
00673     BOOST_REQUIRE(len == dataLen + 2);
00674 
00675     // load the stored value and compare it against the original data buffer
00676     boost::scoped_array<FixedBuffer> loadBuf(new FixedBuffer[dataLen + 2]);
00677     tupleDatum.cbData = 0;
00678     tupleDatum.pData = loadBuf.get();
00679     accessor.loadValue(tupleDatum, storageBuf.get());
00680     BOOST_REQUIRE(tupleDatum.cbData == dataLen);
00681     BOOST_REQUIRE(memcmp(tupleDatum.pData, dataBuf.get(), dataLen) == 0);
00682 }
00683 
00684 void TupleTest::loadStoreNullData(uint typeOrdinal, uint dataLen)
00685 {
00686     FixedBuffer storageBuf[2];
00687     TupleDatum tupleDatum;
00688     tupleDatum.cbData = 0;
00689     tupleDatum.pData = 0;
00690 
00691     StandardTypeDescriptorFactory stdTypeFactory;
00692     TupleAttributeDescriptor attrDesc(
00693         stdTypeFactory.newDataType(typeOrdinal),
00694         true,
00695         dataLen);
00696     UnalignedAttributeAccessor accessor(attrDesc);
00697 
00698     accessor.storeValue(tupleDatum, storageBuf);
00699     uint len = accessor.getStoredByteCount(storageBuf);
00700     BOOST_REQUIRE(len == 1);
00701 
00702     FixedBuffer loadBuf[2];
00703     tupleDatum.cbData = 0xff;
00704     tupleDatum.pData = loadBuf;
00705     accessor.loadValue(tupleDatum, storageBuf);
00706 
00707     BOOST_REQUIRE(tupleDatum.pData == NULL);
00708 }
00709 
00710 FENNEL_UNIT_TEST_SUITE(TupleTest);
00711 
00712 // End TupleTest.cpp
00713 

Generated on Mon Jun 22 04:00:21 2009 for Fennel by  doxygen 1.5.1