10#include "tpcclibConfig.h"
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.",
34 "Usage: @P [options] filename1 filename2",
38 " Parameter values are checked (y, default) or not checked (n).",
40 " Parameter SD values are checked (y) or not checked (n, default).",
42 " Parameter CL values are checked (y) or not checked (n, default).",
44 " TAC names are checked (y) or not checked (n, default).",
46 " Parameter names are checked (y, default) or not checked (n).",
48 " Parameter units are checked (y) or not checked (n, default).",
50 " WSS values are checked (y) or not checked (n, default).",
52 " Absolute differences must not exceed the specified limit.",
54 " Relative differences must not exceed the specified percent limit.",
56 " List of parameter numbers to be tested; all by default.",
58 " List of TAC numbers to be tested; all by default.",
62 " @P -tac=1-3 -par=1,4 results1.csv results2.csv",
64 " @P -abs=0.02 -rel=5 -parnames=n results1.csv results2.csv",
66 "See also: parformat, paradd, pardiff, iftmatch, iftisval, tacmatch",
68 "Keywords: parameter, tool, software testing",
87int main(
int argc,
char **argv)
89 int ai, help=0, version=0, verbose=1;
91 char *cptr, parfile1[FILENAME_MAX], parfile2[FILENAME_MAX];
107 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
109 parfile1[0]=parfile2[0]=(char)0;
111 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
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) {
134 }
else if(strncasecmp(cptr,
"TAC=", 4)==0) {
137 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
143 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
148 for(; ai<argc; ai++) {
150 strlcpy(parfile1, argv[ai], FILENAME_MAX);
continue;
151 }
else if(!parfile2[0]) {
152 strlcpy(parfile2, argv[ai], FILENAME_MAX);
continue;
154 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
160 if(!parfile2[0]) {
tpcPrintUsage(argv[0], info, stdout);
return(1);}
164 for(ai=0; ai<argc; ai++)
165 printf(
"%s ", argv[ai]);
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);
179 printf(
"plist := %d", plist.
i[0]);
180 for(
int i=1; i<plist.
nr; i++) printf(
", %d", plist.
i[i]);
184 printf(
"tlist := %d", tlist.
i[0]);
185 for(
int i=1; i<tlist.
nr; i++) printf(
", %d", tlist.
i[i]);
198 if(verbose>1) {printf(
"reading %s\n", parfile1); fflush(stdout);}
200 ret=
parRead(&par1, parfile1, &status);
202 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), parfile1);
206 if(verbose>1) {printf(
"reading %s\n", parfile2); fflush(stdout);}
207 ret=
parRead(&par2, parfile2, &status);
209 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), parfile2);
218 if(verbose>0) {printf(
"parameter names\n"); fflush(stdout);}
223 for(
int pi=0; pi<plist.
nr && !ret; pi++) {
225 if(ret && verbose>1) printf(
"no match for parameter %d\n", plist.
i[pi]);
229 fprintf(stdout,
"result: parameter names in %s and %s do not match.\n",
241 if(verbose>0) {printf(
"parameter units\n"); fflush(stdout);}
246 for(
int pi=0; pi<plist.
nr && !ret; pi++) {
248 if(ret && verbose>1) printf(
"no match for parameter %d\n", plist.
i[pi]);
252 fprintf(stdout,
"result: parameter units in %s and %s do not match.\n",
264 if(verbose>0) {printf(
"TAC names\n"); fflush(stdout);}
269 for(
int ti=0; ti<tlist.
nr && !ret; ti++) {
271 if(ret && verbose>1) printf(
"no match for TAC %d\n", tlist.
i[ti]);
275 fprintf(stdout,
"result: TAC names in %s and %s do not match.\n",
287 if(verbose>0) {printf(
"parameter values\n"); fflush(stdout);}
288 if(plist.
nr==0 && tlist.
nr==0) {
290 test_abs, 0.01*test_rel, &status);
291 }
else if(plist.
nr==0) {
293 for(
int ti=0; ti<tlist.
nr && !ret; ti++) {
295 1, 0, 0, test_abs, 0.01*test_rel, &status);
297 printf(
"no match for TAC %d\n", tlist.
i[ti]);
299 }
else if(tlist.
nr==0) {
301 for(
int pi=0; pi<plist.
nr && !ret; pi++) {
303 1, 0, 0, test_abs, 0.01*test_rel, &status);
305 printf(
"no match for parameter %d\n", plist.
i[pi]);
309 for(ti=0; ti<tlist.
nr && !ret; ti++) {
310 for(pi=0; pi<plist.
nr && !ret; pi++) {
312 1, 0, 0, test_abs, 0.01*test_rel, &status);
314 printf(
"no match for parameter %d, TAC %d\n",
315 plist.
i[pi], tlist.
i[ti]);
320 fprintf(stdout,
"result: parameter values in %s and %s do not match.\n",
332 if(verbose>0) {printf(
"parameter SD values\n"); fflush(stdout);}
333 if(plist.
nr==0 && tlist.
nr==0) {
335 test_abs, 0.01*test_rel, &status);
336 }
else if(plist.
nr==0) {
338 for(
int ti=0; ti<tlist.
nr && !ret; ti++) {
340 0, 1, 0, test_abs, 0.01*test_rel, &status);
342 printf(
"no match for TAC %d\n", tlist.
i[ti]);
344 }
else if(tlist.
nr==0) {
346 for(
int pi=0; pi<plist.
nr && !ret; pi++) {
348 0, 1, 0, test_abs, 0.01*test_rel, &status);
350 printf(
"no match for parameter %d\n", plist.
i[pi]);
354 for(ti=0; ti<tlist.
nr && !ret; ti++) {
355 for(pi=0; pi<plist.
nr && !ret; pi++) {
357 0, 1, 0, test_abs, 0.01*test_rel, &status);
359 printf(
"no match for parameter %d, TAC %d\n",
360 plist.
i[pi], tlist.
i[ti]);
365 fprintf(stdout,
"result: parameter SD values in %s and %s do not match.\n",
373 if(verbose>0) {printf(
"parameter CL values\n"); fflush(stdout);}
374 if(plist.
nr==0 && tlist.
nr==0) {
376 test_abs, 0.01*test_rel, &status);
377 }
else if(plist.
nr==0) {
379 for(
int ti=0; ti<tlist.
nr && !ret; ti++) {
381 0, 0, 1, test_abs, 0.01*test_rel, &status);
383 printf(
"no match for TAC %d\n", tlist.
i[ti]);
385 }
else if(tlist.
nr==0) {
387 for(
int pi=0; pi<plist.
nr && !ret; pi++) {
389 0, 0, 1, test_abs, 0.01*test_rel, &status);
391 printf(
"no match for parameter %d\n", plist.
i[pi]);
395 for(ti=0; ti<tlist.
nr && !ret; ti++) {
396 for(pi=0; pi<plist.
nr && !ret; pi++) {
398 0, 0, 1, test_abs, 0.01*test_rel, &status);
400 printf(
"no match for parameter %d, TAC %d\n",
401 plist.
i[pi], tlist.
i[ti]);
406 fprintf(stdout,
"result: parameter CL values in %s and %s do not match.\n",
418 if(verbose>0) {printf(
"WSS values\n"); fflush(stdout);}
420 ret=
parCompareWSS(&par1, &par2, test_abs, -1, 0.01*test_rel, &status);
423 for(
int pi=0; pi<plist.
nr && !ret; pi++) {
425 0.01*test_rel, &status);
426 if(ret && verbose>1) printf(
"no match for parameter %d\n", plist.
i[pi]);
430 fprintf(stdout,
"result: WSS values in %s and %s do not match.\n",
441 fprintf(stderr,
"Error: no tests applied.\n"); fflush(stderr);
443 }
else if(verbose>=0) {
444 fprintf(stdout,
"result: match was found.\n"); fflush(stdout);
double atofVerified(const char *s)
void intlistInit(INTLIST *l)
int intlistExpandFromString(const char *s1, const char *s2, INTLIST *l, const int ifnew)
void intlistFree(INTLIST *l)
int parCompareTacNames(PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
int parCompareParameterNames(PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
int parCompareParameterUnits(PAR *d1, PAR *d2, const int i, TPCSTATUS *status)
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)
int parCompareWSS(PAR *d1, PAR *d2, const int ti, const double test_abs, const double test_rel, TPCSTATUS *status)
int parRead(PAR *par, const char *fname, TPCSTATUS *status)
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int tpcYesNo(const char *s)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
Header file for library libtpcextensions.
Header file for library libtpcift.
Header file for libtpcpar.