mysql5/mysql-5.7.27/unittest/gunit/item_timefunc-t.cc

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(&ltime);
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, &ltime, sec->decimals);
}
}