dotest.pp 13 KB

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