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 
24 using namespace faudes;
25 
26 // mini help
27 void 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
51 bool mOptV=false;
52 bool mOptQ=false;
53 std::string mLibFaudes=".";
54 std::string mLuaFaudes;
55 std::string mArgFile;
56 std::string mProtFile;
57 std::string mTestCase;
58 std::string mTestType;
59 std::string mTestPath;
60 std::string mFlxFile;
61 std::string mBinFile;
62 std::string mLuaFile;
63 std::string mPyFile;
64 std::string mTmpProtFile;
65 std::string mTmpDir;;
66 
67 
68 // helper: exe suffix
69 #ifdef FAUDES_POSIX
70 std::string exesfx(void) { return "";}
71 #endif
72 #ifdef FAUDES_WINDOWS
73 std::string exesfx(void) { return ".exe";}
74 #endif
75 #ifdef FAUDES_GENERIC
76 std::string exesfx(void) { return "";}
77 #endif
78 
79 
80 // helper: run faudes executable (o<>success)
81 int 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)
105 int 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)
126 int 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
145 bool 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
170 int 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  testok=runfexec(mLuaFaudes,mLuaFile);
324  }
325  }
326 
327  // python tutorials
328  if(!mPyFile.empty()) {
329  testok=runsexec("python",mPyFile);
330  }
331 
332 
333  // flx extensions
334  if(!mFlxFile.empty()) {
335  // alt: have absolut paths
336  std::string args;
337  args+= "-tbin ../bin";
338  args+= " -t";
339  args+= " ../"+mArgFile+" .";
340  testok=runfexec("../bin/flxinstall",args);
341  }
342 
343  // go back to original dir
344  int pwdok=faudes_chdir(pwd);
345  if(pwdok!=0) {
346  usage("could change to back working dir");
347  }
348 
349  // fail if no tests raun
350  if(testok!=0) {
351  usage("test failed to run");
352  }
353 
354  // flx is done here
355  if(!mFlxFile.empty()) {
356  return testok;
357  }
358 
359  // fail if no protocol found
360  if(!FileExists(mTmpProtFile)) {
361  usage("no test results (expected at \""+mTmpProtFile+"\")");
362  }
363 
364  // do diff
365  testok = rundiff(mProtFile,mTmpProtFile);
366  if(!mOptQ) {
367  if(testok==0)
368  std::cout << "valfaudes: no differences detected: test passed" << std::endl;
369  else
370  std::cout << "valfaudes: diff returncode \"" << testok << "\": test failed" << std::endl;
371  }
372 
373  return (testok==0 ? 0 : 1);
374 }
int faudes_chdir(const std::string &nwd)
const std::string & faudes_pathsep(void)
std::string faudes_extpath(const std::string &rPath)
std::string faudes_getwd(void)
std::string VersionString()
Definition: cfl_utils.cpp:141
std::string ExtractDirectory(const std::string &rFullPath)
Definition: cfl_utils.cpp:283
std::string PrependPath(const std::string &rLeft, const std::string &rRight)
Definition: cfl_utils.cpp:330
std::string ExtractFilename(const std::string &rFullPath)
Definition: cfl_utils.cpp:292
std::string ToLowerCase(const std::string &rString)
Definition: cfl_utils.cpp:111
std::string ExtractBasename(const std::string &rFullPath)
Definition: cfl_utils.cpp:301
bool FileExists(const std::string &rFilename)
Definition: cfl_utils.cpp:412
std::string ExtractSuffix(const std::string &rFullPath)
Definition: cfl_utils.cpp:315
std::string mTestType
Definition: valfaudes.cpp:58
std::string exesfx(void)
Definition: valfaudes.cpp:76
int main(int argc, char *argv[])
Definition: valfaudes.cpp:170
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="")
Definition: valfaudes.cpp:105
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)
Definition: valfaudes.cpp:126
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)
Definition: valfaudes.cpp:145

libFAUDES 2.33h --- 2025.06.18 --- c++ api documentaion by doxygen