CalcCastTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calctest/CalcCastTest.cpp#2 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "fennel/common/CommonPreamble.h"
00024 #include "fennel/test/TestBase.h"
00025 #include "fennel/common/TraceSource.h"
00026 
00027 #include "fennel/tuple/TupleDataWithBuffer.h"
00028 #include "fennel/tuple/TuplePrinter.h"
00029 #include "fennel/calculator/CalcCommon.h"
00030 #include "fennel/calculator/StringToHex.h"
00031 #include "fennel/common/FennelExcn.h"
00032 
00033 #include <boost/test/test_tools.hpp>
00034 #include <boost/scoped_array.hpp>
00035 #include <string>
00036 #include <limits>
00037 
00038 using namespace fennel;
00039 using namespace std;
00040 
00041 
00042 class CalcCastTest : virtual public TestBase, public TraceSource
00043 {
00044     typedef void (*SetFunction)(TupleDataWithBuffer& inTuple);
00045     typedef void (*CheckFunction)(
00046         TupleDataWithBuffer const & inTuple,
00047         int numSrcTypes,
00048         deque<CalcMessage>& warnings,
00049         vector<int> const & expectedWarnings);
00050 
00051     static void testExe(
00052         SetFunction setF,
00053         CheckFunction checkF,
00054         char const * const srcTypeStr,
00055         int numSrcTypes,
00056         char const * const destTypeStr,
00057         int numDestTypes,
00058         int warningCombos[][2],
00059         bool roundValues);
00060 
00061     static bool shouldWarn(
00062         int warningCombos[][2],
00063         int srcIdx,
00064         int destIdx);
00065 
00066     static void checkWarnings(
00067         deque<CalcMessage>& warnings,
00068         vector<int> const & expectedWarnings);
00069 
00070     void PassAll();
00071 
00072     static void PassAllSet(TupleDataWithBuffer& inTuple);
00073 
00074     static void PassAllCheck(
00075         TupleDataWithBuffer const & outTuple,
00076         int numSrcTypes,
00077         deque<CalcMessage>& warnings,
00078         vector<int> const & expectedWarnings);
00079 
00080     void NegValues();
00081 
00082     static void NegValuesSet(TupleDataWithBuffer& inTuple);
00083 
00084     static void NegValuesCheck(
00085         TupleDataWithBuffer const & outTuple,
00086         int numSrcTypes,
00087         deque<CalcMessage>& warnings,
00088         vector<int> const & expectedWarnings);
00089 
00090     void Round();
00091 
00092     static void RoundSet(TupleDataWithBuffer& inTuple);
00093 
00094     static void RoundCheck(
00095         TupleDataWithBuffer const & outTuple,
00096         int numSrcTypes,
00097         deque<CalcMessage>& warnings,
00098         vector<int> const & expectedWarnings);
00099 
00100 
00101     void Overflow();
00102 
00103     static void OverflowSet(TupleDataWithBuffer& inTuple);
00104 
00105     static void OverflowCheck(
00106         TupleDataWithBuffer const & outTuple,
00107         int numSrcTypes,
00108         deque<CalcMessage>& warnings,
00109         vector<int> const & expectedWarnings);
00110 
00111     void Underflow();
00112 
00113     static void UnderflowSet(TupleDataWithBuffer& inTuple);
00114 
00115     static void UnderflowCheck(
00116         TupleDataWithBuffer const & outTuple,
00117         int numSrcTypes,
00118         deque<CalcMessage>& warnings,
00119         vector<int> const & expectedWarnings);
00120 
00121     void testRoundInstruction();
00122 
00123 public:
00124     explicit CalcCastTest()
00125         : TraceSource(shared_from_this(), "CalcCastTest")
00126     {
00127         srand(time(NULL));
00128         CalcInit::instance();
00129         FENNEL_UNIT_TEST_CASE(CalcCastTest, testRoundInstruction);
00130         FENNEL_UNIT_TEST_CASE(CalcCastTest, PassAll);
00131         FENNEL_UNIT_TEST_CASE(CalcCastTest, NegValues);
00132         FENNEL_UNIT_TEST_CASE(CalcCastTest, Round);
00133         FENNEL_UNIT_TEST_CASE(CalcCastTest, Overflow);
00134         FENNEL_UNIT_TEST_CASE(CalcCastTest, Underflow);
00135     }
00136 
00137     virtual ~CalcCastTest()
00138     {
00139     }
00140 };
00141 
00142 // test rounding away from zero
00143 void
00144 CalcCastTest::testRoundInstruction()
00145 {
00146     ostringstream pg("");
00147     int idx;
00148 
00149     const char * const all =
00150         "s1, u1, s2, u2, s4, u4, s8, u8, r, r, r, r, r, d, d, d, d, d";
00151     //   0   1   2   3   4   5   6   7   8  9  10 11 12 13 14 15 16 17
00152 
00153     pg << "O " << all << ";" << endl;
00154     pg << "L " << all << ";" << endl;
00155     pg << "C " << all << ";" << endl;
00156     pg << "V 2, 2, 2, 2, 2, 2, 2, 2,";
00157     pg << "  -0.5, -0.25, 0.0, 0.25, 0.5,";
00158     pg << "  -0.5, -0.25, 0.0, 0.25, 0.5;" << endl;
00159     pg << "T;" << endl;
00160 
00161     for (idx = 0; idx < 18; idx++) {
00162         pg << "ROUND L" << idx << ", C" << idx << ";" << endl;
00163         pg << "REF   O" << idx << ", L" << idx << ";" << endl;
00164     }
00165 
00166     BOOST_MESSAGE(pg.str());
00167 
00168     Calculator calc(0);
00169 
00170     try {
00171         calc.assemble(pg.str().c_str());
00172     } catch (FennelExcn& ex) {
00173         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00174         BOOST_REQUIRE(0);
00175     }
00176 
00177     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00178     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00179 
00180     calc.bind(&inTuple, &outTuple);
00181     calc.exec();
00182 
00183     int64_t exact = 2;
00184     idx = 0;
00185 
00186     BOOST_CHECK_EQUAL(
00187         *(reinterpret_cast<int8_t *>(
00188             const_cast<PBuffer>(outTuple[idx++].pData))),
00189         exact);
00190 
00191     BOOST_CHECK_EQUAL(
00192         *(reinterpret_cast<uint8_t *>(
00193             const_cast<PBuffer>(outTuple[idx++].pData))),
00194         exact);
00195 
00196     BOOST_CHECK_EQUAL(
00197         *(reinterpret_cast<int16_t *>(
00198             const_cast<PBuffer>(outTuple[idx++].pData))),
00199         exact);
00200 
00201     BOOST_CHECK_EQUAL(
00202         *(reinterpret_cast<uint16_t *>(
00203             const_cast<PBuffer>(outTuple[idx++].pData))),
00204         exact);
00205 
00206     BOOST_CHECK_EQUAL(
00207         *(reinterpret_cast<int32_t *>(
00208             const_cast<PBuffer>(outTuple[idx++].pData))),
00209         exact);
00210 
00211     BOOST_CHECK_EQUAL(
00212         *(reinterpret_cast<uint32_t *>(
00213             const_cast<PBuffer>(outTuple[idx++].pData))),
00214         exact);
00215 
00216     BOOST_CHECK_EQUAL(
00217         *(reinterpret_cast<int64_t *>(
00218             const_cast<PBuffer>(outTuple[idx++].pData))),
00219         exact);
00220 
00221     BOOST_CHECK_EQUAL(
00222         *(reinterpret_cast<uint64_t *>(
00223             const_cast<PBuffer>(outTuple[idx++].pData))),
00224         exact);
00225 
00226     BOOST_CHECK_EQUAL(
00227         *(reinterpret_cast<float *>(
00228             const_cast<PBuffer>(outTuple[idx++].pData))),
00229         -1.0);
00230 
00231     BOOST_CHECK_EQUAL(
00232         *(reinterpret_cast<float *>(
00233             const_cast<PBuffer>(outTuple[idx++].pData))),
00234         0.0);
00235 
00236     BOOST_CHECK_EQUAL(
00237         *(reinterpret_cast<float *>(
00238             const_cast<PBuffer>(outTuple[idx++].pData))),
00239         0.0);
00240 
00241     BOOST_CHECK_EQUAL(
00242         *(reinterpret_cast<float *>(
00243             const_cast<PBuffer>(outTuple[idx++].pData))),
00244         0.0);
00245 
00246     BOOST_CHECK_EQUAL(
00247         *(reinterpret_cast<float *>(
00248             const_cast<PBuffer>(outTuple[idx++].pData))),
00249         1.0);
00250 
00251     BOOST_CHECK_EQUAL(
00252         *(reinterpret_cast<double *>(
00253             const_cast<PBuffer>(outTuple[idx++].pData))),
00254         -1.0);
00255 
00256     BOOST_CHECK_EQUAL(
00257         *(reinterpret_cast<double *>(
00258             const_cast<PBuffer>(outTuple[idx++].pData))),
00259         0.0);
00260 
00261     BOOST_CHECK_EQUAL(
00262         *(reinterpret_cast<double *>(
00263             const_cast<PBuffer>(outTuple[idx++].pData))),
00264         0.0);
00265 
00266     BOOST_CHECK_EQUAL(
00267         *(reinterpret_cast<double *>(
00268             const_cast<PBuffer>(outTuple[idx++].pData))),
00269         0.0);
00270 
00271     BOOST_CHECK_EQUAL(
00272         *(reinterpret_cast<double *>(
00273             const_cast<PBuffer>(outTuple[idx++].pData))),
00274         1.0);
00275 }
00276 
00277 void
00278 CalcCastTest::testExe(
00279     SetFunction setF,
00280     CheckFunction checkF,
00281     char const * const srcTypeStr,
00282     int numSrcTypes,
00283     char const * const destTypeStr,
00284     int numDestTypes,
00285     int warningCombos[][2],
00286     bool roundValues)
00287 {
00288     ostringstream pg(""), typeProduct("");
00289 
00290     int destIdx, srcIdx, idx, pc;
00291     bool warn;
00292     vector<int> expectedWarnings;
00293 
00294     // create a dest array with one row for each src type
00295     for (idx = 0; idx < numSrcTypes; idx++) {
00296         if (idx != 0) {
00297             typeProduct << "," << endl << "  ";
00298         }
00299         typeProduct << destTypeStr;
00300     }
00301     typeProduct << ";" << endl;
00302 
00303     pg << "L " << typeProduct.str();
00304     pg << "O " << typeProduct.str();
00305     pg << "I " << srcTypeStr << ";" << endl;
00306     // Slightly abusive use of status register for rounding.
00307     pg << "S " << srcTypeStr << ";" << endl;
00308     pg << "T;" << endl;
00309 
00310     if (roundValues) {
00311         for (srcIdx = 0; srcIdx < numSrcTypes; srcIdx++) {
00312             pg << "ROUND S" << srcIdx << ", I" << srcIdx << ";" << endl;
00313         }
00314     }
00315 
00316     destIdx = 0;
00317     pc = 0;
00318     for (srcIdx = 0; srcIdx < numSrcTypes; srcIdx++) {
00319         for (idx = 0; idx < numDestTypes; idx++) {
00320             warn = shouldWarn(warningCombos, srcIdx, idx);
00321             if (warn) {
00322                 expectedWarnings.push_back(pc);
00323                 BOOST_MESSAGE(
00324                     "ShouldWarn PC=" << pc << " size="
00325                     << expectedWarnings.size());
00326             }
00327             pg << "CAST L" << destIdx;
00328             if (roundValues) {
00329                 pg << ", S";
00330             } else {
00331                 pg << ", I";
00332             }
00333             pg << srcIdx << ";";
00334             pg << "    /* " << pc++ << (warn ? " WARN" : "");
00335             pg << " src=" << srcIdx << " dest=" << idx <<  "  */" << endl;
00336             pg << "REF  O" << destIdx << ", L" << destIdx << ";";
00337             pg << "    /* " << pc++ <<  " */" << endl;
00338             destIdx++;
00339         }
00340     }
00341 
00342     BOOST_MESSAGE(pg.str());
00343 
00344     Calculator calc(0);
00345 
00346     try {
00347         calc.assemble(pg.str().c_str());
00348     } catch (FennelExcn& ex) {
00349         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00350         BOOST_REQUIRE(0);
00351     }
00352 
00353     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00354     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00355 
00356     calc.bind(&inTuple, &outTuple);
00357 
00358     setF(inTuple);
00359 
00360     calc.exec();
00361     BOOST_MESSAGE("Calculator Warnings: |" << calc.warnings() << "|");
00362     checkF(outTuple, numSrcTypes, calc.mWarnings, expectedWarnings);
00363 }
00364 
00365 bool
00366 CalcCastTest::shouldWarn(
00367     int warningCombos[][2],
00368     int srcIdx,
00369     int destIdx)
00370 {
00371     int idx = 0;
00372     // Yeah, so this is O(n^2). It's good enough for now, and probably forever.
00373     while (warningCombos[idx][0] >= 0 &&
00374            warningCombos[idx][1] >= 0) {
00375         if (warningCombos[idx][0] == srcIdx &&
00376             warningCombos[idx][1] == destIdx) {
00377             return true;
00378         }
00379         idx++;
00380     }
00381     return false;
00382 }
00383 
00384 void
00385 CalcCastTest::checkWarnings(
00386     deque<CalcMessage>& warnings,
00387     vector<int> const & expectedWarnings)
00388 {
00389     deque<CalcMessage>::iterator iter = warnings.begin();
00390     deque<CalcMessage>::iterator end = warnings.end();
00391 
00392     int idx = 0;
00393     ostringstream ew("");
00394     ew << "Expected Warnings: (PC=) |";
00395     while (idx < expectedWarnings.size()) {
00396         ew << expectedWarnings[idx++] << ", ";
00397     }
00398     ew << "|" << endl;
00399     BOOST_MESSAGE(ew.str());
00400 
00401     idx = 0;
00402     while (idx < expectedWarnings.size()) {
00403         BOOST_CHECK(iter != end);
00404         BOOST_CHECK_EQUAL(iter->pc, expectedWarnings[idx]);
00405         BOOST_CHECK_EQUAL(0, strcmp(iter->str, "22003"));
00406         iter++;
00407         idx++;
00408     }
00409     BOOST_CHECK(iter == end);
00410 }
00411 
00412 void
00413 CalcCastTest::PassAllSet(TupleDataWithBuffer& inTuple)
00414 {
00415     uint64_t exact = 10;
00416     double approx = 20.0;
00417     int idx = 0;
00418 
00419     *(reinterpret_cast<int8_t *>
00420       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00421     *(reinterpret_cast<uint8_t *>
00422       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00423     *(reinterpret_cast<int16_t *>
00424       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00425     *(reinterpret_cast<uint16_t *>
00426       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00427     *(reinterpret_cast<int32_t *>
00428       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00429     *(reinterpret_cast<uint32_t *>
00430       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00431     *(reinterpret_cast<int64_t *>
00432       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00433     *(reinterpret_cast<uint64_t *>
00434       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00435 
00436     *(reinterpret_cast<float *>
00437       (const_cast<PBuffer>(inTuple[idx++].pData))) = approx;
00438     *(reinterpret_cast<double *>
00439       (const_cast<PBuffer>(inTuple[idx++].pData))) = approx;
00440 
00441 }
00442 
00443 void
00444 CalcCastTest::PassAllCheck(
00445     TupleDataWithBuffer const & outTuple,
00446     int numSrcTypes,
00447     deque<CalcMessage>& warnings,
00448     vector<int> const & expectedWarnings)
00449 {
00450     checkWarnings(warnings, expectedWarnings);
00451 
00452     uint64_t exact;
00453     double approx;
00454     int i, idx = 0;
00455 
00456     for (i = 0; i < numSrcTypes; i++) {
00457         if (i < 8) {
00458             exact = 10;
00459             approx = 10;
00460         } else {
00461             exact = 20;
00462             approx = 20;
00463         }
00464         BOOST_CHECK_EQUAL(
00465             *(reinterpret_cast<int8_t *>(
00466                 const_cast<PBuffer>(outTuple[idx++].pData))),
00467             exact);
00468 
00469         BOOST_CHECK_EQUAL(
00470             *(reinterpret_cast<uint8_t *>(
00471                 const_cast<PBuffer>(outTuple[idx++].pData))),
00472             exact);
00473 
00474         BOOST_CHECK_EQUAL(
00475             *(reinterpret_cast<int16_t *>(
00476                 const_cast<PBuffer>(outTuple[idx++].pData))),
00477             exact);
00478 
00479         BOOST_CHECK_EQUAL(
00480             *(reinterpret_cast<uint16_t *>(
00481                 const_cast<PBuffer>(outTuple[idx++].pData))),
00482             exact);
00483 
00484         BOOST_CHECK_EQUAL(
00485             *(reinterpret_cast<int32_t *>(
00486                 const_cast<PBuffer>(outTuple[idx++].pData))),
00487             exact);
00488 
00489         BOOST_CHECK_EQUAL(
00490             *(reinterpret_cast<uint32_t *>(
00491                 const_cast<PBuffer>(outTuple[idx++].pData))),
00492             exact);
00493 
00494         BOOST_CHECK_EQUAL(
00495             *(reinterpret_cast<int64_t *>(
00496                 const_cast<PBuffer>(outTuple[idx++].pData))),
00497             exact);
00498 
00499         BOOST_CHECK_EQUAL(
00500             *(reinterpret_cast<uint64_t *>(
00501                 const_cast<PBuffer>(outTuple[idx++].pData))),
00502             exact);
00503 
00504         BOOST_CHECK_EQUAL(
00505             *(reinterpret_cast<float *>(
00506                 const_cast<PBuffer>(outTuple[idx++].pData))),
00507             approx);
00508 
00509         BOOST_CHECK_EQUAL(
00510             *(reinterpret_cast<double *>(
00511                 const_cast<PBuffer>(outTuple[idx++].pData))),
00512             approx);
00513     }
00514 }
00515 
00516 
00517 void
00518 CalcCastTest::PassAll()
00519 {
00520     char const * const all =
00521         "s1, u1, s2, u2, s4, u4, s8, u8, r, d";
00522     //   0   1   2   3   4   5   6   7   8  9
00523 
00524     int warningCombos[][2] = {
00525         // src index from just above, then dest index from just above
00526         { -1, -1 }   // sentinel
00527     };
00528 
00529     testExe(
00530         CalcCastTest::PassAllSet,
00531         CalcCastTest::PassAllCheck,
00532         all, 10,
00533         all, 10,
00534         warningCombos,
00535         false);
00536 }
00537 
00538 
00539 void
00540 CalcCastTest::NegValuesSet(TupleDataWithBuffer& inTuple)
00541 {
00542     int64_t exact = -10;
00543     double approx = -20.0;
00544     int idx = 0;
00545 
00546     *(reinterpret_cast<int8_t *>
00547       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00548     *(reinterpret_cast<int16_t *>
00549       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00550     *(reinterpret_cast<int32_t *>
00551       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00552     *(reinterpret_cast<int64_t *>
00553       (const_cast<PBuffer>(inTuple[idx++].pData))) = exact;
00554 
00555     *(reinterpret_cast<float *>
00556       (const_cast<PBuffer>(inTuple[idx++].pData))) = approx;
00557     *(reinterpret_cast<double *>
00558       (const_cast<PBuffer>(inTuple[idx++].pData))) = approx;
00559 }
00560 
00561 void
00562 CalcCastTest::NegValuesCheck(
00563     TupleDataWithBuffer const & outTuple,
00564     int numSrcTypes,
00565     deque<CalcMessage>& warnings,
00566     vector<int> const & expectedWarnings)
00567 {
00568     checkWarnings(warnings, expectedWarnings);
00569 
00570     int64_t exact = -10;
00571     double approx = -20.0;
00572     int i, idx = 0;
00573 
00574     for (i = 0; i < numSrcTypes; i++) {
00575         if (i < 4) {
00576             exact = -10;
00577             approx = -10;
00578         } else {
00579             exact = -20;
00580             approx = -20;
00581         }
00582         BOOST_CHECK_EQUAL(
00583             *(reinterpret_cast<int8_t *>(
00584                 const_cast<PBuffer>(outTuple[idx++].pData))),
00585             exact);
00586 
00587         // uint8_t always generates a warning
00588         idx++;
00589 
00590         BOOST_CHECK_EQUAL(
00591             *(reinterpret_cast<int16_t *>(
00592                 const_cast<PBuffer>(outTuple[idx++].pData))),
00593             exact);
00594 
00595         // uint16_t always generates a warning
00596         idx++;
00597 
00598         BOOST_CHECK_EQUAL(
00599             *(reinterpret_cast<int32_t *>(
00600                 const_cast<PBuffer>(outTuple[idx++].pData))),
00601             exact);
00602 
00603         // uint32_t always generates a warning
00604         idx++;
00605 
00606         BOOST_CHECK_EQUAL(
00607             *(reinterpret_cast<int64_t *>(
00608                 const_cast<PBuffer>(outTuple[idx++].pData))),
00609             exact);
00610 
00611         // uint64_t always generates a warning
00612         idx++;
00613 
00614         BOOST_CHECK_EQUAL(
00615             *(reinterpret_cast<float *>(
00616                 const_cast<PBuffer>(outTuple[idx++].pData))),
00617             approx);
00618 
00619         BOOST_CHECK_EQUAL(
00620             *(reinterpret_cast<double *>(
00621                 const_cast<PBuffer>(outTuple[idx++].pData))),
00622             approx);
00623     }
00624 }
00625 
00626 
00627 void
00628 CalcCastTest::NegValues()
00629 {
00630     char const * const src =
00631         "s1, s2, s4, s8, r, d";
00632     //   0   1   2   3   4  5
00633 
00634     char const * const dest =
00635         "s1, u1, s2, u2, s4, u4, s8, u8, r, d";
00636     //   0   1   2   3   4   5   6   7   8  9
00637 
00638     // combinations of types above that should generate warnings
00639     int warningCombos[][2] = {
00640         // src index from just above, then dest index from just above
00641         {0,  1  },  // s1 -> u1
00642         {  0,  3  },  // s1 -> u2
00643         {  0,  5  },
00644         {  0,  7  },
00645         {  1,  1  },  // s2 -> u1
00646         {  1,  3  },  // s2 -> u2
00647         {  1,  5  },
00648         {  1,  7  },
00649         {  2,  1  },  // s4 -> u1
00650         {  2,  3  },  // s4 -> u2
00651         {  2,  5  },
00652         {  2,  7  },
00653         {  3,  1  },  // s8 -> u1
00654         {  3,  3  },  // s8 -> u2
00655         {  3,  5  },
00656         {  3,  7  },
00657         {  4,  1  },  // r -> u1
00658         {  4,  3  },  // r -> u2
00659         {  4,  5  },
00660         {  4,  7  },
00661         {  5,  1  },  // d -> u1
00662         {  5,  3  },  // d -> u2
00663         {  5,  5  },
00664         {  5,  7  },
00665         {  -1, -1 }   // sentinel
00666     };
00667 
00668     testExe(
00669         CalcCastTest::NegValuesSet,
00670         CalcCastTest::NegValuesCheck,
00671         src, 6,
00672         dest, 10,
00673         warningCombos,
00674         false);
00675 }
00676 
00677 
00678 void
00679 CalcCastTest::RoundSet(TupleDataWithBuffer& inTuple)
00680 {
00681     // expect 20, 21, 21
00682     double val[3] = { 20.2, 20.5, 20.7 };
00683 
00684     int idx = 0, group;
00685 
00686     for (group = 0; group < 3; group++) {
00687         *(reinterpret_cast<float *>
00688           (const_cast<PBuffer>(inTuple[idx++].pData))) = val[group];
00689         *(reinterpret_cast<double *>
00690           (const_cast<PBuffer>(inTuple[idx++].pData))) = val[group];
00691     }
00692 }
00693 
00694 void
00695 CalcCastTest::RoundCheck(
00696     TupleDataWithBuffer const & outTuple,
00697     int numSrcTypes,
00698     deque<CalcMessage>& warnings,
00699     vector<int> const & expectedWarnings)
00700 {
00701     checkWarnings(warnings, expectedWarnings);
00702 
00703     int64_t valE[3] = { 20, 21, 21 }, exact;
00704     int group, srcI, idx = 0;
00705 
00706     for (group = 0; group < 3; group++) {
00707         exact = valE[group];
00708         for (srcI = 0; srcI < 2; srcI++) {
00709             BOOST_CHECK_EQUAL(
00710                 *(reinterpret_cast<int8_t *>(
00711                     const_cast<PBuffer>(outTuple[idx++].pData))),
00712                 exact);
00713 
00714             BOOST_CHECK_EQUAL(
00715                 *(reinterpret_cast<uint8_t *>(
00716                     const_cast<PBuffer>(outTuple[idx++].pData))),
00717                 exact);
00718 
00719             BOOST_CHECK_EQUAL(
00720                 *(reinterpret_cast<int16_t *>(
00721                     const_cast<PBuffer>(outTuple[idx++].pData))),
00722                 exact);
00723 
00724             BOOST_CHECK_EQUAL(
00725                 *(reinterpret_cast<uint16_t *>(
00726                     const_cast<PBuffer>(outTuple[idx++].pData))),
00727                 exact);
00728 
00729             BOOST_CHECK_EQUAL(
00730                 *(reinterpret_cast<int32_t *>(
00731                     const_cast<PBuffer>(outTuple[idx++].pData))),
00732                 exact);
00733 
00734             BOOST_CHECK_EQUAL(
00735                 *(reinterpret_cast<uint32_t *>(
00736                     const_cast<PBuffer>(outTuple[idx++].pData))),
00737                 exact);
00738 
00739             BOOST_CHECK_EQUAL(
00740                 *(reinterpret_cast<int64_t *>(
00741                     const_cast<PBuffer>(outTuple[idx++].pData))),
00742                 exact);
00743 
00744             BOOST_CHECK_EQUAL(
00745                 *(reinterpret_cast<uint64_t *>(
00746                     const_cast<PBuffer>(outTuple[idx++].pData))),
00747                 exact);
00748         }
00749     }
00750 }
00751 
00752 
00753 void
00754 CalcCastTest::Round()
00755 {
00756     char const * const src =
00757         "r, d, r, d, r, d";
00758     //   0  1  2  3  4  5
00759 
00760     char const * const dest =
00761         "s1, u1, s2, u2, s4, u4, s8, u8";
00762     //   0   1   2   3   4   5   6   7
00763 
00764     // combinations of types above that should generate warnings
00765     int warningCombos[][2] = {
00766         // src index from just above, then dest index from just above
00767         {  -1, -1 }   // sentinel
00768     };
00769 
00770     testExe(
00771         CalcCastTest::RoundSet,
00772         CalcCastTest::RoundCheck,
00773         src, 6,
00774         dest, 8,
00775         warningCombos,
00776         true);
00777 }
00778 
00779 
00780 void
00781 CalcCastTest::OverflowSet(TupleDataWithBuffer& inTuple)
00782 {
00783     int idx = 0;
00784 
00785     *(reinterpret_cast<int8_t *>
00786       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00787         std::numeric_limits<int8_t>::max();
00788     *(reinterpret_cast<uint8_t *>
00789       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00790         std::numeric_limits<uint8_t>::max();
00791     *(reinterpret_cast<int16_t *>
00792       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00793         std::numeric_limits<int16_t>::max();
00794     *(reinterpret_cast<uint16_t *>
00795       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00796         std::numeric_limits<uint16_t>::max();
00797     *(reinterpret_cast<int32_t *>
00798       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00799         std::numeric_limits<int32_t>::max();
00800     *(reinterpret_cast<uint32_t *>
00801       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00802         std::numeric_limits<uint32_t>::max();
00803     *(reinterpret_cast<int64_t *>
00804       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00805         std::numeric_limits<int64_t>::max();
00806     *(reinterpret_cast<uint64_t *>
00807       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00808         std::numeric_limits<uint64_t>::max();
00809     *(reinterpret_cast<float *>
00810       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00811         std::numeric_limits<float>::max();
00812     *(reinterpret_cast<double *>
00813       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00814         std::numeric_limits<double>::max();
00815 }
00816 
00817 void
00818 CalcCastTest::OverflowCheck(
00819     TupleDataWithBuffer const & outTuple,
00820     int numSrcTypes,
00821     deque<CalcMessage>& warnings,
00822     vector<int> const & expectedWarnings)
00823 {
00824     checkWarnings(warnings, expectedWarnings);
00825 
00826     // TODO: Checking that the non-warning values are correct would be
00827     // rather complex. Punt for now.
00828 }
00829 
00830 
00831 void
00832 CalcCastTest::Overflow()
00833 {
00834     char const * const src =
00835         "s1, u1, s2, u2, s4, u4, s8, u8, r, d";
00836     //   0   1   2   3   4   5   6   7   8  9
00837 
00838     char const * const dest =
00839         "s1, u1, s2, u2, s4, u4, s8, u8, r, d";
00840     //   0   1   2   3   4   5   6   7   8  9
00841 
00842     // combinations of types above that should generate warnings
00843     int warningCombos[][2] = {
00844         // src index from just above, then dest index from just above
00845         {  1,  0  },  // u1 -> s1
00846         {  2,  0  },  // s2 -> s1
00847         {  2,  1  },  // s2 -> u1
00848         {  3,  0  },  // u2 -> s1
00849         {  3,  1  },  // u2 -> u1
00850         {  3,  2  },  // u2 -> s2
00851         {  4,  0  },  // s4 -> s1
00852         {  4,  1  },  // s4 -> u1
00853         {  4,  2  },  // s4 -> s2
00854         {  4,  3  },  // s4 -> s2
00855         {  5,  0  },  // u4 -> s1
00856         {  5,  1  },  // u4 -> u1
00857         {  5,  2  },  // u4 -> s2
00858         {  5,  3  },  // u4 -> s2
00859         {  5,  4  },  // u4 -> s2
00860         {  6,  0  },  // etc...
00861         {  6,  1  },
00862         {  6,  2  },
00863         {  6,  3  },
00864         {  6,  4  },
00865         {  6,  5  },
00866         {  7,  0  },
00867         {  7,  1  },
00868         {  7,  2  },
00869         {  7,  3  },
00870         {  7,  4  },
00871         {  7,  5  },
00872         {  7,  6  },  // u8 -> s8
00873         // REVIEW jvs 14-Aug-2005:  When I upgraded
00874         // to boost 1.33, the semantics for these two changed.
00875         // Loss of precision isn't the same as overflow, so
00876         // maybe the new semantics are better?
00877         /*
00878         {  7,  8  },  // u8 -> r (loss of precision)
00879         {  7,  9  },  // u8 -> d (loss of precision)
00880         */
00881         {  8,  0  },
00882         {  8,  1  },
00883         {  8,  2  },
00884         {  8,  3  },
00885         {  8,  4  },
00886         {  8,  5  },
00887         {  8,  6  },  // man, you'd think I'da automated this by now.
00888         {  8,  7  },
00889         {  9,  0  },
00890         {  9,  1  },
00891         {  9,  2  },
00892         {  9,  3  },
00893         {  9,  4  },
00894         {  9,  5  },
00895         {  9,  6  },
00896         {  9,  7  },
00897         {  9,  8  },  // d -> r
00898 
00899         { -1, -1  }   // sentinel
00900     };
00901 
00902     testExe(
00903         CalcCastTest::OverflowSet,
00904             CalcCastTest::OverflowCheck,
00905             src, 10,
00906             dest, 10,
00907             warningCombos,
00908             false);
00909 }
00910 
00911 
00912 
00913 void
00914 CalcCastTest::UnderflowSet(TupleDataWithBuffer& inTuple)
00915 {
00916     int idx = 0;
00917 
00918     *(reinterpret_cast<int8_t *>
00919       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00920         std::numeric_limits<int8_t>::min();
00921     *(reinterpret_cast<uint8_t *>
00922       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00923         std::numeric_limits<uint8_t>::min();
00924     *(reinterpret_cast<int16_t *>
00925       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00926         std::numeric_limits<int16_t>::min();
00927     *(reinterpret_cast<uint16_t *>
00928       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00929         std::numeric_limits<uint16_t>::min();
00930     *(reinterpret_cast<int32_t *>
00931       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00932         std::numeric_limits<int32_t>::min();
00933     *(reinterpret_cast<uint32_t *>
00934       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00935         std::numeric_limits<uint32_t>::min();
00936     *(reinterpret_cast<int64_t *>
00937       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00938         std::numeric_limits<int64_t>::min();
00939     *(reinterpret_cast<uint64_t *>
00940       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00941         std::numeric_limits<uint64_t>::min();
00942 
00943     // Note: min() for approx type is the smallest positive
00944     // number, not the most negative number. Unary minus of max()
00945     // gives smallest possible (very negative) number.
00946     *(reinterpret_cast<float *>
00947       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00948         -std::numeric_limits<float>::max();
00949     *(reinterpret_cast<double *>
00950       (const_cast<PBuffer>(inTuple[idx++].pData))) =
00951         -std::numeric_limits<double>::max();
00952 }
00953 
00954 void
00955 CalcCastTest::UnderflowCheck(
00956     TupleDataWithBuffer const & outTuple,
00957     int numSrcTypes,
00958     deque<CalcMessage>& warnings,
00959     vector<int> const & expectedWarnings)
00960 {
00961     checkWarnings(warnings, expectedWarnings);
00962 
00963     // TODO: Checking that the non-warning values are correct would be
00964     // rather complex. Punt for now.
00965 }
00966 
00967 
00968 void
00969 CalcCastTest::Underflow()
00970 {
00971     char const * const src =
00972         "s1, u1, s2, u2, s4, u4, s8, u8, r, d";
00973     //   0   1   2   3   4   5   6   7   8  9
00974 
00975     char const * const dest =
00976         "s1, u1, s2, u2, s4, u4, s8, u8, r, d";
00977     //   0   1   2   3   4   5   6   7   8  9
00978 
00979     // combinations of types above that should generate warnings
00980     int warningCombos[][2] = {
00981         // src index from just above, then dest index from just above
00982         {  0,  1  },  // s1 -> u1
00983         {  0,  3  },  // s1 -> u2
00984         {  0,  5  },  // s1 -> u4
00985         {  0,  7  },  // s1 -> u8
00986 
00987         {  2,  0  },  // s2 -> s1
00988         {  2,  1  },  // s2 -> u1
00989         {  2,  3  },  // s2 -> u2
00990         {  2,  5  },  // s2 -> u4
00991         {  2,  7  },  // s2 -> u8
00992 
00993         {  4,  0  },  // s4 -> s1
00994         {  4,  1  },  // s4 -> u1
00995         {  4,  2  },  // s4 -> s2
00996         {  4,  3  },  // s4 -> u2
00997         {  4,  5  },  // s4 -> u4
00998         {  4,  7  },  // s4 -> u8
00999 
01000         {  6,  0  },  // s8 -> s1
01001         {  6,  1  },  // s8 -> u1
01002         {  6,  2  },  // s8 -> s2
01003         {  6,  3  },  // s8 -> u2
01004         {  6,  4  },  // s8 -> s4
01005         {  6,  5  },  // s8 -> u4
01006         {  6,  7  },  // s8 -> u8
01007 
01008         {  8,  0  },  // r -> s1
01009         {  8,  1  },  // r -> u1
01010         {  8,  2  },  // r -> s2
01011         {  8,  3  },  // r -> u2
01012         {  8,  4  },  // r -> s4
01013         {  8,  5  },  // r -> u4
01014         {  8,  6  },  // r -> s8
01015         {  8,  7  },  // r -> u8
01016 
01017         {  9,  0  },  // d -> s1
01018         {  9,  1  },  // d -> u1
01019         {  9,  2  },  // d -> s2
01020         {  9,  3  },  // d -> u2
01021         {  9,  4  },  // d -> s4
01022         {  9,  5  },  // d -> u4
01023         {  9,  6  },  // d -> s8
01024         {  9,  7  },  // d -> u8
01025         {  9,  8  },  // d -> r
01026 
01027         { -1, -1  }   // sentinel
01028     };
01029 
01030     testExe(
01031         CalcCastTest::UnderflowSet,
01032         CalcCastTest::UnderflowCheck,
01033         src, 10,
01034         dest, 10,
01035         warningCombos,
01036         false);
01037 }
01038 
01039 
01040 FENNEL_UNIT_TEST_SUITE(CalcCastTest);
01041 
01042 // End CalcCastTest.cpp

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