TPCCLIB
Loading...
Searching...
No Matches
parmatch.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <strings.h>
16#include <math.h>
17/*****************************************************************************/
18#include "tpcextensions.h"
19#include "tpcift.h"
20#include "tpcpar.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Verify that the contents in two parameter files are similar.",
26 "This can be used for automating software and analysis tool testing.",
27 "By default exact match is required for numerical values, but this behaviour",
28 "can be changed with options -rel and -abs (below); if both are set, then",
29 "values are considered to match is either of the requirements is met.",
30 "Header contents cannot be tested with this tool.",
31 "Programs return code is 0, if files were matching, 10, if the files did",
32 "not match, and 1-9 in case of error.",
33 " ",
34 "Usage: @P [options] filename1 filename2",
35 " ",
36 "Options:",
37 " -p=<Y|n>",
38 " Parameter values are checked (y, default) or not checked (n).",
39 " -sd=<y|N>",
40 " Parameter SD values are checked (y) or not checked (n, default).",
41 " -cl=<y|N>",
42 " Parameter CL values are checked (y) or not checked (n, default).",
43 " -tacnames=<y|N>",
44 " TAC names are checked (y) or not checked (n, default).",
45 " -parnames=<Y|n>",
46 " Parameter names are checked (y, default) or not checked (n).",
47 " -parunits=<y|N>",
48 " Parameter units are checked (y) or not checked (n, default).",
49 " -wss=<y|N>",
50 " WSS values are checked (y) or not checked (n, default).",
51 " -abs=<value>",
52 " Absolute differences must not exceed the specified limit.",
53 " -rel=<value>",
54 " Relative differences must not exceed the specified percent limit.",
55 " -par=<list>",
56 " List of parameter numbers to be tested; all by default.",
57 " -tac=<list>",
58 " List of TAC numbers to be tested; all by default.",
59 " -stdoptions", // List standard options like --help, -v, etc
60 " ",
61 "Example 1:",
62 " @P -tac=1-3 -par=1,4 results1.csv results2.csv",
63 "Example 2:",
64 " @P -abs=0.02 -rel=5 -parnames=n results1.csv results2.csv",
65 " ",
66 "See also: parformat, paradd, pardiff, iftmatch, iftisval, tacmatch",
67 " ",
68 "Keywords: parameter, tool, software testing",
69 0};
70/*****************************************************************************/
71
72/*****************************************************************************/
73/* Turn on the globbing of the command line, since it is disabled by default in
74 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
75 In Unix&Linux wildcard command line processing is enabled by default. */
76/*
77#undef _CRT_glob
78#define _CRT_glob -1
79*/
80int _dowildcard = -1;
81/*****************************************************************************/
82
83/*****************************************************************************/
87int main(int argc, char **argv)
88{
89 int ai, help=0, version=0, verbose=1;
90 int ret, matchNr=0;
91 char *cptr, parfile1[FILENAME_MAX], parfile2[FILENAME_MAX];
92 double test_abs=-1.0;
93 double test_rel=-1.0;
94 /* Optional tests */
95 int pvals=1;
96 int sdvals=0;
97 int clvals=0;
98 int tacnames=0;
99 int parnames=1;
100 int parunits=0;
101 int wssvals=0;
102 INTLIST tlist, plist;
103
104 /*
105 * Get arguments
106 */
107 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
108 intlistInit(&tlist); intlistInit(&plist);
109 parfile1[0]=parfile2[0]=(char)0;
110 /* Options */
111 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
112 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
113 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
114 if(strncasecmp(cptr, "ABS=", 4)==0) {
115 test_abs=atofVerified(cptr+4); if(!isnan(test_abs)) continue;
116 } else if(strncasecmp(cptr, "REL=", 4)==0) {
117 test_rel=atofVerified(cptr+4); if(!isnan(test_rel)) continue;
118 } else if(strncasecmp(cptr, "P=", 2)==0) {
119 if((pvals=tpcYesNo(cptr+2))>=0) continue;
120 } else if(strncasecmp(cptr, "SD=", 3)==0) {
121 if((sdvals=tpcYesNo(cptr+3))>=0) continue;
122 } else if(strncasecmp(cptr, "CL=", 3)==0) {
123 if((clvals=tpcYesNo(cptr+3))>=0) continue;
124 } else if(strncasecmp(cptr, "WSS=", 4)==0) {
125 if((wssvals=tpcYesNo(cptr+4))>=0) continue;
126 } else if(strncasecmp(cptr, "TACNAMES=", 9)==0) {
127 if((tacnames=tpcYesNo(cptr+9))>=0) continue;
128 } else if(strncasecmp(cptr, "PARNAMES=", 9)==0) {
129 if((parnames=tpcYesNo(cptr+9))>=0) continue;
130 } else if(strncasecmp(cptr, "PARUNITS=", 9)==0) {
131 if((parunits=tpcYesNo(cptr+9))>=0) continue;
132 } else if(strncasecmp(cptr, "PAR=", 4)==0) {
133 if(intlistExpandFromString(cptr+4, ", ", &plist, 1)>0) continue;
134 } else if(strncasecmp(cptr, "TAC=", 4)==0) {
135 if(intlistExpandFromString(cptr+4, ", ", &tlist, 1)>0) continue;
136 }
137 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
138 intlistFree(&tlist); intlistFree(&plist);
139 return(1);
140 } else break;
141
142 /* Print help or version? */
143 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
144 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
145 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
146
147 /* Arguments */
148 for(; ai<argc; ai++) {
149 if(!parfile1[0]) {
150 strlcpy(parfile1, argv[ai], FILENAME_MAX); continue;
151 } else if(!parfile2[0]) {
152 strlcpy(parfile2, argv[ai], FILENAME_MAX); continue;
153 }
154 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
155 intlistFree(&tlist); intlistFree(&plist);
156 return(1);
157 }
158
159 /* Is something missing? */
160 if(!parfile2[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
161
162 /* In verbose mode print arguments and options */
163 if(verbose>1) {
164 for(ai=0; ai<argc; ai++)
165 printf("%s ", argv[ai]);
166 printf("\n");
167 printf("parfile1 := %s\n", parfile1);
168 printf("parfile2 := %s\n", parfile2);
169 if(test_abs>=0.0) printf("test_abs := %g\n", test_abs);
170 if(test_rel>=0.0) printf("test_rel := %g\n", test_rel);
171 printf("pvals := %d\n", pvals);
172 printf("sdvals := %d\n", sdvals);
173 printf("clvals := %d\n", clvals);
174 printf("wssvals := %d\n", wssvals);
175 printf("tacnames := %d\n", tacnames);
176 printf("parnames := %d\n", parnames);
177 printf("parunits := %d\n", parunits);
178 if(plist.nr>0) {
179 printf("plist := %d", plist.i[0]);
180 for(int i=1; i<plist.nr; i++) printf(", %d", plist.i[i]);
181 printf("\n");
182 }
183 if(tlist.nr>0) {
184 printf("tlist := %d", tlist.i[0]);
185 for(int i=1; i<tlist.nr; i++) printf(", %d", tlist.i[i]);
186 printf("\n");
187 }
188 fflush(stdout);
189 }
190
191 TPCSTATUS status; statusInit(&status);
192 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
193 status.verbose=verbose-1;
194
195 /*
196 * Read PAR data
197 */
198 if(verbose>1) {printf("reading %s\n", parfile1); fflush(stdout);}
199 PAR par1, par2; parInit(&par1); parInit(&par2);
200 ret=parRead(&par1, parfile1, &status);
201 if(ret) {
202 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), parfile1);
203 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
204 return(2);
205 }
206 if(verbose>1) {printf("reading %s\n", parfile2); fflush(stdout);}
207 ret=parRead(&par2, parfile2, &status);
208 if(ret) {
209 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), parfile2);
210 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
211 return(3);
212 }
213
214 /*
215 * Check parameter names
216 */
217 if(parnames) {
218 if(verbose>0) {printf("parameter names\n"); fflush(stdout);}
219 if(plist.nr==0) {
220 ret=parCompareParameterNames(&par1, &par2, -1, 1, &status);
221 } else {
222 ret=0;
223 for(int pi=0; pi<plist.nr && !ret; pi++) {
224 ret=parCompareParameterNames(&par1, &par2, plist.i[pi]-1, 1, &status);
225 if(ret && verbose>1) printf("no match for parameter %d\n", plist.i[pi]);
226 }
227 }
228 if(ret) {
229 fprintf(stdout, "result: parameter names in %s and %s do not match.\n",
230 parfile1, parfile2);
231 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
232 return(10);
233 }
234 matchNr++;
235 }
236
237 /*
238 * Check parameter units
239 */
240 if(parunits) {
241 if(verbose>0) {printf("parameter units\n"); fflush(stdout);}
242 if(plist.nr==0) {
243 ret=parCompareParameterUnits(&par1, &par2, -1, &status);
244 } else {
245 ret=0;
246 for(int pi=0; pi<plist.nr && !ret; pi++) {
247 ret=parCompareParameterUnits(&par1, &par2, plist.i[pi]-1, &status);
248 if(ret && verbose>1) printf("no match for parameter %d\n", plist.i[pi]);
249 }
250 }
251 if(ret) {
252 fprintf(stdout, "result: parameter units in %s and %s do not match.\n",
253 parfile1, parfile2);
254 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
255 return(10);
256 }
257 matchNr++;
258 }
259
260 /*
261 * Check TAC ids
262 */
263 if(tacnames) {
264 if(verbose>0) {printf("TAC names\n"); fflush(stdout);}
265 if(tlist.nr==0) {
266 ret=parCompareTacNames(&par1, &par2, -1, 1, &status);
267 } else {
268 ret=0;
269 for(int ti=0; ti<tlist.nr && !ret; ti++) {
270 ret=parCompareTacNames(&par1, &par2, tlist.i[ti]-1, 1, &status);
271 if(ret && verbose>1) printf("no match for TAC %d\n", tlist.i[ti]);
272 }
273 }
274 if(ret) {
275 fprintf(stdout, "result: TAC names in %s and %s do not match.\n",
276 parfile1, parfile2);
277 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
278 return(10);
279 }
280 matchNr++;
281 }
282
283 /*
284 * Check parameter values
285 */
286 if(pvals) {
287 if(verbose>0) {printf("parameter values\n"); fflush(stdout);}
288 if(plist.nr==0 && tlist.nr==0) {
289 ret=parCompareParameters(&par1, &par2, -1, -1, 1, 0, 0,
290 test_abs, 0.01*test_rel, &status);
291 } else if(plist.nr==0) {
292 ret=0;
293 for(int ti=0; ti<tlist.nr && !ret; ti++) {
294 ret=parCompareParameters(&par1, &par2, -1, tlist.i[ti]-1,
295 1, 0, 0, test_abs, 0.01*test_rel, &status);
296 if(ret && verbose>1)
297 printf("no match for TAC %d\n", tlist.i[ti]);
298 }
299 } else if(tlist.nr==0) {
300 ret=0;
301 for(int pi=0; pi<plist.nr && !ret; pi++) {
302 ret=parCompareParameters(&par1, &par2, plist.i[pi]-1, -1,
303 1, 0, 0, test_abs, 0.01*test_rel, &status);
304 if(ret && verbose>1)
305 printf("no match for parameter %d\n", plist.i[pi]);
306 }
307 } else {
308 ret=0; int ti, pi;
309 for(ti=0; ti<tlist.nr && !ret; ti++) {
310 for(pi=0; pi<plist.nr && !ret; pi++) {
311 ret=parCompareParameters(&par1, &par2, plist.i[pi]-1, tlist.i[ti]-1,
312 1, 0, 0, test_abs, 0.01*test_rel, &status);
313 if(ret && verbose>1)
314 printf("no match for parameter %d, TAC %d\n",
315 plist.i[pi], tlist.i[ti]);
316 }
317 }
318 }
319 if(ret) {
320 fprintf(stdout, "result: parameter values in %s and %s do not match.\n",
321 parfile1, parfile2);
322 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
323 return(10);
324 }
325 matchNr++;
326 }
327
328 /*
329 * Check SD and CL values
330 */
331 if(sdvals) {
332 if(verbose>0) {printf("parameter SD values\n"); fflush(stdout);}
333 if(plist.nr==0 && tlist.nr==0) {
334 ret=parCompareParameters(&par1, &par2, -1, -1, 0, 1, 0,
335 test_abs, 0.01*test_rel, &status);
336 } else if(plist.nr==0) {
337 ret=0;
338 for(int ti=0; ti<tlist.nr && !ret; ti++) {
339 ret=parCompareParameters(&par1, &par2, -1, tlist.i[ti]-1,
340 0, 1, 0, test_abs, 0.01*test_rel, &status);
341 if(ret && verbose>1)
342 printf("no match for TAC %d\n", tlist.i[ti]);
343 }
344 } else if(tlist.nr==0) {
345 ret=0;
346 for(int pi=0; pi<plist.nr && !ret; pi++) {
347 ret=parCompareParameters(&par1, &par2, plist.i[pi]-1, -1,
348 0, 1, 0, test_abs, 0.01*test_rel, &status);
349 if(ret && verbose>1)
350 printf("no match for parameter %d\n", plist.i[pi]);
351 }
352 } else {
353 ret=0; int ti, pi;
354 for(ti=0; ti<tlist.nr && !ret; ti++) {
355 for(pi=0; pi<plist.nr && !ret; pi++) {
356 ret=parCompareParameters(&par1, &par2, plist.i[pi]-1, tlist.i[ti]-1,
357 0, 1, 0, test_abs, 0.01*test_rel, &status);
358 if(ret && verbose>1)
359 printf("no match for parameter %d, TAC %d\n",
360 plist.i[pi], tlist.i[ti]);
361 }
362 }
363 }
364 if(ret) {
365 fprintf(stdout, "result: parameter SD values in %s and %s do not match.\n",
366 parfile1, parfile2);
367 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
368 return(10);
369 }
370 matchNr++;
371 }
372 if(clvals) {
373 if(verbose>0) {printf("parameter CL values\n"); fflush(stdout);}
374 if(plist.nr==0 && tlist.nr==0) {
375 ret=parCompareParameters(&par1, &par2, -1, -1, 0, 0, 1,
376 test_abs, 0.01*test_rel, &status);
377 } else if(plist.nr==0) {
378 ret=0;
379 for(int ti=0; ti<tlist.nr && !ret; ti++) {
380 ret=parCompareParameters(&par1, &par2, -1, tlist.i[ti]-1,
381 0, 0, 1, test_abs, 0.01*test_rel, &status);
382 if(ret && verbose>1)
383 printf("no match for TAC %d\n", tlist.i[ti]);
384 }
385 } else if(tlist.nr==0) {
386 ret=0;
387 for(int pi=0; pi<plist.nr && !ret; pi++) {
388 ret=parCompareParameters(&par1, &par2, plist.i[pi]-1, -1,
389 0, 0, 1, test_abs, 0.01*test_rel, &status);
390 if(ret && verbose>1)
391 printf("no match for parameter %d\n", plist.i[pi]);
392 }
393 } else {
394 ret=0; int ti, pi;
395 for(ti=0; ti<tlist.nr && !ret; ti++) {
396 for(pi=0; pi<plist.nr && !ret; pi++) {
397 ret=parCompareParameters(&par1, &par2, plist.i[pi]-1, tlist.i[ti]-1,
398 0, 0, 1, test_abs, 0.01*test_rel, &status);
399 if(ret && verbose>1)
400 printf("no match for parameter %d, TAC %d\n",
401 plist.i[pi], tlist.i[ti]);
402 }
403 }
404 }
405 if(ret) {
406 fprintf(stdout, "result: parameter CL values in %s and %s do not match.\n",
407 parfile1, parfile2);
408 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
409 return(10);
410 }
411 matchNr++;
412 }
413
414 /*
415 * Check WSS values
416 */
417 if(wssvals) {
418 if(verbose>0) {printf("WSS values\n"); fflush(stdout);}
419 if(plist.nr==0) {
420 ret=parCompareWSS(&par1, &par2, test_abs, -1, 0.01*test_rel, &status);
421 } else {
422 ret=0;
423 for(int pi=0; pi<plist.nr && !ret; pi++) {
424 ret=parCompareWSS(&par1, &par2, test_abs, plist.i[pi]-1,
425 0.01*test_rel, &status);
426 if(ret && verbose>1) printf("no match for parameter %d\n", plist.i[pi]);
427 }
428 }
429 if(ret) {
430 fprintf(stdout, "result: WSS values in %s and %s do not match.\n",
431 parfile1, parfile2);
432 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
433 return(10);
434 }
435 matchNr++;
436 }
437
438 parFree(&par1); parFree(&par2); intlistFree(&tlist); intlistFree(&plist);
439
440 if(matchNr==0) {
441 fprintf(stderr, "Error: no tests applied.\n"); fflush(stderr);
442 return(1);
443 } else if(verbose>=0) {
444 fprintf(stdout, "result: match was found.\n"); fflush(stdout);
445 }
446 return(0);
447}
448/*****************************************************************************/
449
450/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
void intlistInit(INTLIST *l)
Definition intutil.c:80
int intlistExpandFromString(const char *s1, const char *s2, INTLIST *l, const int ifnew)
Definition intutil.c:190
void intlistFree(INTLIST *l)
Definition intutil.c:92
void parFree(PAR *par)
Definition par.c:75
void parInit(PAR *par)
Definition par.c:25
int parCompareTacNames(PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
Definition parcomp.c:157
int parCompareParameterNames(PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
Definition parcomp.c:28
int parCompareParameterUnits(PAR *d1, PAR *d2, const int i, TPCSTATUS *status)
Definition parcomp.c:103
int parCompareParameters(PAR *d1, PAR *d2, const int pi, const int ti, int checkpar, int checksd, int checkcl, const double test_abs, const double test_rel, TPCSTATUS *status)
Definition parcomp.c:237
int parCompareWSS(PAR *d1, PAR *d2, const int ti, const double test_abs, const double test_rel, TPCSTATUS *status)
Definition parcomp.c:378
int parRead(PAR *par, const char *fname, TPCSTATUS *status)
Definition pario.c:232
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcYesNo(const char *s)
Definition proginfo.c:459
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
Definition tpcpar.h:100
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
Header file for library libtpcift.
Header file for libtpcpar.