MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
item_timefunc-t.cc
1 /* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
16 // First include (the generated) my_config.h, to get correct platform defines.
17 #include "my_config.h"
18 #include <gtest/gtest.h>
19 #include "test_utils.h"
20 
21 #include "decimal.h"
22 #include "my_decimal.h"
23 #include "my_time.h"
24 #include "mysql_time.h"
25 #include "sql_time.h"
26 #include "m_ctype.h"
27 
28 #include "item.h"
29 #include "item_timefunc.h"
30 
31 #include <string.h>
32 #include <sstream>
33 #include <string>
34 
35 namespace item_timefunc_unittest {
36 
38 
39 class ItemTimeFuncTest : public ::testing::Test
40 {
41 protected:
42  virtual void SetUp()
43  {
44  initializer.SetUp();
45  }
46 
47  virtual void TearDown() { initializer.TearDown(); }
48 
49  THD *thd() { return initializer.thd(); }
50 
51  Server_initializer initializer;
52 };
53 
54 TEST_F(ItemTimeFuncTest, dateAddInterval)
55 {
56  Item_int *arg0= new Item_int(20130122145221LL); // 2013-01-22 14:52:21
57  Item_decimal *arg1= new Item_decimal(0.1234567, 8, 7);
59  new Item_date_add_interval(arg0, arg1, INTERVAL_SECOND_MICROSECOND, false);
60  EXPECT_FALSE(item->fix_fields(thd(), NULL));
61 
62  // The below result is not correct, see Bug#16198372
63  EXPECT_DOUBLE_EQ(20130122145222.234567, item->val_real());
64 }
65 
66 struct test_data
67 {
68  const char *secs;
69  unsigned int hour;
70  unsigned int minute;
71  unsigned int second;
72  unsigned long second_part;
73 };
74 
75 ::std::ostream& operator<<(::std::ostream& os, const struct test_data& data) {
76  return os << data.secs;
77 }
78 
79 
80 class ItemTimeFuncTestP : public ::testing::TestWithParam<test_data>
81 {
82 protected:
83  virtual void SetUp()
84  {
85  initializer.SetUp();
86  m_t= GetParam();
87  }
88 
89  virtual void TearDown() { initializer.TearDown(); }
90 
91  THD *thd() { return initializer.thd(); }
92 
93  Server_initializer initializer;
94  test_data m_t;
95 };
96 
97 const test_data test_values[]=
98 {
99  { "0.1234564", 0, 0, 0, 123456 },
100  { "0.1234567", 0, 0, 0, 123457 },
101  { "0.1234", 0, 0, 0, 123400 },
102  { "12.1234567", 0, 0, 12, 123457},
103  { "123", 0, 2, 3, 0 },
104  { "2378.3422349", 0, 39, 38, 342235 },
105  { "3020398.999999999", 838, 59, 59, 0 },
106  { "3020399", 838, 59, 59, 0 },
107  { "99999999.99999999", 838, 59, 59, 0 }
108 };
109 
110 INSTANTIATE_TEST_CASE_P(a, ItemTimeFuncTestP,
111  ::testing::ValuesIn(test_values));
112 
120 void testItemTimeFunctions(Item_time_func *item, MYSQL_TIME *ltime,
121  int decimals)
122 {
123  long long int mysql_time=
124  10000 * ltime->hour + 100 * ltime->minute + ltime->second;
125  EXPECT_EQ(mysql_time, item->val_int());
126 
127  long long int packed= TIME_to_longlong_packed(ltime);
128  EXPECT_EQ(packed, item->val_time_temporal());
129 
130  double d= mysql_time + ltime->second_part / 1000000.0;
131  EXPECT_DOUBLE_EQ(d, item->val_real());
132 
133  my_decimal decval1, decval2;
134  my_decimal *dec= item->val_decimal(&decval1);
135  double2decimal(d, &decval2);
136  EXPECT_EQ(0, my_decimal_cmp(dec, &decval2));
137 
138  char s[20];
139  sprintf(s, "%02d:%02d:%02d", ltime->hour, ltime->minute, ltime->second);
140  if (ltime->second_part > 0) { // Avoid trailing zeroes
141  int decs= ltime->second_part;
142  while (decs % 10 == 0)
143  decs /= 10;
144  sprintf(s + strlen(s), ".%d", decs);
145  }
146  else if (decimals > 0)
147  // There were decimals, but they have disappeared due to overflow
148  sprintf(s + strlen(s), ".000000");
149  String timeStr(20);
150  EXPECT_STREQ(s, item->val_str(&timeStr)->c_ptr());
151 
152  MYSQL_TIME ldate;
153  //> Second argument of Item_func_time::get_date is not used for anything
154  item->get_date(&ldate, 0);
155  // Todo: Should check that year, month, and day is relative to current date
156  EXPECT_EQ(ltime->hour % 24, ldate.hour);
157  EXPECT_EQ(ltime->minute, ldate.minute);
158  EXPECT_EQ(ltime->second, ldate.second);
159  EXPECT_EQ(ltime->second_part, ldate.second_part);
160 
161  // Todo: Item_time_func::save_in_field is not tested
162 }
163 
164 TEST_P(ItemTimeFuncTestP, secToTime)
165 {
166  Item_decimal *sec=
167  new Item_decimal(m_t.secs, strlen(m_t.secs), &my_charset_latin1_bin);
169  EXPECT_FALSE(time->fix_fields(thd(), NULL));
170 
171  MYSQL_TIME ltime;
172  time->get_time(&ltime);
173  EXPECT_EQ(0U, ltime.year);
174  EXPECT_EQ(0U, ltime.month);
175  EXPECT_EQ(0U, ltime.day);
176  EXPECT_EQ(m_t.hour, ltime.hour);
177  EXPECT_EQ(m_t.minute, ltime.minute);
178  EXPECT_EQ(m_t.second, ltime.second);
179  EXPECT_EQ(m_t.second_part, ltime.second_part);
180 
181  testItemTimeFunctions(time, &ltime, sec->decimals);
182 }
183 
184 }