dotest.pp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  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 : string;
  472. execres : boolean;
  473. begin
  474. RunCompiler:=false;
  475. args:='-n -T'+CompilerTarget+' -Fu'+RTLUnitsDir;
  476. args:=args+' -FE'+TestOutputDir;
  477. {$ifdef macos}
  478. args:=args+' -WT '; {tests should be compiled as MPWTool}
  479. {$endif macos}
  480. if ExtraCompilerOpts<>'' then
  481. args:=args+ExtraCompilerOpts;
  482. {$ifdef unix}
  483. { Add runtime library path to current dir to find .so files }
  484. if Config.NeedLibrary then
  485. {$ifndef darwin}
  486. args:=args+' -Fl'+TestOutputDir+' ''-k-rpath .''';
  487. {$else darwin}
  488. args:=args+' -Fl'+TestOutputDir;
  489. {$endif darwin}
  490. {$endif unix}
  491. if Config.NeedOptions<>'' then
  492. args:=args+' '+Config.NeedOptions;
  493. args:=args+' '+ppfile;
  494. Verbose(V_Debug,'Executing '+compilerbin+' '+args);
  495. { also get the output from as and ld that writes to stderr sometimes }
  496. {$ifndef macos}
  497. execres:=ExecuteRedir(CompilerBin,args,'',CompilerLogFile,'stdout');
  498. {$else macos}
  499. {Due to that Toolserver is not reentrant, we have to asm and link via script.}
  500. execres:=ExecuteRedir(CompilerBin,'-s '+args,'',CompilerLogFile,'stdout');
  501. if execres then
  502. execres:=ExecuteRedir(TestOutputDir + ':ppas','','',CompilerLogFile,'stdout');
  503. {$endif macos}
  504. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  505. { Error during execution? }
  506. if (not execres) and (ExecuteResult=0) then
  507. begin
  508. AddLog(FailLogFile,TestName);
  509. AddLog(ResLogFile,failed_to_compile+PPFileInfo);
  510. AddLog(LongLogFile,line_separation);
  511. AddLog(LongLogFile,failed_to_compile+PPFileInfo);
  512. CopyFile(CompilerLogFile,LongLogFile,true);
  513. { avoid to try again }
  514. AddLog(ExeLogFile,failed_to_compile+PPFileInfo);
  515. Verbose(V_Abort,'IOStatus: '+ToStr(IOStatus));
  516. exit;
  517. end;
  518. { Check for internal error }
  519. if ExitWithInternalError(CompilerLogFile) then
  520. begin
  521. AddLog(FailLogFile,TestName);
  522. if Config.Note<>'' then
  523. AddLog(FailLogFile,Config.Note);
  524. AddLog(ResLogFile,failed_to_compile+PPFileInfo+' internalerror generated');
  525. AddLog(LongLogFile,line_separation);
  526. AddLog(LongLogFile,failed_to_compile+PPFileInfo);
  527. if Config.Note<>'' then
  528. AddLog(LongLogFile,Config.Note);
  529. CopyFile(CompilerLogFile,LongLogFile,true);
  530. { avoid to try again }
  531. AddLog(ExeLogFile,'Failed to compile '+PPFileInfo);
  532. Verbose(V_Abort,'Internal error in compiler');
  533. exit;
  534. end;
  535. { Should the compile fail ? }
  536. if Config.ShouldFail then
  537. begin
  538. if ExecuteResult<>0 then
  539. begin
  540. AddLog(ResLogFile,success_compilation_failed+PPFileInfo);
  541. { avoid to try again }
  542. AddLog(ExeLogFile,success_compilation_failed+PPFileInfo);
  543. RunCompiler:=true;
  544. end
  545. else
  546. begin
  547. AddLog(FailLogFile,TestName);
  548. if Config.Note<>'' then
  549. AddLog(FailLogFile,Config.Note);
  550. AddLog(ResLogFile,failed_compilation_successful+PPFileInfo);
  551. AddLog(LongLogFile,line_separation);
  552. AddLog(LongLogFile,failed_compilation_successful+PPFileInfo);
  553. { avoid to try again }
  554. AddLog(ExeLogFile,failed_compilation_successful+PPFileInfo);
  555. if Config.Note<>'' then
  556. AddLog(LongLogFile,Config.Note);
  557. CopyFile(CompilerLogFile,LongLogFile,true);
  558. end;
  559. end
  560. else
  561. begin
  562. if (ExecuteResult<>0) and
  563. (((Config.KnownCompileNote<>'') and (Config.KnownCompileError=0)) or
  564. ((Config.KnownCompileError<>0) and (ExecuteResult=Config.KnownCompileError))) then
  565. begin
  566. AddLog(FailLogFile,TestName+known_problem+Config.KnownCompileNote);
  567. AddLog(ResLogFile,failed_to_run+PPFileInfo+known_problem+Config.KnownCompileNote);
  568. AddLog(LongLogFile,line_separation);
  569. AddLog(LongLogFile,known_problem+Config.KnownCompileNote);
  570. AddLog(LongLogFile,failed_to_compile+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  571. Copyfile(CompilerLogFile,LongLogFile,true);
  572. Verbose(V_Abort,known_problem+'exitcode: '+ToStr(ExecuteResult));
  573. end
  574. else if ExecuteResult<>0 then
  575. begin
  576. AddLog(FailLogFile,TestName);
  577. if Config.Note<>'' then
  578. AddLog(FailLogFile,Config.Note);
  579. AddLog(ResLogFile,failed_to_compile+PPFileInfo);
  580. AddLog(LongLogFile,line_separation);
  581. AddLog(LongLogFile,failed_to_compile+PPFileInfo);
  582. if Config.Note<>'' then
  583. AddLog(LongLogFile,Config.Note);
  584. CopyFile(CompilerLogFile,LongLogFile,true);
  585. { avoid to try again }
  586. AddLog(ExeLogFile,failed_to_compile+PPFileInfo);
  587. Verbose(V_Abort,'Exitcode: '+ToStr(ExecuteResult)+' (expected 0)');
  588. end
  589. else
  590. begin
  591. AddLog(ResLogFile,successfully_compiled+PPFileInfo);
  592. RunCompiler:=true;
  593. end;
  594. end;
  595. end;
  596. function CheckTestExitCode(const OutName:string):boolean;
  597. var
  598. t : text;
  599. s : string;
  600. i,code : integer;
  601. begin
  602. CheckTestExitCode:=false;
  603. { open logfile }
  604. assign(t,Outname);
  605. {$I-}
  606. reset(t);
  607. {$I+}
  608. if ioresult<>0 then
  609. exit;
  610. while not eof(t) do
  611. begin
  612. readln(t,s);
  613. i:=pos('TestExitCode: ',s);
  614. if i>0 then
  615. begin
  616. delete(s,1,i+14-1);
  617. val(s,ExecuteResult,code);
  618. if code=0 then;
  619. CheckTestExitCode:=true;
  620. break;
  621. end;
  622. end;
  623. close(t);
  624. end;
  625. function RunExecutable:boolean;
  626. const
  627. {$ifdef unix}
  628. CurrDir = './';
  629. {$else}
  630. CurrDir = '';
  631. {$endif}
  632. var
  633. s,
  634. OldDir,
  635. FullExeLogFile,
  636. TestRemoteExe,
  637. TestExe : string;
  638. execcmd : string;
  639. execres : boolean;
  640. EndTicks,
  641. StartTicks : int64;
  642. function ExecuteRemote(const prog,args:string):boolean;
  643. begin
  644. Verbose(V_Debug,'RemoteExecuting '+Prog+' '+args);
  645. StartTicks:=GetMicroSTicks;
  646. ExecuteRemote:=ExecuteRedir(prog,args,'',EXELogFile,'stdout');
  647. EndTicks:=GetMicroSTicks;
  648. end;
  649. function ExecuteEmulated(const prog,args:string):boolean;
  650. begin
  651. Verbose(V_Debug,'EmulatorExecuting '+Prog+' '+args);
  652. StartTicks:=GetMicroSTicks;
  653. ExecuteEmulated:=ExecuteRedir(prog,args,'',FullExeLogFile,'stdout');
  654. EndTicks:=GetMicroSTicks;
  655. end;
  656. begin
  657. RunExecutable:=false;
  658. execres:=true;
  659. { when remote testing, leave extension away }
  660. if RemoteAddr='' then
  661. TestExe:=OutputFileName(PPFile,ExeExt)
  662. else
  663. TestExe:=OutputFileName(PPFile,'');
  664. if EmulatorName<>'' then
  665. begin
  666. { Get full name out log file, because we change the directory during
  667. execution }
  668. FullExeLogFile:=FExpand(EXELogFile);
  669. {$I-}
  670. GetDir(0,OldDir);
  671. ChDir(TestOutputDir);
  672. {$I+}
  673. ioresult;
  674. s:=CurrDir+SplitFileName(TestExe);
  675. execres:=ExecuteEmulated(EmulatorName,s);
  676. {$I-}
  677. ChDir(OldDir);
  678. {$I+}
  679. end
  680. else if RemoteAddr<>'' then
  681. begin
  682. { We don't want to create subdirs, remove paths from the test }
  683. TestRemoteExe:=RemotePath+'/'+SplitFileName(TestExe);
  684. if deBefore in DelExecutable then
  685. ExecuteRemote(rshprog,RemotePara+' '+RemoteAddr+' rm -f '+TestRemoteExe);
  686. ExecuteRemote(rcpprog,RemotePara+' '+TestExe+' '+RemoteAddr+':'+TestRemoteExe);
  687. { rsh doesn't pass the exitcode, use a second command to print the exitcode
  688. on the remoteshell to stdout }
  689. execcmd:=RemotePara+' '+RemoteAddr+' '+rquote+'chmod 755 '+TestRemoteExe+
  690. ' ; cd '+RemotePath+' ;';
  691. if UseTimeout then
  692. begin
  693. execcmd:=execcmd+'timeout -9 ';
  694. if Config.Timeout=0 then
  695. Config.Timeout:=DefaultTimeout;
  696. str(Config.Timeout,s);
  697. execcmd:=execcmd+s;
  698. end;
  699. execcmd:=execcmd+' '+TestRemoteExe+' ; echo "TestExitCode: $?"';
  700. if deAfter in DelExecutable then
  701. execcmd:=execcmd+' ; rm -f '+TestRemoteExe;
  702. execcmd:=execcmd+rquote;
  703. execres:=ExecuteRemote(rshprog,execcmd);
  704. { Check for TestExitCode error in output, sets ExecuteResult }
  705. CheckTestExitCode(EXELogFile);
  706. end
  707. else
  708. begin
  709. { Get full name out log file, because we change the directory during
  710. execution }
  711. FullExeLogFile:=FExpand(EXELogFile);
  712. Verbose(V_Debug,'Executing '+TestExe);
  713. {$I-}
  714. GetDir(0,OldDir);
  715. ChDir(TestOutputDir);
  716. {$I+}
  717. ioresult;
  718. { don't redirect interactive and graph programs }
  719. StartTicks:=GetMicroSTicks;
  720. if Config.IsInteractive or Config.UsesGraph then
  721. execres:=ExecuteRedir(CurrDir+SplitFileName(TestExe),'','','','')
  722. else
  723. execres:=ExecuteRedir(CurrDir+SplitFileName(TestExe),'','',FullExeLogFile,'stdout');
  724. EndTicks:=GetMicroSTicks;
  725. {$I-}
  726. ChDir(OldDir);
  727. {$I+}
  728. ioresult;
  729. end;
  730. { Error during execution? }
  731. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  732. if BenchmarkInfo then
  733. begin
  734. Verbose(V_Normal,'Execution took '+ToStr(EndTicks-StartTicks)+' us');
  735. end;
  736. if (not execres) and (ExecuteResult=0) then
  737. begin
  738. AddLog(FailLogFile,TestName);
  739. AddLog(ResLogFile,failed_to_run+PPFileInfo);
  740. AddLog(LongLogFile,line_separation);
  741. AddLog(LongLogFile,failed_to_run+PPFileInfo);
  742. CopyFile(EXELogFile,LongLogFile,true);
  743. { avoid to try again }
  744. AddLog(ExeLogFile,failed_to_run+PPFileInfo);
  745. Verbose(V_Abort,'IOStatus: '+ToStr(IOStatus));
  746. exit;
  747. end;
  748. if ExecuteResult<>Config.ResultCode then
  749. begin
  750. if (ExecuteResult<>0) and
  751. (ExecuteResult=Config.KnownRunError) then
  752. begin
  753. AddLog(FailLogFile,TestName+known_problem+Config.KnownRunNote);
  754. AddLog(ResLogFile,failed_to_run+PPFileInfo+known_problem+Config.KnownRunNote);
  755. AddLog(LongLogFile,line_separation);
  756. AddLog(LongLogFile,known_problem+Config.KnownRunNote);
  757. AddLog(LongLogFile,failed_to_run+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  758. Copyfile(EXELogFile,LongLogFile,true);
  759. Verbose(V_Abort,known_problem+'exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  760. end
  761. else
  762. begin
  763. AddLog(FailLogFile,TestName);
  764. AddLog(ResLogFile,failed_to_run+PPFileInfo);
  765. AddLog(LongLogFile,line_separation);
  766. AddLog(LongLogFile,failed_to_run+PPFileInfo+' ('+ToStr(ExecuteResult)+')');
  767. Copyfile(EXELogFile,LongLogFile,true);
  768. Verbose(V_Abort,'Exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  769. end
  770. end
  771. else
  772. begin
  773. AddLog(ResLogFile,successfully_run+PPFileInfo);
  774. RunExecutable:=true;
  775. end;
  776. if deAfter in DelExecutable then
  777. begin
  778. Verbose(V_Debug,'Deleting executable '+TestExe);
  779. RemoveFile(TestExe);
  780. RemoveFile(ForceExtension(TestExe,ObjExt));
  781. RemoveFile(ForceExtension(TestExe,PPUExt));
  782. end;
  783. end;
  784. procedure getargs;
  785. var
  786. ch : char;
  787. para : string;
  788. i,j : longint;
  789. procedure helpscreen;
  790. begin
  791. writeln('dotest [Options] <File>');
  792. writeln;
  793. writeln('Options can be:');
  794. writeln(' -B delete executable before remote upload');
  795. writeln(' -C<compiler> set compiler to use');
  796. writeln(' -V verbose');
  797. writeln(' -E execute test also');
  798. writeln(' -X don''t use COMSPEC');
  799. writeln(' -A include ALL tests');
  800. writeln(' -G include graph tests');
  801. writeln(' -K include known bug tests');
  802. writeln(' -I include interactive tests');
  803. writeln(' -O use timeout wrapper for (remote) execution');
  804. writeln(' -M<emulator> run the tests using the given emulator');
  805. writeln(' -R<remote> run the tests remotely with the given rsh/ssh address');
  806. writeln(' -S use ssh instead of rsh');
  807. writeln(' -T[cpu-]<os> run tests for target cpu and os');
  808. writeln(' -P<path> path to the tests tree on the remote machine');
  809. writeln(' -U<remotepara>');
  810. writeln(' pass additional parameter to remote program. Multiple -U can be used');
  811. writeln(' -V be verbose');
  812. writeln(' -W use putty compatible file names when testing (plink and pscp)');
  813. writeln(' -Y<opts> extra options passed to the compiler. Several -Y<opt> can be given.');
  814. writeln(' -Z remove temporary files (executable,ppu,o)');
  815. halt(1);
  816. end;
  817. begin
  818. PPFile:='';
  819. if exeext<>'' then
  820. CompilerBin:='ppc386.'+exeext
  821. else
  822. CompilerBin:='ppc386';
  823. for i:=1 to paramcount do
  824. begin
  825. para:=Paramstr(i);
  826. if (para[1]='-') then
  827. begin
  828. ch:=Upcase(para[2]);
  829. delete(para,1,2);
  830. case ch of
  831. 'A' :
  832. begin
  833. DoGraph:=true;
  834. DoInteractive:=true;
  835. DoKnown:=true;
  836. DoAll:=true;
  837. end;
  838. 'B' : Include(DelExecutable,deBefore);
  839. 'C' : CompilerBin:=Para;
  840. 'E' : DoExecute:=true;
  841. 'G' : begin
  842. DoGraph:=true;
  843. if para='-' then
  844. DoUsual:=false;
  845. end;
  846. 'I' : begin
  847. DoInteractive:=true;
  848. if para='-' then
  849. DoUsual:=false;
  850. end;
  851. 'K' : begin
  852. DoKnown:=true;
  853. if para='-' then
  854. DoUsual:=false;
  855. end;
  856. 'M' : EmulatorName:=Para;
  857. 'O' : UseTimeout:=true;
  858. 'P' : RemotePath:=Para;
  859. 'R' : RemoteAddr:=Para;
  860. 'S' :
  861. begin
  862. rshprog:='ssh';
  863. rcpprog:='scp';
  864. end;
  865. 'T' :
  866. begin
  867. j:=Pos('-',Para);
  868. if j>0 then
  869. begin
  870. CompilerCPU:=Copy(Para,1,j-1);
  871. CompilerTarget:=Copy(Para,j+1,255);
  872. end
  873. else
  874. CompilerTarget:=Para
  875. end;
  876. 'U' :
  877. RemotePara:=RemotePara+' '+Para;
  878. 'V' : DoVerbose:=true;
  879. 'W' :
  880. begin
  881. rshprog:='plink';
  882. rcpprog:='pscp';
  883. rquote:=' ';
  884. end;
  885. 'X' : UseComSpec:=false;
  886. 'Y' : ExtraCompilerOpts:= ExtraCompilerOpts +' '+ Para;
  887. 'Z' : Include(DelExecutable,deAfter);
  888. end;
  889. end
  890. else
  891. begin
  892. If PPFile<>'' then
  893. HelpScreen;
  894. PPFile:=ForceExtension(Para,'pp');
  895. end;
  896. end;
  897. if (PPFile='') then
  898. HelpScreen;
  899. { disable graph,interactive when running remote }
  900. if RemoteAddr<>'' then
  901. begin
  902. DoGraph:=false;
  903. DoInteractive:=false;
  904. end;
  905. SetPPFileInfo;
  906. TestName:=Copy(PPFile,1,Pos('.pp',PPFile)-1);
  907. Verbose(V_Debug,'Running test '+TestName+', file '+PPFile);
  908. end;
  909. procedure RunTest;
  910. var
  911. PPDir : string;
  912. Res : boolean;
  913. begin
  914. Res:=GetConfig(ppfile,Config);
  915. if Res then
  916. begin
  917. Res:=GetCompilerCPU;
  918. Res:=GetCompilerTarget;
  919. {$ifndef MACOS}
  920. RTLUnitsDir:='units/'+{$ifdef LIMIT83FS}CompilerTarget{$else}CompilerFullTarget{$endif};
  921. {$else MACOS}
  922. RTLUnitsDir:=':units:'+CompilerFullTarget;
  923. {$endif MACOS}
  924. if not PathExists(RTLUnitsDir) then
  925. Verbose(V_Abort,'Unit path "'+RTLUnitsDir+'" does not exists');
  926. {$ifndef MACOS}
  927. OutputDir:='output/'+{$ifdef LIMIT83FS}CompilerTarget{$else}CompilerFullTarget{$endif};
  928. {$else MACOS}
  929. OutputDir:=':output:'+CompilerFullTarget;
  930. {$endif MACOS}
  931. if not PathExists(OutputDir) then
  932. Verbose(V_Abort,'Output path "'+OutputDir+'" does not exists');
  933. { Global log files }
  934. ResLogFile:=OutputFileName('log','');
  935. LongLogFile:=OutputFileName('longlog','');
  936. FailLogFile:=OutputFileName('faillist','');
  937. { Make subdir in output if needed }
  938. PPDir:=SplitPath(PPFile);
  939. if PPDir[length(PPDir)] in ['/','\'{$ifdef MACOS},':'{$endif MACOS}] then
  940. Delete(PPDir,length(PPDir),1);
  941. if PPDir<>'' then
  942. begin
  943. {$ifndef MACOS}
  944. TestOutputDir:=OutputDir+'/'+PPDir;
  945. {$else MACOS}
  946. TestOutputDir:=OutputDir+PPDir;
  947. {$endif MACOS}
  948. mkdirtree(TestOutputDir);
  949. end
  950. else
  951. TestOutputDir:=OutputDir;
  952. { Per test logfiles }
  953. CompilerLogFile:=TestOutputFileName(SplitFileName(PPFile),'log');
  954. ExeLogFile:=TestOutputFileName(SplitFileName(PPFile),'elg');
  955. Verbose(V_Debug,'Using Compiler logfile: '+CompilerLogFile);
  956. Verbose(V_Debug,'Using Execution logfile: '+ExeLogFile);
  957. end;
  958. if Res then
  959. begin
  960. if Config.UsesGraph and (not DoGraph) then
  961. begin
  962. AddLog(ResLogFile,skipping_graph_test+PPFileInfo);
  963. { avoid a second attempt by writing to elg file }
  964. AddLog(EXELogFile,skipping_graph_test+PPFileInfo);
  965. Verbose(V_Abort,skipping_graph_test);
  966. Res:=false;
  967. end;
  968. end;
  969. if Res then
  970. begin
  971. if Config.IsInteractive and (not DoInteractive) then
  972. begin
  973. { avoid a second attempt by writing to elg file }
  974. AddLog(EXELogFile,skipping_interactive_test+PPFileInfo);
  975. AddLog(ResLogFile,skipping_interactive_test+PPFileInfo);
  976. Verbose(V_Abort,skipping_interactive_test);
  977. Res:=false;
  978. end;
  979. end;
  980. if Res then
  981. begin
  982. if Config.IsKnownCompileError and (not DoKnown) then
  983. begin
  984. { avoid a second attempt by writing to elg file }
  985. AddLog(EXELogFile,skipping_known_bug+PPFileInfo);
  986. AddLog(ResLogFile,skipping_known_bug+PPFileInfo);
  987. Verbose(V_Abort,skipping_known_bug);
  988. Res:=false;
  989. end;
  990. end;
  991. if Res and not DoUsual then
  992. res:=(Config.IsInteractive and DoInteractive) or
  993. (Config.IsKnownRunError and DoKnown) or
  994. (Config.UsesGraph and DoGraph);
  995. if Res then
  996. begin
  997. if (Config.MinVersion<>'') and not DoAll then
  998. begin
  999. Verbose(V_Debug,'Required compiler version: '+Config.MinVersion);
  1000. Res:=GetCompilerVersion;
  1001. if CompilerVersion<Config.MinVersion then
  1002. begin
  1003. { avoid a second attempt by writing to elg file }
  1004. AddLog(EXELogFile,skipping_compiler_version_too_low+PPFileInfo);
  1005. AddLog(ResLogFile,skipping_compiler_version_too_low+PPFileInfo);
  1006. Verbose(V_Abort,'Compiler version too low '+CompilerVersion+' < '+Config.MinVersion);
  1007. Res:=false;
  1008. end;
  1009. end;
  1010. end;
  1011. if Res then
  1012. begin
  1013. if (Config.MaxVersion<>'') and not DoAll then
  1014. begin
  1015. Verbose(V_Debug,'Highest compiler version: '+Config.MaxVersion);
  1016. Res:=GetCompilerVersion;
  1017. if CompilerVersion>Config.MaxVersion then
  1018. begin
  1019. { avoid a second attempt by writing to elg file }
  1020. AddLog(EXELogFile,skipping_compiler_version_too_high+PPFileInfo);
  1021. AddLog(ResLogFile,skipping_compiler_version_too_high+PPFileInfo);
  1022. Verbose(V_Abort,'Compiler version too high '+CompilerVersion+' > '+Config.MaxVersion);
  1023. Res:=false;
  1024. end;
  1025. end;
  1026. end;
  1027. if Res then
  1028. begin
  1029. if Config.NeedCPU<>'' then
  1030. begin
  1031. Verbose(V_Debug,'Required compiler cpu: '+Config.NeedCPU);
  1032. if not IsInList(CompilerCPU,Config.NeedCPU) then
  1033. begin
  1034. { avoid a second attempt by writing to elg file }
  1035. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo);
  1036. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo);
  1037. Verbose(V_Abort,'Compiler cpu "'+CompilerCPU+'" is not in list "'+Config.NeedCPU+'"');
  1038. Res:=false;
  1039. end;
  1040. end;
  1041. end;
  1042. if Res then
  1043. begin
  1044. if Config.SkipCPU<>'' then
  1045. begin
  1046. Verbose(V_Debug,'Skip compiler cpu: '+Config.SkipCPU);
  1047. if IsInList(CompilerCPU,Config.SkipCPU) then
  1048. begin
  1049. { avoid a second attempt by writing to elg file }
  1050. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo);
  1051. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo);
  1052. Verbose(V_Abort,'Compiler cpu "'+CompilerCPU+'" is in list "'+Config.SkipCPU+'"');
  1053. Res:=false;
  1054. end;
  1055. end;
  1056. end;
  1057. if Res then
  1058. begin
  1059. if Config.SkipEmu<>'' then
  1060. begin
  1061. Verbose(V_Debug,'Skip emulator: '+emulatorname);
  1062. if IsInList(emulatorname,Config.SkipEmu) then
  1063. begin
  1064. { avoid a second attempt by writing to elg file }
  1065. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo);
  1066. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo);
  1067. Verbose(V_Abort,'Emulator "'+emulatorname+'" is in list "'+Config.SkipEmu+'"');
  1068. Res:=false;
  1069. end;
  1070. end;
  1071. end;
  1072. if Res then
  1073. begin
  1074. if Config.NeedTarget<>'' then
  1075. begin
  1076. Verbose(V_Debug,'Required compiler target: '+Config.NeedTarget);
  1077. if not IsInList(CompilerTarget,Config.NeedTarget) then
  1078. begin
  1079. { avoid a second attempt by writing to elg file }
  1080. AddLog(EXELogFile,skipping_other_target+PPFileInfo);
  1081. AddLog(ResLogFile,skipping_other_target+PPFileInfo);
  1082. Verbose(V_Abort,'Compiler target "'+CompilerTarget+'" is not in list "'+Config.NeedTarget+'"');
  1083. Res:=false;
  1084. end;
  1085. end;
  1086. end;
  1087. if Res then
  1088. begin
  1089. if Config.SkipTarget<>'' then
  1090. begin
  1091. Verbose(V_Debug,'Skip compiler target: '+Config.NeedTarget);
  1092. if IsInList(CompilerTarget,Config.SkipTarget) then
  1093. begin
  1094. { avoid a second attempt by writing to elg file }
  1095. AddLog(EXELogFile,skipping_other_target+PPFileInfo);
  1096. AddLog(ResLogFile,skipping_other_target+PPFileInfo);
  1097. Verbose(V_Abort,'Compiler target "'+CompilerTarget+'" is in list "'+Config.SkipTarget+'"');
  1098. Res:=false;
  1099. end;
  1100. end;
  1101. end;
  1102. if Res then
  1103. begin
  1104. Res:=RunCompiler;
  1105. if Res and Config.NeedRecompile then
  1106. Res:=RunCompiler;
  1107. end;
  1108. if Res and (not Config.ShouldFail) then
  1109. begin
  1110. if (Config.NoRun) then
  1111. begin
  1112. { avoid a second attempt by writing to elg file }
  1113. AddLog(EXELogFile,skipping_run_test+PPFileInfo);
  1114. AddLog(ResLogFile,skipping_run_test+PPFileInfo);
  1115. Verbose(V_Debug,skipping_run_test);
  1116. end
  1117. else if Config.IsKnownRunError and (not DoKnown) then
  1118. begin
  1119. { avoid a second attempt by writing to elg file }
  1120. AddLog(EXELogFile,skipping_known_bug+PPFileInfo);
  1121. AddLog(ResLogFile,skipping_known_bug+PPFileInfo);
  1122. Verbose(V_Abort,skipping_known_bug);
  1123. end
  1124. else
  1125. begin
  1126. if DoExecute then
  1127. begin
  1128. if FileExists(TestOutputFilename(PPFile,'ppu')) or
  1129. FileExists(TestOutputFilename(PPFile,'ppo')) or
  1130. FileExists(TestOutputFilename(PPFile,'ppw')) then
  1131. begin
  1132. AddLog(ExeLogFile,skipping_run_unit+PPFileInfo);
  1133. AddLog(ResLogFile,skipping_run_unit+PPFileInfo);
  1134. Verbose(V_Debug,'Unit found, skipping run test')
  1135. end
  1136. else
  1137. Res:=RunExecutable;
  1138. end;
  1139. end;
  1140. end;
  1141. end;
  1142. begin
  1143. GetArgs;
  1144. RunTest;
  1145. end.