1 /* Copyright (c) 2012, 2015, 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, 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 #include "handler-t.h"
24 #include "test_utils.h"
25 #include "fake_table.h"
26 #include "mock_field_datetime.h"
27 
28 #include "sql_executor.h"
29 
30 namespace {
31 
32 using my_testing::Server_initializer;
33 using my_testing::Mock_error_handler;
34 
35 using ::testing::StrictMock;
36 
37 class HandlerTest : public ::testing::Test
38 {
39 protected:
SetUp()40   virtual void SetUp() { initializer.SetUp(); }
TearDown()41   virtual void TearDown() { initializer.TearDown(); }
42 
thd()43   THD *thd() { return initializer.thd(); }
44 
45   Server_initializer initializer;
46 };
47 
48 
49 /**
50   Some handler error returns are passed on to report_handler_error()
51   which will:
52     - ignore errors like END_OF_FILE
53     - print most errors to the error log
54     - pass the error code back to handler::print_error()
55  */
TEST_F(HandlerTest,ReportErrorHandler)56 TEST_F(HandlerTest, ReportErrorHandler)
57 {
58   Mock_field_datetime field_datetime;
59   Fake_TABLE table(&field_datetime);
60   handlerton *hton= NULL;
61   StrictMock<Mock_HANDLER> mock_handler(hton, table.get_share());
62   table.set_handler(&mock_handler);
63 
64   // This error should be ignored.
65   EXPECT_EQ(-1, report_handler_error(&table, HA_ERR_END_OF_FILE));
66 
67   // This one should not be printed to stderr, but passed on to the handler.
68   EXPECT_CALL(mock_handler, print_error(HA_ERR_TABLE_DEF_CHANGED, 0)).Times(1);
69   EXPECT_EQ(1, report_handler_error(&table, HA_ERR_TABLE_DEF_CHANGED));
70 }
71 
72 
TEST_F(HandlerTest,TableInMemoryEstimate)73 TEST_F(HandlerTest, TableInMemoryEstimate)
74 {
75   Mock_field_datetime field_datetime;
76   Fake_TABLE table(&field_datetime);
77   handlerton *hton= NULL;
78   StrictMock<Mock_HANDLER> mock_handler(hton, table.get_share());
79   table.set_handler(&mock_handler);
80 
81   // Verify that the handler does not know the buffer size
82   EXPECT_EQ(mock_handler.get_memory_buffer_size(), -1);
83   /*
84     The implementation of table_in_memory_estimate() assumes that the
85     memory buffer is 100 MB if the storage engine does not report the
86     size of its memory buffer.
87   */
88   const uint mem_buf_size= 100 * 1024 * 1024;
89 
90   /*
91     Define representative table sizes to use in tests.
92   */
93   // Table that is less than 20% of memory buffer
94   const uint table_size_small= static_cast<uint>(mem_buf_size * 0.19);
95   // Table that is larger than 20% but less than 100% of memory buffer
96   const uint table_size_medium= mem_buf_size / 2;
97   // Table that is larger than memory buffer
98   const uint table_size_large= mem_buf_size * 2;
99 
100   /*
101     Verify that the default table in memory estimate for a handler has been
102     correctly initialized.
103   */
104   EXPECT_EQ(mock_handler.stats.table_in_mem_estimate,
105             IN_MEMORY_ESTIMATE_UNKNOWN);
106 
107   /*
108     Test with a table that is less than 20% of memory buffer. This should
109     be entirely in the memory buffer.
110   */
111   mock_handler.stats.data_file_length= table_size_small;
112   EXPECT_EQ(mock_handler.table_in_memory_estimate(), 1.0);
113 
114   /*
115     Test with a medium sized table that is more than 20% but less than
116     100% of the memory buffer size.
117   */
118   mock_handler.stats.data_file_length= table_size_medium;
119   EXPECT_GT(mock_handler.table_in_memory_estimate(), 0.0);
120   EXPECT_LT(mock_handler.table_in_memory_estimate(), 1.0);
121 
122   /*
123     Test with a huge table. This should not be in memory at all.
124   */
125   mock_handler.stats.data_file_length= table_size_large;
126   EXPECT_EQ(mock_handler.table_in_memory_estimate(), 0.0);
127 
128   /*
129     Simulate that the storage engine has reported that 50 percent of the
130     table is in a memory buffer.
131   */
132   mock_handler.stats.table_in_mem_estimate= 0.5;
133 
134   /*
135     Set the table size to be less than 20 percent but larger than 10K.
136   */
137   mock_handler.stats.data_file_length= table_size_small;
138   EXPECT_DOUBLE_EQ(mock_handler.table_in_memory_estimate(), 0.5);
139 
140   /*
141     Set the table size to be larger than 20 percent but less than 100 percent.
142   */
143   mock_handler.stats.data_file_length= table_size_medium;
144   EXPECT_DOUBLE_EQ(mock_handler.table_in_memory_estimate(), 0.5);
145 
146   /*
147     Set the table size to be larger than the memory buffer.
148   */
149   mock_handler.stats.data_file_length= table_size_large;
150   EXPECT_DOUBLE_EQ(mock_handler.table_in_memory_estimate(), 0.5);
151 }
152 
153 
TEST_F(HandlerTest,IndexInMemoryEstimate)154 TEST_F(HandlerTest, IndexInMemoryEstimate)
155 {
156   Mock_field_datetime field_datetime;
157   Fake_TABLE table(&field_datetime);
158   handlerton *hton= NULL;
159   StrictMock<Mock_HANDLER> mock_handler(hton, table.get_share());
160   table.set_handler(&mock_handler);
161   mock_handler.change_table_ptr(&table, table.get_share());
162   const uint key_no= 0;
163 
164   // Verify that the handler does not know the buffer size
165   EXPECT_EQ(mock_handler.get_memory_buffer_size(), -1);
166   /*
167     The implementation of index_in_memory_estimate() assumes that the
168     memory buffer is 100 MB if the storage engine does not report the
169     size of its memory buffer.
170   */
171   const uint mem_buf_size= 100 * 1024 * 1024;
172 
173   /*
174     Define representative table and index sizes to use in tests.
175   */
176   // Index that is less than 20% of memory buffer
177   const uint index_size_small= static_cast<uint>(mem_buf_size * 0.19);
178   // Index that is larger than 20% but less than 100% of memory buffer
179   const uint index_size_medium= mem_buf_size / 2;
180   // Index that is larger than memory buffer
181   const uint index_size_large= mem_buf_size * 2;
182 
183   // Initialize the estimate for how much of the index that is in memory
184   table.key_info[key_no].set_in_memory_estimate(IN_MEMORY_ESTIMATE_UNKNOWN);
185 
186   /*
187     Test with an index that is less than 20% of memory buffer. This should
188     be entirely in the memory buffer.
189   */
190   mock_handler.stats.index_file_length= index_size_small;
191   EXPECT_EQ(mock_handler.index_in_memory_estimate(key_no), 1.0);
192 
193   /*
194     Test with a medium sized index that is more than 20% but less than
195     100% of the memory buffer size.
196   */
197   mock_handler.stats.index_file_length= index_size_medium;
198   EXPECT_GT(mock_handler.index_in_memory_estimate(key_no), 0.0);
199   EXPECT_LT(mock_handler.index_in_memory_estimate(key_no), 1.0);
200 
201   /*
202     Test with a huge index. This should not be in memory at all.
203   */
204   mock_handler.stats.index_file_length= index_size_large;
205   EXPECT_EQ(mock_handler.index_in_memory_estimate(key_no), 0.0);
206 
207   /*
208     Simulate that the storage engine has reported that 50 percent of the
209     index is in a memory buffer.
210   */
211   table.key_info[key_no].set_in_memory_estimate(0.5);
212 
213   /*
214     Set the index size to be less than 20 percent but larger than 10K.
215   */
216   mock_handler.stats.index_file_length= index_size_small;
217   EXPECT_DOUBLE_EQ(mock_handler.index_in_memory_estimate(key_no), 0.5);
218 
219   /*
220     Set the index size to be larger than 20 percent but less than 100 percent.
221   */
222   mock_handler.stats.index_file_length= index_size_medium;
223   EXPECT_DOUBLE_EQ(mock_handler.index_in_memory_estimate(key_no), 0.5);
224 
225   /*
226     Set the index size to be larger than the memory buffer.
227   */
228   mock_handler.stats.index_file_length= index_size_large;
229   EXPECT_DOUBLE_EQ(mock_handler.index_in_memory_estimate(key_no), 0.5);
230 }
231 
232 }
233