SqlStringTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calctest/SqlStringTest.cpp#2 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "fennel/common/CommonPreamble.h"
00024 #include "fennel/test/TestBase.h"
00025 #include "fennel/calculator/SqlString.h"
00026 #include "fennel/common/TraceSource.h"
00027 #include "fennel/calctest/SqlStringBuffer.h"
00028 
00029 #include <boost/test/test_tools.hpp>
00030 #include <boost/scoped_array.hpp>
00031 #include <string>
00032 #include <limits>
00033 #include <iostream>
00034 #include <math.h>
00035 
00036 #ifdef HAVE_ICU
00037 #include <unicode/unistr.h>
00038 #include <unicode/uloc.h>
00039 #endif
00040 
00041 using namespace fennel;
00042 using namespace std;
00043 
00044 #ifdef COMPLETE_REGRESSION_TEST_SETTINGS
00045 // full regression settings
00046 const int MAXLEN = 8;   // Must not be less than 5. Best >=7.
00047 const int MAXRANDOM = 5;  // 5-8 offers good coverage
00048 const int MAXCMPRANDOM = 65536; // Must be nearly 2^16 char set coverage
00049 const int MAXCMPLEN = 8;  // Must not be less than 3.
00050 #else
00051 // faster check-in acceptance testing settings
00052 const int MAXLEN = 5;   // Must not be less than 5. Best >=7.
00053 const int MAXRANDOM = 1;
00054 const int MAXCMPRANDOM = 256; // Must be nearly 2^16 char set coverage
00055 const int MAXCMPLEN = 3;  // Must not be less than 3.
00056 #endif
00057 
00058 class SqlStringTest : virtual public TestBase, public TraceSource
00059 {
00060     void testSqlStringBuffer_Ascii();
00061     void testSqlStringBuffer_UCS2();
00062 
00063     void testSqlStringCat_Fix();
00064     void testSqlStringCat_Var();
00065     void testSqlStringCat_Var2();
00066     void testSqlStringCpy_Fix();
00067     void testSqlStringCpy_Var();
00068     void testSqlStringCmp();
00069     void testSqlStringCmp_Bin();
00070     void testSqlStringLenBit();
00071     void testSqlStringLenChar();
00072     void testSqlStringLenOct();
00073     void testSqlStringOverlay();
00074     void testSqlStringPos();
00075     void testSqlStringSubStr();
00076     void testSqlStringAlterCase();
00077     void testSqlStringTrim();
00078     void testSqlStringCastToExact();
00079     void testSqlStringCastToDecimal();
00080     void testSqlStringCastToApprox();
00081     void testSqlStringCastFromExact();
00082     void testSqlStringCastFromDecimal();
00083     void testSqlStringCastFromApprox();
00084     void testSqlStringCastToVarChar();
00085     void testSqlStringCastToChar();
00086 
00087     void appendCharsToUCS2LikeString(
00088         string& str,
00089         int number,
00090         char character);
00091 
00092     void testSqlStringCmp_Helper(
00093         SqlStringBuffer &src1,
00094         int src1_storage,
00095         int src1_len,
00096         SqlStringBuffer &src2,
00097         int src2_storage,
00098         int src2_len);
00099 
00100     void testSqlStringCmp_Bin_Helper(
00101         SqlStringBuffer &src1,
00102         int src1_storage,
00103         int src1_len,
00104         SqlStringBuffer &src2,
00105         int src2_storage,
00106         int src2_len);
00107 
00108     void testSqlStringCmp_Bin_Helper2(
00109         int &lower,
00110         int &upper);
00111 
00112     int testSqlStringNormalizeLexicalCmp(int v);
00113 
00114     void testSqlStringAlterCase_Ascii(
00115         int dst_storage,
00116         int src_len,
00117         SqlStringBuffer& dest,
00118         SqlStringBuffer& src,
00119         const string& expect,
00120         SqlStrAlterCaseAction action);
00121 
00122     void testSqlStringAlterCase_UCS2(
00123         int dst_storage,
00124         int src_len,
00125         SqlStringBufferUCS2& destU2,
00126         SqlStringBufferUCS2& srcU2,
00127         const string& expect,
00128         SqlStrAlterCaseAction action);
00129 
00130     void testSqlStringAlterCase_Case(
00131         SqlStrAlterCaseAction action,
00132         int dst_storage,
00133         int dest_len,
00134         int src_storage,
00135         int src_len);
00136 
00137     void testSqlStringTrim_Helper(
00138         int dst_storage,
00139         int src_storage,
00140         int src_len,
00141         int leftpad,
00142         int rightpad,
00143         int action);
00144 
00145     void testSqlStringCastToExact_Helper(
00146         uint64_t value,
00147         char const * const buf,
00148         int src_storage,
00149         int src_len,
00150         bool exceptionExpected);
00151 
00152     void testSqlStringCastToDecimal_Helper(
00153         uint64_t value,
00154         int precision,
00155         int scale,
00156         char const * const buf,
00157         int src_storage,
00158         int src_len,
00159         bool outOfRangeExpected,
00160         bool invalidCharExpected);
00161 
00162     void testSqlStringCastToApprox_Helper(
00163         double value,
00164         char const * const buf,
00165         int src_storage,
00166         int src_len,
00167         bool exceptionExpected);
00168 #ifdef HAVE_ICU
00169     string UnicodeToPrintable(const UnicodeString &s);
00170 #endif
00171 
00172 
00173 public:
00174     explicit SqlStringTest()
00175         : TraceSource(shared_from_this(),"SqlStringTest")
00176     {
00177         srand(time(NULL));
00178         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringBuffer_Ascii);
00179         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringBuffer_UCS2);
00180         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCat_Fix);
00181         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCat_Var2);
00182         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCat_Var);
00183         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCpy_Fix);
00184         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCpy_Var);
00185         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCmp);
00186         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCmp_Bin);
00187         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringLenBit);
00188         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringLenChar);
00189         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringLenOct);
00190         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringOverlay);
00191         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringPos);
00192         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringSubStr);
00193         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringAlterCase);
00194         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringTrim);
00195         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastToExact);
00196         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastToDecimal);
00197         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastToApprox);
00198         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastFromExact);
00199         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastFromDecimal);
00200         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastFromApprox);
00201         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastToVarChar);
00202         FENNEL_UNIT_TEST_CASE(SqlStringTest, testSqlStringCastToChar);
00203     }
00204 
00205     virtual ~SqlStringTest()
00206     {
00207     }
00208 };
00209 
00210 #ifdef HAVE_ICU
00211 // Note: Assumes that only ASCII chars are represented
00212 string
00213 SqlStringTest::UnicodeToPrintable(const UnicodeString &s) {
00214     ostringstream o;
00215     int32_t i, length;
00216     char tmp;
00217 
00218     // output the code units (not code points)
00219     length = s.length();
00220     for (i = 0; i < length; ++i) {
00221         tmp = s.charAt(i) & 0xff;
00222         o << i << "=" << tmp << " | ";
00223     }
00224     return o.str();
00225 }
00226 #endif
00227 
00228 // build these strings by hand, not using ICU, so we're also
00229 // testing that ICU is integrated and working correctly.
00230 void
00231 SqlStringTest::appendCharsToUCS2LikeString(
00232     string& str,
00233     int number,
00234     char character)
00235 {
00236     int i;
00237     for (i = 0; i < number; i++) {
00238 #ifdef LITTLEENDIAN
00239         str.push_back(character);
00240         str.push_back(0);
00241 #else
00242         str.push_back(0);
00243         str.push_back(character);
00244 #endif
00245     }
00246 }
00247 
00248 
00249 void
00250 SqlStringTest::testSqlStringBuffer_Ascii()
00251 {
00252     int storage, size, leftpad, rightpad;
00253     int leftbump = 2;
00254     int rightbump = 2;
00255     int k;
00256 
00257     for (storage = 0; storage <= 5; storage++) {
00258         for (size = 0; size <= storage; size++) {
00259             for (leftpad = 0; leftpad <= storage - size; leftpad++) {
00260                 rightpad = (storage - size) - leftpad;
00261 
00262                 SqlStringBuffer t(
00263                     storage, size,
00264                     leftpad, rightpad,
00265                     'x', ' ',
00266                     leftbump, rightbump);
00267 
00268                 BOOST_CHECK_EQUAL(t.mStorage, storage);
00269                 BOOST_CHECK_EQUAL(t.mSize, size);
00270                 BOOST_CHECK_EQUAL(t.mLeftPad, leftpad);
00271                 BOOST_CHECK_EQUAL(t.mRightPad, rightpad);
00272                 BOOST_CHECK_EQUAL(
00273                     static_cast<int>(t.mS.size()),
00274                     storage + leftbump + rightbump);
00275 
00276                 BOOST_CHECK(t.verify());
00277 
00278                 char *p = t.mLeftP;
00279                 // left bumper
00280                 for (k = 0; k < leftbump; k++) {
00281                     BOOST_CHECK_EQUAL(*(p++), SqlStringBuffer::mBumperChar);
00282                 }
00283                 BOOST_CHECK(p == t.mStr);
00284                 // left padding
00285                 for (k = 0; k < leftpad; k++) {
00286                     BOOST_CHECK_EQUAL(*(p++), ' ');
00287                 }
00288                 // text
00289                 for (k = 0; k < size; k++) {
00290                     BOOST_CHECK_EQUAL(*(p++), 'x');
00291                 }
00292                 // right padding
00293                 for (k = 0; k < rightpad; k++) {
00294                     BOOST_CHECK_EQUAL(*(p++), ' ');
00295                 }
00296                 BOOST_CHECK(p == t.mRightP);
00297                 // right bumper
00298                 for (k = 0; k < rightbump; k++) {
00299                     BOOST_CHECK_EQUAL(*(p++), SqlStringBuffer::mBumperChar);
00300                 }
00301                 BOOST_CHECK_EQUAL(
00302                     static_cast<int>(p - t.mLeftP),
00303                     storage + leftbump + rightbump);
00304 
00305                 BOOST_CHECK(t.verify());
00306 
00307                 for (k = 0; k < size; k++) {
00308                     *(t.mStr + k) = '0' + (k % 10);
00309                 }
00310                 BOOST_CHECK(t.verify());
00311 
00312                 *(t.mLeftP) = 'X';
00313                 BOOST_CHECK(!t.verify());
00314                 *(t.mLeftP) = SqlStringBuffer::mBumperChar;
00315                 BOOST_CHECK(t.verify());
00316 
00317                 *(t.mStr - 1) = 'X';
00318                 BOOST_CHECK(!t.verify());
00319                 *(t.mStr - 1) = SqlStringBuffer::mBumperChar;
00320                 BOOST_CHECK(t.verify());
00321 
00322                 *(t.mRightP) = 'X';
00323                 BOOST_CHECK(!t.verify());
00324                 *(t.mRightP) = SqlStringBuffer::mBumperChar;
00325                 BOOST_CHECK(t.verify());
00326 
00327                 *(t.mRightP + t.mRightBump - 1) = 'X';
00328                 BOOST_CHECK(!t.verify());
00329                 *(t.mRightP + t.mRightBump - 1) = SqlStringBuffer::mBumperChar;
00330                 BOOST_CHECK(t.verify());
00331 
00332                 t.randomize();
00333                 BOOST_CHECK(t.verify());
00334             }
00335         }
00336     }
00337 }
00338 
00339 void
00340 SqlStringTest::testSqlStringBuffer_UCS2()
00341 {
00342     int storage, size, leftpad, rightpad;
00343     int leftbump = 2;
00344     int rightbump = 2;
00345     int k;
00346 
00347     int textChar = 'x';
00348     int spaceChar = ' ';
00349     char textChar1, textChar2, spaceChar1, spaceChar2;
00350 #ifdef LITTLEENDIAN
00351     textChar2 = (textChar >> 8) & 0xff;
00352     textChar1 = textChar & 0xff;
00353     spaceChar2 = (spaceChar >> 8) & 0xff;
00354     spaceChar1 = spaceChar & 0xff;
00355 #elif BIGENDIAN
00356     textChar1 = (textChar >> 8) & 0xff;
00357     textChar2 = textChar & 0xff;
00358     spaceChar1 = (spaceChar >> 8) & 0xff;
00359     spaceChar2 = spaceChar & 0xff;
00360 #else
00361 #error "unknown endian"
00362 #endif
00363 
00364     for (storage = 0; storage <= 5; storage++) {
00365         for (size = 0; size <= storage; size++) {
00366             for (leftpad = 0; leftpad <= storage - size; leftpad++) {
00367                 rightpad = (storage - size) - leftpad;
00368 
00369                 SqlStringBuffer a(
00370                     storage, size,
00371                     leftpad, rightpad,
00372                     textChar, spaceChar,
00373                     leftbump, rightbump);
00374                 SqlStringBufferUCS2 b(a);
00375 
00376                 BOOST_CHECK_EQUAL(b.mStorage, storage * 2);
00377                 BOOST_CHECK_EQUAL(b.mSize, size * 2);
00378                 BOOST_CHECK_EQUAL(b.mLeftPad, leftpad * 2);
00379                 BOOST_CHECK_EQUAL(b.mRightPad, rightpad * 2);
00380                 BOOST_CHECK_EQUAL(
00381                     static_cast<int>(b.mS.size()),
00382                     (storage*2)+leftbump+rightbump);
00383 
00384                 BOOST_CHECK(a.verify());
00385                 BOOST_CHECK(b.verify());
00386 
00387                 char *p = b.mLeftP;
00388                 // left bumper
00389                 for (k = 0; k < leftbump; k++) {
00390                     BOOST_CHECK_EQUAL(*(p++), SqlStringBuffer::mBumperChar);
00391                 }
00392                 BOOST_CHECK(p == b.mStr);
00393                 // left padding
00394                 for (k = 0; k < leftpad; k++) {
00395                     BOOST_CHECK_EQUAL(*(p++), spaceChar1);
00396                     BOOST_CHECK_EQUAL(*(p++), spaceChar2);
00397                 }
00398                 // text
00399                 for (k = 0; k < size; k++) {
00400                     BOOST_CHECK_EQUAL(*(p++), textChar1);
00401                     BOOST_CHECK_EQUAL(*(p++), textChar2);
00402                 }
00403                 // right padding
00404                 for (k = 0; k < rightpad; k++) {
00405                     BOOST_CHECK_EQUAL(*(p++), spaceChar1);
00406                     BOOST_CHECK_EQUAL(*(p++), spaceChar2);
00407                 }
00408                 BOOST_CHECK(p == b.mRightP);
00409                 // right bumper
00410                 for (k = 0; k < rightbump; k++) {
00411                     BOOST_CHECK_EQUAL(*(p++), SqlStringBuffer::mBumperChar);
00412                 }
00413                 BOOST_CHECK_EQUAL(
00414                     static_cast<int>(p - b.mLeftP),
00415                     storage*2+leftbump+rightbump);
00416 
00417                 BOOST_CHECK(b.verify());
00418 
00419                 p = b.mStr;
00420                 for (k = 0; k < size; k++) {
00421                     *(p++) = 0x00;
00422                     *(p++) = '0' + (k % 10);
00423                 }
00424                 BOOST_CHECK(b.verify());
00425 
00426                 b.randomize();
00427                 BOOST_CHECK(b.verify());
00428             }
00429         }
00430     }
00431 }
00432 
00433 // Test catting 3 fixed width strings together as proof-of-concept
00434 void
00435 SqlStringTest::testSqlStringCat_Fix()
00436 {
00437     int src1_storage, src2_storage, src3_storage, dst_storage;
00438     int src1_len, src2_len, src3_len;
00439     bool caught;
00440     int newlen;
00441 
00442     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
00443         for (src1_storage = 0; src1_storage < MAXLEN; src1_storage++) {
00444             for (src1_len = 0; src1_len <= src1_storage; src1_len++) {
00445                 for (src2_storage = 0; src2_storage < MAXLEN; src2_storage++) {
00446                     for (src2_len = 0; src2_len <= src2_storage; src2_len++) {
00447                         for (src3_storage = 0; src3_storage < MAXLEN;
00448                              src3_storage++)
00449                         {
00450                             for (src3_len = 0; src3_len <= src3_storage;
00451                                  src3_len++)
00452                             {
00453                                 SqlStringBuffer dst(
00454                                     dst_storage, 0,
00455                                     0, dst_storage,
00456                                     'd', ' ');
00457                                 SqlStringBuffer src1(
00458                                     src1_storage, src1_len,
00459                                     0, src1_storage - src1_len,
00460                                     '1', ' ');
00461                                 SqlStringBuffer src2(
00462                                     src2_storage, src2_len,
00463                                     0, src2_storage - src2_len,
00464                                     '2', ' ');
00465                                 SqlStringBuffer src3(
00466                                     src3_storage, src3_len,
00467                                     0, src3_storage - src3_len,
00468                                     '3', ' ');
00469 
00470                                 caught = false;
00471                                 try {
00472                                     newlen = SqlStrCat(
00473                                         dst.mStr, dst_storage,
00474                                         src1.mStr, src1_storage,
00475                                         src2.mStr, src2_storage);
00476                                 } catch (const char *str) {
00477                                     caught = true;
00478                                     BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00479                                     BOOST_CHECK(
00480                                         src1_storage + src2_storage
00481                                         > dst_storage);
00482                                     BOOST_CHECK(dst.verify());
00483                                     BOOST_CHECK(src1.verify());
00484                                     BOOST_CHECK(src2.verify());
00485                                 } catch (...) {
00486                                     // unexpected exception
00487                                     BOOST_CHECK(false);
00488                                 }
00489                                 if (!caught) {
00490                                     BOOST_CHECK(
00491                                         src1_storage + src2_storage
00492                                         <= dst_storage);
00493                                     BOOST_CHECK(dst.verify());
00494                                     BOOST_CHECK(src1.verify());
00495                                     BOOST_CHECK(src2.verify());
00496 
00497                                     caught = false;
00498                                     try {
00499                                         newlen = SqlStrCat(
00500                                             dst.mStr,
00501                                             dst_storage,
00502                                             newlen,
00503                                             src3.mStr,
00504                                             src3_storage);
00505                                     } catch (const char *str) {
00506                                         caught = true;
00507                                         BOOST_CHECK_EQUAL(
00508                                             strcmp(str, "22001"), 0);
00509                                         BOOST_CHECK(
00510                                             (src1_storage +
00511                                              src2_storage +
00512                                              src3_storage)
00513                                             > dst_storage);
00514                                         BOOST_CHECK(dst.verify());
00515                                         BOOST_CHECK(src1.verify());
00516                                         BOOST_CHECK(src2.verify());
00517                                         BOOST_CHECK(src3.verify());
00518                                     } catch (...) {
00519                                         // unexpected exception
00520                                         BOOST_CHECK(false);
00521                                     }
00522                                     if (!caught) {
00523                                         BOOST_CHECK(dst.verify());
00524                                         BOOST_CHECK(src1.verify());
00525                                         BOOST_CHECK(src2.verify());
00526                                         BOOST_CHECK(src3.verify());
00527                                         BOOST_CHECK_EQUAL(
00528                                             newlen,
00529                                             (src1_storage +
00530                                              src2_storage +
00531                                              src3_storage));
00532 
00533                                         string result(dst.mStr, newlen);
00534                                         string expect(src1.mStr, src1_storage);
00535                                         expect.append(src2.mStr, src2_storage);
00536                                         expect.append(src3.mStr, src3_storage);
00537 
00538                                         BOOST_CHECK(!result.compare(expect));
00539                                     }
00540                                 }
00541                             }
00542                         }
00543                     }
00544                 }
00545             }
00546         }
00547     }
00548 
00549 }
00550 
00551 
00552 void
00553 SqlStringTest::testSqlStringCat_Var2()
00554 {
00555     int src1_storage, src2_storage, dst_storage, src1_len, src2_len;
00556     int newlen;
00557     bool caught;
00558 
00559     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
00560         for (src1_storage = 0; src1_storage < MAXLEN; src1_storage++) {
00561             for (src1_len = 0; src1_len <= src1_storage; src1_len++) {
00562                 for (src2_storage = 0; src2_storage < MAXLEN; src2_storage++) {
00563                     for (src2_len = 0; src2_len <= src2_storage; src2_len++) {
00564                         SqlStringBuffer dst(
00565                             dst_storage, 0,
00566                             0, dst_storage,
00567                             'd', ' ');
00568                         SqlStringBuffer src1(
00569                             src1_storage, src1_len,
00570                             0, src1_storage - src1_len,
00571                             's', ' ');
00572                         SqlStringBuffer src2(
00573                             src2_storage, src2_len,
00574                             0, src2_storage - src2_len,
00575                             'S', ' ');
00576 
00577                         caught = false;
00578                         try {
00579                             newlen = SqlStrCat(
00580                             dst.mStr,
00581                             dst_storage,
00582                             src1.mStr,
00583                             src1_len,
00584                             src2.mStr,
00585                             src2_len);
00586                         } catch (const char *str) {
00587                             caught = true;
00588                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00589                             BOOST_CHECK(src1_len + src2_len > dst_storage);
00590                         } catch (...) {
00591                             // unexpected exception
00592                             BOOST_CHECK(false);
00593                         }
00594                         if (!caught) {
00595                             BOOST_CHECK(src1_len + src2_len <= dst_storage);
00596                             BOOST_CHECK_EQUAL(newlen, src1_len + src2_len);
00597 
00598                             string expect;
00599                             expect.append(src1_len, 's');
00600                             expect.append(src2_len, 'S');
00601 
00602                             string result(dst.mStr, newlen);
00603 
00604                             BOOST_CHECK(!result.compare(expect));
00605                             BOOST_CHECK(!expect.compare(result));
00606                         }
00607                         BOOST_CHECK(dst.verify());
00608                         BOOST_CHECK(src1.verify());
00609                         BOOST_CHECK(src2.verify());
00610                     }
00611                 }
00612             }
00613         }
00614     }
00615 }
00616 
00617 
00618 void
00619 SqlStringTest::testSqlStringCat_Var()
00620 {
00621     int src_storage, dst_storage, src_len, dst_len;
00622     int newlen;
00623     bool caught;
00624 
00625     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
00626         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
00627             for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
00628                 for (src_len = 0; src_len <= src_storage; src_len++) {
00629                     SqlStringBuffer dst(
00630                         dst_storage, dst_len,
00631                         0, dst_storage - dst_len,
00632                         'd', ' ');
00633                     SqlStringBuffer src(
00634                         src_storage, src_len,
00635                         0, src_storage - src_len,
00636                         's', ' ');
00637                     caught = false;
00638                     try {
00639                         newlen = SqlStrCat(
00640                             dst.mStr,
00641                             dst_storage,
00642                             dst_len,
00643                             src.mStr,
00644                             src_len);
00645                     } catch (const char *str) {
00646                         caught = true;
00647                         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00648                         BOOST_CHECK(src_len + dst_len > dst_storage);
00649                     } catch (...) {
00650                         // unexpected exception
00651                         BOOST_CHECK(false);
00652                     }
00653                     if (!caught) {
00654                         BOOST_CHECK(src_len + dst_len <= dst_storage);
00655                         BOOST_CHECK_EQUAL(newlen, src_len + dst_len);
00656 
00657                         string expect;
00658                         expect.append(dst_len, 'd');
00659                         expect.append(src_len, 's');
00660 
00661                         string result(dst.mStr, newlen);
00662 
00663                         BOOST_CHECK(!result.compare(expect));
00664                         BOOST_CHECK(!expect.compare(result));
00665                     }
00666                     BOOST_CHECK(dst.verify());
00667                     BOOST_CHECK(src.verify());
00668                 }
00669             }
00670         }
00671     }
00672 }
00673 void
00674 SqlStringTest::testSqlStringCpy_Fix()
00675 {
00676     int src_storage, dst_storage, src_len, dst_len;
00677     bool caught;
00678 
00679     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
00680         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
00681             for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
00682                 for (src_len = 0; src_len <= src_storage; src_len++) {
00683                     // ASCII
00684                     SqlStringBuffer dst(
00685                         dst_storage, dst_len,
00686                         0, dst_storage - dst_len,
00687                         'd', ' ');
00688                     SqlStringBuffer src(
00689                         src_storage, src_len,
00690                         0, src_storage - src_len,
00691                         's', ' ');
00692                     caught = false;
00693                     try {
00694                         SqlStrCpy_Fix<1, 1>(
00695                             dst.mStr,
00696                             dst_storage,
00697                             src.mStr,
00698                             src_len);
00699                     } catch (const char *str) {
00700                         caught = true;
00701                         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00702                         BOOST_CHECK(src_len > dst_storage);
00703                     } catch (...) {
00704                         // unexpected exception
00705                         BOOST_CHECK(false);
00706                     }
00707                     if (!caught) {
00708                         BOOST_CHECK(src_len <= dst_storage);
00709                         string expect;
00710                         expect.append(src_len, 's');
00711                         expect.append(dst_storage - src_len, ' ');
00712                         //expect.erase(dst_storage);
00713 
00714                         string result(dst.mStr, dst_storage);
00715 #if 0
00716                         BOOST_MESSAGE(" dst_storage=" << dst_storage <<
00717                                       " dst_len=" << dst_len <<
00718                                       " src_storage=" << src_storage <<
00719                                       " src_len=" << src_len);
00720                         BOOST_MESSAGE("src =|" << src.mLeftP << "|");
00721                         BOOST_MESSAGE("expect |" << expect << "|");
00722                         BOOST_MESSAGE("result |" << result << "|");
00723 #endif
00724                         BOOST_CHECK(!result.compare(expect));
00725                     }
00726                     BOOST_CHECK(dst.verify());
00727                     BOOST_CHECK(src.verify());
00728 
00729                     // UCS2
00730                     SqlStringBufferUCS2 srcU2(src);
00731                     SqlStringBufferUCS2 dstU2(dst);
00732 
00733                     caught = false;
00734                     try {
00735                         SqlStrCpy_Fix<2,1>(
00736                             dstU2.mStr,
00737                             dstU2.mStorage,
00738                             srcU2.mStr,
00739                             srcU2.mSize);
00740                     } catch (const char *str) {
00741                         caught = true;
00742                         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00743                         BOOST_CHECK(srcU2.mSize > dstU2.mStorage);
00744                     } catch (...) {
00745                         // unexpected exception
00746                         BOOST_CHECK(false);
00747                     }
00748                     if (!caught) {
00749                         BOOST_CHECK(srcU2.mSize <= dstU2.mStorage);
00750                         string expect;
00751                         BOOST_REQUIRE(!(srcU2.mSize & 1));
00752                         BOOST_REQUIRE(!(dstU2.mStorage & 1));
00753                         appendCharsToUCS2LikeString(
00754                             expect,
00755                             srcU2.mSize >> 1,
00756                             's');
00757                         appendCharsToUCS2LikeString(
00758                             expect,
00759                             (dstU2.mStorage -
00760                              srcU2.mSize) >> 1,
00761                             ' ');
00762                         string result(dstU2.mStr, dstU2.mStorage);
00763 #if 0
00764                         BOOST_MESSAGE(" dstU2.mStorage=" << dstU2.mStorage <<
00765                                       " dstU2.mSize=" << dstU2.mSize <<
00766                                       " srcU2.mStorage=" << srcU2.mStorage <<
00767                                       " srcU2.mSize=" << srcU2.mSize);
00768                         BOOST_MESSAGE("srcU2 =|" << srcU2.mLeftP << "|");
00769                         BOOST_MESSAGE("expectU2 |" << expect << "|");
00770                         BOOST_MESSAGE("resultU2 |" << result << "|");
00771 #endif
00772                         BOOST_CHECK(!result.compare(expect));
00773                     }
00774                     BOOST_CHECK(dstU2.verify());
00775                     BOOST_CHECK(srcU2.verify());
00776                 }
00777             }
00778         }
00779     }
00780 }
00781 
00782 void
00783 SqlStringTest::testSqlStringCpy_Var()
00784 {
00785     int src_storage, dst_storage, src_len, dst_len;
00786     int newlen;
00787     bool caught;
00788 
00789     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
00790         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
00791             for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
00792                 for (src_len = 0; src_len <= src_storage; src_len++) {
00793                     // ASCII
00794                     SqlStringBuffer dst(
00795                         dst_storage, dst_len,
00796                         0, dst_storage - dst_len,
00797                         'd', ' ');
00798                     SqlStringBuffer src(
00799                         src_storage, src_len,
00800                         0, src_storage - src_len,
00801                         's', ' ');
00802                     caught = false;
00803                     try {
00804                         newlen = SqlStrCpy_Var(
00805                             dst.mStr,
00806                             dst_storage,
00807                             src.mStr,
00808                             src_len);
00809                     } catch (const char *str) {
00810                         caught = true;
00811                         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00812                         BOOST_CHECK(src_len > dst_storage);
00813                     } catch (...) {
00814                         // unexpected exception
00815                         BOOST_CHECK(false);
00816                     }
00817                     if (!caught) {
00818                         BOOST_CHECK(src_len <= dst_storage);
00819                         BOOST_CHECK_EQUAL(newlen, src_len);
00820 
00821                         string expect;
00822                         expect.append(src_len, 's');
00823 
00824                         string result(dst.mStr, newlen);
00825 
00826                         BOOST_CHECK(!result.compare(expect));
00827                         BOOST_CHECK(!expect.compare(result));
00828                     }
00829                     BOOST_CHECK(dst.verify());
00830                     BOOST_CHECK(src.verify());
00831 
00832                     // UCS2
00833                     SqlStringBufferUCS2 srcU2(src);
00834                     SqlStringBufferUCS2 dstU2(dst);
00835                     caught = false;
00836                     try {
00837                         newlen = SqlStrCpy_Var(
00838                             dstU2.mStr,
00839                             dstU2.mStorage,
00840                             srcU2.mStr,
00841                             srcU2.mSize);
00842                     } catch (const char *str) {
00843                         caught = true;
00844                         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
00845                         BOOST_CHECK(srcU2.mSize > dstU2.mStorage);
00846                     } catch (...) {
00847                         // unexpected exception
00848                         BOOST_CHECK(false);
00849                     }
00850                     if (!caught) {
00851                         BOOST_CHECK(srcU2.mSize <= dstU2.mStorage);
00852                         BOOST_CHECK_EQUAL(newlen, srcU2.mSize);
00853 
00854                         string expect;
00855                         appendCharsToUCS2LikeString(
00856                             expect,
00857                             src_len,
00858                             's');
00859                         string result(dstU2.mStr, newlen);
00860 
00861                         BOOST_CHECK(!result.compare(expect));
00862                         BOOST_CHECK(!expect.compare(result));
00863                     }
00864                     BOOST_CHECK(dstU2.verify());
00865                     BOOST_CHECK(srcU2.verify());
00866                 }
00867             }
00868         }
00869     }
00870 }
00871 
00872 
00873 int
00874 SqlStringTest::testSqlStringNormalizeLexicalCmp(int v)
00875 {
00876     if (v < 0) {
00877         return -1;
00878     }
00879     if (v > 0) {
00880         return 1;
00881     }
00882     return 0;
00883 }
00884 
00885 void
00886 SqlStringTest::testSqlStringCmp_Helper(
00887     SqlStringBuffer &src1,
00888     int src1_storage,
00889     int src1_len,
00890     SqlStringBuffer &src2,
00891     int src2_storage,
00892     int src2_len)
00893 {
00894     int result, resultflip;
00895 
00896     string s1(src1.mStr, src1_len);
00897     string s2(src2.mStr, src2_len);
00898     string s1F(src1.mStr, src1_storage);
00899     string s2F(src2.mStr, src2_storage);
00900 
00901     // It is possible that test string ends with a space. Remove it.
00902     s1.erase(s1.find_last_not_of(" ") + 1);
00903     s2.erase(s2.find_last_not_of(" ") + 1);
00904 
00905     int expected = testSqlStringNormalizeLexicalCmp(s1.compare(s2));
00906     char const * const s1p = s1.c_str();
00907     char const * const s2p = s2.c_str();
00908     int expected2 = testSqlStringNormalizeLexicalCmp(strcmp(s1p, s2p));
00909     BOOST_CHECK_EQUAL(expected, expected2);
00910 
00911 #if 0
00912     BOOST_MESSAGE("src1=|" << s1 << "|" <<
00913                   " src2=|" << s2 << "|" <<
00914                   " src1F=|" << s1F << "|" <<
00915                   " src2F=|" << s2F << "|" <<
00916                   " expect=" << expected <<
00917                   " expect2=" << expected2);
00918 #endif
00919 
00920     // Test in a more CHAR / padded way
00921     result = SqlStrCmp<1,1>(
00922         src1.mStr, src1_storage,
00923         src2.mStr, src2_storage);
00924     BOOST_CHECK(src1.verify());
00925     BOOST_CHECK(src2.verify());
00926     BOOST_CHECK_EQUAL(result, expected);
00927 
00928     // Test in a more CHAR / padded way, flip arguments
00929     resultflip = SqlStrCmp<1,1>(
00930         src2.mStr, src2_storage,
00931         src1.mStr, src1_storage);
00932     BOOST_CHECK(src1.verify());
00933     BOOST_CHECK(src2.verify());
00934     BOOST_CHECK_EQUAL(resultflip * -1, result);
00935 
00936     // Test in a more VARCHAR / non-padded way
00937     result = SqlStrCmp<1,1>(
00938         src1.mStr, src1_len,
00939         src2.mStr, src2_len);
00940     BOOST_CHECK(src1.verify());
00941     BOOST_CHECK(src2.verify());
00942     BOOST_CHECK_EQUAL(result, expected);
00943 
00944     // Test in a more VARCHAR / non-padded way, flip arguments
00945     resultflip = SqlStrCmp<1,1>(
00946         src2.mStr, src2_len,
00947         src1.mStr, src1_len);
00948     BOOST_CHECK(src1.verify());
00949     BOOST_CHECK(src2.verify());
00950     BOOST_CHECK_EQUAL(resultflip * -1, result);
00951 
00952     // Test in a mixed CHAR/VARCHAR mode
00953     result = SqlStrCmp<1,1>(
00954         src1.mStr, src1_len,
00955         src2.mStr, src2_storage);
00956     BOOST_CHECK(src1.verify());
00957     BOOST_CHECK(src2.verify());
00958     BOOST_CHECK_EQUAL(result, expected);
00959 
00960     // Test in a mixed CHAR/VARCHAR mode, flip
00961     resultflip = SqlStrCmp<1,1>(
00962         src2.mStr, src2_storage,
00963         src1.mStr, src1_len);
00964     BOOST_CHECK(src1.verify());
00965     BOOST_CHECK(src2.verify());
00966     BOOST_CHECK_EQUAL(resultflip * -1, result);
00967 
00968     // Test in a mixed CHAR/VARCHAR mode, flip types
00969     result = SqlStrCmp<1,1>(
00970         src1.mStr, src1_storage,
00971         src2.mStr, src2_len);
00972     BOOST_CHECK(src1.verify());
00973     BOOST_CHECK(src2.verify());
00974     BOOST_CHECK_EQUAL(result, expected);
00975 
00976     // Test in a mixed CHAR/VARCHAR mode, flip types and flip args
00977     resultflip = SqlStrCmp<1,1>(
00978         src2.mStr, src2_len,
00979         src1.mStr, src1_storage);
00980     BOOST_CHECK(src1.verify());
00981     BOOST_CHECK(src2.verify());
00982     BOOST_CHECK_EQUAL(resultflip * -1, result);
00983 
00984 
00985     // force check of equal strings
00986     result = SqlStrCmp<1,1>(
00987         src1.mStr, src1_storage,
00988         src1.mStr, src1_storage);
00989     BOOST_CHECK(src1.verify());
00990     BOOST_CHECK_EQUAL(result, 0);
00991 
00992     result = SqlStrCmp<1,1>(
00993         src1.mStr, src1_len,
00994         src1.mStr, src1_len);
00995     BOOST_CHECK(src1.verify());
00996     BOOST_CHECK_EQUAL(result, 0);
00997 
00998     result = SqlStrCmp<1,1>(
00999         src1.mStr, src1_storage,
01000         src1.mStr, src1_len);
01001     BOOST_CHECK(src1.verify());
01002     BOOST_CHECK_EQUAL(result, 0);
01003 
01004     result = SqlStrCmp<1,1>(
01005         src1.mStr, src1_len,
01006         src1.mStr, src1_storage);
01007     BOOST_CHECK(src1.verify());
01008     BOOST_CHECK_EQUAL(result, 0);
01009 
01010     result = SqlStrCmp<1,1>(
01011         src2.mStr, src2_storage,
01012         src2.mStr, src2_storage);
01013     BOOST_CHECK(src2.verify());
01014     BOOST_CHECK_EQUAL(result, 0);
01015 
01016     result = SqlStrCmp<1,1>(
01017         src2.mStr, src2_len,
01018         src2.mStr, src2_len);
01019     BOOST_CHECK(src2.verify());
01020     BOOST_CHECK_EQUAL(result, 0);
01021 }
01022 
01023 
01024 void
01025 SqlStringTest::testSqlStringCmp()
01026 {
01027     int src1_storage, src2_storage, src1_len, src2_len;
01028 
01029     // can't test w/ 0, confuses strcmp and/or std:string
01030     // want to test test some values less than 'space', some
01031     // values between 'space' and 127, some values around 127,
01032     // and some values above 127. Thus test every 30
01033     // characters (space is 32) in the full 8-bit range to
01034     // hit all combinations these areas to insure that there
01035     // are no unsigned/signed issues, less than space
01036     // issues, etc. given that PAD SPACE is the default and
01037     // only supported mode, testing characters less than
01038     // space doesn't make sense until NO PAD is supported.
01039     // therefore startchar, for now starts one greater than
01040     // space
01041     int startc = ' ' + 1;  // should be 1 to test NO PAD
01042     int range = 255 - startc;
01043 
01044     for (src1_storage = 0; src1_storage <= MAXLEN; src1_storage++) {
01045         for (src1_len = 0; src1_len < src1_storage; src1_len++) {
01046             for (src2_storage = 0; src2_storage <= MAXLEN; src2_storage++) {
01047                 for (src2_len = 0; src2_len < src2_storage; src2_len++) {
01048                     for (int startchar1 = startc; startchar1 < 255;
01049                          startchar1 += 30)
01050                     {
01051                         for (int startchar2 = startc; startchar2 < 255;
01052                              startchar2 += 30)
01053                         {
01054                             SqlStringBuffer src1(
01055                                 src1_storage, src1_len,
01056                                 0, src1_storage - src1_len,
01057                                 'd', ' ');
01058                             SqlStringBuffer src2(
01059                                 src2_storage, src2_len,
01060                                 0, src2_storage - src2_len,
01061                                 's', ' ');
01062 
01063                             src1.patternfill(startchar1, startc, 255);
01064                             src2.patternfill(startchar2, startc, 255);
01065 
01066                             testSqlStringCmp_Helper(
01067                                 src1, src1_storage,
01068                                 src1_len,
01069                                 src2, src2_storage,
01070                                 src2_len);
01071                         }
01072                     }
01073                 }
01074                 // try some fully random character groupings as a test
01075                 // to the more controlled test above
01076                 for (int randX = 0; randX < 5; randX++) {
01077                     SqlStringBuffer src1(
01078                         src1_storage, src1_len,
01079                         0, src1_storage - src1_len,
01080                         'd', ' ');
01081                     SqlStringBuffer src2(
01082                         src2_storage, src2_len,
01083                         0, src2_storage - src2_len,
01084                         's', ' ');
01085 
01086                     src1.randomize(startc + (rand() % range), startc, 255);
01087                     src2.randomize(startc + (rand() % range), startc, 255);
01088 
01089                     testSqlStringCmp_Helper(
01090                         src1, src1_storage, src1_len,
01091                         src2, src2_storage, src2_len);
01092                 }
01093             }
01094         }
01095     }
01096 }
01097 
01098 // src1 and src2 are always not equal, except when both 0 length
01099 void
01100 SqlStringTest::testSqlStringCmp_Bin_Helper(
01101     SqlStringBuffer &src1,
01102     int src1_storage,
01103     int src1_len,
01104     SqlStringBuffer &src2,
01105     int src2_storage,
01106     int src2_len)
01107 {
01108     int result;
01109     string s1(src1.mStr, src1_len);
01110     string s2(src2.mStr, src2_len);
01111 #if 0
01112     BOOST_MESSAGE("src1=|" << s1 << "| " << src1_len << " " << src1_storage <<
01113                   " src2=|" << s2 << "| " << src2_len << " " << src2_storage);
01114 #endif
01115 
01116     int expected = testSqlStringNormalizeLexicalCmp(s1.compare(s2));
01117 
01118     // (generally) different values
01119     result = SqlStrCmp_Bin(
01120         src1.mStr, src1_len,
01121         src2.mStr, src2_len);
01122     BOOST_CHECK(src1.verify());
01123     BOOST_CHECK(src2.verify());
01124     BOOST_CHECK_EQUAL(expected, result);
01125 
01126     // swap different values
01127     result = SqlStrCmp_Bin(
01128         src2.mStr, src2_len,
01129         src1.mStr, src1_len);
01130     BOOST_CHECK(src1.verify());
01131     BOOST_CHECK(src2.verify());
01132     BOOST_CHECK_EQUAL(expected * -1, result);
01133 
01134     // same string
01135     result = SqlStrCmp_Bin(
01136         src1.mStr, src1_len,
01137         src1.mStr, src1_len);
01138     BOOST_CHECK(src1.verify());
01139     BOOST_CHECK_EQUAL(0, result);
01140 
01141     // same string
01142     result = SqlStrCmp_Bin(
01143         src2.mStr, src2_len,
01144         src2.mStr, src2_len);
01145     BOOST_CHECK(src2.verify());
01146     BOOST_CHECK_EQUAL(0, result);
01147 }
01148 
01149 // Lower must be > 0 to allow the use of strncmp() in testing
01150 void
01151 SqlStringTest::testSqlStringCmp_Bin_Helper2(int &lower, int &upper)
01152 {
01153     lower = (rand() % 254) + 1;
01154     upper = lower + (rand() % (255 - lower));
01155     assert(lower > 0 && lower < 256);
01156     assert(upper > 0 && upper < 256);
01157     assert(lower <= upper);
01158 }
01159 
01160 void
01161 SqlStringTest::testSqlStringCmp_Bin()
01162 {
01163     // See SQL2003 Part 2 Section 4.3.2. Binary strings are equal only if
01164     // they are same length if following SQL2003 strictly. Allow an
01165     // extension to test for inequalities, therefore test for -1, 0, 1
01166     // memcmp() semantics.
01167     int src1_storage, src2_storage, src1_len, src2_len;
01168 
01169     for (src1_storage = 0; src1_storage <= MAXCMPLEN; src1_storage++) {
01170         src1_len = src1_storage;
01171         for (src2_storage = 0; src2_storage <= MAXCMPLEN; src2_storage++) {
01172             src2_len = src2_storage;
01173             SqlStringBuffer src1(
01174                 src1_storage, src1_len,
01175                 0, src1_storage - src1_len,
01176                 'd', ' ');
01177             SqlStringBuffer src2(
01178                 src2_storage, src2_len,
01179                 0, src2_storage - src2_len,
01180                 's', ' ');
01181             testSqlStringCmp_Bin_Helper(
01182                 src1, src1_storage, src1_len,
01183                 src2, src2_storage, src2_len);
01184 
01185             if (src1_len == 0 || src2_len == 0) {
01186                 continue;
01187             }
01188             int lower, upper;
01189             int maxcmp = MAXCMPRANDOM >> 2; // no need for high iteration count
01190             if (maxcmp < 16) {
01191                 maxcmp = 16;
01192             }
01193             for (int randX = 0; randX < maxcmp; randX++) {
01194                 testSqlStringCmp_Bin_Helper2(lower, upper);
01195                 src1.randomize(lower, lower, upper);
01196                 // src2 must not == src1, except when 0 length
01197                 int count = 100;
01198                 do {
01199                     testSqlStringCmp_Bin_Helper2(lower, upper);
01200                     src2.randomize(lower, lower, upper);
01201                 } while (src1_len > 0 && count-- > 0 &&
01202                          !memcmp(src1.mStr, src2.mStr, src1_len));
01203                 if (count < 1) {
01204                     // bad luck, just give up on this iteration
01205                     BOOST_MESSAGE("giving up on impossible random string gen");
01206                     break;
01207                 }
01208                 testSqlStringCmp_Bin_Helper(
01209                     src1, src1_storage, src1_len,
01210                     src2, src2_storage, src2_len);
01211             }
01212         }
01213     }
01214 }
01215 
01216 void
01217 SqlStringTest::testSqlStringLenBit()
01218 {
01219     int src_storage, src_len;
01220     int newlen;
01221 
01222     src_storage = MAXLEN;
01223     for (src_storage = 0; src_storage <= MAXLEN; src_storage++) {
01224         for (src_len = 0; src_len <= src_storage; src_len++) {
01225             SqlStringBuffer src(
01226                 src_storage, src_len,
01227                 0, src_storage - src_len,
01228                 's', ' ');
01229 
01230             // VARCHAR-ish test
01231             newlen = SqlStrLenBit(src_len);
01232             BOOST_CHECK_EQUAL(newlen, src_len * 8);
01233             BOOST_CHECK(src.verify());
01234 
01235             // CHAR-ish test
01236             newlen = SqlStrLenBit(src_storage);
01237             BOOST_CHECK_EQUAL(newlen, src_storage * 8);
01238             BOOST_CHECK(src.verify());
01239 
01240             SqlStringBufferUCS2 srcU2(src);
01241 
01242             // VARCHAR-ish test
01243             newlen = SqlStrLenBit(srcU2.mSize);
01244             BOOST_CHECK_EQUAL(newlen, srcU2.mSize * 8);
01245             BOOST_CHECK(src.verify());
01246 
01247             // CHAR-ish test
01248             newlen = SqlStrLenBit(srcU2.mStorage);
01249             BOOST_CHECK_EQUAL(newlen, srcU2.mStorage * 8);
01250             BOOST_CHECK(src.verify());
01251         }
01252     }
01253 }
01254 
01255 void
01256 SqlStringTest::testSqlStringLenChar()
01257 {
01258     int src_storage, src_len;
01259     int newlen;
01260 
01261     src_storage = MAXLEN;
01262     for (src_storage = 0; src_storage <= MAXLEN; src_storage++) {
01263         for (src_len = 0; src_len <= src_storage; src_len++) {
01264             SqlStringBuffer src(
01265                 src_storage, src_len,
01266                 0, src_storage - src_len,
01267                 's', ' ');
01268 
01269             // VARCHAR-ish test
01270             newlen = SqlStrLenChar<1, 1>(
01271                 src.mStr,
01272                 src_len);
01273             BOOST_CHECK_EQUAL(newlen, src_len);
01274             BOOST_CHECK(src.verify());
01275 
01276             // CHAR-ish test
01277             newlen = SqlStrLenChar<1, 1>(
01278                 src.mStr,
01279                 src_storage);
01280             BOOST_CHECK_EQUAL(newlen, src_storage);
01281             BOOST_CHECK(src.verify());
01282 
01283             SqlStringBufferUCS2 srcU2(src);
01284 
01285             // VARCHAR-ish test
01286             newlen = SqlStrLenChar<2,1>(
01287                 srcU2.mStr,
01288                 srcU2.mSize);
01289             // the number characters is unchanged from Ascii src / src_len
01290             BOOST_CHECK_EQUAL(newlen, src_len);
01291             BOOST_CHECK(src.verify());
01292 
01293             // CHAR-ish test
01294             newlen = SqlStrLenChar<2,1>(
01295                 srcU2.mStr,
01296                 srcU2.mStorage);
01297             // the number characters is unchanged from Ascii src / src_storage
01298             BOOST_CHECK_EQUAL(newlen, src_storage);
01299             BOOST_CHECK(src.verify());
01300         }
01301     }
01302 }
01303 
01304 
01305 void
01306 SqlStringTest::testSqlStringLenOct()
01307 {
01308     int src_storage, src_len;
01309     int newlen;
01310 
01311     src_storage = MAXLEN;
01312     for (src_storage = 0; src_storage <= MAXLEN; src_storage++) {
01313         for (src_len = 0; src_len <= src_storage; src_len++) {
01314             SqlStringBuffer src(
01315                 src_storage, src_len,
01316                 0, src_storage - src_len,
01317                 's', ' ');
01318 
01319             // VARCHAR-ish test
01320             newlen = SqlStrLenOct(src_len);
01321             BOOST_CHECK_EQUAL(newlen, src_len);
01322             BOOST_CHECK(src.verify());
01323 
01324             // CHAR-ish test
01325             newlen = SqlStrLenOct(src_storage);
01326             BOOST_CHECK_EQUAL(newlen, src_storage);
01327             BOOST_CHECK(src.verify());
01328 
01329             SqlStringBufferUCS2 srcU2(src);
01330 
01331             // VARCHAR-ish test
01332             newlen = SqlStrLenOct(srcU2.mSize);
01333             BOOST_CHECK_EQUAL(newlen, srcU2.mSize);
01334             BOOST_CHECK(srcU2.verify());
01335 
01336             // CHAR-ish test
01337             newlen = SqlStrLenOct(srcU2.mStorage);
01338             BOOST_CHECK_EQUAL(newlen, srcU2.mStorage);
01339             BOOST_CHECK(srcU2.verify());
01340         }
01341     }
01342 }
01343 
01344 
01345 void
01346 SqlStringTest::testSqlStringOverlay()
01347 {
01348     int dst_storage, src_storage, src_len, over_storage, over_len;
01349     int position, length, lengthI;
01350     int exLeftLen, exMidLen, exRightLen;
01351     char *exLeftP, *exMidP, *exRightP;
01352     bool lenSpecified;
01353     bool caught = false;
01354     int newlen = 0;
01355 
01356     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
01357         for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
01358             src_len = src_storage;
01359             for (over_storage = 0; over_storage < MAXLEN; over_storage++) {
01360                 over_len = over_storage;
01361                 for (position = 0; position < MAXLEN; position++) {
01362                     for (lengthI = -1; lengthI < MAXLEN; lengthI++) {
01363                         if (lengthI == -1) {
01364                             lenSpecified = false;
01365                             length = over_len;
01366                         } else {
01367                             lenSpecified = true;
01368                             length = lengthI;
01369                         }
01370 #if 0
01371                         BOOST_MESSAGE(
01372                             " dst_storage=" << dst_storage <<
01373                             " src_storage=" << src_storage <<
01374                             " over_storage=" << over_storage <<
01375                             " pos=" << position <<
01376                             " length=" << length <<
01377                             " spec=" << lenSpecified);
01378 #endif
01379                         SqlStringBuffer dst(
01380                             dst_storage, dst_storage,
01381                             0, 0,
01382                             'd', ' ');
01383                         SqlStringBuffer src(
01384                             src_storage, src_len,
01385                             0, src_storage - src_len,
01386                             's', ' ');
01387                         SqlStringBuffer over(
01388                             over_storage, over_len,
01389                             0, over_storage - over_len,
01390                             'o', ' ');
01391 
01392                         src.patternfill('a', 'a', 'z');
01393                         over.patternfill('A', 'A', 'Z');
01394 
01395                         // ex* vars are 0-indexed. for loops are 1-indexed
01396                         exLeftP = src.mStr;
01397                         if (position >= 1 && src_len >= 1) {
01398                             exLeftLen = position - 1;  // 1-idx -> 0-idx
01399                             if (exLeftLen > src_len) {
01400                                 exLeftLen = src_len;
01401                             }
01402                         } else {
01403                             exLeftLen = 0;
01404                         }
01405 
01406                         exMidP = over.mStr;
01407                         exMidLen = over_len;
01408 
01409                         exRightLen = src_len - (exLeftLen + length);
01410                         if (exRightLen < 0) {
01411                             exRightLen = 0;
01412                         }
01413                         exRightP = exLeftP + (src_len - exRightLen);
01414 
01415                         string expect(exLeftP, exLeftLen);
01416                         expect.append(exMidP, exMidLen);
01417                         expect.append(exRightP, exRightLen);
01418 
01419                         caught = false;
01420                         try {
01421                             newlen = SqlStrOverlay<1,1>(
01422                                 dst.mStr,
01423                                 dst_storage,
01424                                 src.mStr,
01425                                 src_len,
01426                                 over.mStr,
01427                                 over_len,
01428                                 position,
01429                                 length,
01430                                 lenSpecified);
01431                         } catch (const char *str) {
01432                             caught = true;
01433                             if (!strcmp(str, "22011")) {
01434                                 BOOST_CHECK(
01435                                     position < 1
01436                                     || (lenSpecified && length < 1));
01437                             } else if (!strcmp(str, "22001")) {
01438                                 BOOST_CHECK(src_len + over_len > dst_storage);
01439                             } else {
01440                                 BOOST_CHECK(false);
01441                             }
01442                         }
01443                         if (!caught) {
01444                             BOOST_CHECK(position > 0);
01445                             if (lenSpecified) {
01446                                 BOOST_CHECK(length >= 0);
01447                             }
01448 
01449                             BOOST_CHECK(dst.verify());
01450                             BOOST_CHECK(src.verify());
01451                             BOOST_CHECK(over.verify());
01452 
01453                             string result(dst.mStr, newlen);
01454 
01455                             BOOST_CHECK(!result.compare(expect));
01456                             BOOST_CHECK(!expect.compare(result));
01457                         }
01458                     }
01459                 }
01460             }
01461         }
01462     }
01463 }
01464 
01465 void
01466 SqlStringTest::testSqlStringPos()
01467 {
01468     int src_storage, find_start, find_len, randX;
01469     int alter_char;
01470 
01471     int foundpos;
01472 
01473     for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
01474         for (randX = 0; randX < MAXRANDOM; randX++) {
01475             SqlStringBuffer src(
01476                 src_storage, src_storage,
01477                 0, 0,
01478                 's', ' ');
01479             src.randomize('a', 'a', 'z');
01480 
01481             // find all possible valid substrings
01482             for (find_start = 0; find_start <= src_storage; find_start++) {
01483                 for (find_len = 0; find_len <= src_storage - find_start;
01484                      find_len++)
01485                 {
01486                     string validsubstr(src.mStr + find_start, find_len);
01487                     SqlStringBuffer find(
01488                         find_len, find_len,
01489                         0, 0,
01490                         'X', ' ');
01491                     memcpy(find.mStr, validsubstr.c_str(), find_len);
01492 
01493                     foundpos  = SqlStrPos<1,1>(
01494                         src.mStr,
01495                         src_storage,
01496                         find.mStr,
01497                         find_len);
01498                     BOOST_CHECK(src.verify());
01499                     BOOST_CHECK(find.verify());
01500 
01501                     if (find_len) {
01502                         // foundpos is 1-indexed. find_start is 0-indexed.
01503                         BOOST_CHECK_EQUAL(foundpos, find_start + 1);
01504                     } else {
01505                         BOOST_CHECK_EQUAL(
01506                             foundpos, static_cast<int>(1));  // Case A.
01507                     }
01508 
01509                     // alter valid substring to prevent match
01510                     for (alter_char = 0; alter_char < find_len; alter_char++) {
01511                         char save = *(find.mStr + alter_char);
01512                         // 'X' not between 'a' and 'z'
01513                         *(find.mStr + alter_char) = 'X';
01514 
01515                         foundpos  = SqlStrPos<1,1>(
01516                             src.mStr,
01517                             src_storage,
01518                             find.mStr,
01519                             find_len);
01520                         BOOST_CHECK(src.verify());
01521                         BOOST_CHECK(find.verify());
01522 
01523                         BOOST_CHECK_EQUAL(foundpos, static_cast<int>(0));
01524 
01525                         *(find.mStr + alter_char) = save;
01526                     }
01527                 }
01528             }
01529         }
01530     }
01531 }
01532 
01533 void
01534 SqlStringTest::testSqlStringSubStr()
01535 {
01536     int src_storage, src_len, dst_storage, newlen = 0;
01537     int sub_start, sub_len;
01538     bool caught;
01539     char const * resultP;
01540 
01541     // must test where substart and/or sublen larger than src_storage and
01542     // less than 0
01543 
01544     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
01545         for (src_storage = 0; src_storage <= dst_storage; src_storage++) {
01546             for (src_len = 0; src_len <= src_storage; src_len++) {
01547                 for (sub_start = -3; sub_start <= 3 + src_storage;
01548                      sub_start++)
01549                 {
01550                     for (sub_len = -3; sub_len <= 3 + src_storage; sub_len++) {
01551                         SqlStringBuffer dst(
01552                             dst_storage, dst_storage,
01553                             0, 0,
01554                             'd', ' ');
01555                         SqlStringBuffer src(
01556                             src_storage, src_len,
01557                             0, src_storage - src_len,
01558                             's', ' ');
01559                         src.randomize();
01560 #if 0
01561                         BOOST_MESSAGE("src =|" << src.mLeftP <<
01562                                       "| dst_storage=" << dst_storage <<
01563                                       " src_storage=" << src_storage <<
01564                                       " src_len=" << src_len <<
01565                                       " sub_start=" << sub_start <<
01566                                       " sub_len=" << sub_len);
01567 #endif
01568                         int exsubstart = sub_start;
01569                         int exlen = sub_len;
01570                         if (exsubstart < 1) {
01571                             // will grab fewer characters
01572                             exlen += (exsubstart - 1);
01573                         }
01574                         exsubstart--;                       // convert index
01575                         if (exsubstart < 0) {
01576                             exsubstart = 0; // clean up for std::string
01577                         }
01578                         if (exlen < 0) {
01579                             exlen = 0;           // clean up for std::string
01580                         }
01581 
01582                         if (exsubstart + exlen > src_storage) {
01583                             if (exsubstart > src_storage) {
01584                                 exlen = 0;
01585                             } else {
01586                                 exlen = src_storage - exsubstart;
01587                             }
01588                         }
01589                         if (exsubstart < 0) {
01590                             exsubstart = 0; // clean up for std::string
01591                         }
01592                         if (exlen < 0) {
01593                             exlen = 0;           // clean up for std::string
01594                         }
01595 
01596                         string expect(src.mStr + exsubstart, exlen);
01597 
01598                         caught = false;
01599                         try {
01600                             newlen = SqlStrSubStr<1,1>(
01601                                 &resultP, dst_storage,
01602                                 src.mStr, src_storage,
01603                                 sub_start, sub_len, true);
01604                         } catch (const char *str) {
01605                             caught = true;
01606                             if (!strcmp(str, "22011")) {
01607                                 BOOST_CHECK(sub_len < 0);
01608                             } else if (!strcmp(str, "22001")) {
01609                                 BOOST_CHECK(sub_len > dst_storage);
01610                                 BOOST_CHECK(sub_len >= 0);
01611                             } else {
01612                                 BOOST_CHECK(false);
01613                             }
01614                         }
01615                         if (!caught) {
01616                             BOOST_CHECK(sub_len >= 0);
01617                             string result(resultP, newlen);
01618 #if 0
01619                             BOOST_MESSAGE("expect |" << expect << "|");
01620                             BOOST_MESSAGE("result |" << result << "|");
01621 #endif
01622                             BOOST_CHECK(!result.compare(expect));
01623                             BOOST_CHECK(!expect.compare(result));
01624                         }
01625                         BOOST_CHECK(dst.verify());
01626                         BOOST_CHECK(src.verify());
01627 
01628                         // length unspecified mode
01629                         // test when length is at or past the storage
01630                         if (sub_start > 0 && sub_len > 0 &&
01631                             sub_start + sub_len - 1 > src_storage) {
01632                             caught = false;
01633                             try {
01634                                 newlen = SqlStrSubStr<1,1>(
01635                                     &resultP, dst_storage,
01636                                     src.mStr, src_storage,
01637                                     sub_start, 0, false);
01638                             } catch (const char *str) {
01639                                 caught = true;
01640                                 if (!strcmp(str, "22011")) {
01641                                     BOOST_CHECK(sub_len < 0);
01642                                 } else if (!strcmp(str, "22001")) {
01643                                     BOOST_CHECK(sub_len > dst_storage);
01644                                 } else {
01645                                     BOOST_CHECK(false);
01646                                 }
01647                             }
01648                             if (!caught) {
01649                                 // BOOST_MESSAGE(
01650                                 //     " len=" << sub_len
01651                                 //     << " start=" << sub_start);
01652 
01653                                 string result(resultP, newlen);
01654 #if 0
01655                                 BOOST_MESSAGE("expect |" << expect << "|");
01656                                 BOOST_MESSAGE("result |" << result << "|");
01657 #endif
01658                                 BOOST_CHECK(!result.compare(expect));
01659                                 BOOST_CHECK(!expect.compare(result));
01660                             }
01661                             BOOST_CHECK(dst.verify());
01662                             BOOST_CHECK(src.verify());
01663                         }
01664                     }
01665                 }
01666             }
01667         }
01668     }
01669 }
01670 
01671 // helper to testSqlStringAlterCase()
01672 void
01673 SqlStringTest::testSqlStringAlterCase_Ascii(
01674     int dst_storage,
01675     int src_len,
01676     SqlStringBuffer& dest,
01677     SqlStringBuffer& src,
01678     const string& expect,
01679     SqlStrAlterCaseAction action)
01680 {
01681     int newlen = 0;
01682     bool caught = false;
01683 
01684     try {
01685         switch (action) {
01686         case AlterCaseUpper:
01687             newlen = SqlStrAlterCase<1,1,AlterCaseUpper>(
01688                 dest.mStr,
01689                 dest.mStorage,
01690                 src.mStr,
01691                 src.mSize);
01692             break;
01693         case AlterCaseLower:
01694             newlen = SqlStrAlterCase<1,1,AlterCaseLower>(
01695                 dest.mStr,
01696                 dest.mStorage,
01697                 src.mStr,
01698                 src.mSize);
01699             break;
01700         default:
01701             BOOST_REQUIRE(0);
01702             break;
01703         }
01704     } catch (const char *str) {
01705         caught = true;
01706         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
01707         BOOST_CHECK(src_len > dst_storage);
01708     } catch (...) {
01709         // unexpected exception
01710         BOOST_CHECK(false);
01711     }
01712     if (!caught) {
01713         BOOST_CHECK(src_len <= dst_storage);
01714         BOOST_CHECK(src.verify());
01715         BOOST_CHECK(dest.verify());
01716         BOOST_CHECK_EQUAL(newlen, src_len);
01717 
01718         string result(dest.mStr, newlen);
01719 #if 0
01720         BOOST_MESSAGE(" action=" << action <<
01721                       " newlen="<< newlen <<
01722                       " result=|" << result << "|" <<
01723                       " expect=|" << expect << "|");
01724 #endif
01725         BOOST_CHECK(!expect.compare(result));
01726     }
01727 }
01728 
01729 // helper to testSqlStringAlterCase()
01730 void
01731 SqlStringTest::testSqlStringAlterCase_UCS2(
01732     int dst_storage,
01733     int src_len,
01734     SqlStringBufferUCS2& destU2,
01735     SqlStringBufferUCS2& srcU2,
01736     const string& expect,
01737     SqlStrAlterCaseAction action)
01738 {
01739 #ifdef HAVE_ICU
01740     UnicodeString expectU2(expect.c_str(), "iso-8859-1");
01741     BOOST_REQUIRE(!expectU2.isBogus());
01742 
01743     BOOST_CHECK(srcU2.verify());
01744     BOOST_CHECK(destU2.verify());
01745 
01746     BOOST_REQUIRE(srcU2.mSize == src_len * 2);
01747     BOOST_REQUIRE(destU2.mStorage == dst_storage * 2);
01748 
01749     int newlen;
01750     bool caught = false;
01751     try {
01752         switch (action) {
01753         case AlterCaseUpper:
01754             newlen = SqlStrAlterCase<2,1,AlterCaseUpper>(
01755                 destU2.mStr,
01756                 destU2.mStorage,
01757                 srcU2.mStr,
01758                 srcU2.mSize,
01759                 ULOC_US);
01760             break;
01761         case AlterCaseLower:
01762             newlen = SqlStrAlterCase<2,1,AlterCaseLower>(
01763                 destU2.mStr,
01764                 destU2.mStorage,
01765                 srcU2.mStr,
01766                 srcU2.mSize,
01767                 ULOC_US);
01768             break;
01769         default:
01770             BOOST_REQUIRE(0);
01771             break;
01772         }
01773     } catch (const char *str) {
01774         caught = true;
01775         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
01776         BOOST_CHECK(src_len > dst_storage);
01777     } catch (...) {
01778         // unexpected exception
01779         BOOST_CHECK(false);
01780     }
01781     if (!caught) {
01782         BOOST_CHECK(src_len <= dst_storage);
01783         BOOST_CHECK(srcU2.verify());
01784         BOOST_CHECK(destU2.verify());
01785         BOOST_CHECK_EQUAL(newlen, srcU2.mSize);
01786 
01787         UnicodeString resultU2(
01788             reinterpret_cast<UChar *>(destU2.mStr),
01789             newlen >> 1);
01790 
01791         BOOST_REQUIRE(!resultU2.isBogus());
01792 #if 0
01793         BOOST_MESSAGE("newlen=" << newlen);
01794         BOOST_MESSAGE("srcU2= |" << srcU2.dump());
01795         BOOST_MESSAGE("destU2= |" << destU2.dump());
01796         BOOST_MESSAGE("expect=|" << UnicodeToPrintable(expectU2) << "|");
01797         BOOST_MESSAGE("result=|" << UnicodeToPrintable(resultU2) << "|");
01798 #endif
01799         BOOST_CHECK(!expectU2.compare(resultU2));
01800     }
01801 #endif
01802 }
01803 
01804 // helper to testSqlStringAlterCase()
01805 void
01806 SqlStringTest::testSqlStringAlterCase_Case(
01807     SqlStrAlterCaseAction action,
01808     int dst_storage,
01809     int dest_len,
01810     int src_storage,
01811     int src_len)
01812 {
01813     BOOST_REQUIRE(action == AlterCaseUpper || action == AlterCaseLower);
01814 
01815     SqlStringBuffer dest(
01816         dst_storage, dest_len,
01817         0, 0,
01818         'd', ' ');
01819     SqlStringBuffer src(
01820         src_storage, src_len,
01821         0, src_storage - src_len,
01822         's', ' ');
01823     string expect;
01824 
01825     switch (action) {
01826     case AlterCaseUpper:
01827         src.randomize('a');
01828         expect.assign(src.mStr, src_len);
01829         std::transform(
01830             expect.begin(), expect.end(),
01831             expect.begin(), (int(*)(int)) std::toupper);
01832         break;
01833     case AlterCaseLower:
01834         src.randomize('A');
01835         expect.assign(src.mStr, src_len);
01836         std::transform(
01837             expect.begin(), expect.end(),
01838             expect.begin(), (int(*)(int)) std::tolower);
01839         break;
01840     default:
01841         BOOST_REQUIRE(0);
01842         break;
01843     }
01844 
01845     // Ascii
01846     testSqlStringAlterCase_Ascii(
01847         dst_storage, src_len,
01848         dest,
01849         src,
01850         expect,
01851         action);
01852 
01853     // UCS2 long-word aligned case
01854     // perhaps nits are being picked too fine here. could deprecate.
01855 
01856     SqlStringBufferUCS2 srcU2LongAligned(src, 4, 4);
01857     SqlStringBufferUCS2 destU2LongAligned(dest, 4, 4);
01858 
01859     testSqlStringAlterCase_UCS2(
01860         dst_storage,
01861         src_len,
01862         destU2LongAligned,
01863         srcU2LongAligned,
01864         expect,
01865         action);
01866 
01867     // UCS2 short-word aligned case
01868     SqlStringBufferUCS2 srcU2ShortAligned(src);
01869     SqlStringBufferUCS2 destU2ShortAligned(dest);
01870 
01871     testSqlStringAlterCase_UCS2(
01872         dst_storage,
01873         src_len,
01874         destU2ShortAligned,
01875         srcU2ShortAligned,
01876         expect,
01877         action);
01878 
01879 }
01880 
01881 
01882 void
01883 SqlStringTest::testSqlStringAlterCase()
01884 {
01885     int dst_storage, dest_len, src_storage, src_len, randX;
01886 
01887     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
01888         dest_len = dst_storage;
01889         for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
01890             src_len = src_storage;
01891             for (randX = 0; randX < MAXRANDOM; randX++) {
01892                 testSqlStringAlterCase_Case(
01893                     AlterCaseUpper,
01894                     dst_storage,
01895                     dest_len,
01896                     src_storage,
01897                     src_len);
01898                 testSqlStringAlterCase_Case(
01899                     AlterCaseLower,
01900                     dst_storage,
01901                     dest_len,
01902                     src_storage,
01903                     src_len);
01904             }
01905         }
01906     }
01907 }
01908 
01909 void
01910 SqlStringTest::testSqlStringTrim_Helper(
01911     int dst_storage,
01912     int src_storage,
01913     int src_len,
01914     int leftpad,
01915     int rightpad,
01916     int action)
01917 {
01918     int expectsize, expectsizeU2;
01919     string expect, expectU2;
01920     int lefttrim = 0, righttrim = 0;
01921     char padchar = ' ';
01922     char textchar = 's';
01923     bool caught;
01924 
01925     switch (action) {
01926     case 0:
01927         lefttrim = 1;
01928         righttrim = 1;
01929         expect.append(src_len, textchar);
01930         expectsize = src_len;
01931         appendCharsToUCS2LikeString(
01932             expectU2,
01933             src_len,
01934             textchar);
01935         break;
01936     case 1:
01937         lefttrim = 1;
01938         righttrim = 0;
01939         expect.append(src_len, textchar);
01940         appendCharsToUCS2LikeString(
01941             expectU2,
01942             src_len,
01943             textchar);
01944         // if no text, everything is trimmed
01945         if (src_len) {
01946             expect.append(rightpad, padchar);
01947             appendCharsToUCS2LikeString(
01948                 expectU2,
01949                 rightpad,
01950                 padchar);
01951         }
01952         expectsize = src_len + (src_len ? rightpad : 0);
01953         break;
01954     case 2:
01955         lefttrim = 0;
01956         righttrim = 1;
01957         // if no text, everything is trimmed
01958         if (src_len) {
01959             expect.append(leftpad, padchar);
01960             appendCharsToUCS2LikeString(
01961                 expectU2,
01962                 leftpad,
01963                 padchar);
01964         }
01965         expect.append(src_len, textchar);
01966         appendCharsToUCS2LikeString(
01967             expectU2,
01968             src_len,
01969             textchar);
01970         expectsize = src_len + (src_len ? leftpad : 0);
01971         break;
01972     case 3:
01973         lefttrim = 0;
01974         righttrim = 0;
01975         expect.append(leftpad, padchar);
01976         expect.append(src_len, textchar);
01977         expect.append(rightpad, padchar);
01978         appendCharsToUCS2LikeString(
01979             expectU2,
01980             leftpad,
01981             padchar);
01982         appendCharsToUCS2LikeString(
01983             expectU2,
01984             src_len,
01985             textchar);
01986         appendCharsToUCS2LikeString(
01987             expectU2,
01988             rightpad,
01989             padchar);
01990         expectsize = src_len + leftpad + rightpad;
01991         break;
01992     }
01993     expectsizeU2 = expectsize * 2;
01994     BOOST_REQUIRE(expect.length() == expectsize);
01995     BOOST_REQUIRE(expectU2.length() == expectsizeU2);
01996 
01997     string resultByReference;
01998     string resultCopy;
01999     int newsize;
02000     SqlStringBuffer src(
02001         src_storage, src_len,
02002         leftpad, rightpad,
02003         textchar, padchar);
02004     SqlStringBuffer dst(
02005         dst_storage, dst_storage,
02006         0, 0,
02007         textchar, padchar);
02008 
02009     // ASCII copy
02010     caught = false;
02011     try {
02012         newsize =
02013             SqlStrTrim<1,1>(
02014                 dst.mStr,
02015                 dst_storage,
02016                 src.mStr,
02017                 src_len + leftpad + rightpad,
02018                 lefttrim,
02019                 righttrim);
02020     } catch (const char *str) {
02021         caught = true;
02022         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
02023         BOOST_CHECK(expectsize > dst_storage);
02024     } catch (...) {
02025         // unexpected exception
02026         BOOST_CHECK(false);
02027     }
02028 
02029     if (!caught) {
02030         BOOST_CHECK(expectsize <= dst_storage);
02031 
02032         BOOST_CHECK(src.verify());
02033         BOOST_CHECK(dst.verify());
02034         BOOST_CHECK_EQUAL(newsize, expectsize);
02035         resultCopy = string(dst.mStr, newsize);
02036 
02037         BOOST_CHECK(!resultCopy.compare(expect));
02038     }
02039 
02040     // UCS2 copy
02041     SqlStringBufferUCS2 srcU2(src);
02042     SqlStringBufferUCS2 dstU2(dst);
02043     caught = false;
02044     try {
02045         newsize =
02046             SqlStrTrim<2,1>(
02047                 dstU2.mStr,
02048                 dstU2.mStorage,
02049                 srcU2.mStr,
02050                 (srcU2.mSize +
02051                  srcU2.mLeftPad +
02052                  srcU2.mRightPad),
02053                 lefttrim,
02054                 righttrim);
02055     } catch (const char *str) {
02056         caught = true;
02057         BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
02058         BOOST_CHECK(expectsize > dst_storage);
02059     } catch (...) {
02060         // unexpected exception
02061         BOOST_CHECK(false);
02062     }
02063 
02064     if (!caught) {
02065         BOOST_CHECK(expectsize <= dst_storage);
02066 
02067         BOOST_CHECK(srcU2.verify());
02068         BOOST_CHECK(dstU2.verify());
02069         BOOST_CHECK_EQUAL(newsize, expectsizeU2);
02070         resultCopy = string(dstU2.mStr, newsize);
02071 
02072         BOOST_CHECK(!resultCopy.compare(expectU2));
02073     }
02074 
02075 
02076 
02077     // ASCII by reference
02078     char const * start;
02079     newsize = SqlStrTrim<1,1>(
02080         &start,
02081         src.mStr,
02082         src_len + leftpad + rightpad,
02083         lefttrim,
02084         righttrim);
02085 
02086     BOOST_CHECK(start >= src.mStr);
02087     BOOST_CHECK(start <= src.mStr + src_storage);
02088     BOOST_CHECK(src.verify());
02089     BOOST_CHECK(dst.verify());
02090     BOOST_CHECK_EQUAL(newsize, expectsize);
02091     resultByReference = string(start, newsize);
02092 
02093     BOOST_CHECK(!resultByReference.compare(expect));
02094     BOOST_CHECK(!expect.compare(resultByReference));
02095 
02096     // UCS2 by reference
02097     newsize = SqlStrTrim<2,1>(
02098         &start,
02099         srcU2.mStr,
02100         (srcU2.mSize +
02101          srcU2.mLeftPad +
02102          srcU2.mRightPad),
02103         lefttrim,
02104         righttrim);
02105 
02106     BOOST_CHECK(start >= srcU2.mStr);
02107     BOOST_CHECK(start <= srcU2.mStr + srcU2.mStorage);
02108     BOOST_CHECK(srcU2.verify());
02109     BOOST_CHECK(dstU2.verify());
02110     BOOST_CHECK_EQUAL(newsize, expectsizeU2);
02111     resultByReference = string(start, newsize);
02112 
02113     BOOST_CHECK(!resultByReference.compare(expectU2));
02114 }
02115 
02116 
02117 void
02118 SqlStringTest::testSqlStringTrim()
02119 {
02120     int dst_storage, src_storage, src_len, leftpad, rightpad, randX, action;
02121 
02122     BOOST_REQUIRE(MAXLEN >= 5); // 2 pad + 1 text + 2 pad
02123 
02124     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
02125         for (src_storage = 0; src_storage < dst_storage + 5; src_storage++) {
02126             for (src_len = 0; src_len <= src_storage; src_len++) {
02127                 for (leftpad = 0; leftpad <= src_storage - src_len; leftpad++) {
02128                     rightpad = src_storage - (src_len + leftpad);
02129                     for (randX = 0; randX < MAXRANDOM; randX++) {
02130                         BOOST_REQUIRE(
02131                             leftpad + rightpad + src_len
02132                             == src_storage);
02133                         for (action = 0; action < 4; action++) {
02134                             testSqlStringTrim_Helper(
02135                                 dst_storage,
02136                                 src_storage,
02137                                 src_len,
02138                                 leftpad,
02139                                 rightpad,
02140                                 action);
02141                         }
02142                     }
02143                 }
02144             }
02145         }
02146     }
02147 }
02148 
02149 void
02150 SqlStringTest::testSqlStringCastToExact_Helper(
02151     uint64_t value,
02152     char const * const buf,
02153     int src_storage,
02154     int src_len,
02155     bool exceptionExpected)
02156 {
02157     bool caught = false;
02158     int64_t newvalue = 0;
02159     SqlStringBuffer src(
02160         src_storage, src_len,
02161         0, src_storage - src_len,
02162         's', ' ');
02163 
02164 #if 0
02165     BOOST_MESSAGE("buf = |" << buf << "|");
02166 #endif
02167     if (strlen(buf) > src_len) {
02168         // not all test cases will fit, just silently ignore them
02169         return;
02170     }
02171 
02172     // copy string, minus null
02173     memcpy(src.mStr, buf, strlen(buf));
02174     // pad out any leftovers with spaces (say, if value is very small for
02175     // string length)
02176     memset(src.mStr + strlen(buf), ' ', src_len - strlen(buf));
02177 #if 0
02178     BOOST_MESSAGE("str = |" << src.mLeftP << "|");
02179 #endif
02180 
02181     try {
02182         newvalue = SqlStrCastToExact<1,1>(
02183             src.mStr,
02184             src_len);
02185     } catch (const char *str) {
02186         caught = true;
02187         BOOST_CHECK_EQUAL(strcmp(str, "22018"), 0);
02188     }
02189     BOOST_CHECK_EQUAL(caught, exceptionExpected);
02190     if (!caught) {
02191         BOOST_CHECK_EQUAL(value, newvalue);
02192         BOOST_CHECK(src.verify());
02193     }
02194 }
02195 
02196 // tests varchar case, at least partially, when src_len == src_storage
02197 void
02198 SqlStringTest::testSqlStringCastToExact()
02199 {
02200     int src_storage, src_len;
02201     int rand_idx;
02202     int64_t power, poweridx;
02203     int64_t value, valuer1, valuer2, valuer3;
02204     char buf[256];
02205 
02206     src_storage = MAXLEN;
02207     //    strlen(2^64) = 20;
02208     for (src_storage = 1; src_storage <= 20; src_storage++) {
02209         for (src_len = 1; src_len <= src_storage; src_len++) {
02210             power = 1;
02211             for (poweridx = 0; poweridx < src_len; poweridx++) {
02212                 power *= 10;
02213             }
02214             // do a bit more than typical random to get decent coverage
02215             // on positives, negatives, and various length numbers.
02216             // besides, test runs very quickly anyway.
02217             for (rand_idx = 0; rand_idx < 5 * MAXRANDOM; rand_idx++) {
02218                 // rand only produces a long, not a long long, so get jiggy.
02219                 valuer1 = rand();
02220                 valuer2 = rand();
02221                 valuer3 = rand();
02222                 value = (valuer1 * valuer2 * valuer3) % power;
02223                 // overflow will cause some negative values
02224                 if (value < 0) {
02225                     value *= -1;
02226                 }
02227                 if (src_len > 1 && rand() % 2) {
02228                     // cause ~half of values to be negative, but
02229                     // reduce length by one to prevent overflow of
02230                     // src.
02231                     value /= -10;
02232                 }
02233 
02234 
02235 #if 0
02236                 BOOST_MESSAGE("src_storage = " << src_storage);
02237                 BOOST_MESSAGE("src_len = " << src_len);
02238                 BOOST_MESSAGE("power = " << power);
02239                 BOOST_MESSAGE("value = " << value);
02240 #endif
02241 
02242                 // positive test, "1234   "
02243                 sprintf(buf, "%" FMT_INT64, value);
02244                 BOOST_REQUIRE(strlen(buf) <= src_len);
02245                 testSqlStringCastToExact_Helper(
02246                     value,
02247                     buf,
02248                     src_storage,
02249                     src_len,
02250                     false);
02251 
02252                 // positive test, "+123   "
02253                 if (src_len >= 2 && value >= 0) {
02254                     sprintf(buf, "+%" FMT_INT64, value / 10);
02255                     BOOST_REQUIRE(strlen(buf) <= src_len);
02256                     testSqlStringCastToExact_Helper(
02257                         value / 10,
02258                         buf,
02259                         src_storage,
02260                         src_len,
02261                         false);
02262                 }
02263 
02264 
02265                 // positive test, "  123", " 1234", "12345", "123456"
02266                 sprintf(buf, "%5" FMT_INT64, value);
02267                 testSqlStringCastToExact_Helper(
02268                     value,
02269                     buf,
02270                     src_storage,
02271                     src_len,
02272                     false);
02273 
02274                 // positive test, "            1234"
02275                 sprintf(buf, "%20" FMT_INT64, value);
02276                 testSqlStringCastToExact_Helper(
02277                     value,
02278                     buf,
02279                     src_storage,
02280                     src_len,
02281                     false);
02282 
02283                 // positive test, "000000000000001234"
02284                 sprintf(buf, "%020" FMT_INT64, value);
02285                 testSqlStringCastToExact_Helper(
02286                     value,
02287                     buf,
02288                     src_storage,
02289                     src_len,
02290                     false);
02291 
02292                 // positive test, "0001234  "
02293                 sprintf(buf, "%07" FMT_INT64, value);
02294                 testSqlStringCastToExact_Helper(
02295                     value,
02296                     buf,
02297                     src_storage,
02298                     src_len,
02299                     false);
02300 
02301                 // negative test, "a234   "
02302                 sprintf(buf, "%" FMT_INT64, value);
02303                 buf[0] = 'a';
02304                 testSqlStringCastToExact_Helper(
02305                         value,
02306                         buf,
02307                         src_storage,
02308                         src_len,
02309                         true);
02310 
02311                 // negative test, "1a34   "
02312                 if (src_len > 2) {
02313                     sprintf(buf, "%" FMT_INT64, value);
02314                     buf[1] = 'a';
02315                     testSqlStringCastToExact_Helper(
02316                         value,
02317                         buf,
02318                         src_storage,
02319                         src_len,
02320                         true);
02321                 }
02322 
02323                 // negative test, "1 23 "
02324                 if (src_len > 3 && value >= 100) {
02325                     sprintf(buf, "%" FMT_INT64, value);
02326                     buf[1] = ' ';
02327                     testSqlStringCastToExact_Helper(
02328                         value,
02329                         buf,
02330                         src_storage,
02331                         src_len,
02332                         true);
02333                 }
02334 
02335                 // negative test, "    "
02336                 memset(buf, ' ', src_len);
02337                 testSqlStringCastToExact_Helper(
02338                     value,
02339                     buf,
02340                     src_storage,
02341                     src_len,
02342                     true);
02343 
02344                 // negative test, "- 3"
02345                 if (src_len > 3) {
02346                     sprintf(buf, "%" FMT_INT64, value);
02347                     buf[0] = '-';
02348                     buf[1] = ' ';
02349                     testSqlStringCastToExact_Helper(
02350                         value,
02351                         buf,
02352                         src_storage,
02353                         src_len,
02354                         true);
02355                 }
02356 
02357                 // negative test, "+ 3"
02358                 if (src_len > 3) {
02359                     sprintf(buf, "%" FMT_INT64, value);
02360                     buf[0] = '-';
02361                     buf[1] = ' ';
02362                     testSqlStringCastToExact_Helper(
02363                         value,
02364                         buf,
02365                         src_storage,
02366                         src_len,
02367                         true);
02368                 }
02369 
02370                 // negative test, "- "
02371                 memset(buf, ' ', src_len);
02372                 buf[0] = '-';
02373                 testSqlStringCastToExact_Helper(
02374                     value,
02375                     buf,
02376                     src_storage,
02377                     src_len,
02378                     true);
02379                 // negative test, "+ "
02380                 memset(buf, ' ', src_len);
02381                 buf[0] = '+';
02382                 testSqlStringCastToExact_Helper(
02383                     value,
02384                     buf,
02385                     src_storage,
02386                     src_len,
02387                     true);
02388             }
02389         }
02390     }
02391 }
02392 
02393 void
02394 SqlStringTest::testSqlStringCastToDecimal_Helper(
02395     uint64_t value,
02396     int precision,
02397     int scale,
02398     char const * const buf,
02399     int src_storage,
02400     int src_len,
02401     bool outOfRangeExpected,
02402     bool invalidCharExpected)
02403 {
02404     bool caught = false;
02405     int64_t newvalue = 0;
02406     SqlStringBuffer src(
02407         src_storage, src_len,
02408         0, src_storage - src_len,
02409         's', ' ');
02410 
02411 #if 0
02412     BOOST_MESSAGE("buf = |" << buf << "|");
02413 #endif
02414 
02415     if (strlen(buf) > src_len) {
02416         // not all test cases will fit, just silently ignore them
02417         return;
02418     }
02419 
02420     // copy string, minus null
02421     memcpy(src.mStr, buf, strlen(buf));
02422     // pad out any leftovers with spaces (say, if value is very small for
02423     // string length)
02424     memset(src.mStr + strlen(buf), ' ', src_len - strlen(buf));
02425 #if 0
02426     BOOST_MESSAGE("str = |" << src.mLeftP << "|");
02427 #endif
02428 
02429     try {
02430         newvalue = SqlStrCastToExact<1,1>(
02431             src.mStr,
02432             src_len,
02433             precision,
02434             scale);
02435     } catch (const char *str) {
02436         caught = true;
02437         if (outOfRangeExpected) {
02438             BOOST_CHECK_EQUAL(strcmp(str, "22003"), 0);
02439         } else if (invalidCharExpected) {
02440             BOOST_CHECK_EQUAL(strcmp(str, "22018"), 0);
02441         } else {
02442             // Unexpected exception
02443             BOOST_CHECK(false);
02444         }
02445     }
02446     BOOST_CHECK_EQUAL(caught, (invalidCharExpected || outOfRangeExpected));
02447     if (!caught) {
02448         BOOST_CHECK_EQUAL(value, newvalue);
02449         BOOST_CHECK(src.verify());
02450     }
02451 }
02452 
02453 
02454 // tests varchar case, at least partially, when src_len == src_storage
02455 void
02456 SqlStringTest::testSqlStringCastToDecimal()
02457 {
02458     int src_storage, src_len;
02459     int rand_idx;
02460     int precision, scale;
02461     int64_t power, poweridx;
02462     int64_t value, valuer1, valuer2, valuer3;
02463     char buf[256];
02464 
02465     src_storage = MAXLEN;
02466     //    strlen(2^64) = 20;
02467     for (src_storage = 1; src_storage <= 20; src_storage++) {
02468         for (src_len = 1; src_len <= src_storage; src_len++) {
02469             power = 1;
02470             for (poweridx = 0; poweridx < src_len; poweridx++) {
02471                 power *= 10;
02472             }
02473             // do a bit more than typical random to get decent coverage
02474             // on positives, negatives, and various length numbers.
02475             // besides, test runs very quickly anyway.
02476             for (rand_idx = 0; rand_idx < 5 * MAXRANDOM; rand_idx++) {
02477                 // rand only produces a long, not a long long, so get jiggy.
02478                 valuer1 = rand();
02479                 valuer2 = rand();
02480                 valuer3 = rand();
02481                 value = (valuer1 * valuer2 * valuer3) % power;
02482                 // overflow will cause some negative values
02483                 if (value < 0) {
02484                     value *= -1;
02485                 }
02486                 if (src_len > 1 && rand() % 2) {
02487                     // cause ~half of values to be negative, but
02488                     // reduce length by one to prevent overflow of
02489                     // src.
02490                     value /= -10;
02491                 }
02492 
02493 #if 0
02494                 BOOST_MESSAGE("src_storage = " << src_storage);
02495                 BOOST_MESSAGE("src_len = " << src_len);
02496                 BOOST_MESSAGE("power = " << power);
02497                 BOOST_MESSAGE("value = " << value);
02498 #endif
02499 
02500                 scale = 0;
02501 
02502                 // positive test, "1234   "
02503                 sprintf(buf, "%" FMT_INT64, value);
02504                 precision = (value < 0) ? strlen(buf) - 1 : strlen(buf);
02505                 BOOST_REQUIRE(strlen(buf) <= src_len);
02506                 testSqlStringCastToDecimal_Helper(
02507                     value,
02508                     precision,
02509                     scale,
02510                     buf,
02511                     src_storage,
02512                     src_len,
02513                     false,
02514                     false);
02515 
02516                 // positive test, "+123   "
02517                 if (src_len >= 2 && value >= 0) {
02518                     sprintf(buf, "+%" FMT_INT64, value / 10);
02519                     BOOST_REQUIRE(strlen(buf) <= src_len);
02520                     testSqlStringCastToDecimal_Helper(
02521                         value / 10,
02522                         precision,
02523                         scale,
02524                         buf,
02525                         src_storage,
02526                         src_len,
02527                         false,
02528                         false);
02529                 }
02530 
02531 
02532                 // positive test, "  123", " 1234", "12345", "123456"
02533                 sprintf(buf, "%5" FMT_INT64, value);
02534                 testSqlStringCastToDecimal_Helper(
02535                     value,
02536                     precision,
02537                     scale,
02538                     buf,
02539                     src_storage,
02540                     src_len,
02541                     false,
02542                     false);
02543 
02544                 // positive test, "            1234"
02545                 sprintf(buf, "%20" FMT_INT64, value);
02546                 testSqlStringCastToDecimal_Helper(
02547                     value,
02548                     precision,
02549                     scale,
02550                     buf,
02551                     src_storage,
02552                     src_len,
02553                     false,
02554                     false);
02555 
02556                 // positive test, "000000000000001234"
02557                 sprintf(buf, "%020" FMT_INT64, value);
02558                 testSqlStringCastToDecimal_Helper(
02559                     value,
02560                     precision,
02561                     scale,
02562                     buf,
02563                     src_storage,
02564                     src_len,
02565                     false,
02566                     false);
02567 
02568 
02569                 // positive test, "0001234  "
02570                 sprintf(buf, "%07" FMT_INT64, value);
02571                 testSqlStringCastToDecimal_Helper(
02572                     value,
02573                     precision,
02574                     scale,
02575                     buf,
02576                     src_storage,
02577                     src_len,
02578                     false,
02579                     false);
02580 
02581                 // positive test, ".1234"
02582                 sprintf(buf, ".%" FMT_INT64, value);
02583                 if (value < 0) {
02584                     buf[0] = '-';
02585                     buf[1] = '.';
02586                 }
02587                 testSqlStringCastToDecimal_Helper(
02588                     value,
02589                     precision,
02590                     precision,
02591                     buf,
02592                     src_storage + 1,
02593                     src_len + 1,
02594                     false,
02595                     false);
02596 
02597                 // positive test, ".1234e3" = "123.4"
02598                 sprintf(buf, ".%" FMT_INT64 "e3", value);
02599                 if (value < 0) {
02600                     buf[0] = '-';
02601                     buf[1] = '.';
02602                 }
02603                 testSqlStringCastToDecimal_Helper(
02604                     value,
02605                     precision,
02606                     precision - 3,
02607                     buf,
02608                     src_storage + 3,
02609                     src_len + 3,
02610                     false,
02611                     false);
02612 
02613                 if (value != 0) {
02614                     // negative test, out of range
02615                     testSqlStringCastToDecimal_Helper(
02616                         value,
02617                         precision,
02618                         precision,
02619                         buf,
02620                         src_storage + 3,
02621                         src_len + 3,
02622                         true,
02623                         false);
02624                 }
02625 
02626                 // positive test, "1234e-3"
02627                 uint64_t tmp;
02628                 sprintf(buf, "%" FMT_INT64 "e-3", value);
02629 
02630                 testSqlStringCastToDecimal_Helper(
02631                     value,
02632                     precision,
02633                     3,
02634                     buf,
02635                     src_storage,
02636                     src_len,
02637                     false,
02638                     false);
02639 
02640                 // positive test, rounding
02641                 if (value < 0) {
02642                     tmp = -((-value + 5) /10);
02643                 } else {
02644                     tmp = (value + 5) / 10;
02645                 }
02646                 testSqlStringCastToDecimal_Helper(
02647                     tmp,
02648                     precision,
02649                     2,
02650                     buf,
02651                     src_storage+3,
02652                     src_len + 3,
02653                     false,
02654                     false);
02655 
02656                 if (value != 0) {
02657                     // negative test, out of range
02658                     testSqlStringCastToDecimal_Helper(
02659                         value,
02660                         precision,
02661                         4,
02662                         buf,
02663                         src_storage + 3,
02664                         src_len + 3,
02665                         true,
02666                         false);
02667                 }
02668 
02669 
02670                 // negative test, out of range
02671                 if (abs(value) >= 10) {
02672                     sprintf(buf, "%" FMT_INT64, value);
02673                     testSqlStringCastToDecimal_Helper(
02674                         value,
02675                         precision - 1,
02676                         scale,
02677                         buf,
02678                         src_storage,
02679                         src_len,
02680                         true,
02681                         false);
02682                 }
02683 
02684                 // negative test, "123e"
02685                 sprintf(buf, "%" FMT_INT64 "e", value);
02686                 testSqlStringCastToDecimal_Helper(
02687                     value,
02688                     precision,
02689                     scale,
02690                     buf,
02691                     src_storage + 1,
02692                     src_len + 1,
02693                     false,
02694                     true);
02695 
02696                 // negative test, "a234   "
02697                 sprintf(buf, "%" FMT_INT64, value);
02698                 buf[0] = 'a';
02699                 testSqlStringCastToDecimal_Helper(
02700                     value,
02701                     precision,
02702                     scale,
02703                     buf,
02704                     src_storage,
02705                     src_len,
02706                     false,
02707                     true);
02708 
02709                 // negative test, "1a34   "
02710                 if (src_len > 2) {
02711                     sprintf(buf, "%" FMT_INT64, value);
02712                     buf[1] = 'a';
02713                     testSqlStringCastToDecimal_Helper(
02714                         value,
02715                         precision,
02716                         scale,
02717                         buf,
02718                         src_storage,
02719                         src_len,
02720                         false,
02721                         true);
02722                 }
02723 
02724                 // negative test, "1 23 "
02725                 if (src_len > 3 && value >= 100) {
02726                     sprintf(buf, "%" FMT_INT64, value);
02727                     buf[1] = ' ';
02728                     testSqlStringCastToDecimal_Helper(
02729                         value,
02730                         precision,
02731                         scale,
02732                         buf,
02733                         src_storage,
02734                         src_len,
02735                         false,
02736                         true);
02737                 }
02738 
02739                 // negative test, "    "
02740                 memset(buf, ' ', src_len);
02741                 testSqlStringCastToDecimal_Helper(
02742                     value,
02743                     precision,
02744                     scale,
02745                     buf,
02746                     src_storage,
02747                     src_len,
02748                     false,
02749                     true);
02750 
02751                 // negative test, "- 3"
02752                 if (src_len > 3) {
02753                     sprintf(buf, "%" FMT_INT64, value);
02754                     buf[0] = '-';
02755                     buf[1] = ' ';
02756                     testSqlStringCastToDecimal_Helper(
02757                         value,
02758                         precision,
02759                         scale,
02760                         buf,
02761                         src_storage,
02762                         src_len,
02763                         false,
02764                         true);
02765                 }
02766 
02767                 // negative test, "+ 3"
02768                 if (src_len > 3) {
02769                     sprintf(buf, "%" FMT_INT64, value);
02770                     buf[0] = '-';
02771                     buf[1] = ' ';
02772                     testSqlStringCastToDecimal_Helper(
02773                         value,
02774                         precision,
02775                         scale,
02776                         buf,
02777                         src_storage,
02778                         src_len,
02779                         false,
02780                         true);
02781                 }
02782 
02783                 // negative test, "- "
02784                 memset(buf, ' ', src_len);
02785                 buf[0] = '-';
02786                 testSqlStringCastToDecimal_Helper(
02787                     value,
02788                     precision,
02789                     scale,
02790                     buf,
02791                     src_storage,
02792                     src_len,
02793                     false,
02794                     true);
02795                 // negative test, "+ "
02796                 memset(buf, ' ', src_len);
02797                 buf[0] = '+';
02798                 testSqlStringCastToDecimal_Helper(
02799                     value,
02800                     precision,
02801                     scale,
02802                     buf,
02803                     src_storage,
02804                     src_len,
02805                     false,
02806                     true);
02807             }
02808         }
02809     }
02810 }
02811 
02812 void
02813 SqlStringTest::testSqlStringCastToApprox_Helper(
02814     double value,
02815     char const * const buf,
02816     int src_storage,
02817     int src_len,
02818     bool exceptionExpected)
02819 {
02820     bool caught = false;
02821     double newvalue = 0;
02822     SqlStringBuffer src(
02823         src_storage, src_len,
02824         0, src_storage - src_len,
02825         's', ' ');
02826 
02827 #if 0
02828     BOOST_MESSAGE("buf = |" << buf << "|");
02829     {
02830         char foo[256];
02831         sprintf(foo, "%.8lf", value);
02832         BOOST_MESSAGE("expected value = " << value << " " << foo);
02833     }
02834 #endif
02835     if (strlen(buf) > src_len) {
02836         // not all test cases will fit, just silently ignore them
02837         return;
02838     }
02839 
02840     // copy string, minus null
02841     memcpy(src.mStr, buf, strlen(buf));
02842     // pad out any leftovers with spaces (say, if value is very small for
02843     // string length)
02844     memset(src.mStr + strlen(buf), ' ', src_len - strlen(buf));
02845 #if 0
02846     BOOST_MESSAGE("str = |" << src.mLeftP << "|");
02847 #endif
02848 
02849     try {
02850         newvalue = SqlStrCastToApprox<1,1>(
02851             src.mStr,
02852             src_len);
02853     } catch (const char *str) {
02854         caught = true;
02855         BOOST_CHECK_EQUAL(strcmp(str, "22018"), 0);
02856     }
02857     BOOST_CHECK_EQUAL(caught, exceptionExpected);
02858     if (!caught) {
02859         // absolute epsilon doesn't make sense, must be relative
02860         // to size of numbers being compared. (trying to emulate
02861         // some sort of absolute mantissa, but have exponent adjust
02862         // accordingly.)
02863         double epsilon = fabs(value / 10000);
02864         if (epsilon < 0.0001) {
02865             // set a floor to epsilon so it doesn't get rounded out as well.
02866             epsilon = 0.0001;
02867         }
02868         BOOST_CHECK(fabs(value - newvalue) < epsilon);
02869         BOOST_CHECK(src.verify());
02870     }
02871 }
02872 
02873 // tests varchar case, at least partially, when src_len == src_storage
02874 void
02875 SqlStringTest::testSqlStringCastToApprox()
02876 {
02877     int src_storage, src_len;
02878     char exponent_buf[256];
02879     char decimal_buf[256];
02880     char neg_buf[256];
02881     double orig_value, dec_value, exp_value;
02882     double small_idx;
02883     int leading;
02884     int leadingplus;
02885     int leadingminus;
02886     int beforedec;
02887     int afterdec;
02888     int src_len_left;
02889     int buildlen;
02890     int idx;
02891     int rnd;
02892     int neg_idx;
02893 
02894     src_storage = MAXLEN;
02895     // No point in strings less than 3 bytes long (0.0, +3., -.4 or 1E0 is
02896     // kinda the minimal practial representation)
02897     for (src_storage = 2; src_storage <= 10; src_storage++) {
02898         for (src_len = 2; src_len <= src_storage; src_len++) {
02899             for (leading = 0; leading <= 2; leading++) {
02900                 leadingplus = leadingminus = 0;
02901                 if (leading == 1 && src_len > 2) {
02902                     leadingplus = 1;
02903                 }
02904                 if (leading == 2 && src_len > 2) {
02905                     leadingminus = 1;
02906                 }
02907                 src_len_left = src_len;
02908                 if (leadingplus || leadingminus) {
02909                     src_len_left--;
02910                 }
02911                 for (beforedec = 0; beforedec <= src_len_left; beforedec++) {
02912                     afterdec = src_len_left - beforedec;
02913 
02914 #if 0
02915                     BOOST_MESSAGE("src_storage = " << src_storage);
02916                     BOOST_MESSAGE("src_len = " << src_len);
02917                     BOOST_MESSAGE("leadingplus = " << leadingplus);
02918                     BOOST_MESSAGE("leadingminus = " << leadingminus);
02919                     BOOST_MESSAGE("beforedec = " << beforedec);
02920                     BOOST_MESSAGE("afterdec = " << afterdec);
02921 #endif
02922 
02923                     buildlen = leadingplus + leadingminus + beforedec +
02924                         afterdec;
02925                     BOOST_REQUIRE(buildlen == src_len);
02926 
02927                     string s;
02928                     if (leadingplus) {
02929                         s.append("+");
02930                     }
02931                     if (leadingminus) {
02932                         s.append("-");
02933                     }
02934                     idx = beforedec;
02935                     while (idx-- > 0) {
02936                         rnd = rand() % 10;
02937                         s.append(1, '0' + rnd);
02938                     }
02939                     if (afterdec) {
02940                         s.append(".");
02941                         idx = afterdec - 1;
02942                         while (idx-- > 0) {
02943                             rnd = rand() % 10;
02944                             s.append(1, '0' + rnd);
02945                         }
02946                     }
02947                     sscanf(s.c_str(), "%lf", &orig_value);
02948 
02949                     for (small_idx = 1E+10;
02950                          small_idx > 1E-10;
02951                          small_idx *= 0.01) {
02952                         dec_value = orig_value * small_idx;
02953                         // TODO: This masks the + in string s above.
02954                         sprintf(decimal_buf, "%.8lf", orig_value * small_idx);
02955                         sscanf(decimal_buf, "%lf", &dec_value);
02956                         sprintf(exponent_buf, "%.8E", orig_value * small_idx);
02957                         sscanf(exponent_buf, "%lf", &exp_value);
02958 
02959 #if 0
02960                         BOOST_MESSAGE("s = |" << s << "|");
02961                         BOOST_MESSAGE("exponent_buf = |"<< exponent_buf<< "|");
02962                         BOOST_MESSAGE("dec_value = " << dec_value);
02963                         BOOST_MESSAGE("exp_value = " << exp_value);
02964 #endif
02965 
02966 
02967                         // positive test, "12E34   "
02968                         testSqlStringCastToApprox_Helper(
02969                             exp_value,
02970                             exponent_buf,
02971                             src_storage,
02972                             src_len,
02973                             false);
02974                         // positive test, "12.34   "
02975                         testSqlStringCastToApprox_Helper(
02976                             dec_value,
02977                             decimal_buf,
02978                             src_storage,
02979                             src_len,
02980                             false);
02981 
02982                         // positive test, "   12E34   "
02983                         sprintf(
02984                             exponent_buf, "%10.8E",
02985                             orig_value * small_idx);
02986                         sscanf(exponent_buf, "%lf", &exp_value);
02987                         testSqlStringCastToApprox_Helper(
02988                             exp_value,
02989                             exponent_buf,
02990                             src_storage,
02991                             src_len,
02992                             false);
02993 
02994                         // positive test, "   12.34   "
02995                         sprintf(
02996                             decimal_buf, "%10.8lf",
02997                             orig_value * small_idx);
02998                         sscanf(decimal_buf, "%lf", &dec_value);
02999                         testSqlStringCastToApprox_Helper(
03000                             dec_value,
03001                             decimal_buf,
03002                             src_storage,
03003                             src_len,
03004                             false);
03005 
03006                         // positive test, "00012E34   "
03007                         sprintf(
03008                             exponent_buf, "%010.8E",
03009                             orig_value * small_idx);
03010                         sscanf(exponent_buf, "%lf", &exp_value);
03011                         testSqlStringCastToApprox_Helper(
03012                             exp_value,
03013                             exponent_buf,
03014                             src_storage,
03015                             src_len,
03016                             false);
03017 
03018                         // positive test, "00012.34   "
03019                         sprintf(
03020                             decimal_buf, "%010.8lf",
03021                             orig_value * small_idx);
03022                         sscanf(decimal_buf, "%lf", &dec_value);
03023                         testSqlStringCastToApprox_Helper(
03024                             dec_value,
03025                             decimal_buf,
03026                             src_storage,
03027                             src_len,
03028                             false);
03029 
03030                         // don't do negative tests every time as they
03031                         // are highly highly redundant. good coverage
03032                         // at small sizes, then taper way off.
03033                         if (src_storage < 4 || !(rand() % 10)) {
03034                             // get back to base values
03035                             sprintf(
03036                                 decimal_buf, "%.8lf",
03037                                 orig_value * small_idx);
03038                             sscanf(
03039                                 decimal_buf, "%lf",
03040                                 &dec_value);
03041                             sprintf(
03042                                 exponent_buf, "%.8E",
03043                                 orig_value * small_idx);
03044                             sscanf(exponent_buf, "%lf", &exp_value);
03045                             int exp_len = strlen(exponent_buf);
03046                             int dec_len = strlen(decimal_buf);
03047 
03048                             for (neg_idx = 0;
03049                                  neg_idx < dec_len;
03050                                  neg_idx++)
03051                             {
03052                                 strcpy(neg_buf, decimal_buf);
03053                                 neg_buf[neg_idx] = 'a';
03054                                 testSqlStringCastToApprox_Helper(
03055                                     dec_value,
03056                                     neg_buf,
03057                                     src_storage,
03058                                     src_len,
03059                                     true);
03060                                 if (neg_idx > 1 && neg_idx < dec_len - 1) {
03061                                     // leading and trailing spaces are OK
03062                                     neg_buf[neg_idx] = ' ';
03063                                     testSqlStringCastToApprox_Helper(
03064                                         dec_value,
03065                                         neg_buf,
03066                                         src_storage,
03067                                         src_len,
03068                                         true);
03069                                 }
03070                             }
03071 
03072                             for (neg_idx = 0;
03073                                  neg_idx < exp_len;
03074                                  neg_idx++)
03075                             {
03076                                 strcpy(neg_buf, exponent_buf);
03077                                 neg_buf[neg_idx] = 'a';
03078                                 testSqlStringCastToApprox_Helper(
03079                                     exp_value,
03080                                     neg_buf,
03081                                     src_storage,
03082                                     src_len,
03083                                     true);
03084                                 if (neg_idx > 1 && neg_idx < exp_len - 1) {
03085                                     // leading and trailing spaces are OK
03086                                     neg_buf[neg_idx] = ' ';
03087                                     testSqlStringCastToApprox_Helper(
03088                                         exp_value,
03089                                         neg_buf,
03090                                         src_storage,
03091                                         src_len,
03092                                         true);
03093                                 }
03094                             }
03095 
03096                             // negative test, "    "
03097                             memset(neg_buf, ' ', src_len);
03098                             testSqlStringCastToApprox_Helper(
03099                                 exp_value,
03100                                 neg_buf,
03101                                 src_storage,
03102                                 src_len,
03103                                 true);
03104                         }
03105                     }
03106                 }
03107             }
03108         }
03109     }
03110 }
03111 
03112 void
03113 SqlStringTest::testSqlStringCastFromExact()
03114 {
03115     int src_len;
03116     int dst_storage, dst_len, newlen = 0;
03117     int rand_idx, power_idx;
03118     int negative;
03119     int64_t value, newones;
03120     bool caught;
03121 
03122     // strlen(MAX_VAL(int64_t))=19, strlen(MIN_VAL(int64_t))=20
03123     for (dst_storage = 0; dst_storage <= 22; dst_storage++) {
03124         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
03125             for (src_len = 0; src_len < 19; src_len++) {
03126                 for (rand_idx = 0; rand_idx < 1; rand_idx++) {
03127                     for (negative = 0; negative <= 1; negative++) {
03128                         value = 0;
03129                         for (power_idx = 0;
03130                              power_idx < src_len - negative; // space for '-'
03131                              power_idx++) {
03132                             if (!value) {
03133                                 // no leading zeros
03134                                 newones = rand() % 9 + 1;
03135                             } else {
03136                                 newones = rand() % 10;
03137                             }
03138                             value = value*10 + newones;
03139                         }
03140                         if (!(rand() % 10)) {
03141                             value = 0; // goose odds of 0
03142                         }
03143                         if (negative) {
03144                             value *= -1;
03145                         }
03146 
03147                         ostringstream ostr("");
03148                         ostr << value;
03149                         string expect = ostr.str();
03150                         string expect_fix(expect); // right padded (CHAR)
03151                         if (expect_fix.length() < dst_storage) {
03152                             expect_fix.append(
03153                                 dst_storage -
03154                                 expect_fix.length(),
03155                                 ' ');
03156                         }
03157 
03158                         SqlStringBuffer dst(
03159                             dst_storage, dst_len,
03160                             0, dst_storage - dst_len,
03161                             's', ' ');
03162 
03163                         caught = false;
03164                         try {
03165                             newlen = SqlStrCastFromExact<1,1>(
03166                                 dst.mStr,
03167                                 dst_storage,
03168                                 value,
03169                                 false);
03170                         } catch (const char *str) {
03171                             caught = true;
03172                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
03173                             BOOST_CHECK(expect.length() > dst_storage);
03174                             BOOST_CHECK(dst.verify());
03175                         }
03176                         if (!caught) {
03177                             string result(dst.mStr, newlen);
03178                             BOOST_CHECK(dst.verify());
03179                             BOOST_CHECK(expect.length() <= dst_storage);
03180                             BOOST_CHECK(!expect.compare(result));
03181                         }
03182 
03183                         SqlStringBuffer dst_fix(
03184                             dst_storage, dst_len,
03185                             0, dst_storage - dst_len,
03186                             's', ' ');
03187 
03188                         caught = false;
03189                         try {
03190                             newlen = SqlStrCastFromExact<1,1>(
03191                                 dst_fix.mStr,
03192                                 dst_storage,
03193                                 value,
03194                                 true);
03195                         } catch (const char *str) {
03196                             caught = true;
03197                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
03198                             BOOST_CHECK(expect_fix.length() > dst_storage);
03199                             BOOST_CHECK(dst_fix.verify());
03200                         }
03201                         if (!caught) {
03202                             string result_fix(dst_fix.mStr, newlen);
03203                             BOOST_CHECK(dst_fix.verify());
03204                             BOOST_CHECK(expect_fix.length() <= dst_storage);
03205                             BOOST_CHECK(!expect_fix.compare(result_fix));
03206                         }
03207                     }
03208                 }
03209             }
03210         }
03211     }
03212 }
03213 
03214 void
03215 SqlStringTest::testSqlStringCastFromDecimal()
03216 {
03217     int precision, scale;
03218     int src_len;
03219     int dst_storage, dst_len, newlen = 0;
03220     int rand_idx, power_idx;
03221     int negative;
03222     int64_t value, newones, whole, decimal;
03223     char expected_buf[256];
03224     char digits[] = "0123456789";
03225     bool caught;
03226 
03227     // strlen(MAX_VAL(int64_t))=19, strlen(MIN_VAL(int64_t))=20
03228     for (dst_storage = 0; dst_storage <= 22; dst_storage++) {
03229         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
03230             for (src_len = 0; src_len < 19; src_len++) {
03231                 for (rand_idx = 0; rand_idx < 1; rand_idx++) {
03232                     for (negative = 0; negative <= 1; negative++) {
03233                         precision = src_len;
03234                         value = 0;
03235                         for (power_idx = 0;
03236                              power_idx < src_len - negative; // space for '-'
03237                              power_idx++) {
03238                             if (!value) {
03239                                 // no leading zeros
03240                                 newones = rand() % 9 + 1;
03241                             } else {
03242                                 newones = rand() % 10;
03243                             }
03244                             value = value*10 + newones;
03245                         }
03246                         if (!(rand() % 10)) {
03247                             value = 0; // goose odds of 0
03248                         }
03249                         if (negative) {
03250                             value *= -1;
03251                         }
03252                         scale = rand() % 25 - 5;
03253 
03254                         if (scale == 0) {
03255                             sprintf(expected_buf, "%" FMT_INT64, value);
03256                         } else if (scale > 0) {
03257                             whole = value;
03258                             for (int i = 0; i < scale; i++) {
03259                                 whole /= 10;
03260                             }
03261 
03262                             if (whole != 0) {
03263                                 sprintf(expected_buf, "%" FMT_INT64, whole);
03264                             } else {
03265                                 if (value < 0) {
03266                                     expected_buf[0] = '-';
03267                                     expected_buf[1] = '\0';
03268                                 } else {
03269                                     expected_buf[0] = '\0';
03270                                 }
03271                             }
03272 
03273                             for (int i = 0; i < scale; i++) {
03274                                 whole *= 10;
03275                             }
03276                             decimal = abs(value - whole);
03277 
03278                             int len = strlen(expected_buf);
03279                             expected_buf[len] = '.';
03280                             for (int i = scale-1; i >= 0; i--) {
03281                                 expected_buf[len + i + 1] =
03282                                     digits[decimal % 10];
03283                                 decimal /= 10;
03284                             }
03285                             expected_buf[len+scale+1] = '\0';
03286                         } else if (scale < 0) {
03287                             sprintf(expected_buf, "%" FMT_INT64, value);
03288                             if (value != 0) {
03289                                 int len = strlen(expected_buf);
03290                                 memset(expected_buf + len, '0', -scale);
03291                                 expected_buf[len - scale] = '\0';
03292                             }
03293                         }
03294 
03295                         string expect(expected_buf);
03296                         string expect_fix(expect); // right padded (CHAR)
03297                         if (expect_fix.length() < dst_storage) {
03298                             expect_fix.append(
03299                                 dst_storage -
03300                                 expect_fix.length(),
03301                                 ' ');
03302                         }
03303 
03304                         SqlStringBuffer dst(
03305                             dst_storage, dst_len,
03306                             0, dst_storage - dst_len,
03307                             's', ' ');
03308 
03309                         caught = false;
03310                         try {
03311                             newlen = SqlStrCastFromExact<1,1>(
03312                                 dst.mStr,
03313                                 dst_storage,
03314                                 value,
03315                                 precision,
03316                                 scale,
03317                                 false);
03318                         } catch (const char *str) {
03319                             caught = true;
03320                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
03321                             BOOST_CHECK(expect.length() > dst_storage);
03322                             BOOST_CHECK(dst.verify());
03323                         }
03324                         if (!caught) {
03325                             string result(dst.mStr, newlen);
03326                             BOOST_CHECK(dst.verify());
03327                             BOOST_CHECK(expect.length() <= dst_storage);
03328                             BOOST_CHECK(!expect.compare(result));
03329                         }
03330 
03331                         SqlStringBuffer dst_fix(
03332                             dst_storage, dst_len,
03333                             0, dst_storage - dst_len,
03334                             's', ' ');
03335 
03336                         caught = false;
03337                         try {
03338                             newlen = SqlStrCastFromExact<1,1>(
03339                                 dst_fix.mStr,
03340                                 dst_storage,
03341                                 value,
03342                                 precision,
03343                                 scale,
03344                                 true);
03345                         } catch (const char *str) {
03346                             caught = true;
03347                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
03348                             BOOST_CHECK(expect_fix.length() > dst_storage);
03349                             BOOST_CHECK(dst_fix.verify());
03350                         }
03351                         if (!caught) {
03352                             string result_fix(dst_fix.mStr, newlen);
03353                             BOOST_CHECK(dst_fix.verify());
03354                             BOOST_CHECK(expect_fix.length() <= dst_storage);
03355                             BOOST_CHECK(!expect_fix.compare(result_fix));
03356                         }
03357                     }
03358                 }
03359             }
03360         }
03361     }
03362 }
03363 
03364 void
03365 SqlStringTest::testSqlStringCastFromApprox()
03366 {
03367     int src_len;
03368     int dst_storage, dst_len, newlen = 0;
03369     int rand_idx, power_idx;
03370     int negative;
03371     int isFloat;
03372     int max_precision;
03373     double value, newones, exponent;
03374     char expected_buf[256];
03375     bool caught;
03376 
03377     // strlen(%E.16) = 22
03378     for (dst_storage = 0; dst_storage <= 24; dst_storage++) {
03379         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
03380             // double seems to have ~16 digits of precision
03381             for (src_len = 0; src_len < 16; src_len++) {
03382                 for (rand_idx = 0; rand_idx < 1; rand_idx++) {
03383                     for (negative = 0; negative <= 1; negative++) {
03384                         value = 0;
03385                         for (power_idx = 0;
03386                              // space for (optional) '-' '.', 'E+xx'
03387                              power_idx < src_len - (negative + 5);
03388                              power_idx++) {
03389                             if (!value) {
03390                                 // no leading zeros
03391                                 newones = rand() % 9 + 1;
03392                             } else {
03393                                 newones = rand() % 10;
03394                             }
03395                             value = value*10 + newones;
03396                         }
03397                         if (!(rand() % 10)) {
03398                             value = 0; // goose odds of 0
03399                         }
03400                         if (negative) {
03401                             value *= -1;
03402                         }
03403                         // get some exponent on.
03404                         exponent = 1 + rand() % 30;
03405                         if (!(rand() % 2)) {
03406                             exponent *= -1;
03407                         }
03408                         value = pow(value, 1 + rand() % 80);
03409 
03410                         isFloat = rand() % 2;
03411                         if (isFloat) {
03412                             value = (float) value;
03413                         }
03414                         max_precision = (isFloat) ? 7 : 16;
03415 
03416                         if (value > std::numeric_limits<double>::max()) {
03417                             strcpy(expected_buf, "INF");
03418                         } else if (value
03419                                    < -std::numeric_limits<double>::max())
03420                         {
03421                             strcpy(expected_buf, "-INF");
03422                         } else if (value) {
03423                             int i, epos = -1, prec = 0, buflen, exp;
03424                             int neg = (value < 0) ? 1 : 0;
03425                             char last_digit = 0;
03426                             sprintf(expected_buf, "%.*E", max_precision, value);
03427                             buflen = strlen(expected_buf);
03428                             epos = neg + max_precision + 2;
03429                             if (buflen > epos && expected_buf[epos] == 'E') {
03430                                 sscanf(expected_buf + epos + 1, "%d", &exp);
03431 
03432                                 // Round up if needed
03433                                 if ((expected_buf[epos - 1] >= '5') &&
03434                                     (expected_buf[epos - 1] <= '9'))
03435                                 {
03436                                     expected_buf[epos - 1] = '0';
03437                                     for (int i = epos - 2; i >= neg; i--) {
03438                                         if (expected_buf[i] == '9') {
03439                                             expected_buf[i] = '0';
03440                                         } else if (expected_buf[i] != '.') {
03441                                             expected_buf[i]++;
03442                                             break;
03443                                         }
03444                                     }
03445 
03446                                     // See if initial digit overflowed
03447                                     if (expected_buf[neg] == '0') {
03448                                         expected_buf[neg] = '1';
03449                                         for (int i = epos - 1; i > neg + 2;
03450                                              i--)
03451                                         {
03452                                             expected_buf[i] =
03453                                                 expected_buf[i - 1];
03454                                         }
03455                                         expected_buf[neg + 2] = '0';
03456 
03457                                         // increment exponent
03458                                         exp++;
03459                                     }
03460                                 }
03461 
03462                                 for (i = epos - 2; i >= 0; i--) {
03463                                     if (expected_buf[i] != '0') {
03464                                         if (expected_buf[i] == '.') {
03465                                             BOOST_CHECK_EQUAL(i, 1 + neg);
03466                                             last_digit = expected_buf[i - 1];
03467                                         } else {
03468                                             last_digit = expected_buf[i];
03469                                         }
03470                                         prec = i - 1 - neg;
03471                                         break;
03472                                     }
03473                                 }
03474                                 sprintf(expected_buf, "%.*E", prec, value);
03475                                 buflen = strlen(expected_buf);
03476                                 epos =
03477                                     (prec > 0) ? (neg + prec + 2) : (neg + 1);
03478                                 BOOST_CHECK(buflen > epos);
03479                                 BOOST_CHECK(expected_buf[epos] == 'E');
03480                                 expected_buf[epos - 1] = last_digit;
03481                                 sprintf(expected_buf + epos + 1, "%d", exp);
03482                             }
03483                         } else {
03484                             // per spec, 0 -> '0E0'
03485                             strcpy(expected_buf, "0E0");
03486                         }
03487 
03488                         string expect(expected_buf);
03489                         string expect_fix(expect); // right padded (CHAR)
03490                         if (expect_fix.length() < dst_storage) {
03491                             expect_fix.append(
03492                                 dst_storage -
03493                                 expect_fix.length(),
03494                                 ' ');
03495                         }
03496 
03497 #if 0
03498                         BOOST_MESSAGE("value = " << value);
03499                         BOOST_MESSAGE("storage = " << dst_storage <<
03500                                       " len = " << dst_len <<
03501                                       " src_len = " << src_len);
03502                         BOOST_MESSAGE("expect = |" << expect << "|");
03503                         BOOST_MESSAGE("expect_fix = |" << expect_fix << "|");
03504 #endif
03505 
03506                         SqlStringBuffer dst(
03507                             dst_storage, dst_len,
03508                             0, dst_storage - dst_len,
03509                             's', ' ');
03510 
03511                         caught = false;
03512                         try {
03513                             newlen = SqlStrCastFromApprox<1,1>(
03514                                 dst.mStr,
03515                                 dst_storage,
03516                                 value,
03517                                 isFloat,
03518                                 false);
03519                         } catch (const char *str) {
03520                             caught = true;
03521                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
03522                             BOOST_CHECK(expect.length() > dst_storage);
03523                             BOOST_CHECK(dst.verify());
03524                         }
03525                         if (!caught) {
03526                             string result(dst.mStr, newlen);
03527                             //BOOST_MESSAGE("result = |" << result << "|");
03528                             BOOST_CHECK(dst.verify());
03529                             BOOST_CHECK(expect.length() <= dst_storage);
03530                             BOOST_CHECK(!expect.compare(result));
03531                             if (expect.compare(result)) {
03532                                 BOOST_MESSAGE("Got " << result <<
03533                                     ", expected " << expect <<
03534                                     ", value " << value);
03535                             }
03536                         }
03537 
03538                         SqlStringBuffer dst_fix(
03539                             dst_storage, dst_len,
03540                             0, dst_storage - dst_len,
03541                             's', ' ');
03542 
03543                         caught = false;
03544                         try {
03545                             newlen = SqlStrCastFromApprox<1,1>(
03546                                 dst_fix.mStr,
03547                                 dst_storage,
03548                                 value,
03549                                 isFloat,
03550                                 true);
03551                         } catch (const char *str) {
03552                             caught = true;
03553                             BOOST_CHECK_EQUAL(strcmp(str, "22001"), 0);
03554                             BOOST_CHECK(expect_fix.length() > dst_storage);
03555                             BOOST_CHECK(dst_fix.verify());
03556                         }
03557                         if (!caught) {
03558                             string result_fix(dst_fix.mStr, newlen);
03559                             BOOST_CHECK(dst_fix.verify());
03560                             BOOST_CHECK(expect_fix.length() <= dst_storage);
03561                             BOOST_CHECK(!expect_fix.compare(result_fix));
03562                         }
03563                     }
03564                 }
03565             }
03566         }
03567     }
03568 }
03569 
03570 
03571 void
03572 SqlStringTest::testSqlStringCastToVarChar()
03573 {
03574     int src_storage, dst_storage, src_len, dst_len;
03575 
03576     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
03577         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
03578             for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
03579                 for (src_len = 0; src_len <= src_storage; src_len++) {
03580                     // ASCII
03581 
03582                     SqlStringBuffer dst(
03583                         dst_storage, dst_len,
03584                         0, dst_storage - dst_len,
03585                         'd', ' ');
03586 
03587                     SqlStringBuffer src(
03588                         src_storage, src_len,
03589                         0, src_storage - src_len,
03590                         's', ' ');
03591 
03592                     int rightTruncWarning = 0;
03593                     try {
03594                         SqlStrCastToVarChar<1,1>(
03595                             dst.mStr,
03596                             dst_storage,
03597                             src.mStr,
03598                             src_len,
03599                             &rightTruncWarning);
03600                     } catch (...) {
03601                         BOOST_CHECK(false);
03602                     }
03603 
03604                     BOOST_CHECK(
03605                         (src_len <= dst_storage && !rightTruncWarning)
03606                         || (src_len > dst_storage && rightTruncWarning));
03607 
03608                     string expect;
03609                     expect.append(min(src_len, dst_storage), 's');
03610 
03611                     if (dst_storage > src_len) {
03612                         expect.append(dst_storage - src_len, ' ');
03613                     }
03614 
03615                     string result(dst.mStr, dst_storage);
03616 
03617 #if 0
03618                     BOOST_MESSAGE(" dst_storage=" << dst_storage <<
03619                                   " dst_len=" << dst_len <<
03620                                   " src_storage=" << src_storage <<
03621                                   " src_len=" << src_len);
03622                     BOOST_MESSAGE("src =|" << src.mLeftP << "|");
03623                     BOOST_MESSAGE("expect |" << expect << "|");
03624                     BOOST_MESSAGE("result |" << result << "|");
03625 #endif
03626 
03627                     BOOST_CHECK(!result.compare(expect));
03628 
03629                     BOOST_CHECK(dst.verify());
03630                     BOOST_CHECK(src.verify());
03631 
03632                     // REVIEW: SZ: 8/10/2004: add testing UCS2 support
03633                     // once it exists.
03634                 }
03635             }
03636         }
03637     }
03638 }
03639 
03640 
03641 void
03642 SqlStringTest::testSqlStringCastToChar()
03643 {
03644     int src_storage, dst_storage, src_len, dst_len, new_len = 0;
03645 
03646     // REVIEW: SZ: 8/10/2004: I believe that we should also test
03647     // unpadded varchars -- e.g. where src_storage > src_len and
03648     // left_padding == right_padding = 0.  The cast behaves
03649     // differently in this case, but SqlStringBuffer asserts when
03650     // length + padding != storage
03651 
03652     for (dst_storage = 0; dst_storage < MAXLEN; dst_storage++) {
03653         for (dst_len = 0; dst_len <= dst_storage; dst_len++) {
03654             for (src_storage = 0; src_storage < MAXLEN; src_storage++) {
03655                 for (src_len = 0; src_len <= src_storage; src_len++) {
03656                     // ASCII
03657 
03658                     SqlStringBuffer dst(
03659                         dst_storage, dst_len,
03660                         0, dst_storage - dst_len,
03661                         'd', ' ');
03662 
03663                     SqlStringBuffer src(
03664                         src_storage, src_len,
03665                         0, src_storage - src_len,
03666                         's', ' ');
03667 
03668                     int rightTruncWarning = 0;
03669 
03670                     try {
03671                         new_len = SqlStrCastToChar<1,1>(
03672                             dst.mStr,
03673                             dst_storage,
03674                             src.mStr,
03675                             src_len,
03676                             &rightTruncWarning);
03677                     } catch (...) {
03678                         BOOST_CHECK(false);
03679                     }
03680 
03681                     BOOST_CHECK(
03682                         (src_len <= dst_storage && !rightTruncWarning)
03683                         || (src_len > dst_storage && rightTruncWarning));
03684                     BOOST_CHECK_EQUAL(new_len, dst_storage);
03685 
03686                     string expect;
03687                     expect.append(min(src_len, dst_storage), 's');
03688 
03689                     if (dst_storage > src_len) {
03690                         expect.append(dst_storage - src_len, ' ');
03691                     }
03692 
03693                     string result(dst.mStr, dst_storage);
03694 
03695 #if 0
03696                     BOOST_MESSAGE(" dst_storage=" << dst_storage <<
03697                                   " dst_len=" << dst_len <<
03698                                   " src_storage=" << src_storage <<
03699                                   " src_len=" << src_len);
03700                     BOOST_MESSAGE("src =|" << src.mLeftP << "|");
03701                     BOOST_MESSAGE("expect |" << expect << "|");
03702                     BOOST_MESSAGE("result |" << result << "|");
03703 #endif
03704 
03705                     BOOST_CHECK(!result.compare(expect));
03706 
03707                     BOOST_CHECK(dst.verify());
03708                     BOOST_CHECK(src.verify());
03709 
03710                     // REVIEW: SZ: 8/10/2004: add testing UCS2 support
03711                     // once it exists.
03712                 }
03713             }
03714         }
03715     }
03716 }
03717 
03718 
03719 FENNEL_UNIT_TEST_SUITE(SqlStringTest);
03720 
03721 // End SqlStringTest.cpp

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