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