ctest.cxx 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "ctest.h"
  14. #include "cmRegularExpression.h"
  15. #include "cmSystemTools.h"
  16. #include "cmListFileCache.h"
  17. #include <stdio.h>
  18. #include <time.h>
  19. static std::string CleanString(std::string str)
  20. {
  21. std::string::size_type spos = str.find_first_not_of(" \n\t");
  22. std::string::size_type epos = str.find_last_not_of(" \n\t");
  23. if ( spos == str.npos )
  24. {
  25. return std::string();
  26. }
  27. if ( epos != str.npos )
  28. {
  29. epos = epos - spos + 1;
  30. }
  31. return str.substr(spos, epos);
  32. }
  33. static std::string CurrentTime()
  34. {
  35. time_t currenttime = time(0);
  36. return ::CleanString(ctime(&currenttime));
  37. }
  38. static const char* cmCTestErrorMatches[] = {
  39. "^[Bb]us [Ee]rror",
  40. "^[Ss]egmentation [Vv]iolation",
  41. "^[Ss]egmentation [Ff]ault",
  42. "([^ :]+):([0-9]+): ([^ \\t])",
  43. "([^:]+): error[ \\t]*[0-9]+[ \\t]*:",
  44. "^Error ([0-9]+):",
  45. "^Error ",
  46. "^\"[^\"]+\", line [0-9]+: [^Ww]",
  47. "^cc[^C]*CC: ERROR File = ([^,]+), Line = ([0-9]+)",
  48. "^ld([^:])*:([ \\t])*ERROR([^:])*:",
  49. "^ild:([ \\t])*\\(undefined symbol\\)",
  50. "([^ :]+) : (error|fatal error|catastrophic error)",
  51. "([^:]+): (Error:|error|undefined reference|multiply defined)",
  52. "([^:]+)\\(([^\\)]+)\\) : (error|fatal error|catastrophic error)",
  53. "^fatal error C[0-9]+:",
  54. ": syntax error ",
  55. "^collect2: ld returned 1 exit status",
  56. "Unsatisfied symbols:",
  57. "Undefined symbols:",
  58. "^Undefined[ \\t]+first referenced",
  59. "^CMake Error:",
  60. ":[ \\t]cannot find",
  61. 0
  62. };
  63. static const char* cmCTestErrorExceptions[] = {
  64. 0
  65. };
  66. static const char* cmCTestWarningMatches[] = {
  67. "([^ :]+):([0-9]+): warning:",
  68. "^cc[^C]*CC: WARNING File = ([^,]+), Line = ([0-9]+)",
  69. "^ld([^:])*:([ \\t])*WARNING([^:])*:",
  70. "([^:]+): warning ([0-9]+):",
  71. "^\"[^\"]+\", line [0-9]+: [Ww]arning",
  72. "([^:]+): warning[ \\t]*[0-9]+[ \\t]*:",
  73. "^Warning ([0-9]+):",
  74. "^Warning ",
  75. "([^ :]+) : warning",
  76. "([^:]+): warning",
  77. 0
  78. };
  79. static const char* cmCTestWarningExceptions[] = {
  80. "/usr/openwin/include/X11/Xlib\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration",
  81. "/usr/openwin/include/X11/Xutil\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration",
  82. "/usr/openwin/include/X11/XResource\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration",
  83. "WARNING 84 :",
  84. "WARNING 47 :",
  85. "makefile:",
  86. "Makefile:",
  87. "warning: Clock skew detected. Your build may be incomplete.",
  88. "/usr/openwin/include/GL/[^:]+:",
  89. "bind_at_load",
  90. "XrmQGetResource",
  91. "IceFlush",
  92. "warning LNK4089: all references to .GDI32.dll. discarded by .OPT:REF",
  93. "warning LNK4089: all references to .USER32.dll. discarded by .OPT:REF",
  94. "ld32: WARNING 85: definition of dataKey in",
  95. 0
  96. };
  97. std::string ctest::MakeXMLSafe(const std::string& str)
  98. {
  99. std::string::size_type pos = 0;
  100. cmOStringStream ost;
  101. char buffer[10];
  102. for ( pos = 0; pos < str.size(); pos ++ )
  103. {
  104. char ch = str[pos];
  105. if ( ch > 126 )
  106. {
  107. sprintf(buffer, "&%x", (int)ch);
  108. ost << buffer;
  109. }
  110. else
  111. {
  112. switch ( ch )
  113. {
  114. case '&': ost << "&amp;"; break;
  115. case '<': ost << "&lt;"; break;
  116. case '>': ost << "&gt;"; break;
  117. default: ost << ch;
  118. }
  119. }
  120. }
  121. return ost.str();
  122. }
  123. bool TryExecutable(const char *dir, const char *file,
  124. std::string *fullPath, const char *subdir)
  125. {
  126. // try current directory
  127. std::string tryPath;
  128. if (dir && strcmp(dir,""))
  129. {
  130. tryPath = dir;
  131. tryPath += "/";
  132. }
  133. if (subdir && strcmp(subdir,""))
  134. {
  135. tryPath += subdir;
  136. tryPath += "/";
  137. }
  138. tryPath += file;
  139. if(cmSystemTools::FileExists(tryPath.c_str()))
  140. {
  141. *fullPath = cmSystemTools::CollapseFullPath(tryPath.c_str());
  142. return true;
  143. }
  144. tryPath += cmSystemTools::GetExecutableExtension();
  145. if(cmSystemTools::FileExists(tryPath.c_str()))
  146. {
  147. *fullPath = cmSystemTools::CollapseFullPath(tryPath.c_str());
  148. return true;
  149. }
  150. return false;
  151. }
  152. ctest::ctest()
  153. {
  154. m_UseIncludeRegExp = false;
  155. m_UseExcludeRegExp = false;
  156. m_UseExcludeRegExpFirst = false;
  157. m_Verbose = false;
  158. m_DartMode = false;
  159. int cc;
  160. for ( cc=0; cc < ctest::LAST_TEST; cc ++ )
  161. {
  162. m_Tests[cc] = 0;
  163. }
  164. }
  165. void ctest::Initialize()
  166. {
  167. m_ToplevelPath = cmSystemTools::GetCurrentWorkingDirectory();
  168. // parse the dart test file
  169. std::ifstream fin("DartConfiguration.tcl");
  170. if(!fin)
  171. {
  172. return;
  173. }
  174. char buffer[1024];
  175. while ( fin )
  176. {
  177. buffer[0] = 0;
  178. fin.getline(buffer, 1023);
  179. buffer[1023] = 0;
  180. std::string line = ::CleanString(buffer);
  181. if(line.size() == 0)
  182. {
  183. continue;
  184. }
  185. while ( fin && (line[line.size()-1] == '\\') )
  186. {
  187. line = line.substr(0, line.size()-1);
  188. buffer[0] = 0;
  189. fin.getline(buffer, 1023);
  190. buffer[1023] = 0;
  191. line += ::CleanString(buffer);
  192. }
  193. if ( line[0] == '#' )
  194. {
  195. continue;
  196. }
  197. std::string::size_type cpos = line.find_first_of(":");
  198. if ( cpos == line.npos )
  199. {
  200. continue;
  201. }
  202. std::string key = line.substr(0, cpos);
  203. std::string value = ::CleanString(line.substr(cpos+1, line.npos));
  204. m_DartConfiguration[key] = value;
  205. }
  206. fin.close();
  207. if ( m_DartMode )
  208. {
  209. std::string testingDir = m_ToplevelPath + "/Testing/CDart";
  210. if ( cmSystemTools::FileExists(testingDir.c_str()) )
  211. {
  212. if ( !cmSystemTools::FileIsDirectory(testingDir.c_str()) )
  213. {
  214. std::cerr << "File " << testingDir << " is in the place of the testing directory"
  215. << std::endl;
  216. return;
  217. }
  218. }
  219. else
  220. {
  221. if ( !cmSystemTools::MakeDirectory(testingDir.c_str()) )
  222. {
  223. std::cerr << "Cannot create directory " << testingDir
  224. << std::endl;
  225. return;
  226. }
  227. }
  228. std::string tagfile = testingDir + "/TAG";
  229. std::ifstream tfin(tagfile.c_str());
  230. std::string tag;
  231. time_t tctime = time(0);
  232. struct tm *lctime = gmtime(&tctime);
  233. if ( tfin )
  234. {
  235. tfin >> tag;
  236. tfin.close();
  237. int year = 0;
  238. int mon = 0;
  239. int day = 0;
  240. int hour = 0;
  241. int min = 0;
  242. sscanf(tag.c_str(), "%04d%02d%02d-%02d%02d",
  243. &year, &mon, &day, &hour, &min);
  244. if ( year != lctime->tm_year + 1900 ||
  245. mon != lctime->tm_mon ||
  246. day != lctime->tm_mday )
  247. {
  248. tag = "";
  249. }
  250. }
  251. if ( tag.size() == 0 )
  252. {
  253. char datestring[100];
  254. sprintf(datestring, "%04d%02d%02d-%02d%02d",
  255. lctime->tm_year + 1900,
  256. lctime->tm_mon,
  257. lctime->tm_mday,
  258. lctime->tm_hour,
  259. lctime->tm_min);
  260. tag = datestring;
  261. std::ofstream ofs(tagfile.c_str());
  262. if ( ofs )
  263. {
  264. ofs << tag << std::endl;
  265. }
  266. ofs.close();
  267. std::cout << "Create new tag: " << tag << std::endl;
  268. }
  269. m_CurrentTag = tag;
  270. }
  271. }
  272. bool ctest::SetTest(const char* ttype)
  273. {
  274. if ( cmSystemTools::LowerCase(ttype) == "all" )
  275. {
  276. m_Tests[ctest::ALL_TEST] = 1;
  277. }
  278. else if ( cmSystemTools::LowerCase(ttype) == "update" )
  279. {
  280. m_Tests[ctest::UPDATE_TEST] = 1;
  281. }
  282. else if ( cmSystemTools::LowerCase(ttype) == "configure" )
  283. {
  284. m_Tests[ctest::CONFIGURE_TEST] = 1;
  285. }
  286. else if ( cmSystemTools::LowerCase(ttype) == "build" )
  287. {
  288. m_Tests[ctest::BUILD_TEST] = 1;
  289. }
  290. else if ( cmSystemTools::LowerCase(ttype) == "test" )
  291. {
  292. m_Tests[ctest::TEST_TEST] = 1;
  293. }
  294. else if ( cmSystemTools::LowerCase(ttype) == "coverage" )
  295. {
  296. m_Tests[ctest::COVERAGE_TEST] = 1;
  297. }
  298. else if ( cmSystemTools::LowerCase(ttype) == "purify" )
  299. {
  300. m_Tests[ctest::PURIFY_TEST] = 1;
  301. }
  302. else
  303. {
  304. std::cerr << "Don't know about test \"" << ttype << "\" yet..." << std::endl;
  305. return false;
  306. }
  307. return true;
  308. }
  309. void ctest::Finalize()
  310. {
  311. }
  312. std::string ctest::FindExecutable(const char *exe)
  313. {
  314. std::string fullPath = "";
  315. std::string dir;
  316. std::string file;
  317. cmSystemTools::SplitProgramPath(exe, dir, file);
  318. if(m_ConfigType != "")
  319. {
  320. if(TryExecutable(dir.c_str(), file.c_str(), &fullPath,
  321. m_ConfigType.c_str()))
  322. {
  323. return fullPath;
  324. }
  325. dir += "/";
  326. dir += m_ConfigType;
  327. dir += "/";
  328. dir += file;
  329. cmSystemTools::Error("config type specified on the command line, but test executable not found.",
  330. dir.c_str());
  331. return "";
  332. }
  333. if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"."))
  334. {
  335. return fullPath;
  336. }
  337. if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,""))
  338. {
  339. return fullPath;
  340. }
  341. if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Release"))
  342. {
  343. return fullPath;
  344. }
  345. if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Debug"))
  346. {
  347. return fullPath;
  348. }
  349. if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"MinSizeRel"))
  350. {
  351. return fullPath;
  352. }
  353. if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"RelWithDebInfo"))
  354. {
  355. return fullPath;
  356. }
  357. // if everything else failed, check the users path
  358. if (dir != "")
  359. {
  360. std::string path = cmSystemTools::FindProgram(file.c_str());
  361. if (path != "")
  362. {
  363. return path;
  364. }
  365. }
  366. return fullPath;
  367. }
  368. int ctest::UpdateDirectory()
  369. {
  370. std::string cvsCommand = m_DartConfiguration["CVSCommand"];
  371. if ( cvsCommand.size() == 0 )
  372. {
  373. std::cerr << "Cannot find CVSCommand key in the DartConfiguration.tcl" << std::endl;
  374. return 1;
  375. }
  376. std::string cvsOptions = m_DartConfiguration["CVSUpdateOptions"];
  377. if ( cvsOptions.size() == 0 )
  378. {
  379. std::cerr << "Cannot find CVSUpdateOptions key in the DartConfiguration.tcl" << std::endl;
  380. return 1;
  381. }
  382. std::string sourceDirectory = m_DartConfiguration["SourceDirectory"];
  383. if ( sourceDirectory.size() == 0 )
  384. {
  385. std::cerr << "Cannot find SourceDirectory key in the DartConfiguration.tcl" << std::endl;
  386. return 1;
  387. }
  388. std::string command = cvsCommand + " update " + cvsOptions;
  389. std::string output;
  390. int retVal;
  391. bool res = cmSystemTools::RunCommand(command.c_str(), output,
  392. retVal, sourceDirectory.c_str(),
  393. m_Verbose);
  394. if (! res || retVal )
  395. {
  396. std::cerr << "Error(s) when updating the project" << std::endl;
  397. return 1;
  398. }
  399. return 0;
  400. }
  401. int ctest::ConfigureDirectory()
  402. {
  403. std::string cCommand = m_DartConfiguration["ConfigureCommand"];
  404. if ( cCommand.size() == 0 )
  405. {
  406. std::cerr << "Cannot find ConfigureCommand key in the DartConfiguration.tcl" << std::endl;
  407. return 1;
  408. }
  409. std::string buildDirectory = m_DartConfiguration["BuildDirectory"];
  410. if ( buildDirectory.size() == 0 )
  411. {
  412. std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl;
  413. return 1;
  414. }
  415. std::string output;
  416. int retVal;
  417. bool res = cmSystemTools::RunCommand(cCommand.c_str(), output,
  418. retVal, buildDirectory.c_str(),
  419. m_Verbose);
  420. if (! res || retVal )
  421. {
  422. std::cerr << "Error(s) when updating the project" << std::endl;
  423. return 1;
  424. }
  425. return 0;
  426. }
  427. int ctest::BuildDirectory()
  428. {
  429. std::string makeCommand = m_DartConfiguration["MakeCommand"];
  430. if ( makeCommand.size() == 0 )
  431. {
  432. std::cerr << "Cannot find MakeCommand key in the DartConfiguration.tcl" << std::endl;
  433. return 1;
  434. }
  435. std::string buildDirectory = m_DartConfiguration["BuildDirectory"];
  436. if ( buildDirectory.size() == 0 )
  437. {
  438. std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl;
  439. return 1;
  440. }
  441. m_StartBuild = ::CurrentTime();
  442. std::string output;
  443. int retVal;
  444. bool res = cmSystemTools::RunCommand(makeCommand.c_str(), output,
  445. retVal, buildDirectory.c_str(),
  446. m_Verbose);
  447. m_EndBuild = ::CurrentTime();
  448. if (! res || retVal )
  449. {
  450. std::cerr << "Error(s) when building project" << std::endl;
  451. }
  452. // Parsing of output for errors and warnings.
  453. std::vector<cmStdString> lines;
  454. cmSystemTools::Split(output.c_str(), lines);
  455. std::ofstream ofs;
  456. if ( this->OpenOutputFile("Temporary", "LastBuild.log", ofs) )
  457. {
  458. ofs << output;
  459. ofs.close();
  460. }
  461. else
  462. {
  463. std::cerr << "Cannot create LastBuild.log file" << std::endl;
  464. }
  465. // Lines are marked:
  466. // 0 - nothing
  467. // 1 - error
  468. // > 1 - warning
  469. std::vector<int> markedLines(lines.size(), 0);
  470. int cc;
  471. // Errors
  472. for ( cc = 0; cmCTestErrorMatches[cc]; cc ++ )
  473. {
  474. cmRegularExpression re(cmCTestErrorMatches[cc]);
  475. std::vector<std::string>::size_type kk;
  476. for ( kk = 0; kk < lines.size(); kk ++ )
  477. {
  478. if ( re.find(lines[kk]) )
  479. {
  480. markedLines[kk] = 1;
  481. }
  482. }
  483. }
  484. // Warnings
  485. for ( cc = 0; cmCTestWarningMatches[cc]; cc ++ )
  486. {
  487. cmRegularExpression re(cmCTestWarningMatches[cc]);
  488. std::vector<std::string>::size_type kk;
  489. for ( kk = 0; kk < lines.size(); kk ++ )
  490. {
  491. if ( re.find(lines[kk]) )
  492. {
  493. markedLines[kk] += 2;
  494. }
  495. }
  496. }
  497. // Errors exceptions
  498. for ( cc = 0; cmCTestErrorExceptions[cc]; cc ++ )
  499. {
  500. cmRegularExpression re(cmCTestErrorExceptions[cc]);
  501. std::vector<int>::size_type kk;
  502. for ( kk =0; kk < markedLines.size(); kk ++ )
  503. {
  504. if ( markedLines[cc] == 1 )
  505. {
  506. if ( re.find(lines[kk]) )
  507. {
  508. markedLines[cc] = 0;
  509. }
  510. }
  511. }
  512. }
  513. // Warning exceptions
  514. for ( cc = 0; cmCTestWarningExceptions[cc]; cc ++ )
  515. {
  516. cmRegularExpression re(cmCTestWarningExceptions[cc]);
  517. std::vector<int>::size_type kk;
  518. for ( kk =0; kk < markedLines.size(); kk ++ )
  519. {
  520. if ( markedLines[cc] > 1 )
  521. {
  522. if ( re.find(lines[kk]) )
  523. {
  524. markedLines[cc] = 0;
  525. }
  526. }
  527. }
  528. }
  529. std::vector<cmCTestBuildErrorWarning> errorsWarnings;
  530. std::vector<int>::size_type kk;
  531. cmCTestBuildErrorWarning errorwarning;
  532. for ( kk =0; kk < markedLines.size(); kk ++ )
  533. {
  534. errorwarning.m_LineNumber = -1;
  535. bool found = false;
  536. if ( markedLines[kk] == 1 )
  537. {
  538. std::cout << "Error: " << lines[kk] << std::endl;
  539. errorwarning.m_Error = true;
  540. found = true;
  541. }
  542. else if ( markedLines[kk] > 1 )
  543. {
  544. std::cout << "Warning: " << lines[kk] << std::endl;
  545. errorwarning.m_Error = false;
  546. found = true;
  547. }
  548. if ( found )
  549. {
  550. errorwarning.m_LogLine = static_cast<int>(kk+1);
  551. errorwarning.m_Text = lines[kk];
  552. errorwarning.m_PreContext = "";
  553. errorwarning.m_PostContext = "";
  554. std::vector<int>::size_type jj;
  555. std::vector<int>::size_type ll = 0;
  556. if ( kk > 6 )
  557. {
  558. ll = kk - 6;
  559. }
  560. for ( jj = kk;
  561. jj > 0 && jj > ll /* && markedLines[jj] == 0 */;
  562. jj -- );
  563. for (; jj < kk; jj ++ )
  564. {
  565. errorwarning.m_PreContext += lines[jj] + "\n";
  566. }
  567. for ( jj = kk+1;
  568. jj < lines.size() && jj < kk + 7 /* && markedLines[jj] == 0*/;
  569. jj ++ )
  570. {
  571. errorwarning.m_PostContext += lines[jj] + "\n";
  572. }
  573. errorsWarnings.push_back(errorwarning);
  574. }
  575. }
  576. if( !this->OpenOutputFile("", "Build.xml", ofs) )
  577. {
  578. std::cerr << "Cannot create build XML file" << std::endl;
  579. return 1;
  580. }
  581. this->GenerateDartBuildOutput(ofs, errorsWarnings);
  582. return 0;
  583. }
  584. int ctest::CoverageDirectory()
  585. {
  586. std::vector<std::string> files;
  587. std::vector<std::string> cfiles;
  588. std::vector<std::string> cdirs;
  589. bool done = false;
  590. std::string::size_type cc;
  591. std::string glob;
  592. std::map<std::string, std::string> allsourcefiles;
  593. std::map<std::string, std::string> allbinaryfiles;
  594. std::string start_time = ::CurrentTime();
  595. // Find all source files.
  596. std::string sourceDirectory = m_DartConfiguration["SourceDirectory"];
  597. if ( sourceDirectory.size() == 0 )
  598. {
  599. std::cerr << "Cannot find SourceDirectory key in the DartConfiguration.tcl" << std::endl;
  600. return 1;
  601. }
  602. cdirs.push_back(sourceDirectory);
  603. while ( !done )
  604. {
  605. if ( cdirs.size() <= 0 )
  606. {
  607. break;
  608. }
  609. glob = cdirs[cdirs.size()-1] + "/*";
  610. //std::cout << "Glob: " << glob << std::endl;
  611. cdirs.pop_back();
  612. if ( cmSystemTools::SimpleGlob(glob, cfiles, 1) )
  613. {
  614. for ( cc = 0; cc < cfiles.size(); cc ++ )
  615. {
  616. allsourcefiles[cmSystemTools::GetFilenameName(cfiles[cc])] = cfiles[cc];
  617. }
  618. }
  619. if ( cmSystemTools::SimpleGlob(glob, cfiles, -1) )
  620. {
  621. for ( cc = 0; cc < cfiles.size(); cc ++ )
  622. {
  623. if ( cfiles[cc] != "." && cfiles[cc] != ".." )
  624. {
  625. cdirs.push_back(cfiles[cc]);
  626. }
  627. }
  628. }
  629. }
  630. // find all binary files
  631. cdirs.push_back(cmSystemTools::GetCurrentWorkingDirectory());
  632. while ( !done )
  633. {
  634. if ( cdirs.size() <= 0 )
  635. {
  636. break;
  637. }
  638. glob = cdirs[cdirs.size()-1] + "/*";
  639. //std::cout << "Glob: " << glob << std::endl;
  640. cdirs.pop_back();
  641. if ( cmSystemTools::SimpleGlob(glob, cfiles, 1) )
  642. {
  643. for ( cc = 0; cc < cfiles.size(); cc ++ )
  644. {
  645. allbinaryfiles[cmSystemTools::GetFilenameName(cfiles[cc])] = cfiles[cc];
  646. }
  647. }
  648. if ( cmSystemTools::SimpleGlob(glob, cfiles, -1) )
  649. {
  650. for ( cc = 0; cc < cfiles.size(); cc ++ )
  651. {
  652. if ( cfiles[cc] != "." && cfiles[cc] != ".." )
  653. {
  654. cdirs.push_back(cfiles[cc]);
  655. }
  656. }
  657. }
  658. }
  659. std::map<std::string, std::string>::iterator sit;
  660. for ( sit = allbinaryfiles.begin(); sit != allbinaryfiles.end(); sit ++ )
  661. {
  662. const std::string& fname = sit->second;
  663. //std::cout << "File: " << fname << std::endl;
  664. if ( strcmp(fname.substr(fname.size()-3, 3).c_str(), ".da") == 0 )
  665. {
  666. files.push_back(fname);
  667. }
  668. }
  669. if ( files.size() == 0 )
  670. {
  671. std::cout << "Cannot find any coverage information files (.da)" << std::endl;
  672. return 1;
  673. }
  674. std::ofstream log;
  675. if (!this->OpenOutputFile("Coverage", "Coverage.log", log))
  676. {
  677. std::cout << "Cannot open log file" << std::endl;
  678. return 1;
  679. }
  680. log.close();
  681. if (!this->OpenOutputFile("", "Coverage.xml", log))
  682. {
  683. std::cout << "Cannot open log file" << std::endl;
  684. return 1;
  685. }
  686. std::string opath = m_ToplevelPath + "/Testing/CDart/Coverage";
  687. for ( cc = 0; cc < files.size(); cc ++ )
  688. {
  689. std::string command = "gcov -l \"" + files[cc] + "\"";
  690. std::string output;
  691. int retVal;
  692. //std::cout << "Run gcov on " << files[cc] << std::flush;
  693. bool res = cmSystemTools::RunCommand(command.c_str(), output,
  694. retVal, opath.c_str(),
  695. m_Verbose);
  696. if ( res && retVal == 0 )
  697. {
  698. //std::cout << " - done" << std::endl;
  699. }
  700. else
  701. {
  702. //std::cout << " - fail" << std::endl;
  703. }
  704. }
  705. files.clear();
  706. glob = opath + "/*";
  707. if ( !cmSystemTools::SimpleGlob(glob, cfiles, 1) )
  708. {
  709. std::cout << "Cannot found any coverage files" << std::endl;
  710. return 1;
  711. }
  712. std::map<std::string, std::vector<std::string> > sourcefiles;
  713. for ( cc = 0; cc < cfiles.size(); cc ++ )
  714. {
  715. std::string& fname = cfiles[cc];
  716. //std::cout << "File: " << fname << std::endl;
  717. if ( strcmp(fname.substr(fname.size()-5, 5).c_str(), ".gcov") == 0 )
  718. {
  719. files.push_back(fname);
  720. std::string::size_type pos = fname.find(".da.");
  721. if ( pos != fname.npos )
  722. {
  723. pos += 4;
  724. std::string::size_type epos = fname.size() - pos - strlen(".gcov");
  725. std::string nf = fname.substr(pos, epos);
  726. //std::cout << "Substring: " << nf << std::endl;
  727. if ( allsourcefiles.find(nf) != allsourcefiles.end() ||
  728. allbinaryfiles.find(nf) != allbinaryfiles.end() )
  729. {
  730. std::vector<std::string> &cvec = sourcefiles[nf];
  731. cvec.push_back(fname);
  732. }
  733. }
  734. }
  735. }
  736. for ( cc = 0; cc < files.size(); cc ++ )
  737. {
  738. //std::cout << "File: " << files[cc] << std::endl;
  739. }
  740. std::map<std::string, std::vector<std::string> >::iterator it;
  741. ctest::tm_CoverageMap coverageresults;
  742. log << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  743. << "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
  744. << "\" BuildStamp=\"" << m_CurrentTag << "-Experimental\" Name=\""
  745. << m_DartConfiguration["Site"] << "\">\n"
  746. << "<Coverage>\n"
  747. << "\t<StartDateTime>" << start_time << "</StartDateTime>" << std::endl;
  748. int total_tested = 0;
  749. int total_untested = 0;
  750. for ( it = sourcefiles.begin(); it != sourcefiles.end(); it ++ )
  751. {
  752. //std::cerr << "Source file: " << it->first << std::endl;
  753. std::vector<std::string> &gfiles = it->second;
  754. for ( cc = 0; cc < gfiles.size(); cc ++ )
  755. {
  756. //std::cout << "\t" << gfiles[cc] << std::endl;
  757. std::ifstream ifile(gfiles[cc].c_str());
  758. ifile.seekg (0, std::ios::end);
  759. int length = ifile.tellg();
  760. ifile.seekg (0, std::ios::beg);
  761. char *buffer = new char [ length + 1 ];
  762. ifile.read(buffer, length);
  763. buffer [length] = 0;
  764. //std::cout << "Read: " << buffer << std::endl;
  765. std::vector<cmStdString> lines;
  766. cmSystemTools::Split(buffer, lines);
  767. delete [] buffer;
  768. ctest::cmCTestCoverage& cov = coverageresults[it->first];
  769. std::vector<int>& covlines = cov.m_Lines;
  770. if ( cov.m_FullPath == "" )
  771. {
  772. covlines.insert(covlines.begin(), lines.size(), -1);
  773. if ( allsourcefiles.find(it->first) != allsourcefiles.end() )
  774. {
  775. cov.m_FullPath = allsourcefiles[it->first];
  776. }
  777. else if ( allbinaryfiles.find(it->first) != allbinaryfiles.end() )
  778. {
  779. cov.m_FullPath = allbinaryfiles[it->first];
  780. }
  781. //std::cerr << "Full path: " << cov.m_FullPath << std::endl;
  782. }
  783. for ( cc = 0; cc < lines.size(); cc ++ )
  784. {
  785. std::string& line = lines[cc];
  786. std::string sub = line.substr(0, strlen(" ######"));
  787. int count = atoi(sub.c_str());
  788. if ( sub.compare(" ######") == 0 )
  789. {
  790. if ( covlines[cc] == -1 )
  791. {
  792. covlines[cc] = 0;
  793. }
  794. cov.m_UnTested ++;
  795. //std::cout << "Untested - ";
  796. }
  797. else if ( count > 0 )
  798. {
  799. if ( covlines[cc] == -1 )
  800. {
  801. covlines[cc] = 0;
  802. }
  803. cov.m_Tested ++;
  804. covlines[cc] += count;
  805. //std::cout << "Tested[" << count << "] - ";
  806. }
  807. //std::cout << line << std::endl;
  808. }
  809. }
  810. }
  811. //std::cerr << "Finalizing" << std::endl;
  812. ctest::tm_CoverageMap::iterator cit;
  813. int ccount = 0;
  814. std::ofstream cfileoutput;
  815. int cfileoutputcount = 0;
  816. char cfileoutputname[100];
  817. sprintf(cfileoutputname, "CoverageLog-%d.xml", cfileoutputcount++);
  818. if (!this->OpenOutputFile("", cfileoutputname, cfileoutput))
  819. {
  820. std::cout << "Cannot open log file" << std::endl;
  821. return 1;
  822. }
  823. std::string local_start_time = ::CurrentTime();
  824. std::string local_end_time;
  825. for ( cit = coverageresults.begin(); cit != coverageresults.end(); cit ++ )
  826. {
  827. if ( ccount == 100 )
  828. {
  829. local_end_time = ::CurrentTime();
  830. cfileoutput << "\t<EndDateTime>" << local_end_time << "</EndDateTime>\n"
  831. << "</CoverageLog>\n"
  832. << "</Site>" << std::endl;
  833. cfileoutput.close();
  834. sprintf(cfileoutputname, "CoverageLog-%d.xml", cfileoutputcount++);
  835. if (!this->OpenOutputFile("", cfileoutputname, cfileoutput))
  836. {
  837. std::cout << "Cannot open log file" << std::endl;
  838. return 1;
  839. }
  840. ccount = 0;
  841. }
  842. if ( ccount == 0 )
  843. {
  844. local_start_time = ::CurrentTime();
  845. cfileoutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  846. << "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
  847. << "\" BuildStamp=\"" << m_CurrentTag << "-Experimental\" Name=\""
  848. << m_DartConfiguration["Site"] << "\">\n"
  849. << "<CoverageLog>\n"
  850. << "\t<StartDateTime>" << local_start_time << "</StartDateTime>" << std::endl;
  851. }
  852. //std::cerr << "Final process of Source file: " << cit->first << std::endl;
  853. ctest::cmCTestCoverage &cov = cit->second;
  854. std::ifstream ifile(cov.m_FullPath.c_str());
  855. ifile.seekg (0, std::ios::end);
  856. int length = ifile.tellg();
  857. ifile.seekg (0, std::ios::beg);
  858. char *buffer = new char [ length + 1 ];
  859. ifile.read(buffer, length);
  860. buffer [length] = 0;
  861. //std::cout << "Read: " << buffer << std::endl;
  862. std::vector<cmStdString> lines;
  863. cmSystemTools::Split(buffer, lines);
  864. delete [] buffer;
  865. cfileoutput << "\t<File Name=\"" << cit->first << "\" FullPath=\""
  866. << cov.m_FullPath << std::endl << "\">\n"
  867. << "\t\t<Report>" << std::endl;
  868. for ( cc = 0; cc < lines.size(); cc ++ )
  869. {
  870. cfileoutput << "\t\t<Line Number=\""
  871. << static_cast<int>(cc) << "\" Count=\""
  872. << cov.m_Lines[cc] << "\">"
  873. << lines[cc] << "</Line>" << std::endl;
  874. }
  875. cfileoutput << "\t\t</Report>\n"
  876. << "\t</File>" << std::endl;
  877. total_tested += cov.m_Tested;
  878. total_untested += cov.m_UnTested;
  879. float cper = 0;
  880. float cmet = 0;
  881. if ( total_tested + total_untested > 0 )
  882. {
  883. cper = (100 * static_cast<float>(cov.m_Tested)/
  884. static_cast<float>(cov.m_Tested + cov.m_UnTested));
  885. cmet = ( static_cast<float>(cov.m_Tested + 10) /
  886. static_cast<float>(cov.m_Tested + cov.m_UnTested + 10));
  887. }
  888. log << "\t<File Name=\"" << cit->first << "\" FullPath=\"" << cov.m_FullPath
  889. << "\" Covered=\"" << cov.m_Covered << "\">\n"
  890. << "\t\t<LOCTested>" << cov.m_Tested << "</LOCTested>\n"
  891. << "\t\t<LOCUnTested>" << cov.m_UnTested << "</LOCUnTested>\n"
  892. << "\t\t<PercentCoverage>" << cper << "</PercentCoverage>\n"
  893. << "\t\t<CoverageMetric>" << cmet << "</CoverageMetric>\n"
  894. << "\t</File>" << std::endl;
  895. }
  896. if ( ccount > 0 )
  897. {
  898. local_end_time = ::CurrentTime();
  899. cfileoutput << "\t<EndDateTime>" << local_end_time << "</EndDateTime>\n"
  900. << "</CoverageLog>\n"
  901. << "</Site>" << std::endl;
  902. cfileoutput.close();
  903. }
  904. int total_lines = total_tested + total_untested;
  905. float percent_coverage = 100 * static_cast<float>(total_tested) /
  906. static_cast<float>(total_lines);
  907. if ( total_lines == 0 )
  908. {
  909. percent_coverage = 0;
  910. }
  911. std::string end_time = ::CurrentTime();
  912. log << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
  913. << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
  914. << "\t<LOC>" << total_lines << "</LOC>\n"
  915. << "\t<PercentCoverage>" << percent_coverage << "</PercentCoverage>\n"
  916. << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
  917. << "</Coverage>\n"
  918. << "</Site>" << std::endl;
  919. std::cout << "\tCovered LOC: " << total_tested << std::endl
  920. << "\tNot covered LOC: " << total_untested << std::endl
  921. << "\tTotal LOC: " << total_lines << std::endl
  922. << "\tPercentage Coverage: " << percent_coverage << "%" << std::endl;
  923. std::cerr << "Coverage test is not yet implemented" << std::endl;
  924. return 1;
  925. }
  926. bool ctest::OpenOutputFile(const std::string& path,
  927. const std::string& name, std::ofstream& stream)
  928. {
  929. std::string testingDir = m_ToplevelPath + "/Testing/CDart";
  930. if ( path.size() > 0 )
  931. {
  932. testingDir += "/" + path;
  933. }
  934. if ( cmSystemTools::FileExists(testingDir.c_str()) )
  935. {
  936. if ( !cmSystemTools::FileIsDirectory(testingDir.c_str()) )
  937. {
  938. std::cerr << "File " << testingDir
  939. << " is in the place of the testing directory"
  940. << std::endl;
  941. return false;
  942. }
  943. }
  944. else
  945. {
  946. if ( !cmSystemTools::MakeDirectory(testingDir.c_str()) )
  947. {
  948. std::cerr << "Cannot create directory " << testingDir
  949. << std::endl;
  950. return false;
  951. }
  952. }
  953. std::string filename = testingDir + "/" + name;
  954. stream.open(filename.c_str());
  955. if( !stream )
  956. {
  957. return false;
  958. }
  959. return true;
  960. }
  961. void ctest::GenerateDartBuildOutput(std::ostream& os,
  962. std::vector<cmCTestBuildErrorWarning> ew)
  963. {
  964. os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  965. << "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
  966. << "\" BuildStamp=\"" << m_CurrentTag << "-Experimental\" Name=\""
  967. << m_DartConfiguration["Site"] << "\">\n"
  968. << "<Build>\n"
  969. << "\t<StartDateTime>" << m_StartBuild << "</StartDateTime>\n"
  970. << "<BuildCommand>"
  971. << this->MakeXMLSafe(m_DartConfiguration["MakeCommand"])
  972. << "</BuildCommand>" << std::endl;
  973. std::vector<cmCTestBuildErrorWarning>::iterator it;
  974. for ( it = ew.begin(); it != ew.end(); it++ )
  975. {
  976. cmCTestBuildErrorWarning *cm = &(*it);
  977. os << "\t<" << (cm->m_Error ? "Error" : "Warning") << ">\n"
  978. << "\t\t<BuildLogLine>" << cm->m_LogLine << "</BuildLogLine>\n"
  979. << "\t\t<Text>" << this->MakeXMLSafe(cm->m_Text)
  980. << "\n</Text>" << std::endl;
  981. if ( cm->m_SourceFile.size() > 0 )
  982. {
  983. os << "\t\t<SourceFile>" << cm->m_SourceFile << "</SourceFile>"
  984. << std::endl;
  985. }
  986. if ( cm->m_SourceFileTail.size() > 0 )
  987. {
  988. os << "\t\t<SourceFileTail>" << cm->m_SourceFileTail
  989. << "</SourceFileTail>" << std::endl;
  990. }
  991. if ( cm->m_LineNumber >= 0 )
  992. {
  993. os << "\t\t<SourceLineNumber>" << cm->m_LineNumber
  994. << "</SourceLineNumber>" << std::endl;
  995. }
  996. os << "\t\t<PreContext>" << this->MakeXMLSafe(cm->m_PreContext)
  997. << "</PreContext>\n"
  998. << "\t\t<PostContext>" << this->MakeXMLSafe(cm->m_PostContext)
  999. << "</PostContext>\n"
  1000. << "\t\t<RepeatCount>0</RepeatCount>\n"
  1001. << "</" << (cm->m_Error ? "Error" : "Warning") << ">\n\n"
  1002. << std::endl;
  1003. }
  1004. os << "\t<Log Encoding=\"base64\" Compression=\"/bin/gzip\">\n\t</Log>\n"
  1005. << "\t<EndDateTime>" << m_EndBuild << "</EndDateTime>\n"
  1006. << "</Build>\n"
  1007. << "</Site>" << std::endl;
  1008. }
  1009. void ctest::ProcessDirectory(std::vector<std::string> &passed,
  1010. std::vector<std::string> &failed)
  1011. {
  1012. // does the DartTestfile.txt exist ?
  1013. if(!cmSystemTools::FileExists("DartTestfile.txt"))
  1014. {
  1015. return;
  1016. }
  1017. // parse the file
  1018. std::ifstream fin("DartTestfile.txt");
  1019. if(!fin)
  1020. {
  1021. return;
  1022. }
  1023. int firstTest = 1;
  1024. long line = 0;
  1025. std::string name;
  1026. std::vector<std::string> args;
  1027. cmRegularExpression ireg(this->m_IncludeRegExp.c_str());
  1028. cmRegularExpression ereg(this->m_ExcludeRegExp.c_str());
  1029. cmRegularExpression dartStuff("([\t\n ]*<DartMeasurement.*/DartMeasurement[a-zA-Z]*>[\t ]*[\n]*)");
  1030. bool parseError;
  1031. while ( fin )
  1032. {
  1033. cmListFileFunction lff;
  1034. if(cmListFileCache::ParseFunction(fin, lff, "DartTestfile.txt",
  1035. parseError, line))
  1036. {
  1037. const std::string& name = lff.m_Name;
  1038. const std::vector<cmListFileArgument>& args = lff.m_Arguments;
  1039. if (name == "SUBDIRS")
  1040. {
  1041. std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  1042. for(std::vector<cmListFileArgument>::const_iterator j = args.begin();
  1043. j != args.end(); ++j)
  1044. {
  1045. std::string nwd = cwd + "/";
  1046. nwd += j->Value;
  1047. if (cmSystemTools::FileIsDirectory(nwd.c_str()))
  1048. {
  1049. cmSystemTools::ChangeDirectory(nwd.c_str());
  1050. this->ProcessDirectory(passed, failed);
  1051. }
  1052. }
  1053. // return to the original directory
  1054. cmSystemTools::ChangeDirectory(cwd.c_str());
  1055. }
  1056. if (name == "ADD_TEST")
  1057. {
  1058. if (this->m_UseExcludeRegExp &&
  1059. this->m_UseExcludeRegExpFirst &&
  1060. ereg.find(args[0].Value.c_str()))
  1061. {
  1062. continue;
  1063. }
  1064. if (this->m_UseIncludeRegExp && !ireg.find(args[0].Value.c_str()))
  1065. {
  1066. continue;
  1067. }
  1068. if (this->m_UseExcludeRegExp &&
  1069. !this->m_UseExcludeRegExpFirst &&
  1070. ereg.find(args[0].Value.c_str()))
  1071. {
  1072. continue;
  1073. }
  1074. cmCTestTestResult cres;
  1075. if (firstTest)
  1076. {
  1077. std::string nwd = cmSystemTools::GetCurrentWorkingDirectory();
  1078. std::cerr << "Changing directory into " << nwd.c_str() << "\n";
  1079. firstTest = 0;
  1080. }
  1081. cres.m_Name = args[0].Value;
  1082. fprintf(stderr,"Testing %-30s ",args[0].Value.c_str());
  1083. fflush(stderr);
  1084. //std::cerr << "Testing " << args[0] << " ... ";
  1085. // find the test executable
  1086. std::string testCommand = this->FindExecutable(args[1].Value.c_str());
  1087. testCommand = cmSystemTools::ConvertToOutputPath(testCommand.c_str());
  1088. // continue if we did not find the executable
  1089. if (testCommand == "")
  1090. {
  1091. std::cerr << "Unable to find executable: " <<
  1092. args[1].Value.c_str() << "\n";
  1093. continue;
  1094. }
  1095. // add the arguments
  1096. std::vector<cmListFileArgument>::const_iterator j = args.begin();
  1097. ++j;
  1098. ++j;
  1099. for(;j != args.end(); ++j)
  1100. {
  1101. testCommand += " ";
  1102. testCommand += cmSystemTools::EscapeSpaces(j->Value.c_str());
  1103. }
  1104. /**
  1105. * Run an executable command and put the stdout in output.
  1106. */
  1107. std::string output;
  1108. int retVal;
  1109. double clock_start, clock_finish;
  1110. clock_start = cmSystemTools::GetTime();
  1111. if ( m_Verbose )
  1112. {
  1113. std::cout << std::endl << "Test command: " << testCommand << std::endl;
  1114. }
  1115. bool res = cmSystemTools::RunCommand(testCommand.c_str(), output,
  1116. retVal, 0, false);
  1117. clock_finish = cmSystemTools::GetTime();
  1118. cres.m_ExecutionTime = (double)(clock_finish - clock_start);
  1119. cres.m_FullCommandLine = testCommand;
  1120. if (!res || retVal != 0)
  1121. {
  1122. fprintf(stderr,"***Failed\n");
  1123. if (output != "")
  1124. {
  1125. if (dartStuff.find(output.c_str()))
  1126. {
  1127. cmSystemTools::ReplaceString(output,
  1128. dartStuff.match(1).c_str(),"");
  1129. }
  1130. if (output != "" && m_Verbose)
  1131. {
  1132. std::cerr << output.c_str() << "\n";
  1133. }
  1134. }
  1135. failed.push_back(args[0].Value);
  1136. }
  1137. else
  1138. {
  1139. fprintf(stderr," Passed\n");
  1140. if (output != "")
  1141. {
  1142. if (dartStuff.find(output.c_str()))
  1143. {
  1144. cmSystemTools::ReplaceString(output,
  1145. dartStuff.match(1).c_str(),"");
  1146. }
  1147. if (output != "" && m_Verbose)
  1148. {
  1149. std::cerr << output.c_str() << "\n";
  1150. }
  1151. }
  1152. passed.push_back(args[0].Value);
  1153. }
  1154. cres.m_Output = output;
  1155. cres.m_ReturnValue = retVal;
  1156. std::string nwd = cmSystemTools::GetCurrentWorkingDirectory();
  1157. if ( nwd.size() > m_ToplevelPath.size() )
  1158. {
  1159. nwd = "." + nwd.substr(m_ToplevelPath.size(), nwd.npos);
  1160. }
  1161. cres.m_Path = nwd;
  1162. cres.m_CompletionStatus = "Completed";
  1163. m_TestResults.push_back( cres );
  1164. }
  1165. }
  1166. }
  1167. }
  1168. int ctest::TestDirectory()
  1169. {
  1170. std::vector<std::string> passed;
  1171. std::vector<std::string> failed;
  1172. int total;
  1173. m_StartTest = ::CurrentTime();
  1174. this->ProcessDirectory(passed, failed);
  1175. m_EndTest = ::CurrentTime();
  1176. total = int(passed.size()) + int(failed.size());
  1177. if (total == 0)
  1178. {
  1179. std::cerr << "No tests were found!!!\n";
  1180. }
  1181. else
  1182. {
  1183. if (passed.size() && (m_UseIncludeRegExp || m_UseExcludeRegExp))
  1184. {
  1185. std::cerr << "\nThe following tests passed:\n";
  1186. for(std::vector<std::string>::iterator j = passed.begin();
  1187. j != passed.end(); ++j)
  1188. {
  1189. std::cerr << "\t" << *j << "\n";
  1190. }
  1191. }
  1192. float percent = float(passed.size()) * 100.0f / total;
  1193. fprintf(stderr,"\n%.0f%% tests passed, %i tests failed out of %i\n",
  1194. percent, int(failed.size()), total);
  1195. if (failed.size())
  1196. {
  1197. std::cerr << "\nThe following tests FAILED:\n";
  1198. for(std::vector<std::string>::iterator j = failed.begin();
  1199. j != failed.end(); ++j)
  1200. {
  1201. std::cerr << "\t" << *j << "\n";
  1202. }
  1203. }
  1204. }
  1205. if ( m_DartMode )
  1206. {
  1207. std::ofstream ofs;
  1208. if( !this->OpenOutputFile("", "Test.xml", ofs) )
  1209. {
  1210. std::cerr << "Cannot create testing XML file" << std::endl;
  1211. return 1;
  1212. }
  1213. this->GenerateDartOutput(ofs);
  1214. }
  1215. return int(failed.size());
  1216. }
  1217. void ctest::GenerateDartOutput(std::ostream& os)
  1218. {
  1219. if ( !m_DartMode )
  1220. {
  1221. return;
  1222. }
  1223. if ( m_TestResults.size() == 0 )
  1224. {
  1225. return;
  1226. }
  1227. os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  1228. << "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
  1229. << "\" BuildStamp=\"" << m_CurrentTag << "-Experimental\" Name=\""
  1230. << m_DartConfiguration["Site"] << "\">\n"
  1231. << "<Testing>\n"
  1232. << "\t<StartDateTime>" << m_StartTest << "</StartDateTime>\n"
  1233. << "\t<TestList>\n";
  1234. tm_TestResultsVector::size_type cc;
  1235. for ( cc = 0; cc < m_TestResults.size(); cc ++ )
  1236. {
  1237. cmCTestTestResult *result = &m_TestResults[cc];
  1238. os << "\t\t<Test>" << this->MakeXMLSafe(result->m_Path)
  1239. << "/" << this->MakeXMLSafe(result->m_Name)
  1240. << "</Test>" << std::endl;
  1241. }
  1242. os << "\t</TestList>\n";
  1243. for ( cc = 0; cc < m_TestResults.size(); cc ++ )
  1244. {
  1245. cmCTestTestResult *result = &m_TestResults[cc];
  1246. os << "\t<Test Status=\"" << (result->m_ReturnValue?"failed":"passed")
  1247. << "\">\n"
  1248. << "\t\t<Name>" << this->MakeXMLSafe(result->m_Name) << "</Name>\n"
  1249. << "\t\t<Path>" << this->MakeXMLSafe(result->m_Path) << "</Path>\n"
  1250. << "\t\t<FullName>" << this->MakeXMLSafe(result->m_Path)
  1251. << "/" << this->MakeXMLSafe(result->m_Name) << "</FullName>\n"
  1252. << "\t\t<FullCommandLine>"
  1253. << this->MakeXMLSafe(result->m_FullCommandLine)
  1254. << "</FullCommandLine>\n"
  1255. << "\t\t<Results>" << std::endl;
  1256. if ( result->m_ReturnValue )
  1257. {
  1258. os << "\t\t\t<NamedMeasurement type=\"text/string\" name=\"Exit Code\"><Value>"
  1259. << "CHILDSTATUS" << "</Value></NamedMeasurement>\n"
  1260. << "\t\t\t<NamedMeasurement type=\"text/string\" name=\"Exit Value\"><Value>"
  1261. << result->m_ReturnValue << "</Value></NamedMeasurement>" << std::endl;
  1262. }
  1263. os << "\t\t\t<NamedMeasurement type=\"numeric/double\" "
  1264. << "name=\"Execution Time\"><Value>"
  1265. << result->m_ExecutionTime << "</Value></NamedMeasurement>\n"
  1266. << "\t\t\t<NamedMeasurement type=\"text/string\" "
  1267. << "name=\"Completion Status\"><Value>"
  1268. << result->m_CompletionStatus << "</Value></NamedMeasurement>\n"
  1269. << "\t\t\t<Measurement>\n"
  1270. << "\t\t\t\t<Value>" << this->MakeXMLSafe(result->m_Output)
  1271. << "</Value>\n"
  1272. << "\t\t\t</Measurement>\n"
  1273. << "\t\t</Results>\n"
  1274. << "\t</Test>" << std::endl;
  1275. }
  1276. os << "\t<EndDateTime>" << m_EndTest << "</EndDateTime>\n"
  1277. << "</Testing>\n"
  1278. << "</Site>" << std::endl;
  1279. }
  1280. int ctest::ProcessTests()
  1281. {
  1282. int res = 0;
  1283. bool notest = true;
  1284. int cc;
  1285. for ( cc = 0; cc < LAST_TEST; cc ++ )
  1286. {
  1287. if ( m_Tests[cc] )
  1288. {
  1289. notest = false;
  1290. break;
  1291. }
  1292. }
  1293. if ( m_Tests[UPDATE_TEST] || m_Tests[ALL_TEST] )
  1294. {
  1295. res += this->UpdateDirectory();
  1296. }
  1297. if ( m_Tests[CONFIGURE_TEST] || m_Tests[ALL_TEST] )
  1298. {
  1299. res += this->ConfigureDirectory();
  1300. }
  1301. if ( m_Tests[BUILD_TEST] || m_Tests[ALL_TEST] )
  1302. {
  1303. res += this->BuildDirectory();
  1304. }
  1305. if ( m_Tests[TEST_TEST] || m_Tests[ALL_TEST] || notest )
  1306. {
  1307. res += this->TestDirectory();
  1308. }
  1309. if ( m_Tests[COVERAGE_TEST] || m_Tests[ALL_TEST] )
  1310. {
  1311. this->CoverageDirectory();
  1312. }
  1313. if ( m_Tests[PURIFY_TEST] || m_Tests[ALL_TEST] )
  1314. {
  1315. std::cerr << "Purify test is not yet implemented" << std::endl;
  1316. }
  1317. return res;
  1318. }
  1319. // this is a test driver program for cmake.
  1320. int main (int argc, char *argv[])
  1321. {
  1322. cmSystemTools::EnableMSVCDebugHook();
  1323. ctest inst;
  1324. // look at the args
  1325. std::vector<std::string> args;
  1326. for(int i =0; i < argc; ++i)
  1327. {
  1328. args.push_back(argv[i]);
  1329. }
  1330. #ifdef _WIN32
  1331. std::string comspec = "cmw9xcom.exe";
  1332. cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
  1333. #endif
  1334. for(unsigned int i=1; i < args.size(); ++i)
  1335. {
  1336. std::string arg = args[i];
  1337. if(arg.find("-D",0) == 0 && i < args.size() - 1)
  1338. {
  1339. inst.m_ConfigType = args[i+1];
  1340. }
  1341. if( arg.find("-V",0) == 0 || arg.find("--verbose",0) == 0 )
  1342. {
  1343. inst.m_Verbose = true;
  1344. }
  1345. if( ( arg.find("-T",0) == 0 || arg.find("--dart-mode",0) == 0 ) && (i < args.size() -1) )
  1346. {
  1347. inst.m_DartMode = true;
  1348. inst.SetTest(args[i+1].c_str());
  1349. }
  1350. if(arg.find("-R",0) == 0 && i < args.size() - 1)
  1351. {
  1352. inst.m_UseIncludeRegExp = true;
  1353. inst.m_IncludeRegExp = args[i+1];
  1354. }
  1355. if(arg.find("-E",0) == 0 && i < args.size() - 1)
  1356. {
  1357. inst.m_UseExcludeRegExp = true;
  1358. inst.m_ExcludeRegExp = args[i+1];
  1359. inst.m_UseExcludeRegExpFirst = inst.m_UseIncludeRegExp ? false : true;
  1360. }
  1361. if(arg.find("-h") == 0 ||
  1362. arg.find("-help") == 0 ||
  1363. arg.find("-H") == 0 ||
  1364. arg.find("--help") == 0 ||
  1365. arg.find("/H") == 0 ||
  1366. arg.find("/HELP") == 0 ||
  1367. arg.find("/?") == 0)
  1368. {
  1369. std::cerr << "Usage: " << argv[0] << " <options>" << std::endl
  1370. << "\t -D type Specify config type" << std::endl
  1371. << "\t -E test Specify regular expression for tests to exclude"
  1372. << std::endl
  1373. << "\t -R test Specify regular expression for tests to include"
  1374. << std::endl
  1375. << "\t -V Verbose testing" << std::endl
  1376. << "\t -H Help page" << std::endl;
  1377. return 1;
  1378. }
  1379. }
  1380. // call process directory
  1381. inst.Initialize();
  1382. int res = inst.ProcessTests();
  1383. inst.Finalize();
  1384. return res;
  1385. }