dotest.pp 41 KB

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