1 /* Copyright (c) 2008, 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 #include <my_global.h>
24 #include <my_thread.h>
25 #include <pfs_instr.h>
26 #include <pfs_stat.h>
27 #include <pfs_global.h>
28 #include <pfs_user.h>
29 #include <pfs_host.h>
30 #include <pfs_account.h>
31 #include <pfs_instr_class.h>
32 #include <pfs_buffer_container.h>
33 #include <tap.h>
34
35 #include "stub_pfs_global.h"
36 #include "stub_global_status_var.h"
37
38 #include <string.h> /* memset */
39
40 extern struct PSI_bootstrap PFS_bootstrap;
41
42 PSI_thread_key thread_key_1;
43 PSI_thread_info all_thread[]=
44 {
45 {&thread_key_1, "T-1", 0}
46 };
47
48 /** Simulate initialize_performance_schema(). */
49
initialize_performance_schema_helper(PFS_global_param * param)50 PSI * initialize_performance_schema_helper(PFS_global_param *param)
51 {
52 PSI *psi;
53
54 stub_alloc_always_fails= false;
55 stub_alloc_fails_after_count= 1000;
56
57 param->m_enabled= true;
58 param->m_thread_class_sizing= 10;
59 param->m_thread_sizing= 1000;
60
61 pre_initialize_performance_schema();
62
63 init_event_name_sizing(param);
64 init_sync_class(param->m_mutex_class_sizing, param->m_rwlock_class_sizing, param->m_cond_class_sizing);
65 init_thread_class(param->m_thread_class_sizing);
66 init_table_share(param->m_table_share_sizing);
67 init_table_share_lock_stat(param->m_table_lock_stat_sizing);
68 init_table_share_index_stat(param->m_index_stat_sizing);
69 init_file_class(param->m_file_class_sizing);
70 init_stage_class(param->m_stage_class_sizing);
71 init_statement_class(param->m_statement_class_sizing);
72 init_socket_class(param->m_socket_class_sizing);
73 init_memory_class(param->m_memory_class_sizing);
74 init_instruments(param);
75 init_events_waits_history_long(param->m_events_waits_history_long_sizing);
76 init_events_stages_history_long(param->m_events_stages_history_long_sizing);
77 init_events_statements_history_long(param->m_events_statements_history_long_sizing);
78 init_events_transactions_history_long(param->m_events_transactions_history_long_sizing);
79 init_file_hash(param);
80 init_table_share_hash(param);
81 init_setup_actor(param);
82 init_setup_actor_hash(param);
83 init_setup_object(param);
84 init_setup_object_hash(param);
85 init_host(param);
86 init_host_hash(param);
87 init_user(param);
88 init_user_hash(param);
89 init_account(param);
90 init_account_hash(param);
91 init_digest(param);
92 init_digest_hash(param);
93 init_program(param);
94 init_program_hash(param);
95 init_prepared_stmt(param);
96 pfs_initialized= true;
97
98 PSI_bootstrap *boot= &PFS_bootstrap;
99 psi= (PSI *)boot->get_interface(PSI_VERSION_1);
100 psi->register_thread("test", all_thread, 1);
101 return (psi);
102 }
103
test_oom()104 void test_oom()
105 {
106 int rc;
107 PSI *psi;
108 PFS_global_param param;
109
110 stub_alloc_always_fails= false;
111 stub_alloc_fails_after_count= 1000;
112
113 PFS_mutex_class dummy_mutex_class;
114 PFS_rwlock_class dummy_rwlock_class;
115 PFS_cond_class dummy_cond_class;
116 PFS_thread_class dummy_thread_class;
117 PFS_file_class dummy_file_class;
118 PFS_socket_class dummy_socket_class;
119 PFS_table_share dummy_table_share;
120 PFS_mutex *mutex_1;
121 PFS_mutex *mutex_2;
122 PFS_rwlock *rwlock_1;
123 PFS_rwlock *rwlock_2;
124 PFS_cond *cond_1;
125 PFS_cond *cond_2;
126 PFS_thread *thread_1;
127 PFS_thread *thread_2;
128 PFS_file *file_1;
129 PFS_file *file_2;
130 PFS_socket *socket_1;
131 PFS_socket *socket_2;
132 PFS_table *table_1;
133 PFS_table *table_2;
134
135 memset(& param, 0xFF, sizeof(param));
136 param.m_enabled= true;
137 param.m_mutex_class_sizing= 1;
138 param.m_rwlock_class_sizing= 1;
139 param.m_cond_class_sizing= 1;
140 param.m_thread_class_sizing= 1;
141 param.m_table_share_sizing= 1;
142 param.m_file_class_sizing= 1;
143 param.m_socket_class_sizing= 1;
144 param.m_mutex_sizing= 1;
145 param.m_rwlock_sizing= 1;
146 param.m_cond_sizing= 1;
147 param.m_thread_sizing= 1;
148 param.m_table_sizing= 1;
149 param.m_file_sizing= 1;
150 param.m_file_handle_sizing= 100;
151 param.m_socket_sizing= 2;
152 param.m_events_waits_history_sizing= 10;
153 param.m_events_waits_history_long_sizing= 10000;
154 param.m_setup_actor_sizing= 0;
155 param.m_setup_object_sizing= 0;
156 param.m_host_sizing= 0;
157 param.m_user_sizing= 0;
158 param.m_account_sizing= 0;
159 param.m_stage_class_sizing= 0;
160 param.m_events_stages_history_sizing= 0;
161 param.m_events_stages_history_long_sizing= 0;
162 param.m_statement_class_sizing= 0;
163 param.m_events_statements_history_sizing= 0;
164 param.m_events_statements_history_long_sizing= 0;
165 param.m_events_transactions_history_sizing= 0;
166 param.m_events_transactions_history_long_sizing= 0;
167 param.m_digest_sizing= 0;
168 param.m_session_connect_attrs_sizing= 0;
169 param.m_program_sizing= 0;
170 param.m_prepared_stmt_sizing= 0;
171 param.m_statement_stack_sizing= 0;
172 param.m_memory_class_sizing= 1;
173 param.m_metadata_lock_sizing= 0;
174 param.m_max_digest_length= 0;
175 param.m_max_sql_text_length= 0;
176
177 init_event_name_sizing(¶m);
178 rc= init_instruments(¶m);
179 ok(rc == 0, "instances init");
180
181 dummy_mutex_class.m_event_name_index= 0;
182 dummy_mutex_class.m_flags= 0;
183 dummy_mutex_class.m_enabled= true;
184 dummy_mutex_class.m_volatility= PSI_VOLATILITY_UNKNOWN;
185 dummy_rwlock_class.m_event_name_index= 1;
186 dummy_rwlock_class.m_flags= 0;
187 dummy_rwlock_class.m_enabled= true;
188 dummy_rwlock_class.m_volatility= PSI_VOLATILITY_UNKNOWN;
189 dummy_cond_class.m_event_name_index= 2;
190 dummy_cond_class.m_flags= 0;
191 dummy_cond_class.m_enabled= true;
192 dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
193 dummy_file_class.m_event_name_index= 3;
194 dummy_file_class.m_flags= 0;
195 dummy_file_class.m_enabled= true;
196 dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
197 dummy_socket_class.m_event_name_index= 4;
198 dummy_socket_class.m_flags= 0;
199 dummy_socket_class.m_enabled= true;
200 dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
201 dummy_table_share.m_enabled= true;
202 dummy_table_share.m_timed= true;
203
204 /* Create mutex. */
205 stub_alloc_always_fails= false;
206 mutex_1= create_mutex(&dummy_mutex_class, NULL);
207 ok(mutex_1 != NULL, "create mutex");
208 destroy_mutex(mutex_1);
209 cleanup_instruments();
210
211 stub_alloc_always_fails= true;
212 mutex_2= create_mutex(&dummy_mutex_class, NULL);
213 ok(mutex_2 == NULL, "oom (create mutex)");
214
215 /* Create rwlock. */
216 stub_alloc_always_fails = false;
217 rc = init_instruments(¶m);
218 ok(rc == 0, "instances init");
219 rwlock_1= create_rwlock(&dummy_rwlock_class, NULL);
220 ok(rwlock_1 != NULL, "create rwlock");
221 destroy_rwlock(rwlock_1);
222 cleanup_instruments();
223
224 stub_alloc_always_fails= true;
225 rwlock_2= create_rwlock(&dummy_rwlock_class, NULL);
226 ok(rwlock_2 == NULL, "oom (create rwlock)");
227
228 /* Create cond. */
229 stub_alloc_always_fails = false;
230 rc = init_instruments(¶m);
231 ok(rc == 0, "instances init");
232 cond_1= create_cond(&dummy_cond_class, NULL);
233 ok(cond_1 != NULL, "create cond");
234 destroy_cond(cond_1);
235 cleanup_instruments();
236
237 stub_alloc_always_fails= true;
238 cond_2= create_cond(&dummy_cond_class, NULL);
239 ok(cond_2 == NULL, "oom (create cond)");
240
241 /* Create file. */
242 PFS_thread fake_thread;
243 rc = init_instruments(¶m);
244 fake_thread.m_filename_hash_pins= NULL;
245 init_file_hash(¶m);
246
247 stub_alloc_always_fails = true;
248 file_2 = find_or_create_file(&fake_thread, &dummy_file_class, "dummy", 5, true);
249 ok(file_2 == NULL, "oom (create file)");
250
251 stub_alloc_always_fails= false;
252 file_1= find_or_create_file(&fake_thread, &dummy_file_class, "dummy", 5, true);
253 ok(file_1 != NULL, "create file");
254 release_file(file_1);
255 cleanup_instruments();
256
257 /* Create socket. */
258 stub_alloc_always_fails = false;
259 rc = init_instruments(¶m);
260 ok(rc == 0, "instances init");
261 socket_1= create_socket(&dummy_socket_class, NULL, NULL, 0);
262 ok(socket_1 != NULL, "create socket");
263 destroy_socket(socket_1);
264 cleanup_instruments();
265
266 stub_alloc_always_fails= true;
267 socket_2= create_socket(&dummy_socket_class, NULL, NULL, 0);
268 ok(socket_2 == NULL, "oom (create socket)");
269
270 /* Create table. */
271 stub_alloc_always_fails= false;
272 rc = init_instruments(¶m);
273 table_1= create_table(&dummy_table_share, &fake_thread, NULL);
274 ok(table_1 != NULL, "create table");
275 destroy_table(table_1);
276 cleanup_instruments();
277
278 stub_alloc_always_fails= true;
279 table_2= create_table(&dummy_table_share, &fake_thread, NULL);
280 ok(table_2 == NULL, "oom (create table)");
281
282 /* Create thread. */
283 stub_alloc_always_fails= false;
284 rc = init_instruments(¶m);
285 thread_1= create_thread(&dummy_thread_class, NULL, 0);
286 ok(thread_1 != NULL, "create thread");
287 destroy_thread(thread_1);
288 cleanup_instruments();
289
290 stub_alloc_always_fails= true;
291 thread_2= create_thread(&dummy_thread_class, NULL, 0);
292 ok(thread_2 == NULL, "oom (create thread)");
293
294 PSI_thread *thread;
295
296 /* Per thread wait. */
297 memset(¶m, 0, sizeof(param));
298 param.m_mutex_class_sizing= 50;
299 param.m_rwlock_class_sizing= 50;
300 param.m_cond_class_sizing= 50;
301 param.m_file_class_sizing= 50;
302 param.m_socket_class_sizing= 0;
303 psi= initialize_performance_schema_helper(¶m);
304 stub_alloc_fails_after_count= 2;
305 thread= psi->new_thread(thread_key_1, NULL, 0);
306 ok(thread == NULL, "oom (per thread wait)");
307
308 cleanup_sync_class();
309 cleanup_thread_class();
310 cleanup_file_class();
311 cleanup_instruments();
312
313 /* Thread waits history sizing. */
314 memset(¶m, 0, sizeof(param));
315 param.m_enabled= true;
316 param.m_events_waits_history_sizing= 10;
317 psi= initialize_performance_schema_helper(¶m);
318 stub_alloc_fails_after_count= 3;
319 thread= psi->new_thread(thread_key_1, NULL, 0);
320 ok(thread == NULL, "oom (thread waits history sizing)");
321
322 cleanup_thread_class();
323 cleanup_instruments();
324
325 /* Per thread stages. */
326 memset(¶m, 0, sizeof(param));
327 param.m_stage_class_sizing= 50;
328 psi= initialize_performance_schema_helper(¶m);
329 stub_alloc_fails_after_count= 3;
330 thread= psi->new_thread(thread_key_1, NULL, 0);
331 ok(thread == NULL, "oom (per thread stages)");
332
333 cleanup_stage_class();
334 cleanup_thread_class();
335 cleanup_instruments();
336 cleanup_stage_class();
337
338 /* Thread stages history sizing. */
339 memset(¶m, 0, sizeof(param));
340 param.m_events_stages_history_sizing= 10;
341 psi= initialize_performance_schema_helper(¶m);
342 stub_alloc_fails_after_count= 3;
343 thread= psi->new_thread(thread_key_1, NULL, 0);
344 ok(thread == NULL, "oom (thread stages history sizing)");
345
346 cleanup_instruments();
347 cleanup_thread_class();
348
349 /* Per thread statements. */
350 memset(¶m, 0, sizeof(param));
351 param.m_stage_class_sizing= 50;
352 psi= initialize_performance_schema_helper(¶m);
353 init_statement_class(param.m_statement_class_sizing);
354 stub_alloc_fails_after_count= 3;
355 thread= psi->new_thread(thread_key_1, NULL, 0);
356 ok(thread == NULL, "oom (per thread statements)");
357
358 cleanup_stage_class();
359 cleanup_statement_class();
360 cleanup_thread_class();
361 cleanup_instruments();
362
363 /* Thread statements history sizing. */
364 memset(¶m, 0, sizeof(param));
365 param.m_events_statements_history_sizing= 10;
366 psi= initialize_performance_schema_helper(¶m);
367 stub_alloc_fails_after_count= 3;
368 thread= psi->new_thread(thread_key_1, NULL, 0);
369 ok(thread == NULL, "oom (thread statements history sizing)");
370
371 cleanup_thread_class();
372 cleanup_instruments();
373
374 /* Per thread transactions. */
375 memset(¶m, 0, sizeof(param));
376 psi= initialize_performance_schema_helper(¶m);
377 transaction_class_max= 1; // set by register_global_classes();
378 stub_alloc_fails_after_count= 3;
379 thread= psi->new_thread(thread_key_1, NULL, 0);
380 ok(thread == NULL, "oom (per thread transactions)");
381 transaction_class_max= 0;
382
383 cleanup_thread_class();
384 cleanup_instruments();
385
386 /* Thread transactions history sizing. */
387 memset(¶m, 0, sizeof(param));
388 param.m_events_transactions_history_sizing= 10;
389 psi= initialize_performance_schema_helper(¶m);
390 stub_alloc_fails_after_count= 3;
391 thread= psi->new_thread(thread_key_1, NULL, 0);
392 ok(thread == NULL, "oom (thread transactions history sizing)");
393
394 cleanup_thread_class();
395 cleanup_instruments();
396
397 /* Global stages. */
398 memset(¶m, 0, sizeof(param));
399 param.m_enabled= true;
400 param.m_mutex_class_sizing= 10;
401 param.m_stage_class_sizing= 20;
402
403 stub_alloc_fails_after_count= 2;
404 init_event_name_sizing(¶m);
405 rc= init_stage_class(param.m_stage_class_sizing);
406 ok(rc == 0, "init stage class");
407 rc= init_instruments(& param);
408 ok(rc == 1, "oom (global stages)");
409
410 cleanup_stage_class();
411 cleanup_instruments();
412
413 /* Global statements. */
414 memset(¶m, 0, sizeof(param));
415 param.m_enabled= true;
416 param.m_mutex_class_sizing= 10;
417 param.m_statement_class_sizing= 20;
418
419 stub_alloc_fails_after_count= 2;
420 init_event_name_sizing(¶m);
421 rc= init_statement_class(param.m_statement_class_sizing);
422 ok(rc == 0, "init statement class");
423 rc= init_instruments(¶m);
424 ok(rc == 1, "oom (global statements)");
425
426 cleanup_statement_class();
427 cleanup_instruments();
428
429 /* Global memory. */
430 memset(¶m, 0, sizeof(param));
431 param.m_enabled= true;
432 param.m_mutex_class_sizing= 10;
433 param.m_memory_class_sizing= 20;
434
435 stub_alloc_fails_after_count= 2;
436 init_event_name_sizing(¶m);
437 rc= init_memory_class(param.m_memory_class_sizing);
438 ok(rc == 0, "init memory class");
439 rc= init_instruments(& param);
440 ok(rc == 1, "oom (global memory)");
441
442 cleanup_memory_class();
443 cleanup_instruments();
444 }
445
do_all_tests()446 void do_all_tests()
447 {
448 test_oom();
449 }
450
main(int,char **)451 int main(int, char **)
452 {
453 plan(32);
454 MY_INIT("pfs_instr-oom-t");
455 do_all_tests();
456 return (exit_status());
457 }
458
459