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_file_hash();
256 cleanup_instruments();
257
258 /* Create socket. */
259 stub_alloc_always_fails = false;
260 rc = init_instruments(¶m);
261 ok(rc == 0, "instances init");
262 socket_1= create_socket(&dummy_socket_class, NULL, NULL, 0);
263 ok(socket_1 != NULL, "create socket");
264 destroy_socket(socket_1);
265 cleanup_instruments();
266
267 stub_alloc_always_fails= true;
268 socket_2= create_socket(&dummy_socket_class, NULL, NULL, 0);
269 ok(socket_2 == NULL, "oom (create socket)");
270
271 /* Create table. */
272 stub_alloc_always_fails= false;
273 rc = init_instruments(¶m);
274 table_1= create_table(&dummy_table_share, &fake_thread, NULL);
275 ok(table_1 != NULL, "create table");
276 destroy_table(table_1);
277 cleanup_instruments();
278
279 stub_alloc_always_fails= true;
280 table_2= create_table(&dummy_table_share, &fake_thread, NULL);
281 ok(table_2 == NULL, "oom (create table)");
282
283 /* Create thread. */
284 stub_alloc_always_fails= false;
285 rc = init_instruments(¶m);
286 thread_1= create_thread(&dummy_thread_class, NULL, 0);
287 ok(thread_1 != NULL, "create thread");
288 destroy_thread(thread_1);
289 cleanup_instruments();
290
291 stub_alloc_always_fails= true;
292 thread_2= create_thread(&dummy_thread_class, NULL, 0);
293 ok(thread_2 == NULL, "oom (create thread)");
294
295 PSI_thread *thread;
296
297 /* Per thread wait. */
298 memset(¶m, 0, sizeof(param));
299 param.m_mutex_class_sizing= 50;
300 param.m_rwlock_class_sizing= 50;
301 param.m_cond_class_sizing= 50;
302 param.m_file_class_sizing= 50;
303 param.m_socket_class_sizing= 0;
304 psi= initialize_performance_schema_helper(¶m);
305 stub_alloc_fails_after_count= 2;
306 thread= psi->new_thread(thread_key_1, NULL, 0);
307 ok(thread == NULL, "oom (per thread wait)");
308
309 cleanup_sync_class();
310 cleanup_thread_class();
311 cleanup_file_class();
312 cleanup_instruments();
313
314 /* Thread waits history sizing. */
315 memset(¶m, 0, sizeof(param));
316 param.m_enabled= true;
317 param.m_events_waits_history_sizing= 10;
318 psi= initialize_performance_schema_helper(¶m);
319 stub_alloc_fails_after_count= 3;
320 thread= psi->new_thread(thread_key_1, NULL, 0);
321 ok(thread == NULL, "oom (thread waits history sizing)");
322
323 cleanup_thread_class();
324 cleanup_instruments();
325
326 /* Per thread stages. */
327 memset(¶m, 0, sizeof(param));
328 param.m_stage_class_sizing= 50;
329 psi= initialize_performance_schema_helper(¶m);
330 stub_alloc_fails_after_count= 3;
331 thread= psi->new_thread(thread_key_1, NULL, 0);
332 ok(thread == NULL, "oom (per thread stages)");
333
334 cleanup_stage_class();
335 cleanup_thread_class();
336 cleanup_instruments();
337 cleanup_stage_class();
338
339 /* Thread stages history sizing. */
340 memset(¶m, 0, sizeof(param));
341 param.m_events_stages_history_sizing= 10;
342 psi= initialize_performance_schema_helper(¶m);
343 stub_alloc_fails_after_count= 3;
344 thread= psi->new_thread(thread_key_1, NULL, 0);
345 ok(thread == NULL, "oom (thread stages history sizing)");
346
347 cleanup_instruments();
348 cleanup_thread_class();
349
350 /* Per thread statements. */
351 memset(¶m, 0, sizeof(param));
352 param.m_stage_class_sizing= 50;
353 psi= initialize_performance_schema_helper(¶m);
354 init_statement_class(param.m_statement_class_sizing);
355 stub_alloc_fails_after_count= 3;
356 thread= psi->new_thread(thread_key_1, NULL, 0);
357 ok(thread == NULL, "oom (per thread statements)");
358
359 cleanup_stage_class();
360 cleanup_statement_class();
361 cleanup_thread_class();
362 cleanup_instruments();
363
364 /* Thread statements history sizing. */
365 memset(¶m, 0, sizeof(param));
366 param.m_events_statements_history_sizing= 10;
367 psi= initialize_performance_schema_helper(¶m);
368 stub_alloc_fails_after_count= 3;
369 thread= psi->new_thread(thread_key_1, NULL, 0);
370 ok(thread == NULL, "oom (thread statements history sizing)");
371
372 cleanup_thread_class();
373 cleanup_instruments();
374
375 /* Per thread transactions. */
376 memset(¶m, 0, sizeof(param));
377 psi= initialize_performance_schema_helper(¶m);
378 transaction_class_max= 1; // set by register_global_classes();
379 stub_alloc_fails_after_count= 3;
380 thread= psi->new_thread(thread_key_1, NULL, 0);
381 ok(thread == NULL, "oom (per thread transactions)");
382 transaction_class_max= 0;
383
384 cleanup_thread_class();
385 cleanup_instruments();
386
387 /* Thread transactions history sizing. */
388 memset(¶m, 0, sizeof(param));
389 param.m_events_transactions_history_sizing= 10;
390 psi= initialize_performance_schema_helper(¶m);
391 stub_alloc_fails_after_count= 3;
392 thread= psi->new_thread(thread_key_1, NULL, 0);
393 ok(thread == NULL, "oom (thread transactions history sizing)");
394
395 cleanup_thread_class();
396 cleanup_instruments();
397
398 /* Global stages. */
399 memset(¶m, 0, sizeof(param));
400 param.m_enabled= true;
401 param.m_mutex_class_sizing= 10;
402 param.m_stage_class_sizing= 20;
403
404 stub_alloc_fails_after_count= 2;
405 init_event_name_sizing(¶m);
406 rc= init_stage_class(param.m_stage_class_sizing);
407 ok(rc == 0, "init stage class");
408 rc= init_instruments(& param);
409 ok(rc == 1, "oom (global stages)");
410
411 cleanup_stage_class();
412 cleanup_instruments();
413
414 /* Global statements. */
415 memset(¶m, 0, sizeof(param));
416 param.m_enabled= true;
417 param.m_mutex_class_sizing= 10;
418 param.m_statement_class_sizing= 20;
419
420 stub_alloc_fails_after_count= 2;
421 init_event_name_sizing(¶m);
422 rc= init_statement_class(param.m_statement_class_sizing);
423 ok(rc == 0, "init statement class");
424 rc= init_instruments(¶m);
425 ok(rc == 1, "oom (global statements)");
426
427 cleanup_statement_class();
428 cleanup_instruments();
429
430 /* Global memory. */
431 memset(¶m, 0, sizeof(param));
432 param.m_enabled= true;
433 param.m_mutex_class_sizing= 10;
434 param.m_memory_class_sizing= 20;
435
436 stub_alloc_fails_after_count= 2;
437 init_event_name_sizing(¶m);
438 rc= init_memory_class(param.m_memory_class_sizing);
439 ok(rc == 0, "init memory class");
440 rc= init_instruments(& param);
441 ok(rc == 1, "oom (global memory)");
442
443 cleanup_memory_class();
444 cleanup_instruments();
445 }
446
do_all_tests()447 void do_all_tests()
448 {
449 test_oom();
450 }
451
main(int,char **)452 int main(int, char **)
453 {
454 plan(32);
455 MY_INIT("pfs_instr-oom-t");
456 do_all_tests();
457 return (exit_status());
458 }
459
460