00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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/CalcAssembler.h"
00031 #include "fennel/calculator/StringToHex.h"
00032 #include "fennel/common/FennelExcn.h"
00033
00034 #include <boost/test/test_tools.hpp>
00035
00036 #include <fstream.h>
00037 #include <strstream.h>
00038 #include <iomanip.h>
00039
00040 using namespace fennel;
00041
00042 bool verbose = false;
00043 bool showProgram = true;
00044
00045
00046 #define USING_NOISY_ARITHMETIC (1)
00047
00048
00049 template <typename T>
00050 class RegisterTestInfo
00051 {
00052 public:
00053 enum ERegisterCheck {
00054 EINVALID = -1,
00055 ENULL = 0,
00056 EVALID = 1
00057 };
00058
00059 explicit
00060 RegisterTestInfo(string desc, TProgramCounter pc):
00061 mDesc(desc), mCheckValue(EINVALID), mPC(pc)
00062 {
00063 }
00064
00065 explicit
00066 RegisterTestInfo(string desc, T v, TProgramCounter pc):
00067 mDesc(desc), mValue(v), mCheckValue(EVALID), mPC(pc)
00068 {
00069 }
00070
00071 explicit
00072 RegisterTestInfo(string desc, T* pV, TProgramCounter pc):
00073 mDesc(desc), mPC(pc)
00074 {
00075 if (pV == NULL) {
00076 mCheckValue = ENULL;
00077 } else {
00078 mValue = *pV;
00079 mCheckValue = EVALID;
00080 }
00081 }
00082
00083 void setTupleDatum(TupleDatum& datum)
00084 {
00085 switch (mCheckValue) {
00086 case EINVALID:
00087
00088 break;
00089 case ENULL:
00090
00091 datum.pData = NULL;
00092 break;
00093 case EVALID:
00094 assert(datum.pData != NULL);
00095 (*reinterpret_cast<T*>(const_cast<PBuffer>(datum.pData))) = mValue;
00096 break;
00097 default:
00098 permAssert(false);
00099 }
00100 }
00101
00102 bool checkTupleDatum(TupleDatum& datum)
00103 {
00104 switch (mCheckValue) {
00105 case EINVALID:
00106
00107 return true;
00108 case ENULL:
00109
00110 return (datum.pData == NULL);
00111 case EVALID:
00112 if (datum.pData == NULL) {
00113 return false;
00114 }
00115 return (*reinterpret_cast<const T*>(datum.pData) == mValue);
00116 default:
00117 permAssert(false);
00118 }
00119 }
00120
00121 string toString()
00122 {
00123 ostringstream ostr("");
00124 switch (mCheckValue) {
00125 case EINVALID:
00126 break;
00127 case ENULL:
00128 ostr << "(NULL) for test ";
00129 break;
00130 case EVALID:
00131 ostr << "(" << mValue << ") for test ";
00132 break;
00133 default:
00134 permAssert(false);
00135 }
00136
00137 ostr << "'" << mDesc << "'" << " at PC=" << mPC;
00138 return ostr.str();
00139 }
00140
00141 ~RegisterTestInfo() {}
00142
00143
00144 string mDesc;
00145
00146
00147 T mValue;
00148
00149
00150 ERegisterCheck mCheckValue;
00151
00152
00153 TProgramCounter mPC;
00154 };
00155
00156 class CalcChecker
00157 {
00158 public:
00159 virtual ~CalcChecker() {}
00160 virtual bool checkResult(Calculator& calc, TupleData& output) = 0;
00161 };
00162
00163 template <typename T>
00164 class CalcTestInfo : public CalcChecker
00165 {
00166 public:
00167 explicit
00168 CalcTestInfo(StandardTypeDescriptorOrdinal type)
00169 : typeOrdinal(type) {}
00170 virtual ~CalcTestInfo() {}
00171
00172 void add(string desc, T* pV, TProgramCounter pc, uint line = 0)
00173 {
00174 if (line) {
00175 ostringstream ostr("");
00176 ostr << " Line: " << line;
00177 desc += ostr.str();
00178 }
00179 mOutRegInfo.push_back(RegisterTestInfo<T>(desc, pV, pc));
00180 }
00181
00182 void add(string desc, T v, TProgramCounter pc, uint line = 0)
00183 {
00184 if (line) {
00185 ostringstream ostr("");
00186 ostr << " Line: " << line;
00187 desc += ostr.str();
00188 }
00189 mOutRegInfo.push_back(RegisterTestInfo<T>(desc, v, pc));
00190 }
00191
00192 void addRegister(string desc, TProgramCounter pc)
00193 {
00194 mOutRegInfo.push_back(RegisterTestInfo<T>(desc, pc));
00195 }
00196
00197 void addWarning(const char* msg, TProgramCounter pc)
00198 {
00199 mWarnings.push_back(CalcMessage(msg, pc));
00200 }
00201
00202 void add(string desc, const char* error, TProgramCounter pc, uint line = 0)
00203 {
00204 if (line) {
00205 ostringstream ostr("");
00206 ostr << " Line: " << line;
00207 desc += ostr.str();
00208 }
00209 addRegister(desc, pc);
00210 if (error != NULL) {
00211 addWarning(error, pc);
00212 }
00213 }
00214
00215 void setTupleData(TupleData& tuple)
00216 {
00217 assert(tuple.size() == mOutRegInfo.size());
00218
00219
00220 for (uint i = 0; i < tuple.size(); i++) {
00221 mOutRegInfo[i].setTupleDatum(tuple[i]);
00222 }
00223 }
00224
00225 virtual bool checkResult(Calculator& calc, TupleData& outputTuple)
00226 {
00227 TupleDescriptor outputTupleDesc = calc.getOutputRegisterDescriptor();
00228
00229 assert(outputTupleDesc.size() == outputTuple.size());
00230
00231
00232 if (outputTupleDesc.size() != mOutRegInfo.size()) {
00233 ostringstream message("");
00234 message << "Mismatch of output register number: Expected ";
00235 message << outputTupleDesc.size();
00236 message << ", Actual " << mOutRegInfo.size();
00237 BOOST_ERROR(message.str());
00238 return false;
00239 }
00240
00241
00242 for (uint i = 0; i < outputTupleDesc.size(); i++) {
00243 if (outputTupleDesc[i].pTypeDescriptor->getOrdinal() !=
00244 static_cast<StoredTypeDescriptor::Ordinal>(typeOrdinal))
00245 {
00246 ostringstream message("");
00247 message << "Type ordinal mismatch: Expected ";
00248 message << outputTupleDesc[i].pTypeDescriptor->getOrdinal();
00249 message << ", Actual";
00250 message << static_cast<StoredTypeDescriptor::Ordinal>(
00251 typeOrdinal);
00252 BOOST_ERROR(message.str());
00253 return false;
00254 }
00255
00256 if (!mOutRegInfo[i].checkTupleDatum(outputTuple[i])) {
00257 ostringstream message("");
00258 message << "Tuple datum mismatch: Register " << i
00259 << " should be " << mOutRegInfo[i].toString()
00260 << ".";
00261 BOOST_ERROR(message.str());
00262 return false;
00263 }
00264 }
00265
00266
00267 if (calc.mWarnings.size() != mWarnings.size()) {
00268 ostringstream message("");
00269 message << "# of warnings should be " << mWarnings.size()
00270 << " not " << calc.mWarnings.size();
00271 BOOST_ERROR(message.str());
00272 return false;
00273 }
00274
00275 for (uint i = 0; i < mWarnings.size(); i++) {
00276 if (calc.mWarnings[i].pc != mWarnings[i].pc) {
00277 ostringstream message("");
00278 message << "Warning expected at PC=" << mWarnings[i].pc
00279 << ". Got warning at PC="
00280 << calc.mWarnings[i].pc;
00281 BOOST_ERROR(message.str());
00282 return false;
00283 }
00284
00285 if (strcmp(calc.mWarnings[i].str, mWarnings[i].str)) {
00286 ostringstream message("");
00287 message << "Message should be |" << mWarnings[i].str
00288 << "| not |" << calc.mWarnings[i].str << "| at PC="
00289 << mWarnings[i].pc ;
00290 BOOST_ERROR(message.str());
00291 return false;
00292 }
00293 }
00294
00295 return true;
00296 }
00297
00298 public:
00299
00300 vector< RegisterTestInfo<T> > mOutRegInfo;
00301
00302
00303 deque<CalcMessage> mWarnings;
00304
00305 StandardTypeDescriptorOrdinal typeOrdinal;
00306 };
00307
00308 class CalcAssemblerTestCase
00309 {
00310 public:
00311 static const uint MAX_WIDTH = 512;
00312
00313 explicit
00314 CalcAssemblerTestCase(uint line, const char* desc, const char* code)
00315 : mDescription(desc), mProgram(code), mAssemblerError(NULL),
00316 mInputTuple(NULL), mExpectedOutputTuple(NULL), mInputBuf(NULL),
00317 mExpOutputBuf(NULL), mFailed(false), mAssembled(false),
00318 mID(++testID), mLine(line), mCalc(0)
00319 {
00320 }
00321
00322 ~CalcAssemblerTestCase()
00323 {
00324 if (mInputTuple) {
00325 delete mInputTuple;
00326 }
00327 if (mExpectedOutputTuple) {
00328 delete mExpectedOutputTuple;
00329 }
00330 if (mInputBuf) {
00331 delete[] mInputBuf;
00332 }
00333 if (mExpOutputBuf) {
00334 delete[] mExpOutputBuf;
00335 }
00336 }
00337
00338 static uint getFailedNumber()
00339 {
00340 return nFailed;
00341 }
00342
00343 static uint getPassedNumber()
00344 {
00345 return nPassed;
00346 }
00347
00348 static uint getTestNumber()
00349 {
00350 return testID;
00351 }
00352
00353 void fail(const char *exp, const char* actual)
00354 {
00355 assert(exp);
00356 assert(actual);
00357 assert(mDescription);
00358 ostringstream message("");
00359 message << "test " << mID << " failed: | ";
00360 message << mDescription << " | Got \"" << actual << "\" | ";
00361 message << "Expected \"" << exp << "\" | line " << mLine;
00362 BOOST_ERROR(message.str());
00363 mFailed = true;
00364 nFailed++;
00365 }
00366
00367 void passed(const char *exp, const char* actual)
00368 {
00369 assert(exp);
00370 assert(actual);
00371 assert(mDescription);
00372 if (verbose) {
00373 ostringstream message("");
00374 message << "test " << mID << " passed: | ";
00375 message << mDescription << " | Got \"" << actual << "\" | ";
00376 message << "Expected \"" << exp << "\" | line " << mLine;
00377 BOOST_MESSAGE(message.str());
00378 }
00379 nPassed++;
00380 }
00381
00382 bool assemble()
00383 {
00384 assert(!mFailed && !mAssembled);
00385 assert(mProgram != NULL);
00386 try {
00387 mCalc.outputRegisterByReference(false);
00388 mCalc.assemble(mProgram);
00389
00390 TupleDescriptor inputTupleDesc = mCalc.getInputRegisterDescriptor();
00391 TupleDescriptor outputTupleDesc =
00392 mCalc.getOutputRegisterDescriptor();
00393
00394 mInputTuple = CalcAssembler::createTupleData(
00395 inputTupleDesc, &mInputBuf);
00396 mExpectedOutputTuple = CalcAssembler::createTupleData(
00397 outputTupleDesc, &mExpOutputBuf);
00398
00399
00400 mAssembled = true;
00401
00402 if (mAssemblerError) {
00403
00404
00405 string errorStr = "Error assembling program: ";
00406 errorStr += mAssemblerError;
00407 fail(errorStr.c_str(), "Program assembled.");
00408 }
00409 } catch (CalcAssemblerException& ex) {
00410 if (mAssemblerError) {
00411
00412
00413
00414
00415 if (ex.getMessage().find(mAssemblerError) == string::npos) {
00416
00417 fail(mAssemblerError, ex.getMessage().c_str());
00418 } else {
00419
00420 passed(mAssemblerError, ex.getMessage().c_str());
00421 }
00422 } else {
00423 string errorStr = "Error assembling program: ";
00424 errorStr += ex.getMessage();
00425 fail("Success assembling program", errorStr.c_str());
00426
00427 if (showProgram) {
00428
00429 ostringstream prog("");
00430 prog << "Program Code: " << endl;
00431 prog << ex.getCode() << endl;
00432 prog << "Program Snippet: " << endl;
00433 prog << ex.getCodeSnippet() << endl;
00434 BOOST_MESSAGE(prog.str());
00435 }
00436 }
00437 }
00438
00439
00440 return (mAssembled && !mFailed);
00441 }
00442
00443 static string tupleToString(
00444 TupleDescriptor const& tupleDesc,
00445 TupleData* tuple)
00446 {
00447 assert(tuple != NULL);
00448 ostringstream ostr("");
00449 TuplePrinter tuplePrinter;
00450 tuplePrinter.print(ostr, tupleDesc, *tuple);
00451 return ostr.str();
00452 }
00453
00454 bool test(CalcChecker* pChecker = NULL)
00455 {
00456 assert(mAssembled);
00457 bool res = true;
00458
00459 TupleDescriptor inputTupleDesc = mCalc.getInputRegisterDescriptor();
00460 TupleDescriptor outputTupleDesc = mCalc.getOutputRegisterDescriptor();
00461
00462 FixedBuffer* outputBuf;
00463 TupleData* outputTuple = CalcAssembler::createTupleData(
00464 outputTupleDesc, &outputBuf);
00465
00466 mCalc.bind(mInputTuple, outputTuple);
00467
00468 mCalc.exec();
00469
00470 string instr = tupleToString(inputTupleDesc, mInputTuple);
00471 string outstr = tupleToString(outputTupleDesc, outputTuple);
00472 string expoutstr = tupleToString(outputTupleDesc, mExpectedOutputTuple);
00473
00474 if (pChecker == NULL) {
00475
00476
00477 res = (expoutstr == outstr);
00478
00479
00480 if (!mCalc.mWarnings.empty()) {
00481 res = false;
00482 fail(expoutstr.c_str(), "Calculator warnings");
00483
00484
00485
00486
00487 }
00488 } else {
00489 res = pChecker->checkResult(mCalc, *outputTuple);
00490 }
00491
00492 if (res) {
00493
00494 string resStr = instr + " -> " + outstr;
00495 passed(expoutstr.c_str(), resStr.c_str());
00496 } else {
00497 string errorStr = "Calculator result: " ;
00498 errorStr += instr + " -> " + outstr;
00499 fail(expoutstr.c_str(), errorStr.c_str());
00500 }
00501
00502 delete outputTuple;
00503 delete[] outputBuf;
00504 return res;
00505 }
00506
00507 void expectAssemblerError(const char* err)
00508 {
00509 mAssemblerError = err;
00510 }
00511
00512 void writeMaxData(TupleDatum &datum, uint typeOrdinal);
00513 void writeMinData(TupleDatum &datum, uint typeOrdinal);
00514 string toLiteralString(TupleDatum &datum, uint typeOrdinal);
00515
00516 void setTupleDatumMax(TupleDatum& datum, TupleAttributeDescriptor& desc)
00517 {
00518 StoredTypeDescriptor::Ordinal type = desc.pTypeDescriptor->getOrdinal();
00519 writeMaxData(datum, type);
00520 }
00521
00522 void setTupleDatumMin(TupleDatum& datum, TupleAttributeDescriptor& desc)
00523 {
00524 StoredTypeDescriptor::Ordinal type = desc.pTypeDescriptor->getOrdinal();
00525 writeMinData(datum, type);
00526 }
00527
00528 void setTupleDatumNull(TupleDatum& datum)
00529 {
00530 datum.pData = NULL;
00531 }
00532
00533 template <typename T>
00534 void setTupleDatum(TupleDatum& datum, T value)
00535 {
00536 *(reinterpret_cast<T*>(const_cast<PBuffer>(datum.pData))) = value;
00537 }
00538
00539 template <typename T>
00540 void setTupleDatum(
00541 TupleDatum& datum,
00542 TupleAttributeDescriptor& desc,
00543 T* buf,
00544 uint buflen)
00545 {
00546 assert(buf != NULL);
00547 StoredTypeDescriptor::Ordinal type = desc.pTypeDescriptor->getOrdinal();
00548
00549 T* ptr = reinterpret_cast<T*>(const_cast<PBuffer>(datum.pData));
00550 switch (type) {
00551 case STANDARD_TYPE_CHAR:
00552 case STANDARD_TYPE_BINARY:
00553
00554 assert(buflen <= datum.cbData);
00555 memset((void*) ptr, 0, datum.cbData);
00556 memcpy((void*) ptr, buf, buflen);
00557 break;
00558
00559 case STANDARD_TYPE_VARCHAR:
00560 case STANDARD_TYPE_VARBINARY:
00561
00562 assert(buflen <= desc.cbStorage);
00563 memset((void*)ptr, 'I', desc.cbStorage);
00564 memcpy((void*)ptr, buf, buflen);
00565 datum.cbData = buflen;
00566 break;
00567
00568 default:
00569 permAssert(false);
00570 }
00571 }
00572
00573 void setInputMin(uint index)
00574 {
00575 assert(mInputTuple != NULL);
00576 assert(index < mInputTuple->size());
00577 TupleDescriptor inputTupleDesc = mCalc.getInputRegisterDescriptor();
00578 setTupleDatumMin((*mInputTuple)[index], inputTupleDesc[index]);
00579 }
00580
00581 void setInputMax(uint index)
00582 {
00583 assert(mInputTuple != NULL);
00584 assert(index < mInputTuple->size());
00585 TupleDescriptor inputTupleDesc = mCalc.getInputRegisterDescriptor();
00586 setTupleDatumMax((*mInputTuple)[index], inputTupleDesc[index]);
00587 }
00588
00589 void setInputNull(uint index)
00590 {
00591 assert(mInputTuple != NULL);
00592 assert(index < mInputTuple->size());
00593 setTupleDatumNull((*mInputTuple)[index]);
00594 }
00595
00596 template <typename T>
00597 void setInput(uint index, T value)
00598 {
00599 assert(mInputTuple != NULL);
00600 assert(index < mInputTuple->size());
00601 setTupleDatum((*mInputTuple)[index], value);
00602 }
00603
00604 template <typename T>
00605 void setInput(uint index, T* buf, uint buflen)
00606 {
00607 assert(mInputTuple != NULL);
00608 assert(index < mInputTuple->size());
00609 TupleDescriptor inputTupleDesc = mCalc.getInputRegisterDescriptor();
00610 setTupleDatum(
00611 (*mInputTuple)[index],
00612 inputTupleDesc[index],
00613 buf,
00614 buflen);
00615 }
00616
00617 string getInput(uint index)
00618 {
00619 assert(mInputTuple != NULL);
00620 assert(index < mInputTuple->size());
00621 TupleDescriptor inputTupleDesc = mCalc.getInputRegisterDescriptor();
00622 return toLiteralString(
00623 (*mInputTuple)[index],
00624 inputTupleDesc[index].pTypeDescriptor->getOrdinal());
00625 }
00626
00627 TupleData* getInputTuple()
00628 {
00629 return mInputTuple;
00630 }
00631
00632
00633 void setExpectedOutputNull(uint index)
00634 {
00635 assert(mExpectedOutputTuple != NULL);
00636 assert(index < mExpectedOutputTuple->size());
00637 setTupleDatumNull((*mExpectedOutputTuple)[index]);
00638 }
00639
00640 void setExpectedOutputMax(uint index)
00641 {
00642 assert(mExpectedOutputTuple != NULL);
00643 assert(index < mExpectedOutputTuple->size());
00644 TupleDescriptor outputTupleDesc = mCalc.getOutputRegisterDescriptor();
00645 setTupleDatumMax(
00646 (*mExpectedOutputTuple)[index],
00647 outputTupleDesc[index]);
00648 }
00649 void setExpectedOutputMin(uint index)
00650 {
00651 assert(mExpectedOutputTuple != NULL);
00652 assert(index < mExpectedOutputTuple->size());
00653 TupleDescriptor outputTupleDesc = mCalc.getOutputRegisterDescriptor();
00654 setTupleDatumMin(
00655 (*mExpectedOutputTuple)[index],
00656 outputTupleDesc[index]);
00657 }
00658
00659 template <typename T>
00660 void setExpectedOutput(uint index, T value)
00661 {
00662 assert(mExpectedOutputTuple != NULL);
00663 assert(index < mExpectedOutputTuple->size());
00664 setTupleDatum((*mExpectedOutputTuple)[index], value);
00665 }
00666
00667 template <typename T>
00668 void setExpectedOutput(uint index, T* buf, uint buflen)
00669 {
00670 assert(mExpectedOutputTuple != NULL);
00671 assert(index < mExpectedOutputTuple->size());
00672 TupleDescriptor outputTupleDesc = mCalc.getOutputRegisterDescriptor();
00673 setTupleDatum(
00674 (*mExpectedOutputTuple)[index],
00675 outputTupleDesc[index],
00676 buf,
00677 buflen);
00678 }
00679
00680 string getExpectedOutput(uint index)
00681 {
00682 assert(mExpectedOutputTuple != NULL);
00683 assert(index < mExpectedOutputTuple->size());
00684 TupleDescriptor outputTupleDesc = mCalc.getOutputRegisterDescriptor();
00685 return toLiteralString(
00686 (*mExpectedOutputTuple)[index],
00687 outputTupleDesc[index].pTypeDescriptor->getOrdinal());
00688 }
00689
00690 TupleData* getExpectedOutputTuple()
00691 {
00692 return mExpectedOutputTuple;
00693 }
00694
00695 bool failed()
00696 {
00697 return mFailed;
00698 }
00699
00700 protected:
00701 const char* mDescription;
00702 const char* mProgram;
00703 const char* mAssemblerError;
00704 TupleData* mInputTuple;
00705 TupleData* mExpectedOutputTuple;
00706 FixedBuffer* mInputBuf;
00707 FixedBuffer* mExpOutputBuf;
00708 bool mFailed;
00709 bool mAssembled;
00710 uint mID;
00711 uint mLine;
00712
00713 Calculator mCalc;
00714 static uint testID;
00715 static uint nFailed;
00716 static uint nPassed;
00717 };
00718
00719 uint CalcAssemblerTestCase::testID = 0;
00720 uint CalcAssemblerTestCase::nFailed = 0;
00721 uint CalcAssemblerTestCase::nPassed = 0;
00722
00723 class CalcAssemblerTest : virtual public TestBase, public TraceSource
00724 {
00725 protected:
00726 void testAdd();
00727
00728 void testBool();
00729 void testPointer();
00730 void testReturn();
00731 void testJump();
00732 void testExtended();
00733
00734 void testLiteralBinding();
00735
00736 void testInvalidPrograms();
00737 void testStandardTypes();
00738
00739 void testComments();
00740
00741 void testBoolInstructions(StandardTypeDescriptorOrdinal type);
00742
00743 template <typename T>
00744 void testNativeInstructions(StandardTypeDescriptorOrdinal type);
00745
00746 template <typename T>
00747 void testIntegralNativeInstructions(StandardTypeDescriptorOrdinal type);
00748
00749 string getTypeString(StandardTypeDescriptorOrdinal type, uint arraylen = 0);
00750 string createRegisterString(string s, uint n, char c = ',');
00751 void addBinaryInstructions(
00752 ostringstream& ostr,
00753 string opcode,
00754 uint& outreg,
00755 uint n);
00756
00757 void addUnaryInstructions(
00758 ostringstream& ostr,
00759 string opcode,
00760 uint& outreg,
00761 uint n);
00762
00763 public:
00764 explicit CalcAssemblerTest()
00765 : TraceSource(shared_from_this(),"CalcAssemblerTest")
00766 {
00767 srand(time(NULL));
00768 CalcInit::instance();
00769 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testLiteralBinding);
00770 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testBool);
00771 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testPointer);
00772 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testAdd);
00773 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testReturn);
00774 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testJump);
00775 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testExtended);
00776 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testComments);
00777
00778
00779 #ifndef __MSVC__
00780 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testInvalidPrograms);
00781 FENNEL_UNIT_TEST_CASE(CalcAssemblerTest, testStandardTypes);
00782 #endif
00783 }
00784
00785 virtual ~CalcAssemblerTest()
00786 {
00787 }
00788
00789 };
00790
00791
00792
00793
00794
00795 string CalcAssemblerTestCase::toLiteralString(
00796 TupleDatum &datum,
00797 uint typeOrdinal)
00798 {
00799
00800
00801
00802 ostringstream ostr("");
00803 if (datum.pData != NULL) {
00804 switch (typeOrdinal) {
00805 case STANDARD_TYPE_BOOL:
00806 if (*reinterpret_cast<const bool*>(datum.pData)) {
00807 ostr << "1";
00808 } else {
00809 ostr << "0";
00810 }
00811 break;
00812 case STANDARD_TYPE_INT_8:
00813 ostr << (int64_t) (*reinterpret_cast<const int8_t*>(datum.pData));
00814 break;
00815 case STANDARD_TYPE_UINT_8:
00816 ostr << (int64_t) (*reinterpret_cast<const uint8_t*>(datum.pData));
00817 break;
00818 case STANDARD_TYPE_INT_16:
00819 ostr << (int64_t) (*reinterpret_cast<const int16_t*>(datum.pData));
00820 break;
00821 case STANDARD_TYPE_UINT_16:
00822 ostr << (int64_t) (*reinterpret_cast<const uint16_t*>(datum.pData));
00823 break;
00824 case STANDARD_TYPE_INT_32:
00825 ostr << (int64_t) (*reinterpret_cast<const int32_t*>(datum.pData));
00826 break;
00827 case STANDARD_TYPE_UINT_32:
00828 ostr << (int64_t) (*reinterpret_cast<const uint32_t*>(datum.pData));
00829 break;
00830 case STANDARD_TYPE_INT_64:
00831 ostr << (*reinterpret_cast<const int64_t*>(datum.pData));
00832 break;
00833 case STANDARD_TYPE_UINT_64:
00834 ostr << (*reinterpret_cast<const uint64_t*>(datum.pData));
00835 break;
00836 case STANDARD_TYPE_REAL:
00837 ostr << (*reinterpret_cast<const float*>(datum.pData));
00838 break;
00839 case STANDARD_TYPE_DOUBLE:
00840 ostr << (*reinterpret_cast<const double*>(datum.pData));
00841 break;
00842 case STANDARD_TYPE_BINARY:
00843 case STANDARD_TYPE_CHAR:
00844 case STANDARD_TYPE_VARCHAR:
00845 case STANDARD_TYPE_VARBINARY:
00846 ostr << "0x";
00847 ostr << stringToHex(
00848 (reinterpret_cast<const char*>(datum.pData)),
00849 datum.cbData);
00850 break;
00851 default:
00852 permAssert(false);
00853 }
00854 }
00855 return ostr.str();
00856 }
00857
00858
00859 void CalcAssemblerTestCase::writeMaxData(TupleDatum &datum, uint typeOrdinal)
00860 {
00861 PBuffer pData = const_cast<PBuffer>(datum.pData);
00862 switch (typeOrdinal) {
00863 case STANDARD_TYPE_BOOL:
00864 *(reinterpret_cast<bool *>(pData)) = true;
00865 break;
00866 case STANDARD_TYPE_INT_8:
00867 *(reinterpret_cast<int8_t *>(pData)) =
00868 std::numeric_limits<int8_t>::max();
00869 break;
00870 case STANDARD_TYPE_UINT_8:
00871 *(reinterpret_cast<uint8_t *>(pData)) =
00872 std::numeric_limits<uint8_t>::max();
00873 break;
00874 case STANDARD_TYPE_INT_16:
00875 *(reinterpret_cast<int16_t *>(pData)) =
00876 std::numeric_limits<int16_t>::max();
00877 break;
00878 case STANDARD_TYPE_UINT_16:
00879 *(reinterpret_cast<uint16_t *>(pData)) =
00880 std::numeric_limits<uint16_t>::max();
00881 break;
00882 case STANDARD_TYPE_INT_32:
00883 *(reinterpret_cast<int32_t *>(pData)) =
00884 std::numeric_limits<int32_t>::max();
00885 break;
00886 case STANDARD_TYPE_UINT_32:
00887 *(reinterpret_cast<uint32_t *>(pData)) =
00888 std::numeric_limits<uint32_t>::max();
00889 break;
00890 case STANDARD_TYPE_INT_64:
00891 *(reinterpret_cast<int64_t *>(pData)) =
00892 std::numeric_limits<int64_t>::max();
00893 break;
00894 case STANDARD_TYPE_UINT_64:
00895 *(reinterpret_cast<uint64_t *>(pData)) =
00896 std::numeric_limits<uint64_t>::max();
00897 break;
00898 case STANDARD_TYPE_REAL:
00899 *(reinterpret_cast<float *>(pData)) =
00900 std::numeric_limits<float>::max();
00901 break;
00902 case STANDARD_TYPE_DOUBLE:
00903 *(reinterpret_cast<double *>(pData)) =
00904 std::numeric_limits<double>::max();
00905 break;
00906 case STANDARD_TYPE_BINARY:
00907 memset(pData,0xFF,datum.cbData);
00908 break;
00909 case STANDARD_TYPE_CHAR:
00910 memset(pData,'z',datum.cbData);
00911 break;
00912 case STANDARD_TYPE_VARCHAR:
00913 datum.cbData = MAX_WIDTH;
00914 memset(pData,'z',datum.cbData);
00915 break;
00916 case STANDARD_TYPE_VARBINARY:
00917 datum.cbData = MAX_WIDTH;
00918 memset(pData,0xFF,datum.cbData);
00919 break;
00920 default:
00921 permAssert(false);
00922 }
00923 }
00924
00925
00926 void CalcAssemblerTestCase::writeMinData(TupleDatum &datum,uint typeOrdinal)
00927 {
00928 PBuffer pData = const_cast<PBuffer>(datum.pData);
00929 switch (typeOrdinal) {
00930 case STANDARD_TYPE_BOOL:
00931 *(reinterpret_cast<bool *>(pData)) = false;
00932 break;
00933 case STANDARD_TYPE_INT_8:
00934 *(reinterpret_cast<int8_t *>(pData)) =
00935 std::numeric_limits<int8_t>::min();
00936 break;
00937 case STANDARD_TYPE_UINT_8:
00938 *(reinterpret_cast<uint8_t *>(pData)) =
00939 std::numeric_limits<uint8_t>::min();
00940 break;
00941 case STANDARD_TYPE_INT_16:
00942 *(reinterpret_cast<int16_t *>(pData)) =
00943 std::numeric_limits<int16_t>::min();
00944 break;
00945 case STANDARD_TYPE_UINT_16:
00946 *(reinterpret_cast<uint16_t *>(pData)) =
00947 std::numeric_limits<uint16_t>::min();
00948 break;
00949 case STANDARD_TYPE_INT_32:
00950 *(reinterpret_cast<int32_t *>(pData)) =
00951 std::numeric_limits<int32_t>::min();
00952 break;
00953 case STANDARD_TYPE_UINT_32:
00954 *(reinterpret_cast<uint32_t *>(pData)) =
00955 std::numeric_limits<uint32_t>::min();
00956 break;
00957 case STANDARD_TYPE_INT_64:
00958 *(reinterpret_cast<int64_t *>(pData)) =
00959 std::numeric_limits<int64_t>::min();
00960 break;
00961 case STANDARD_TYPE_UINT_64:
00962 *(reinterpret_cast<uint64_t *>(pData)) =
00963 std::numeric_limits<uint64_t>::min();
00964 break;
00965 case STANDARD_TYPE_REAL:
00966 *(reinterpret_cast<float *>(pData)) =
00967 std::numeric_limits<float>::min();
00968 break;
00969 case STANDARD_TYPE_DOUBLE:
00970 *(reinterpret_cast<double *>(pData)) =
00971 std::numeric_limits<double>::min();
00972 break;
00973 case STANDARD_TYPE_BINARY:
00974 memset(pData,0,datum.cbData);
00975 break;
00976 case STANDARD_TYPE_CHAR:
00977 memset(pData,'A',datum.cbData);
00978 break;
00979 case STANDARD_TYPE_VARCHAR:
00980 case STANDARD_TYPE_VARBINARY:
00981 datum.cbData = 0;
00982 break;
00983 default:
00984 permAssert(false);
00985 }
00986 }
00987
00988 string CalcAssemblerTest::getTypeString(
00989 StandardTypeDescriptorOrdinal type,
00990 uint arraylen)
00991 {
00992 string typestr = StandardTypeDescriptor::toString(type);
00993 if (StandardTypeDescriptor::isArray(type)) {
00994 ostringstream size("");
00995 size << "," << arraylen;
00996 typestr += size.str();
00997 }
00998 return typestr;
00999 }
01000
01001 string CalcAssemblerTest::createRegisterString(
01002 string s,
01003 uint n,
01004 char c)
01005 {
01006 ostringstream ostr("");
01007 for (uint i = 0; i < n; i++) {
01008 if (i > 0) {
01009 ostr << c;
01010 }
01011 ostr << s;
01012 }
01013 return ostr.str();
01014 }
01015
01016 void CalcAssemblerTest::addUnaryInstructions(
01017 ostringstream& ostr,
01018 string opcode,
01019 uint& outreg,
01020 uint n)
01021 {
01022 for (uint i = 0; i < n; i++) {
01023 ostr << opcode << " O" << outreg++ << ", I"
01024 << i << ";" << endl;
01025 }
01026 }
01027
01028 void CalcAssemblerTest::addBinaryInstructions(
01029 ostringstream& ostr,
01030 string opcode,
01031 uint& outreg,
01032 uint n)
01033 {
01034 for (uint i = 0; i < n; i++) {
01035 for (uint j = 0; j < n; j++) {
01036 ostr << opcode << " O" << outreg++ << ", I"
01037 << i << ", I" << j << ";" << endl;
01038 }
01039 }
01040 }
01041
01042 template <typename T>
01043 void CalcAssemblerTest::testIntegralNativeInstructions(
01044 StandardTypeDescriptorOrdinal type)
01045 {
01046 string typestr = getTypeString(type, CalcAssemblerTestCase::MAX_WIDTH);
01047 uint inregs = 4;
01048
01049
01050 ostringstream instostr("");
01051 uint outreg = 0;
01052 CalcTestInfo<T> expectedCalcOut(type);
01053 TProgramCounter pc = 0;
01054 T* pNULL = NULL;
01055 T zero = 0;
01056 T min = std::numeric_limits<T>::min();
01057 T max = std::numeric_limits<T>::max();
01058 T mid = 10;
01059
01060 const char* divbyzero = "22012";
01061
01062
01063 string modstr = string("MOD ") + typestr;
01064 addBinaryInstructions(instostr, "MOD", outreg, inregs);
01065 if (min != zero) {
01066 expectedCalcOut.add(
01067 modstr, (T) (min % min), pc++, __LINE__);
01068 } else {
01069 expectedCalcOut.add(
01070 modstr, divbyzero, pc++, __LINE__);
01071 }
01072 expectedCalcOut.add(
01073 modstr, (T) (min % max), pc++, __LINE__);
01074 expectedCalcOut.add(
01075 modstr, pNULL, pc++, __LINE__);
01076 expectedCalcOut.add(
01077 modstr, (T) (min % mid), pc++, __LINE__);
01078
01079 if (min != zero) {
01080 expectedCalcOut.add(
01081 modstr, (T) (max % min), pc++, __LINE__);
01082 } else {
01083 expectedCalcOut.add(
01084 modstr, divbyzero, pc++, __LINE__);
01085 }
01086 expectedCalcOut.add(
01087 modstr, (T) (max % max), pc++, __LINE__);
01088 expectedCalcOut.add(
01089 modstr, pNULL, pc++, __LINE__);
01090 expectedCalcOut.add(
01091 modstr, (T) (max % mid), pc++, __LINE__);
01092
01093 expectedCalcOut.add(
01094 modstr, pNULL, pc++, __LINE__);
01095 expectedCalcOut.add(
01096 modstr, pNULL, pc++, __LINE__);
01097 expectedCalcOut.add(
01098 modstr, pNULL, pc++, __LINE__);
01099 expectedCalcOut.add(
01100 modstr, pNULL, pc++, __LINE__);
01101
01102 if (min != zero) {
01103 expectedCalcOut.add(
01104 modstr, (T) (mid % min), pc++, __LINE__);
01105 } else {
01106 expectedCalcOut.add(
01107 modstr, divbyzero, pc++, __LINE__);
01108 }
01109 expectedCalcOut.add(
01110 modstr, (T) (mid % max), pc++, __LINE__);
01111 expectedCalcOut.add(
01112 modstr, pNULL, pc++, __LINE__);
01113 expectedCalcOut.add(
01114 modstr, (T) (mid % mid), pc++, __LINE__);
01115
01116
01117 string andstr = string("AND ") + typestr;
01118 addBinaryInstructions(instostr, "AND", outreg, inregs);
01119 expectedCalcOut.add(
01120 andstr, (T) (min&min), pc++, __LINE__);
01121 expectedCalcOut.add(
01122 andstr, (T) (min&max), pc++, __LINE__);
01123 expectedCalcOut.add(
01124 andstr, pNULL, pc++, __LINE__);
01125 expectedCalcOut.add(
01126 andstr, (T) (min&mid), pc++, __LINE__);
01127
01128 expectedCalcOut.add(
01129 andstr, (T) (max&min), pc++, __LINE__);
01130 expectedCalcOut.add(
01131 andstr, (T) (max&max), pc++, __LINE__);
01132 expectedCalcOut.add(
01133 andstr, pNULL, pc++, __LINE__);
01134 expectedCalcOut.add(
01135 andstr, (T) (max&mid), pc++, __LINE__);
01136
01137 expectedCalcOut.add(
01138 andstr, pNULL, pc++, __LINE__);
01139 expectedCalcOut.add(
01140 andstr, pNULL, pc++, __LINE__);
01141 expectedCalcOut.add(
01142 andstr, pNULL, pc++, __LINE__);
01143 expectedCalcOut.add(
01144 andstr, pNULL, pc++, __LINE__);
01145
01146 expectedCalcOut.add(
01147 andstr, (T) (mid&min), pc++, __LINE__);
01148 expectedCalcOut.add(
01149 andstr, (T) (mid&max), pc++, __LINE__);
01150 expectedCalcOut.add(
01151 andstr, pNULL, pc++, __LINE__);
01152 expectedCalcOut.add(
01153 andstr, (T) (mid&mid), pc++, __LINE__);
01154
01155
01156 string orstr = string("OR ") + typestr;
01157 addBinaryInstructions(instostr, "OR", outreg, inregs);
01158 expectedCalcOut.add(
01159 orstr, (T) (min | min), pc++, __LINE__);
01160 expectedCalcOut.add(
01161 orstr, (T) (min | max), pc++, __LINE__);
01162 expectedCalcOut.add(
01163 orstr, pNULL, pc++, __LINE__);
01164 expectedCalcOut.add(
01165 orstr, (T) (min | mid), pc++, __LINE__);
01166
01167 expectedCalcOut.add(
01168 orstr, (T) (max | min), pc++, __LINE__);
01169 expectedCalcOut.add(
01170 orstr, (T) (max | max), pc++, __LINE__);
01171 expectedCalcOut.add(
01172 orstr, pNULL, pc++, __LINE__);
01173 expectedCalcOut.add(
01174 orstr, (T) (max | mid), pc++, __LINE__);
01175
01176 expectedCalcOut.add(
01177 orstr, pNULL, pc++, __LINE__);
01178 expectedCalcOut.add(
01179 orstr, pNULL, pc++, __LINE__);
01180 expectedCalcOut.add(
01181 orstr, pNULL, pc++, __LINE__);
01182 expectedCalcOut.add(
01183 orstr, pNULL, pc++, __LINE__);
01184
01185 expectedCalcOut.add(
01186 orstr, (T) (mid | min), pc++, __LINE__);
01187 expectedCalcOut.add(
01188 orstr, (T) (mid | max), pc++, __LINE__);
01189 expectedCalcOut.add(
01190 orstr, pNULL, pc++, __LINE__);
01191 expectedCalcOut.add(
01192 orstr, (T) (mid | mid), pc++, __LINE__);
01193
01194
01195 string shflstr = string("SHFL ") + typestr;
01196 addBinaryInstructions(instostr, "SHFL", outreg, inregs);
01197 expectedCalcOut.add(
01198 shflstr, (T) (min<<min), pc++, __LINE__);
01199 expectedCalcOut.add(
01200 shflstr, (T) (min<<max), pc++, __LINE__);
01201 expectedCalcOut.add(
01202 shflstr, pNULL, pc++, __LINE__);
01203 expectedCalcOut.add(
01204 shflstr, (T) (min<<mid), pc++, __LINE__);
01205
01206 expectedCalcOut.add(
01207 shflstr, (T) (max<<min), pc++, __LINE__);
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 expectedCalcOut.addRegister(shflstr, pc++);
01219 expectedCalcOut.add(
01220 shflstr, pNULL, pc++, __LINE__);
01221 expectedCalcOut.add(
01222 shflstr, (T) (max<<mid), pc++, __LINE__);
01223
01224 expectedCalcOut.add(
01225 shflstr, pNULL, pc++, __LINE__);
01226 expectedCalcOut.add(
01227 shflstr, pNULL, pc++, __LINE__);
01228 expectedCalcOut.add(
01229 shflstr, pNULL, pc++, __LINE__);
01230 expectedCalcOut.add(
01231 shflstr, pNULL, pc++, __LINE__);
01232
01233 expectedCalcOut.add(
01234 shflstr, (T) (mid<<min), pc++, __LINE__);
01235 expectedCalcOut.add(
01236 shflstr, (T) (mid<<max), pc++, __LINE__);
01237 expectedCalcOut.add(
01238 shflstr, pNULL, pc++, __LINE__);
01239 expectedCalcOut.add(
01240 shflstr, (T) (mid<<mid), pc++, __LINE__);
01241
01242
01243 string shfrstr = string("SHFR ") + typestr;
01244 addBinaryInstructions(instostr, "SHFR", outreg, inregs);
01245 expectedCalcOut.add(
01246 shfrstr, (T) (min >> min), pc++, __LINE__);
01247 expectedCalcOut.add(
01248 shfrstr, (T) (min >> max), pc++, __LINE__);
01249 expectedCalcOut.add(
01250 shfrstr, pNULL, pc++, __LINE__);
01251 expectedCalcOut.add(
01252 shfrstr, (T) (min >> mid), pc++, __LINE__);
01253
01254 expectedCalcOut.add(
01255 shfrstr, (T) (max >> min), pc++, __LINE__);
01256
01257 expectedCalcOut.addRegister(shfrstr, pc++);
01258 expectedCalcOut.add(
01259 shfrstr, pNULL, pc++, __LINE__);
01260 expectedCalcOut.add(
01261 shfrstr, (T) (max >> mid), pc++, __LINE__);
01262
01263 expectedCalcOut.add(
01264 shfrstr, pNULL, pc++, __LINE__);
01265 expectedCalcOut.add(
01266 shfrstr, pNULL, pc++, __LINE__);
01267 expectedCalcOut.add(
01268 shfrstr, pNULL, pc++, __LINE__);
01269 expectedCalcOut.add(
01270 shfrstr, pNULL, pc++, __LINE__);
01271
01272 expectedCalcOut.add(
01273 shfrstr, (T) (mid >> min), pc++, __LINE__);
01274 expectedCalcOut.add(
01275 shfrstr, (T) (mid >> max), pc++, __LINE__);
01276 expectedCalcOut.add(
01277 shfrstr, pNULL, pc++, __LINE__);
01278 expectedCalcOut.add(
01279 shfrstr, (T) (mid >> mid), pc++, __LINE__);
01280
01281 assert(outreg == static_cast<uint>(pc));
01282
01283
01284 string testdesc = "testNativeInstructions: " + typestr;
01285 ostringstream testostr("");
01286
01287 testostr << "I " << createRegisterString(typestr, inregs) << ";" << endl;
01288 testostr << "O " << createRegisterString(typestr, outreg) << ";" << endl;
01289 testostr << "T;" << endl;
01290
01291 testostr << instostr.str();
01292
01293 string teststr = testostr.str();
01294
01295 CalcAssemblerTestCase testCase1(
01296 __LINE__, testdesc.c_str(),
01297 teststr.c_str());
01298 if (testCase1.assemble()) {
01299 testCase1.setInputMin(0);
01300 testCase1.setInputMax(1);
01301 testCase1.setInputNull(2);
01302 testCase1.template setInput<T>(3, mid);
01303 TupleData* outputTuple = testCase1.getExpectedOutputTuple();
01304 assert(outputTuple != NULL);
01305 expectedCalcOut.setTupleData(*outputTuple);
01306 testCase1.test(&expectedCalcOut);
01307 }
01308
01309 }
01310
01323 template <typename T>
01324 void CalcAssemblerTest::testNativeInstructions(
01325 StandardTypeDescriptorOrdinal type)
01326 {
01327 string typestr = getTypeString(type, CalcAssemblerTestCase::MAX_WIDTH);
01328 uint inregs = 4;
01329
01330
01331 ostringstream instostr("");
01332 uint outreg = 0;
01333 CalcTestInfo<T> expectedCalcOut(type);
01334 TProgramCounter pc = 0;
01335 T* pNULL = NULL;
01336 T zero = 0;
01337 T min = std::numeric_limits<T>::min();
01338 T max = std::numeric_limits<T>::max();
01339 T mid = 10;
01340
01341 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01342 const char *overflow = "22003";
01343 const char *underflow = "22000";
01344
01345 #endif
01346 const char *divbyzero = "22012";
01347
01348
01349 addBinaryInstructions(instostr, "ADD", outreg, inregs);
01350 string addstr = string("ADD ") + typestr;
01351 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01352 if (std::numeric_limits<T>::is_signed
01353 && std::numeric_limits<T>::is_integer)
01354 {
01355 expectedCalcOut.add(
01356 addstr, overflow, pc++, __LINE__);
01357 } else {
01358 expectedCalcOut.add(
01359 addstr, (T) (min + min), pc++, __LINE__);
01360 }
01361 #else
01362 expectedCalcOut.add(
01363 addstr, (T) (min + min), pc++, __LINE__);
01364 #endif
01365 expectedCalcOut.add(
01366 addstr, (T) (min + max), pc++, __LINE__);
01367 expectedCalcOut.add(
01368 addstr, pNULL, pc++, __LINE__);
01369 expectedCalcOut.add(
01370 addstr, (T) (min + mid), pc++, __LINE__);
01371
01372 expectedCalcOut.add(
01373 addstr, (T) (max + min), pc++, __LINE__);
01374 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01375 expectedCalcOut.add(
01376 addstr, overflow, pc++, __LINE__);
01377 #else
01378 expectedCalcOut.add(
01379 addstr, (T) (max + max), pc++, __LINE__);
01380 #endif
01381 expectedCalcOut.add(
01382 addstr, pNULL, pc++, __LINE__);
01383 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01384 if (std::numeric_limits<T>::is_integer) {
01385 expectedCalcOut.add(
01386 addstr, overflow, pc++, __LINE__);
01387 } else {
01388 expectedCalcOut.add(
01389 addstr, (T) (max + mid), pc++, __LINE__);
01390 }
01391 #else
01392 expectedCalcOut.add(
01393 addstr, (T) (max + mid), pc++, __LINE__);
01394 #endif
01395
01396
01397 expectedCalcOut.add(
01398 addstr, pNULL, pc++, __LINE__);
01399 expectedCalcOut.add(
01400 addstr, pNULL, pc++, __LINE__);
01401 expectedCalcOut.add(
01402 addstr, pNULL, pc++, __LINE__);
01403 expectedCalcOut.add(
01404 addstr, pNULL, pc++, __LINE__);
01405
01406 expectedCalcOut.add(
01407 addstr, (T) (mid + min), pc++, __LINE__);
01408 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01409 if (std::numeric_limits<T>::is_integer) {
01410 expectedCalcOut.add(
01411 addstr, overflow, pc++, __LINE__);
01412 } else {
01413 expectedCalcOut.add(
01414 addstr, (T) (mid + max), pc++, __LINE__);
01415 }
01416 #else
01417 expectedCalcOut.add(
01418 addstr, (T) (mid + max), pc++, __LINE__);
01419 #endif
01420 expectedCalcOut.add(
01421 addstr, pNULL, pc++, __LINE__);
01422 expectedCalcOut.add(
01423 addstr, (T) (mid + mid), pc++, __LINE__);
01424
01425
01426 addBinaryInstructions(instostr, "SUB", outreg, inregs);
01427 string substr = string("SUB ") + typestr;
01428 expectedCalcOut.add(
01429 substr, (T) (min - min), pc++, __LINE__);
01430 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01431 if (std::numeric_limits<T>::is_integer) {
01432 expectedCalcOut.add(
01433 substr, overflow, pc++, __LINE__);
01434 } else {
01435 expectedCalcOut.add(
01436 substr, (T) (min - max), pc++, __LINE__);
01437 }
01438 #else
01439 expectedCalcOut.add(
01440 substr, (T) (min - max), pc++, __LINE__);
01441 #endif
01442 expectedCalcOut.add(
01443 substr, pNULL, pc++, __LINE__);
01444 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01445 if (std::numeric_limits<T>::is_integer) {
01446 expectedCalcOut.add(
01447 substr, overflow, pc++, __LINE__);
01448 } else {
01449 expectedCalcOut.add(
01450 substr, (T) (min - mid), pc++, __LINE__);
01451 }
01452 #else
01453 expectedCalcOut.add(
01454 substr, (T) (min - mid), pc++, __LINE__);
01455 #endif
01456
01457 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01458 if (std::numeric_limits<T>::is_signed
01459 && std::numeric_limits<T>::is_integer)
01460 {
01461 expectedCalcOut.add(
01462 substr, overflow, pc++, __LINE__);
01463 } else {
01464 expectedCalcOut.add(
01465 substr, (T) (max - min), pc++, __LINE__);
01466 }
01467 #else
01468 expectedCalcOut.add(
01469 substr, (T) (max - min), pc++, __LINE__);
01470 #endif
01471 expectedCalcOut.add(
01472 substr, (T) (max - max), pc++, __LINE__);
01473 expectedCalcOut.add(
01474 substr, pNULL, pc++, __LINE__);
01475 expectedCalcOut.add(
01476 substr, (T) (max - mid), pc++, __LINE__);
01477
01478 expectedCalcOut.add(
01479 substr, pNULL, pc++, __LINE__);
01480 expectedCalcOut.add(
01481 substr, pNULL, pc++, __LINE__);
01482 expectedCalcOut.add(
01483 substr, pNULL, pc++, __LINE__);
01484 expectedCalcOut.add(
01485 substr, pNULL, pc++, __LINE__);
01486
01487 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01488 if (std::numeric_limits<T>::is_signed
01489 && std::numeric_limits<T>::is_integer)
01490 {
01491 expectedCalcOut.add(
01492 substr, overflow, pc++, __LINE__);
01493 } else {
01494 expectedCalcOut.add(
01495 substr, (T) (mid - min), pc++, __LINE__);
01496 }
01497 #else
01498 expectedCalcOut.add(
01499 substr, (T) (mid - min), pc++, __LINE__);
01500 #endif
01501 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01502 if (!std::numeric_limits<T>::is_signed) {
01503 expectedCalcOut.add(
01504 substr, overflow, pc++, __LINE__);
01505 } else {
01506 expectedCalcOut.add(
01507 substr, (T) (mid - max), pc++, __LINE__);
01508 }
01509 #else
01510 expectedCalcOut.add(
01511 substr, (T) (mid - max), pc++, __LINE__);
01512 #endif
01513 expectedCalcOut.add(
01514 substr, pNULL, pc++, __LINE__);
01515 expectedCalcOut.add(
01516 substr, (T) (mid - mid), pc++, __LINE__);
01517
01518
01519 addBinaryInstructions(instostr, "MUL", outreg, inregs);
01520 string mulstr = string("MUL ") + typestr;
01521 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01522 if (!std::numeric_limits<T>::is_signed) {
01523 expectedCalcOut.add(
01524 mulstr, (T) (min * min), pc++, __LINE__);
01525 } else if (std::numeric_limits<T>::is_integer) {
01526 expectedCalcOut.add(
01527 mulstr, overflow, pc++, __LINE__);
01528 } else {
01529 expectedCalcOut.add(
01530 mulstr, underflow, pc++, __LINE__);
01531 }
01532 #else
01533 expectedCalcOut.add(
01534 mulstr, (T) (min * min), pc++, __LINE__);
01535 #endif
01536 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01537 if (std::numeric_limits<T>::is_signed
01538 && std::numeric_limits<T>::is_integer)
01539 {
01540 expectedCalcOut.add(
01541 mulstr, overflow, pc++, __LINE__);
01542 } else {
01543 expectedCalcOut.add(
01544 mulstr, (T) (min * max), pc++, __LINE__);
01545 }
01546 #else
01547 expectedCalcOut.add(
01548 mulstr, (T) (min*max), pc++, __LINE__);
01549 #endif
01550 expectedCalcOut.add(
01551 mulstr, pNULL, pc++, __LINE__);
01552 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01553 if (std::numeric_limits<T>::is_signed
01554 && std::numeric_limits<T>::is_integer)
01555 {
01556 expectedCalcOut.add(
01557 mulstr, overflow, pc++, __LINE__);
01558 } else {
01559 expectedCalcOut.add(
01560 mulstr, (T) (min*mid), pc++, __LINE__);
01561 }
01562 #else
01563 expectedCalcOut.add(
01564 mulstr, (T) (min*mid), pc++, __LINE__);
01565 #endif
01566
01567 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01568 if (std::numeric_limits<T>::is_signed
01569 && std::numeric_limits<T>::is_integer)
01570 {
01571 expectedCalcOut.add(
01572 mulstr, overflow, pc++, __LINE__);
01573 } else {
01574 expectedCalcOut.add(
01575 mulstr, (T) (max * min), pc++, __LINE__);
01576 }
01577 #else
01578 expectedCalcOut.add(
01579 mulstr, (T) (max * min), pc++, __LINE__);
01580 #endif
01581 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01582 expectedCalcOut.add(
01583 mulstr, overflow, pc++, __LINE__);
01584 #else
01585 expectedCalcOut.add(
01586 mulstr, (T) (max*max), pc++, __LINE__);
01587 #endif
01588 expectedCalcOut.add(
01589 mulstr, pNULL, pc++, __LINE__);
01590 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01591 expectedCalcOut.add(
01592 mulstr, overflow, pc++, __LINE__);
01593 #else
01594 expectedCalcOut.add(
01595 mulstr, (T) (max*mid), pc++, __LINE__);
01596 #endif
01597
01598 expectedCalcOut.add(
01599 mulstr, pNULL, pc++, __LINE__);
01600 expectedCalcOut.add(
01601 mulstr, pNULL, pc++, __LINE__);
01602 expectedCalcOut.add(
01603 mulstr, pNULL, pc++, __LINE__);
01604 expectedCalcOut.add(
01605 mulstr, pNULL, pc++, __LINE__);
01606
01607 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01608 if (std::numeric_limits<T>::is_signed
01609 && std::numeric_limits<T>::is_integer)
01610 {
01611 expectedCalcOut.add(
01612 mulstr, overflow, pc++, __LINE__);
01613 } else {
01614 expectedCalcOut.add(
01615 mulstr, (T) (mid*min), pc++, __LINE__);
01616 }
01617 #else
01618 expectedCalcOut.add(
01619 mulstr, (T) (mid*min), pc++, __LINE__);
01620 #endif
01621 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01622 expectedCalcOut.add(
01623 mulstr, overflow, pc++, __LINE__);
01624 #else
01625 expectedCalcOut.add(
01626 mulstr, (T) (mid*max), pc++, __LINE__);
01627 #endif
01628 expectedCalcOut.add(
01629 mulstr, pNULL, pc++, __LINE__);
01630 expectedCalcOut.add(
01631 mulstr, (T) (mid*mid), pc++, __LINE__);
01632
01633
01634 addBinaryInstructions(instostr, "DIV", outreg, inregs);
01635 string divstr = string("DIV ") + typestr;
01636 if (min != zero) {
01637 expectedCalcOut.add(
01638 divstr, (T) (min / min), pc++, __LINE__);
01639 } else {
01640 expectedCalcOut.add(
01641 divstr, divbyzero, pc++, __LINE__);
01642 }
01643 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01644 if (std::numeric_limits<T>::is_integer) {
01645 expectedCalcOut.add(
01646 divstr, (T) (min / max), pc++, __LINE__);
01647 } else {
01648 expectedCalcOut.add(
01649 divstr, underflow, pc++, __LINE__);
01650 }
01651 #else
01652 expectedCalcOut.add(
01653 divstr, (T) (min / max), pc++, __LINE__);
01654 #endif
01655 expectedCalcOut.add(
01656 divstr, pNULL, pc++, __LINE__);
01657 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01658 if (std::numeric_limits<T>::is_integer) {
01659 expectedCalcOut.add(
01660 divstr, (T) (min / mid), pc++, __LINE__);
01661 } else {
01662 expectedCalcOut.add(
01663 divstr, underflow, pc++, __LINE__);
01664 }
01665 #else
01666 expectedCalcOut.add(
01667 divstr, (T) (min / mid), pc++, __LINE__);
01668 #endif
01669
01670 if (min != zero) {
01671 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01672 if (std::numeric_limits<T>::is_integer) {
01673 expectedCalcOut.add(
01674 divstr, (T) (max / min), pc++, __LINE__);
01675 } else {
01676 expectedCalcOut.add(
01677 divstr, overflow, pc++, __LINE__);
01678 }
01679 #else
01680 expectedCalcOut.add(
01681 divstr, (T) (max / min), pc++, __LINE__);
01682 #endif
01683 } else {
01684 expectedCalcOut.add(
01685 divstr, divbyzero, pc++, __LINE__);
01686 }
01687 expectedCalcOut.add(
01688 divstr, (T) (max / max), pc++, __LINE__);
01689 expectedCalcOut.add(
01690 divstr, pNULL, pc++, __LINE__);
01691 expectedCalcOut.add(
01692 divstr, (T) (max / mid), pc++, __LINE__);
01693
01694 expectedCalcOut.add(
01695 divstr, pNULL, pc++, __LINE__);
01696 expectedCalcOut.add(
01697 divstr, pNULL, pc++, __LINE__);
01698 expectedCalcOut.add(
01699 divstr, pNULL, pc++, __LINE__);
01700 expectedCalcOut.add(
01701 divstr, pNULL, pc++, __LINE__);
01702
01703 if (min != zero) {
01704 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01705 if (std::numeric_limits<T>::is_integer) {
01706 expectedCalcOut.add(
01707 divstr, (T) (mid / min), pc++);
01708 } else {
01709 expectedCalcOut.add(
01710 divstr, overflow, pc++, __LINE__);
01711 }
01712 #else
01713 expectedCalcOut.add(
01714 divstr, (T) (mid / min), pc++);
01715 #endif
01716 } else {
01717 expectedCalcOut.add(
01718 divstr, divbyzero, pc++);
01719 }
01720 expectedCalcOut.add(
01721 divstr, (T) (mid / max), pc++);
01722 expectedCalcOut.add(
01723 divstr, pNULL, pc++);
01724 expectedCalcOut.add(
01725 divstr, (T) (mid / mid), pc++);
01726
01727
01728 addUnaryInstructions(instostr, "NEG", outreg, inregs);
01729 string negstr = string("NEG ") + typestr;
01730 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01731 if (std::numeric_limits<T>::is_signed
01732 && std::numeric_limits<T>::is_integer)
01733 {
01734 expectedCalcOut.add(
01735 negstr, overflow, pc++, __LINE__);
01736 } else {
01737 expectedCalcOut.add(
01738 negstr, (T) (-min), pc++, __LINE__);
01739 }
01740 #else
01741 expectedCalcOut.add(
01742 negstr, (T) (-min), pc++, __LINE__);
01743 #endif
01744 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01745 if (!std::numeric_limits<T>::is_signed) {
01746 expectedCalcOut.add(
01747 negstr, overflow, pc++, __LINE__);
01748 } else {
01749 expectedCalcOut.add(
01750 negstr, (T) (-max), pc++, __LINE__);
01751 }
01752 #else
01753 expectedCalcOut.add(
01754 negstr, (T) (-max), pc++, __LINE__);
01755 #endif
01756 expectedCalcOut.add(
01757 negstr, pNULL, pc++, __LINE__);
01758 #if defined(USING_NOISY_ARITHMETIC) && USING_NOISY_ARITHMETIC
01759 if (std::numeric_limits<T>::is_signed) {
01760 expectedCalcOut.add(
01761 negstr, (T) (-mid), pc++, __LINE__);
01762 } else {
01763 expectedCalcOut.add(
01764 negstr, overflow, pc++, __LINE__);
01765 }
01766 #else
01767 expectedCalcOut.add(
01768 negstr, (T) (-mid), pc++, __LINE__);
01769 #endif
01770
01771 assert(outreg == static_cast<uint>(pc));
01772
01773
01774 string testdesc = "testNativeInstructions: " + typestr;
01775 ostringstream testostr("");
01776
01777 testostr << "I " << createRegisterString(typestr, inregs) << ";" << endl;
01778 testostr << "O " << createRegisterString(typestr, outreg) << ";" << endl;
01779 testostr << "T;" << endl;
01780
01781 testostr << instostr.str();
01782
01783 string teststr = testostr.str();
01784
01785 CalcAssemblerTestCase testCase1(
01786 __LINE__, testdesc.c_str(),
01787 teststr.c_str());
01788 if (testCase1.assemble()) {
01789 testCase1.setInputMin(0);
01790 testCase1.setInputMax(1);
01791 testCase1.setInputNull(2);
01792 testCase1.template setInput<T>(3, mid);
01793 TupleData* outputTuple = testCase1.getExpectedOutputTuple();
01794 assert(outputTuple != NULL);
01795 expectedCalcOut.setTupleData(*outputTuple);
01796 testCase1.test(&expectedCalcOut);
01797 }
01798 }
01799
01812 void CalcAssemblerTest::testBoolInstructions(StandardTypeDescriptorOrdinal type)
01813 {
01814 string typestr = getTypeString(type, CalcAssemblerTestCase::MAX_WIDTH);
01815 string boolstr = getTypeString(STANDARD_TYPE_BOOL);
01816 uint inregs = 3;
01817
01818
01819 ostringstream instostr("");
01820 uint outreg = 0;
01821 vector<bool*> boolout;
01822 bool bFalse = false;
01823 bool bTrue = true;
01824 bool* pFalse = &bFalse;
01825 bool* pTrue = &bTrue;
01826
01827
01828 instostr << "MOVE L0, I0;" << endl;
01829 instostr << "MOVE L1, I1;" << endl;
01830 instostr << "MOVE L2, I2;" << endl;
01831
01832
01833 addUnaryInstructions(instostr, "ISNULL", outreg, inregs);
01834 boolout.push_back(pFalse);
01835 boolout.push_back(pFalse);
01836 boolout.push_back(pTrue);
01837
01838
01839 addUnaryInstructions(instostr, "ISNOTNULL", outreg, inregs);
01840 boolout.push_back(pTrue);
01841 boolout.push_back(pTrue);
01842 boolout.push_back(pFalse);
01843
01844
01845
01846 instostr << "EQ O" << outreg++ <<", L0, I0;" << endl;
01847 boolout.push_back(pTrue);
01848 instostr << "EQ O" << outreg++ <<", L1, I1;" << endl;
01849 boolout.push_back(pTrue);
01850
01851
01852 addBinaryInstructions(instostr, "EQ", outreg, inregs);
01853 boolout.push_back(pTrue);
01854 boolout.push_back(pFalse);
01855 boolout.push_back(NULL);
01856 boolout.push_back(pFalse);
01857 boolout.push_back(pTrue);
01858 boolout.push_back(NULL);
01859 boolout.push_back(NULL);
01860 boolout.push_back(NULL);
01861 boolout.push_back(NULL);
01862
01863
01864
01865 instostr << "NE O" << outreg++ <<", L0, I0;" << endl;
01866 boolout.push_back(pFalse);
01867 instostr << "NE O" << outreg++ <<", L1, I1;" << endl;
01868 boolout.push_back(pFalse);
01869
01870
01871 addBinaryInstructions(instostr, "NE", outreg, inregs);
01872 boolout.push_back(pFalse);
01873 boolout.push_back(pTrue);
01874 boolout.push_back(NULL);
01875 boolout.push_back(pTrue);
01876 boolout.push_back(pFalse);
01877 boolout.push_back(NULL);
01878 boolout.push_back(NULL);
01879 boolout.push_back(NULL);
01880 boolout.push_back(NULL);
01881
01882
01883 addBinaryInstructions(instostr, "GT", outreg, inregs);
01884 boolout.push_back(pFalse);
01885 boolout.push_back(pFalse);
01886 boolout.push_back(NULL);
01887 boolout.push_back(pTrue);
01888 boolout.push_back(pFalse);
01889 boolout.push_back(NULL);
01890 boolout.push_back(NULL);
01891 boolout.push_back(NULL);
01892 boolout.push_back(NULL);
01893
01894
01895 addBinaryInstructions(instostr, "LT", outreg, inregs);
01896 boolout.push_back(pFalse);
01897 boolout.push_back(pTrue);
01898 boolout.push_back(NULL);
01899 boolout.push_back(pFalse);
01900 boolout.push_back(pFalse);
01901 boolout.push_back(NULL);
01902 boolout.push_back(NULL);
01903 boolout.push_back(NULL);
01904 boolout.push_back(NULL);
01905
01906 if (type == STANDARD_TYPE_BOOL) {
01907
01908 addUnaryInstructions(instostr, "NOT", outreg, inregs);
01909 boolout.push_back(pTrue);
01910 boolout.push_back(pFalse);
01911 boolout.push_back(NULL);
01912
01913
01914 addBinaryInstructions(instostr, "IS", outreg, inregs);
01915 boolout.push_back(pTrue);
01916 boolout.push_back(pFalse);
01917 boolout.push_back(pFalse);
01918 boolout.push_back(pFalse);
01919 boolout.push_back(pTrue);
01920 boolout.push_back(pFalse);
01921 boolout.push_back(pFalse);
01922 boolout.push_back(pFalse);
01923 boolout.push_back(pTrue);
01924
01925
01926 addBinaryInstructions(instostr, "ISNOT", outreg, inregs);
01927 boolout.push_back(pFalse);
01928 boolout.push_back(pTrue);
01929 boolout.push_back(pTrue);
01930 boolout.push_back(pTrue);
01931 boolout.push_back(pFalse);
01932 boolout.push_back(pTrue);
01933 boolout.push_back(pTrue);
01934 boolout.push_back(pTrue);
01935 boolout.push_back(pFalse);
01936
01937
01938 addBinaryInstructions(instostr, "AND", outreg, inregs);
01939 boolout.push_back(pFalse);
01940 boolout.push_back(pFalse);
01941 boolout.push_back(pFalse);
01942 boolout.push_back(pFalse);
01943 boolout.push_back(pTrue);
01944 boolout.push_back(NULL);
01945 boolout.push_back(pFalse);
01946 boolout.push_back(NULL);
01947 boolout.push_back(NULL);
01948
01949
01950 addBinaryInstructions(instostr, "OR", outreg, inregs);
01951 boolout.push_back(pFalse);
01952 boolout.push_back(pTrue);
01953 boolout.push_back(NULL);
01954 boolout.push_back(pTrue);
01955 boolout.push_back(pTrue);
01956 boolout.push_back(pTrue);
01957 boolout.push_back(NULL);
01958 boolout.push_back(pTrue);
01959 boolout.push_back(NULL);
01960 } else {
01961
01962 addBinaryInstructions(instostr, "GE", outreg, inregs);
01963 boolout.push_back(pTrue);
01964 boolout.push_back(pFalse);
01965 boolout.push_back(NULL);
01966 boolout.push_back(pTrue);
01967 boolout.push_back(pTrue);
01968 boolout.push_back(NULL);
01969 boolout.push_back(NULL);
01970 boolout.push_back(NULL);
01971 boolout.push_back(NULL);
01972
01973
01974 addBinaryInstructions(instostr, "LE", outreg, inregs);
01975 boolout.push_back(pTrue);
01976 boolout.push_back(pTrue);
01977 boolout.push_back(NULL);
01978 boolout.push_back(pFalse);
01979 boolout.push_back(pTrue);
01980 boolout.push_back(NULL);
01981 boolout.push_back(NULL);
01982 boolout.push_back(NULL);
01983 boolout.push_back(NULL);
01984 }
01985
01986 assert(outreg == boolout.size());
01987
01988
01989 string testdesc = "testBoolInstructions: " + typestr;
01990 ostringstream testostr("");
01991
01992 testostr << "I " << createRegisterString(typestr, inregs) << ";" << endl;
01993 testostr << "L " << createRegisterString(typestr, inregs) << ";" << endl;
01994 testostr << "O " << createRegisterString(boolstr, outreg) << ";" << endl;
01995 testostr << "T;" << endl;
01996
01997 testostr << instostr.str();
01998
01999 string teststr = testostr.str();
02000
02001 CalcAssemblerTestCase testCase1(
02002 __LINE__, testdesc.c_str(), teststr.c_str());
02003 if (testCase1.assemble()) {
02004 testCase1.setInputMin(0);
02005 testCase1.setInputMax(1);
02006 testCase1.setInputNull(2);
02007 for (uint i = 0; i < outreg; i++) {
02008 if (boolout[i]) {
02009 testCase1.setExpectedOutput<bool>(i, *boolout[i]);
02010 } else {
02011 testCase1.setExpectedOutputNull(i);
02012 }
02013 }
02014 testCase1.test();
02015 }
02016 }
02017
02018 void CalcAssemblerTest::testStandardTypes()
02019 {
02020 string max[STANDARD_TYPE_END_NO_UNICODE];
02021 string min[STANDARD_TYPE_END_NO_UNICODE];
02022 string overflow[STANDARD_TYPE_END_NO_UNICODE];
02023 string underflow[STANDARD_TYPE_END_NO_UNICODE];
02024
02025 min[STANDARD_TYPE_BOOL] = "0";
02026 max[STANDARD_TYPE_BOOL] = "1";
02027 underflow[STANDARD_TYPE_BOOL] = "-1";
02028 overflow[STANDARD_TYPE_BOOL] = "2";
02029
02030 min[STANDARD_TYPE_INT_8] = "-128";
02031 max[STANDARD_TYPE_INT_8] = "127";
02032 min[STANDARD_TYPE_UINT_8] = "0";
02033 max[STANDARD_TYPE_UINT_8] = "255";
02034
02035 underflow[STANDARD_TYPE_INT_8] = "-129";
02036 overflow[STANDARD_TYPE_INT_8] = "128";
02037 underflow[STANDARD_TYPE_UINT_8] = "-1";
02038 overflow[STANDARD_TYPE_UINT_8] = "256";
02039
02040 min[STANDARD_TYPE_INT_16] = "-32768";
02041 max[STANDARD_TYPE_INT_16] = "32767";
02042 min[STANDARD_TYPE_UINT_16] = "0";
02043 max[STANDARD_TYPE_UINT_16] = "65535";
02044
02045 underflow[STANDARD_TYPE_INT_16] = "-32769";
02046 overflow[STANDARD_TYPE_INT_16] = "32768";
02047 underflow[STANDARD_TYPE_UINT_16] = "-1";
02048 overflow[STANDARD_TYPE_UINT_16] = "65536";
02049
02050 min[STANDARD_TYPE_INT_32] = "-2147483648";
02051 max[STANDARD_TYPE_INT_32] = "2147483647";
02052 min[STANDARD_TYPE_UINT_32] = "0";
02053 max[STANDARD_TYPE_UINT_32] = "4294967295";
02054
02055 underflow[STANDARD_TYPE_INT_32] = "-2147483649";
02056 overflow[STANDARD_TYPE_INT_32] = "2147483648";
02057 underflow[STANDARD_TYPE_UINT_32] = "-1";
02058 overflow[STANDARD_TYPE_UINT_32] = "4294967296";
02059
02060 min[STANDARD_TYPE_INT_64] = "-9223372036854775808";
02061 max[STANDARD_TYPE_INT_64] = "9223372036854775807";
02062 min[STANDARD_TYPE_UINT_64] = "0";
02063 max[STANDARD_TYPE_UINT_64] = "18446744073709551615";
02064
02065 underflow[STANDARD_TYPE_INT_64] = "-9223372036854775809";
02066 overflow[STANDARD_TYPE_INT_64] = "9223372036854775808";
02067 underflow[STANDARD_TYPE_UINT_64] = "-1";
02068 overflow[STANDARD_TYPE_UINT_64] = "18446744073709551616";
02069
02070 min[STANDARD_TYPE_REAL] = "1.17549e-38";
02071 max[STANDARD_TYPE_REAL] = "3.40282e+38";
02072 min[STANDARD_TYPE_DOUBLE] = "2.22507e-308";
02073 max[STANDARD_TYPE_DOUBLE] = "1.79769e+308";
02074
02075
02076
02077 underflow[STANDARD_TYPE_REAL] = "1.17549e-46";
02078 overflow[STANDARD_TYPE_REAL] = "3.40282e+39";
02079 underflow[STANDARD_TYPE_DOUBLE] = "2.22507e-324";
02080 overflow[STANDARD_TYPE_DOUBLE] = "1.79769e+309";
02081
02082 for (uint i = STANDARD_TYPE_MIN; i < STANDARD_TYPE_END_NO_UNICODE; i++) {
02083
02084
02085
02086 StandardTypeDescriptorOrdinal type = StandardTypeDescriptorOrdinal(i);
02087 string typestr = getTypeString(type, CalcAssemblerTestCase::MAX_WIDTH);
02088 string testdesc = "testStandardTypes: " + typestr;
02089 ostringstream testostr("");
02090 testostr << "I " << createRegisterString(typestr, 3) << ";" << endl;
02091 testostr << "O " << createRegisterString(typestr, 4) << ";" << endl;
02092 testostr << "T;" << endl;
02093 testostr << "MOVE O0, I0;" << endl;
02094 testostr << "MOVE O1, I1;" << endl;
02095 testostr << "MOVE O2, I2;" << endl;
02096 testostr << "TONULL O3;" << endl;
02097 string teststr = testostr.str();
02098
02099 CalcAssemblerTestCase testCase1(
02100 __LINE__, testdesc.c_str(), teststr.c_str());
02101 if (testCase1.assemble()) {
02102 testCase1.setInputMin(0);
02103 testCase1.setExpectedOutputMin(0);
02104 testCase1.setInputMax(1);
02105 testCase1.setExpectedOutputMax(1);
02106 testCase1.setInputNull(2);
02107 testCase1.setExpectedOutputNull(2);
02108 testCase1.setExpectedOutputNull(3);
02109 testCase1.test();
02110 }
02111
02112 if (!StandardTypeDescriptor::isArray(type)) {
02113
02114 assert (testCase1.getInput(0) == min[type]);
02115 assert (testCase1.getInput(1) == max[type]);
02116 }
02117
02118
02119
02120 ostringstream testostr2("");
02121 testostr2 << "O " << createRegisterString(typestr, 3) << ";" << endl;
02122 testostr2 << "C " << createRegisterString(typestr, 3) << ";" << endl;
02123 testostr2 << "V " << testCase1.getInput(0)
02124 << ", " << testCase1.getInput(1)
02125 << ", " << testCase1.getInput(2)
02126 << ";" << endl;
02127 testostr2 << "T;" << endl;
02128 testostr2 << "MOVE O0, C0;" << endl;
02129 testostr2 << "MOVE O1, C1;" << endl;
02130 testostr2 << "MOVE O2, C2;" << endl;
02131 string teststr2 = testostr2.str();
02132
02133 CalcAssemblerTestCase testCase2(
02134 __LINE__, testdesc.c_str(), teststr2.c_str());
02135 if (testCase2.assemble()) {
02136 testCase2.setExpectedOutputMin(0);
02137 testCase2.setExpectedOutputMax(1);
02138 testCase2.setExpectedOutputNull(2);
02139 testCase2.test();
02140 }
02141
02142 if (!StandardTypeDescriptor::isArray(type)) {
02143
02144
02145 ostringstream testostr3("");
02146 testostr3 << "O " << createRegisterString(typestr, 1)
02147 << ";" << endl;
02148 testostr3 << "C " << createRegisterString(typestr, 1)
02149 << ";" << endl;
02150 testostr3 << "V " << underflow[type] << ";" << endl;
02151 testostr3 << "T;" << endl;
02152 testostr3 << "MOVE O0, C0;" << endl;
02153
02154 string teststr3 = testostr3.str();
02155
02156 CalcAssemblerTestCase testCase3(
02157 __LINE__, testdesc.c_str(), teststr3.c_str());
02158 if (type == STANDARD_TYPE_INT_64 || type == STANDARD_TYPE_DOUBLE) {
02159 testCase3.expectAssemblerError("out of");
02160 } else if (underflow[type] == "-1") {
02161 testCase3.expectAssemblerError("Invalid value");
02162 } else {
02163 testCase3.expectAssemblerError(
02164 "bad numeric");
02165 }
02166 testCase3.assemble();
02167
02168
02169 ostringstream testostr4("");
02170 testostr4 << "O " << createRegisterString(typestr, 1)
02171 << ";" << endl;
02172 testostr4 << "C " << createRegisterString(typestr, 1)
02173 << ";" << endl;
02174 testostr4 << "V " << overflow[type] << ";" << endl;
02175 testostr4 << "T;" << endl;
02176 testostr4 << "MOVE O0, C0;" << endl;
02177
02178 string teststr4 = testostr4.str();
02179
02180 CalcAssemblerTestCase testCase4(
02181 __LINE__, testdesc.c_str(),
02182 teststr4.c_str());
02183 if (type == STANDARD_TYPE_UINT_64 || type == STANDARD_TYPE_DOUBLE) {
02184 testCase4.expectAssemblerError("out of range");
02185 } else if (type == STANDARD_TYPE_BOOL) {
02186 testCase4.expectAssemblerError("Invalid value");
02187 } else {
02188 testCase4.expectAssemblerError(
02189 "bad numeric");
02190 }
02191 testCase4.assemble();
02192 }
02193
02194 testBoolInstructions(type);
02195
02196 switch (type) {
02197 case STANDARD_TYPE_UINT_8:
02198 testNativeInstructions<uint8_t>(type);
02199 testIntegralNativeInstructions<uint8_t>(type);
02200 break;
02201
02202 case STANDARD_TYPE_INT_8:
02203 testNativeInstructions<int8_t>(type);
02204 testIntegralNativeInstructions<int8_t>(type);
02205 break;
02206
02207 case STANDARD_TYPE_UINT_16:
02208 testNativeInstructions<uint16_t>(type);
02209 testIntegralNativeInstructions<uint16_t>(type);
02210 break;
02211
02212 case STANDARD_TYPE_INT_16:
02213 testNativeInstructions<int16_t>(type);
02214 testIntegralNativeInstructions<int16_t>(type);
02215 break;
02216
02217 case STANDARD_TYPE_UINT_32:
02218 testNativeInstructions<uint32_t>(type);
02219 testIntegralNativeInstructions<uint32_t>(type);
02220 break;
02221
02222 case STANDARD_TYPE_INT_32:
02223 testNativeInstructions<int32_t>(type);
02224 testIntegralNativeInstructions<int32_t>(type);
02225 break;
02226
02227 case STANDARD_TYPE_UINT_64:
02228 testNativeInstructions<uint64_t>(type);
02229 testIntegralNativeInstructions<uint64_t>(type);
02230 break;
02231
02232 case STANDARD_TYPE_INT_64:
02233 testNativeInstructions<int64_t>(type);
02234 testIntegralNativeInstructions<int64_t>(type);
02235 break;
02236
02237 case STANDARD_TYPE_REAL:
02238 testNativeInstructions<float>(type);
02239 break;
02240
02241 case STANDARD_TYPE_DOUBLE:
02242 testNativeInstructions<double>(type);
02243 break;
02244
02245 default:
02246 break;
02247 }
02248 }
02249 }
02250
02251 void CalcAssemblerTest::testLiteralBinding()
02252 {
02253
02254
02255 CalcAssemblerTestCase testCase1(
02256 __LINE__, "OVERFLOW U2",
02257 "O u2; C u2; V 777777; T; ADD O0, C0, C0;");
02258 testCase1.expectAssemblerError(
02259 "bad numeric conversion");
02260 testCase1.assemble();
02261
02262
02263 CalcAssemblerTestCase testCase2(
02264 __LINE__, "BADVALUE U2",
02265 "O u2; C u2; V 2451.342; T; ADD O0, C0, C0;");
02266 testCase2.expectAssemblerError("Invalid value");
02267 testCase2.assemble();
02268
02269
02270 CalcAssemblerTestCase testCase2b(
02271 __LINE__, "EXP",
02272 "O r, r; C r, r;\nV 24.0e-4, 54.0E6;\n"
02273 "T;\nMOVE O0, C0; MOVE O1, C1;");
02274 if (testCase2b.assemble()) {
02275 testCase2b.setExpectedOutput<float>(0, 0.0024);
02276 testCase2b.setExpectedOutput<float>(1, 54000000.0);
02277 testCase2b.test();
02278 }
02279
02280
02281 CalcAssemblerTestCase testCase3(
02282 __LINE__, "NEGVALUE U4",
02283 "O u4; C u4; V -513; T; ADD O0, C0, C0;");
02284 testCase3.expectAssemblerError("Invalid value");
02285 testCase3.assemble();
02286
02287
02288 CalcAssemblerTestCase testCase4(
02289 __LINE__, "NEGVALUE U4",
02290 "O s2; C s2; V 40000; T; ADD O0, C0, C0;");
02291 testCase4.expectAssemblerError(
02292 "bad numeric conversion");
02293 testCase4.assemble();
02294
02295
02296 CalcAssemblerTestCase testCase5(
02297 __LINE__, "BAD INDEX", "I s1; C s1; V 1, 2;");
02298 testCase5.expectAssemblerError("out of bounds");
02299 testCase5.assemble();
02300
02301 CalcAssemblerTestCase testCase6(
02302 __LINE__, "LREG/VAL MISMATCH", "I bo; C s1, s4; V 1;");
02303 testCase6.expectAssemblerError("Error binding literal");
02304 testCase6.assemble();
02305
02306
02307 CalcAssemblerTestCase testCase7(
02308 __LINE__, "LREG/VAL MISMATCH", "I s1, s4; V 1, 4; T; RETURN;");
02309 testCase7.expectAssemblerError("");
02310 testCase7.assemble();
02311
02312
02313 CalcAssemblerTestCase testCase8(__LINE__, "BOOL = 2", "I bo; C bo; V 2;");
02314 testCase8.expectAssemblerError("Invalid value");
02315 testCase8.assemble();
02316
02317
02318 string teststr9;
02319 teststr9 = "O c,4, u8; C c,4, u8; V 0x";
02320 teststr9 += stringToHex("test");
02321 teststr9 += ", 60000000; T; MOVE O0, C0; MOVE O1, C1;";
02322 CalcAssemblerTestCase testCase9(
02323 __LINE__, "STRING (CHAR) = \"test\"", teststr9.c_str());
02324 if (testCase9.assemble()) {
02325 testCase9.setExpectedOutput<const char>(0, "test", 4);
02326 testCase9.setExpectedOutput<uint64_t>(1, 60000000);
02327 testCase9.test();
02328 }
02329
02330
02331 string teststr10;
02332 teststr10 = "O vc,8; C vc,8; V 0x";
02333 teststr10 += stringToHex("short");
02334 teststr10 += "; T; MOVE O0, C0;";
02335 CalcAssemblerTestCase testCase10(
02336 __LINE__, "STRING (VARCHAR) = \"short\"", teststr10.c_str());
02337 if (testCase10.assemble()) {
02338 testCase10.setExpectedOutput<const char>(0, "short", 5);
02339 testCase10.test();
02340 }
02341
02342
02343 string teststr11;
02344 teststr11 = "O vc,8, u8; C vc,8, u8; V 0x";
02345 teststr11 += stringToHex("muchtoolongstring");
02346 teststr11 += "; T; MOVE O0, C0;";
02347
02348 CalcAssemblerTestCase testCase11(
02349 __LINE__, "STRING (VARCHAR) TOO LONG", teststr11.c_str());
02350 testCase11.expectAssemblerError("too long");
02351 testCase11.assemble();
02352
02353
02354 string teststr12;
02355 teststr12 = "O c,100, u8; C c,100, u8; V 0x";
02356 teststr12 += stringToHex("binarytooshort");
02357 teststr12 += ", 60000000; T; MOVE O0, C0; MOVE O1, C1;";
02358 CalcAssemblerTestCase testCase12(
02359 __LINE__, "STRING (BINARY) TOO SHORT", teststr12.c_str());
02360 testCase12.expectAssemblerError("not equal");
02361 testCase12.assemble();
02362
02363
02364 string teststr13;
02365 teststr13 = "O b,1, vb,1; C b,1, vb,1; V 0xFF,0xFF;";
02366 teststr13 += "T; MOVE O0, C0; MOVE O1, C1;";
02367 CalcAssemblerTestCase testCase13(
02368 __LINE__, "STRING (BINARY) 1", teststr13.c_str());
02369 if (testCase13.assemble()) {
02370 uint8_t tmp = 0xFF;
02371 testCase13.setExpectedOutput<uint8_t>(0, &tmp, 1);
02372 testCase13.setExpectedOutput<uint8_t>(1, &tmp, 1);
02373 testCase13.test();
02374 }
02375 }
02376
02377 void CalcAssemblerTest::testAdd()
02378 {
02379 CalcAssemblerTestCase testCase1(
02380 __LINE__, "ADD U4", "I u4, u4;\nO u4;\nT;\nADD O0, I0, I1;");
02381 if (testCase1.assemble()) {
02382 testCase1.setInput<uint32_t>(0, 100);
02383 testCase1.setInput<uint32_t>(1, 4030);
02384 testCase1.setExpectedOutput<uint32_t>(0, 4130);
02385 testCase1.test();
02386 }
02387
02388 CalcAssemblerTestCase testCase2(
02389 __LINE__, "ADD UNKNOWN INST",
02390 "I u2, u4;\nO u4;\nT;\nADD O0, I0, I1;");
02391 testCase2.expectAssemblerError("not a registered instruction");
02392 testCase2.assemble();
02393
02394 CalcAssemblerTestCase testCase3(
02395 __LINE__, "ADD O0 I0",
02396 "I u2, u4;\nO u4;\nT;\nADD O0, I0;");
02397 testCase3.expectAssemblerError("not a registered instruction");
02398 testCase3.assemble();
02399
02400 CalcAssemblerTestCase testCase4(__LINE__, "ADD FLOAT", "I r, r;\nO r, r;\n"
02401 "C r, r;\nV 0.3, -2.3;\n"
02402 "T;\nADD O0, I0, C0;\nADD O1, I1, C1;");
02403 if (testCase4.assemble()) {
02404 testCase4.setInput<float>(0, 200);
02405 testCase4.setInput<float>(1, 3000);
02406 testCase4.setExpectedOutput<float>(0, 200+0.3);
02407 testCase4.setExpectedOutput<float>(1, 3000-2.3);
02408 testCase4.test();
02409 }
02410 }
02411
02412 void CalcAssemblerTest::testBool()
02413 {
02414 CalcAssemblerTestCase testCase1(
02415 __LINE__, "AND 1 1",
02416 "O bo;\nC bo, bo;\nV 1, 1; T;\n"
02417 "AND O0, C0, C1;");
02418 if (testCase1.assemble()) {
02419 testCase1.setExpectedOutput<bool>(0, true);
02420 testCase1.test();
02421 }
02422
02423 CalcAssemblerTestCase testCase2(
02424 __LINE__, "EQ 1 0",
02425 "O bo;\nC bo, bo;\nV 1, 0; T;\n"
02426 "EQ O0, C0, C1;");
02427 if (testCase2.assemble()) {
02428 testCase2.setExpectedOutput<bool>(0, false);
02429 testCase2.test();
02430 }
02431 }
02432
02433 void CalcAssemblerTest::testPointer()
02434 {
02435 CalcAssemblerTestCase testCase1(
02436 __LINE__, "CHAR EQ",
02437 "I c,10, c,10;\nO bo, bo;\nT;\n"
02438 "EQ O0, I0, I1; EQ O1, I0, I0;");
02439 if (testCase1.assemble()) {
02440 testCase1.setInput<const char>(0, "test", 4);
02441 testCase1.setInput<const char>(1, "junk", 4);
02442 testCase1.setExpectedOutput<bool>(0, false);
02443 testCase1.setExpectedOutput<bool>(1, true);
02444 testCase1.test();
02445 }
02446
02447 CalcAssemblerTestCase testCase2(
02448 __LINE__, "VARCHAR EQ/ADD",
02449 "I vc,255, vc,255;\n"
02450 "O bo, bo, vc,255, u4;\nC u4; V 10;T;\n"
02451 "EQ O0, I0, I1; EQ O1, I0, I0; ADD O2, I0, C0; GETS O3, I0;");
02452 if (testCase2.assemble()) {
02453 testCase2.setInput<const char>(
02454 0, "test varchar equal and add ....", 31);
02455 testCase2.setInput<const char>(1, "junk", 4);
02456 testCase2.setExpectedOutput<bool>(0, false);
02457 testCase2.setExpectedOutput<bool>(1, true);
02458 testCase2.setExpectedOutput<const char>(2, "ar equal and add ....", 21);
02459 testCase2.setExpectedOutput<uint32_t>(3, 31);
02460 testCase2.test();
02461 }
02462 }
02463
02464 void CalcAssemblerTest::testJump()
02465 {
02466
02467 CalcAssemblerTestCase testCase1(
02468 __LINE__, "JUMP TRUE",
02469 "I u2, u2;\nO u2, u2;\nL bo;\n"
02470 "C u2, u2;\nV 0, 1;\nT;\n"
02471 "MOVE O0, C0;\nMOVE O1, C0;\n"
02472 "ADD O0, O0, I0;\nADD O1, O1, C1;\n"
02473 "LT L0, O1, I1;\nJMPT @2, L0;\n");
02474 if (testCase1.assemble()) {
02475 testCase1.setInput<uint16_t>(0, 3);
02476 testCase1.setInput<uint16_t>(1, 4);
02477 testCase1.setExpectedOutput<uint16_t>(0, 12);
02478 testCase1.setExpectedOutput<uint16_t>(1, 4);
02479 testCase1.test();
02480 }
02481
02482
02483 CalcAssemblerTestCase testCase2(
02484 __LINE__, "INVALID PC", "I u2; O u2; T; JMP @10;");
02485 testCase2.expectAssemblerError("Invalid PC");
02486 testCase2.assemble();
02487
02488
02489 CalcAssemblerTestCase testCase3(
02490 __LINE__, "VALID PC",
02491 "I u2; O u2;\n"
02492 "C bo; V 0; T;\n"
02493 "MOVE O0, I0;\n"
02494 "JMPF @4, C0;\n"
02495 "ADD O0, O0, I0;\n"
02496 "ADD O0, O0, I0;\n"
02497 "ADD O0, O0, I0;\n");
02498 if (testCase3.assemble()) {
02499 testCase3.setInput<uint16_t>(0, 15);
02500 testCase3.setExpectedOutput<uint16_t>(0, 30);
02501 testCase3.test();
02502 }
02503 }
02504
02505 void CalcAssemblerTest::testReturn()
02506 {
02507
02508 CalcAssemblerTestCase testCase1(
02509 __LINE__, "RETURN",
02510 "I u2;\nO u2;\n"
02511 "T;\n"
02512 "MOVE O0, I0;\n"
02513 "RETURN;\n"
02514 "ADD O0, I0, I0;\n");
02515 if (testCase1.assemble()) {
02516 testCase1.setInput<uint16_t>(0, 100);
02517 testCase1.setExpectedOutput<uint16_t>(0, 100);
02518 testCase1.test();
02519 }
02520 }
02521
02522 void convertFloatToInt(
02523 RegisterRef<int>* regOut,
02524 RegisterRef<float>* regIn)
02525 {
02526 regOut->value((int)regIn->value());
02527 }
02528
02529 void CalcAssemblerTest::testExtended()
02530 {
02531
02532 ExtendedInstructionTable* table =
02533 InstructionFactory::getExtendedInstructionTable();
02534 assert(table != NULL);
02535
02536 vector<StandardTypeDescriptorOrdinal> parameterTypes;
02537
02538
02539 parameterTypes.resize(2);
02540 parameterTypes[0] = STANDARD_TYPE_UINT_32;
02541 parameterTypes[1] = STANDARD_TYPE_REAL;
02542 table->add(
02543 "convert",
02544 parameterTypes,
02545 (ExtendedInstruction2<int32_t, float>*) NULL,
02546 &convertFloatToInt);
02547
02548
02549 CalcAssemblerTestCase testCase1(
02550 __LINE__, "CONVERT FLOAT TO INT",
02551 "I r; O u4;\n"
02552 "T;\n"
02553 "CALL 'convert(O0, I0);\n");
02554 if (testCase1.assemble()) {
02555 testCase1.setInput<float>(0, 53.34);
02556 testCase1.setExpectedOutput<uint32_t>(0, 53);
02557 testCase1.test();
02558 }
02559
02560 CalcAssemblerTestCase testCase2(
02561 __LINE__, "CONVERT INT TO FLOAT (NOT REGISTERED)",
02562 "I u4; O r;\n"
02563 "T;\n"
02564 "CALL 'convert(O0, I0);\n");
02565 testCase2.expectAssemblerError("not registered");
02566 testCase2.assemble();
02567 }
02568
02569 void CalcAssemblerTest::testInvalidPrograms()
02570 {
02571 const char* parse_error = "error";
02572
02573 CalcAssemblerTestCase testCase1(__LINE__, "JUNK", "Junk");
02574 testCase1.expectAssemblerError(parse_error);
02575 testCase1.assemble();
02576
02577
02578 CalcAssemblerTestCase testCase2(
02579 __LINE__, "UNKNOWN INST", "I u2, u4;\nO u4;\nT;\nBAD O0, I0;");
02580 testCase2.expectAssemblerError("not a registered instruction");
02581 testCase2.assemble();
02582
02583
02584 CalcAssemblerTestCase testCase3(
02585 __LINE__, "AND float", "I d, d;\nO d;\nT;\nAND O0, I0, I1;");
02586 testCase3.expectAssemblerError("not a registered instruction");
02587 testCase3.assemble();
02588
02589 CalcAssemblerTestCase testCase4(
02590 __LINE__, "BAD SIGNATURE",
02591 "I u2, u4;\nO u4;\nT;\nBAD O0, I0, I0, I1;");
02592 testCase4.expectAssemblerError(parse_error);
02593 testCase4.assemble();
02594
02595 CalcAssemblerTestCase testCase5(
02596 __LINE__, "BAD INST", "I u2, u4;\nO u4;\nT;\nklk34dfw;");
02597 testCase5.expectAssemblerError(parse_error);
02598 testCase5.assemble();
02599
02600
02601 CalcAssemblerTestCase testCase6(
02602 __LINE__, "BAD REG INDEX", "I u2, u4;\nO u4;\nT;\n\nADD O0, I0, I12;");
02603 testCase6.expectAssemblerError("out of bounds");
02604 testCase6.assemble();
02605
02606
02607 CalcAssemblerTestCase testCase7(
02608 __LINE__, "BAD REG INDEX",
02609 "I u2, u4;\nO u4;\nT;\n"
02610 "ADD O0, I0, I888888888888888888888888888888888888888888;");
02611 testCase7.expectAssemblerError("out of range");
02612 testCase7.assemble();
02613
02614
02615 }
02616
02617 void CalcAssemblerTest::testComments()
02618 {
02619 const char* parse_error = "error";
02620
02621 CalcAssemblerTestCase testCase1(
02622 __LINE__, "COMMENTS (ONE LINE)",
02623 "I u2;\nO /* comments */ u2;\n"
02624 "T;\n"
02625 "MOVE O0, I0;\n"
02626 "RETURN;\n"
02627 "ADD O0, I0, I0;\n");
02628 if (testCase1.assemble()) {
02629 testCase1.setInput<uint16_t>(0, 100);
02630 testCase1.setExpectedOutput<uint16_t>(0, 100);
02631 testCase1.test();
02632 }
02633
02634 CalcAssemblerTestCase testCase2(
02635 __LINE__, "COMMENTS (MULTILINE)",
02636 "I u2;\nO u2; /* *****\n*****/\n"
02637 "T;\n"
02638 "MOVE O0, I0;\n"
02639 "RETURN;\n"
02640 "ADD O0, I0, I0;\n");
02641 if (testCase2.assemble()) {
02642 testCase2.setInput<uint16_t>(0, 100);
02643 testCase2.setExpectedOutput<uint16_t>(0, 100);
02644 testCase2.test();
02645 }
02646
02647 CalcAssemblerTestCase testCase3(
02648 __LINE__, "COMMENTS (MULTIPLE)",
02649 "I u2;\nO u2;\n"
02650 "T;\n"
02651 "MOVE O0, /* /* MOVE\n****\nO0 */ I0;\n"
02652 "RETURN;\n"
02653 "ADD /* FOR '0x' */ O0, I0, I0;\n");
02654 if (testCase3.assemble()) {
02655 testCase3.setInput<uint16_t>(0, 100);
02656 testCase3.setExpectedOutput<uint16_t>(0, 100);
02657 testCase3.test();
02658 }
02659
02660 CalcAssemblerTestCase testCase4(
02661 __LINE__, "UNCLOSED COMMENT",
02662 "I u2;\nO u2;\n"
02663 "T;\n"
02664 "MOVE O0, /* I0;\n"
02665 "RETURN;\n"
02666 "ADD O0, I0, I0;\n");
02667 testCase4.expectAssemblerError("Unterminated comment");
02668 testCase4.assemble();
02669
02670 CalcAssemblerTestCase testCase5(
02671 __LINE__, "CLOSE COMMENT ONLY",
02672 "I u2;\nO u2;\n"
02673 "T;\n"
02674 "MOVE O0, */ I0;\n"
02675 "RETURN;\n"
02676 "ADD O0, I0, I0;\n");
02677
02678
02679
02680 testCase5.expectAssemblerError(parse_error);
02681 testCase5.assemble();
02682 }
02683
02684 #if 0
02685 int main (int argc, char **argv)
02686 {
02687 ProgramName = argv[0];
02688 InstructionFactory inst();
02689 InstructionFactory::registerInstructions();
02690
02691 try {
02692 CalcAssemblerTest test;
02693 test.testAssembler();
02694 } catch (exception& ex) {
02695 cerr << ex.what() << endl;
02696 }
02697
02698 cout << CalcAssemblerTestCase::getPassedNumber() << "/"
02699 << CalcAssemblerTestCase::getTestNumber() << " tests passed" << endl;
02700 return CalcAssemblerTestCase::getFailedNumber();
02701 }
02702
02703 #endif
02704 FENNEL_UNIT_TEST_SUITE(CalcAssemblerTest);
02705
02706