1 /*
2    Copyright (c) 2014, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software Foundation,
22    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23 
24 // First include (the generated) my_config.h, to get correct platform defines.
25 #include "my_config.h"
26 #include <gtest/gtest.h>
27 
28 #include "item.h"
29 #include "opt_costmodel.h"
30 
31 #include "fake_table.h"
32 #include "test_utils.h"
33 
34 namespace costconstants_unittest {
35 
36 using my_testing::Server_initializer;
37 
38 /*
39   Default values for cost constants. These needs to be updated when
40   cost constants in opt_costconstans.h are changed.
41 */
42 
43 // Default value for Server_cost_constants::ROW_EVALUATE_COST
44 const double default_row_evaluate_cost= 0.2;
45 
46 // Default value for Server_cost_constants::KEY_COMPARE_COST
47 const double default_key_compare_cost= 0.1;
48 
49 // Default value for Server_cost_constants::HEAP_TEMPTABLE_CREATE_COST
50 const double default_memory_temptable_create_cost= 2.0;
51 
52 // Default value for Server_cost_constants::HEAP_TEMPTABLE_ROW_COST
53 const double default_memory_temptable_row_cost= 0.2;
54 
55 // Default value for Server_cost_constants::DISK_TEMPTABLE_CREATE_COST
56 const double default_disk_temptable_create_cost= 40.0;
57 
58 // Default value for Server_cost_constants::DISK_TEMPTABLE_ROW_COST
59 const double default_disk_temptable_row_cost= 1.0;
60 
61 //  Default value SE_cost_constants::MEMORY_BLOCK_READ_COST
62 const double default_memory_block_read_cost= 1.0;
63 
64 //  Default value SE_cost_constants::IO_BLOCK_READ_COST
65 const double default_io_block_read_cost= 1.0;
66 
67 
68 class CostConstantsTest : public ::testing::Test
69 {
70 protected:
SetUp()71   virtual void SetUp()
72   {
73     initializer.SetUp();
74 
75     // Initilize one storage engine
76     LEX_STRING engine_name= {C_STRING_WITH_LEN("InnoDB")};
77     hton2plugin[0]= new st_plugin_int();
78     hton2plugin[0]->name= engine_name;
79   }
80 
TearDown()81   virtual void TearDown()
82   {
83     initializer.TearDown();
84     delete hton2plugin[0];
85     hton2plugin[0]= NULL;
86   }
87 
thd()88   THD *thd() { return initializer.thd(); }
89 
90   Server_initializer initializer;
91 };
92 
93 
94 /*
95   Class for making it possible to test protected member functions
96   of the SE_cost_constants class.
97 */
98 class Testable_SE_cost_constants : public SE_cost_constants
99 {
100 public:
101   /*
102     Wrapper function that allows testing of the protected update() function.
103   */
test_update_func(const LEX_CSTRING & name,const double value)104   cost_constant_error test_update_func(const LEX_CSTRING &name,
105                                        const double value)
106   {
107     return update(name, value);
108   }
109 
110   /*
111     Wrapper function that allows testing of the protected update() function.
112   */
test_update_default_func(const LEX_CSTRING & name,const double value)113   cost_constant_error test_update_default_func(const LEX_CSTRING &name,
114                                                const double value)
115   {
116     return update_default(name, value);
117   }
118 };
119 
120 
121 
122 /*
123   Storage engines can extend the cost model by adding new cost
124   constants.  This is done by making a subclass of the
125   SE_cost_constant class.  To make a limited test for this, a
126   fictional storage engine called TapeEngine is used. The following
127   class adds a new cost constant called TAPE_IO_COST.  Note that this
128   should inherit from SE_cost_constants, but to make it easier to write
129   a unit test, we inherit from Testable_SE_cost_constants.
130 */
131 class TapeEngine_cost_constants : public Testable_SE_cost_constants
132 {
133 public:
TapeEngine_cost_constants()134   TapeEngine_cost_constants() : m_tape_io_cost(200.0),
135     m_tape_io_cost_default(true) {}
136 
tape_io_cost() const137   double tape_io_cost() const { return m_tape_io_cost; }
138 
139 protected:
set(const LEX_CSTRING & name,const double value,bool default_value)140   cost_constant_error set(const LEX_CSTRING &name, const double value,
141                           bool default_value)
142   {
143     // Process TAPE_IO_COST here
144     if (!my_strcasecmp(&my_charset_utf8_general_ci, "TAPE_IO_COST", name.str))
145     {
146       update_cost_value(&m_tape_io_cost, &m_tape_io_cost_default, value,
147                         default_value);
148       return COST_CONSTANT_OK;
149     }
150 
151     // If the cost constant name was not recognized here, call the parent
152     return Testable_SE_cost_constants::set(name, value, default_value);
153   }
154 
155 private:
156   double m_tape_io_cost;
157   bool m_tape_io_cost_default;
158 };
159 
160 
161 /*
162   Class for making it easier to test protected member function of the
163   Cost_model_class. To make it possible to call some of the functions
164   that relies on storage engine plugins being loaded, without having
165   the plugins loaded, this class re-implements a fake version of one
166   of the utility functions.
167 */
168 class Testable_Cost_model_constants : public Cost_model_constants
169 {
170 public:
171   /*
172     Wrapper function that allows testing of the protected inc_ref_count()
173     function.
174   */
test_inc_ref_count()175   void test_inc_ref_count()
176   {
177     inc_ref_count();
178   }
179 
180   /*
181     Wrapper function that allows testing of the protected dec_ref_count()
182     function.
183   */
test_dec_ref_count()184   unsigned int test_dec_ref_count()
185   {
186     return dec_ref_count();
187   }
188 
189 private:
190   /**
191     The implementation of Cost_model_constants relies on using the
192     installed plugins for looking up the handler's slot id based on the
193     name of the storage engine. For unit tests this does not work since
194     no storage engines are installed. We fake this here by overriding the
195     function that looks up the handler's slot id.
196 
197     This function supports two storage engines, "Karius" installed in slot
198     4 and "Baktus" installed in slot 7.
199   */
200 
find_handler_slot_from_name(THD * thd,const LEX_CSTRING & name) const201   uint find_handler_slot_from_name(THD *thd,
202                                    const LEX_CSTRING &name) const
203   {
204     if (my_strcasecmp(&my_charset_utf8_general_ci, "Karius", name.str) == 0)
205       return 4;
206 
207     if (my_strcasecmp(&my_charset_utf8_general_ci, "Baktus", name.str) == 0)
208       return 7;
209 
210     // There is no handler for a storage engine with the given name
211     return HA_SLOT_UNDEF;
212   }
213 };
214 
215 
216 /**
217   Validates that a cost constant object for server cost constants has
218   the expected default values.
219 */
220 
validate_default_server_cost_constants(const Server_cost_constants * cost)221 void validate_default_server_cost_constants(const Server_cost_constants *cost)
222 {
223   EXPECT_EQ(cost->row_evaluate_cost(), default_row_evaluate_cost);
224   EXPECT_EQ(cost->key_compare_cost(), default_key_compare_cost);
225   EXPECT_EQ(cost->memory_temptable_create_cost(),
226             default_memory_temptable_create_cost);
227   EXPECT_EQ(cost->memory_temptable_row_cost(),
228             default_memory_temptable_row_cost);
229   EXPECT_EQ(cost->disk_temptable_create_cost(),
230             default_disk_temptable_create_cost);
231   EXPECT_EQ(cost->disk_temptable_row_cost(), default_disk_temptable_row_cost);
232 }
233 
234 
235 /*
236   Test the Server_cost_constants interface.
237 */
TEST_F(CostConstantsTest,CostConstantsServer)238 TEST_F(CostConstantsTest, CostConstantsServer)
239 {
240   Server_cost_constants server_constants;
241 
242   // Validate expected default values for cost constants
243   validate_default_server_cost_constants(&server_constants);
244 
245   /*
246     Test updating values for cost constants
247   */
248   const double new_value= 3.14;
249 
250   // row_evaluate_cost
251   const LEX_CSTRING row_evaluate_name= {STRING_WITH_LEN("ROW_EVALUATE_COST")};
252   EXPECT_EQ(server_constants.row_evaluate_cost(), default_row_evaluate_cost);
253   EXPECT_EQ(server_constants.set(row_evaluate_name, new_value),
254             COST_CONSTANT_OK);
255   EXPECT_EQ(server_constants.row_evaluate_cost(), new_value);
256 
257   // key_compare_cost
258   const LEX_CSTRING key_compare_name= {STRING_WITH_LEN("KEY_COMPARE_COST")};
259   EXPECT_EQ(server_constants.key_compare_cost(), default_key_compare_cost);
260   EXPECT_EQ(server_constants.set(key_compare_name, new_value),
261             COST_CONSTANT_OK);
262   EXPECT_EQ(server_constants.key_compare_cost(), new_value);
263 
264   // memory_temptable_create_cost
265   const LEX_CSTRING memory_temptable_create_name=
266     {STRING_WITH_LEN("MEMORY_TEMPTABLE_CREATE_COST")};
267   EXPECT_EQ(server_constants.memory_temptable_create_cost(),
268             default_memory_temptable_create_cost);
269   EXPECT_EQ(server_constants.set(memory_temptable_create_name, new_value),
270             COST_CONSTANT_OK);
271   EXPECT_EQ(server_constants.memory_temptable_create_cost(), new_value);
272 
273   // memory_temptable_row_cost
274   const LEX_CSTRING memory_temptable_row_name=
275     {STRING_WITH_LEN("MEMORY_TEMPTABLE_ROW_COST")};
276   EXPECT_EQ(server_constants.memory_temptable_row_cost(),
277             default_memory_temptable_row_cost);
278   EXPECT_EQ(server_constants.set(memory_temptable_row_name, new_value),
279             COST_CONSTANT_OK);
280   EXPECT_EQ(server_constants.memory_temptable_row_cost(), new_value);
281 
282   // disk_temptable_create_cost
283   const LEX_CSTRING disk_temptable_create_name=
284     {STRING_WITH_LEN("DISK_TEMPTABLE_CREATE_COST")};
285   EXPECT_EQ(server_constants.disk_temptable_create_cost(),
286             default_disk_temptable_create_cost);
287   EXPECT_EQ(server_constants.set(disk_temptable_create_name, new_value),
288             COST_CONSTANT_OK);
289   EXPECT_EQ(server_constants.disk_temptable_create_cost(), new_value);
290 
291   // disk_temptable_row_cost
292   const LEX_CSTRING disk_temptable_row_name=
293     {STRING_WITH_LEN("DISK_TEMPTABLE_ROW_COST")};
294   EXPECT_EQ(server_constants.disk_temptable_row_cost(),
295             default_disk_temptable_row_cost);
296   EXPECT_EQ(server_constants.set(disk_temptable_row_name, new_value),
297             COST_CONSTANT_OK);
298   EXPECT_EQ(server_constants.disk_temptable_row_cost(), new_value);
299 
300   /*
301     Test with upper, lower and mixed case for cost constant name.
302   */
303   const LEX_CSTRING name_upper= {STRING_WITH_LEN("ROW_EVALUATE_COST")};
304   const LEX_CSTRING name_lower= {STRING_WITH_LEN("row_evaluate_cost")};
305   const LEX_CSTRING name_mixed= {STRING_WITH_LEN("rOw_EvAlUaTe_CoSt")};
306   const LEX_CSTRING name_space= {STRING_WITH_LEN("ROW_EVALUATE_COST ")};
307 
308   const double value1= 2.74;
309   const double value2= 3.14;
310 
311   EXPECT_EQ(server_constants.set(name_upper, value1), COST_CONSTANT_OK);
312   EXPECT_EQ(server_constants.row_evaluate_cost(), value1);
313   EXPECT_EQ(server_constants.set(name_lower, value2), COST_CONSTANT_OK);
314   EXPECT_EQ(server_constants.row_evaluate_cost(), value2);
315   EXPECT_EQ(server_constants.set(name_mixed, value1), COST_CONSTANT_OK);
316   EXPECT_EQ(server_constants.row_evaluate_cost(), value1);
317 
318   EXPECT_EQ(server_constants.set(name_space, value2), UNKNOWN_COST_NAME);
319   EXPECT_EQ(server_constants.row_evaluate_cost(), value1);
320 
321   /*
322     Test with an unknown cost constant name.
323   */
324   const LEX_CSTRING unknown_name= {STRING_WITH_LEN("UNKNOWN_COST")};
325   EXPECT_EQ(server_constants.set(unknown_name, value1), UNKNOWN_COST_NAME);
326 
327   /*
328     Test with illegal cost values: negative or zero should not be allowed.
329   */
330   EXPECT_EQ(server_constants.row_evaluate_cost(), value1);
331   EXPECT_EQ(server_constants.set(row_evaluate_name, -1.0), INVALID_COST_VALUE);
332   EXPECT_EQ(server_constants.row_evaluate_cost(), value1);
333   EXPECT_EQ(server_constants.set(row_evaluate_name, 0.0), INVALID_COST_VALUE);
334   EXPECT_EQ(server_constants.row_evaluate_cost(), value1);
335 }
336 
337 
338 /*
339   Test the SE_cost_constants interface.
340 */
TEST_F(CostConstantsTest,CostConstantsStorageEngine)341 TEST_F(CostConstantsTest, CostConstantsStorageEngine)
342 {
343   SE_cost_constants se_constants;
344 
345   // Validate expected default values for cost constants
346   EXPECT_EQ(se_constants.memory_block_read_cost(),
347             default_memory_block_read_cost);
348   EXPECT_EQ(se_constants.io_block_read_cost(), default_io_block_read_cost);
349 
350   /*
351     Test updating values for cost constants
352   */
353   Testable_SE_cost_constants se_constants2;
354 
355   const double new_value1= 2.74;
356   const double new_value2= 3.14;
357 
358   /*
359     Test memory_block_read_cost
360   */
361   const LEX_CSTRING memory_block_read_name=
362     {STRING_WITH_LEN("MEMORY_BLOCK_READ_COST")};
363 
364   // Update the default value, first time
365   EXPECT_EQ(se_constants2.test_update_default_func(memory_block_read_name,
366                                                    new_value1),
367             COST_CONSTANT_OK);
368   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value1);
369 
370   // Update the default value, second time
371   EXPECT_EQ(se_constants2.test_update_default_func(memory_block_read_name,
372                                                    new_value2),
373             COST_CONSTANT_OK);
374   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value2);
375 
376   // Update with a engine specific value, first time
377   EXPECT_EQ(se_constants2.test_update_func(memory_block_read_name, new_value1),
378             COST_CONSTANT_OK);
379   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value1);
380 
381   // Update with a engine specific value, second time
382   EXPECT_EQ(se_constants2.test_update_func(memory_block_read_name, new_value2),
383             COST_CONSTANT_OK);
384   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value2);
385 
386   // Update the default value, this should not change the value
387   EXPECT_EQ(se_constants2.test_update_default_func(memory_block_read_name,
388                                                    new_value1),
389             COST_CONSTANT_OK);
390   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value2);
391 
392   /*
393     Test with upper, lower and mixed case for cost constant name.
394   */
395   const LEX_CSTRING mem_name_upper= {STRING_WITH_LEN("MEMORY_BLOCK_READ_COST")};
396   const LEX_CSTRING mem_name_lower= {STRING_WITH_LEN("memory_block_read_cost")};
397   const LEX_CSTRING mem_name_mixed= {STRING_WITH_LEN("mEmOrY_bLoCk_ReAd_CoSt")};
398 
399   EXPECT_EQ(se_constants2.test_update_func(mem_name_upper, new_value1),
400             COST_CONSTANT_OK);
401   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value1);
402   EXPECT_EQ(se_constants2.test_update_func(mem_name_lower, new_value2),
403             COST_CONSTANT_OK);
404   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value2);
405   EXPECT_EQ(se_constants2.test_update_func(mem_name_mixed, new_value1),
406             COST_CONSTANT_OK);
407   EXPECT_EQ(se_constants2.memory_block_read_cost(), new_value1);
408 
409   /*
410     Test io_block_read_cost
411   */
412   const LEX_CSTRING io_block_read_name= {STRING_WITH_LEN("IO_BLOCK_READ_COST")};
413 
414   // Update the default value, first time
415   EXPECT_EQ(se_constants2.test_update_default_func(io_block_read_name,
416                                                    new_value1),
417             COST_CONSTANT_OK);
418   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
419 
420   // Update the default value, second time
421   EXPECT_EQ(se_constants2.test_update_default_func(io_block_read_name,
422                                                    new_value2),
423             COST_CONSTANT_OK);
424   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value2);
425 
426   // Update with a engine specific value, first time
427   EXPECT_EQ(se_constants2.test_update_func(io_block_read_name, new_value1),
428             COST_CONSTANT_OK);
429   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
430 
431   // Update with a engine specific value, second time
432   EXPECT_EQ(se_constants2.test_update_func(io_block_read_name, new_value2),
433             COST_CONSTANT_OK);
434   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value2);
435 
436   // Update the default value, this should not change the value
437   EXPECT_EQ(se_constants2.test_update_default_func(io_block_read_name,
438                                                    new_value1),
439             COST_CONSTANT_OK);
440   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value2);
441 
442   /*
443     Test with upper, lower and mixed case for cost constant name.
444   */
445   const LEX_CSTRING io_name_upper= {STRING_WITH_LEN("IO_BLOCK_READ_COST")};
446   const LEX_CSTRING io_name_lower= {STRING_WITH_LEN("io_block_read_cost")};
447   const LEX_CSTRING io_name_mixed= {STRING_WITH_LEN("iO_bLoCk_ReAd_CoSt")};
448 
449   EXPECT_EQ(se_constants2.test_update_func(io_name_upper, new_value1),
450             COST_CONSTANT_OK);
451   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
452   EXPECT_EQ(se_constants2.test_update_func(io_name_lower, new_value2),
453             COST_CONSTANT_OK);
454   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value2);
455   EXPECT_EQ(se_constants2.test_update_func(io_name_mixed, new_value1),
456             COST_CONSTANT_OK);
457   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
458 
459   /*
460     Test with an unknown cost constant name.
461   */
462   const LEX_CSTRING unknown_name= {STRING_WITH_LEN("UNKNOWN_COST")};
463   EXPECT_EQ(se_constants2.test_update_func(unknown_name, new_value2),
464             UNKNOWN_COST_NAME);
465   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
466 
467   /*
468     Test with illegal cost values: negative and zero is illegal.
469   */
470   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
471   EXPECT_EQ(se_constants2.test_update_func(io_block_read_name, -1.0),
472             INVALID_COST_VALUE);
473   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
474   EXPECT_EQ(se_constants2.test_update_func(io_block_read_name, 0.0),
475             INVALID_COST_VALUE);
476   EXPECT_EQ(se_constants2.io_block_read_cost(), new_value1);
477 
478   /*
479     Test with cost constants for a storage engine that has added a new
480     storage engine specific cost constant named TAPE_IO_COST.
481   */
482   TapeEngine_cost_constants tape_constants;
483 
484   // Validate expected default values for cost constants
485   EXPECT_EQ(tape_constants.io_block_read_cost(), default_io_block_read_cost);
486   EXPECT_EQ(tape_constants.tape_io_cost(), 200.0);
487 
488   // change io_block_read_cost
489   EXPECT_EQ(tape_constants.io_block_read_cost(), default_io_block_read_cost);
490   EXPECT_EQ(tape_constants.test_update_func(io_block_read_name, new_value1),
491             COST_CONSTANT_OK);
492   EXPECT_EQ(tape_constants.io_block_read_cost(), new_value1);
493 
494   // change tape_io_cost
495   const LEX_CSTRING tape_io_name= {STRING_WITH_LEN("TAPE_IO_COST")};
496   EXPECT_EQ(tape_constants.tape_io_cost(), 200.0);
497 
498   // Change default value for tape_io_cost
499   EXPECT_EQ(tape_constants.test_update_default_func(tape_io_name, new_value1),
500             COST_CONSTANT_OK);
501   EXPECT_EQ(tape_constants.tape_io_cost(), new_value1);
502 
503   // Change engine specific value for tape_io_cost
504   EXPECT_EQ(tape_constants.test_update_func(tape_io_name, new_value2),
505             COST_CONSTANT_OK);
506   EXPECT_EQ(tape_constants.tape_io_cost(), new_value2);
507 
508   // Test with an unknown cost constant name.
509   EXPECT_EQ(tape_constants.test_update_func(unknown_name, new_value1),
510             UNKNOWN_COST_NAME);
511 }
512 
513 /*
514   Test the Cost model constants interface.
515 */
TEST_F(CostConstantsTest,CostConstants)516 TEST_F(CostConstantsTest, CostConstants)
517 {
518   /*
519     Test ref counter.
520   */
521   {
522     Testable_Cost_model_constants cost_constants_ref_test;
523 
524     cost_constants_ref_test.test_inc_ref_count();
525     cost_constants_ref_test.test_inc_ref_count();
526     EXPECT_EQ(cost_constants_ref_test.test_dec_ref_count(), 1U);
527     EXPECT_EQ(cost_constants_ref_test.test_dec_ref_count(), 0U);
528   }
529 
530   /*
531     Test default server cost constants.
532   */
533   Cost_model_constants cost_constants;
534 
535   const Server_cost_constants *server_const=
536     cost_constants.get_server_cost_constants();
537 
538   validate_default_server_cost_constants(server_const);
539 
540   /*
541     Test default table cost constants.
542   */
543   Fake_TABLE table(1, false);
544 
545   const SE_cost_constants *se_const=
546     cost_constants.get_se_cost_constants(&table);
547 
548   // Validate expected default values for cost constants
549   EXPECT_EQ(se_const->memory_block_read_cost(), default_memory_block_read_cost);
550   EXPECT_EQ(se_const->io_block_read_cost(), default_io_block_read_cost);
551 
552   /*
553     Test updating server constants.
554   */
555   const double new_value1= 2.74;
556   const double new_value2= 3.14;
557   const double new_value3= 5.00;
558 
559   const LEX_CSTRING row_evaluate_name= {STRING_WITH_LEN("ROW_EVALUATE_COST")};
560   EXPECT_EQ(cost_constants.update_server_cost_constant(row_evaluate_name,
561                                                        new_value1),
562             COST_CONSTANT_OK);
563   server_const= cost_constants.get_server_cost_constants();
564   EXPECT_EQ(server_const->row_evaluate_cost(), new_value1);
565 
566   const LEX_CSTRING unknown_name= {STRING_WITH_LEN("UNKNOWN_COST")};
567   EXPECT_EQ(cost_constants.update_server_cost_constant(unknown_name,
568                                                        new_value2),
569             UNKNOWN_COST_NAME);
570 
571   // Test with illegal cost constant values
572   EXPECT_EQ(server_const->row_evaluate_cost(), new_value1);
573   EXPECT_EQ(cost_constants.update_server_cost_constant(row_evaluate_name,
574                                                        -1.0),
575             INVALID_COST_VALUE);
576   EXPECT_EQ(server_const->row_evaluate_cost(), new_value1);
577   EXPECT_EQ(cost_constants.update_server_cost_constant(row_evaluate_name,
578                                                        0.0),
579            INVALID_COST_VALUE );
580   EXPECT_EQ(server_const->row_evaluate_cost(), new_value1);
581 
582   /*
583     Test updating table cost constants.
584   */
585   const LEX_CSTRING default_name= {STRING_WITH_LEN("default")};
586   const LEX_CSTRING io_block_read_name= {STRING_WITH_LEN("IO_BLOCK_READ_COST")};
587   EXPECT_EQ(
588     cost_constants.update_engine_cost_constant(NULL, default_name, 0,
589                                                io_block_read_name, new_value1),
590             COST_CONSTANT_OK);
591 
592   // Verify that the cost constant is updated
593   se_const= cost_constants.get_se_cost_constants(&table);
594   EXPECT_EQ(se_const->io_block_read_cost(), new_value1);
595 
596   /*
597     Do a second update of the same default value.
598   */
599   EXPECT_EQ(
600     cost_constants.update_engine_cost_constant(NULL, default_name, 0,
601                                                io_block_read_name, new_value2),
602             COST_CONSTANT_OK);
603 
604   // Verify that the cost constant is updated
605   se_const= cost_constants.get_se_cost_constants(&table);
606   EXPECT_EQ(se_const->io_block_read_cost(), new_value2);
607 
608   /*
609     Test with illegal cost constant values.
610   */
611   EXPECT_EQ(
612     cost_constants.update_engine_cost_constant(NULL, default_name, 0,
613                                                io_block_read_name, -1.0),
614     INVALID_COST_VALUE);
615   EXPECT_EQ(se_const->io_block_read_cost(), new_value2);
616   EXPECT_EQ(
617     cost_constants.update_engine_cost_constant(NULL, default_name, 0,
618                                                io_block_read_name, 0.0),
619     INVALID_COST_VALUE);
620   EXPECT_EQ(se_const->io_block_read_cost(), new_value2);
621 
622   /*
623     Test updating with a none existing cost constant.
624   */
625   const LEX_CSTRING lunch_cost_name= {STRING_WITH_LEN("LUNCH_COST")};
626   EXPECT_EQ(
627     cost_constants.update_engine_cost_constant(NULL, default_name, 0,
628                                                lunch_cost_name, new_value1),
629     UNKNOWN_COST_NAME);
630 
631   /*
632     Test handling of illegal storage category number.
633   */
634   EXPECT_EQ(
635     cost_constants.update_engine_cost_constant(NULL, default_name, 100,
636                                                io_block_read_name, new_value1),
637     INVALID_DEVICE_TYPE);
638 
639   // Verify that the cost constant is not updated
640   se_const= cost_constants.get_se_cost_constants(&table);
641   EXPECT_EQ(se_const->io_block_read_cost(), new_value2);
642 
643   /*
644     Create two table objects that are stored in different storage engines.
645   */
646   Fake_TABLE table_se1(1, false);
647   table_se1.file->ht->slot= 1;
648   Fake_TABLE table_se2(1, false);
649   table_se2.file->ht->slot= 2;
650 
651   Cost_model_constants cost_constants2;
652 
653   const SE_cost_constants* se_cost1=
654     cost_constants2.get_se_cost_constants(&table_se1);
655   const SE_cost_constants* se_cost2=
656     cost_constants2.get_se_cost_constants(&table_se2);
657 
658   // Verify that both tables have the same default value
659   EXPECT_EQ(se_cost1->io_block_read_cost(), default_io_block_read_cost);
660   EXPECT_EQ(se_cost2->io_block_read_cost(), default_io_block_read_cost);
661 
662   // Update the default value and verify that the cost constant for both
663   // tables are changed.
664   EXPECT_EQ(cost_constants2.update_engine_cost_constant(NULL, default_name, 0,
665                                                         io_block_read_name,
666                                                         new_value1),
667             COST_CONSTANT_OK);
668   EXPECT_EQ(se_cost1->io_block_read_cost(), new_value1);
669   EXPECT_EQ(se_cost2->io_block_read_cost(), new_value1);
670 
671   /*
672     Create a cost model constants set that has cost constants for the
673     two storage engines named "Karius" and "Baktus". We use this instead
674     of the real Cost_model_constant class since that relies on that the
675     plugins for storage engines have been initialized.
676   */
677   Testable_Cost_model_constants cost_constants3;
678 
679   const LEX_CSTRING karius_name= {STRING_WITH_LEN("Karius")};
680 
681   // Create two tables that use these storage engines
682   Fake_TABLE table_karius(1, false);
683   table_karius.file->ht->slot= 4;     // Karius is in ht->slot 4
684   Fake_TABLE table_baktus(1, false);
685   table_baktus.file->ht->slot= 7;     // Baktus is in ht->slot 7
686 
687   // Get cost constants to use for these tables
688   const SE_cost_constants* se_cost_karius=
689     cost_constants3.get_se_cost_constants(&table_karius);
690   const SE_cost_constants* se_cost_baktus=
691     cost_constants3.get_se_cost_constants(&table_baktus);
692 
693   // Verify that both tables have the same default value
694   EXPECT_EQ(se_cost_karius->io_block_read_cost(), default_io_block_read_cost);
695   EXPECT_EQ(se_cost_baktus->io_block_read_cost(), default_io_block_read_cost);
696 
697   // Update the default value and verify that the cost constant for both
698   // tables are changed.
699   EXPECT_EQ(cost_constants3.update_engine_cost_constant(NULL, default_name, 0,
700                                                         io_block_read_name,
701                                                         new_value1),
702             COST_CONSTANT_OK);
703   EXPECT_EQ(se_cost_karius->io_block_read_cost(), new_value1);
704   EXPECT_EQ(se_cost_baktus->io_block_read_cost(), new_value1);
705 
706   // Update one of the storage engines with a new cost value and verify that
707   // only this engine got the new cost value
708   EXPECT_EQ(cost_constants3.update_engine_cost_constant(NULL, karius_name, 0,
709                                                         io_block_read_name,
710                                                         new_value2),
711             COST_CONSTANT_OK);
712   EXPECT_EQ(se_cost_karius->io_block_read_cost(), new_value2);
713   EXPECT_EQ(se_cost_baktus->io_block_read_cost(), new_value1);
714 
715   // Do a new update of the default value and verify that only the storage
716   // engine that still is using the default value is changed.
717   EXPECT_EQ(cost_constants3.update_engine_cost_constant(NULL, default_name, 0,
718                                                         io_block_read_name,
719                                                         new_value3),
720             COST_CONSTANT_OK);
721   EXPECT_EQ(se_cost_karius->io_block_read_cost(), new_value2);
722   EXPECT_EQ(se_cost_baktus->io_block_read_cost(), new_value3);
723 }
724 
725 }
726