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(&param);
178   rc= init_instruments(&param);
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(&param);
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(&param);
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(&param);
244   fake_thread.m_filename_hash_pins= NULL;
245   init_file_hash(&param);
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(&param);
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(&param);
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(&param);
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(&param, 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(&param);
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(&param, 0, sizeof(param));
315   param.m_enabled= true;
316   param.m_events_waits_history_sizing= 10;
317   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
327   param.m_stage_class_sizing= 50;
328   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
340   param.m_events_stages_history_sizing= 10;
341   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
351   param.m_stage_class_sizing= 50;
352   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
365   param.m_events_statements_history_sizing= 10;
366   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
376   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
388   param.m_events_transactions_history_sizing= 10;
389   psi= initialize_performance_schema_helper(&param);
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(&param, 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(&param);
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(&param, 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(&param);
421   rc= init_statement_class(param.m_statement_class_sizing);
422   ok(rc == 0, "init statement class");
423   rc= init_instruments(&param);
424   ok(rc == 1, "oom (global statements)");
425 
426   cleanup_statement_class();
427   cleanup_instruments();
428 
429   /* Global memory. */
430   memset(&param, 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(&param);
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