1 /* Copyright (c) 2012, 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 St, 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
27 #include "test_utils.h"
28
29 #include "sys_vars.h"
30
31 #include "filesort.h"
32 #include "sql_sort.h"
33
34 namespace make_sortkey_unittest {
35
36 using my_testing::Server_initializer;
37 using my_testing::Mock_error_handler;
38
39 /**
40 Test that sortlength() and make_sortkey() agree on what to do:
41 i.e. that there is no buffer underwrite/overwrite in make_sortkey()
42 if sortlength() has set a very small size.
43
44 We allocate a buffer, fill it with 'a's and then tell make_sortkey()
45 to put it's result somewhere in the middle.
46 The buffer should be unchanged outside of the area determined by sortlength.
47 */
48 class MakeSortKeyTest : public ::testing::Test
49 {
50 protected:
MakeSortKeyTest()51 MakeSortKeyTest()
52 {
53 m_sort_fields[0].field= NULL;
54 m_sort_fields[1].field= NULL;
55 m_sort_fields[0].reverse= false;
56 m_sort_fields[1].reverse= false;
57 m_sort_param.local_sortorder=
58 Bounds_checked_array<st_sort_field>(m_sort_fields, 1);
59 memset(m_buff, 'a', sizeof(m_buff));
60 m_to= &m_buff[8];
61 }
62
SetUp()63 virtual void SetUp() { initializer.SetUp(); }
TearDown()64 virtual void TearDown() { initializer.TearDown(); }
65
thd()66 THD *thd() { return initializer.thd(); }
67
verify_buff(uint length)68 void verify_buff(uint length)
69 {
70 for (uchar *pu= m_buff; pu < m_to; ++pu)
71 {
72 EXPECT_EQ('a', *pu) << " position " << pu - m_buff;
73 }
74 for (uchar *pu= m_to + length; pu < m_buff + 100; ++pu)
75 {
76 EXPECT_EQ('a', *pu) << " position " << pu - m_buff;
77 }
78 }
79
80 Server_initializer initializer;
81
82 Sort_param m_sort_param;
83 st_sort_field m_sort_fields[2]; // sortlength() adds an end marker !!
84 bool m_multi_byte_charset;
85 bool m_use_hash;
86 uchar m_ref_buff[4]; // unused, but needed for make_sortkey()
87 uchar m_buff[100];
88 uchar *m_to;
89 };
90
91
TEST_F(MakeSortKeyTest,IntResult)92 TEST_F(MakeSortKeyTest, IntResult)
93 {
94 thd()->variables.max_sort_length= 4U;
95 m_sort_fields[0].item= new Item_int(42);
96
97 const uint total_length=
98 sortlength(thd(), m_sort_fields, 1, &m_multi_byte_charset, &m_use_hash);
99 EXPECT_EQ(sizeof(longlong), total_length);
100 EXPECT_FALSE(m_multi_byte_charset);
101 EXPECT_FALSE(m_use_hash);
102 EXPECT_EQ(sizeof(longlong), m_sort_fields[0].length);
103 EXPECT_EQ(INT_RESULT, m_sort_fields[0].result_type);
104
105 m_sort_param.make_sortkey(m_to, m_ref_buff);
106 SCOPED_TRACE("");
107 verify_buff(total_length);
108 }
109
110
TEST_F(MakeSortKeyTest,IntResultNull)111 TEST_F(MakeSortKeyTest, IntResultNull)
112 {
113 thd()->variables.max_sort_length= 4U;
114 Item *int_item= m_sort_fields[0].item= new Item_int(42);
115 int_item->maybe_null= true;
116 int_item->null_value= true;
117
118 const uint total_length=
119 sortlength(thd(), m_sort_fields, 1, &m_multi_byte_charset, &m_use_hash);
120 EXPECT_EQ(1 + sizeof(longlong), total_length);
121 EXPECT_FALSE(m_multi_byte_charset);
122 EXPECT_FALSE(m_use_hash);
123 EXPECT_EQ(sizeof(longlong), m_sort_fields[0].length);
124 EXPECT_EQ(INT_RESULT, m_sort_fields[0].result_type);
125
126 m_sort_param.make_sortkey(m_to, m_ref_buff);
127 SCOPED_TRACE("");
128 verify_buff(total_length);
129 }
130
TEST_F(MakeSortKeyTest,DecimalResult)131 TEST_F(MakeSortKeyTest, DecimalResult)
132 {
133 const char dec_str[]= "1234567890.1234567890";
134 thd()->variables.max_sort_length= 4U;
135 m_sort_fields[0].item=
136 new Item_decimal(POS(), dec_str, strlen(dec_str), &my_charset_bin);
137 Parse_context pc(thd(), thd()->lex->current_select());
138 EXPECT_FALSE(m_sort_fields[0].item->itemize(&pc, &m_sort_fields[0].item));
139
140 const uint total_length=
141 sortlength(thd(), m_sort_fields, 1, &m_multi_byte_charset, &m_use_hash);
142 EXPECT_EQ(10U, total_length);
143 EXPECT_FALSE(m_multi_byte_charset);
144 EXPECT_FALSE(m_use_hash);
145 EXPECT_EQ(10U, m_sort_fields[0].length);
146 EXPECT_EQ(DECIMAL_RESULT, m_sort_fields[0].result_type);
147
148 m_sort_param.make_sortkey(m_to, m_ref_buff);
149 SCOPED_TRACE("");
150 verify_buff(total_length);
151 }
152
TEST_F(MakeSortKeyTest,RealResult)153 TEST_F(MakeSortKeyTest, RealResult)
154 {
155 const char dbl_str[]= "1234567890.1234567890";
156 thd()->variables.max_sort_length= 4U;
157 m_sort_fields[0].item= new Item_float(dbl_str, strlen(dbl_str));
158
159 const uint total_length=
160 sortlength(thd(), m_sort_fields, 1, &m_multi_byte_charset, &m_use_hash);
161 EXPECT_EQ(sizeof(double), total_length);
162 EXPECT_FALSE(m_multi_byte_charset);
163 EXPECT_FALSE(m_use_hash);
164 EXPECT_EQ(sizeof(double), m_sort_fields[0].length);
165 EXPECT_EQ(REAL_RESULT, m_sort_fields[0].result_type);
166
167 m_sort_param.make_sortkey(m_to, m_ref_buff);
168 SCOPED_TRACE("");
169 verify_buff(total_length);
170 }
171
172 }
173