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_instr_class.h>
29 #include <pfs_buffer_container.h>
30 #include <tap.h>
31 
32 #include "stub_global_status_var.h"
33 
34 #include <memory.h>
35 
test_no_instruments()36 void test_no_instruments()
37 {
38   int rc;
39   PFS_global_param param;
40 
41   memset(& param, 0xFF, sizeof(param));
42   param.m_enabled= true;
43   param.m_mutex_class_sizing= 0;
44   param.m_rwlock_class_sizing= 0;
45   param.m_cond_class_sizing= 0;
46   param.m_thread_class_sizing= 0;
47   param.m_table_share_sizing= 0;
48   param.m_file_class_sizing= 0;
49   param.m_socket_class_sizing= 0;
50   param.m_mutex_sizing= 0;
51   param.m_rwlock_sizing= 0;
52   param.m_cond_sizing= 0;
53   param.m_thread_sizing= 0;
54   param.m_table_sizing= 0;
55   param.m_file_sizing= 0;
56   param.m_file_handle_sizing= 0;
57   param.m_socket_sizing= 0;
58   param.m_events_waits_history_sizing= 0;
59   param.m_events_waits_history_long_sizing= 0;
60   param.m_setup_actor_sizing= 0;
61   param.m_setup_object_sizing= 0;
62   param.m_host_sizing= 0;
63   param.m_user_sizing= 0;
64   param.m_account_sizing= 0;
65   param.m_stage_class_sizing= 0;
66   param.m_events_stages_history_sizing= 0;
67   param.m_events_stages_history_long_sizing= 0;
68   param.m_statement_class_sizing= 0;
69   param.m_events_statements_history_sizing= 0;
70   param.m_events_statements_history_long_sizing= 0;
71   param.m_events_transactions_history_sizing= 0;
72   param.m_events_transactions_history_long_sizing= 0;
73   param.m_digest_sizing= 0;
74   param.m_session_connect_attrs_sizing= 0;
75   param.m_program_sizing= 0;
76   param.m_prepared_stmt_sizing= 0;
77   param.m_statement_stack_sizing= 0;
78   param.m_memory_class_sizing= 0;
79   param.m_metadata_lock_sizing= 0;
80 
81   init_event_name_sizing(& param);
82   rc= init_instruments(& param);
83   ok(rc == 0, "zero init");
84 
85   cleanup_instruments();
86 }
87 
test_no_instances()88 void test_no_instances()
89 {
90   int rc;
91   PFS_mutex_class dummy_mutex_class;
92   PFS_rwlock_class dummy_rwlock_class;
93   PFS_cond_class dummy_cond_class;
94   PFS_thread_class dummy_thread_class;
95   PFS_file_class dummy_file_class;
96   PFS_table_share dummy_table_share;
97   PFS_socket_class dummy_socket_class;
98   PFS_mutex *mutex;
99   PFS_rwlock *rwlock;
100   PFS_cond *cond;
101   PFS_thread *thread;
102   PFS_file *file;
103   PFS_socket *socket;
104   PFS_table *table;
105   PFS_global_param param;
106 
107   dummy_mutex_class.m_event_name_index = 0;
108   dummy_mutex_class.m_flags = 0;
109   dummy_mutex_class.m_enabled = true;
110   dummy_mutex_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
111   dummy_rwlock_class.m_event_name_index = 1;
112   dummy_rwlock_class.m_flags = 0;
113   dummy_rwlock_class.m_enabled = true;
114   dummy_rwlock_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
115   dummy_cond_class.m_event_name_index = 2;
116   dummy_cond_class.m_flags = 0;
117   dummy_cond_class.m_enabled = true;
118   dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
119   dummy_file_class.m_event_name_index = 3;
120   dummy_file_class.m_flags = 0;
121   dummy_file_class.m_enabled = true;
122   dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
123   dummy_socket_class.m_event_name_index = 4;
124   dummy_socket_class.m_flags = 0;
125   dummy_socket_class.m_enabled = true;
126   dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
127 
128   memset(& param, 0xFF, sizeof(param));
129   param.m_enabled= true;
130   param.m_mutex_class_sizing= 1;
131   param.m_rwlock_class_sizing= 1;
132   param.m_cond_class_sizing= 1;
133   param.m_thread_class_sizing= 1;
134   param.m_table_share_sizing= 1;
135   param.m_file_class_sizing= 1;
136   param.m_socket_class_sizing= 0;
137   param.m_mutex_sizing= 0;
138   param.m_rwlock_sizing= 0;
139   param.m_cond_sizing= 0;
140   param.m_thread_sizing= 0;
141   param.m_table_sizing= 0;
142   param.m_file_sizing= 0;
143   param.m_file_handle_sizing= 0;
144   param.m_socket_sizing= 0;
145   param.m_events_waits_history_sizing= 0;
146   param.m_events_waits_history_long_sizing= 0;
147   param.m_setup_actor_sizing= 0;
148   param.m_setup_object_sizing= 0;
149   param.m_host_sizing= 0;
150   param.m_user_sizing= 0;
151   param.m_account_sizing= 0;
152   param.m_stage_class_sizing= 0;
153   param.m_events_stages_history_sizing= 0;
154   param.m_events_stages_history_long_sizing= 0;
155   param.m_statement_class_sizing= 0;
156   param.m_events_statements_history_sizing= 0;
157   param.m_events_statements_history_long_sizing= 0;
158   param.m_events_transactions_history_sizing= 0;
159   param.m_events_transactions_history_long_sizing= 0;
160   param.m_digest_sizing= 0;
161   param.m_session_connect_attrs_sizing= 0;
162   param.m_program_sizing= 0;
163   param.m_prepared_stmt_sizing= 0;
164   param.m_statement_stack_sizing= 0;
165   param.m_memory_class_sizing= 1;
166   param.m_metadata_lock_sizing= 0;
167 
168   init_event_name_sizing(& param);
169   rc= init_instruments(& param);
170   ok(rc == 0, "no instances init");
171 
172   mutex= create_mutex(& dummy_mutex_class, NULL);
173   ok(mutex == NULL, "no mutex");
174   ok(global_mutex_container.get_lost_counter() == 1, "lost 1");
175   mutex= create_mutex(& dummy_mutex_class, NULL);
176   ok(mutex == NULL, "no mutex");
177   ok(global_mutex_container.get_lost_counter() == 2, "lost 2");
178 
179   rwlock= create_rwlock(& dummy_rwlock_class, NULL);
180   ok(rwlock == NULL, "no rwlock");
181   ok(global_rwlock_container.m_lost == 1, "lost 1");
182   rwlock= create_rwlock(& dummy_rwlock_class, NULL);
183   ok(rwlock == NULL, "no rwlock");
184   ok(global_rwlock_container.m_lost == 2, "lost 2");
185 
186   cond= create_cond(& dummy_cond_class, NULL);
187   ok(cond == NULL, "no cond");
188   ok(global_cond_container.m_lost == 1, "lost 1");
189   cond= create_cond(& dummy_cond_class, NULL);
190   ok(cond == NULL, "no cond");
191   ok(global_cond_container.m_lost == 2, "lost 2");
192 
193   thread= create_thread(& dummy_thread_class, NULL, 0);
194   ok(thread == NULL, "no thread");
195   ok(global_thread_container.m_lost == 1, "lost 1");
196   thread= create_thread(& dummy_thread_class, NULL, 0);
197   ok(thread == NULL, "no thread");
198   ok(global_thread_container.m_lost == 2, "lost 2");
199 
200   PFS_thread fake_thread;
201   fake_thread.m_filename_hash_pins= NULL;
202 
203   file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
204   ok(file == NULL, "no file");
205   ok(global_file_container.m_lost == 1, "lost 1");
206   file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
207   ok(file == NULL, "no file");
208   ok(global_file_container.m_lost == 2, "lost 2");
209 
210   init_file_hash(& param);
211 
212   file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
213   ok(file == NULL, "no file");
214   ok(global_file_container.m_lost == 3, "lost 3");
215   file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
216   ok(file == NULL, "no file");
217   ok(global_file_container.m_lost == 4, "lost 4");
218 
219   char long_file_name[10000];
220   int size= sizeof(long_file_name);
221   memset(long_file_name, 'X', size);
222 
223   file= find_or_create_file(& fake_thread, & dummy_file_class, long_file_name, size, true);
224   ok(file == NULL, "no file");
225   ok(global_file_container.m_lost == 5, "lost 5");
226 
227   table= create_table(& dummy_table_share, & fake_thread, NULL);
228   ok(table == NULL, "no table");
229   ok(global_table_container.m_lost == 1, "lost 1");
230   table= create_table(& dummy_table_share, & fake_thread, NULL);
231   ok(table == NULL, "no table");
232   ok(global_table_container.m_lost == 2, "lost 2");
233 
234   socket= create_socket(& dummy_socket_class, NULL, NULL, 0);
235   ok(socket == NULL, "no socket");
236   ok(global_socket_container.m_lost == 1, "lost 1");
237   socket= create_socket(& dummy_socket_class, NULL, NULL, 0);
238   ok(socket == NULL, "no socket");
239   ok(global_socket_container.m_lost == 2, "lost 2");
240 
241   /* No result to test, just make sure it does not crash */
242   reset_events_waits_by_instance();
243   reset_events_waits_by_thread();
244 
245   cleanup_file_hash();
246   cleanup_instruments();
247 }
248 
test_with_instances()249 void test_with_instances()
250 {
251   int rc;
252   PFS_mutex_class dummy_mutex_class;
253   PFS_rwlock_class dummy_rwlock_class;
254   PFS_cond_class dummy_cond_class;
255   PFS_thread_class dummy_thread_class;
256   PFS_file_class dummy_file_class;
257   PFS_socket_class dummy_socket_class;
258   PFS_table_share dummy_table_share;
259   PFS_mutex *mutex_1;
260   PFS_mutex *mutex_2;
261   PFS_rwlock *rwlock_1;
262   PFS_rwlock *rwlock_2;
263   PFS_cond *cond_1;
264   PFS_cond *cond_2;
265   PFS_thread *thread_1;
266   PFS_thread *thread_2;
267   PFS_file *file_1;
268   PFS_file *file_2;
269   PFS_socket *socket_1;
270   PFS_socket *socket_2;
271   PFS_table *table_1;
272   PFS_table *table_2;
273   PFS_global_param param;
274 
275   memset(& param, 0xFF, sizeof(param));
276   param.m_enabled= true;
277   param.m_mutex_class_sizing= 1;
278   param.m_rwlock_class_sizing= 1;
279   param.m_cond_class_sizing= 1;
280   param.m_thread_class_sizing= 1;
281   param.m_table_share_sizing= 1;
282   param.m_file_class_sizing= 1;
283   param.m_socket_class_sizing= 1;
284   param.m_mutex_sizing= 2;
285   param.m_rwlock_sizing= 2;
286   param.m_cond_sizing= 2;
287   param.m_thread_sizing= 2;
288   param.m_table_sizing= 2;
289   param.m_file_sizing= 2;
290   param.m_file_handle_sizing= 100;
291   param.m_socket_sizing= 2;
292   param.m_events_waits_history_sizing= 10;
293   param.m_events_waits_history_long_sizing= 10000;
294   param.m_setup_actor_sizing= 0;
295   param.m_setup_object_sizing= 0;
296   param.m_host_sizing= 0;
297   param.m_user_sizing= 0;
298   param.m_account_sizing= 0;
299   param.m_stage_class_sizing= 0;
300   param.m_events_stages_history_sizing= 0;
301   param.m_events_stages_history_long_sizing= 0;
302   param.m_statement_class_sizing= 0;
303   param.m_events_statements_history_sizing= 0;
304   param.m_events_statements_history_long_sizing= 0;
305   param.m_events_transactions_history_sizing= 0;
306   param.m_events_transactions_history_long_sizing= 0;
307   param.m_digest_sizing= 0;
308   param.m_session_connect_attrs_sizing= 0;
309   param.m_program_sizing= 0;
310   param.m_prepared_stmt_sizing= 0;
311   param.m_statement_stack_sizing= 0;
312   param.m_memory_class_sizing= 1;
313   param.m_metadata_lock_sizing= 0;
314 
315   init_event_name_sizing(& param);
316   rc= init_instruments(& param);
317   ok(rc == 0, "instances init");
318 
319   dummy_mutex_class.m_event_name_index= 0;
320   dummy_mutex_class.m_flags= 0;
321   dummy_mutex_class.m_enabled= true;
322   dummy_mutex_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
323   dummy_rwlock_class.m_event_name_index= 1;
324   dummy_rwlock_class.m_flags= 0;
325   dummy_rwlock_class.m_enabled= true;
326   dummy_rwlock_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
327   dummy_cond_class.m_event_name_index= 2;
328   dummy_cond_class.m_flags= 0;
329   dummy_cond_class.m_enabled= true;
330   dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
331   dummy_file_class.m_event_name_index= 3;
332   dummy_file_class.m_flags= 0;
333   dummy_file_class.m_enabled= true;
334   dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
335   dummy_socket_class.m_event_name_index= 4;
336   dummy_socket_class.m_flags= 0;
337   dummy_socket_class.m_enabled= true;
338   dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
339 
340   dummy_table_share.m_enabled= true;
341   dummy_table_share.m_timed= true;
342 
343   mutex_1= create_mutex(& dummy_mutex_class, NULL);
344   ok(mutex_1 != NULL, "mutex");
345   ok(global_mutex_container.get_lost_counter() == 0, "not lost");
346   mutex_2= create_mutex(& dummy_mutex_class, NULL);
347   ok(mutex_2 != NULL, "mutex");
348   ok(global_mutex_container.get_lost_counter() == 0, "not lost");
349   mutex_2= create_mutex(& dummy_mutex_class, NULL);
350   ok(mutex_2 == NULL, "no mutex");
351   ok(global_mutex_container.get_lost_counter() == 1, "lost 1");
352   destroy_mutex(mutex_1);
353   mutex_2= create_mutex(& dummy_mutex_class, NULL);
354   ok(mutex_2 != NULL, "mutex");
355   ok(global_mutex_container.get_lost_counter() == 1, "no new loss");
356 
357   rwlock_1= create_rwlock(& dummy_rwlock_class, NULL);
358   ok(rwlock_1 != NULL, "rwlock");
359   ok(global_rwlock_container.m_lost == 0, "not lost");
360   rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
361   ok(rwlock_2 != NULL, "rwlock");
362   ok(global_rwlock_container.m_lost == 0, "not lost");
363   rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
364   ok(rwlock_2 == NULL, "no rwlock");
365   ok(global_rwlock_container.m_lost == 1, "lost 1");
366   destroy_rwlock(rwlock_1);
367   rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
368   ok(rwlock_2 != NULL, "rwlock");
369   ok(global_rwlock_container.m_lost == 1, "no new loss");
370 
371   cond_1= create_cond(& dummy_cond_class, NULL);
372   ok(cond_1 != NULL, "cond");
373   ok(global_cond_container.m_lost == 0, "not lost");
374   cond_2= create_cond(& dummy_cond_class, NULL);
375   ok(cond_2 != NULL, "cond");
376   ok(global_cond_container.m_lost == 0, "not lost");
377   cond_2= create_cond(& dummy_cond_class, NULL);
378   ok(cond_2 == NULL, "no cond");
379   ok(global_cond_container.m_lost == 1, "lost 1");
380   destroy_cond(cond_1);
381   cond_2= create_cond(& dummy_cond_class, NULL);
382   ok(cond_2 != NULL, "cond");
383   ok(global_cond_container.m_lost == 1, "no new loss");
384 
385   thread_1= create_thread(& dummy_thread_class, NULL, 0);
386   ok(thread_1 != NULL, "thread");
387   ok(global_thread_container.m_lost == 0, "not lost");
388   thread_2= create_thread(& dummy_thread_class, NULL, 0);
389   ok(thread_2 != NULL, "thread");
390   ok(global_thread_container.m_lost == 0, "not lost");
391   thread_2= create_thread(& dummy_thread_class, NULL, 0);
392   ok(thread_2 == NULL, "no thread");
393   ok(global_thread_container.m_lost == 1, "lost 1");
394   destroy_thread(thread_1);
395   thread_2= create_thread(& dummy_thread_class, NULL, 0);
396   ok(thread_2 != NULL, "thread");
397   ok(global_thread_container.m_lost == 1, "no new loss");
398 
399   PFS_thread fake_thread;
400   fake_thread.m_filename_hash_pins= NULL;
401 
402   file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
403   ok(file_1 == NULL, "no file");
404   ok(global_file_container.m_lost == 1, "lost 1");
405   file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
406   ok(file_1 == NULL, "no file");
407   ok(global_file_container.m_lost == 2, "lost 2");
408 
409   init_file_hash(& param);
410   global_file_container.m_lost= 0;
411 
412   file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7, true);
413   ok(file_1 != NULL, "file");
414   ok(file_1->m_file_stat.m_open_count == 1, "open count 1");
415   ok(global_file_container.m_lost == 0, "not lost");
416   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7, true);
417   ok(file_1 == file_2, "same file");
418   ok(file_1->m_file_stat.m_open_count == 2, "open count 2");
419   ok(global_file_container.m_lost == 0, "not lost");
420   release_file(file_2);
421   ok(file_1->m_file_stat.m_open_count == 1, "open count 1");
422   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_B", 7, true);
423   ok(file_2 != NULL, "file");
424   ok(global_file_container.m_lost == 0, "not lost");
425   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_C", 7, true);
426   ok(file_2 == NULL, "no file");
427   ok(global_file_container.m_lost == 1, "lost");
428   release_file(file_1);
429   /* the file still exists, not destroyed */
430   ok(file_1->m_file_stat.m_open_count == 0, "open count 0");
431   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_D", 7, true);
432   ok(file_2 == NULL, "no file");
433   ok(global_file_container.m_lost == 2, "lost");
434 
435   socket_1= create_socket(& dummy_socket_class, NULL, NULL, 0);
436   ok(socket_1 != NULL, "socket");
437   ok(global_socket_container.m_lost == 0, "not lost");
438   socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
439   ok(socket_2 != NULL, "socket");
440   ok(global_socket_container.m_lost == 0, "not lost");
441   socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
442   ok(socket_2 == NULL, "no socket");
443   ok(global_socket_container.m_lost == 1, "lost 1");
444   destroy_socket(socket_1);
445   socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
446   ok(socket_2 != NULL, "socket");
447   ok(global_socket_container.m_lost == 1, "no new loss");
448 
449   table_1= create_table(& dummy_table_share, & fake_thread, NULL);
450   ok(table_1 != NULL, "table");
451   ok(global_table_container.m_lost == 0, "not lost");
452   table_2= create_table(& dummy_table_share, & fake_thread, NULL);
453   ok(table_2 != NULL, "table");
454   ok(global_table_container.m_lost == 0, "not lost");
455   table_2= create_table(& dummy_table_share, & fake_thread, NULL);
456   ok(table_2 == NULL, "no table");
457   ok(global_table_container.m_lost == 1, "lost 1");
458   destroy_table(table_1);
459   table_2= create_table(& dummy_table_share, & fake_thread, NULL);
460   ok(table_2 != NULL, "table");
461   ok(global_table_container.m_lost == 1, "no new loss");
462 
463   //TODO: test that cleanup works
464   reset_events_waits_by_instance();
465   reset_events_waits_by_thread();
466 
467   cleanup_file_hash();
468   cleanup_instruments();
469 }
470 
do_all_tests()471 void do_all_tests()
472 {
473   flag_global_instrumentation= true;
474   flag_thread_instrumentation= true;
475 
476   test_no_instruments();
477   test_no_instances();
478   test_with_instances();
479 }
480 
main(int,char **)481 int main(int, char **)
482 {
483   plan(103);
484   MY_INIT("pfs_instr-t");
485   do_all_tests();
486   return (exit_status());
487 }
488 
489