dotest.pp 34 KB

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