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