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_file_hash();
256   cleanup_instruments();
257 
258   /* Create socket. */
259   stub_alloc_always_fails = false;
260   rc = init_instruments(&param);
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(&param);
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(&param);
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(&param, 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(&param);
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(&param, 0, sizeof(param));
316   param.m_enabled= true;
317   param.m_events_waits_history_sizing= 10;
318   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
328   param.m_stage_class_sizing= 50;
329   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
341   param.m_events_stages_history_sizing= 10;
342   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
352   param.m_stage_class_sizing= 50;
353   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
366   param.m_events_statements_history_sizing= 10;
367   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
377   psi= initialize_performance_schema_helper(&param);
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(&param, 0, sizeof(param));
389   param.m_events_transactions_history_sizing= 10;
390   psi= initialize_performance_schema_helper(&param);
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(&param, 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(&param);
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(&param, 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(&param);
422   rc= init_statement_class(param.m_statement_class_sizing);
423   ok(rc == 0, "init statement class");
424   rc= init_instruments(&param);
425   ok(rc == 1, "oom (global statements)");
426 
427   cleanup_statement_class();
428   cleanup_instruments();
429 
430   /* Global memory. */
431   memset(&param, 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(&param);
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