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, Fifth Floor, 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 
36 PFS_global_param param;
37 
test_no_instruments()38 void test_no_instruments()
39 {
40   int rc;
41 
42   memset(& param, 0xFF, sizeof(param));
43   param.m_enabled= true;
44   param.m_mutex_class_sizing= 0;
45   param.m_rwlock_class_sizing= 0;
46   param.m_cond_class_sizing= 0;
47   param.m_thread_class_sizing= 0;
48   param.m_table_share_sizing= 0;
49   param.m_file_class_sizing= 0;
50   param.m_socket_class_sizing= 0;
51   param.m_mutex_sizing= 0;
52   param.m_rwlock_sizing= 0;
53   param.m_cond_sizing= 0;
54   param.m_thread_sizing= 0;
55   param.m_table_sizing= 0;
56   param.m_file_sizing= 0;
57   param.m_file_handle_sizing= 0;
58   param.m_socket_sizing= 0;
59   param.m_events_waits_history_sizing= 0;
60   param.m_events_waits_history_long_sizing= 0;
61   param.m_setup_actor_sizing= 0;
62   param.m_setup_object_sizing= 0;
63   param.m_host_sizing= 0;
64   param.m_user_sizing= 0;
65   param.m_account_sizing= 0;
66   param.m_stage_class_sizing= 0;
67   param.m_events_stages_history_sizing= 0;
68   param.m_events_stages_history_long_sizing= 0;
69   param.m_statement_class_sizing= 0;
70   param.m_events_statements_history_sizing= 0;
71   param.m_events_statements_history_long_sizing= 0;
72   param.m_events_transactions_history_sizing= 0;
73   param.m_events_transactions_history_long_sizing= 0;
74   param.m_digest_sizing= 0;
75   param.m_session_connect_attrs_sizing= 0;
76   param.m_program_sizing= 0;
77   param.m_prepared_stmt_sizing= 0;
78   param.m_statement_stack_sizing= 0;
79   param.m_memory_class_sizing= 0;
80   param.m_metadata_lock_sizing= 0;
81 
82   init_event_name_sizing(& param);
83   rc= init_instruments(& param);
84   ok(rc == 0, "zero init");
85 
86   cleanup_instruments();
87 }
88 
test_no_instances()89 void test_no_instances()
90 {
91   int rc;
92   PFS_mutex_class dummy_mutex_class;
93   PFS_rwlock_class dummy_rwlock_class;
94   PFS_cond_class dummy_cond_class;
95   PFS_thread_class dummy_thread_class;
96   PFS_file_class dummy_file_class;
97   PFS_table_share dummy_table_share;
98   PFS_socket_class dummy_socket_class;
99   PFS_mutex *mutex;
100   PFS_rwlock *rwlock;
101   PFS_cond *cond;
102   PFS_thread *thread;
103   PFS_file *file;
104   PFS_socket *socket;
105   PFS_table *table;
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 
274   memset(& param, 0xFF, sizeof(param));
275   param.m_enabled= true;
276   param.m_mutex_class_sizing= 1;
277   param.m_rwlock_class_sizing= 1;
278   param.m_cond_class_sizing= 1;
279   param.m_thread_class_sizing= 1;
280   param.m_table_share_sizing= 1;
281   param.m_file_class_sizing= 1;
282   param.m_socket_class_sizing= 1;
283   param.m_mutex_sizing= 2;
284   param.m_rwlock_sizing= 2;
285   param.m_cond_sizing= 2;
286   param.m_thread_sizing= 2;
287   param.m_table_sizing= 2;
288   param.m_file_sizing= 2;
289   param.m_file_handle_sizing= 100;
290   param.m_socket_sizing= 2;
291   param.m_events_waits_history_sizing= 10;
292   param.m_events_waits_history_long_sizing= 10000;
293   param.m_setup_actor_sizing= 0;
294   param.m_setup_object_sizing= 0;
295   param.m_host_sizing= 0;
296   param.m_user_sizing= 0;
297   param.m_account_sizing= 0;
298   param.m_stage_class_sizing= 0;
299   param.m_events_stages_history_sizing= 0;
300   param.m_events_stages_history_long_sizing= 0;
301   param.m_statement_class_sizing= 0;
302   param.m_events_statements_history_sizing= 0;
303   param.m_events_statements_history_long_sizing= 0;
304   param.m_events_transactions_history_sizing= 0;
305   param.m_events_transactions_history_long_sizing= 0;
306   param.m_digest_sizing= 0;
307   param.m_session_connect_attrs_sizing= 0;
308   param.m_program_sizing= 0;
309   param.m_prepared_stmt_sizing= 0;
310   param.m_statement_stack_sizing= 0;
311   param.m_memory_class_sizing= 1;
312   param.m_metadata_lock_sizing= 0;
313 
314   init_event_name_sizing(& param);
315   rc= init_instruments(& param);
316   ok(rc == 0, "instances init");
317 
318   dummy_mutex_class.m_event_name_index= 0;
319   dummy_mutex_class.m_flags= 0;
320   dummy_mutex_class.m_enabled= true;
321   dummy_mutex_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
322   dummy_rwlock_class.m_event_name_index= 1;
323   dummy_rwlock_class.m_flags= 0;
324   dummy_rwlock_class.m_enabled= true;
325   dummy_rwlock_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
326   dummy_cond_class.m_event_name_index= 2;
327   dummy_cond_class.m_flags= 0;
328   dummy_cond_class.m_enabled= true;
329   dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
330   dummy_file_class.m_event_name_index= 3;
331   dummy_file_class.m_flags= 0;
332   dummy_file_class.m_enabled= true;
333   dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
334   dummy_socket_class.m_event_name_index= 4;
335   dummy_socket_class.m_flags= 0;
336   dummy_socket_class.m_enabled= true;
337   dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
338 
339   dummy_table_share.m_enabled= true;
340   dummy_table_share.m_timed= true;
341 
342   mutex_1= create_mutex(& dummy_mutex_class, NULL);
343   ok(mutex_1 != NULL, "mutex");
344   ok(global_mutex_container.get_lost_counter() == 0, "not lost");
345   mutex_2= create_mutex(& dummy_mutex_class, NULL);
346   ok(mutex_2 != NULL, "mutex");
347   ok(global_mutex_container.get_lost_counter() == 0, "not lost");
348   mutex_2= create_mutex(& dummy_mutex_class, NULL);
349   ok(mutex_2 == NULL, "no mutex");
350   ok(global_mutex_container.get_lost_counter() == 1, "lost 1");
351   destroy_mutex(mutex_1);
352   mutex_2= create_mutex(& dummy_mutex_class, NULL);
353   ok(mutex_2 != NULL, "mutex");
354   ok(global_mutex_container.get_lost_counter() == 1, "no new loss");
355 
356   rwlock_1= create_rwlock(& dummy_rwlock_class, NULL);
357   ok(rwlock_1 != NULL, "rwlock");
358   ok(global_rwlock_container.m_lost == 0, "not lost");
359   rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
360   ok(rwlock_2 != NULL, "rwlock");
361   ok(global_rwlock_container.m_lost == 0, "not lost");
362   rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
363   ok(rwlock_2 == NULL, "no rwlock");
364   ok(global_rwlock_container.m_lost == 1, "lost 1");
365   destroy_rwlock(rwlock_1);
366   rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
367   ok(rwlock_2 != NULL, "rwlock");
368   ok(global_rwlock_container.m_lost == 1, "no new loss");
369 
370   cond_1= create_cond(& dummy_cond_class, NULL);
371   ok(cond_1 != NULL, "cond");
372   ok(global_cond_container.m_lost == 0, "not lost");
373   cond_2= create_cond(& dummy_cond_class, NULL);
374   ok(cond_2 != NULL, "cond");
375   ok(global_cond_container.m_lost == 0, "not lost");
376   cond_2= create_cond(& dummy_cond_class, NULL);
377   ok(cond_2 == NULL, "no cond");
378   ok(global_cond_container.m_lost == 1, "lost 1");
379   destroy_cond(cond_1);
380   cond_2= create_cond(& dummy_cond_class, NULL);
381   ok(cond_2 != NULL, "cond");
382   ok(global_cond_container.m_lost == 1, "no new loss");
383 
384   thread_1= create_thread(& dummy_thread_class, NULL, 0);
385   ok(thread_1 != NULL, "thread");
386   ok(global_thread_container.m_lost == 0, "not lost");
387   thread_2= create_thread(& dummy_thread_class, NULL, 0);
388   ok(thread_2 != NULL, "thread");
389   ok(global_thread_container.m_lost == 0, "not lost");
390   thread_2= create_thread(& dummy_thread_class, NULL, 0);
391   ok(thread_2 == NULL, "no thread");
392   ok(global_thread_container.m_lost == 1, "lost 1");
393   destroy_thread(thread_1);
394   thread_2= create_thread(& dummy_thread_class, NULL, 0);
395   ok(thread_2 != NULL, "thread");
396   ok(global_thread_container.m_lost == 1, "no new loss");
397 
398   PFS_thread fake_thread;
399   fake_thread.m_filename_hash_pins= NULL;
400 
401   file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
402   ok(file_1 == NULL, "no file");
403   ok(global_file_container.m_lost == 1, "lost 1");
404   file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
405   ok(file_1 == NULL, "no file");
406   ok(global_file_container.m_lost == 2, "lost 2");
407 
408   init_file_hash(& param);
409   global_file_container.m_lost= 0;
410 
411   file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7, true);
412   ok(file_1 != NULL, "file");
413   ok(file_1->m_file_stat.m_open_count == 1, "open count 1");
414   ok(global_file_container.m_lost == 0, "not lost");
415   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7, true);
416   ok(file_1 == file_2, "same file");
417   ok(file_1->m_file_stat.m_open_count == 2, "open count 2");
418   ok(global_file_container.m_lost == 0, "not lost");
419   release_file(file_2);
420   ok(file_1->m_file_stat.m_open_count == 1, "open count 1");
421   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_B", 7, true);
422   ok(file_2 != NULL, "file");
423   ok(global_file_container.m_lost == 0, "not lost");
424   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_C", 7, true);
425   ok(file_2 == NULL, "no file");
426   ok(global_file_container.m_lost == 1, "lost");
427   release_file(file_1);
428   /* the file still exists, not destroyed */
429   ok(file_1->m_file_stat.m_open_count == 0, "open count 0");
430   file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_D", 7, true);
431   ok(file_2 == NULL, "no file");
432   ok(global_file_container.m_lost == 2, "lost");
433 
434   socket_1= create_socket(& dummy_socket_class, NULL, NULL, 0);
435   ok(socket_1 != NULL, "socket");
436   ok(global_socket_container.m_lost == 0, "not lost");
437   socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
438   ok(socket_2 != NULL, "socket");
439   ok(global_socket_container.m_lost == 0, "not lost");
440   socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
441   ok(socket_2 == NULL, "no socket");
442   ok(global_socket_container.m_lost == 1, "lost 1");
443   destroy_socket(socket_1);
444   socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
445   ok(socket_2 != NULL, "socket");
446   ok(global_socket_container.m_lost == 1, "no new loss");
447 
448   table_1= create_table(& dummy_table_share, & fake_thread, NULL);
449   ok(table_1 != NULL, "table");
450   ok(global_table_container.m_lost == 0, "not lost");
451   table_2= create_table(& dummy_table_share, & fake_thread, NULL);
452   ok(table_2 != NULL, "table");
453   ok(global_table_container.m_lost == 0, "not lost");
454   table_2= create_table(& dummy_table_share, & fake_thread, NULL);
455   ok(table_2 == NULL, "no table");
456   ok(global_table_container.m_lost == 1, "lost 1");
457   destroy_table(table_1);
458   table_2= create_table(& dummy_table_share, & fake_thread, NULL);
459   ok(table_2 != NULL, "table");
460   ok(global_table_container.m_lost == 1, "no new loss");
461 
462   //TODO: test that cleanup works
463   reset_events_waits_by_instance();
464   reset_events_waits_by_thread();
465 
466   cleanup_file_hash();
467   cleanup_instruments();
468 }
469 
do_all_tests()470 void do_all_tests()
471 {
472   flag_global_instrumentation= true;
473   flag_thread_instrumentation= true;
474 
475   test_no_instruments();
476   test_no_instances();
477   test_with_instances();
478 }
479 
main(int argc,char ** argv)480 int main(int argc, char **argv)
481 {
482   plan(103);
483   MY_INIT(argv[0]);
484   do_all_tests();
485   my_end(0);
486   return (exit_status());
487 }
488 
489