SqlDateTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calctest/SqlDateTest.cpp#2 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/test/TestBase.h"
00026 #include "fennel/calculator/SqlDate.h"
00027 #include "fennel/common/TraceSource.h"
00028 #include "fennel/calctest/SqlStringBuffer.h"
00029 #include <boost/test/test_tools.hpp>
00030 #include <boost/scoped_array.hpp>
00031 #include <string>
00032 #include <limits>
00033 #include <iostream>
00034 
00035 #ifdef HAVE_ICU
00036 #include <unicode/unistr.h>
00037 #include <unicode/uloc.h>
00038 #endif
00039 
00040 using namespace fennel;
00041 using namespace std;
00042 
00043 
00044 static const int MAXLEN = 8;   // Must not be less than 5. Best >=7.
00045 static const int MAXRANDOM = 5;
00046 static const int MAXCMPLEN = 8;  // Must not be less than 3.
00047 
00048 
00049 static int64_t const ticks_per_day =
00050     boost::posix_time::ptime::time_rep_type::frac_sec_per_day();
00051 static int64_t const ticks_per_year = ticks_per_day * 365LL;
00052 static int64_t const ticks_per_month = ticks_per_day * 31LL;
00053 static int64_t const ticks_per_hour = ticks_per_day / 24;
00054 static int64_t const ticks_per_minute = ticks_per_hour / 60;
00055 static int64_t const ticks_per_sec = ticks_per_minute / 60;
00056 
00057 enum SqlStrToDateConvAction {
00058     StrToDate,
00059     StrToTime,
00060     StrToTimestamp
00061 };
00062 
00063 class SqlDateTest : virtual public TestBase, public TraceSource
00064 {
00065 
00066     void testSqlDateToStr_Ascii();
00067     void testSqlTimeToStr_Ascii();
00068     void appendCharsToUCS2LikeString(
00069         string& str,
00070         int number,
00071         char character);
00072 
00073     void testSqlStrToDate_Ascii_Helper(
00074         SqlStrToDateConvAction action,
00075         uint64_t value,
00076         char const * const src,
00077         int len,
00078         bool errorExpected);
00079     void testSqlStrToDate_Ascii();
00080 
00081     void testLocalTime();
00082     void testUniversalTime();
00083 
00084 #ifdef HAVE_ICU
00085     string UnicodeToPrintable(const UnicodeString &s);
00086 #endif
00087 
00088 
00089 public:
00090     explicit SqlDateTest()
00091         : TraceSource(shared_from_this(),"SqlDateTest")
00092     {
00093         srand(time(NULL));
00094         FENNEL_UNIT_TEST_CASE(SqlDateTest, testSqlDateToStr_Ascii);
00095         FENNEL_UNIT_TEST_CASE(SqlDateTest, testSqlTimeToStr_Ascii);
00096         // FENNEL_UNIT_TEST_CASE(SqlDateTest, testSqlTimeStampToStr_Ascii);
00097         FENNEL_UNIT_TEST_CASE(SqlDateTest, testSqlStrToDate_Ascii);
00098         // FENNEL_UNIT_TEST_CASE(SqlDateTest, testSqlStrToTime_Ascii);
00099         // FENNEL_UNIT_TEST_CASE(SqlDateTest, testSqlStrToTimestamp_Ascii);
00100         FENNEL_UNIT_TEST_CASE(SqlDateTest, testLocalTime);
00101     }
00102 
00103     virtual ~SqlDateTest()
00104     {
00105     }
00106 };
00107 
00108 #ifdef HAVE_ICU
00109 // Note: Assumes that only ASCII chars are represented
00110 string
00111 SqlDateTest::UnicodeToPrintable(const UnicodeString &s) {
00112     ostringstream o;
00113     int32_t i, length;
00114     char tmp;
00115 
00116     // output the code units (not code points)
00117     length = s.length();
00118     for (i = 0; i < length; ++i) {
00119         tmp = s.charAt(i) & 0xff;
00120         o << i << "=" << tmp << " | ";
00121     }
00122     return o.str();
00123 }
00124 #endif
00125 
00126 // build these strings by hand, not using ICU, so we're also
00127 // testing that ICU is integrated and working correctly.
00128 void
00129 SqlDateTest::appendCharsToUCS2LikeString(
00130     string& str,
00131     int number,
00132     char character)
00133 {
00134     int i;
00135     for (i = 0; i < number; i++) {
00136 #ifdef LITTLEENDIAN
00137         str.push_back(character);
00138         str.push_back(0);
00139 #else
00140         str.push_back(0);
00141         str.push_back(character);
00142 #endif
00143     }
00144 }
00145 
00146 void
00147 SqlDateTest::testSqlDateToStr_Ascii()
00148 {
00149     int storage;
00150     int leftbump = 2;
00151     int rightbump = 2;
00152 
00153     SqlStringBuffer s1(
00154         10, 10,
00155         0, 0,
00156         'x', ' ',
00157         leftbump, rightbump);
00158 
00159     storage = 10;
00160     SqlDateToStr<1,1,SQLDATE>(s1.mStr, storage, 0);
00161     BOOST_CHECK(s1.verify());
00162     SqlDateToStr<1,1,SQLDATE>(s1.mStr, storage, ticks_per_day);
00163     BOOST_CHECK(s1.verify());
00164     SqlDateToStr<1,1,SQLDATE>(s1.mStr, storage, ticks_per_month);
00165     BOOST_CHECK(s1.verify());
00166 
00167     int size, leftpad, rightpad;
00168     for (storage = 5; storage <= 15; storage++) {
00169         for (size = 0; size <= storage; size++) {
00170             for (leftpad = 0; leftpad <= storage - size; leftpad++) {
00171                 rightpad = (storage - size) - leftpad;
00172 
00173                 SqlStringBuffer t(
00174                     storage, size,
00175                     leftpad, rightpad,
00176                     'x', ' ',
00177                     leftbump, rightbump);
00178 
00179                 bool caught = false;
00180                 try {
00181                     SqlDateToStr<1,1,SQLDATE>(
00182                         t.mStr,
00183                         storage,
00184                         ticks_per_year
00185                         + size * ticks_per_month
00186                         + storage * ticks_per_day);
00187                 } catch (const char *str) {
00188                     caught = true;
00189                     BOOST_CHECK_EQUAL(strcmp(str,"22001"),0);
00190                     BOOST_CHECK(t.verify());
00191                     BOOST_CHECK(storage < 10);
00192                 } catch (...) {
00193                     BOOST_CHECK(false);
00194                 }
00195                 if (!caught) {
00196                     BOOST_CHECK(t.verify());
00197                     //                    cout << t.mStr << endl;
00198                 }
00199             }
00200         }
00201     }
00202 }
00203 
00204 void
00205 SqlDateTest::testSqlTimeToStr_Ascii()
00206 {
00207     int storage ;
00208     int leftbump = 2;
00209     int rightbump = 2;
00210 
00211     SqlStringBuffer s1(
00212         10, 10,
00213         0, 0,
00214         'x', ' ',
00215         leftbump, rightbump);
00216 
00217     storage = 10;
00218     SqlDateToStr<1,1,SQLTIME>(s1.mStr, storage, 0);
00219     BOOST_CHECK(s1.verify());
00220     SqlDateToStr<1,1,SQLTIME>(s1.mStr, storage, ticks_per_hour);
00221     BOOST_CHECK(s1.verify());
00222     SqlDateToStr<1,1,SQLTIME>(s1.mStr, storage, 13LL * ticks_per_hour);
00223     BOOST_CHECK(s1.verify());
00224     SqlDateToStr<1,1,SQLTIME>(s1.mStr, storage, 1000*57601000LL);
00225     BOOST_CHECK(s1.verify());
00226     //    cout << s1.mStr << endl;
00227 
00228     int size, leftpad, rightpad;
00229     for (storage = 5; storage <= 15; storage++) {
00230         for (size = 0; size <= storage; size++) {
00231             for (leftpad = 0; leftpad <= storage - size; leftpad++) {
00232                 rightpad = (storage - size) - leftpad;
00233 
00234                 SqlStringBuffer t(
00235                     storage, size,
00236                     leftpad, rightpad,
00237                     'x', ' ',
00238                     leftbump, rightbump);
00239 
00240                 bool caught = false;
00241                 try {
00242                     SqlDateToStr<1,1,SQLTIME>(
00243                         t.mStr,
00244                         storage,
00245                         ticks_per_hour
00246                         + size * ticks_per_minute
00247                         + storage * ticks_per_sec);
00248                 } catch (const char *str) {
00249                     caught = true;
00250                     BOOST_CHECK_EQUAL(strcmp(str,"22001"),0);
00251                     BOOST_CHECK(t.verify());
00252                     BOOST_CHECK(storage < 10);
00253                 } catch (...) {
00254                     BOOST_CHECK(false);
00255                 }
00256                 if (!caught) {
00257                     BOOST_CHECK(t.verify());
00258                     //              cout << t.mStr << endl;
00259                 }
00260             }
00261         }
00262     }
00263 }
00264 
00265 
00266 // Helper to testSqlStrToDate_Ascii
00267 void
00268 SqlDateTest::testSqlStrToDate_Ascii_Helper(
00269     SqlStrToDateConvAction action,
00270     uint64_t value,
00271     char const * const src,
00272     int len,
00273     bool errorExpected)
00274 
00275 {
00276     int64_t t = 0;
00277     bool caught = false;
00278 
00279     try {
00280         switch (action) {
00281         case StrToDate:
00282             t = IsoStringToDate(src, len);
00283             break;
00284         case StrToTime:
00285             t = IsoStringToTime(src, len);
00286             break;
00287         case StrToTimestamp:
00288             t = IsoStringToTimestamp(src, len);
00289             break;
00290         default:
00291             permAssert(false);
00292         }
00293     } catch (const char *str) {
00294         caught = true;
00295         BOOST_CHECK_EQUAL(strcmp(str, "22007"), 0);
00296     } catch (...) {
00297         // unexpected exception
00298         BOOST_CHECK(false);
00299     }
00300     BOOST_CHECK_EQUAL(errorExpected, caught);
00301     if (!caught) {
00302         BOOST_CHECK_EQUAL(value, t);
00303     }
00304 }
00305 
00306 
00307 
00308 void
00309 SqlDateTest::testSqlStrToDate_Ascii()
00310 {
00311     int64_t oct2k = 972086400000LL; // GMT + 0; - in milliseconds
00312     testSqlStrToDate_Ascii_Helper(
00313         StrToDate, oct2k, "2000-10-21", 10, false);
00314     testSqlStrToDate_Ascii_Helper(
00315         StrToDate, oct2k, "  2000-10-21  ", 14, false);
00316     testSqlStrToDate_Ascii_Helper(
00317         StrToDate, oct2k, "junk", 4, true);
00318     testSqlStrToDate_Ascii_Helper(
00319         StrToDate, oct2k, "2000-23-23", 10, true);
00320     testSqlStrToDate_Ascii_Helper(
00321         StrToDate, oct2k, "2000-2-30", 10, true);
00322 
00323     int64_t fourteen21 =
00324         (ticks_per_hour * 14 +
00325          ticks_per_minute * 21 +
00326          ticks_per_sec * 1) / 1000;
00327     testSqlStrToDate_Ascii_Helper(
00328         StrToTime, fourteen21, "14:21:01", 8, false);
00329     testSqlStrToDate_Ascii_Helper(
00330         StrToTime, fourteen21, "14:21:1", 7, false);
00331     testSqlStrToDate_Ascii_Helper(
00332         StrToTime, fourteen21, "  14:21:01  ", 12, false);
00333     // TODO: Fractional seconds not handled
00334     //testSqlStrToDate_Ascii_Helper(
00335     //    StrToTime, fourteen21 + 987, "  14:21:01.987  ", 12, false);
00336     testSqlStrToDate_Ascii_Helper(
00337         StrToTime, fourteen21, "12:61:01", 8, true);
00338     testSqlStrToDate_Ascii_Helper(
00339         StrToTime, fourteen21, "junk", 4, true);
00340     testSqlStrToDate_Ascii_Helper(
00341         StrToTime, fourteen21, "12:34", 5, true);
00342 
00343     int64_t ts = oct2k + fourteen21;
00344     testSqlStrToDate_Ascii_Helper(
00345         StrToTimestamp, ts, "2000-10-21 14:21:01", 19, false);
00346     testSqlStrToDate_Ascii_Helper(
00347         StrToTimestamp, ts, "2000-10-21 14:21:1", 18, false);
00348     // TODO: Fractional seconds not handled
00349     //testSqlStrToDate_Ascii_Helper(
00350     //    StrToTimestamp, ts + 323, "2000-10-21 14:21:01.323", 19, false);
00351     testSqlStrToDate_Ascii_Helper(
00352         StrToTimestamp, ts, "  2000-10-21 14:21:01  ", 23, false);
00353     testSqlStrToDate_Ascii_Helper(
00354         StrToTimestamp, ts, "2000-10-21 27:21:01", 19, true);
00355     testSqlStrToDate_Ascii_Helper(
00356         StrToTimestamp, ts, "2000-10-32 01:21:01", 19, true);
00357     testSqlStrToDate_Ascii_Helper(
00358         StrToTimestamp, ts, "junk", 4, true);
00359     testSqlStrToDate_Ascii_Helper(
00360         StrToTimestamp, ts, "2323-6-25", 9, true);
00361 }
00362 
00363 
00364 void
00365 SqlDateTest::testUniversalTime()
00366 {
00367     int64_t t = UniversalTime();
00368     int64_t ts = UniversalTimestamp();
00369 
00370     cout << "UniversalTime = " << t << endl;
00371     cout << "UniversalTimestamp = " << ts << endl;
00372 }
00373 
00374 void
00375 SqlDateTest::testLocalTime()
00376 {
00377     boost::local_time::time_zone_ptr tzPST(
00378         new boost::local_time::posix_time_zone(
00379             std::string("PST-8PDT,M3.2.0,M11.1.0")));
00380     boost::local_time::time_zone_ptr tzUTC(
00381         new boost::local_time::posix_time_zone(
00382             std::string("UTC0")));
00383     boost::local_time::time_zone_ptr tzJST(
00384         new boost::local_time::posix_time_zone(
00385             std::string("JST9")));
00386 
00387     int64_t tPST = LocalTime(tzPST);
00388     int64_t tJST = LocalTime(tzJST);
00389     int64_t tUTC = LocalTime(tzUTC);
00390     int64_t tsPST = LocalTimestamp(tzPST);
00391     int64_t tsJST = LocalTimestamp(tzJST);
00392     int64_t tsUTC = LocalTimestamp(tzUTC);
00393 
00394     cout << "LocalTime(PST) = " << tPST << endl;
00395     cout << "LocalTime(JST) = " << tJST << endl;
00396     cout << "LocalTime(UTC) = " << tUTC << endl;
00397     cout << "LocalTimestamp(PST) = " << tsPST << endl;
00398     cout << "LocalTimestamp(JST) = " << tsJST << endl;
00399     cout << "LocalTimestamp(UTC) = " << tsUTC << endl;
00400 }
00401 
00402 FENNEL_UNIT_TEST_SUITE(SqlDateTest);
00403 
00404 // End SqlDateTest.cpp
00405 

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