valfaudes.cpp
Go to the documentation of this file.
1/** valfaudes.cpp Utility validate test cases */
2
3/* FAU Discrete Event Systems Library (libfaudes)
4
5 Copyright (C) 2025 Thomas Moor
6 Exclusive copyright is granted to Klaus Schmidt
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
21
22#include "corefaudes.h"
23
24using namespace faudes;
25
26// mini help
27void usage(const std::string& msg="") {
28 if (msg != "") {
29 std::cerr << "valfaudes: error: " << msg << std::endl;
30 std::cerr << std::endl;
31 exit(1);
32 }
33 std::cerr << "valfaudes --- run and validate testcases (" << faudes::VersionString() << ")" << std::endl;
34 std::cerr << std::endl;
35 std::cerr << "usage:" << std::endl;
36 std::cerr << " valfaudes [-v|q] [-t <tmp>] <main-in>" << std::endl;
37 std::cerr << std::endl;
38 std::cerr << "with:" << std::endl;
39 std::cerr << " <main-in> specify '.prot' or a '.flx' input" << std::endl;
40 std::cerr << std::endl;
41 std::cerr << "options:" << std::endl;
42 std::cerr << " -t <tmp> temp dir for extracting/validating flx packages" << std::endl;
43 std::cerr << std::endl;
44 std::cerr << "note: this tool is meant to facilitate the libFAUDES build process and" << std::endl;
45 std::cerr << "relies on std libFAUDES folder layout" << std::endl;
46 std::cerr << std::endl;
47 exit(0);
48}
49
50// config
51bool mOptV=false;
52bool mOptQ=false;
53std::string mLibFaudes=".";
54std::string mLuaFaudes;
55std::string mArgFile;
56std::string mProtFile;
57std::string mTestCase;
58std::string mTestType;
59std::string mTestPath;
60std::string mFlxFile;
61std::string mBinFile;
62std::string mLuaFile;
63std::string mPyFile;
64std::string mTmpProtFile;
65std::string mTmpDir;;
66
67
68// helper: exe suffix
69#ifdef FAUDES_POSIX
70std::string exesfx(void) { return "";}
71#endif
72#ifdef FAUDES_WINDOWS
73std::string exesfx(void) { return ".exe";}
74#endif
75#ifdef FAUDES_GENERIC
76std::string exesfx(void) { return "";}
77#endif
78
79
80// helper: run faudes executable (0<>success)
81int runfexec(const std::string& command, const std::string& arguments="") {
82 std::string cmd=command;
83#ifdef FAUDES_POSIX
84 if(cmd.size()>0)
85 if((cmd.at(0)!='/') && (cmd.at(0)!='.'))
86 cmd= "." + faudes_pathsep() + cmd;
87 if(!arguments.empty())
88 cmd += " " + arguments;
89 if(!mOptV)
90 cmd = cmd + " > /dev/null 2>&1 ";
91#endif
92#ifdef FAUDES_WINDOWS
93 cmd=faudes_extpath(cmd);
94 if(!arguments.empty())
95 cmd += " " + arguments;
96 if(!mOptV)
97 cmd = cmd + " > NUL 2>&1";
98#endif
99 if(!mOptQ)
100 std::cout << "valfaudes: running: \"" << cmd << "\"" << std::endl;
101 return std::system(cmd.c_str());
102}
103
104// helper: run system executable (o<>success)
105int runsexec(const std::string& command, const std::string& arguments="") {
106 std::string cmd=command;
107#ifdef FAUDES_POSIX
108 if(!arguments.empty())
109 cmd += " " + arguments;
110 if(!mOptV)
111 cmd = cmd + " > /dev/null 2>&1 ";
112#endif
113#ifdef FAUDES_WINDOWS
114 cmd=faudes_extpath(cmd);
115 if(!arguments.empty())
116 cmd += " " + arguments;
117 if(!mOptV)
118 cmd = cmd + " > NUL 2>&1";
119#endif
120 if(!mOptQ)
121 std::cout << "valfaudes: running: \"" << cmd << "\"" << std::endl;
122 return std::system(cmd.c_str());
123}
124
125// helper: diff (0<>match)
126int rundiff(const std::string& file1, const std::string& file2) {
127 std::string cmd;
128#ifdef FAUDES_POSIX
129 if(!mOptV)
130 cmd = cmd + " > /dev/null 2>&1 ";
131 cmd= "diff -w --context=3 --show-function-line=mark " + file1 + " " + file2;
132#endif
133#ifdef FAUDES_WINDOWS
134 cmd= "fc /W " + faudes_extpath(file1) + " " + faudes_extpath(file2);
135 if(!mOptV)
136 cmd = cmd + " > NUL 2>&1";
137#endif
138 if(!mOptQ)
139 std::cout << "valfaudes: running: \"" << cmd << "\"" << std::endl;
140 return std::system(cmd.c_str());
141}
142
143
144// helper: find luafaudes
145bool findlua(void) {
146 // is it right here?
147 mLuaFaudes="luafaudes"+exesfx();
148 if(FileExists(mLuaFaudes)) return true;
149 // is it in bin?
151 if(FileExists(mLuaFaudes)) return true;
152 // is it in bin one up?
154 if(FileExists(mLuaFaudes)) return true;
155 // is it in bin two up?
157 if(FileExists(mLuaFaudes)) return true;
158 // is it in bin three up?
160 if(FileExists(mLuaFaudes)) return true;
161 // were lost
162 if(!mOptQ) {
163 std::cout << "valfaudes: could not find luafaudes ( last try \"" << mLuaFaudes <<"\""
164 << "from \"" << faudes_getwd() <<"\""<<std::endl;
165 }
166 return false;
167}
168
169// runner
170int main(int argc, char *argv[]) {
171
172 // primitive command line parser
173 for(int i=1; i<argc; i++) {
174 std::string option(argv[i]);
175 // option: help
176 if((option=="-?") || (option=="--help")) {
177 usage();
178 continue;
179 }
180 // option: verb
181 if((option=="-v") || (option=="--verbose")) {
182 mOptV=true;
183 mOptQ=false;
184 continue;
185 }
186 // option: verb
187 if((option=="-q") || (option=="--quiet")) {
188 mOptV=false;
189 mOptQ=true;
190 continue;
191 }
192 // option: tmp dir
193 if((option=="-t") || (option=="--temp")) {
194 if(++i>argc)
195 usage("cannot read temp dir (-t)");
196 mTmpDir=argv[i];
197 continue;
198 }
199 // option: unknown
200 if(option.c_str()[0]=='-') {
201 usage("unknown option "+ option);
202 continue;
203 }
204 // argument #1 input file
205 if(mArgFile.empty()) {
206 mArgFile=argv[i];
207 continue;
208 }
209 // fail
210 usage("no more than one argument must be specified" );
211 }
212
213 // fail on no input
214 if(mArgFile.empty())
215 usage("no input file specified");
216
217 //report
218 if(!mOptQ)
219 std::cout << "varfaudes: input file: \"" << mArgFile <<"\"" << std::endl;
220
221 // derive config: test type
223 std::string sfx=ExtractSuffix(mArgFile);
224 // case a) its a .prot
225 if(sfx=="prot") {
228 size_t seppos=mTestCase.find_last_of('_');
229 if(seppos==std::string::npos) {
230 usage("could not figure test type (no seperator '_' in '.prot' file)");
231 }
232 mTestType=mTestCase.substr(seppos+1);
233 if(ToLowerCase(mTestType)=="cpp") {
234 mBinFile=mTestCase.substr(0,seppos);
235 }
236 if(ToLowerCase(mTestType)=="lua") {
238 mLuaFile.at(seppos)='.';
239 }
240 if(ToLowerCase(mTestType)=="py") {
242 mPyFile.at(seppos)='.';
243 }
244 mTmpProtFile= "tmp_" + mTestCase + ".prot";
245 mTestCase = mTestCase.substr(0,seppos);
246 }
247 // case b) its an .flx
248 if(sfx=="flx") {
249 mTestType="flx";
253 }
254 // failed test type
255 if(mTestType.empty()) {
256 usage("could not figure test type");
257 }
258
259 // derive config: working dir (for .prot files)
260 if(sfx=="prot") {
261 size_t datapos=mTestPath.rfind("data");
262 if(datapos==std::string::npos) {
263 usage("could not figure working dir (path must end with 'data' [a])");
264 }
265 if(datapos!=mTestPath.size()-5) {
266 usage("could not figure working dir (path must end with 'data' [b])");
267 }
268 if(datapos==0) {
269 usage("could not figure working dir (layout mismatch)");
270 }
271 mTestPath=mTestPath.substr(0,datapos-1);
273 }
274
275 //report
276 if(!mOptQ) {
277 std::cout << "varfaudes:" << std::endl;
278 std::cout << " test case: \"" << mTestCase <<"\"" << std::endl;
279 std::cout << " test working dir: \"" << mTestPath <<"\"" << std::endl;
280 if(!mBinFile.empty())
281 std::cout << " exeutable: \"" << mBinFile <<"\"" << std::endl;
282 if(!mLuaFile.empty())
283 std::cout << " lua script: \"" << mLuaFile <<"\"" << std::endl;
284 if(!mPyFile.empty())
285 std::cout << " python script: \"" << mPyFile <<"\"" << std::endl;
286 if(!mFlxFile.empty())
287 std::cout << " flx file: \"" << mFlxFile <<"\"" << std::endl;
288 }
289
290 // result code (0 for ok)
291 int testok=-1;
292
293 // is there nothing to test?
294 if(mBinFile.empty() && mLuaFile.empty() && mFlxFile.empty() && mPyFile.empty()) {
295 std::cout << "varfaudes: error: nothing we can validate" << std::endl;
296 return 1;
297 }
298
299 // change working dir
300 std::string pwd=faudes_getwd();
301 if(pwd.empty()) {
302 usage("could not figure current working dir");
303 }
304 int cdok=faudes_chdir(mTestPath);
305 if(cdok!=0) {
306 usage("could change to test working dir");
307 }
308
309 // cpp tutorials
310 if(!mBinFile.empty()) {
311 testok=runfexec(mBinFile);
312 }
313
314 // lua tutorials
315 if(!mLuaFile.empty()) {
316 if(!findlua()) {
317#ifdef FAUDES_PLUGIN_LUABUINDINGS
318 usage("could not find luafaudes");
319#endif
320 std::cout << "valfaudes: silently skipping test case" << std::endl;
321 testok=0;
322 } else {
323 std::string arg=mLuaFile;
324 if(mOptV)
325 arg= "-d " + arg;
326 testok=runfexec(mLuaFaudes,arg);
327 }
328 }
329
330 // python tutorials
331 if(!mPyFile.empty()) {
332 testok=runsexec("python",mPyFile);
333 }
334
335
336 // flx extensions
337 if(!mFlxFile.empty()) {
338 // alt: have absolut paths
339 std::string args;
340 args+= "-tbin ../bin";
341 args+= " -t";
342 args+= " ../"+mArgFile+" .";
343 testok=runfexec("../bin/flxinstall",args);
344 }
345
346 // go back to original dir
347 int pwdok=faudes_chdir(pwd);
348 if(pwdok!=0) {
349 usage("could change back working dir");
350 }
351
352 // fail if no tests raun
353 if(testok!=0) {
354 usage("test failed to run");
355 }
356
357 // flx is done here
358 if(!mFlxFile.empty()) {
359 return testok;
360 }
361
362 // fail if no protocol found
364 usage("no test results (expected at \""+mTmpProtFile+"\")");
365 }
366
367 // do diff
369 if(!mOptQ) {
370 if(testok==0)
371 std::cout << "valfaudes: no differences detected: test passed" << std::endl;
372 else
373 std::cout << "valfaudes: diff returncode \"" << testok << "\": test failed" << std::endl;
374 }
375
376 return (testok==0 ? 0 : 1);
377}
int main()
int faudes_chdir(const std::string &nwd)
std::string faudes_extpath(const std::string &rPath)
const std::string & faudes_pathsep(void)
std::string faudes_getwd(void)
std::string VersionString()
std::string ExtractDirectory(const std::string &rFullPath)
std::string PrependPath(const std::string &rLeft, const std::string &rRight)
std::string ExtractFilename(const std::string &rFullPath)
std::string ToLowerCase(const std::string &rString)
std::string ExtractBasename(const std::string &rFullPath)
bool FileExists(const std::string &rFilename)
std::string ExtractSuffix(const std::string &rFullPath)
std::string mTestType
Definition valfaudes.cpp:58
std::string exesfx(void)
Definition valfaudes.cpp:76
std::string mLuaFaudes
Definition valfaudes.cpp:54
int runfexec(const std::string &command, const std::string &arguments="")
Definition valfaudes.cpp:81
std::string mProtFile
Definition valfaudes.cpp:56
std::string mFlxFile
Definition valfaudes.cpp:60
std::string mPyFile
Definition valfaudes.cpp:63
bool mOptV
Definition valfaudes.cpp:51
std::string mArgFile
Definition valfaudes.cpp:55
void usage(const std::string &msg="")
Definition valfaudes.cpp:27
int runsexec(const std::string &command, const std::string &arguments="")
std::string mBinFile
Definition valfaudes.cpp:61
std::string mTmpDir
Definition valfaudes.cpp:65
std::string mLuaFile
Definition valfaudes.cpp:62
bool mOptQ
Definition valfaudes.cpp:52
int rundiff(const std::string &file1, const std::string &file2)
std::string mTmpProtFile
Definition valfaudes.cpp:64
std::string mTestCase
Definition valfaudes.cpp:57
std::string mTestPath
Definition valfaudes.cpp:59
std::string mLibFaudes
Definition valfaudes.cpp:53
bool findlua(void)

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen