1 /* Copyright (c) 2011, 2021, Oracle and/or its affiliates.
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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22 
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26 #include <gmock/gmock.h>
27 
28 #include "test_utils.h"
29 
30 #include "item.h"
31 #include "item_cmpfunc.h"
32 #include "item_create.h"
33 #include "item_strfunc.h"
34 #include "item_timefunc.h"
35 #include "sql_class.h"
36 #include "tztime.h"
37 
38 #include "fake_table.h"
39 #include "mock_field_timestamp.h"
40 
41 namespace item_unittest {
42 
43 using my_testing::Server_initializer;
44 using my_testing::Mock_error_handler;
45 using ::testing::Return;
46 
47 class ItemTest : public ::testing::Test
48 {
49 protected:
SetUp()50   virtual void SetUp() { initializer.SetUp(); }
TearDown()51   virtual void TearDown() { initializer.TearDown(); }
52 
thd()53   THD *thd() { return initializer.thd(); }
54 
55   Server_initializer initializer;
56 };
57 
58 
59 /**
60   This is a simple mock Field class, illustrating how to set expectations on
61   type_conversion_status Field_long::store(longlong nr, bool unsigned_val);
62 */
63 class Mock_field_long : public Field_long
64 {
65 public:
Mock_field_long(uint32 lenght)66   Mock_field_long(uint32 lenght)
67     : Field_long(0,                             // ptr_arg
68                  lenght,                        // len_arg
69                  NULL,                          // null_ptr_arg
70                  0,                             // null_bit_arg
71                  Field::NONE,                   // unireg_check_arg
72                  0,                             // field_name_arg
73                  false,                         // zero_arg
74                  false)                         // unsigned_arg
75   {}
76 
77   // Avoid warning about hiding other overloaded versions of store().
78   using Field_long::store;
79 
80   /*
81     This is the only member function we need to override.
82     Note: Sun Studio needs a little help in resolving longlong.
83    */
84   MOCK_METHOD2(store, type_conversion_status(::longlong nr, bool unsigned_val));
85 };
86 
87 
88 /**
89   Mock class for CHAR field.
90 */
91 
92 class Mock_field_string : public Field_string
93 {
94 private:
95   Fake_TABLE *m_fake_tbl;
96 
97 public:
Mock_field_string(uint32 length,const CHARSET_INFO * cs=& my_charset_latin1)98   Mock_field_string(uint32 length, const CHARSET_INFO *cs= &my_charset_latin1)
99     : Field_string(0,                  // ptr_arg
100                    length,             // len_arg
101                    NULL,               // null_ptr_arg
102                    0,                  // null_bit_arg
103                    Field::NONE,        // unireg_check_arg
104                    NULL,               // field_name_arg
105                    cs)                 // char set
106   {
107     m_fake_tbl= new Fake_TABLE(this);
108 
109     // Allocate place for storing the field value
110     ptr= new uchar[length];
111 
112     // Make it possible to write into this field
113     bitmap_set_bit(m_fake_tbl->write_set, 0);
114 
115     /*
116       count_cuted_fields must be set in order for producing
117       warning/error for Item_string::save_in_field().
118     */
119     m_fake_tbl->in_use->count_cuted_fields= CHECK_FIELD_WARN;
120   }
121 
~Mock_field_string()122   ~Mock_field_string()
123   {
124     delete [] ptr;
125     ptr= NULL;
126     delete m_fake_tbl;
127     m_fake_tbl= NULL;
128   }
129 };
130 
131 
132 /**
133   Mock class for VARCHAR field.
134 */
135 
136 class Mock_field_varstring : public Field_varstring
137 {
138 private:
139   Fake_TABLE *m_fake_tbl;
140 
141 public:
Mock_field_varstring(uint32 length,TABLE_SHARE * share,const CHARSET_INFO * cs=& my_charset_latin1)142   Mock_field_varstring(uint32 length, TABLE_SHARE *share,
143                        const CHARSET_INFO *cs= &my_charset_latin1)
144     : Field_varstring(length,             // len_arg
145                       false,              // maybe_null_arg
146                       NULL,               // field_name_arg
147                       share,              // share
148                       cs)                 // char set
149   {
150     m_fake_tbl= new Fake_TABLE(this);
151 
152     // Allocate place for storing the field value
153     ptr= new uchar[length + 1];
154 
155     // Make it possible to write into this field
156     bitmap_set_bit(m_fake_tbl->write_set, 0);
157 
158     /*
159       count_cuted_fields must be set in order for producing
160       warning/error for Item_string::save_in_field().
161     */
162     m_fake_tbl->in_use->count_cuted_fields= CHECK_FIELD_WARN;
163   }
164 
~Mock_field_varstring()165   ~Mock_field_varstring()
166   {
167     delete [] ptr;
168     ptr= NULL;
169     delete m_fake_tbl;
170     m_fake_tbl= NULL;
171   }
172 };
173 
174 
TEST_F(ItemTest,ItemInt)175 TEST_F(ItemTest, ItemInt)
176 {
177   const int32 val= 42;
178   char stringbuf[10];
179   (void) my_snprintf(stringbuf, sizeof(stringbuf), "%d", val);
180 
181   // An Item expects to be owned by current_thd->free_list,
182   // so allocate with new, and do not delete it.
183   Item_int *item_int= new Item_int(val);
184 
185   EXPECT_EQ(Item::INT_ITEM,      item_int->type());
186   EXPECT_EQ(INT_RESULT,          item_int->result_type());
187   EXPECT_EQ(MYSQL_TYPE_LONGLONG, item_int->field_type());
188   EXPECT_EQ(val,                 item_int->val_int());
189   EXPECT_DOUBLE_EQ((double) val, item_int->val_real());
190   EXPECT_TRUE(item_int->basic_const_item());
191 
192   my_decimal decimal_val;
193   EXPECT_EQ(&decimal_val, item_int->val_decimal(&decimal_val));
194 
195   String string_val;
196   EXPECT_EQ(&string_val, item_int->val_str(&string_val));
197   EXPECT_STREQ(stringbuf, string_val.c_ptr_safe());
198 
199   Mock_field_long field_val(item_int->max_length);
200   // We expect to be called with arguments(nr == val, unsigned_val == false)
201   EXPECT_CALL(field_val, store(val, false))
202     .Times(1)
203     .WillRepeatedly(Return(TYPE_OK));
204   EXPECT_EQ(TYPE_OK, item_int->save_in_field(&field_val, true));
205 
206   Item *clone= item_int->clone_item();
207   EXPECT_TRUE(item_int->eq(clone, true));
208   EXPECT_TRUE(item_int->eq(item_int, true));
209 
210   String print_val;
211   item_int->print(&print_val, QT_ORDINARY);
212   EXPECT_STREQ(stringbuf, print_val.c_ptr_safe());
213 
214   const uint precision= item_int->decimal_precision();
215   EXPECT_EQ(MY_INT32_NUM_DECIMAL_DIGITS, precision);
216 
217   item_int->neg();
218   EXPECT_EQ(-val, item_int->val_int());
219   EXPECT_EQ(precision - 1, item_int->decimal_precision());
220 
221   // Functions inherited from parent class(es).
222   const table_map tmap= 0;
223   EXPECT_EQ(tmap, item_int->used_tables());
224 
225   /*
226    TODO: There are about 100 member functions in Item.
227          Figure out which ones are relevant for unit testing here.
228   */
229 }
230 
231 
TEST_F(ItemTest,ItemString)232 TEST_F(ItemTest, ItemString)
233 {
234   const char short_str[]= "abc";
235   const char long_str[]= "abcd";
236   const char space_str[]= "abc ";
237   const char bad_char[]= "��abc";
238   const char bad_char_end[]= "abc��";
239 
240   Item_string *item_short_string=
241     new Item_string(STRING_WITH_LEN(short_str), &my_charset_latin1);
242   Item_string *item_long_string=
243     new Item_string(STRING_WITH_LEN(long_str), &my_charset_latin1);
244   Item_string *item_space_string=
245     new Item_string(STRING_WITH_LEN(space_str), &my_charset_latin1);
246   Item_string *item_bad_char=
247     new Item_string(STRING_WITH_LEN(bad_char), &my_charset_bin);
248   Item_string *item_bad_char_end=
249     new Item_string(STRING_WITH_LEN(bad_char_end), &my_charset_bin);
250 
251   /*
252     Bug 16407965 ITEM::SAVE_IN_FIELD_NO_WARNING() DOES NOT RETURN CORRECT
253                  CONVERSION STATUS
254   */
255 
256   // Create a CHAR field that can store short_str but not long_str
257   Mock_field_string field_string(3);
258   EXPECT_EQ(MYSQL_TYPE_STRING, field_string.type());
259 
260   // CHAR field for testing strings with illegal values
261   Mock_field_string field_string_utf8(20, &my_charset_utf8_general_ci);
262   EXPECT_EQ(MYSQL_TYPE_STRING, field_string_utf8.type());
263 
264   /*
265     Tests of Item_string::save_in_field() when storing into a CHAR field.
266   */
267   EXPECT_EQ(TYPE_OK, item_short_string->save_in_field(&field_string, true));
268   EXPECT_EQ(TYPE_WARN_TRUNCATED,
269             item_long_string->save_in_field(&field_string, true));
270   // Field_string does not consider trailing spaces when truncating a string
271   EXPECT_EQ(TYPE_OK,
272             item_space_string->save_in_field(&field_string, true));
273   // When the first character invalid, the whole string is truncated.
274   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
275             item_bad_char->save_in_field(&field_string_utf8, true));
276   // If the string contains an invalid character, the entire string is invalid
277   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
278             item_bad_char_end->save_in_field(&field_string_utf8, true));
279 
280   /*
281     Tests of Item_string::save_in_field_no_warnings() when storing into
282     a CHAR field.
283   */
284   EXPECT_EQ(TYPE_OK,
285             item_short_string->save_in_field_no_warnings(&field_string, true));
286   EXPECT_EQ(TYPE_WARN_TRUNCATED,
287             item_long_string->save_in_field_no_warnings(&field_string, true));
288   // Field_string does not consider trailing spaces when truncating a string
289   EXPECT_EQ(TYPE_OK,
290             item_space_string->save_in_field_no_warnings(&field_string, true));
291   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
292             item_bad_char->save_in_field_no_warnings(&field_string_utf8, true));
293   // If the string contains an invalid character, the entire string is invalid
294   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
295             item_bad_char_end->save_in_field_no_warnings(&field_string_utf8,
296                                                          true));
297 
298   /*
299     Create a VARCHAR field that can store short_str but not long_str.
300     Need a table share object since the constructor for Field_varstring
301     updates its table share.
302   */
303   TABLE_SHARE table_share;
304   Mock_field_varstring field_varstring(3, &table_share);
305   EXPECT_EQ(MYSQL_TYPE_VARCHAR, field_varstring.type());
306 
307   // VARCHAR field for testing strings with illegal values
308   Mock_field_varstring field_varstring_utf8(20, &table_share,
309                                             &my_charset_utf8_general_ci);
310   EXPECT_EQ(MYSQL_TYPE_VARCHAR, field_varstring_utf8.type());
311 
312   /*
313     Tests of Item_string::save_in_field() when storing into a VARCHAR field.
314   */
315   EXPECT_EQ(TYPE_OK, item_short_string->save_in_field(&field_varstring, true));
316   EXPECT_EQ(TYPE_WARN_TRUNCATED,
317             item_long_string->save_in_field(&field_varstring, true));
318   // Field_varstring produces a note when truncating a string with
319   // trailing spaces
320   EXPECT_EQ(TYPE_NOTE_TRUNCATED,
321             item_space_string->save_in_field(&field_varstring, true));
322   // When the first character invalid, the whole string is truncated.
323   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
324             item_bad_char->save_in_field(&field_varstring_utf8, true));
325   // If the string contains an invalid character, the entire string is invalid
326   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
327             item_bad_char_end->save_in_field(&field_varstring_utf8, true));
328 
329   /*
330     Tests of Item_string::save_in_field_no_warnings() when storing into
331     a VARCHAR field.
332   */
333   EXPECT_EQ(TYPE_OK,
334          item_short_string->save_in_field_no_warnings(&field_varstring, true));
335   EXPECT_EQ(TYPE_WARN_TRUNCATED,
336          item_long_string->save_in_field_no_warnings(&field_varstring, true));
337   // Field_varstring produces a note when truncating a string with
338   // trailing spaces
339   EXPECT_EQ(TYPE_NOTE_TRUNCATED,
340          item_space_string->save_in_field_no_warnings(&field_varstring, true));
341   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
342          item_bad_char->save_in_field_no_warnings(&field_varstring_utf8, true));
343   // If the string contains an invalid character, the entire string is invalid
344   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
345          item_bad_char_end->save_in_field_no_warnings(&field_varstring_utf8, true));
346 }
347 
348 
TEST_F(ItemTest,ItemEqual)349 TEST_F(ItemTest, ItemEqual)
350 {
351   // Bug#13720201 VALGRIND: VARIOUS BLOCKS OF BYTES DEFINITELY LOST
352   Mock_field_timestamp mft;
353   mft.table->const_table= true;
354   mft.make_readable();
355   // foo is longer than STRING_BUFFER_USUAL_SIZE used by cmp_item_sort_string.
356   const char foo[]=
357     "0123456789012345678901234567890123456789"
358     "0123456789012345678901234567890123456789"
359     "0123456789012345678901234567890123456789";
360   Item_equal *item_equal=
361     new Item_equal(new Item_string(STRING_WITH_LEN(foo), &my_charset_bin),
362                    new Item_field(&mft));
363 
364   EXPECT_FALSE(item_equal->fix_fields(thd(), NULL));
365   EXPECT_EQ(1, item_equal->val_int());
366 }
367 
368 
TEST_F(ItemTest,ItemFuncDesDecrypt)369 TEST_F(ItemTest, ItemFuncDesDecrypt)
370 {
371   // Bug #59632 Assertion failed: arg_length > length
372   const uint length= 1U;
373   Item_int *item_one= new Item_int(1, length);
374   Item_int *item_two= new Item_int(2, length);
375   Item *item_decrypt=
376     new Item_func_des_decrypt(POS(), item_two, item_one);
377   Parse_context pc(thd(), thd()->lex->current_select());
378   EXPECT_FALSE(item_decrypt->itemize(&pc, &item_decrypt));
379 
380   EXPECT_FALSE(item_decrypt->fix_fields(thd(), NULL));
381   EXPECT_EQ(length, item_one->max_length);
382   EXPECT_EQ(length, item_two->max_length);
383   EXPECT_LE(item_decrypt->max_length, length);
384 }
385 
386 
TEST_F(ItemTest,ItemFuncExportSet)387 TEST_F(ItemTest, ItemFuncExportSet)
388 {
389   String str;
390   Item *on_string= new Item_string(STRING_WITH_LEN("on"), &my_charset_bin);
391   Item *off_string= new Item_string(STRING_WITH_LEN("off"), &my_charset_bin);
392   Item *sep_string= new Item_string(STRING_WITH_LEN(","), &my_charset_bin);
393   {
394     // Testing basic functionality.
395     Item *export_set=
396       new Item_func_export_set(POS(),
397                                new Item_int(2),
398                                on_string,
399                                off_string,
400                                sep_string,
401                                new Item_int(4));
402     Parse_context pc(thd(), thd()->lex->current_select());
403     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
404     EXPECT_FALSE(export_set->fix_fields(thd(), NULL));
405     EXPECT_EQ(&str, export_set->val_str(&str));
406     EXPECT_STREQ("off,on,off,off", str.c_ptr_safe());
407   }
408   {
409     // Testing corner case: number_of_bits == zero.
410     Item *export_set=
411       new Item_func_export_set(POS(),
412                                new Item_int(2),
413                                on_string,
414                                off_string,
415                                sep_string,
416                                new Item_int(0));
417     Parse_context pc(thd(), thd()->lex->current_select());
418     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
419     EXPECT_FALSE(export_set->fix_fields(thd(), NULL));
420     EXPECT_EQ(&str, export_set->val_str(&str));
421     EXPECT_STREQ("", str.c_ptr_safe());
422   }
423 
424   /*
425     Bug#11765562 58545:
426     EXPORT_SET() CAN BE USED TO MAKE ENTIRE SERVER COMPLETELY UNRESPONSIVE
427    */
428   const ulong max_size= 1024;
429   const ulonglong repeat= max_size / 2;
430   Item *item_int_repeat= new Item_int(repeat);
431   Item *string_x= new Item_string(STRING_WITH_LEN("x"), &my_charset_bin);
432   String * const null_string= NULL;
433   thd()->variables.max_allowed_packet= max_size;
434   {
435     // Testing overflow caused by 'on-string'.
436     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
437     Item *export_set=
438       new Item_func_export_set(POS(),
439                                new Item_int(0xff),
440                                new Item_func_repeat(POS(),
441                                                     string_x, item_int_repeat),
442                                string_x,
443                                sep_string);
444     Parse_context pc(thd(), thd()->lex->current_select());
445     SCOPED_TRACE("");
446     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
447     EXPECT_FALSE(export_set->fix_fields(thd(), NULL));
448     EXPECT_EQ(null_string, export_set->val_str(&str));
449     EXPECT_STREQ("", str.c_ptr_safe());
450     EXPECT_EQ(1, error_handler.handle_called());
451   }
452   {
453     // Testing overflow caused by 'off-string'.
454     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
455     Item *export_set=
456       new Item_func_export_set(POS(),
457                                new Item_int(0xff),
458                                string_x,
459                                new Item_func_repeat(POS(),
460                                                     string_x, item_int_repeat),
461                                sep_string);
462     Parse_context pc(thd(), thd()->lex->current_select());
463     SCOPED_TRACE("");
464     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
465     EXPECT_FALSE(export_set->fix_fields(thd(), NULL));
466     EXPECT_EQ(null_string, export_set->val_str(&str));
467     EXPECT_STREQ("", str.c_ptr_safe());
468     EXPECT_EQ(1, error_handler.handle_called());
469   }
470   {
471     // Testing overflow caused by 'separator-string'.
472     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
473     Item *export_set=
474       new Item_func_export_set(POS(),
475                                new Item_int(0xff),
476                                string_x,
477                                string_x,
478                                new Item_func_repeat(POS(),
479                                                     string_x, item_int_repeat));
480     Parse_context pc(thd(), thd()->lex->current_select());
481     SCOPED_TRACE("");
482     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
483     EXPECT_FALSE(export_set->fix_fields(thd(), NULL));
484     EXPECT_EQ(null_string, export_set->val_str(&str));
485     EXPECT_STREQ("", str.c_ptr_safe());
486     EXPECT_EQ(1, error_handler.handle_called());
487   }
488   {
489     // Testing overflow caused by 'on-string'.
490     longlong max_size= 1024LL;
491     thd()->variables.max_allowed_packet= static_cast<ulong>(max_size);
492     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
493     Item *lpad=
494       new Item_func_lpad(POS(),
495                          new Item_string(STRING_WITH_LEN("a"),
496                                          &my_charset_bin),
497                          new Item_int(max_size),
498                          new Item_string(STRING_WITH_LEN("pppppppppppppppp"
499                                                          "pppppppppppppppp"),
500                                          &my_charset_bin)
501                          );
502     Item *export_set=
503       new Item_func_export_set(POS(),
504                                new Item_string(STRING_WITH_LEN("1111111"),
505                                                &my_charset_bin),
506                                lpad,
507                                new Item_int(1));
508     Parse_context pc(thd(), thd()->lex->current_select());
509     SCOPED_TRACE("");
510     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
511     EXPECT_FALSE(export_set->fix_fields(thd(), NULL));
512     EXPECT_EQ(null_string, export_set->val_str(&str));
513     EXPECT_STREQ("", str.c_ptr_safe());
514     EXPECT_EQ(1, error_handler.handle_called());
515   }
516 }
517 
518 
TEST_F(ItemTest,ItemFuncIntDivOverflow)519 TEST_F(ItemTest, ItemFuncIntDivOverflow)
520 {
521   const char dividend_str[]=
522     "99999999999999999999999999999999999999999"
523     "99999999999999999999999999999999999999999";
524   const char divisor_str[]= "0.5";
525   Item_float *dividend= new Item_float(dividend_str, sizeof(dividend_str));
526   Item_float *divisor= new Item_float(divisor_str, sizeof(divisor_str));
527   Item_func_int_div* quotient= new Item_func_int_div(dividend, divisor);
528 
529   Mock_error_handler error_handler(thd(), ER_TRUNCATED_WRONG_VALUE);
530   EXPECT_FALSE(quotient->fix_fields(thd(), NULL));
531   initializer.set_expected_error(ER_DATA_OUT_OF_RANGE);
532   quotient->val_int();
533 }
534 
535 
TEST_F(ItemTest,ItemFuncIntDivUnderflow)536 TEST_F(ItemTest, ItemFuncIntDivUnderflow)
537 {
538   // Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
539   const char dividend_str[]= "1.175494351E-37";
540   const char divisor_str[]= "1.7976931348623157E+308";
541   Item_float *dividend= new Item_float(dividend_str, sizeof(dividend_str));
542   Item_float *divisor= new Item_float(divisor_str, sizeof(divisor_str));
543   Item_func_int_div* quotient= new Item_func_int_div(dividend, divisor);
544 
545   Mock_error_handler error_handler(thd(), ER_TRUNCATED_WRONG_VALUE);
546   EXPECT_FALSE(quotient->fix_fields(thd(), NULL));
547   EXPECT_EQ(0, quotient->val_int());
548 }
549 
550 
TEST_F(ItemTest,ItemFuncNegLongLongMin)551 TEST_F(ItemTest, ItemFuncNegLongLongMin)
552 {
553   // Bug#14314156 MAIN.FUNC_MATH TEST FAILS ON MYSQL-TRUNK ON PB2
554   const longlong longlong_min= LLONG_MIN;
555   Item_func_neg *item_neg= new Item_func_neg(new Item_int(longlong_min));
556 
557   EXPECT_FALSE(item_neg->fix_fields(thd(), NULL));
558   initializer.set_expected_error(ER_DATA_OUT_OF_RANGE);
559   EXPECT_EQ(0, item_neg->int_op());
560 }
561 
562 
563 /*
564   This is not an exhaustive test. It simply demonstrates that more of the
565   initializations in mysqld.cc are needed for testing Item_xxx classes.
566 */
TEST_F(ItemTest,ItemFuncSetUserVar)567 TEST_F(ItemTest, ItemFuncSetUserVar)
568 {
569   const longlong val1= 1;
570   Item_decimal *item_dec= new Item_decimal(val1, false);
571   Item_string  *item_str= new Item_string("1", 1, &my_charset_latin1);
572 
573   LEX_STRING var_name= { C_STRING_WITH_LEN("a") };
574   Item_func_set_user_var *user_var=
575     new Item_func_set_user_var(var_name, item_str, false);
576   EXPECT_FALSE(user_var->set_entry(thd(), true));
577   EXPECT_FALSE(user_var->fix_fields(thd(), NULL));
578   EXPECT_EQ(val1, user_var->val_int());
579 
580   my_decimal decimal;
581   my_decimal *decval_1= user_var->val_decimal(&decimal);
582   user_var->save_item_result(item_str);
583   my_decimal *decval_2= user_var->val_decimal(&decimal);
584   user_var->save_item_result(item_dec);
585 
586   EXPECT_EQ(decval_1, decval_2);
587   EXPECT_EQ(decval_1, &decimal);
588 }
589 
590 
591 // Test of Item::operator new() when we simulate out-of-memory.
TEST_F(ItemTest,OutOfMemory)592 TEST_F(ItemTest, OutOfMemory)
593 {
594   Item_int *null_item= NULL;
595   Item_int *item= new Item_int(42);
596   EXPECT_NE(null_item, item);
597   delete null_item;
598 
599 #if !defined(NDEBUG)
600   // Setting debug flags triggers enter/exit trace, so redirect to /dev/null.
601   DBUG_SET("o," IF_WIN("NUL", "/dev/null"));
602 
603   DBUG_SET("+d,simulate_out_of_memory");
604   item= new Item_int(42);
605   EXPECT_EQ(null_item, item);
606 
607   DBUG_SET("+d,simulate_out_of_memory");
608   item= new (thd()->mem_root) Item_int(42);
609   EXPECT_EQ(null_item, item);
610 #endif
611 }
612 
613 
614 // We never use dynamic_cast, but we expect it to work.
TEST_F(ItemTest,DynamicCast)615 TEST_F(ItemTest, DynamicCast)
616 {
617   Item *item= new Item_int(42);
618   const Item_int *null_item= NULL;
619   EXPECT_NE(null_item, dynamic_cast<Item_int*>(item));
620 }
621 
622 
TEST_F(ItemTest,ItemFuncXor)623 TEST_F(ItemTest, ItemFuncXor)
624 {
625   const uint length= 1U;
626   Item_int *item_zero= new Item_int(0, length);
627   Item_int *item_one_a= new Item_int(1, length);
628 
629   Item_func_xor *item_xor=
630     new Item_func_xor(item_zero, item_one_a);
631 
632   EXPECT_FALSE(item_xor->fix_fields(thd(), NULL));
633   EXPECT_EQ(1, item_xor->val_int());
634   EXPECT_EQ(1U, item_xor->decimal_precision());
635 
636   Item_int *item_one_b= new Item_int(1, length);
637 
638   Item_func_xor *item_xor_same=
639     new Item_func_xor(item_one_a, item_one_b);
640 
641   EXPECT_FALSE(item_xor_same->fix_fields(thd(), NULL));
642   EXPECT_EQ(0, item_xor_same->val_int());
643   EXPECT_FALSE(item_xor_same->val_bool());
644   EXPECT_FALSE(item_xor_same->is_null());
645 
646   String print_buffer;
647   item_xor->print(&print_buffer, QT_ORDINARY);
648   EXPECT_STREQ("(0 xor 1)", print_buffer.c_ptr_safe());
649 
650   Item *neg_xor= item_xor->neg_transformer(thd());
651   EXPECT_FALSE(neg_xor->fix_fields(thd(), NULL));
652   EXPECT_EQ(0, neg_xor->val_int());
653   EXPECT_DOUBLE_EQ(0.0, neg_xor->val_real());
654   EXPECT_FALSE(neg_xor->val_bool());
655   EXPECT_FALSE(neg_xor->is_null());
656 
657   print_buffer= String();
658   neg_xor->print(&print_buffer, QT_ORDINARY);
659   EXPECT_STREQ("((not(0)) xor 1)", print_buffer.c_ptr_safe());
660 
661   Item_func_xor *item_xor_null=
662     new Item_func_xor(item_zero, new Item_null());
663   EXPECT_FALSE(item_xor_null->fix_fields(thd(), NULL));
664 
665   EXPECT_EQ(0, item_xor_null->val_int());
666   EXPECT_TRUE(item_xor_null->is_null());
667 }
668 
669 
670 /*
671   Testing MYSQL_TIME_cache.
672 */
TEST_F(ItemTest,MysqlTimeCache)673 TEST_F(ItemTest, MysqlTimeCache)
674 {
675   String str_buff, *str;
676   MYSQL_TIME datetime6=
677   { 2011, 11, 7, 10, 20, 30, 123456, 0, MYSQL_TIMESTAMP_DATETIME };
678   MYSQL_TIME time6=
679   { 0, 0, 0, 10, 20, 30, 123456, 0, MYSQL_TIMESTAMP_TIME };
680   struct timeval tv6= {1320661230, 123456};
681   const MYSQL_TIME *ltime;
682   MYSQL_TIME_cache cache;
683 
684   /*
685     Testing DATETIME(6).
686     Initializing from MYSQL_TIME.
687   */
688   cache.set_datetime(&datetime6, 6);
689   EXPECT_EQ(1840440237558456896LL, cache.val_packed());
690   EXPECT_EQ(6, cache.decimals());
691   // Call val_str() then cptr()
692   str= cache.val_str(&str_buff);
693   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
694   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
695   cache.set_datetime(&datetime6, 6);
696   // Now call the other way around: cptr() then val_str()
697   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
698   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
699   // Testing get_TIME_ptr()
700   ltime= cache.get_TIME_ptr();
701   EXPECT_EQ(ltime->year, datetime6.year);
702   EXPECT_EQ(ltime->month, datetime6.month);
703   EXPECT_EQ(ltime->day, datetime6.day);
704   EXPECT_EQ(ltime->hour, datetime6.hour);
705   EXPECT_EQ(ltime->minute, datetime6.minute);
706   EXPECT_EQ(ltime->second, datetime6.second);
707   EXPECT_EQ(ltime->second_part, datetime6.second_part);
708   EXPECT_EQ(ltime->neg, datetime6.neg);
709   EXPECT_EQ(ltime->time_type, datetime6.time_type);
710   // Testing eq()
711   {
712     MYSQL_TIME datetime6_2= datetime6;
713     MYSQL_TIME_cache cache2;
714     datetime6_2.second_part+= 1;
715     cache2.set_datetime(&datetime6_2, 6);
716     EXPECT_EQ(cache.eq(cache), true);
717     EXPECT_EQ(cache.eq(cache2), false);
718     EXPECT_EQ(cache2.eq(cache2), true);
719     EXPECT_EQ(cache2.eq(cache), false);
720   }
721 
722   /*
723      Testing DATETIME(6).
724      Initializing from "struct timeval".
725   */
726   cache.set_datetime(tv6, 6, my_tz_UTC);
727   EXPECT_EQ(1840440237558456896LL, cache.val_packed());
728   EXPECT_EQ(6, cache.decimals());
729   str= cache.val_str(&str_buff);
730   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
731   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
732 
733   /*
734     Testing TIME(6).
735     Initializing from MYSQL_TIME.
736   */
737   cache.set_time(&time6, 6);
738   EXPECT_EQ(709173043776LL, cache.val_packed());
739   EXPECT_EQ(6, cache.decimals());
740   // Call val_str() then cptr()
741   str= cache.val_str(&str_buff);
742   EXPECT_STREQ("10:20:30.123456", str->c_ptr_safe());
743   EXPECT_STREQ("10:20:30.123456", cache.cptr());
744 
745   /*
746     Testing TIME(6).
747     Initializing from "struct timeval".
748   */
749   cache.set_time(tv6, 6, my_tz_UTC);
750   EXPECT_EQ(709173043776LL, cache.val_packed());
751   EXPECT_EQ(6, cache.decimals());
752   str= cache.val_str(&str_buff);
753   EXPECT_STREQ("10:20:30.123456", str->c_ptr_safe());
754   EXPECT_STREQ("10:20:30.123456", cache.cptr());
755 
756   /*
757     Testing DATETIME(5)
758   */
759   MYSQL_TIME datetime5=
760   { 2011, 11, 7, 10, 20, 30, 123450, 0, MYSQL_TIMESTAMP_DATETIME };
761   cache.set_datetime(&datetime5, 5);
762   EXPECT_EQ(1840440237558456890LL, cache.val_packed());
763   EXPECT_EQ(5, cache.decimals());
764   /* Call val_str() then cptr() */
765   str= cache.val_str(&str_buff);
766   EXPECT_STREQ("2011-11-07 10:20:30.12345", str->c_ptr_safe());
767   EXPECT_STREQ("2011-11-07 10:20:30.12345", cache.cptr());
768   cache.set_datetime(&datetime5, 5);
769   /* Now call the other way around: cptr() then val_str() */
770   EXPECT_STREQ("2011-11-07 10:20:30.12345", cache.cptr());
771   EXPECT_STREQ("2011-11-07 10:20:30.12345", str->c_ptr_safe());
772 
773   /*
774     Testing DATE.
775     Initializing from MYSQL_TIME.
776   */
777   MYSQL_TIME date=
778   { 2011, 11, 7, 0, 0, 0, 0, 0, MYSQL_TIMESTAMP_DATE };
779   cache.set_date(&date);
780   EXPECT_EQ(1840439528385413120LL, cache.val_packed());
781   EXPECT_EQ(0, cache.decimals());
782   str= cache.val_str(&str_buff);
783   EXPECT_STREQ("2011-11-07", str->c_ptr_safe());
784   EXPECT_STREQ("2011-11-07", cache.cptr());
785 
786   /*
787     Testing DATE.
788     Initializing from "struct tm".
789   */
790   cache.set_date(tv6, my_tz_UTC);
791   EXPECT_EQ(1840439528385413120LL, cache.val_packed());
792   EXPECT_EQ(0, cache.decimals());
793   str= cache.val_str(&str_buff);
794   EXPECT_STREQ("2011-11-07", str->c_ptr_safe());
795   EXPECT_STREQ("2011-11-07", cache.cptr());
796 }
797 
798 extern "C"
799 {
800   // Verifies that Item_func_conv::val_str does not call my_strntoll()
fail_strntoll(const struct charset_info_st *,const char * s,size_t l,int base,char ** e,int * err)801   longlong fail_strntoll(const struct charset_info_st *, const char *s,
802                          size_t l, int base, char **e, int *err)
803   {
804     ADD_FAILURE() << "Unexpected call";
805     return 0;
806   }
807 }
808 
809 class Mock_charset : public CHARSET_INFO
810 {
811 public:
Mock_charset(const CHARSET_INFO & csi)812   Mock_charset(const CHARSET_INFO &csi)
813   {
814     CHARSET_INFO *this_as_cset= this;
815     *this_as_cset= csi;
816 
817     number= 666;
818     m_cset_handler= *(csi.cset);
819     m_cset_handler.strntoll= fail_strntoll;
820     cset= &m_cset_handler;
821   }
822 private:
823   MY_CHARSET_HANDLER m_cset_handler;
824 };
825 
TEST_F(ItemTest,ItemFuncConvIntMin)826 TEST_F(ItemTest, ItemFuncConvIntMin)
827 {
828   Mock_charset charset(*system_charset_info);
829   SCOPED_TRACE("");
830   Item *item_conv=
831     new Item_func_conv(POS(),
832                        new Item_string("5", 1, &charset),
833                        new Item_int(INT_MIN),   // from_base
834                        new Item_int(INT_MIN));  // to_base
835   Parse_context pc(thd(), thd()->lex->current_select());
836   EXPECT_FALSE(item_conv->itemize(&pc, &item_conv));
837   EXPECT_FALSE(item_conv->fix_fields(thd(), NULL));
838   const String *null_string= NULL;
839   String str;
840   EXPECT_EQ(null_string, item_conv->val_str(&str));
841 }
842 
TEST_F(ItemTest,ItemDecimalTypecast)843 TEST_F(ItemTest, ItemDecimalTypecast)
844 {
845   const char msg[]= "";
846   POS pos;
847   pos.cpp.start= pos.cpp.end= pos.raw.start= pos.raw.end= msg;
848   // Sun Studio needs this null_item,
849   // it fails to compile EXPECT_EQ(NULL, create_func_cast());
850   const Item *null_item= NULL;
851 
852   Cast_type type;
853   type.target= ITEM_CAST_DECIMAL;
854 
855   type.length= "123456789012345678901234567890";
856   type.dec= NULL;
857 
858   {
859     initializer.set_expected_error(ER_TOO_BIG_PRECISION);
860     EXPECT_EQ(null_item, create_func_cast(thd(), pos, NULL, &type));
861   }
862 
863   {
864     char buff[20];
865     my_snprintf(buff, sizeof(buff) - 1, "%d", DECIMAL_MAX_PRECISION + 1);
866     type.length= buff;
867     type.dec= NULL;
868     initializer.set_expected_error(ER_TOO_BIG_PRECISION);
869     EXPECT_EQ(null_item, create_func_cast(thd(), pos, NULL, &type));
870   }
871 
872   {
873     type.length= NULL;
874     type.dec= "123456789012345678901234567890";
875     initializer.set_expected_error(ER_TOO_BIG_SCALE);
876     EXPECT_EQ(null_item, create_func_cast(thd(), pos, NULL, &type));
877   }
878 
879   {
880     char buff[20];
881     my_snprintf(buff, sizeof(buff) - 1, "%d", DECIMAL_MAX_SCALE + 1);
882     type.length= buff;
883     type.dec= buff;
884     initializer.set_expected_error(ER_TOO_BIG_SCALE);
885     EXPECT_EQ(null_item, create_func_cast(thd(), pos, NULL, &type));
886   }
887 
888 }
889 
TEST_F(ItemTest,NormalizedPrint)890 TEST_F(ItemTest, NormalizedPrint)
891 {
892   Item_null *item_null= new Item_null;
893   {
894     String s;
895     item_null->print(&s, QT_ORDINARY);
896     EXPECT_STREQ("NULL", s.c_ptr());
897   }
898   {
899     String s;
900     item_null->print(&s, QT_NORMALIZED_FORMAT);
901     EXPECT_STREQ("?", s.c_ptr());
902   }
903 }
904 
905 }
906