/* Copyright (C) 2014 InfiniDB, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * $Id$ */ #include #include using namespace std; #include #include "dataconvert.h" #include "funchelpers.h" using namespace funcexp; using namespace dataconvert; #define MAX_DAY_NUMBER 3652424L #include "functioncolumn.h" #include "intervalcolumn.h" using namespace execplan; #include "timeextract.h" class FuncExpTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( FuncExpTest ); CPPUNIT_TEST( fe_getnumbertest ); CPPUNIT_TEST( fe_strtodatetest ); CPPUNIT_TEST( fe_dateaddtest ); CPPUNIT_TEST( fe_daynametest ); CPPUNIT_TEST( fe_fromunixtimetest ); CPPUNIT_TEST_SUITE_END(); private: public: void setUp() { } void tearDown() { } void show_datetime_debugs( const string & nm, const DateTime& d1 ) { cout << nm << ".day = " << setw(10) << d1.day << endl; cout << nm << ".month = " << setw(10) << d1.month << endl; cout << nm << ".year = " << setw(10) << d1.year << endl; cout << nm << ".hour = " << setw(10) << d1.hour << endl; cout << nm << ".minute = " << setw(10) << d1.minute << endl; cout << nm << ".second = " << setw(10) << d1.second << endl; cout << nm << ".msecond = " << setw(10) << d1.msecond << endl; } void fe_strtodatetest() { struct DateCheck { const char* inputstr; const char* formatstr; DateTime date; }; DateCheck date_tests[] = { { "2009","%Y",DateTime(2009,0,0,0,0,0,0) } , { " 2009","%Y",DateTime(2009,0,0,0,0,0,0) } , { " 2009"," %Y",DateTime(2009,0,0,0,0,0,0) } , { "jan","%b",DateTime(0,1,0,0,0,0,0) } , { "2009feb","%Y%b",DateTime(2009,2,0,0,0,0,0) } , { " 2009 ApR"," %Y %b",DateTime(2009,4,0,0,0,0,0) } , { "200910","%Y%m",DateTime(2009,10,0,0,0,0,0) } , { " 2009 10"," %Y %m",DateTime(2009,10,0,0,0,0,0) } , { "200910","%Y%c",DateTime(2009,10,0,0,0,0,0) } , { " 2009 10"," %Y %c",DateTime(2009,10,0,0,0,0,0) } , { "01,5,2013","%d,%m,%Y",DateTime(2013,5,1,0,0,0,0) }, { "01,5,2013","%e,%m,%Y",DateTime(2013,5,1,0,0,0,0) }, { "7,5th,2012","%m,%D,%Y",DateTime(2012,7,5,0,0,0,0) }, { "a09:30:17","a%h:%i",DateTime(0,0,0,9,30,0,0) } , { "a09:30:17","%h:%i",DateTime(0,0,0,0,0,0,0) } , { "9:30.170","%h:%i.%f",DateTime(0,0,0,9,30,0,170000) } , { "178546 17","%f %H",DateTime(0,0,0,17,0,0,178546) } , { "2009march415","%Y%b",DateTime(2009,3,0,0,0,0,0) } , { " 2009 July"," %Y %b",DateTime(2009,7,0,0,0,0,0) } , { "09 pm","%h %p",DateTime(0,0,0,21,0,0,0) } , { "09:13:14pm","%r",DateTime(0,0,0,9,13,14,0) } , { "12:13:14am","%r",DateTime(0,0,0,12,13,14,0) } , { "92"," %Y",DateTime(1992,0,0,0,0,0,0) } , { "9"," %Y",DateTime(2009,0,0,0,0,0,0) } , { "2013 31","%Y %j",DateTime(2013,1,31,0,0,0,0) } , { "2013 1 3","%Y %U %w",DateTime(2013,1,9,0,0,0,0) } , { "2013 1 3","%Y %u %w",DateTime(2013,1,9,0,0,0,0) } , { "2007 1 3","%Y %U %w",DateTime(2007,1,10,0,0,0,0) } , { "2007 1 3","%Y %u %w",DateTime(2007,1,3,0,0,0,0) } , { "2013 1 3","%X %V %w",DateTime(2013,1,9,0,0,0,0) } , { "2013 1 3","%X %v %w",DateTime(2013,1,9,0,0,0,0) } , { "2007 1 3","%X %V %w",DateTime(2007,1,10,0,0,0,0) } , { "2007 1 3","%X %v %w",DateTime(2007,1,3,0,0,0,0) } , { "33:30.170","%h:%i.%f",DateTime(0,0,0,0,0,0,0) } , { "01,25,2013","%d,%m,%Y",DateTime(0,0,0,0,0,0,0) }, { "%09:30:17","%%%h:%i:%s",DateTime(0,0,0,9,30,17,0) } , { "2009 foobar","%Y",DateTime(2009,0,0,0,0,0,0) } , { "2009-12-31","%h:%i:%s %p",DateTime(0,0,0,0,0,0,0) } , { "12:00:01 AM","%h:%i:%s %p",DateTime(0,0,0,0,0,1,0) } , { "12:00:01 PM","%h:%i:%s %p",DateTime(0,0,0,12,0,1,0) } , { "11:00:01 PM","%h:%i:%s %p",DateTime(0,0,0,23,0,1,0) } , { "11:00:01 AM","%h:%i:%s %p",DateTime(0,0,0,11,0,1,0) } , { "10000-01-02","%Y:%m:%d",DateTime(0,0,0,0,0,0,0) } , }; for (unsigned i = 0; i < sizeof(date_tests)/sizeof(DateCheck); i++) { DateTime dt; dt.year = 0; dt.month = 0; dt.day = 0; dt.hour = 0; dt.minute = 0; dt.second = 0; dt.msecond = 0; TimeExtractor extractor; int ret = extractor.extractTime(date_tests[i].inputstr,date_tests[i].formatstr,dt); if( ret != 0 ) cout << "Extractor reported error for " << date_tests[i].inputstr << "," << date_tests[i].formatstr << endl; bool check = ((*(reinterpret_cast (&date_tests[i].date))) == ((*(reinterpret_cast (&dt))))); if (!check) { printf("For input \"%s\", format \"%s\", check 0x%016lx vs 0x%016lx\n", date_tests[i].inputstr, date_tests[i].formatstr, *(reinterpret_cast (&dt)), *(reinterpret_cast(&date_tests[i].date)) ); show_datetime_debugs("check",dt); show_datetime_debugs("ref",date_tests[i].date); } CPPUNIT_ASSERT( check ); } } void fe_getnumbertest() { const int MAX_VALS=5; struct Check { const char* str; int numvals; int vals[MAX_VALS]; }; Check tests[] = { { " ", 0, {} }, { "0", 1, {0} }, { "0.0", 2, {0,0} }, { "0:0.0", 3, {0,0,0} }, { "-0", 1, {0} }, { "0000-000", 1, {0} }, { "-2", 1, {-2} }, { "2223", 1, {2223} }, { "37", 1, {37} }, { "393", 1, {393} }, { "39-3", 1, {39} }, { "17-", 1, {17} }, { "10.2303", 2, {10,2303} }, { "20:10.2303", 3, {20,10,2303} }, { "17:37", 2, {17,37} }, }; int a1[MAX_VALS] = { 0xdeadbeef }; for (unsigned i = 0; i < sizeof(tests)/sizeof(Check); i++) { int rc1 = helpers::getNumbers(tests[i].str,a1,execplan::OP_ADD); cout << "For input \"" << tests[i].str << "\", numbers = " << rc1 << ",["; bool check = true; if (rc1 != tests[i].numvals) check = false; for (int j = 0; j < rc1; ++j) { if (j > 0) cout << ','; cout << a1[j]; if (a1[j] != tests[i].vals[j]) { check = false; } } cout << ']' << endl; CPPUNIT_ASSERT( check ); } } void fe_dateaddtest() { struct DateCheck { const char* intervalstr; IntervalColumn::interval_type unit; OpType funcType; DateTime date; DateTime ref; }; DateCheck date_tests[] = { { "111111:22",IntervalColumn::INTERVAL_YEAR_MONTH,execplan::OP_ADD,DateTime(1997,01,01,0,0,0,0),DateTime(0,0,0,0,0,0,0) } , { "-30",IntervalColumn::INTERVAL_DAY,execplan::OP_ADD,DateTime(2013,3,1,0,0,0,0),DateTime(2013,1,30,0,0,0,0) } , }; for (unsigned i = 0; i < sizeof(date_tests)/sizeof(DateCheck); i++) { DateTime dt; uint64_t timeval = *(reinterpret_cast (&date_tests[i].date)); uint64_t value = helpers::dateAdd( timeval, date_tests[i].intervalstr, date_tests[i].unit, false, date_tests[i].funcType ); *(reinterpret_cast (&dt)) = value; bool check = ( value == *(reinterpret_cast (&date_tests[i].ref))); if (!check) { printf("For interval \"%s\", check 0x%016lx vs 0x%016lx\n", date_tests[i].intervalstr, *(reinterpret_cast (&dt)), *(reinterpret_cast(&date_tests[i].ref)) ); show_datetime_debugs("check",dt); show_datetime_debugs("ref",date_tests[i].ref); } CPPUNIT_ASSERT( check ); } } void fe_daynametest() { struct DateCheck { DateTime date; const char* dayname; }; DateCheck date_tests[] = { { DateTime(1997,01,01,0,0,0,0),"Wednesday" } , }; for (unsigned i = 0; i < sizeof(date_tests)/sizeof(DateCheck); i++) { boost::gregorian::date d(date_tests[i].date.year, date_tests[i].date.month, date_tests[i].date.day); uint32_t dayofweek = helpers::calc_mysql_weekday(date_tests[i].date.year, date_tests[i].date.month, date_tests[i].date.day, false); bool check = ( strcmp( helpers::weekdayFullNames[dayofweek].c_str(), date_tests[i].dayname ) == 0 ); if (!check) { printf("For date %s, check %s vs %s\n", to_simple_string(d).c_str(), helpers::weekdayFullNames[dayofweek].c_str(), date_tests[i].dayname ); } CPPUNIT_ASSERT( check ); } } DateTime getDateTime(int64_t val) { if (val < 0 || val > helpers::TIMESTAMP_MAX_VALUE) return 0; DateTime dt; struct tm tmp_tm; time_t tmp_t= (time_t)val; localtime_r(&tmp_t, &tmp_tm); //to->neg=0; dt.year = (int64_t) ((tmp_tm.tm_year+1900) % 10000); dt.month = (int64_t) tmp_tm.tm_mon+1; dt.day = (int64_t) tmp_tm.tm_mday; dt.hour = (int64_t) tmp_tm.tm_hour; dt.minute = (int64_t) tmp_tm.tm_min; dt.second = (int64_t) tmp_tm.tm_sec; dt.msecond = 0; return dt; } void fe_fromunixtimetest() { struct DateCheck { int64_t ts; const char* formatstr; const char* refstr; }; DateCheck date_tests[] = { { -26, "%H:%i:%s", "NULL" }, { 26, "%H:%i:%s", "18:00:26" }, { 0, "%H:%i:%s", "18:00:00" }, }; for (unsigned i = 0; i < sizeof(date_tests)/sizeof(DateCheck); i++) { bool check = false; string ret; DateTime dt = getDateTime(date_tests[i].ts); if (*reinterpret_cast(&dt) == 0) { check = ( strcmp( date_tests[i].refstr, "NULL" ) == 0 ); } else { ret = helpers::IDB_date_format(dt, date_tests[i].formatstr); check = ( strcmp( date_tests[i].refstr, ret.c_str() ) == 0 ); } if (!check) { printf("For timestamp %ld, check %s vs %s\n", date_tests[i].ts, ret.c_str(), date_tests[i].refstr ); } CPPUNIT_ASSERT( check ); } } }; CPPUNIT_TEST_SUITE_REGISTRATION( FuncExpTest ); #include #include int main( int argc, char **argv) { CppUnit::TextUi::TestRunner runner; CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest( registry.makeTest() ); bool wasSuccessful = runner.run( "", false ); return (wasSuccessful ? 0 : 1); }