00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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
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