/* 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& registry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); bool wasSuccessful = runner.run("", false); return (wasSuccessful ? 0 : 1); }