dotest.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. {
  2. $Id$
  3. }
  4. program dotest;
  5. uses
  6. dos,
  7. redir;
  8. const
  9. {$ifdef UNIX}
  10. ExeExt='';
  11. {$else UNIX}
  12. ExeExt='exe';
  13. {$endif UNIX}
  14. type
  15. TVerboseLevel=(V_Abort,V_Error,V_Warning,V_Normal,V_Debug);
  16. TConfig = record
  17. NeedOptions,
  18. NeedCPU,
  19. NeedVersion : string;
  20. ResultCode : longint;
  21. NeedRecompile : boolean;
  22. IsInteractive : boolean;
  23. IsKnown : boolean;
  24. NoRun : boolean;
  25. UsesGraph : boolean;
  26. ShouldFail : boolean;
  27. Category : string;
  28. end;
  29. var
  30. Config : TConfig;
  31. CompilerBin : string;
  32. CompilerCPU : string;
  33. CompilerVersion : string;
  34. PPFile : string;
  35. PPFileInfo : string;
  36. TestName : string;
  37. Note : string;
  38. const
  39. ResLogfile : string[32] = 'log';
  40. LongLogfile : string[32] = 'longlog';
  41. FailLogfile : string[32] = 'faillist';
  42. DoVerbose : boolean = false;
  43. DoGraph : boolean = false;
  44. DoInteractive : boolean = false;
  45. DoExecute : boolean = false;
  46. DoKnown : boolean = false;
  47. procedure Verbose(lvl:TVerboseLevel;const s:string);
  48. begin
  49. case lvl of
  50. V_Normal :
  51. writeln(s);
  52. V_Debug :
  53. if DoVerbose then
  54. writeln('Debug: ',s);
  55. V_Warning :
  56. writeln('Warning: ',s);
  57. V_Error :
  58. begin
  59. writeln('Error: ',s);
  60. halt(1);
  61. end;
  62. V_Abort :
  63. begin
  64. writeln('Abort: ',s);
  65. halt(0);
  66. end;
  67. end;
  68. end;
  69. Function FileExists (Const F : String) : Boolean;
  70. {
  71. Returns True if the file exists, False if not.
  72. }
  73. Var
  74. info : searchrec;
  75. begin
  76. FindFirst (F,anyfile,Info);
  77. FileExists:=DosError=0;
  78. FindClose (Info);
  79. end;
  80. function ToStr(l:longint):string;
  81. var
  82. s : string;
  83. begin
  84. Str(l,s);
  85. ToStr:=s;
  86. end;
  87. function ToStrZero(l:longint;nbzero : byte):string;
  88. var
  89. s : string;
  90. begin
  91. Str(l,s);
  92. while length(s)<nbzero do
  93. s:='0'+s;
  94. ToStrZero:=s;
  95. end;
  96. procedure SetPPFileInfo;
  97. Var
  98. info : searchrec;
  99. dt : DateTime;
  100. begin
  101. FindFirst (PPFile,anyfile,Info);
  102. If DosError=0 then
  103. begin
  104. UnpackTime(info.time,dt);
  105. PPFileInfo:=PPFile+' '+ToStr(dt.year)+'/'+ToStrZero(dt.month,2)+'/'+
  106. ToStrZero(dt.day,2)+' '+ToStrZero(dt.Hour,2)+':'+ToStrZero(dt.min,2)+':'+ToStrZero(dt.sec,2);
  107. end
  108. else
  109. PPFileInfo:=PPfile;
  110. FindClose (Info);
  111. end;
  112. procedure TrimB(var s:string);
  113. begin
  114. while (s<>'') and (s[1] in [' ',#9]) do
  115. delete(s,1,1);
  116. end;
  117. procedure TrimE(var s:string);
  118. begin
  119. while (s<>'') and (s[length(s)] in [' ',#9]) do
  120. delete(s,length(s),1);
  121. end;
  122. function upper(const s : string) : string;
  123. var
  124. i : longint;
  125. begin
  126. for i:=1 to length(s) do
  127. if s[i] in ['a'..'z'] then
  128. upper[i]:=char(byte(s[i])-32)
  129. else
  130. upper[i]:=s[i];
  131. upper[0]:=s[0];
  132. end;
  133. function SplitPath(const s:string):string;
  134. var
  135. i : longint;
  136. begin
  137. i:=Length(s);
  138. while (i>0) and not(s[i] in ['/','\']) do
  139. dec(i);
  140. SplitPath:=Copy(s,1,i);
  141. end;
  142. function ForceExtension(Const HStr,ext:String):String;
  143. {
  144. Return a filename which certainly has the extension ext
  145. }
  146. var
  147. j : longint;
  148. begin
  149. j:=length(Hstr);
  150. while (j>0) and (Hstr[j]<>'.') do
  151. dec(j);
  152. if j=0 then
  153. j:=255;
  154. if Ext<>'' then
  155. ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext
  156. else
  157. ForceExtension:=Copy(Hstr,1,j-1);
  158. end;
  159. procedure Copyfile(const fn1,fn2:string;append:boolean);
  160. const
  161. bufsize = 16384;
  162. var
  163. f,g : file;
  164. i : longint;
  165. buf : pointer;
  166. begin
  167. if Append then
  168. Verbose(V_Debug,'Appending '+fn1+' to '+fn2)
  169. else
  170. Verbose(V_Debug,'Copying '+fn1+' to '+fn2);
  171. assign(f,fn1);
  172. assign(g,fn2);
  173. {$I-}
  174. reset(f,1);
  175. {$I+}
  176. if ioresult<>0 then
  177. Verbose(V_Error,'Can''t open '+fn1);
  178. if append then
  179. begin
  180. {$I-}
  181. reset(g,1);
  182. {$I+}
  183. if ioresult<>0 then
  184. append:=false
  185. else
  186. seek(g,filesize(g));
  187. end;
  188. if not append then
  189. begin
  190. {$I-}
  191. rewrite(g,1);
  192. {$I+}
  193. if ioresult<>0 then
  194. Verbose(V_Error,'Can''t open '+fn2+' for output');
  195. end;
  196. getmem(buf,bufsize);
  197. repeat
  198. blockread(f,buf^,bufsize,i);
  199. blockwrite(g,buf^,i);
  200. until i<bufsize;
  201. freemem(buf,bufsize);
  202. close(f);
  203. close(g);
  204. end;
  205. procedure AddLog(const logfile,s:string);
  206. var
  207. t : text;
  208. begin
  209. assign(t,logfile);
  210. {$I-}
  211. append(t);
  212. {$I+}
  213. if ioresult<>0 then
  214. begin
  215. {$I-}
  216. rewrite(t);
  217. {$I+}
  218. if ioresult<>0 then
  219. Verbose(V_Abort,'Can''t append to '+logfile);
  220. end;
  221. writeln(t,s);
  222. close(t);
  223. end;
  224. function GetConfig(const fn:string;var r:TConfig):boolean;
  225. var
  226. t : text;
  227. code : integer;
  228. s,res : string;
  229. function GetEntry(const entry:string):boolean;
  230. var
  231. i : longint;
  232. begin
  233. Getentry:=false;
  234. Res:='';
  235. if Upper(Copy(s,1,length(entry)))=Upper(entry) then
  236. begin
  237. Delete(s,1,length(entry));
  238. TrimB(s);
  239. if (s<>'') then
  240. begin
  241. if (s[1]='=') then
  242. begin
  243. delete(s,1,1);
  244. i:=pos('}',s);
  245. if i=0 then
  246. i:=255
  247. else
  248. dec(i);
  249. res:=Copy(s,1,i);
  250. TrimB(res);
  251. TrimE(res);
  252. end;
  253. Verbose(V_Debug,'Config: '+Entry+' = "'+Res+'"');
  254. GetEntry:=true;
  255. end;
  256. end;
  257. end;
  258. begin
  259. FillChar(r,sizeof(r),0);
  260. GetConfig:=false;
  261. Verbose(V_Debug,'Reading '+fn);
  262. assign(t,fn);
  263. {$I-}
  264. reset(t);
  265. {$I+}
  266. if ioresult<>0 then
  267. begin
  268. Verbose(V_Error,'Can''t open '+fn);
  269. exit;
  270. end;
  271. Note:='';
  272. while not eof(t) do
  273. begin
  274. readln(t,s);
  275. if s<>'' then
  276. begin
  277. if s[1]='{' then
  278. begin
  279. delete(s,1,1);
  280. TrimB(s);
  281. if (s<>'') and (s[1]='%') then
  282. begin
  283. delete(s,1,1);
  284. if GetEntry('OPT') then
  285. r.NeedOptions:=res
  286. else
  287. if GetEntry('CPU') then
  288. r.NeedCPU:=res
  289. else
  290. if GetEntry('VERSION') then
  291. r.NeedVersion:=res
  292. else
  293. if GetEntry('RESULT') then
  294. Val(res,r.ResultCode,code)
  295. else
  296. if GetEntry('GRAPH') then
  297. r.UsesGraph:=true
  298. else
  299. if GetEntry('FAIL') then
  300. r.ShouldFail:=true
  301. else
  302. if GetEntry('RECOMPILE') then
  303. r.NeedRecompile:=true
  304. else
  305. if GetEntry('NORUN') then
  306. r.NoRun:=true
  307. else
  308. if GetEntry('KNOWN') then
  309. r.IsKnown:=true
  310. else
  311. if GetEntry('INTERACTIVE') then
  312. r.IsInteractive:=true
  313. else
  314. if GetEntry('NOTE') then
  315. begin
  316. Note:='Note: '+res;
  317. Verbose(V_Normal,Note);
  318. end
  319. else
  320. Verbose(V_Error,'Unknown entry: '+s);
  321. end;
  322. end
  323. else
  324. break;
  325. end;
  326. end;
  327. close(t);
  328. GetConfig:=true;
  329. end;
  330. function GetCompilerVersion:boolean;
  331. var
  332. t : text;
  333. begin
  334. GetCompilerVersion:=false;
  335. ExecuteRedir(CompilerBin,'-iV','','out','');
  336. assign(t,'out');
  337. {$I-}
  338. reset(t);
  339. readln(t,CompilerVersion);
  340. close(t);
  341. erase(t);
  342. {$I+}
  343. if ioresult<>0 then
  344. Verbose(V_Error,'Can''t get Compiler Version')
  345. else
  346. begin
  347. Verbose(V_Debug,'Current Compiler Version: '+CompilerVersion);
  348. GetCompilerVersion:=true;
  349. end;
  350. end;
  351. function GetCompilerCPU:boolean;
  352. var
  353. t : text;
  354. begin
  355. GetCompilerCPU:=false;
  356. ExecuteRedir(CompilerBin,'-iTP','','out','');
  357. assign(t,'out');
  358. {$I-}
  359. reset(t);
  360. readln(t,CompilerCPU);
  361. close(t);
  362. erase(t);
  363. {$I+}
  364. if ioresult<>0 then
  365. Verbose(V_Error,'Can''t get Compiler CPU Target')
  366. else
  367. begin
  368. Verbose(V_Debug,'Current Compiler CPU Target: '+CompilerCPU);
  369. GetCompilerCPU:=true;
  370. end;
  371. end;
  372. function RunCompiler:boolean;
  373. var
  374. outname,
  375. args : string;
  376. begin
  377. RunCompiler:=false;
  378. OutName:=ForceExtension(PPFile,'log');
  379. args:='-Fuunits';
  380. if Config.NeedOptions<>'' then
  381. args:=args+' '+Config.NeedOptions;
  382. args:=args+' '+ppfile;
  383. Verbose(V_Debug,'Executing '+compilerbin+' '+args);
  384. { also get the output from as and ld that writes to stderr sometimes }
  385. ExecuteRedir(CompilerBin,args,'',OutName,OutName);
  386. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  387. { Shoud the compile fail ? }
  388. if Config.ShouldFail then
  389. begin
  390. if ExecuteResult<>0 then
  391. begin
  392. AddLog(ResLogFile,'Success, compilation failed '+PPFileInfo);
  393. { avoid to try again }
  394. AddLog(ForceExtension(PPFile,'elg'),'Success, compilation failed '+PPFileInfo);
  395. RunCompiler:=true;
  396. end
  397. else
  398. begin
  399. AddLog(FailLogFile,TestName);
  400. if Note<>'' then
  401. AddLog(FailLogFile,Note);
  402. AddLog(ResLogFile,'Failed, compilation successful '+PPFileInfo);
  403. AddLog(LongLogFile,'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
  404. AddLog(LongLogFile,'Failed, compilation successful '+PPFileInfo);
  405. { avoid to try again }
  406. AddLog(ForceExtension(PPFile,'elg'),'Failed, compilation successful '+PPFileInfo);
  407. if Note<>'' then
  408. AddLog(LongLogFile,Note);
  409. CopyFile(OutName,LongLogFile,true);
  410. end;
  411. end
  412. else
  413. begin
  414. if ExecuteResult<>0 then
  415. begin
  416. AddLog(FailLogFile,TestName);
  417. if Note<>'' then
  418. AddLog(FailLogFile,Note);
  419. AddLog(ResLogFile,'Failed to compile '+PPFileInfo);
  420. AddLog(LongLogFile,'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
  421. AddLog(LongLogFile,'Failed to compile '+PPFileInfo);
  422. if Note<>'' then
  423. AddLog(LongLogFile,Note);
  424. CopyFile(OutName,LongLogFile,true);
  425. { avoid to try again }
  426. AddLog(ForceExtension(PPFile,'elg'),'Failed to compile '++PPFileInfo);
  427. Verbose(V_Abort,'Exitcode: '+ToStr(ExecuteResult)+' (expected 0)');
  428. end
  429. else
  430. begin
  431. AddLog(ResLogFile,'Successfully compiled '+PPFileInfo);
  432. RunCompiler:=true;
  433. end;
  434. end;
  435. end;
  436. function RunExecutable:boolean;
  437. var
  438. outname,
  439. TestExe : string;
  440. begin
  441. RunExecutable:=false;
  442. TestExe:=ForceExtension(PPFile,ExeExt);
  443. OutName:=ForceExtension(PPFile,'elg');
  444. Verbose(V_Debug,'Executing '+TestExe);
  445. ExecuteRedir(TestExe,'','',OutName,'');
  446. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  447. if ExecuteResult<>Config.ResultCode then
  448. begin
  449. AddLog(FailLogFile,TestName);
  450. AddLog(ResLogFile,'Failed to run '+PPFileInfo);
  451. AddLog(LongLogFile,'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
  452. AddLog(LongLogFile,'Failed to run '+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  453. Copyfile(OutName,LongLogFile,true);
  454. Verbose(V_Abort,'Exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  455. end
  456. else
  457. begin
  458. AddLog(ResLogFile,'Successfully run '+PPFileInfo);
  459. RunExecutable:=true;
  460. end;
  461. end;
  462. procedure getargs;
  463. var
  464. ch : char;
  465. para : string;
  466. i : longint;
  467. procedure helpscreen;
  468. begin
  469. writeln('dotest [Options] <File>');
  470. writeln;
  471. writeln('Options can be:');
  472. writeln(' -C<compiler> set compiler to use');
  473. writeln(' -V verbose');
  474. writeln(' -E execute test also');
  475. writeln(' -A include ALL tests');
  476. writeln(' -G include graph tests');
  477. writeln(' -K include known bug tests');
  478. writeln(' -I include interactive tests');
  479. halt(1);
  480. end;
  481. begin
  482. PPFile:='';
  483. if exeext<>'' then
  484. CompilerBin:='ppc386.'+exeext
  485. else
  486. CompilerBin:='ppc386';
  487. for i:=1 to paramcount do
  488. begin
  489. para:=Paramstr(i);
  490. if (para[1]='-') then
  491. begin
  492. ch:=Upcase(para[2]);
  493. delete(para,1,2);
  494. case ch of
  495. 'A' :
  496. begin
  497. DoGraph:=true;
  498. DoInteractive:=true;
  499. DoKnown:=true;
  500. end;
  501. 'C' : CompilerBin:=Para;
  502. 'E' : DoExecute:=true;
  503. 'G' : DoGraph:=true;
  504. 'I' : DoInteractive:=true;
  505. 'V' : DoVerbose:=true;
  506. 'K' : DoKnown:=true;
  507. end;
  508. end
  509. else
  510. begin
  511. If PPFile<>'' then
  512. HelpScreen;
  513. PPFile:=ForceExtension(Para,'pp');
  514. end;
  515. end;
  516. if (PPFile='') then
  517. HelpScreen;
  518. SetPPFileInfo;
  519. TestName:=Copy(PPFile,1,Pos('.pp',PPFile)-1);
  520. Verbose(V_Debug,'Running test '+TestName+', file '+PPFile);
  521. end;
  522. procedure RunTest;
  523. var
  524. Res : boolean;
  525. OutName : string;
  526. begin
  527. Res:=GetConfig(ppfile,Config);
  528. OutName:=ForceExtension(PPFile,'elg');
  529. if Res then
  530. begin
  531. if Config.UsesGraph and (not DoGraph) then
  532. begin
  533. AddLog(ResLogFile,'Skipping test because it uses graph '+PPFileInfo);
  534. { avoid a second attempt by writing to elg file }
  535. AddLog(OutName,'Skipping test because it uses graph '+PPFileInfo);
  536. Verbose(V_Abort,'Skipping test because it uses graph ');
  537. Res:=false;
  538. end;
  539. end;
  540. if Res then
  541. begin
  542. if Config.IsInteractive and (not DoInteractive) then
  543. begin
  544. { avoid a second attempt by writing to elg file }
  545. AddLog(OutName,'Skipping test because it is interactive '+PPFileInfo);
  546. AddLog(ResLogFile,'Skipping test because it is interactive '+PPFileInfo);
  547. Verbose(V_Abort,'Skipping test because it is interactive ');
  548. Res:=false;
  549. end;
  550. end;
  551. if Res then
  552. begin
  553. if Config.IsKnown and (not DoKnown) then
  554. begin
  555. { avoid a second attempt by writing to elg file }
  556. AddLog(OutName,'Skipping test because it is a known bug '+PPFileInfo);
  557. AddLog(ResLogFile,'Skipping test because it is a known bug '+PPFileInfo);
  558. Verbose(V_Abort,'Skipping test because it is a known bug ');
  559. Res:=false;
  560. end;
  561. end;
  562. if Res then
  563. begin
  564. if Config.NeedVersion<>'' then
  565. begin
  566. Verbose(V_Debug,'Required compiler version: '+Config.NeedVersion);
  567. Res:=GetCompilerVersion;
  568. if CompilerVersion<Config.NeedVersion then
  569. begin
  570. { avoid a second attempt by writing to elg file }
  571. AddLog(OutName,'Skipping test because compiler version too low '+PPFileInfo);
  572. AddLog(ResLogFile,'Skipping test because compiler version too low '+PPFileInfo);
  573. Verbose(V_Abort,'Compiler version too low '+CompilerVersion+' < '+Config.NeedVersion);
  574. Res:=false;
  575. end;
  576. end;
  577. end;
  578. if Res then
  579. begin
  580. if Config.NeedCPU<>'' then
  581. begin
  582. Verbose(V_Debug,'Required compiler cpu: '+Config.NeedCPU);
  583. Res:=GetCompilerCPU;
  584. if Upper(Config.NeedCPU)<>Upper(CompilerCPU) then
  585. begin
  586. { avoid a second attempt by writing to elg file }
  587. AddLog(OutName,'Skipping test because for other cpu '+PPFileInfo);
  588. AddLog(ResLogFile,'Skipping test because for other cpu '+PPFileInfo);
  589. Verbose(V_Abort,'Compiler cpu wrong '+CompilerCPU+' <> '+Config.NeedCPU);
  590. Res:=false;
  591. end;
  592. end;
  593. end;
  594. if Res then
  595. begin
  596. Res:=RunCompiler;
  597. if Res and Config.NeedRecompile then
  598. Res:=RunCompiler;
  599. end;
  600. if Res then
  601. begin
  602. if (Config.NoRun) then
  603. begin
  604. { avoid a second attempt by writing to elg file }
  605. AddLog(OutName,'Skipping run test '+PPFileInfo);
  606. AddLog(ResLogFile,'Skipping run test '+PPFileInfo);
  607. Verbose(V_Debug,'Skipping run test ');
  608. end
  609. else
  610. begin
  611. if (not Config.ShouldFail) and DoExecute then
  612. begin
  613. if FileExists(ForceExtension(PPFile,'ppu')) or
  614. FileExists(ForceExtension(PPFile,'ppo')) or
  615. FileExists(ForceExtension(PPFile,'ppw')) then
  616. begin
  617. AddLog(ForceExtension(PPFile,'elg'),'Skipping test run because it is a unit '+PPFileInfo);
  618. AddLog(ResLogFile,'Skipping test run because it is a unit '+PPFileInfo);
  619. Verbose(V_Debug,'Unit found, skipping run test')
  620. end
  621. else
  622. Res:=RunExecutable;
  623. end;
  624. end;
  625. end;
  626. end;
  627. begin
  628. GetArgs;
  629. RunTest;
  630. end.
  631. {
  632. $Log$
  633. Revision 1.13 2002-03-03 13:27:28 hajny
  634. + added support for OS/2 units (.ppo)
  635. Revision 1.12 2002/01/29 13:24:16 pierre
  636. + also generate .elg file for units
  637. Revision 1.11 2002/01/29 12:51:08 pierre
  638. + PPFileInfo to also display time stamp of test file
  639. * generate .elg file in several cases
  640. to avoid trying to recompute the same test
  641. over and over again.
  642. Revision 1.10 2001/07/31 09:00:16 pierre
  643. + %Note= comment added
  644. Revision 1.9 2001/07/04 11:23:39 florian
  645. * spelling mistake fixed
  646. Revision 1.8 2001/06/02 00:41:36 peter
  647. * write exitcode for all executed programs in debug mode
  648. Revision 1.7 2000/12/09 16:01:10 peter
  649. + known bug flag
  650. + norun flag
  651. + recompile flag
  652. Revision 1.6 2000/12/04 22:06:25 peter
  653. * fixed stupid c&p bug for CPU check
  654. Revision 1.5 2000/12/03 22:59:10 florian
  655. * some problems for go32v2 fixed
  656. }