193 lines
5.5 KiB
C++
193 lines
5.5 KiB
C++
/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
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,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
|
|
|
// First include (the generated) my_config.h, to get correct platform defines.
|
|
#include "my_config.h"
|
|
#include <gtest/gtest.h>
|
|
#include "test_utils.h"
|
|
|
|
#include "decimal.h"
|
|
#include "my_decimal.h"
|
|
#include "my_time.h"
|
|
#include "mysql_time.h"
|
|
#include "sql_time.h"
|
|
#include "m_ctype.h"
|
|
|
|
#include "item.h"
|
|
#include "item_timefunc.h"
|
|
|
|
#include <string.h>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
namespace item_timefunc_unittest {
|
|
|
|
using my_testing::Server_initializer;
|
|
|
|
class ItemTimeFuncTest : public ::testing::Test
|
|
{
|
|
protected:
|
|
virtual void SetUp()
|
|
{
|
|
initializer.SetUp();
|
|
}
|
|
|
|
virtual void TearDown() { initializer.TearDown(); }
|
|
|
|
THD *thd() { return initializer.thd(); }
|
|
|
|
Server_initializer initializer;
|
|
};
|
|
|
|
TEST_F(ItemTimeFuncTest, dateAddInterval)
|
|
{
|
|
Item_int *arg0= new Item_int(20130122145221LL); // 2013-01-22 14:52:21
|
|
Item_decimal *arg1= new Item_decimal(0.1234567, 8, 7);
|
|
Item *item=
|
|
new Item_date_add_interval(POS(),
|
|
arg0, arg1, INTERVAL_SECOND_MICROSECOND, false);
|
|
Parse_context pc(thd(), thd()->lex->current_select());
|
|
EXPECT_FALSE(item->itemize(&pc, &item));
|
|
EXPECT_FALSE(item->fix_fields(thd(), NULL));
|
|
|
|
// The below result is not correct, see Bug#16198372
|
|
EXPECT_DOUBLE_EQ(20130122145222.234567, item->val_real());
|
|
}
|
|
|
|
struct test_data
|
|
{
|
|
const char *secs;
|
|
unsigned int hour;
|
|
unsigned int minute;
|
|
unsigned int second;
|
|
unsigned long second_part;
|
|
};
|
|
|
|
::std::ostream& operator<<(::std::ostream& os, const struct test_data& data) {
|
|
return os << data.secs;
|
|
}
|
|
|
|
|
|
class ItemTimeFuncTestP : public ::testing::TestWithParam<test_data>
|
|
{
|
|
protected:
|
|
virtual void SetUp()
|
|
{
|
|
initializer.SetUp();
|
|
m_t= GetParam();
|
|
}
|
|
|
|
virtual void TearDown() { initializer.TearDown(); }
|
|
|
|
THD *thd() { return initializer.thd(); }
|
|
|
|
Server_initializer initializer;
|
|
test_data m_t;
|
|
};
|
|
|
|
const test_data test_values[]=
|
|
{
|
|
{ "0.1234564", 0, 0, 0, 123456 },
|
|
{ "0.1234567", 0, 0, 0, 123457 },
|
|
{ "0.1234", 0, 0, 0, 123400 },
|
|
{ "12.1234567", 0, 0, 12, 123457},
|
|
{ "123", 0, 2, 3, 0 },
|
|
{ "2378.3422349", 0, 39, 38, 342235 },
|
|
{ "3020398.999999999", 838, 59, 59, 0 },
|
|
{ "3020399", 838, 59, 59, 0 },
|
|
{ "99999999.99999999", 838, 59, 59, 0 }
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(a, ItemTimeFuncTestP,
|
|
::testing::ValuesIn(test_values));
|
|
|
|
/**
|
|
Test member function of @c Item_time_func
|
|
|
|
@param item item of a sub-class of @c Item_time_func
|
|
@param ltime time structure that contains the expected result
|
|
@param decimals number of significant decimals in the expected result
|
|
*/
|
|
void testItemTimeFunctions(Item_time_func *item, MYSQL_TIME *ltime,
|
|
int decimals)
|
|
{
|
|
long long int mysql_time=
|
|
10000 * ltime->hour + 100 * ltime->minute + ltime->second;
|
|
EXPECT_EQ(mysql_time, item->val_int());
|
|
|
|
long long int packed= TIME_to_longlong_packed(ltime);
|
|
EXPECT_EQ(packed, item->val_time_temporal());
|
|
|
|
double d= mysql_time + ltime->second_part / 1000000.0;
|
|
EXPECT_DOUBLE_EQ(d, item->val_real());
|
|
|
|
my_decimal decval1, decval2;
|
|
my_decimal *dec= item->val_decimal(&decval1);
|
|
double2decimal(d, &decval2);
|
|
EXPECT_EQ(0, my_decimal_cmp(dec, &decval2));
|
|
|
|
char s[20];
|
|
sprintf(s, "%02d:%02d:%02d", ltime->hour, ltime->minute, ltime->second);
|
|
if (ltime->second_part > 0) { // Avoid trailing zeroes
|
|
int decs= ltime->second_part;
|
|
while (decs % 10 == 0)
|
|
decs /= 10;
|
|
sprintf(s + strlen(s), ".%d", decs);
|
|
}
|
|
else if (decimals > 0)
|
|
// There were decimals, but they have disappeared due to overflow
|
|
sprintf(s + strlen(s), ".000000");
|
|
String timeStr(20);
|
|
EXPECT_STREQ(s, item->val_str(&timeStr)->c_ptr());
|
|
|
|
MYSQL_TIME ldate;
|
|
//> Second argument of Item_func_time::get_date is not used for anything
|
|
item->get_date(&ldate, 0);
|
|
// Todo: Should check that year, month, and day is relative to current date
|
|
EXPECT_EQ(ltime->hour % 24, ldate.hour);
|
|
EXPECT_EQ(ltime->minute, ldate.minute);
|
|
EXPECT_EQ(ltime->second, ldate.second);
|
|
EXPECT_EQ(ltime->second_part, ldate.second_part);
|
|
|
|
// Todo: Item_time_func::save_in_field is not tested
|
|
}
|
|
|
|
TEST_P(ItemTimeFuncTestP, secToTime)
|
|
{
|
|
Item_decimal *sec=
|
|
new Item_decimal(POS(), m_t.secs, strlen(m_t.secs), &my_charset_latin1_bin);
|
|
Item_func_sec_to_time *time= new Item_func_sec_to_time(POS(), sec);
|
|
|
|
Parse_context pc(thd(), thd()->lex->current_select());
|
|
Item *item;
|
|
EXPECT_FALSE(time->itemize(&pc, &item));
|
|
EXPECT_EQ(time, item);
|
|
EXPECT_FALSE(time->fix_fields(thd(), NULL));
|
|
|
|
MYSQL_TIME ltime;
|
|
time->get_time(<ime);
|
|
EXPECT_EQ(0U, ltime.year);
|
|
EXPECT_EQ(0U, ltime.month);
|
|
EXPECT_EQ(0U, ltime.day);
|
|
EXPECT_EQ(m_t.hour, ltime.hour);
|
|
EXPECT_EQ(m_t.minute, ltime.minute);
|
|
EXPECT_EQ(m_t.second, ltime.second);
|
|
EXPECT_EQ(m_t.second_part, ltime.second_part);
|
|
|
|
testItemTimeFunctions(time, <ime, sec->decimals);
|
|
}
|
|
|
|
}
|