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 Foundation,
21    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 // First include (the generated) my_config.h, to get correct platform defines,
24 // then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
25 #include "my_config.h"
26 #include <gtest/gtest.h>
27 
28 #include "mock_create_field.h"
29 #include "test_utils.h"
30 #include "mock_field_timestamp.h"
31 #include "item.h"
32 #include "sql_class.h"
33 #include "rpl_handler.h"                        // delegates_init()
34 #include "sql_table.h"
35 
36 namespace sql_table_unittest {
37 
38 using my_testing::Server_initializer;
39 using my_testing::Mock_error_handler;
40 
41 /*
42   Test of functionality in the file sql_table.cc
43  */
44 class SqlTableTest : public ::testing::Test
45 {
46 protected:
SetUp()47   virtual void SetUp() { initializer.SetUp(); }
TearDown()48   virtual void TearDown() { initializer.TearDown(); }
49 
get_thd()50   THD *get_thd() { return initializer.thd(); }
51 
52   Server_initializer initializer;
53 };
54 
55 
56 /*
57   Test of promote_first_timestamp_column(). We pass it a list of two TIMESTAMP
58   NOT NULL columns, the first of which should be promoted to DEFAULT
59   CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. The second column should not
60   be promoted.
61  */
TEST_F(SqlTableTest,PromoteFirstTimestampColumn1)62 TEST_F(SqlTableTest, PromoteFirstTimestampColumn1)
63 {
64   Mock_create_field column_1_definition(MYSQL_TYPE_TIMESTAMP, NULL, NULL);
65   Mock_create_field column_2_definition(MYSQL_TYPE_TIMESTAMP, NULL, NULL);
66   column_1_definition.flags|= NOT_NULL_FLAG;
67   column_2_definition.flags|= NOT_NULL_FLAG;
68   List<Create_field> definitions;
69   definitions.push_front(&column_1_definition);
70   definitions.push_back(&column_2_definition);
71   promote_first_timestamp_column(&definitions);
72   EXPECT_EQ(Field::TIMESTAMP_DNUN_FIELD, column_1_definition.unireg_check);
73   EXPECT_EQ(Field::NONE, column_2_definition.unireg_check);
74 }
75 
76 
77 
78 /*
79   Test of promote_first_timestamp_column(). We pass it a list of two TIMESTAMP
80   NOT NULL columns, the first of which should be promoted to DEFAULT
81   CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. The second column should not
82   be promoted.
83  */
TEST_F(SqlTableTest,PromoteFirstTimestampColumn2)84 TEST_F(SqlTableTest, PromoteFirstTimestampColumn2)
85 {
86   Mock_create_field column_1_definition(MYSQL_TYPE_TIMESTAMP2, NULL, NULL);
87   Mock_create_field column_2_definition(MYSQL_TYPE_TIMESTAMP2, NULL, NULL);
88   column_1_definition.flags|= NOT_NULL_FLAG;
89   column_2_definition.flags|= NOT_NULL_FLAG;
90   List<Create_field> definitions;
91   definitions.push_front(&column_1_definition);
92   definitions.push_back(&column_2_definition);
93   promote_first_timestamp_column(&definitions);
94   EXPECT_EQ(Field::TIMESTAMP_DNUN_FIELD, column_1_definition.unireg_check);
95   EXPECT_EQ(Field::NONE, column_2_definition.unireg_check);
96 }
97 
98 
99 /*
100   Test of promote_first_timestamp_column(). We pass it a list of two columns,
101   one TIMESTAMP NULL DEFAULT 1, and one TIMESTAMP NOT NULL. No promotion
102   should take place.
103  */
TEST_F(SqlTableTest,PromoteFirstTimestampColumn3)104 TEST_F(SqlTableTest, PromoteFirstTimestampColumn3)
105 {
106   Item_string  *item_str= new Item_string("1", 1, &my_charset_latin1);
107   Mock_create_field column_1_definition(MYSQL_TYPE_TIMESTAMP, item_str, NULL);
108   Mock_create_field column_2_definition(MYSQL_TYPE_TIMESTAMP, NULL, NULL);
109   column_2_definition.flags|= NOT_NULL_FLAG;
110   List<Create_field> definitions;
111   definitions.push_front(&column_1_definition);
112   definitions.push_back(&column_2_definition);
113   promote_first_timestamp_column(&definitions);
114   EXPECT_EQ(Field::NONE, column_1_definition.unireg_check);
115   EXPECT_EQ(Field::NONE, column_2_definition.unireg_check);
116 }
117 
118 
119 /*
120   This is a test case based on innobase_init()
121   There was an out-of-bounds read when converting "-@" to a table name.
122  */
TEST_F(SqlTableTest,FileNameToTableName)123 TEST_F(SqlTableTest, FileNameToTableName)
124 {
125   struct PackStuff
126   {
127     char foo1;
128     char str[3];
129     char foo2;
130   };
131   PackStuff foo;
132   memcpy(foo.str, "-@", 3);
133   MEM_NOACCESS(&foo.foo1, 1);
134   MEM_NOACCESS(&foo.foo2, 1);
135 
136   const char test_filename[] = "-@";
137   char       test_tablename[sizeof test_filename
138                             + sizeof("#mysql50#") - 1];
139   //#mysql50# is prefix used by MySQL to indicate pre-5.1 table name encoding.
140 
141 
142   // This one used to fail with AddressSanitizer
143   size_t name_length;
144   name_length= filename_to_tablename(test_filename,
145                                      test_tablename,
146                                      sizeof(test_tablename)
147 #ifndef NDEBUG
148                                      , true
149 #endif
150                                      );
151   EXPECT_EQ((sizeof(test_tablename)) - 1, name_length);
152 
153   // This one used to fail if compiled with -DHAVE_VALGRIND
154   name_length= filename_to_tablename(foo.str,
155                                      test_tablename,
156                                      sizeof(test_tablename)
157 #ifndef NDEBUG
158                                      , true
159 #endif
160                                      );
161   EXPECT_EQ((sizeof(test_tablename)) - 1, name_length);
162 
163 }
164 
165 }
166