dbdigest.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. {
  2. This file is part of the Free Pascal test suite.
  3. Copyright (c) 2002 by the Free Pascal development team.
  4. This program generates a digest
  5. of the last tests run.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. {$h+}
  14. program digest;
  15. uses
  16. sysutils,teststr,testu,tresults,dbtests;
  17. Var
  18. StatusCount : Array[TTestStatus] of Integer;
  19. UnknownLines : integer;
  20. Procedure ExtractTestFileName(Var Line : string);
  21. Var I : integer;
  22. begin
  23. I:=Pos(' ',Line);
  24. If (I<>0) then
  25. Line:=Copy(Line,1,I-1);
  26. end;
  27. Function Analyse(Var Line : string; Var Status : TTestStatus) : Boolean;
  28. Var
  29. TS : TTestStatus;
  30. begin
  31. Result:=False;
  32. For TS:=FirstStatus to LastStatus do
  33. begin
  34. Result:=Pos(StatusText[TS],Line)=1;
  35. If Result then
  36. begin
  37. Status:=TS;
  38. Delete(Line,1,Length(StatusText[TS]));
  39. ExtractTestFileName(Line);
  40. Break;
  41. end;
  42. end;
  43. end;
  44. Type
  45. TConfigOpt = (
  46. coDatabaseName,
  47. soHost,
  48. coUserName,
  49. coPassword,
  50. coPort,
  51. coLogFile,
  52. coOS,
  53. coCPU,
  54. coCategory,
  55. coVersion,
  56. coDate,
  57. coSubmitter,
  58. coMachine,
  59. coComment,
  60. coTestSrcDir,
  61. coRelSrcDir,
  62. coVerbose
  63. );
  64. { Additional options only for dbdigest.cfg file }
  65. TConfigAddOpt = (
  66. coCompilerDate,
  67. coCompilerFullVersion,
  68. coSvnCompilerRevision,
  69. coSvnTestsRevision,
  70. coSvnRTLRevision,
  71. coSvnPackagesRevision
  72. );
  73. Const
  74. ConfigStrings : Array [TConfigOpt] of string = (
  75. 'databasename',
  76. 'host',
  77. 'username',
  78. 'password',
  79. 'port',
  80. 'logfile',
  81. 'os',
  82. 'cpu',
  83. 'category',
  84. 'version',
  85. 'date',
  86. 'submitter',
  87. 'machine',
  88. 'comment',
  89. 'testsrcdir',
  90. 'relsrcdir',
  91. 'verbose'
  92. );
  93. ConfigAddStrings : Array [TConfigAddOpt] of string = (
  94. 'compilerdate',
  95. 'compilerfullversion',
  96. 'svncompilerrevision',
  97. 'svntestsrevision',
  98. 'svnrtlrevision',
  99. 'svnpackagesrevision'
  100. );
  101. ConfigAddCols : Array [TConfigAddOpt] of string = (
  102. 'TU_COMPILERDATE',
  103. 'TU_COMPILERFULLVERSION',
  104. 'TU_SVNCOMPILERREVISION',
  105. 'TU_SVNTESTSREVISION',
  106. 'TU_SVNRTLREVISION',
  107. 'TU_SVNPACKAGESREVISION'
  108. );
  109. ConfigOpts : Array[TConfigOpt] of char
  110. = ('d','h','u','p','P','l','o','c','a','v','t','s','m','C','S','r','V');
  111. Var
  112. TestOS,
  113. TestCPU,
  114. TestVersion,
  115. TestCategory,
  116. DatabaseName,
  117. HostName,
  118. UserName,
  119. Password,
  120. Port,
  121. LogFileName,
  122. Submitter,
  123. Machine,
  124. Comment : String;
  125. TestDate : TDateTime;
  126. TestCompilerDate,
  127. TestCompilerFullVersion,
  128. TestSvnCompilerRevision,
  129. TestSvnTestsRevision,
  130. TestSvnRTLRevision,
  131. TestSvnPackagesRevision : String;
  132. Procedure SetAddOpt (O : TConfigAddOpt; Value : string);
  133. begin
  134. Case O of
  135. coCompilerDate:
  136. TestCompilerDate:=Value;
  137. coCompilerFullVersion:
  138. TestCompilerFullVersion:=Value;
  139. coSvnCompilerRevision:
  140. TestSvnCompilerRevision:=Value;
  141. coSvnTestsRevision:
  142. TestSvnTestsRevision:=Value;
  143. coSvnRTLRevision:
  144. TestSvnRTLRevision:=Value;
  145. coSvnPackagesRevision:
  146. TestSvnPackagesRevision:=Value;
  147. end;
  148. end;
  149. Procedure SetOpt (O : TConfigOpt; Value : string);
  150. var
  151. year,month,day,min,hour : word;
  152. begin
  153. Case O of
  154. coDatabaseName : DatabaseName:=Value;
  155. soHost : HostName:=Value;
  156. coUserName : UserName:=Value;
  157. coPassword : Password:=Value;
  158. coPort : Port:=Value;
  159. coLogFile : LogFileName:=Value;
  160. coOS : TestOS:=Value;
  161. coCPU : TestCPU:=Value;
  162. coCategory : TestCategory:=Value;
  163. coVersion : TestVersion:=Value;
  164. coDate :
  165. begin
  166. { Formated like YYYYMMDDhhmm }
  167. if Length(value)=12 then
  168. begin
  169. year:=StrToInt(Copy(value,1,4));
  170. month:=StrToInt(Copy(value,5,2));
  171. day:=StrToInt(Copy(Value,7,2));
  172. hour:=StrToInt(Copy(Value,9,2));
  173. min:=StrToInt(Copy(Value,11,2));
  174. TestDate:=EncodeDate(year,month,day)+EncodeTime(hour,min,0,0);
  175. end
  176. else
  177. Verbose(V_Error,'Error in date format, use YYYYMMDDhhmm');
  178. end;
  179. coSubmitter : Submitter:=Value;
  180. coMachine : Machine:=Value;
  181. coComment : Comment:=Value;
  182. coVerbose : DoVerbose:=true;
  183. coTestSrcDir :
  184. begin
  185. TestSrcDir:=Value;
  186. if (TestSrcDir<>'') and (TestSrcDir[length(TestSrcDir)]<>'/') then
  187. TestSrcDir:=TestSrcDir+'/';
  188. end;
  189. coRelSrcDir :
  190. begin
  191. RelSrcDir:=Value;
  192. if (RelSrcDir<>'') and (RelSrcDir[length(RelSrcDir)]<>'/') then
  193. RelSrcDir:=RelSrcDir+'/';
  194. if (RelSrcDir<>'') and (RelSrcDir[1]='/') then
  195. RelSrcDir:=copy(RelSrcDir,2,length(RelSrcDir)-1);
  196. end;
  197. end;
  198. end;
  199. Function ProcessOption(S: String) : Boolean;
  200. Var
  201. N : String;
  202. I : Integer;
  203. co : TConfigOpt;
  204. coa : TConfigAddOpt;
  205. begin
  206. Verbose(V_DEBUG,'Processing option: '+S);
  207. I:=Pos('=',S);
  208. Result:=(I<>0);
  209. If Result then
  210. begin
  211. N:=Copy(S,1,I-1);
  212. Delete(S,1,I);
  213. For co:=low(TConfigOpt) to high(TConfigOpt) do
  214. begin
  215. Result:=CompareText(ConfigStrings[co],N)=0;
  216. If Result then
  217. begin
  218. SetOpt(co,S);
  219. Exit;
  220. end;
  221. end;
  222. For coa:=low(TConfigAddOpt) to high(TConfigAddOpt) do
  223. begin
  224. Result:=CompareText(ConfigAddStrings[coa],N)=0;
  225. If Result then
  226. begin
  227. SetAddOpt(coa,S);
  228. Exit;
  229. end;
  230. end;
  231. end;
  232. Verbose(V_ERROR,'Unknown option : '+n+S);
  233. end;
  234. Procedure ProcessConfigfile(FN : String);
  235. Var
  236. F : Text;
  237. S : String;
  238. I : Integer;
  239. begin
  240. // Set the default value for old digests without RelSrcDir to the rtl/compiler
  241. // testsuite
  242. RelSrcDir:='tests/';
  243. If Not FileExists(FN) Then
  244. Exit;
  245. Verbose(V_DEBUG,'Parsing config file: '+FN);
  246. Assign(F,FN);
  247. {$i-}
  248. Reset(F);
  249. If IOResult<>0 then
  250. Exit;
  251. {$I+}
  252. While not(EOF(F)) do
  253. begin
  254. ReadLn(F,S);
  255. S:=trim(S);
  256. I:=Pos('#',S);
  257. If I<>0 then
  258. S:=Copy(S,1,I-1);
  259. If (S<>'') then
  260. ProcessOption(S);
  261. end;
  262. Close(F);
  263. end;
  264. Procedure ProcessCommandLine;
  265. Var
  266. I : Integer;
  267. O : String;
  268. c,co : TConfigOpt;
  269. Found : Boolean;
  270. begin
  271. I:=1;
  272. While I<=ParamCount do
  273. begin
  274. O:=Paramstr(I);
  275. Found:=Length(O)=2;
  276. If Found then
  277. For co:=low(TConfigOpt) to high(TConfigOpt) do
  278. begin
  279. Found:=(O[2]=ConfigOpts[co]);
  280. If Found then
  281. begin
  282. c:=co;
  283. Break;
  284. end;
  285. end;
  286. If Not Found then
  287. Verbose(V_ERROR,'Illegal command-line option : '+O)
  288. else
  289. begin
  290. Found:=(I<ParamCount);
  291. If Not found then
  292. Verbose(V_ERROR,'Option requires argument : '+O)
  293. else
  294. begin
  295. inc(I);
  296. O:=Paramstr(I);
  297. SetOpt(c,o);
  298. end;
  299. end;
  300. Inc(I);
  301. end;
  302. end;
  303. Var
  304. TestCPUID : Integer;
  305. TestOSID : Integer;
  306. TestVersionID : Integer;
  307. TestCategoryID : Integer;
  308. TestRunID : Integer;
  309. Procedure GetIDs;
  310. begin
  311. TestCPUID := GetCPUId(TestCPU);
  312. If TestCPUID=-1 then
  313. Verbose(V_Error,'NO ID for CPU "'+TestCPU+'" found.');
  314. TestOSID := GetOSID(TestOS);
  315. If TestOSID=-1 then
  316. Verbose(V_Error,'NO ID for OS "'+TestOS+'" found.');
  317. TestCategoryID := GetCategoryID(TestCategory);
  318. If TestCategoryID=-1 then
  319. begin
  320. // Verbose(V_Error,'NO ID for Category "'+TestCategory+'" found.');
  321. TestCategoryID:=1;
  322. end;
  323. TestVersionID := GetVersionID(TestVersion);
  324. If TestVersionID=-1 then
  325. Verbose(V_Error,'NO ID for version "'+TestVersion+'" found.');
  326. If (Round(TestDate)=0) then
  327. Testdate:=Now;
  328. TestRunID:=GetRunID(TestOSID,TestCPUID,TestVersionID,TestDate);
  329. If (TestRunID=-1) then
  330. begin
  331. TestRunID:=AddRun(TestOSID,TestCPUID,TestVersionID,TestCategoryID,TestDate);
  332. If TestRUnID=-1 then
  333. Verbose(V_Error,'Could not insert new testrun record!');
  334. end
  335. else
  336. CleanTestRun(TestRunID);
  337. end;
  338. Function GetLog(FN : String) : String;
  339. begin
  340. FN:=ChangeFileExt(FN,'.log');
  341. If FileExists(FN) then
  342. Result:=GetFileContents(FN)
  343. else
  344. Result:='';
  345. end;
  346. Function GetExecuteLog(FN : String) : String;
  347. begin
  348. FN:=ChangeFileExt(FN,'.elg');
  349. If FileExists(FN) then
  350. Result:=GetFileContents(FN)
  351. else
  352. Result:='';
  353. end;
  354. Procedure Processfile (FN: String);
  355. var
  356. logfile : text;
  357. line,prevLine : string;
  358. TS,PrevTS : TTestStatus;
  359. ID,PrevID : integer;
  360. Testlog : string;
  361. is_new : boolean;
  362. begin
  363. Assign(logfile,FN);
  364. PrevId:=-1;
  365. PrevLine:='';
  366. is_new:=false;
  367. PrevTS:=low(TTestStatus);
  368. {$i-}
  369. reset(logfile);
  370. if ioresult<>0 then
  371. Verbose(V_Error,'Unable to open log file'+logfilename);
  372. {$i+}
  373. while not eof(logfile) do
  374. begin
  375. readln(logfile,line);
  376. If analyse(line,TS) then
  377. begin
  378. Verbose(V_NORMAL,'Analysing result for test '+Line);
  379. If Not ExpectRun[TS] then
  380. begin
  381. ID:=RequireTestID(Line);
  382. if (PrevID<>-1) and (PrevID<>ID) then
  383. begin
  384. { This can only happen if a Successfully compiled message
  385. is not followed by any other line about the same test }
  386. TestLog:='';
  387. AddTestResult(PrevID,TestRunId,ord(PrevTS),
  388. TestOK[PrevTS],TestSkipped[PrevTS],TestLog,is_new);
  389. Verbose(V_Warning,'Orphaned test: "'+prevline+'"');
  390. end;
  391. PrevID:=-1;
  392. If (ID<>-1) then
  393. begin
  394. If Not (TestOK[TS] or TestSkipped[TS]) then
  395. begin
  396. TestLog:=GetExecuteLog(Line);
  397. if pos(failed_to_compile,TestLog)=1 then
  398. TestLog:=GetLog(Line);
  399. end
  400. else
  401. TestLog:='';
  402. { AddTestResult can fail for test that contain %recompile
  403. as the same }
  404. if AddTestResult(ID,TestRunID,Ord(TS),TestOK[TS],
  405. TestSkipped[TS],TestLog,is_new) <> -1 then
  406. begin
  407. if is_new then
  408. Inc(StatusCount[TS])
  409. else
  410. Verbose(V_Debug,'Test: "'+line+'" was updated');
  411. end
  412. else
  413. begin
  414. Verbose(V_Warning,'Test: "'+line+'" already registered');
  415. end;
  416. end;
  417. end
  418. else
  419. begin
  420. Inc(StatusCount[TS]);
  421. PrevTS:=TS;
  422. PrevID:=RequireTestID(line);
  423. PrevLine:=line;
  424. end;
  425. end
  426. else
  427. begin
  428. Inc(UnknownLines);
  429. Verbose(V_Warning,'Unknown line: "'+line+'"');
  430. end;
  431. end;
  432. close(logfile);
  433. end;
  434. procedure UpdateTestRun;
  435. var
  436. i : TTestStatus;
  437. qry : string;
  438. res : TQueryResult;
  439. begin
  440. qry:='UPDATE TESTRUN SET ';
  441. for i:=low(TTestStatus) to high(TTestStatus) do
  442. qry:=qry+format('%s=%d, ',[SQLField[i],StatusCount[i]]);
  443. if TestCompilerDate<>'' then
  444. qry:=qry+format('%s="%s", ',[ConfigAddCols[coCompilerDate],EscapeSQL(TestCompilerDate)]);
  445. if TestCompilerFullVersion<>'' then
  446. qry:=qry+format('%s="%s", ',[ConfigAddCols[coCompilerFullVersion],EscapeSQL(TestCompilerFullVersion)]);
  447. if TestSvnCompilerRevision<>'' then
  448. qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnCompilerRevision],EscapeSQL(TestSvnCompilerRevision)]);
  449. if TestSvnTestsRevision<>'' then
  450. qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnTestsRevision],EscapeSQL(TestSvnTestsRevision)]);
  451. if TestSvnRTLRevision<>'' then
  452. qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnRTLRevision],EscapeSQL(TestSvnRTLRevision)]);
  453. if TestSvnPackagesRevision<>'' then
  454. qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnPackagesRevision],EscapeSQL(TestSvnPackagesRevision)]);
  455. qry:=qry+format('TU_SUBMITTER="%s", TU_MACHINE="%s", TU_COMMENT="%s", TU_DATE="%s"',[Submitter,Machine,Comment,SqlDate(TestDate)]);
  456. qry:=qry+' WHERE TU_ID='+format('%d',[TestRunID]);
  457. RunQuery(Qry,res)
  458. end;
  459. begin
  460. ProcessConfigFile('dbdigest.cfg');
  461. ProcessCommandLine;
  462. If LogFileName<>'' then
  463. begin
  464. ConnectToDatabase(DatabaseName,HostName,UserName,Password,Port);
  465. GetIDs;
  466. ProcessFile(LogFileName);
  467. UpdateTestRun;
  468. end
  469. else
  470. Verbose(V_ERROR,'Missing log file name');
  471. end.