CalcMiscTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calctest/CalcMiscTest.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 
00039 using namespace fennel;
00040 using namespace std;
00041 
00042 
00043 class CalcMiscTest : virtual public TestBase, public TraceSource
00044 {
00045     void testCalcStatusReg();
00046     void testCalcStatusRegZero();
00047     void testCalcRefInst();
00048     void testCalcReturn();
00049     void testCalcRaise();
00050     void testCalcContinueOnException();
00051 
00052 public:
00053     explicit CalcMiscTest()
00054         : TraceSource(shared_from_this(),"CalcMiscTest")
00055     {
00056         srand(time(NULL));
00057         CalcInit::instance();
00058         FENNEL_UNIT_TEST_CASE(CalcMiscTest, testCalcStatusReg);
00059         FENNEL_UNIT_TEST_CASE(CalcMiscTest, testCalcStatusRegZero);
00060         FENNEL_UNIT_TEST_CASE(CalcMiscTest, testCalcRefInst);
00061         FENNEL_UNIT_TEST_CASE(CalcMiscTest, testCalcReturn);
00062         FENNEL_UNIT_TEST_CASE(CalcMiscTest, testCalcRaise);
00063         FENNEL_UNIT_TEST_CASE(CalcMiscTest, testCalcContinueOnException);
00064     }
00065 
00066     virtual ~CalcMiscTest()
00067     {
00068     }
00069 };
00070 
00071 void
00072 CalcMiscTest::testCalcStatusReg()
00073 {
00074     ostringstream pg("");
00075 
00076     pg << "L u2;" << endl;
00077     pg << "O u2;" << endl;
00078     pg << "S u2, u2, u2;" << endl;
00079     pg << "C u2, u2, u2;" << endl;
00080     pg << "V 4, 5, 6;" << endl;
00081     pg << "T;" << endl;
00082     pg << "MOVE S 0, C 0;" << endl;
00083     pg << "MOVE L 0, C 1;" << endl;
00084     pg << "REF  O 0, C 2;" << endl;
00085     pg << "MOVE S 1, L 0;" << endl;
00086     pg << "MOVE S 2, O 0;" << endl;
00087 
00088     // BOOST_MESSAGE(pg.str());
00089 
00090     Calculator calc(0);
00091 
00092     try {
00093         calc.assemble(pg.str().c_str());
00094     } catch (FennelExcn& ex) {
00095         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00096         BOOST_REQUIRE(0);
00097     }
00098 
00099     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00100     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00101 
00102     calc.bind(&inTuple, &outTuple);
00103     calc.exec();
00104 
00105     TupleData const * const statusTuple = calc.getStatusRegister();
00106 #if 0
00107     TupleDescriptor statusDesc = calc.getStatusRegisterDescriptor();
00108     TuplePrinter tuplePrinter;
00109     tuplePrinter.print(cout, statusDesc, *statusTuple);
00110     cout << endl;
00111 #endif
00112 
00113     BOOST_CHECK_EQUAL(
00114         *(reinterpret_cast<uint16_t *>(
00115             const_cast<PBuffer>((*statusTuple)[0].pData))),
00116         4);
00117     BOOST_CHECK_EQUAL(
00118         *(reinterpret_cast<uint16_t *>(
00119             const_cast<PBuffer>((*statusTuple)[1].pData))),
00120         5);
00121     BOOST_CHECK_EQUAL(
00122         *(reinterpret_cast<uint16_t *>(
00123             const_cast<PBuffer>((*statusTuple)[2].pData))),
00124         6);
00125 }
00126 
00127 void
00128 CalcMiscTest::testCalcStatusRegZero()
00129 {
00130     ostringstream pg("");
00131 
00132     pg << "L u2;" << endl;
00133     pg << "O u2;" << endl;
00134     pg << "S u2, u2;" << endl;
00135     pg << "C u2, u2;" << endl;
00136     pg << "V 1, 2;" << endl;
00137     pg << "T;" << endl;
00138     pg << "MOVE L 0, S 0;" << endl;
00139     pg << "ADD S 0, L 0, C 0;" << endl;
00140     pg << "MOVE L 0, S 1;" << endl;
00141     pg << "ADD S 1, L 0, C 1;" << endl;
00142 
00143     // BOOST_MESSAGE(pg.str());
00144 
00145     Calculator calc(0);
00146 
00147     try {
00148         calc.assemble(pg.str().c_str());
00149     } catch (FennelExcn& ex) {
00150         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00151         BOOST_REQUIRE(0);
00152     }
00153 
00154     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00155     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00156 
00157     calc.bind(&inTuple, &outTuple);
00158 
00159     TupleData const * const statusTuple = calc.getStatusRegister();
00160 
00161     for (int i = 1; i <= 3; i++) {
00162         calc.exec();
00163 
00164         BOOST_CHECK_EQUAL(
00165             *(reinterpret_cast<uint16_t *>(
00166                 const_cast<PBuffer>((*statusTuple)[0].pData))),
00167             i);
00168         BOOST_CHECK_EQUAL(
00169             *(reinterpret_cast<uint16_t *>(
00170                 const_cast<PBuffer>((*statusTuple)[1].pData))),
00171             i * 2);
00172     }
00173 
00174     calc.zeroStatusRegister();
00175 
00176     BOOST_CHECK_EQUAL(
00177         *(reinterpret_cast<uint16_t *>(
00178             const_cast<PBuffer>((*statusTuple)[0].pData))),
00179         0);
00180     BOOST_CHECK_EQUAL(
00181         *(reinterpret_cast<uint16_t *>(
00182             const_cast<PBuffer>((*statusTuple)[1].pData))),
00183         0);
00184 
00185     calc.exec();
00186 
00187     BOOST_CHECK_EQUAL(
00188         *(reinterpret_cast<uint16_t *>(
00189             const_cast<PBuffer>((*statusTuple)[0].pData))),
00190         1);
00191     BOOST_CHECK_EQUAL(
00192         *(reinterpret_cast<uint16_t *>(
00193             const_cast<PBuffer>((*statusTuple)[1].pData))),
00194         2);
00195 }
00196 
00197 void
00198 CalcMiscTest::testCalcRefInst()
00199 {
00200     ostringstream pg("");
00201 
00202     char const * const all =
00203         "bo, s1, u1, s2, u2, s4, u4, s8, u8, r, d, vc,2, c,2";
00204     //   0   1   2   3   4   5   6   7   8   9  10 11    12
00205     int const numTypes = 13;
00206     char regs[] = { 'I', 'L', 'C' };
00207     int const numRegSets = 3;
00208 
00209     // TODO: Add binary and varbinary once supported.
00210     pg << "I " << all << ";" << endl;
00211     pg << "O " << all << ", " << endl;
00212     pg << "  " << all << ", " << endl;
00213     pg << "  " << all << ";" << endl;
00214     pg << "L " << all << ";" << endl;
00215     pg << "C " << all << ";" << endl;
00216     pg << "V 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.0, 10.0, 0x";
00217     pg << stringToHex("11") << ", 0x" << stringToHex("12") << ";" << endl;
00218     pg << "T;" << endl;
00219 
00220     int outReg = 0, regSet, regFrom;
00221     // copy constants to local
00222     for (regFrom = 0; regFrom < numTypes; regFrom++) {
00223         pg << "MOVE L" << regFrom << ", C" << regFrom << ";" << endl;
00224     }
00225 
00226     // have output refer to other three sets
00227     for (regSet = 0; regSet < numRegSets; regSet++) {
00228         for (regFrom = 0; regFrom < numTypes; regFrom++) {
00229             pg << "REF O" << outReg++ << ", " << regs[regSet];
00230             pg << regFrom << ";" << endl;
00231         }
00232     }
00233 
00234     //    BOOST_MESSAGE(pg.str());
00235 
00236     Calculator calc(0);
00237 
00238     try {
00239         calc.assemble(pg.str().c_str());
00240     } catch (FennelExcn& ex) {
00241         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00242         BOOST_REQUIRE(0);
00243     }
00244 
00245     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00246     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00247 
00248     calc.bind(&inTuple, &outTuple);
00249     calc.exec();
00250 
00251     outReg = 0;
00252     for (regSet = 0; regSet < numRegSets; regSet++) {
00253         for (regFrom = 0; regFrom < numTypes; regFrom++) {
00254             switch (regs[regSet]) {
00255             case 'I':
00256                 // verify that pointers are identical
00257                 BOOST_CHECK_EQUAL(
00258                     outTuple[outReg].pData,
00259                     inTuple[regFrom].pData);
00260                 break;
00261             case 'L':
00262             case 'C':
00263                 // no trivial way to verify that pointers
00264                 // are identical w/o breaking object encapsulation
00265                 // of calculator. instead, see if data matches up.
00266                 // should be sufficent.
00267                 if (regFrom <= 8) {
00268                     // integer natives cast correctly w/o help
00269                     // (at least on x86!)
00270                     BOOST_CHECK_EQUAL(
00271                         *(outTuple[outReg].pData),
00272                         regFrom);
00273                 } else if (regFrom == 9) {
00274                     // real (float)
00275                     BOOST_CHECK_EQUAL(
00276                         *(reinterpret_cast<float const *>(
00277                             outTuple[outReg].pData)),
00278                         static_cast<float>(regFrom));
00279                 } else if (regFrom == 10) {
00280                     // double
00281                     BOOST_CHECK_EQUAL(
00282                         *(reinterpret_cast<double const*>(
00283                             outTuple[outReg].pData)),
00284                         static_cast<double>(regFrom));
00285                 } else if (regFrom == 11) {
00286                     // varchar string
00287                     BOOST_CHECK_EQUAL(
00288                         0,
00289                         strncmp(
00290                             reinterpret_cast<char const *>(
00291                                 outTuple[outReg].pData),
00292                             "11",
00293                             2));
00294                 } else if (regFrom == 12) {
00295                     // char string
00296                     BOOST_CHECK_EQUAL(
00297                         0,
00298                         strncmp(
00299                             reinterpret_cast<char const *>(
00300                                 outTuple[outReg].pData),
00301                             "12",
00302                             2));
00303                 } else {
00304                     BOOST_FAIL("logic error");
00305                 }
00306                 break;
00307             }
00308             outReg++;
00309         }
00310     }
00311 }
00312 
00313 void
00314 CalcMiscTest::testCalcReturn()
00315 {
00316     ostringstream pg("");
00317 
00318     pg << "S u4;" << endl;
00319     pg << "C u4, u4, u4;" << endl;
00320     pg << "V 4, 5, 6;" << endl;
00321     pg << "T;" << endl;
00322     pg << "MOVE S 0, C 0;" << endl;
00323     pg << "RETURN;" << endl;
00324     pg << "MOVE S 0, C 1;" << endl;
00325 
00326     // BOOST_MESSAGE(pg.str());
00327 
00328     Calculator calc(0);
00329 
00330     try {
00331         calc.assemble(pg.str().c_str());
00332     } catch (FennelExcn& ex) {
00333         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00334         BOOST_REQUIRE(0);
00335     }
00336 
00337     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00338     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00339 
00340     calc.bind(&inTuple, &outTuple);
00341     calc.exec();
00342 
00343     TupleData const * const statusTuple = calc.getStatusRegister();
00344 #if 0
00345     TupleDescriptor statusDesc = calc.getStatusRegisterDescriptor();
00346     TuplePrinter tuplePrinter;
00347     tuplePrinter.print(cout, statusDesc, *statusTuple);
00348     cout << endl;
00349 #endif
00350 
00351     BOOST_CHECK_EQUAL(
00352         *(reinterpret_cast<uint32_t *>(
00353             const_cast<PBuffer>((*statusTuple)[0].pData))),
00354         4);
00355 }
00356 
00357 
00358 void
00359 CalcMiscTest::testCalcRaise()
00360 {
00361     ostringstream pg("");
00362 
00363     pg << "I u4;" << endl;
00364     pg << "S u4;" << endl;
00365     pg << "C u4, u4, vc,5, vc,5;" << endl;
00366     pg << "V 4, 5, 0x" << stringToHex("12345") << ",;" << endl;
00367     pg << "T;" << endl;
00368     pg << "MOVE S0, C0;" << endl;
00369     pg << "RAISE C2;" << endl;
00370     pg << "RAISE C3;" << endl; // null should induce no-op mode;
00371     pg << "MOVE S0, C1;" << endl;
00372     pg << "RETURN;" << endl;
00373 
00374     //    BOOST_MESSAGE(pg.str());
00375 
00376     Calculator calc(0);
00377 
00378     try {
00379         calc.assemble(pg.str().c_str());
00380     } catch (FennelExcn& ex) {
00381         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00382         BOOST_REQUIRE(0);
00383     }
00384 
00385     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00386     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00387 
00388     calc.bind(&inTuple, &outTuple);
00389     calc.exec();
00390 
00391     TupleData const * const statusTuple = calc.getStatusRegister();
00392 #if 0
00393     TupleDescriptor statusDesc = calc.getStatusRegisterDescriptor();
00394     TuplePrinter tuplePrinter;
00395     tuplePrinter.print(cout, statusDesc, *statusTuple);
00396     cout << endl;
00397 #endif
00398 
00399     BOOST_CHECK_EQUAL(
00400         *(reinterpret_cast<uint32_t *>(
00401             const_cast<PBuffer>((*statusTuple)[0].pData))),
00402         5);
00403 
00404     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00405     deque<CalcMessage>::iterator end = calc.mWarnings.end();
00406 
00407     //BOOST_MESSAGE("warnings: |" << calc.warnings() << "|");
00408 
00409     BOOST_CHECK(iter != end);
00410     BOOST_CHECK_EQUAL(iter->pc, 1);
00411     BOOST_CHECK_EQUAL(0, strcmp(iter->str, "12345"));
00412     iter++;
00413     BOOST_CHECK(iter == end);
00414 }
00415 
00416 void
00417 CalcMiscTest::testCalcContinueOnException()
00418 {
00419     ostringstream pg("");
00420 
00421     pg << "I u4;" << endl;
00422     pg << "S u4;" << endl;
00423     pg << "C u4, u4, vc,5, vc,5;" << endl;
00424     pg << "V 4, 5, 0x" << stringToHex("12345") << ",;" << endl;
00425     pg << "T;" << endl;
00426     pg << "MOVE S0, C0;" << endl;
00427     pg << "RAISE C2;" << endl;
00428     pg << "MOVE S0, C1;" << endl;
00429     pg << "RETURN;" << endl;
00430 
00431     BOOST_MESSAGE(pg.str());
00432 
00433     Calculator calc(0);
00434 
00435     try {
00436         calc.assemble(pg.str().c_str());
00437     } catch (FennelExcn& ex) {
00438         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00439         BOOST_REQUIRE(0);
00440     }
00441 
00442     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00443     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00444 
00445     calc.bind(&inTuple, &outTuple);
00446     // run default mode, which continues after exception
00447     calc.exec();
00448 
00449     TupleData const * const statusTuple = calc.getStatusRegister();
00450 #if 0
00451     TupleDescriptor statusDesc = calc.getStatusRegisterDescriptor();
00452     TuplePrinter tuplePrinter;
00453     tuplePrinter.print(cout, statusDesc, *statusTuple);
00454     cout << endl;
00455 #endif
00456 
00457     BOOST_CHECK_EQUAL(
00458         *(reinterpret_cast<uint32_t *>(
00459             const_cast<PBuffer>((*statusTuple)[0].pData))),
00460         5);
00461 
00462     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00463     deque<CalcMessage>::iterator end = calc.mWarnings.end();
00464 
00465     BOOST_MESSAGE("warnings: |" << calc.warnings() << "|");
00466 
00467     BOOST_CHECK(iter != end);
00468     BOOST_CHECK_EQUAL(
00469             iter->pc, 1);
00470     BOOST_CHECK_EQUAL(
00471             0, strcmp(iter->str, "12345"));
00472     iter++;
00473     BOOST_CHECK(iter == end);
00474 
00475     // change mode to return on exception
00476     calc.continueOnException(false);
00477     calc.exec();
00478 
00479     BOOST_CHECK_EQUAL(
00480         *(reinterpret_cast<uint32_t *>(
00481             const_cast<PBuffer>((*statusTuple)[0].pData))),
00482         4);
00483 
00484     iter = calc.mWarnings.begin();
00485     end = calc.mWarnings.end();
00486 
00487     BOOST_MESSAGE("warnings: |" << calc.warnings() << "|");
00488 
00489     BOOST_CHECK(iter != end);
00490     BOOST_CHECK_EQUAL(
00491             iter->pc, 1);
00492     BOOST_CHECK_EQUAL(
00493             0, strcmp(iter->str, "12345"));
00494     iter++;
00495     BOOST_CHECK(iter == end);
00496 
00497 }
00498 
00499 FENNEL_UNIT_TEST_SUITE(CalcMiscTest);
00500 
00501 // End CalcMiscTest.cpp

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