dotest.pp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. {
  2. $Id$
  3. This file is part of the Free Pascal test suite.
  4. Copyright (c) 1999-2002 by the Free Pascal development team.
  5. This program makes the compilation and
  6. execution of individual test sources.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {$H+}
  14. program dotest;
  15. uses
  16. dos,
  17. teststr,
  18. testu,
  19. redir;
  20. {$ifdef go32v2}
  21. {$define LIMIT83FS}
  22. {$endif}
  23. {$ifdef os2}
  24. {$define LIMIT83FS}
  25. {$endif}
  26. type
  27. tcompinfo = (compver,comptarget,compcpu);
  28. const
  29. ObjExt='o';
  30. PPUExt='ppu';
  31. {$ifdef UNIX}
  32. ExeExt='';
  33. {$else UNIX}
  34. ExeExt='exe';
  35. {$endif UNIX}
  36. var
  37. Config : TConfig;
  38. CompilerLogFile,
  39. ExeLogFile,
  40. LongLogfile,
  41. FailLogfile,
  42. RTLUnitsDir,
  43. TestOutputDir,
  44. OutputDir : string;
  45. CompilerBin : string;
  46. CompilerCPU : string;
  47. CompilerTarget : string;
  48. CompilerVersion : string;
  49. PPFile : string;
  50. PPFileInfo : string;
  51. TestName : string;
  52. const
  53. DoGraph : boolean = false;
  54. DoInteractive : boolean = false;
  55. DoExecute : boolean = false;
  56. DoKnown : boolean = false;
  57. DoAll : boolean = false;
  58. DoUsual : boolean = true;
  59. TargetDir : string = '';
  60. ExtraCompilerOpts : string = '';
  61. DelExecutable : boolean = false;
  62. RemoteAddr : string = '';
  63. RemotePath : string = '/tmp';
  64. RemotePara : string = '';
  65. rshprog : string = 'rsh';
  66. rcpprog : string = 'rcp';
  67. rquote : char = '''';
  68. emulatorname : string = '';
  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 PathExists (Const F : String) : Boolean;
  81. {
  82. Returns True if the file exists, False if not.
  83. }
  84. Var
  85. info : searchrec;
  86. begin
  87. FindFirst (F,anyfile,Info);
  88. PathExists:=(DosError=0) and (Info.Attr and Directory=Directory);
  89. FindClose (Info);
  90. end;
  91. function ToStr(l:longint):string;
  92. var
  93. s : string;
  94. begin
  95. Str(l,s);
  96. ToStr:=s;
  97. end;
  98. function ToStrZero(l:longint;nbzero : byte):string;
  99. var
  100. s : string;
  101. begin
  102. Str(l,s);
  103. while length(s)<nbzero do
  104. s:='0'+s;
  105. ToStrZero:=s;
  106. end;
  107. function trimspace(const s:string):string;
  108. var
  109. i,j : longint;
  110. begin
  111. i:=length(s);
  112. while (i>0) and (s[i] in [#9,' ']) do
  113. dec(i);
  114. j:=1;
  115. while (j<i) and (s[j] in [#9,' ']) do
  116. inc(j);
  117. trimspace:=Copy(s,j,i-j+1);
  118. end;
  119. function IsInList(const entry,list:string):boolean;
  120. var
  121. i,istart : longint;
  122. begin
  123. IsInList:=false;
  124. i:=0;
  125. while (i<length(list)) do
  126. begin
  127. { Find list item }
  128. istart:=i+1;
  129. while (i<length(list)) and
  130. (list[i+1]<>',') do
  131. inc(i);
  132. if Upcase(entry)=Upcase(TrimSpace(Copy(list,istart,i-istart+1))) then
  133. begin
  134. IsInList:=true;
  135. exit;
  136. end;
  137. { skip , }
  138. inc(i);
  139. end;
  140. end;
  141. procedure SetPPFileInfo;
  142. Var
  143. info : searchrec;
  144. dt : DateTime;
  145. begin
  146. FindFirst (PPFile,anyfile,Info);
  147. If DosError=0 then
  148. begin
  149. UnpackTime(info.time,dt);
  150. PPFileInfo:=PPFile+' '+ToStr(dt.year)+'/'+ToStrZero(dt.month,2)+'/'+
  151. ToStrZero(dt.day,2)+' '+ToStrZero(dt.Hour,2)+':'+ToStrZero(dt.min,2)+':'+ToStrZero(dt.sec,2);
  152. end
  153. else
  154. PPFileInfo:=PPfile;
  155. FindClose (Info);
  156. end;
  157. function SplitPath(const s:string):string;
  158. var
  159. i : longint;
  160. begin
  161. i:=Length(s);
  162. while (i>0) and not(s[i] in ['/','\']) do
  163. dec(i);
  164. SplitPath:=Copy(s,1,i);
  165. end;
  166. Function SplitFileName(const s:string):string;
  167. var
  168. p : dirstr;
  169. n : namestr;
  170. e : extstr;
  171. begin
  172. FSplit(s,p,n,e);
  173. SplitFileName:=n+e;
  174. end;
  175. function ForceExtension(Const HStr,ext:String):String;
  176. {
  177. Return a filename which certainly has the extension ext
  178. }
  179. var
  180. j : longint;
  181. begin
  182. j:=length(Hstr);
  183. while (j>0) and (Hstr[j]<>'.') do
  184. dec(j);
  185. if j=0 then
  186. j:=255;
  187. if Ext<>'' then
  188. ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext
  189. else
  190. ForceExtension:=Copy(Hstr,1,j-1);
  191. end;
  192. procedure mkdirtree(const s:string);
  193. var
  194. hs : string;
  195. begin
  196. if s='' then
  197. exit;
  198. if s[length(s)] in ['\','/'] then
  199. hs:=Copy(s,1,length(s)-1)
  200. else
  201. hs:=s;
  202. if not PathExists(hs) then
  203. begin
  204. { Try parent first }
  205. mkdirtree(SplitPath(hs));
  206. { make this dir }
  207. Verbose(V_Debug,'Making Directory '+s);
  208. {$I-}
  209. mkdir(s);
  210. {$I+}
  211. ioresult;
  212. end;
  213. end;
  214. Function RemoveFile(const f:string):boolean;
  215. var
  216. g : file;
  217. begin
  218. assign(g,f);
  219. {$I-}
  220. erase(g);
  221. {$I+}
  222. RemoveFile:=(ioresult=0);
  223. end;
  224. procedure Copyfile(const fn1,fn2:string;append:boolean);
  225. const
  226. bufsize = 16384;
  227. var
  228. f,g : file;
  229. i : longint;
  230. buf : pointer;
  231. begin
  232. if Append then
  233. Verbose(V_Debug,'Appending '+fn1+' to '+fn2)
  234. else
  235. Verbose(V_Debug,'Copying '+fn1+' to '+fn2);
  236. assign(f,fn1);
  237. assign(g,fn2);
  238. {$I-}
  239. reset(f,1);
  240. {$I+}
  241. if ioresult<>0 then
  242. Verbose(V_Error,'Can''t open '+fn1);
  243. if append then
  244. begin
  245. {$I-}
  246. reset(g,1);
  247. {$I+}
  248. if ioresult<>0 then
  249. append:=false
  250. else
  251. seek(g,filesize(g));
  252. end;
  253. if not append then
  254. begin
  255. {$I-}
  256. rewrite(g,1);
  257. {$I+}
  258. if ioresult<>0 then
  259. Verbose(V_Error,'Can''t open '+fn2+' for output');
  260. end;
  261. getmem(buf,bufsize);
  262. repeat
  263. blockread(f,buf^,bufsize,i);
  264. blockwrite(g,buf^,i);
  265. until i<bufsize;
  266. freemem(buf,bufsize);
  267. close(f);
  268. close(g);
  269. end;
  270. procedure AddLog(const logfile,s:string);
  271. var
  272. t : text;
  273. begin
  274. assign(t,logfile);
  275. {$I-}
  276. append(t);
  277. {$I+}
  278. if ioresult<>0 then
  279. begin
  280. {$I-}
  281. rewrite(t);
  282. {$I+}
  283. if ioresult<>0 then
  284. Verbose(V_Abort,'Can''t append to '+logfile);
  285. end;
  286. writeln(t,s);
  287. close(t);
  288. end;
  289. function GetCompilerInfo(c:tcompinfo):boolean;
  290. function GetToken(var s:string):string;
  291. var
  292. i : longint;
  293. begin
  294. i:=pos(' ',s);
  295. if i=0 then
  296. i:=length(s)+1;
  297. GetToken:=Copy(s,1,i-1);
  298. Delete(s,1,i);
  299. end;
  300. var
  301. t : text;
  302. hs : string;
  303. begin
  304. GetCompilerInfo:=false;
  305. { Try to get all information in one call, this is
  306. supported in 1.1. Older compilers 1.0.x will only
  307. return the first info }
  308. case c of
  309. compver :
  310. hs:='-iVTPTO';
  311. compcpu :
  312. hs:='-iTPTOV';
  313. comptarget :
  314. hs:='-iTOTPV';
  315. end;
  316. ExecuteRedir(CompilerBin,hs,'','out','');
  317. assign(t,'out');
  318. {$I-}
  319. reset(t);
  320. readln(t,hs);
  321. close(t);
  322. erase(t);
  323. {$I+}
  324. if ioresult<>0 then
  325. Verbose(V_Error,'Can''t get Compiler Info')
  326. else
  327. begin
  328. Verbose(V_Debug,'Retrieved Compiler Info: "'+hs+'"');
  329. case c of
  330. compver :
  331. begin
  332. CompilerVersion:=GetToken(hs);
  333. CompilerCPU:=GetToken(hs);
  334. CompilerTarget:=GetToken(hs);
  335. end;
  336. compcpu :
  337. begin
  338. CompilerCPU:=GetToken(hs);
  339. CompilerTarget:=GetToken(hs);
  340. CompilerVersion:=GetToken(hs);
  341. end;
  342. comptarget :
  343. begin
  344. CompilerTarget:=GetToken(hs);
  345. CompilerCPU:=GetToken(hs);
  346. CompilerVersion:=GetToken(hs);
  347. end;
  348. end;
  349. GetCompilerInfo:=true;
  350. end;
  351. end;
  352. function GetCompilerVersion:boolean;
  353. begin
  354. if CompilerVersion='' then
  355. GetCompilerVersion:=GetCompilerInfo(compver)
  356. else
  357. GetCompilerVersion:=true;
  358. if GetCompilerVersion then
  359. Verbose(V_Debug,'Compiler Version: "'+CompilerVersion+'"');
  360. end;
  361. function GetCompilerCPU:boolean;
  362. begin
  363. if CompilerCPU='' then
  364. GetCompilerCPU:=GetCompilerInfo(compcpu)
  365. else
  366. GetCompilerCPU:=true;
  367. if GetCompilerCPU then
  368. Verbose(V_Debug,'Compiler CPU: "'+CompilerCPU+'"');
  369. end;
  370. function GetCompilerTarget:boolean;
  371. begin
  372. if CompilerTarget='' then
  373. GetCompilerTarget:=GetCompilerInfo(comptarget)
  374. else
  375. GetCompilerTarget:=true;
  376. if GetCompilerTarget then
  377. Verbose(V_Debug,'Compiler Target: "'+CompilerTarget+'"');
  378. end;
  379. function CompilerFullTarget:string;
  380. begin
  381. CompilerFullTarget:=CompilerCPU+'-'+CompilerTarget;
  382. end;
  383. function OutputFileName(Const s,ext:String):String;
  384. begin
  385. OutputFileName:=OutputDir+'/'+ForceExtension(s,ext);
  386. end;
  387. function TestOutputFileName(Const s,ext:String):String;
  388. begin
  389. TestOutputFileName:=TestOutputDir+'/'+ForceExtension(SplitFileName(s),ext);
  390. end;
  391. function ExitWithInternalError(const OutName:string):boolean;
  392. var
  393. t : text;
  394. s : string;
  395. begin
  396. ExitWithInternalError:=false;
  397. { open logfile }
  398. assign(t,Outname);
  399. {$I-}
  400. reset(t);
  401. {$I+}
  402. if ioresult<>0 then
  403. exit;
  404. while not eof(t) do
  405. begin
  406. readln(t,s);
  407. if pos('Fatal: Internal error ',s)>0 then
  408. begin
  409. ExitWithInternalError:=true;
  410. break;
  411. end;
  412. end;
  413. close(t);
  414. end;
  415. function RunCompiler:boolean;
  416. var
  417. args : string;
  418. execres : boolean;
  419. begin
  420. RunCompiler:=false;
  421. args:='-n -Fu'+RTLUnitsDir;
  422. args:=args+' -FE'+TestOutputDir;
  423. if ExtraCompilerOpts<>'' then
  424. args:=args+ExtraCompilerOpts;
  425. {$ifdef unix}
  426. { Add runtime library path to current dir to find .so files }
  427. if Config.NeedLibrary then
  428. args:=args+' -Fl'+TestOutputDir+' ''-k-rpath .''';
  429. {$endif unix}
  430. if Config.NeedOptions<>'' then
  431. args:=args+' '+Config.NeedOptions;
  432. args:=args+' '+ppfile;
  433. Verbose(V_Debug,'Executing '+compilerbin+' '+args);
  434. { also get the output from as and ld that writes to stderr sometimes }
  435. execres:=ExecuteRedir(CompilerBin,args,'',CompilerLogFile,'stdout');
  436. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  437. { Error during execution? }
  438. if (not execres) and (ExecuteResult=0) then
  439. begin
  440. AddLog(FailLogFile,TestName);
  441. AddLog(ResLogFile,failed_to_compile+PPFileInfo);
  442. AddLog(LongLogFile,line_separation);
  443. AddLog(LongLogFile,failed_to_compile+PPFileInfo);
  444. CopyFile(CompilerLogFile,LongLogFile,true);
  445. { avoid to try again }
  446. AddLog(ExeLogFile,failed_to_compile+PPFileInfo);
  447. Verbose(V_Abort,'IOStatus: '+ToStr(IOStatus));
  448. exit;
  449. end;
  450. { Check for internal error }
  451. if ExitWithInternalError(CompilerLogFile) then
  452. begin
  453. AddLog(FailLogFile,TestName);
  454. if Config.Note<>'' then
  455. AddLog(FailLogFile,Config.Note);
  456. AddLog(ResLogFile,failed_to_compile+PPFileInfo+' internalerror generated');
  457. AddLog(LongLogFile,line_separation);
  458. AddLog(LongLogFile,failed_to_compile+PPFileInfo);
  459. if Config.Note<>'' then
  460. AddLog(LongLogFile,Config.Note);
  461. CopyFile(CompilerLogFile,LongLogFile,true);
  462. { avoid to try again }
  463. AddLog(ExeLogFile,'Failed to compile '++PPFileInfo);
  464. Verbose(V_Abort,'Internal error in compiler');
  465. exit;
  466. end;
  467. { Shoud the compile fail ? }
  468. if Config.ShouldFail then
  469. begin
  470. if ExecuteResult<>0 then
  471. begin
  472. AddLog(ResLogFile,success_compilation_failed+PPFileInfo);
  473. { avoid to try again }
  474. AddLog(ExeLogFile,success_compilation_failed+PPFileInfo);
  475. RunCompiler:=true;
  476. end
  477. else
  478. begin
  479. AddLog(FailLogFile,TestName);
  480. if Config.Note<>'' then
  481. AddLog(FailLogFile,Config.Note);
  482. AddLog(ResLogFile,failed_compilation_successful+PPFileInfo);
  483. AddLog(LongLogFile,line_separation);
  484. AddLog(LongLogFile,failed_compilation_successful+PPFileInfo);
  485. { avoid to try again }
  486. AddLog(ExeLogFile,failed_compilation_successful+PPFileInfo);
  487. if Config.Note<>'' then
  488. AddLog(LongLogFile,Config.Note);
  489. CopyFile(CompilerLogFile,LongLogFile,true);
  490. end;
  491. end
  492. else
  493. begin
  494. if (ExecuteResult<>0) and
  495. (((Config.KnownCompileNote<>'') and (Config.KnownCompileError=0)) or
  496. ((Config.KnownCompileError<>0) and (ExecuteResult=Config.KnownCompileError))) then
  497. begin
  498. AddLog(FailLogFile,TestName+known_problem+Config.KnownCompileNote);
  499. AddLog(ResLogFile,failed_to_run+PPFileInfo+known_problem+Config.KnownCompileNote);
  500. AddLog(LongLogFile,line_separation);
  501. AddLog(LongLogFile,known_problem+Config.KnownCompileNote);
  502. AddLog(LongLogFile,failed_to_compile+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  503. Copyfile(CompilerLogFile,LongLogFile,true);
  504. Verbose(V_Abort,known_problem+'exitcode: '+ToStr(ExecuteResult));
  505. end
  506. else if ExecuteResult<>0 then
  507. begin
  508. AddLog(FailLogFile,TestName);
  509. if Config.Note<>'' then
  510. AddLog(FailLogFile,Config.Note);
  511. AddLog(ResLogFile,failed_to_compile+PPFileInfo);
  512. AddLog(LongLogFile,line_separation);
  513. AddLog(LongLogFile,failed_to_compile+PPFileInfo);
  514. if Config.Note<>'' then
  515. AddLog(LongLogFile,Config.Note);
  516. CopyFile(CompilerLogFile,LongLogFile,true);
  517. { avoid to try again }
  518. AddLog(ExeLogFile,failed_to_compile+PPFileInfo);
  519. Verbose(V_Abort,'Exitcode: '+ToStr(ExecuteResult)+' (expected 0)');
  520. end
  521. else
  522. begin
  523. AddLog(ResLogFile,successfully_compiled+PPFileInfo);
  524. RunCompiler:=true;
  525. end;
  526. end;
  527. end;
  528. function CheckTestExitCode(const OutName:string):boolean;
  529. var
  530. t : text;
  531. s : string;
  532. i,code : integer;
  533. begin
  534. CheckTestExitCode:=false;
  535. { open logfile }
  536. assign(t,Outname);
  537. {$I-}
  538. reset(t);
  539. {$I+}
  540. if ioresult<>0 then
  541. exit;
  542. while not eof(t) do
  543. begin
  544. readln(t,s);
  545. i:=pos('TestExitCode: ',s);
  546. if i>0 then
  547. begin
  548. delete(s,1,i+14-1);
  549. val(s,ExecuteResult,code);
  550. if code=0 then;
  551. CheckTestExitCode:=true;
  552. break;
  553. end;
  554. end;
  555. close(t);
  556. end;
  557. function RunExecutable:boolean;
  558. const
  559. {$ifdef unix}
  560. CurrDir = './';
  561. {$else}
  562. CurrDir = '';
  563. {$endif}
  564. var
  565. OldDir,
  566. FullExeLogFile,
  567. TestRemoteExe,
  568. TestExe : string;
  569. execres : boolean;
  570. function ExecuteRemote(const prog,args:string):boolean;
  571. begin
  572. Verbose(V_Debug,'RemoteExecuting '+Prog+' '+args);
  573. ExecuteRemote:=ExecuteRedir(prog,args,'',EXELogFile,'stdout');
  574. end;
  575. function ExecuteEmulated(const prog,args:string):boolean;
  576. begin
  577. Verbose(V_Debug,'EmulatorExecuting '+Prog+' '+args);
  578. ExecuteEmulated:=ExecuteRedir(prog,args,'',FullExeLogFile,'stdout');
  579. end;
  580. begin
  581. RunExecutable:=false;
  582. execres:=true;
  583. { when remote testing, leave extension away }
  584. if RemoteAddr='' then
  585. TestExe:=OutputFileName(PPFile,ExeExt)
  586. else
  587. TestExe:=OutputFileName(PPFile,'');
  588. if EmulatorName<>'' then
  589. begin
  590. { Get full name out log file, because we change the directory during
  591. execution }
  592. FullExeLogFile:=FExpand(EXELogFile);
  593. {$I-}
  594. GetDir(0,OldDir);
  595. ChDir(TestOutputDir);
  596. {$I+}
  597. ioresult;
  598. execres:=ExecuteEmulated(EmulatorName,CurrDir+SplitFileName(TestExe));
  599. {$I-}
  600. ChDir(OldDir);
  601. {$I+}
  602. end
  603. else if RemoteAddr<>'' then
  604. begin
  605. { We don't want to create subdirs, remove paths from the test }
  606. TestRemoteExe:=RemotePath+'/'+SplitFileName(TestExe);
  607. ExecuteRemote(rshprog,RemotePara+' '+RemoteAddr+' rm -f '+TestRemoteExe);
  608. ExecuteRemote(rcpprog,RemotePara+' '+TestExe+' '+RemoteAddr+':'+TestRemoteExe);
  609. { rsh doesn't pass the exitcode, use a second command to print the exitcode
  610. on the remoteshell to stdout }
  611. execres:=ExecuteRemote(rshprog,RemotePara+' '+RemoteAddr+' '+rquote+'chmod 755 '+TestRemoteExe+
  612. ' ; cd '+RemotePath+' ; '+TestRemoteExe+' ; echo "TestExitCode: $?"'+rquote);
  613. { Check for TestExitCode error in output, sets ExecuteResult }
  614. CheckTestExitCode(EXELogFile);
  615. end
  616. else
  617. begin
  618. { Get full name out log file, because we change the directory during
  619. execution }
  620. FullExeLogFile:=FExpand(EXELogFile);
  621. Verbose(V_Debug,'Executing '+TestExe);
  622. {$I-}
  623. GetDir(0,OldDir);
  624. ChDir(TestOutputDir);
  625. {$I+}
  626. ioresult;
  627. { don't redirect interactive and graph programs }
  628. if Config.IsInteractive or Config.UsesGraph then
  629. execres:=ExecuteRedir(CurrDir+SplitFileName(TestExe),'','','','')
  630. else
  631. execres:=ExecuteRedir(CurrDir+SplitFileName(TestExe),'','',FullExeLogFile,'stdout');
  632. {$I-}
  633. ChDir(OldDir);
  634. {$I+}
  635. ioresult;
  636. end;
  637. { Error during execution? }
  638. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  639. if (not execres) and (ExecuteResult=0) then
  640. begin
  641. AddLog(FailLogFile,TestName);
  642. AddLog(ResLogFile,failed_to_run+PPFileInfo);
  643. AddLog(LongLogFile,line_separation);
  644. AddLog(LongLogFile,failed_to_run+PPFileInfo);
  645. CopyFile(EXELogFile,LongLogFile,true);
  646. { avoid to try again }
  647. AddLog(ExeLogFile,failed_to_run+PPFileInfo);
  648. Verbose(V_Abort,'IOStatus: '+ToStr(IOStatus));
  649. exit;
  650. end;
  651. if ExecuteResult<>Config.ResultCode then
  652. begin
  653. if (ExecuteResult<>0) and
  654. (ExecuteResult=Config.KnownRunError) then
  655. begin
  656. AddLog(FailLogFile,TestName+known_problem+Config.KnownRunNote);
  657. AddLog(ResLogFile,failed_to_run+PPFileInfo+known_problem+Config.KnownRunNote);
  658. AddLog(LongLogFile,line_separation);
  659. AddLog(LongLogFile,known_problem+Config.KnownRunNote);
  660. AddLog(LongLogFile,failed_to_run+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  661. Copyfile(EXELogFile,LongLogFile,true);
  662. Verbose(V_Abort,known_problem+'exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  663. end
  664. else
  665. begin
  666. AddLog(FailLogFile,TestName);
  667. AddLog(ResLogFile,failed_to_run+PPFileInfo);
  668. AddLog(LongLogFile,line_separation);
  669. AddLog(LongLogFile,failed_to_run+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  670. Copyfile(EXELogFile,LongLogFile,true);
  671. Verbose(V_Abort,'Exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  672. end
  673. end
  674. else
  675. begin
  676. AddLog(ResLogFile,successfully_run+PPFileInfo);
  677. RunExecutable:=true;
  678. end;
  679. if DelExecutable then
  680. begin
  681. Verbose(V_Debug,'Deleting executable '+TestExe);
  682. if RemoteAddr<>'' then
  683. ExecuteRemote(rshprog,RemotePara+' '+RemoteAddr+' rm -f '+TestRemoteExe);
  684. RemoveFile(TestExe);
  685. RemoveFile(ForceExtension(TestExe,ObjExt));
  686. RemoveFile(ForceExtension(TestExe,PPUExt));
  687. end;
  688. end;
  689. procedure getargs;
  690. var
  691. ch : char;
  692. para : string;
  693. i : longint;
  694. procedure helpscreen;
  695. begin
  696. writeln('dotest [Options] <File>');
  697. writeln;
  698. writeln('Options can be:');
  699. writeln(' -C<compiler> set compiler to use');
  700. writeln(' -V verbose');
  701. writeln(' -E execute test also');
  702. writeln(' -X don''t use COMSPEC');
  703. writeln(' -A include ALL tests');
  704. writeln(' -G include graph tests');
  705. writeln(' -K include known bug tests');
  706. writeln(' -I include interactive tests');
  707. writeln(' -M<emulator> run the tests using the given emulator');
  708. writeln(' -R<remote> run the tests remotely with the given rsh/ssh address');
  709. writeln(' -S use ssh instead of rsh');
  710. writeln(' -T remove temporary files (executable,ppu,o)');
  711. writeln(' -P<path> path to the tests tree on the remote machine');
  712. writeln(' -U<remotepara>');
  713. writeln(' pass additional parameter to remove program. Multiple -U can be used');
  714. writeln(' -V be verbose');
  715. writeln(' -W use putty compatible file names when testing (plink and pscp)');
  716. writeln(' -Y<opts> extra options passed to the compiler. Several -Y<opt> can be given.');
  717. halt(1);
  718. end;
  719. begin
  720. PPFile:='';
  721. if exeext<>'' then
  722. CompilerBin:='ppc386.'+exeext
  723. else
  724. CompilerBin:='ppc386';
  725. for i:=1 to paramcount do
  726. begin
  727. para:=Paramstr(i);
  728. if (para[1]='-') then
  729. begin
  730. ch:=Upcase(para[2]);
  731. delete(para,1,2);
  732. case ch of
  733. 'A' :
  734. begin
  735. DoGraph:=true;
  736. DoInteractive:=true;
  737. DoKnown:=true;
  738. DoAll:=true;
  739. end;
  740. 'C' : CompilerBin:=Para;
  741. 'E' : DoExecute:=true;
  742. 'G' : begin
  743. DoGraph:=true;
  744. if para='-' then
  745. DoUsual:=false;
  746. end;
  747. 'I' : begin
  748. DoInteractive:=true;
  749. if para='-' then
  750. DoUsual:=false;
  751. end;
  752. 'K' : begin
  753. DoKnown:=true;
  754. if para='-' then
  755. DoUsual:=false;
  756. end;
  757. 'M' : EmulatorName:=Para;
  758. 'P' : RemotePath:=Para;
  759. 'R' : RemoteAddr:=Para;
  760. 'S' :
  761. begin
  762. rshprog:='ssh';
  763. rcpprog:='scp';
  764. end;
  765. 'T' :
  766. DelExecutable:=true;
  767. 'U' :
  768. RemotePara:=+RemotePara+' '+Para;
  769. 'V' : DoVerbose:=true;
  770. 'W' :
  771. begin
  772. rshprog:='plink';
  773. rcpprog:='pscp';
  774. rquote:=' ';
  775. end;
  776. 'X' : UseComSpec:=false;
  777. 'Y' : ExtraCompilerOpts:= ExtraCompilerOpts +' '+ Para;
  778. end;
  779. end
  780. else
  781. begin
  782. If PPFile<>'' then
  783. HelpScreen;
  784. PPFile:=ForceExtension(Para,'pp');
  785. end;
  786. end;
  787. if (PPFile='') then
  788. HelpScreen;
  789. { disable graph,interactive when running remote }
  790. if RemoteAddr<>'' then
  791. begin
  792. DoGraph:=false;
  793. DoInteractive:=false;
  794. end;
  795. SetPPFileInfo;
  796. TestName:=Copy(PPFile,1,Pos('.pp',PPFile)-1);
  797. Verbose(V_Debug,'Running test '+TestName+', file '+PPFile);
  798. end;
  799. procedure RunTest;
  800. var
  801. PPDir : string;
  802. Res : boolean;
  803. begin
  804. Res:=GetConfig(ppfile,Config);
  805. if Res then
  806. begin
  807. Res:=GetCompilerCPU;
  808. Res:=GetCompilerTarget;
  809. RTLUnitsDir:='units/'+{$ifdef LIMIT83FS}CompilerTarget{$else}CompilerFullTarget{$endif};
  810. if not PathExists(RTLUnitsDir) then
  811. Verbose(V_Abort,'Unit path "'+RTLUnitsDir+'" does not exists');
  812. OutputDir:='output/'+{$ifdef LIMIT83FS}CompilerTarget{$else}CompilerFullTarget{$endif};
  813. if not PathExists(OutputDir) then
  814. Verbose(V_Abort,'Output path "'+OutputDir+'" does not exists');
  815. { Global log files }
  816. ResLogFile:=OutputFileName('log','');
  817. LongLogFile:=OutputFileName('longlog','');
  818. FailLogFile:=OutputFileName('faillist','');
  819. { Make subdir in output if needed }
  820. PPDir:=SplitPath(PPFile);
  821. if PPDir[length(PPDir)] in ['/','\'] then
  822. Delete(PPDir,length(PPDir),1);
  823. if PPDir<>'' then
  824. begin
  825. TestOutputDir:=OutputDir+'/'+PPDir;
  826. mkdirtree(TestOutputDir);
  827. end
  828. else
  829. TestOutputDir:=OutputDir;
  830. { Per test logfiles }
  831. CompilerLogFile:=TestOutputFileName(SplitFileName(PPFile),'log');
  832. ExeLogFile:=TestOutputFileName(SplitFileName(PPFile),'elg');
  833. Verbose(V_Debug,'Using Compiler logfile: '+CompilerLogFile);
  834. Verbose(V_Debug,'Using Execution logfile: '+ExeLogFile);
  835. end;
  836. if Res then
  837. begin
  838. if Config.UsesGraph and (not DoGraph) then
  839. begin
  840. AddLog(ResLogFile,skipping_graph_test+PPFileInfo);
  841. { avoid a second attempt by writing to elg file }
  842. AddLog(EXELogFile,skipping_graph_test+PPFileInfo);
  843. Verbose(V_Abort,skipping_graph_test);
  844. Res:=false;
  845. end;
  846. end;
  847. if Res then
  848. begin
  849. if Config.IsInteractive and (not DoInteractive) then
  850. begin
  851. { avoid a second attempt by writing to elg file }
  852. AddLog(EXELogFile,skipping_interactive_test+PPFileInfo);
  853. AddLog(ResLogFile,skipping_interactive_test+PPFileInfo);
  854. Verbose(V_Abort,skipping_interactive_test);
  855. Res:=false;
  856. end;
  857. end;
  858. if Res then
  859. begin
  860. if Config.IsKnownCompileError and (not DoKnown) then
  861. begin
  862. { avoid a second attempt by writing to elg file }
  863. AddLog(EXELogFile,skipping_known_bug+PPFileInfo);
  864. AddLog(ResLogFile,skipping_known_bug+PPFileInfo);
  865. Verbose(V_Abort,skipping_known_bug);
  866. Res:=false;
  867. end;
  868. end;
  869. if Res and not DoUsual then
  870. res:=(Config.IsInteractive and DoInteractive) or
  871. (Config.IsKnownRunError and DoKnown) or
  872. (Config.UsesGraph and DoGraph);
  873. if Res then
  874. begin
  875. if (Config.MinVersion<>'') and not DoAll then
  876. begin
  877. Verbose(V_Debug,'Required compiler version: '+Config.MinVersion);
  878. Res:=GetCompilerVersion;
  879. if CompilerVersion<Config.MinVersion then
  880. begin
  881. { avoid a second attempt by writing to elg file }
  882. AddLog(EXELogFile,skipping_compiler_version_too_low+PPFileInfo);
  883. AddLog(ResLogFile,skipping_compiler_version_too_low+PPFileInfo);
  884. Verbose(V_Abort,'Compiler version too low '+CompilerVersion+' < '+Config.MinVersion);
  885. Res:=false;
  886. end;
  887. end;
  888. end;
  889. if Res then
  890. begin
  891. if (Config.MaxVersion<>'') and not DoAll then
  892. begin
  893. Verbose(V_Debug,'Highest compiler version: '+Config.MaxVersion);
  894. Res:=GetCompilerVersion;
  895. if CompilerVersion>Config.MaxVersion then
  896. begin
  897. { avoid a second attempt by writing to elg file }
  898. AddLog(EXELogFile,skipping_compiler_version_too_high+PPFileInfo);
  899. AddLog(ResLogFile,skipping_compiler_version_too_high+PPFileInfo);
  900. Verbose(V_Abort,'Compiler version too high '+CompilerVersion+' > '+Config.MaxVersion);
  901. Res:=false;
  902. end;
  903. end;
  904. end;
  905. if Res then
  906. begin
  907. if Config.NeedCPU<>'' then
  908. begin
  909. Verbose(V_Debug,'Required compiler cpu: '+Config.NeedCPU);
  910. if not IsInList(CompilerCPU,Config.NeedCPU) then
  911. begin
  912. { avoid a second attempt by writing to elg file }
  913. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo);
  914. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo);
  915. Verbose(V_Abort,'Compiler cpu "'+CompilerCPU+'" is not in list "'+Config.NeedCPU+'"');
  916. Res:=false;
  917. end;
  918. end;
  919. end;
  920. if Res then
  921. begin
  922. if Config.SkipCPU<>'' then
  923. begin
  924. Verbose(V_Debug,'Skip compiler cpu: '+Config.NeedCPU);
  925. if IsInList(CompilerCPU,Config.SkipCPU) then
  926. begin
  927. { avoid a second attempt by writing to elg file }
  928. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo);
  929. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo);
  930. Verbose(V_Abort,'Compiler cpu "'+CompilerCPU+'" is in list "'+Config.SkipCPU+'"');
  931. Res:=false;
  932. end;
  933. end;
  934. end;
  935. if Res then
  936. begin
  937. if Config.NeedTarget<>'' then
  938. begin
  939. Verbose(V_Debug,'Required compiler target: '+Config.NeedTarget);
  940. if not IsInList(CompilerTarget,Config.NeedTarget) then
  941. begin
  942. { avoid a second attempt by writing to elg file }
  943. AddLog(EXELogFile,skipping_other_target+PPFileInfo);
  944. AddLog(ResLogFile,skipping_other_target+PPFileInfo);
  945. Verbose(V_Abort,'Compiler target "'+CompilerTarget+'" is not in list "'+Config.NeedTarget+'"');
  946. Res:=false;
  947. end;
  948. end;
  949. end;
  950. if Res then
  951. begin
  952. if Config.SkipTarget<>'' then
  953. begin
  954. Verbose(V_Debug,'Skip compiler target: '+Config.NeedTarget);
  955. if IsInList(CompilerTarget,Config.SkipTarget) then
  956. begin
  957. { avoid a second attempt by writing to elg file }
  958. AddLog(EXELogFile,skipping_other_target+PPFileInfo);
  959. AddLog(ResLogFile,skipping_other_target+PPFileInfo);
  960. Verbose(V_Abort,'Compiler target "'+CompilerTarget+'" is in list "'+Config.SkipTarget+'"');
  961. Res:=false;
  962. end;
  963. end;
  964. end;
  965. if Res then
  966. begin
  967. Res:=RunCompiler;
  968. if Res and Config.NeedRecompile then
  969. Res:=RunCompiler;
  970. end;
  971. if Res then
  972. begin
  973. if (Config.NoRun) then
  974. begin
  975. { avoid a second attempt by writing to elg file }
  976. AddLog(EXELogFile,skipping_run_test+PPFileInfo);
  977. AddLog(ResLogFile,skipping_run_test+PPFileInfo);
  978. Verbose(V_Debug,skipping_run_test);
  979. end
  980. else if Config.IsKnownRunError and (not DoKnown) then
  981. begin
  982. { avoid a second attempt by writing to elg file }
  983. AddLog(EXELogFile,skipping_known_bug+PPFileInfo);
  984. AddLog(ResLogFile,skipping_known_bug+PPFileInfo);
  985. Verbose(V_Abort,skipping_known_bug);
  986. end
  987. else
  988. begin
  989. if (not Config.ShouldFail) and DoExecute then
  990. begin
  991. if FileExists(TestOutputFilename(PPFile,'ppu')) or
  992. FileExists(TestOutputFilename(PPFile,'ppo')) or
  993. FileExists(TestOutputFilename(PPFile,'ppw')) then
  994. begin
  995. AddLog(ExeLogFile,skipping_run_unit+PPFileInfo);
  996. AddLog(ResLogFile,skipping_run_unit+PPFileInfo);
  997. Verbose(V_Debug,'Unit found, skipping run test')
  998. end
  999. else
  1000. Res:=RunExecutable;
  1001. end;
  1002. end;
  1003. end;
  1004. end;
  1005. begin
  1006. GetArgs;
  1007. RunTest;
  1008. end.
  1009. {
  1010. $Log$
  1011. Revision 1.43 2005-01-01 18:59:52 florian
  1012. + emulator execution support added
  1013. Revision 1.42 2004/11/29 21:25:32 peter
  1014. support for limit83fs
  1015. Revision 1.41 2004/11/09 23:13:50 peter
  1016. * fixed library tests
  1017. * fix test cases to generate their own temporary files
  1018. Revision 1.40 2004/11/09 21:26:29 peter
  1019. * use ./ before executable under unix
  1020. Revision 1.39 2004/11/09 17:26:28 peter
  1021. * use separate output dirs
  1022. * same tree can be used for multiple targets
  1023. Revision 1.38 2004/09/30 15:38:59 peter
  1024. * chdir to remote path before executing test
  1025. Revision 1.37 2004/07/03 18:28:21 florian
  1026. + added support of putty utils to dotest
  1027. + remote testing executes a chmod 755 before running a test
  1028. Revision 1.36 2004/05/17 20:51:29 peter
  1029. * print exitcode of remote test to stdout and parse the output file.
  1030. this is the most reliable passing of the exitcode
  1031. Revision 1.35 2004/05/16 20:13:04 peter
  1032. * remote execute updates, see readme.txt
  1033. Revision 1.34 2004/05/03 14:48:51 peter
  1034. * support redir from stderr to stdout so the same file can be used
  1035. Revision 1.33 2004/05/02 09:31:52 peter
  1036. * remove failed_to_execute_ strings, use the failed_to_run
  1037. Revision 1.32 2004/04/29 21:41:44 peter
  1038. * test result of execution and report as failure with iostatus displayed
  1039. Revision 1.31 2004/04/01 12:51:32 olle
  1040. + Several -Y<opt> is now allowed
  1041. Revision 1.30 2004/03/21 19:15:18 florian
  1042. * explanation for running the testsuite remotely
  1043. + dotest supports remote execution using scp/ssh
  1044. Revision 1.29 2003/10/31 16:14:20 peter
  1045. * remove compileerror10, note10
  1046. * remove known, use knowncompileerror,knownrunerror instead
  1047. * knowncompileerror,knownrunerror tests are now really skipped
  1048. Revision 1.28 2003/10/13 14:19:02 peter
  1049. * digest updated for max version limit
  1050. Revision 1.27 2003/06/13 08:16:34 pierre
  1051. * fix a problem with KNOWNCOMPILE10ERROR
  1052. Revision 1.26 2003/02/20 12:41:15 pierre
  1053. + handle KNOWNCOMPILEERROR and KNOWNCOMPILE10ERROR
  1054. Revision 1.25 2002/12/24 22:30:41 peter
  1055. * small verbosity update
  1056. Revision 1.24 2002/12/24 21:47:49 peter
  1057. * NeedTarget, SkipTarget, SkipCPU added
  1058. * Retrieve compiler info in a single call for 1.1 compiler
  1059. Revision 1.23 2002/12/17 15:04:32 michael
  1060. + Added dbdigest to store results in a database
  1061. Revision 1.22 2002/12/15 13:30:46 peter
  1062. * NEEDLIBRARY option to add -rpath to the linker for unix. This is
  1063. needed to test runtime library tests. The library needs the -FE.
  1064. option to place the .so in the correct directory
  1065. Revision 1.21 2002/12/05 16:03:34 pierre
  1066. + -X option to disable UseComSpec
  1067. Revision 1.20 2002/11/18 16:42:43 pierre
  1068. + KNOWNRUNERROR added
  1069. Revision 1.19 2002/11/18 01:31:07 pierre
  1070. + use -n option
  1071. + use -G- for only graph
  1072. + use -I- for only interactive
  1073. + use -K- for only known bugs.
  1074. Revision 1.18 2002/11/14 10:36:12 pierre
  1075. * add internalerror info to log file
  1076. Revision 1.17 2002/11/13 15:26:24 pierre
  1077. + digest program added
  1078. Revision 1.16 2002/11/13 15:19:44 pierre
  1079. log strings moved to teststr unit
  1080. Revision 1.15 2002/09/07 15:40:56 peter
  1081. * old logs removed and tabs fixed
  1082. Revision 1.14 2002/04/21 18:15:32 peter
  1083. * Check for internal errors
  1084. Revision 1.13 2002/03/03 13:27:28 hajny
  1085. + added support for OS/2 units (.ppo)
  1086. Revision 1.12 2002/01/29 13:24:16 pierre
  1087. + also generate .elg file for units
  1088. Revision 1.11 2002/01/29 12:51:08 pierre
  1089. + PPFileInfo to also display time stamp of test file
  1090. * generate .elg file in several cases
  1091. to avoid trying to recompute the same test
  1092. over and over again.
  1093. }