CalcExtMathTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calctest/CalcExtMathTest.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 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/test/TestBase.h"
00026 #include "fennel/common/TraceSource.h"
00027 
00028 #include "fennel/tuple/TupleDataWithBuffer.h"
00029 #include "fennel/tuple/TuplePrinter.h"
00030 #include "fennel/calculator/CalcCommon.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 #include <math.h>
00038 
00039 using namespace fennel;
00040 using namespace std;
00041 
00042 
00043 class CalcExtMathTest : virtual public TestBase, public TraceSource
00044 {
00045     void checkWarnings(Calculator& calc, string expected);
00046 
00047     void testCalcExtMathLogarithms();
00048     void testCalcExtMathLogarithmsFails();
00049     void testCalcExtMathPow();
00050     void testCalcExtMathPowFails();
00051     void testCalcExtMathAbs();
00052 
00053     void printOutput(
00054         TupleData const & tup,
00055         Calculator const & calc);
00056 
00057     string mProgramPower;
00058 public:
00059     explicit CalcExtMathTest()
00060         : TraceSource(shared_from_this(),"CalcExtMathTest")
00061     {
00062         srand(time(NULL));
00063         CalcInit::instance();
00064         FENNEL_UNIT_TEST_CASE(CalcExtMathTest, testCalcExtMathLogarithms);
00065         FENNEL_UNIT_TEST_CASE(CalcExtMathTest, testCalcExtMathLogarithmsFails);
00066         FENNEL_UNIT_TEST_CASE(CalcExtMathTest, testCalcExtMathAbs);
00067         FENNEL_UNIT_TEST_CASE(CalcExtMathTest, testCalcExtMathPow);
00068         FENNEL_UNIT_TEST_CASE(CalcExtMathTest, testCalcExtMathPowFails);
00069 
00070 
00071         //~ Programs used by more than one function -------------------------
00072         ostringstream pg;
00073 
00074         pg << "O d;" << endl;
00075         pg << "L d;" << endl;
00076         pg << "C %s, %s;" << endl;
00077         pg << "V %s, %s;" << endl;
00078         pg << "T;" << endl;
00079         pg << "CALL 'POW(L0, C0, C1);" << endl;
00080         pg << "REF O0, L0;" << endl;
00081 
00082         mProgramPower = pg.str();
00083     }
00084 
00085     virtual ~CalcExtMathTest()
00086     {
00087     }
00088 };
00089 
00090 // for nitty-gritty debugging. sadly, doesn't use BOOST_MESSAGE.
00091 void
00092 CalcExtMathTest::printOutput(
00093     TupleData const & tup,
00094     Calculator const & calc)
00095 {
00096 #if 0
00097     TuplePrinter tuplePrinter;
00098     tuplePrinter.print(cout, calc.getOutputRegisterDescriptor(), tup);
00099     cout << endl;
00100 #endif
00101 }
00102 
00103 
00104 void
00105 CalcExtMathTest::checkWarnings(Calculator& calc, string expected)
00106 {
00107     try {
00108         calc.exec();
00109     } catch (...) {
00110         BOOST_FAIL("An exception was thrown while running program");
00111     }
00112 
00113     int i = calc.warnings().find(expected);
00114 
00115     if (i < 0) {
00116         string msg = "Unexpected or no warning found\n";
00117         msg += "Expected: ";
00118         msg += expected;
00119         msg += "\nActual:  ";
00120         msg += calc.warnings();
00121 
00122         BOOST_FAIL(msg);
00123     }
00124 }
00125 
00126 void
00127 CalcExtMathTest::testCalcExtMathLogarithms()
00128 {
00129     ostringstream pg("");
00130 
00131     pg << "O d, d;" << endl;
00132     pg << "L d, d;" << endl;
00133     pg << "C d, d;" << endl;
00134     pg << "V 2.71828, 10.0;" << endl;
00135     pg << "T;" << endl;
00136     pg << "CALL 'LN(L0, C0);" << endl;
00137     pg << "CALL 'LOG10(L1, C1);" << endl;
00138     pg << "REF O0, L0;" << endl;
00139     pg << "REF O1, L1;" << endl;
00140 
00141     Calculator calc(0);
00142 
00143     try {
00144         calc.assemble(pg.str().c_str());
00145     } catch (FennelExcn& ex) {
00146         BOOST_FAIL("Assemble exception " << ex.getMessage()<< pg.str());
00147     }
00148 
00149     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00150     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00151 
00152     calc.bind(&inTuple, &outTuple);
00153     calc.exec();
00154     printOutput(outTuple, calc);
00155 
00156     for (int i = 0; i < 2; i++) {
00157         BOOST_CHECK(
00158             fabs(
00159                 *(reinterpret_cast<double*>
00160                   (const_cast<PBuffer>(outTuple[i].pData))) - 1.0)
00161             < 0.0001);
00162     }
00163 }
00164 
00165 
00166 void
00167 CalcExtMathTest::testCalcExtMathLogarithmsFails()
00168 {
00169     char buff[1024];
00170     const char* pg =
00171         "O d;\n"
00172         "L d;\n"
00173         "C %s;\n"
00174         "V %s;\n"
00175         "T;\n"
00176         "CALL '%s(L0, C0);\n"
00177         "REF O0, L0;\n";
00178 
00179     const char* tests[][3] = {
00180         { "LN", "s8", "0" },
00181         { "LN", "d", "0.0" },
00182         { "LN", "s8", "-1" },
00183         { "LN", "d", "-1.0" },
00184         { "LOG10", "s8", "0" },
00185         { "LOG10", "d", "0.0" },
00186         { "LOG10", "s8", "-1" },
00187         { "LOG10", "d", "-1.0" },
00188     };
00189 
00190     int n = sizeof(tests) / sizeof(tests[0]);
00191     for (int i = 0; i < n; i++) {
00192         Calculator calc(0);
00193         sprintf(buff, pg, tests[i][1], tests[i][2], tests[i][0]);
00194         try {
00195             calc.assemble(buff);
00196         } catch (FennelExcn& ex) {
00197             BOOST_FAIL("Assemble exception " << ex.getMessage() << ex.what());
00198         }
00199 
00200         TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00201         TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00202 
00203         calc.bind(&inTuple, &outTuple);
00204         checkWarnings(calc,"22023");
00205         if (!outTuple.containsNull()) {
00206             BOOST_FAIL("Result should be NULL");
00207         }
00208     }
00209 }
00210 
00211 void
00212 CalcExtMathTest::testCalcExtMathAbs()
00213 {
00214     ostringstream pg("");
00215 
00216     pg << "O d, d, d, s8, s8, s8;" << endl;
00217     pg << "L d, d, d, s8, s8, s8;" << endl;
00218     pg << "C d, d, d, s8, s8, s8;" << endl;
00219     // Pick a precision that fits in a double, but wouldn't fit in a float
00220     pg << "V 0.0, -1234567890123.0,  1234567890123.0,";;
00221     pg <<   "0, 9223372036854775807, -9223372036854775807;" << endl;
00222     pg << "T;" << endl;
00223     pg << "CALL 'ABS(L0, C0);" << endl;
00224     pg << "CALL 'ABS(L1, C1);" << endl;
00225     pg << "CALL 'ABS(L2, C2);" << endl;
00226     pg << "CALL 'ABS(L3, C3);" << endl;
00227     pg << "CALL 'ABS(L4, C4);" << endl;
00228     pg << "CALL 'ABS(L5, C5);" << endl;
00229     pg << "REF O0, L0;" << endl;
00230     pg << "REF O1, L1;" << endl;
00231     pg << "REF O2, L2;" << endl;
00232     pg << "REF O3, L3;" << endl;
00233     pg << "REF O4, L4;" << endl;
00234     pg << "REF O5, L5;" << endl;
00235 
00236     //BOOST_MESSAGE(pg.str());
00237 
00238     Calculator calc(0);
00239 
00240     try {
00241         calc.assemble(pg.str().c_str());
00242     } catch (FennelExcn& ex) {
00243         BOOST_FAIL("Assemble exception " << ex.getMessage() << pg.str());
00244     }
00245 
00246     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00247     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00248 
00249     calc.bind(&inTuple, &outTuple);
00250     calc.exec();
00251     printOutput(outTuple, calc);
00252 
00253 
00254     double epsilon = 0.000001;
00255 
00256     BOOST_CHECK(
00257         fabs(
00258             *(reinterpret_cast<double*>
00259               (const_cast<PBuffer>(outTuple[0].pData))) -
00260             0)
00261         < epsilon);
00262 
00263     BOOST_CHECK(
00264         fabs(
00265             *(reinterpret_cast<double*>
00266               (const_cast<PBuffer>(outTuple[1].pData))) -
00267             1234567890123.0)
00268         < epsilon);
00269 
00270     BOOST_CHECK(
00271         fabs(
00272             *(reinterpret_cast<double*>
00273               (const_cast<PBuffer>(outTuple[2].pData))) -
00274             1234567890123.0)
00275         < epsilon);
00276 
00277     BOOST_CHECK_EQUAL(
00278         *(reinterpret_cast<uint64_t*>
00279           (const_cast<PBuffer>(outTuple[3].pData))),0);
00280 
00281     BOOST_CHECK_EQUAL(
00282         *(reinterpret_cast<uint64_t*>(
00283             const_cast<PBuffer>(outTuple[4].pData))),
00284         9223372036854775807LL);
00285     BOOST_CHECK_EQUAL(
00286         *(reinterpret_cast<uint64_t*>(
00287             const_cast<PBuffer>(outTuple[5].pData))),
00288         9223372036854775807LL);
00289 }
00290 
00291 void
00292 CalcExtMathTest::testCalcExtMathPow()
00293 {
00294     char buff[1024];
00295 
00296 
00297     const char* tests[][4] = {
00298         { "d", "d", "2.0", "2.2" },
00299         { "d", "d", "2.0", "-2.2" },
00300         { "d", "d", "-2.0", "2.0" },
00301     };
00302 
00303     double results[] = { 4.5947934, 0.21763764, 4};
00304     int n = sizeof(results) / sizeof(results[0]);
00305     assert(n == (sizeof(tests) / sizeof(tests[0])));
00306     for (int i = 0; i < n; i++) {
00307         sprintf(
00308             buff, mProgramPower.c_str(),
00309             tests[i][0], tests[i][1], tests[i][2], tests[i][3]);
00310 
00311         Calculator calc(0);
00312         try {
00313             calc.assemble(buff);
00314         } catch (FennelExcn& ex) {
00315             BOOST_FAIL(
00316                 "Assemble exception " << ex.getMessage() << ex.what() << buff);
00317         }
00318 
00319         TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00320         TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00321 
00322         calc.bind(&inTuple, &outTuple);
00323         calc.exec();
00324         printOutput(outTuple, calc);
00325 
00326         BOOST_CHECK(
00327             fabs(
00328                 *(reinterpret_cast<double*>(
00329                     const_cast<PBuffer>(outTuple[0].pData))) - results[i])
00330             < 0.00001);
00331     }
00332 }
00333 
00334 void
00335 CalcExtMathTest::testCalcExtMathPowFails()
00336 {
00337     char buff[1024];
00338 
00339     const char* tests[][4] = {
00340         { "d", "d", "0.0", "-1.0" },
00341         { "d", "d", "-2.0", "2.2" },
00342         { "d", "d", "-2.0", "-2.2" },
00343     };
00344 
00345     int n = sizeof(tests) / sizeof(tests[0]);
00346     for (int i = 0; i < n; i++) {
00347         Calculator calc(0);
00348         sprintf(
00349             buff, mProgramPower.c_str(),
00350             tests[i][0], tests[i][1], tests[i][2], tests[i][3]);
00351 
00352         try {
00353             calc.assemble(buff);
00354         } catch (FennelExcn& ex) {
00355             BOOST_FAIL("Assemble exception " << ex.getMessage() << ex.what());
00356         }
00357 
00358         TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00359         TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00360 
00361         calc.bind(&inTuple, &outTuple);
00362         checkWarnings(calc,"22023");
00363         if (!outTuple.containsNull()) {
00364             BOOST_FAIL("Result should be NULL");
00365         }
00366     }
00367 }
00368 
00369 
00370 FENNEL_UNIT_TEST_SUITE(CalcExtMathTest);
00371 
00372 // End CalcExtMathTest.cpp

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