dotest.pp 34 KB

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