utests.pp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. {$mode objfpc}
  2. {$h+}
  3. unit utests;
  4. interface
  5. uses cgiapp,sysutils,mysqlDB4,whtml,dbwhtml,db,
  6. Classes,ftFont,fpimage,fpimgcanv,fpWritePng,fpcanvas;
  7. {$ifndef TEST}
  8. const
  9. CGI = 'testsuite.cgi';
  10. {$else TEST}
  11. const
  12. CGI = 'testsuite-new.cgi';
  13. {$endif TEST}
  14. Type
  15. TTestSuite = Class(TCgiApplication)
  16. Private
  17. FHTMLWriter : THtmlWriter;
  18. FComboBoxProducer : TComboBoxProducer;
  19. FDB : TMySQLDatabase;
  20. FRunID,
  21. FCompareRunID,
  22. FTestFileID,
  23. FVersion,
  24. FCPU,
  25. FOS : String;
  26. FDate : TDateTime;
  27. FDebug,
  28. FNoSkipped,
  29. FOnlyFailed : Boolean;
  30. FRunSkipCount,
  31. FRunFailedCount,
  32. FRunCount : Integer;
  33. FAction : Integer;
  34. FTestLastDays : Integer;
  35. Procedure GetOverviewRowAttr(Sender : TObject; Var BGColor : String;
  36. Var Align : THTMLAlign; Var VAlign : THTMLValign;
  37. Var CustomAttr : String) ;
  38. Procedure GetRunRowAttr(Sender : TObject; Var BGColor : String;
  39. Var Align : THTMLAlign; Var VAlign : THTMLValign;
  40. Var CustomAttr : String) ;
  41. Procedure FormatFailedOverview(Sender : TObject; Var CellData : String);
  42. Procedure FormatFileDetails(Sender: TObject; var CellData: String);
  43. Procedure DoDrawPie(Img : TFPCustomImage; Skipped,Failed,Total : Integer);
  44. Public
  45. Function CreateDataset(Qry : String) : TMySQLDataset;
  46. Function CreateTableProducer(DS : TDataset) :TTableProducer;
  47. Procedure DefaultTableFromQuery(Qry,ALink : String; IncludeRecordCount : Boolean);
  48. Procedure ComboBoxFromQuery(Const ComboName,Qry : String);
  49. Procedure ComboBoxFromQuery(Const ComboName,Qry,Value : String);
  50. Function GetSingleTon(Const Qry : String) : String;
  51. Function GetOSName(ID : String) : String;
  52. Function GetCPUName(ID : String) : String;
  53. Function GetVersionName(ID : String) : String;
  54. Function GetTestFileName(ID : String) : String;
  55. Function InitCGIVars : Integer;
  56. Procedure DoRun; override;
  57. Procedure EmitOverviewForm;
  58. Procedure ShowRunResults;
  59. Procedure ShowRunComparison;
  60. Procedure ShowOneTest;
  61. Function ConnectToDB : Boolean;
  62. procedure DisconnectFromDB;
  63. Procedure EmitTitle(ATitle : String);
  64. Procedure ShowRunOverview;
  65. Procedure CreateRunPie;
  66. Function ShowRunData : Boolean;
  67. end;
  68. implementation
  69. Const
  70. {$i utests.cfg}
  71. { if utests.cfg is missed, create one with the following contents:
  72. DefDatabase = 'TESTSUITE';
  73. DefHost = '';
  74. DefDBUser = ''; // fill this in when compiling.
  75. DefPassword = ''; // fill this in, too.
  76. }
  77. Const
  78. SDetailsURL = CGI + '?action=1&run1id=%s';
  79. Procedure TTestSuite.DoRun;
  80. begin
  81. Try
  82. Try
  83. Case InitCGIVars of
  84. 0 : EmitOverviewForm;
  85. 1 :
  86. if Length(FCompareRunID) = 0 then
  87. ShowRunResults
  88. else
  89. ShowRunComparison;
  90. 2 : CreateRunPie;
  91. 3 : ShowOneTest;
  92. end;
  93. finally
  94. DisConnectFromDB;
  95. end;
  96. Finally
  97. Terminate;
  98. end;
  99. end;
  100. Function TTestSuite.InitCGIVars : Integer;
  101. Var
  102. S : String;
  103. begin
  104. FHtmlWriter:=THTMLWriter.Create(Response);
  105. FComboBoxProducer:=TComboBoxProducer.Create(Self);
  106. DateSeparator:='/';
  107. Result:=0;
  108. S:=RequestVariables['action'];
  109. if Length(S) = 0 then
  110. S:=RequestVariables['TESTACTION'];
  111. FAction:=StrToIntDef(S,0);
  112. FVersion:=RequestVariables['version'];
  113. if Length(FVersion) = 0 then
  114. FVersion:=RequestVariables['TESTVERSION'];
  115. FOS:=RequestVariables['os'];
  116. if Length(FOS) = 0 then
  117. FOS:=RequestVariables['TESTOS'];
  118. FCPU:=RequestVariables['cpu'];
  119. if Length(FCPU) = 0 then
  120. FCPU:=RequestVariables['TESTCPU'];
  121. FRunID:=RequestVariables['run1id'];
  122. if Length(FRunID) = 0 then
  123. FRunID:=RequestVariables['TESTRUN'];
  124. S:=RequestVariables['lastdays'];
  125. if Length(S) = 0 then
  126. S:=RequestVariables['TESTLASTDAYS'];
  127. FTestLastDays:=StrToIntDef(S,31);
  128. S:=RequestVariables['date'];
  129. if Length(S) = 0 then
  130. S:=RequestVariables['TESTDATE'];
  131. if Length(S) > 0 then
  132. try
  133. FDate:=StrToDate(S);
  134. except
  135. FDate:=0;
  136. end;
  137. S:=RequestVariables['failedonly'];
  138. if Length(S) = 0 then
  139. S:=RequestVariables['TESTFAILEDONLY'];
  140. FOnlyFailed:=(S='1');
  141. S:=RequestVariables['noskipped'];
  142. if Length(S) = 0 then
  143. S:=RequestVariables['TESTNOSKIPPED'];
  144. FNoSkipped:=(S='1');
  145. FCompareRunID:=RequestVariables['run2id'];
  146. FTestFileID:=RequestVariables['testfileid'];
  147. FRunCount:=StrToIntDef(RequestVariables['PIETOTAL'],0);
  148. FRunSkipCount:=StrToIntDef(RequestVariables['PIESKIPPED'],0);
  149. FRunFailedCount:=StrToIntDef(RequestVariables['PIEFAILED'],0);
  150. S:=RequestVariables['DEBUGCGI'];
  151. FDebug:=(S='1');
  152. Result:=FAction;
  153. end;
  154. Function TTestSuite.ConnectToDB : Boolean;
  155. begin
  156. Result:=False;
  157. FDB:=TMySQLDatabase.Create(Self);
  158. FDB.HostName:=DefHost;
  159. FDB.DatabaseName:=DefDatabase;
  160. FDB.UserName:=DefDBUser;
  161. FDB.Password:=DefPassword;
  162. FDB.Connected:=True;
  163. Result:=True;
  164. end;
  165. procedure TTestSuite.DisconnectFromDB;
  166. begin
  167. If Assigned(FDB) then
  168. begin
  169. if (FDB.Connected) then
  170. FDB.Connected:=False;
  171. FreeAndNil(FDB);
  172. end;
  173. end;
  174. Procedure TTestSuite.ComboBoxFromQuery(Const ComboName,Qry: String);
  175. begin
  176. ComboBoxFromQuery(ComboName,Qry,'')
  177. end;
  178. Procedure TTestSuite.ComboBoxFromQuery(Const ComboName,Qry,Value : String);
  179. Var
  180. Q : TMySQLDataset;
  181. begin
  182. Q:=TMySQLDataset.Create(Self);
  183. try
  184. Q.Database:=FDB;
  185. Q.SQL.Text:=Qry;
  186. Q.Open;
  187. FComboboxProducer.Dataset:=Q;
  188. FComboBoxProducer.ValueField:=Q.Fields[0].FieldName;
  189. FComboBoxProducer.DataField:=Q.Fields[1].FieldName;
  190. FComboBoxProducer.Value:=Value;
  191. FComboBoxProducer.InputName:=ComboName;
  192. FComboBoxProducer.CreateComboBox(Response);
  193. Finally
  194. Q.Free;
  195. end;
  196. end;
  197. Function TTestSuite.GetSingleton(Const Qry : String) : String;
  198. Var
  199. Q : TMySQLDataset;
  200. begin
  201. Result:='';
  202. Q:=TMySQLDataset.Create(Self);
  203. try
  204. Q.Database:=FDB;
  205. Q.SQL.Text:=Qry;
  206. Q.Open;
  207. Try
  208. If Not (Q.EOF and Q.BOF) then
  209. Result:=Q.Fields[0].AsString;
  210. Finally
  211. Q.Close;
  212. end;
  213. finally
  214. Q.Free;
  215. end;
  216. end;
  217. Procedure TTestSuite.EmitTitle(ATitle : String);
  218. begin
  219. AddResponseLn('<HTML>');
  220. AddResponseLn('<TITLE>'+ATitle+'</TITLE>');
  221. AddResponseLn('<BODY>');
  222. end;
  223. Procedure TTestSuite.EmitOverviewForm;
  224. begin
  225. ConnectToDB;
  226. ContentType:='text/html';
  227. EmitContentType;
  228. EmitTitle(Title);
  229. With FHTMLWriter do
  230. begin
  231. HeaderStart(1);
  232. Write('View Test suite results');
  233. HeaderEnd(1);
  234. Write('Please specify search criteria:');
  235. ParagraphStart;
  236. FormStart(CGI,'');
  237. TableStart(2,true);
  238. RowStart;
  239. CellStart;
  240. Write('Operating system:');
  241. CellNext;
  242. ComboBoxFromQuery('os','SELECT TO_ID,TO_NAME FROM TESTOS ORDER BY TO_NAME',FOS);
  243. CellEnd;
  244. RowNext;
  245. CellStart;
  246. Write('Processor:');
  247. CellNext;
  248. ComboBoxFromQuery('cpu','SELECT TC_ID,TC_NAME FROM TESTCPU ORDER BY TC_NAME',FCPU);
  249. CellEnd;
  250. RowNext;
  251. CellStart;
  252. Write('Version');
  253. CellNext;
  254. ComboBoxFromQuery('version','SELECT TV_ID,TV_VERSION FROM TESTVERSION ORDER BY TV_VERSION DESC',FVERSION);
  255. CellEnd;
  256. RowNext;
  257. CellStart;
  258. Write('Date');
  259. CellNext;
  260. If (FDate=0) then
  261. EmitInput('date','')
  262. else
  263. EmitInput('date',DateToStr(FDate));
  264. CellEnd;
  265. RowNext;
  266. CellStart;
  267. Write('Only failed tests');
  268. CellNext;
  269. EmitCheckBox('failedonly','1',FonlyFailed);
  270. CellEnd;
  271. RowNext;
  272. CellStart;
  273. Write('Hide skipped tests');
  274. CellNext;
  275. EmitCheckBox('noskipped','1',FNoSkipped);
  276. CellEnd;
  277. RowEnd;
  278. TableEnd;
  279. ParaGraphStart;
  280. EmitSubmitButton('','Search');
  281. EmitResetButton('','Reset form');
  282. FormEnd;
  283. end;
  284. ShowRunOverview;
  285. AddResponseLn('</BODY>');
  286. AddResponseLn('</HTML>');
  287. end;
  288. procedure TTestSuite.GetOverviewRowAttr(Sender: TObject; var BGColor: String;
  289. var Align: THTMLAlign; var VAlign: THTMLValign; var CustomAttr: String);
  290. begin
  291. If ((Sender as TTAbleProducer).CurrentRow mod 2=0) then
  292. BGColor:='#EEEEEE'
  293. end;
  294. Function TTestSuite.CreateDataset(Qry : String) : TMySQLDataset;
  295. begin
  296. Result:=TMySQLdataset.Create(Self);
  297. With Result do
  298. begin
  299. Database:=FDB;
  300. SQL.Text:=Qry;
  301. end;
  302. end;
  303. Function TTestSuite.CreateTableProducer(DS : TDataset) :TTableProducer;
  304. begin
  305. Result:=TTableProducer.Create(Self);
  306. Result.Dataset:=DS;
  307. end;
  308. Procedure TTestSuite.DefaultTableFromQuery(Qry,Alink : String; IncludeRecordCount : Boolean);
  309. Var
  310. Q : TMySQLDataset;
  311. begin
  312. If FDebug then
  313. Writeln('Query : '+Qry);
  314. Q:=CreateDataset(Qry);
  315. With Q do
  316. try
  317. Open;
  318. Try
  319. With CreateTableProducer(Q) do
  320. Try
  321. Border:=True;
  322. If (Alink<>'') then
  323. begin
  324. CreateColumns(Nil);
  325. If TableColumns.Count>0 then
  326. (TableColumns.Items[0] as TTableColumn).ActionURL:=ALink;
  327. end;
  328. CreateTable(Response);
  329. Finally
  330. Free;
  331. end;
  332. If IncludeRecordCount then
  333. Writeln('<p>Record count: ',Q.RecordCount,'</p>');
  334. Finally
  335. Close;
  336. end;
  337. finally
  338. Free;
  339. end;
  340. end;
  341. Procedure TTestSuite.ShowRunOverview;
  342. Const
  343. SOverview = 'SELECT TU_ID as ID,TU_DATE as Date,TC_NAME as CPU,TO_NAME as OS,'+
  344. 'TV_VERSION as Version,COUNT(TR_ID) as Count,'+
  345. '(TU_SUCCESSFULLYFAILED+TU_SUCCESFULLYCOMPILED+TU_SUCCESSFULLYRUN) AS OK,'+
  346. '(TU_FAILEDTOCOMPILE+TU_FAILEDTORUN+TU_FAILEDTOFAIL) as Failed,'+
  347. '(TU_SUCCESSFULLYFAILED+TU_SUCCESFULLYCOMPILED+TU_SUCCESSFULLYRUN+'+
  348. 'TU_FAILEDTOCOMPILE+TU_FAILEDTORUN+TU_FAILEDTOFAIL) as Total,'+
  349. 'TU_SUBMITTER as Submitter, TU_MACHINE as Machine, TU_COMMENT as Comment '+
  350. 'FROM TESTRESULTS,TESTRUN,TESTCPU,TESTOS,TESTVERSION '+
  351. 'WHERE '+
  352. '(TC_ID=TU_CPU_FK) AND '+
  353. '(TO_ID=TU_OS_FK) AND '+
  354. '(TV_ID=TU_VERSION_FK) AND '+
  355. '(TR_TESTRUN_FK=TU_ID) '+
  356. '%s '+
  357. 'GROUP BY TU_ID '+
  358. 'ORDER BY TU_ID DESC LIMIT 50';
  359. Var
  360. S,A,Qry : String;
  361. Q : TMySQLDataset;
  362. begin
  363. S:='';
  364. If (FCPU<>'') and (GetCPUName(FCPU)<>'All') then
  365. S:=S+' AND (TU_CPU_FK='+FCPU+')';
  366. If (FVersion<>'') and (GetVersionName(FVersion)<>'All') then
  367. S:=S+' AND (TU_VERSION_FK='+FVERSION+')';
  368. if (FOS<>'') and (GetOSName(FOS)<>'All') then
  369. S:=S+' AND (TU_OS_FK='+FOS+')';
  370. If (Round(FDate)<>0) then
  371. S:=S+' AND (TU_DATE="'+FormatDateTime('YYYY/MM/DD',FDate)+'")';
  372. If FOnlyFailed then
  373. S:=S+' AND (TR_OK="-")';
  374. A:=SDetailsURL;
  375. If FOnlyFailed then
  376. A:=A+'&failedonly=1';
  377. If FNoSkipped then
  378. A:=A+'&noskipped=1';
  379. Qry:=Format(SOverview,[S]);
  380. If FDebug then
  381. Writeln('Query : '+Qry);
  382. Q:=CreateDataset(Qry);
  383. With Q do
  384. try
  385. Open;
  386. Try
  387. With CreateTableProducer(Q) do
  388. Try
  389. Border:=True;
  390. OnGetRowAttributes:=@GetOverViewRowAttr;
  391. CreateColumns(Nil);
  392. TableColumns.ColumnByName('ID').ActionURL:=A;
  393. TableColumns.ColumnByNAme('Failed').OnGetCellContents:=@FormatFailedOverview;
  394. CreateTable(Response);
  395. Finally
  396. Free;
  397. end;
  398. Writeln('<p>Record count: ',Q.RecordCount,'</p>');
  399. Finally
  400. Close;
  401. end;
  402. finally
  403. Free;
  404. end;
  405. end;
  406. Function TTestSuite.GetOSName(ID : String) : String;
  407. begin
  408. if (ID<>'') then
  409. Result:=GetSingleTon('SELECT TO_NAME FROM TESTOS WHERE TO_ID='+ID);
  410. end;
  411. Function TTestSuite.GetTestFileName(ID : String) : String;
  412. begin
  413. if (ID<>'') then
  414. Result:=GetSingleTon('SELECT T_NAME FROM TESTS WHERE T_ID='+ID);
  415. end;
  416. Function TTestSuite.GetCPUName(ID : String) : String;
  417. begin
  418. if (ID<>'') then
  419. Result:=GetSingleTon('SELECT TC_NAME FROM TESTCPU WHERE TC_ID='+ID);
  420. end;
  421. Function TTestSuite.GetVersionName(ID : String) : String;
  422. begin
  423. if (ID<>'') then
  424. Result:=GetSingleton('SELECT TV_VERSION FROM TESTVERSION WHERE TV_ID='+ID);
  425. end;
  426. Function TTestSuite.ShowRunData : Boolean;
  427. Const
  428. SGetRunData = 'SELECT TU_ID,TU_DATE,TC_NAME,TO_NAME,TU_COMMENT,TV_VERSION '+
  429. ' FROM TESTRUN,TESTCPU,TESTOS,TESTVERSION '+
  430. 'WHERE '+
  431. ' (TC_ID=TU_CPU_FK) AND '+
  432. ' (TO_ID=TU_OS_FK) AND '+
  433. ' (TV_ID=TU_VERSION_FK) AND '+
  434. ' (TU_ID=%s)';
  435. Var
  436. Q1,Q2 : TmYSQLDataset;
  437. F : TField;
  438. Date1, Date2: TDateTime;
  439. begin
  440. Result:=(FRunID<>'');
  441. If Result then
  442. begin
  443. Q1:=CreateDataset(Format(SGetRunData,[FRunID]));
  444. if Length(FCompareRunID) > 0 then
  445. Q2:=CreateDataset(Format(SGetRunData,[FCompareRunID]))
  446. else
  447. Q2:=nil;
  448. Try
  449. Q1.Open;
  450. if Q2 <> nil then
  451. Q2.Open;
  452. Result:=Not (Q1.EOF and Q1.BOF);
  453. If Result then
  454. With FHTMLWriter do
  455. begin
  456. FormStart(CGI,'get');
  457. EmitHiddenVar('action', '1');
  458. TableStart(3,true);
  459. RowStart;
  460. CellStart;
  461. Write('Run ID:');
  462. CellNext;
  463. EmitInput('run1id',FRunID);
  464. CellNext;
  465. EmitInput('run2id',FCompareRunID);
  466. CellEnd;
  467. RowNext;
  468. CellStart;
  469. Write('Operating system:');
  470. CellNext;
  471. Write(Q1.FieldByName('TO_NAME').AsString);
  472. CellNext;
  473. if Q2 <> nil then
  474. Write(Q2.FieldByName('TO_NAME').AsString);
  475. CellEnd;
  476. RowNext;
  477. CellStart;
  478. Write('Processor:');
  479. CellNext;
  480. Write(Q1.FieldByName('TC_NAME').AsString);
  481. CellNext;
  482. if Q2 <> nil then
  483. Write(Q2.FieldByName('TC_NAME').AsString);
  484. CellEnd;
  485. RowNext;
  486. CellStart;
  487. Write('Version:');
  488. CellNext;
  489. Write(Q1.FieldByNAme('TV_VERSION').AsString);
  490. CellNext;
  491. if Q2 <> nil then
  492. Write(Q2.FieldByNAme('TV_VERSION').AsString);
  493. CellEnd;
  494. RowNext;
  495. CellStart;
  496. Write('Comment:');
  497. CellNext;
  498. Write(Q1.FieldByName('TU_COMMENT').AsString);
  499. CellNext;
  500. if Q2 <> nil then
  501. Write(Q2.FieldByName('TU_COMMENT').AsString);
  502. CellEnd;
  503. RowNext;
  504. CellStart;
  505. Write('Date:');
  506. CellNext;
  507. F := Q1.FieldByName('TU_DATE');
  508. Date1 := F.AsDateTime;
  509. Write(F.AsString);
  510. CellNext;
  511. if Q2 <> nil then
  512. begin
  513. F := Q2.FieldByName('TU_DATE');
  514. Date2 := F.AsDateTime;
  515. Write(F.AsString);
  516. end;
  517. CellEnd;
  518. RowEnd;
  519. TableEnd;
  520. ParagraphStart;
  521. EmitCheckBox('noskipped','1',FNoSkipped);
  522. Write(' Hide skipped tests');
  523. EmitCheckBox('failedonly','1',FonlyFailed);
  524. Write(' Show only failed tests');
  525. ParagraphEnd;
  526. ParaGraphStart;
  527. EmitSubmitButton('','Show/Compare');
  528. EmitResetButton('','Reset form');
  529. ParagraphEnd;
  530. FormEnd;
  531. { give warning if dates reversed }
  532. if (Q2 <> nil) and (Date1 > Date2) then
  533. begin
  534. ParagraphStart;
  535. Write('Warning: testruns are not compared in chronological order.');
  536. ParagraphEnd;
  537. end;
  538. end;
  539. Finally
  540. Q1.Close;
  541. Q1.Free;
  542. if Q2 <> nil then
  543. begin
  544. Q2.Close;
  545. Q2.Free;
  546. end;
  547. end;
  548. end;
  549. end;
  550. Procedure TTestSuite.ShowRunResults;
  551. Var
  552. S : String;
  553. Qry : String;
  554. Q : TMySQLDataset;
  555. FL : String;
  556. begin
  557. ConnectToDB;
  558. ContentType:='text/html';
  559. EmitContentType;
  560. EmitTitle(Title+' : Search Results');
  561. With FHTMLWriter do
  562. begin
  563. HeaderStart(1);
  564. Write('Test suite results for run '+FRunID);
  565. HeaderEnd(1);
  566. HeaderStart(2);
  567. Write('Test run data : ');
  568. HeaderEnd(2);
  569. If ShowRunData then
  570. begin
  571. HeaderStart(2);
  572. Write('Detailed test run results:');
  573. FL:='';
  574. If FOnlyFailed or FNoSkipped then
  575. begin
  576. FL:='';
  577. If FOnlyFailed then
  578. FL:='successful';
  579. if FNoSkipped then
  580. begin
  581. If (FL<>'') then
  582. FL:=FL+' and ';
  583. FL:=FL+'skipped';
  584. end;
  585. Write(' ('+FL+' tests are hidden)');
  586. end;
  587. HeaderEnd(2);
  588. ParaGraphStart;
  589. S:='SELECT T_ID as Id,T_NAME as Filename,TR_SKIP as Skipped,TR_OK as OK'
  590. +' FROM TESTRESULTS,TESTS'
  591. +' WHERE (TR_TEST_FK=T_ID) AND (TR_TESTRUN_FK='+FRunID+') ';
  592. If FOnlyFailed then
  593. S:=S+' AND (TR_OK="-")';
  594. If FNoSkipped then
  595. S:=S+' AND (TR_SKIP="-")';
  596. Qry:=S;
  597. If FDebug then
  598. begin
  599. Writeln('Query : '+Qry);
  600. Flush(stdout);
  601. end;
  602. FRunCount:=0;
  603. FRunSkipCount:=0;
  604. FRunFailedCount:=0;
  605. Q:=CreateDataset(Qry);
  606. With Q do
  607. try
  608. Open;
  609. Try
  610. With CreateTableProducer(Q) do
  611. Try
  612. Border:=True;
  613. FL:='Id,Filename';
  614. If Not FNoSkipped then
  615. FL:=FL+',Skipped';
  616. If Not FOnlyFailed then
  617. FL:=FL+',OK';
  618. CreateColumns(FL);
  619. OnGetRowAttributes:=@GetRunRowAttr;
  620. TableColumns.ColumnByNAme('Filename').OnGetCellContents:=@FormatFileDetails;
  621. //(TableColumns.Items[0] as TTableColumn).ActionURL:=ALink;
  622. CreateTable(Response);
  623. Finally
  624. Free;
  625. end;
  626. Writeln('<p>Record count: ',Q.RecordCount,'</p>');
  627. Finally
  628. Close;
  629. end;
  630. finally
  631. Free;
  632. end;
  633. If Not (FRunCount=0) and not (FNoSkipped or FOnlyFailed) then
  634. begin
  635. ParaGraphStart;
  636. TagStart('IMG',Format('Src="'+CGI+'?action=2&pietotal=%d&piefailed=%d&pieskipped=%d"',[FRunCount,FRunFailedCount,FRunSkipCount]));
  637. end;
  638. end
  639. else
  640. Write('No data for test run with ID: '+FRunID);
  641. end;
  642. end;
  643. Procedure TTestSuite.ShowOneTest;
  644. Var
  645. S : String;
  646. Qry : String;
  647. Q : TMySQLDataset;
  648. FL : String;
  649. begin
  650. ConnectToDB;
  651. ContentType:='text/html';
  652. EmitContentType;
  653. EmitTitle(Title+' : File '+GetTestFileName(FTestFileID)+' Results');
  654. With FHTMLWriter do
  655. begin
  656. HeaderStart(1);
  657. Write('Test suite results for test file '+GetTestFileName(FTestFileID));
  658. HeaderEnd(1);
  659. HeaderStart(2);
  660. Write('Test run data : ');
  661. HeaderEnd(2);
  662. If ShowRunData then
  663. begin
  664. HeaderStart(2);
  665. Write('Detailed test run results:');
  666. FL:='';
  667. HeaderEnd(2);
  668. ParaGraphStart;
  669. S:='SELECT * FROM TESTS'
  670. +' WHERE (T_ID='+FTestFileID+') ';
  671. Qry:=S;
  672. If FDebug then
  673. begin
  674. Writeln('Query : '+Qry);
  675. Flush(stdout);
  676. end;
  677. FRunCount:=0;
  678. FRunSkipCount:=0;
  679. FRunFailedCount:=0;
  680. Q:=CreateDataset(Qry);
  681. With Q do
  682. try
  683. Open;
  684. Try
  685. With CreateTableProducer(Q) do
  686. Try
  687. Border:=True;
  688. FL:='Filename';
  689. If Not FNoSkipped then
  690. FL:=FL+',Skipped';
  691. If Not FOnlyFailed then
  692. FL:=FL+',OK';
  693. CreateColumns(FL);
  694. OnGetRowAttributes:=@GetRunRowAttr;
  695. //(TableColumns.Items[0] as TTableColumn).ActionURL:=ALink;
  696. CreateTable(Response);
  697. Finally
  698. Free;
  699. end;
  700. Writeln('<p>Record count: ',Q.RecordCount,'</p>');
  701. Finally
  702. Close;
  703. end;
  704. finally
  705. Free;
  706. end;
  707. end
  708. else
  709. Write('No data for test file with ID: '+FTestFileID);
  710. end;
  711. end;
  712. Procedure TTestSuite.ShowRunComparison;
  713. Var
  714. S : String;
  715. Qry : String;
  716. Q : TMySQLDataset;
  717. FL : String;
  718. begin
  719. ConnectToDB;
  720. ContentType:='text/html';
  721. EmitContentType;
  722. EmitTitle(Title+' : Compare 2 runs');
  723. With FHTMLWriter do
  724. begin
  725. HeaderStart(1);
  726. Write('Test suite results for run '+FRunID+' vs. '+FCompareRunID);
  727. HeaderEnd(1);
  728. HeaderStart(2);
  729. Write('Test run data: ');
  730. HeaderEnd(2);
  731. If ShowRunData then
  732. begin
  733. HeaderStart(2);
  734. Write('Detailed test run results:');
  735. FL:='';
  736. If FOnlyFailed or FNoSkipped then
  737. begin
  738. FL:='';
  739. If FOnlyFailed then
  740. FL:='successful';
  741. if FNoSkipped then
  742. begin
  743. If (FL<>'') then
  744. FL:=FL+' and ';
  745. FL:=FL+'skipped';
  746. end;
  747. Write(' ('+FL+' tests are hidden)');
  748. end;
  749. HeaderEnd(2);
  750. ParaGraphStart;
  751. Q:=CreateDataset('');
  752. Q.SQL.Text:='CREATE TEMPORARY TABLE tr1 like TESTRESULTS;';
  753. Q.ExecSQL;
  754. Q.SQL.Text:='CREATE TEMPORARY TABLE tr2 like TESTRESULTS;';
  755. Q.ExecSQL;
  756. Q.SQL.Text:='INSERT INTO tr1 SELECT * FROM TESTRESULTS WHERE TR_TESTRUN_FK='+FRunID+';';
  757. Q.ExecSQL;
  758. Q.SQL.Text:='INSERT INTO tr2 SELECT * FROM TESTRESULTS WHERE TR_TESTRUN_FK='+FCompareRunID+';';
  759. Q.ExecSQL;
  760. S:='SELECT T_NAME as Filename,tr1.TR_SKIP as Run1_Skipped,'
  761. +'tr2.TR_SKIP as Run2_Skipped,tr1.TR_OK as Run1_OK,tr2.TR_OK as Run2_OK '
  762. +'FROM TESTS, tr2 LEFT JOIN tr1 USING (TR_TEST_FK) '
  763. +'WHERE ((tr1.TR_SKIP IS NULL) or (%s(tr1.TR_OK<>tr2.TR_OK))) and (T_ID=tr2.TR_TEST_FK)';
  764. If FNoSkipped then
  765. begin
  766. S:=S+' and (tr2.TR_SKIP<>"+")';
  767. Qry:='(tr1.TR_SKIP<>"+") and';
  768. end
  769. else
  770. Qry:='';
  771. Qry:=Format(S,[Qry]);
  772. If FDebug then
  773. begin
  774. Writeln('Query: '+Qry);
  775. Flush(stdout);
  776. end;
  777. FRunCount:=0;
  778. FRunSkipCount:=0;
  779. FRunFailedCount:=0;
  780. Q.SQL.Text:=Qry;
  781. With Q do
  782. try
  783. Open;
  784. Try
  785. With CreateTableProducer(Q) do
  786. Try
  787. Border:=True;
  788. FL:='Filename,Run1_OK,Run2_OK';
  789. If Not FNoSkipped then
  790. FL:=FL+',Run1_Skipped,Run2_Skipped';
  791. CreateColumns(FL);
  792. OnGetRowAttributes:=@GetRunRowAttr;
  793. //(TableColumns.Items[0] as TTableColumn).ActionURL:=ALink;
  794. CreateTable(Response);
  795. Finally
  796. Free;
  797. end;
  798. Writeln('<p>Record count: ',Q.RecordCount,'</p>');
  799. Finally
  800. Close;
  801. end;
  802. finally
  803. Free;
  804. end;
  805. If Not (FRunCount=0) and not (FNoSkipped or FOnlyFailed) then
  806. begin
  807. ParaGraphStart;
  808. TagStart('IMG',Format('Src="'+CGI+'?action=2&pietotal=%d&piefailed=%d&pieskipped=%d"',[FRunCount,FRunFailedCount,FRunSkipCount]));
  809. end;
  810. end
  811. else
  812. Write('No data for test run with ID: '+FRunID);
  813. end;
  814. end;
  815. procedure TTestSuite.GetRunRowAttr(Sender: TObject; var BGColor: String;
  816. var Align: THTMLAlign; var VAlign: THTMLValign; var CustomAttr: String);
  817. Var
  818. P : TTableProducer;
  819. Skip1Field, Skip2Field, Run1Field, Run2Field : TField;
  820. begin
  821. P:=(Sender as TTAbleProducer);
  822. Inc(FRunCount);
  823. If (FOnlyFailed and FNoSkipped) then
  824. begin
  825. If (P.CurrentRow Mod 2)=0 then
  826. BGColor:='#EEEEEE'
  827. end
  828. else
  829. begin
  830. Skip1Field := P.Dataset.FindField('Skipped');
  831. if Skip1Field = nil then
  832. begin
  833. Skip1Field := P.Dataset.FindField('Run1_Skipped');
  834. Skip2Field := P.Dataset.FindField('Run2_Skipped');
  835. end
  836. else
  837. Skip2Field := nil;
  838. Run1Field := P.Dataset.FindField('OK');
  839. if Run1Field = nil then
  840. Run1Field := P.Dataset.FindField('Run1_OK');
  841. Run2Field := P.Dataset.FindField('OK');
  842. if Run2Field = nil then
  843. Run2Field := P.Dataset.FindField('Run2_OK');
  844. If (not FNoSkipped) and ((Skip1Field.AsString='+')
  845. or ((Skip2Field <> nil) and (Skip2Field.AsString = '+'))) then
  846. begin
  847. Inc(FRunSkipCount);
  848. BGColor:='yellow'; // Yellow
  849. end
  850. else If Run2Field.AsString='+' then
  851. if Run1Field.AsString='' then
  852. BGColor:='#68DFB8'
  853. else
  854. BGColor:='#98FB98' // pale Green
  855. else
  856. begin
  857. Inc(FRunFailedCount);
  858. if Run1Field.AsString='' then
  859. BGColor:='#FF82AB' // Light red
  860. else
  861. BGColor:='#FF225B';
  862. end;
  863. end;
  864. end;
  865. procedure TTestSuite.FormatFailedOverview(Sender: TObject; var CellData: String);
  866. Var
  867. S: String;
  868. P : TTableProducer;
  869. begin
  870. P:=(Sender as TTableProducer);
  871. S:=Format(SDetailsURL,[P.DataSet.FieldByName('ID').AsString]);
  872. S:=S+'&failedonly=1&noskipped=1';
  873. CellData:=Format('<A HREF="%s">%s</A>',[S,CellData]);
  874. end;
  875. procedure TTestSuite.FormatFileDetails(Sender: TObject; var CellData: String);
  876. Var
  877. S: String;
  878. P : TTableProducer;
  879. begin
  880. P:=(Sender as TTableProducer);
  881. S:=Format(CGI + '?action=3&run1id=%s&filenameid=%s',[FRunID,P.DataSet.FieldByName('Id').AsString]);
  882. CellData:=Format('<A HREF="%s">%s</A>',[S,CellData]);
  883. end;
  884. Procedure TTestSuite.CreateRunPie;
  885. Var
  886. I : TFPMemoryImage;
  887. M : TMemoryStream;
  888. begin
  889. ftFont.InitEngine;
  890. FontMgr.SearchPath:='/usr/lib/X11/fonts/truetype';
  891. I:=TFPMemoryImage.Create(320,320);
  892. try
  893. If FRunCount=0 Then
  894. Raise Exception.Create('Invalid parameters passed to script: No total count');
  895. DoDrawPie(I,FRunSkipCount,FRunFailedCount,FRunCount);
  896. M:=TMemoryStream.Create;
  897. Try
  898. With TFPWriterPNG.Create do
  899. try
  900. UseAlpha:=True;
  901. ImageWrite(M,I);
  902. Finally
  903. Free;
  904. end;
  905. ContentType:='image/png';
  906. EmitContentType;
  907. M.Position:=0;
  908. Response.CopyFrom(M,M.Size);
  909. Finally
  910. M.Free;
  911. end;
  912. Finally
  913. I.Free;
  914. end;
  915. end;
  916. Procedure TTestSuite.DoDrawPie(Img : TFPCustomImage; Skipped,Failed,Total : Integer);
  917. Var
  918. Cnv : TFPImageCanvas;
  919. W,H,FH,CR,ra : Integer;
  920. A1,A2,FR,SR,PR : Double;
  921. R : TRect;
  922. F : TFreeTypeFont;
  923. Procedure AddPie(X,Y,R : Integer; AStart,AStop : Double; Col : TFPColor);
  924. Var
  925. DX,Dy : Integer;
  926. begin
  927. DX:=Round(R*Cos(A1));
  928. DY:=Round(R*Sin(A1));
  929. Cnv.Line(X,Y,X+DX,Y-DY);
  930. DX:=Round(Ra*Cos(A2));
  931. DY:=Round(Ra*Sin(A2));
  932. Cnv.Line(X,Y,X+DX,Y-Dy);
  933. DX:=Round(R/2*Cos((A1+A2)/2));
  934. DY:=Round(R/2*Sin((A1+A2)/2));
  935. Cnv.Brush.FpColor:=Col;
  936. Cnv.FloodFill(X+DX,Y-DY);
  937. end;
  938. Function FractionAngle(F,T : Integer): Double;
  939. begin
  940. Result:=(2*Pi*(F/T))
  941. end;
  942. begin
  943. F:=TFreeTypeFont.Create;
  944. With F do
  945. begin
  946. Name:='arial';
  947. FontIndex:=0;
  948. Size:=12;
  949. FPColor:=colred;
  950. AntiAliased:=False;
  951. Resolution:=96;
  952. end;
  953. // Writeln('Creating image');
  954. Cnv:=TFPImageCanvas.Create(Img);
  955. // Writeln('Getting width and height');
  956. W:=Img.Width;
  957. H:=Img.Height;
  958. // Writeln('Transparant');
  959. cnv.Brush.Style:=bsSolid;
  960. cnv.Brush.FPColor:=colTransparent;
  961. cnv.Pen.FPColor:=colWhite;
  962. Cnv.Rectangle(0,0,W,H);
  963. // Writeln('Setting font');
  964. Cnv.Font:=F;
  965. // Writeln('Getting textwidth ');
  966. FH:=CNV.GetTextHeight('A');
  967. If FH=0 then
  968. FH:=14; // 3 * 14;
  969. Inc(FH,3);
  970. R.Top:=FH*4;
  971. R.Left:=0;
  972. R.Bottom:=H;
  973. CR:=H-(FH*4);
  974. If W>CR then
  975. R.Right:=CR
  976. else
  977. R.Right:=W;
  978. Ra:=CR div 2;
  979. // Writeln('Setting pen color');
  980. Cnv.Pen.FPColor:=colBlack;
  981. // Writeln('Palette size : ',Img.Palette.Count);
  982. // Writeln('Setting brush style');
  983. cnv.brush.FPColor:=colRed;
  984. // cnv.pen.width:=1;
  985. // Writeln('Drawing ellipse');
  986. Cnv.Ellipse(R);
  987. // Writeln('Setting text');
  988. // Writeln('Palette size : ',Img.Palette.Count);
  989. cnv.font.FPColor:=colred;
  990. Inc(FH,4);
  991. FR:=Failed/Total;
  992. SR:=Skipped/Total;
  993. PR:=1-(FR+SR);
  994. Cnv.Textout(1,FH,Format('%d Failed (%3.1f%%)',[Failed,Fr*100]));
  995. // Writeln('Palette size : ',Img.Palette.Count);
  996. cnv.font.FPColor:=colYellow;
  997. Cnv.Textout(1,FH*2,Format('%d Skipped (%3.1f%%)',[Skipped,SR*100]));
  998. A1:=(Pi*2*(failed/total));
  999. A2:=A1+(Pi*2*(Skipped/Total));
  1000. AddPie(Ra,R.Top+Ra,Ra,A1,A2,ColYellow);
  1001. cnv.font.FPColor:=colGreen;
  1002. // Writeln('Palette size : ',Img.Palette.Count);
  1003. A1:=A2;
  1004. A2:=A1+(Pi*2*((Total-(Skipped+Failed))/Total));
  1005. Cnv.Textout(1,FH*3,Format('%d Passed (%3.1f%%',[Total-Skipped-Failed,PR*100]));
  1006. AddPie(Ra,R.Top+Ra,Ra,A1,A2,ColGreen);
  1007. // Writeln('Palette size : ',Img.Palette.Count);
  1008. // Writeln('All done');
  1009. end;
  1010. end.