1 /*
2 * libstatgrab
3 * https://libstatgrab.org
4 * Copyright (C) 2003-2004 Peter Saunders
5 * Copyright (C) 2003-2019 Tim Bishop
6 * Copyright (C) 2003-2013 Adam Sampson
7 * Copyright (C) 2012-2019 Jens Rehsack
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library 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 GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25 #include <tools.h>
26 #include "testlib.h"
27
28 #define SG_EASY_FUNC(stat,full) { #stat, \
29 #full, (statgrab_stat_fn)(&full), \
30 NULL, NULL, \
31 0, 0, 0 }
32
33 #define SG_COMPLEX_FUNC(stat,full,diff) { #stat, \
34 #full, (statgrab_stat_fn)(&full), \
35 #diff, (statgrab_stat_fn)(&diff), \
36 0, 0, 0 }
37
38 static struct statgrab_testfuncs statgrab_test_funcs[] =
39 {
40 SG_EASY_FUNC(host_info, sg_get_host_info),
41 SG_COMPLEX_FUNC(cpu_stats, sg_get_cpu_stats, sg_get_cpu_stats_diff), /* XXX cpu_percent */
42 SG_EASY_FUNC(mem_stats, sg_get_mem_stats),
43 SG_EASY_FUNC(load_stats, sg_get_load_stats),
44 SG_EASY_FUNC(user_stats, sg_get_user_stats),
45 SG_EASY_FUNC(swap_stats, sg_get_swap_stats),
46 SG_COMPLEX_FUNC(fs_stats, sg_get_fs_stats, sg_get_fs_stats_diff),
47 SG_COMPLEX_FUNC(disk_io_stats, sg_get_disk_io_stats,sg_get_disk_io_stats_diff),
48 SG_EASY_FUNC(network_iface_stats, sg_get_network_iface_stats),
49 SG_COMPLEX_FUNC(network_io_stats, sg_get_network_io_stats, sg_get_network_io_stats_diff),
50 SG_COMPLEX_FUNC(page_stats, sg_get_page_stats, sg_get_page_stats_diff),
51 SG_EASY_FUNC(process_stats, sg_get_process_stats) /* XXX process count */
52 };
53
54 struct statgrab_testfuncs *
get_testable_functions(size_t * entries)55 get_testable_functions(size_t *entries) {
56 if(entries)
57 *entries = lengthof(statgrab_test_funcs);
58
59 return statgrab_test_funcs;
60 }
61
62 static size_t
find_full_func(const char * func_name,size_t namelen)63 find_full_func(const char *func_name, size_t namelen) {
64 size_t idx;
65
66 for( idx = 0; idx < lengthof(statgrab_test_funcs); ++idx ) {
67 if( 0 == strncmp( func_name, statgrab_test_funcs[idx].full_name, namelen ) ) /* XXX memcmp? */
68 break;
69 }
70
71 return idx;
72 }
73
74 static size_t
find_diff_func(const char * func_name,size_t namelen)75 find_diff_func(const char *func_name, size_t namelen) {
76 size_t idx;
77
78 for( idx = 0; idx < lengthof(statgrab_test_funcs); ++idx ) {
79 if( NULL == statgrab_test_funcs[idx].diff_name )
80 continue;
81 if( 0 == strncmp( func_name, statgrab_test_funcs[idx].diff_name, namelen ) ) /* XXX memcmp? */
82 break;
83 }
84
85 return idx;
86 }
87
88 #define NAME_OF(a,full) full ? (a).full_name : (a).diff_name
89
90 size_t
funcnames_to_indices(const char * name_list,size_t ** indices,int full)91 funcnames_to_indices(const char *name_list, size_t **indices, int full) {
92 size_t i = 0;
93 const char *name_start;
94
95 if( ( indices == NULL ) || ( *indices != NULL ) )
96 return 0;
97 *indices = calloc( lengthof(statgrab_test_funcs), sizeof(indices[0]) );
98 if( *indices == NULL )
99 return 0;
100
101 for( name_start = name_list; *name_list; ++name_list ) {
102 if( ',' == *name_list ) {
103 size_t idx = full
104 ? find_full_func( name_start, name_list - name_start )
105 : find_diff_func( name_start, name_list - name_start );
106 if( idx >= lengthof(statgrab_test_funcs) ) {
107 fprintf( stderr, "invalid function name for testing: %s\n", name_start );
108 exit(255);
109 }
110 DEBUG_LOG_FMT( "testlib", "funcnames_to_indices: found function %s", NAME_OF(statgrab_test_funcs[i],full) );
111 (*indices)[i++] = idx;
112 name_start = name_list + 1;
113 }
114 }
115
116 if( name_start < name_list ) {
117 size_t idx = full
118 ? find_full_func( name_start, name_list - name_start )
119 : find_diff_func( name_start, name_list - name_start );
120 if( idx >= lengthof(statgrab_test_funcs) ) {
121 fprintf( stderr, "invalid function name for testing: %s\n", name_start );
122 exit(255);
123 }
124 DEBUG_LOG_FMT( "testlib", "funcnames_to_indices: found function %s", NAME_OF(statgrab_test_funcs[i],full) );
125 (*indices)[i++] = idx;
126 name_start = name_list + 1;
127 }
128
129 return i;
130 }
131
132 void
print_testable_functions(int full)133 print_testable_functions(int full)
134 {
135 size_t i;
136
137 for( i = 0; i < lengthof(statgrab_test_funcs); ++i ) {
138 if( !full && NULL == statgrab_test_funcs[i].diff_name )
139 continue;
140 printf( "%s\n", full ? statgrab_test_funcs[i].full_name : statgrab_test_funcs[i].diff_name );
141 }
142 }
143
144 size_t
report_testable_functions(int full)145 report_testable_functions(int full)
146 {
147 size_t i, ok = 0;
148 for( i = 0; i < lengthof(statgrab_test_funcs); ++i ) {
149 if(0 != statgrab_test_funcs[i].needed)
150 printf( "%s (%s) - needed: %d, succeeded: %d, done: %d\n",
151 statgrab_test_funcs[i].stat_name,
152 full ? statgrab_test_funcs[i].full_name : statgrab_test_funcs[i].diff_name,
153 statgrab_test_funcs[i].needed,
154 statgrab_test_funcs[i].succeeded,
155 statgrab_test_funcs[i].done );
156 if( statgrab_test_funcs[i].needed == statgrab_test_funcs[i].done )
157 ++ok;
158 }
159
160 return ok;
161 }
162
163 void
mark_func(size_t func_index)164 mark_func(size_t func_index) {
165 if( func_index >= lengthof(statgrab_test_funcs) ) {
166 fprintf( stderr, "mark_func: index out of range: %lu\n", (unsigned long int)(func_index) );
167 exit(1);
168 }
169
170 ++statgrab_test_funcs[func_index].needed;
171 }
172
173 int
run_func(size_t func_index,int full)174 run_func(size_t func_index, int full) {
175 size_t entries;
176 void *stats;
177
178 if( func_index >= lengthof(statgrab_test_funcs) ) {
179 fprintf( stderr, "run_func: index out of range: %lu\n", (unsigned long int)(func_index) );
180 exit(1);
181 }
182
183 INFO_LOG_FMT( "testlib", "Calling %s...", NAME_OF(statgrab_test_funcs[func_index],full) );
184 stats = full
185 ? statgrab_test_funcs[func_index].full_fn(&entries)
186 : statgrab_test_funcs[func_index].diff_fn(&entries);
187 #if !(defined(WITH_LIBLOG4CPLUS) || defined(WITH_FULL_CONSOLE_LOGGER))
188 if(!stats) {
189 sg_error_details err_det;
190 char *errmsg = NULL;
191 sg_error errc;
192
193 if( SG_ERROR_NONE != ( errc = sg_get_error_details(&err_det) ) ) {
194 fprintf(stderr, "panic: can't get error details (%d, %s)\n", errc, sg_str_error(errc));
195 }
196 else if( NULL == sg_strperror(&errmsg, &err_det) ) {
197 errc = sg_get_error();
198 fprintf(stderr, "panic: can't prepare error message (%d, %s)\n", errc, sg_str_error(errc));
199 }
200 else {
201 fprintf( stderr, "%s: %s\n", NAME_OF(statgrab_test_funcs[func_index],full), errmsg );
202 }
203
204 free( errmsg );
205 }
206 #endif
207 INFO_LOG_FMT( "testlib", "%s - stats = %p, entries = %lu", NAME_OF(statgrab_test_funcs[func_index],full), stats, entries );
208
209 return stats != 0;
210 }
211
212 void
done_func(size_t func_index,int succeeded)213 done_func(size_t func_index, int succeeded) {
214 if( func_index >= lengthof(statgrab_test_funcs) ) {
215 fprintf( stderr, "done_func: index out of range: %lu\n", (unsigned long int)(func_index) );
216 exit(1);
217 }
218
219 ++statgrab_test_funcs[func_index].done;
220 if(succeeded)
221 ++statgrab_test_funcs[func_index].succeeded;
222 }
223