TPCCLIB
Loading...
Searching...
No Matches
tacmatch.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <strings.h>
15#include <math.h>
16/*****************************************************************************/
17#include "tpcextensions.h"
18#include "tpcift.h"
19#include "tpctac.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Verify that the contents in two TAC files are similar.",
25 "This can be used for automating software and analysis tool testing.",
26 "By default exact match is required for numerical values, but this behavior",
27 "can be changed with options -rel and -abs (below); if both are set, then",
28 "values are considered to match is either of the requirements is met.",
29 "Programs return code is 0, if files were matching, 10, if the files did",
30 "not match, and 1-9 in case of error.",
31 " ",
32 "Usage: @P [options] filename1 filename2",
33 " ",
34 "Options:",
35 " -x[=<Y|n>]",
36 " X values (sample times) are checked (y, default) or not checked (n).",
37 " -y[=<Y|n>]",
38 " Y values (concentrations) are checked (y, default) or not checked (n).",
39 " -w=<y|N>",
40 " Weights are checked (y) or not checked (n, default).",
41 " -tacnames[=<y|N>]",
42 " TAC names are checked (y) or not checked (n, default).",
43 " -xunit[=<y|N>]",
44 " Time unit is checked (y) or not checked (n, default).",
45 " -yunit[=<y|N>]",
46 " Concentration unit is checked (y) or not checked (n, default).",
47 " -abs=<value>",
48 " Absolute differences must not exceed the specified limit.",
49 " -rel=<value>",
50 " Relative differences must not exceed the specified percent limit.",
51 " -stdoptions", // List standard options like --help, -v, etc
52 " ",
53 "Example 1:",
54 " @P data1.tac data2.tac",
55 "Example 2:",
56 " @P -abs=0.02 -rel=5 data1.dat data2.dat",
57 " ",
58 "See also: taclist, iftmatch, imgmatch",
59 " ",
60 "Keywords: TAC, tool, software testing",
61 0};
62/*****************************************************************************/
63
64/*****************************************************************************/
65/* Turn on the globbing of the command line, since it is disabled by default in
66 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
67 In Unix&Linux wildcard command line processing is enabled by default. */
68/*
69#undef _CRT_glob
70#define _CRT_glob -1
71*/
72int _dowildcard = -1;
73/*****************************************************************************/
74
75/*****************************************************************************/
79int main(int argc, char **argv)
80{
81 int ai, help=0, version=0, verbose=1;
82 int ret, matchNr=0;
83 char *cptr, tacfile1[FILENAME_MAX], tacfile2[FILENAME_MAX];
84 TAC tac1, tac2;
85 double test_abs=-1.0;
86 double test_rel=-1.0;
87 /* Optional tests */
88 int xvals=1;
89 int yvals=1;
90 int wvals=0;
91 int tacnames=0;
92 int xunit=0;
93 int yunit=0;
94
95 /*
96 * Get arguments
97 */
98 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
99 tacInit(&tac1); tacInit(&tac2);
100 tacfile1[0]=tacfile2[0]=(char)0;
101 /* Options */
102 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
103 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
104 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
105 if(strncasecmp(cptr, "ABS=", 4)==0) {
106 test_abs=atofVerified(cptr+4); if(!isnan(test_abs)) continue;
107 } else if(strncasecmp(cptr, "REL=", 4)==0) {
108 test_rel=atofVerified(cptr+4); if(!isnan(test_rel)) continue;
109 } else if(strcasecmp(cptr, "X")==0) {
110 xvals=1; continue;
111 } else if(strncasecmp(cptr, "X=", 2)==0) {
112 cptr+=2;
113 if(strncasecmp(cptr, "YES", 1)==0) {xvals=1; continue;}
114 else if(strncasecmp(cptr, "NO", 1)==0) {xvals=0; continue;}
115 } else if(strcasecmp(cptr, "Y")==0) {
116 yvals=1; continue;
117 } else if(strncasecmp(cptr, "Y=", 2)==0) {
118 cptr+=2;
119 if(strncasecmp(cptr, "YES", 1)==0) {yvals=1; continue;}
120 else if(strncasecmp(cptr, "NO", 1)==0) {yvals=0; continue;}
121 } else if(strncasecmp(cptr, "W=", 2)==0) {
122 cptr+=2;
123 if(strncasecmp(cptr, "YES", 1)==0) {wvals=1; continue;}
124 else if(strncasecmp(cptr, "NO", 1)==0) {wvals=0; continue;}
125 } else if(strcasecmp(cptr, "XUNIT")==0) {
126 xunit=1; continue;
127 } else if(strncasecmp(cptr, "XUNIT=", 6)==0) {
128 cptr+=6;
129 if(strncasecmp(cptr, "YES", 1)==0) {xunit=1; continue;}
130 else if(strncasecmp(cptr, "NO", 1)==0) {xunit=0; continue;}
131 } else if(strcasecmp(cptr, "YUNIT")==0) {
132 yunit=1; continue;
133 } else if(strncasecmp(cptr, "YUNIT=", 6)==0) {
134 cptr+=6;
135 if(strncasecmp(cptr, "YES", 1)==0) {yunit=1; continue;}
136 else if(strncasecmp(cptr, "NO", 1)==0) {yunit=0; continue;}
137 } else if(strcasecmp(cptr, "TACNAMES")==0) {
138 tacnames=1; continue;
139 } else if(strncasecmp(cptr, "TACNAMES=", 9)==0) {
140 cptr+=9;
141 if(strncasecmp(cptr, "YES", 1)==0) {tacnames=1; continue;}
142 else if(strncasecmp(cptr, "NO", 1)==0) {tacnames=0; continue;}
143 }
144 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
145 return(1);
146 } else break;
147
148 /* Print help or version? */
149 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
150 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
151 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
152
153 /* Arguments */
154 for(; ai<argc; ai++) {
155 if(!tacfile1[0]) {
156 strlcpy(tacfile1, argv[ai], FILENAME_MAX); continue;
157 } else if(!tacfile2[0]) {
158 strlcpy(tacfile2, argv[ai], FILENAME_MAX); continue;
159 }
160 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
161 return(1);
162 }
163
164 /* Is something missing? */
165 if(!tacfile2[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
166
167 /* In verbose mode print arguments and options */
168 if(verbose>1) {
169 for(ai=0; ai<argc; ai++) printf("%s ", argv[ai]);
170 printf("\n");
171 printf("tacfile1 := %s\n", tacfile1);
172 printf("tacfile2 := %s\n", tacfile2);
173 if(test_abs>=0.0) printf("test_abs := %g\n", test_abs);
174 if(test_rel>=0.0) printf("test_rel := %g\n", test_rel);
175 printf("xvals := %d\n", xvals);
176 printf("yvals := %d\n", yvals);
177 printf("wvals := %d\n", wvals);
178 printf("xunit := %d\n", xunit);
179 printf("yunit := %d\n", yunit);
180 printf("tacnames := %d\n", tacnames);
181 fflush(stdout);
182 }
183
184 TPCSTATUS status; statusInit(&status);
185 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
186 status.verbose=verbose-1;
187
188 /*
189 * Read TAC data
190 */
191 if(verbose>1) printf("\nreading %s\n", tacfile1);
192 ret=tacRead(&tac1, tacfile1, &status);
193 if(ret) {
194 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile1);
195 tacFree(&tac1); tacFree(&tac2);
196 return(2);
197 }
198 if(verbose>2) {
199 printf("fileformat := %s\n", tacFormattxt(tac1.format));
200 printf("tacNr := %d\n", tac1.tacNr);
201 printf("sampleNr := %d\n", tac1.sampleNr);
202 if(tac1.isframe) printf("frames := yes\n"); else printf("frames := no\n");
203 fflush(stdout);
204 }
205 if(verbose>1) printf("\nreading %s\n", tacfile2);
206 ret=tacRead(&tac2, tacfile2, &status);
207 if(ret) {
208 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile2);
209 tacFree(&tac1); tacFree(&tac2);
210 return(3);
211 }
212 if(verbose>2) {
213 printf("fileformat := %s\n", tacFormattxt(tac2.format));
214 printf("tacNr := %d\n", tac2.tacNr);
215 printf("sampleNr := %d\n", tac2.sampleNr);
216 if(tac2.isframe) printf("frames := yes\n"); else printf("frames := no\n");
217 printf("\n");
218 fflush(stdout);
219 }
220
221
222 /*
223 * Check frame and TAC number
224 */
225 if(xvals && yvals && wvals && tac1.sampleNr!=tac2.sampleNr) {
226 fprintf(stdout, " sample numbers in %s and %s do not match.\n", tacfile1, tacfile2);
227 tacFree(&tac1); tacFree(&tac2);
228 return(10);
229 }
230 if(yvals && tacnames && tac1.tacNr!=tac2.tacNr) {
231 fprintf(stdout, " TAC numbers in %s and %s do not match.\n", tacfile1, tacfile2);
232 tacFree(&tac1); tacFree(&tac2);
233 return(10);
234 }
235
236
237 /*
238 * Check units
239 */
240 if(xunit || yunit) {
241 if(verbose>0) printf("test units\n");
242 ret=tacCompareUnit(&tac1, &tac2, &status);
243 if(yunit && (ret==1 || ret==3)) {
244 fprintf(stdout, " concentration units in %s and %s do not match.\n", tacfile1, tacfile2);
245 tacFree(&tac1); tacFree(&tac2);
246 return(10);
247 }
248 if(xunit && (ret==2 || ret==3)) {
249 fprintf(stdout, " time units in %s and %s do not match.\n", tacfile1, tacfile2);
250 tacFree(&tac1); tacFree(&tac2);
251 return(10);
252 }
253 matchNr++;
254 }
255
256 /*
257 * Check x values
258 */
259 if(xvals) {
260 /* If xunit is not tested, convert units if necessary and possible */
261 if(!xunit && tac1.tunit!=tac2.tunit) {
262 ret=tacXUnitConvert(&tac2, tac1.tunit, &status);
263 if(verbose>1) {
264 if(ret==TPCERROR_OK) printf(" sample time units converted.\n");
265 else printf(" sample time units could not be converted.\n");
266 }
267 }
268 if(verbose>0) printf("test sample times\n");
269 if(tacCompareTimes(&tac1, &tac2, test_abs, 0.01*test_rel, &status)) {
270 fprintf(stdout, " time samples in %s and %s do not match.\n", tacfile1, tacfile2);
271 tacFree(&tac1); tacFree(&tac2);
272 return(10);
273 }
274 matchNr++;
275 }
276
277 /*
278 * Check y values
279 */
280 if(yvals) {
281 /* If yunit is not tested, convert units if necessary and possible */
282 if(!yunit && tac1.cunit!=tac2.cunit) {
283 ret=tacYUnitConvert(&tac2, tac1.cunit, &status);
284 if(verbose>1) {
285 if(ret==TPCERROR_OK) printf(" concentration units converted.\n");
286 else printf(" concentration units could not be converted.\n");
287 }
288 }
289 if(verbose>0) printf("test sample concentrations\n");
290 if(tacCompareConc(&tac1, &tac2, -1, test_abs, 0.01*test_rel, &status)) {
291 fprintf(stdout, " concentrations in %s and %s do not match.\n", tacfile1, tacfile2);
292 tacFree(&tac1); tacFree(&tac2);
293 return(10);
294 }
295 matchNr++;
296 }
297
298 /*
299 * Check weights
300 */
301 if(wvals) {
302 if(verbose>0) printf("test sample weights\n");
303 if(tacCompareWeights(&tac1, &tac2, test_abs, 0.01*test_rel, &status)) {
304 fprintf(stdout, " weights in %s and %s do not match.\n", tacfile1, tacfile2);
305 tacFree(&tac1); tacFree(&tac2);
306 return(10);
307 }
308 matchNr++;
309 }
310
311 /*
312 * Check TAC names
313 */
314 if(tacnames) {
315 if(verbose>0) printf("test tac names\n");
316 if(tacCompareNames(&tac1, &tac2, -1, &status)!=0) {
317 fprintf(stdout, " TAC names in %s and %s do not match.\n", tacfile1, tacfile2);
318 tacFree(&tac1); tacFree(&tac2);
319 return(10);
320 }
321 matchNr++;
322 }
323
324 tacFree(&tac1); tacFree(&tac2);
325
326 if(matchNr==0) {
327 fprintf(stderr, "Error: no tests applied.\n");
328 return(1);
329 } else if(verbose>=0)
330 fprintf(stdout, "Match was found.\n");
331
332 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
333 return(0);
334}
335/*****************************************************************************/
336
337/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
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 tpctac.h:87
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
int isframe
Definition tpctac.h:95
unit tunit
Definition tpctac.h:109
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacCompareWeights(TAC *d1, TAC *d2, const double test_abs, const double test_rel, TPCSTATUS *status)
Definition taccomp.c:289
int tacCompareNames(TAC *d1, TAC *d2, const int i, TPCSTATUS *status)
Definition taccomp.c:67
int tacCompareTimes(TAC *d1, TAC *d2, const double test_abs, const double test_rel, TPCSTATUS *status)
Definition taccomp.c:201
int tacCompareConc(TAC *d1, TAC *d2, const int i, const double test_abs, const double test_rel, TPCSTATUS *status)
Definition taccomp.c:122
int tacCompareUnit(TAC *d1, TAC *d2, TPCSTATUS *status)
Definition taccomp.c:27
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
char * tacFormattxt(tacformat c)
Definition tacio.c:98
int tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:72
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
Header file for library libtpcift.
Header file for library libtpctac.