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