dotest.pp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012
  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. {$mode objfpc}
  13. {$goto on}
  14. {$H+}
  15. program dotest;
  16. uses
  17. sysutils,
  18. dos,
  19. {$ifdef macos}
  20. macutils,
  21. {$endif}
  22. teststr,
  23. testu,
  24. redir,
  25. bench,
  26. classes;
  27. {$ifdef go32v2}
  28. {$define LIMIT83FS}
  29. {$endif}
  30. {$ifdef os2}
  31. {$define LIMIT83FS}
  32. {$endif}
  33. type
  34. tcompinfo = (compver,comptarget,compcpu);
  35. tdelexecutable = (deBefore, deAfter);
  36. tdelexecutables = set of tdelexecutable;
  37. const
  38. ObjExt='o';
  39. PPUExt='ppu';
  40. {$ifdef UNIX}
  41. SrcExeExt='';
  42. {$else UNIX}
  43. {$ifdef MACOS}
  44. SrcExeExt='';
  45. {$else MACOS}
  46. SrcExeExt='.exe';
  47. {$endif MACOS}
  48. {$endif UNIX}
  49. ExeExt : string = '';
  50. DefaultTimeout=60;
  51. var
  52. Config : TConfig;
  53. CompilerLogFile,
  54. ExeLogFile,
  55. LongLogfile,
  56. FailLogfile,
  57. RTLUnitsDir,
  58. TestOutputDir,
  59. OutputDir : string;
  60. CompilerBin,
  61. { CompilerCPU and CompilerTarget are lowercased at start
  62. to avoid need to call lowercase again and again ... }
  63. CompilerCPU,
  64. CompilerTarget,
  65. CompilerVersion,
  66. DefaultCompilerCPU,
  67. DefaultCompilerTarget,
  68. DefaultCompilerVersion : string;
  69. PPFile : TStringList;
  70. PPFileInfo : TStringList;
  71. TestName : string;
  72. Current : longint;
  73. const
  74. DoGraph : boolean = false;
  75. UseOSOnly : boolean = false;
  76. DoInteractive : boolean = false;
  77. DoExecute : boolean = false;
  78. DoKnown : boolean = false;
  79. DoAll : boolean = false;
  80. DoUsual : boolean = true;
  81. { TargetDir : string = ''; unused }
  82. BenchmarkInfo : boolean = false;
  83. ExtraCompilerOpts : string = '';
  84. DelExecutable : TDelExecutables = [];
  85. RemoteAddr : string = '';
  86. RemotePathPrefix : string = '';
  87. RemotePath : string = '/tmp';
  88. RemotePara : string = '';
  89. RemoteRshParas : string = '';
  90. RemoteShell : string = '';
  91. RemoteShellBase : string = '';
  92. RemoteShellNeedsExport : boolean = false;
  93. rshprog : string = 'rsh';
  94. rcpprog : string = 'rcp';
  95. rquote : string = '''';
  96. UseTimeout : boolean = false;
  97. emulatorname : string = '';
  98. TargetCanCompileLibraries : boolean = true;
  99. UniqueSuffix: string = '';
  100. { Constants used in IsAbsolute function }
  101. TargetHasDosStyleDirectories : boolean = false;
  102. TargetAmigaLike : boolean = false;
  103. TargetIsMacOS : boolean = false;
  104. TargetIsUnix : boolean = false;
  105. { extracted from rtl/macos/macutils.inc }
  106. function IsMacFullPath (const path: string): Boolean;
  107. begin
  108. if Pos(':', path) = 0 then {its partial}
  109. IsMacFullPath := false
  110. else if path[1] = ':' then
  111. IsMacFullPath := false
  112. else
  113. IsMacFullPath := true
  114. end;
  115. Function IsAbsolute (Const F : String) : boolean;
  116. {
  117. Returns True if the name F is a absolute file name
  118. }
  119. begin
  120. IsAbsolute:=false;
  121. if TargetHasDosStyleDirectories then
  122. begin
  123. if (F[1]='/') or (F[1]='\') then
  124. IsAbsolute:=true;
  125. if (Length(F)>2) and (F[2]=':') and ((F[3]='\') or (F[3]='/')) then
  126. IsAbsolute:=true;
  127. end
  128. else if TargetAmigaLike then
  129. begin
  130. if (length(F)>0) and (Pos(':',F) <> 0) then
  131. IsAbsolute:=true;
  132. end
  133. else if TargetIsMacOS then
  134. begin
  135. IsAbsolute:=IsMacFullPath(F);
  136. end
  137. { generic case }
  138. else if (F[1]='/') then
  139. IsAbsolute:=true;
  140. end;
  141. Function FileExists (Const F : String) : Boolean;
  142. {
  143. Returns True if the file exists, False if not.
  144. }
  145. Var
  146. info : searchrec;
  147. begin
  148. FindFirst (F,anyfile,Info);
  149. FileExists:=DosError=0;
  150. FindClose (Info);
  151. end;
  152. Function PathExists (Const F : String) : Boolean;
  153. {
  154. Returns True if the file exists, False if not.
  155. }
  156. Var
  157. info : searchrec;
  158. begin
  159. FindFirst (F,anyfile,Info);
  160. PathExists:=(DosError=0) and (Info.Attr and Directory=Directory);
  161. FindClose (Info);
  162. end;
  163. function ToStr(l:longint):string;
  164. var
  165. s : string;
  166. begin
  167. Str(l,s);
  168. ToStr:=s;
  169. end;
  170. function ToStrZero(l:longint;nbzero : byte):string;
  171. var
  172. s : string;
  173. begin
  174. Str(l,s);
  175. while length(s)<nbzero do
  176. s:='0'+s;
  177. ToStrZero:=s;
  178. end;
  179. function trimspace(const s:string):string;
  180. var
  181. i,j : longint;
  182. begin
  183. i:=length(s);
  184. while (i>0) and (s[i] in [#9,' ']) do
  185. dec(i);
  186. j:=1;
  187. while (j<i) and (s[j] in [#9,' ']) do
  188. inc(j);
  189. trimspace:=Copy(s,j,i-j+1);
  190. end;
  191. function IsInList(const entry,list:string):boolean;
  192. var
  193. i,istart : longint;
  194. begin
  195. IsInList:=false;
  196. i:=0;
  197. while (i<length(list)) do
  198. begin
  199. { Find list item }
  200. istart:=i+1;
  201. while (i<length(list)) and
  202. (list[i+1]<>',') do
  203. inc(i);
  204. if Upcase(entry)=Upcase(TrimSpace(Copy(list,istart,i-istart+1))) then
  205. begin
  206. IsInList:=true;
  207. exit;
  208. end;
  209. { skip , }
  210. inc(i);
  211. end;
  212. end;
  213. procedure SetPPFileInfo;
  214. Var
  215. info : searchrec;
  216. dt : DateTime;
  217. begin
  218. FindFirst (PPFile[current],anyfile,Info);
  219. If DosError=0 then
  220. begin
  221. UnpackTime(info.time,dt);
  222. PPFileInfo.Insert(current,PPFile[current]+' '+ToStr(dt.year)+'/'+ToStrZero(dt.month,2)+'/'+
  223. ToStrZero(dt.day,2)+' '+ToStrZero(dt.Hour,2)+':'+ToStrZero(dt.min,2)+':'+ToStrZero(dt.sec,2));
  224. end
  225. else
  226. PPFileInfo.Insert(current,PPFile[current]);
  227. FindClose (Info);
  228. end;
  229. function SplitPath(const s:string):string;
  230. var
  231. i : longint;
  232. begin
  233. i:=Length(s);
  234. while (i>0) and not(s[i] in ['/','\'{$IFDEF MACOS},':'{$ENDIF}]) do
  235. dec(i);
  236. SplitPath:=Copy(s,1,i);
  237. end;
  238. function SplitBasePath(const s:string): string;
  239. var
  240. i : longint;
  241. begin
  242. i:=1;
  243. while (i<length(s)) and not(s[i] in ['/','\'{$IFDEF MACOS},':'{$ENDIF}]) do
  244. inc(i);
  245. if s[i] in ['/','\'{$IFDEF MACOS},':'{$ENDIF}] then
  246. dec(i);
  247. SplitBasePath:=Copy(s,1,i);
  248. end;
  249. Function SplitFileName(const s:string):string;
  250. var
  251. p : dirstr;
  252. n : namestr;
  253. e : extstr;
  254. begin
  255. FSplit(s,p,n,e);
  256. SplitFileName:=n+e;
  257. end;
  258. Function SplitFileBase(const s:string):string;
  259. var
  260. p : dirstr;
  261. n : namestr;
  262. e : extstr;
  263. begin
  264. FSplit(s,p,n,e);
  265. SplitFileBase:=n;
  266. end;
  267. function ForceExtension(Const HStr,ext:String):String;
  268. {
  269. Return a filename which certainly has the extension ext
  270. }
  271. var
  272. j : longint;
  273. begin
  274. j:=length(Hstr);
  275. while (j>0) and (Hstr[j]<>'.') do
  276. dec(j);
  277. if j=0 then
  278. j:=length(Hstr)+1;
  279. if Ext<>'' then
  280. begin
  281. if Ext[1]='.' then
  282. ForceExtension:=Copy(Hstr,1,j-1)+Ext
  283. else
  284. ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext
  285. end
  286. else
  287. ForceExtension:=Copy(Hstr,1,j-1);
  288. end;
  289. procedure mkdirtree(const s:string);
  290. var
  291. hs : string;
  292. begin
  293. if s='' then
  294. exit;
  295. if s[length(s)] in ['\','/'{$IFDEF MACOS},':'{$ENDIF}] then
  296. hs:=Copy(s,1,length(s)-1)
  297. else
  298. hs:=s;
  299. if not PathExists(hs) then
  300. begin
  301. { Try parent first }
  302. mkdirtree(SplitPath(hs));
  303. { make this dir }
  304. Verbose(V_Debug,'Making Directory '+s);
  305. {$I-}
  306. mkdir(s);
  307. {$I+}
  308. ioresult;
  309. end;
  310. end;
  311. Function RemoveFile(const f:string):boolean;
  312. var
  313. g : file;
  314. begin
  315. assign(g,f);
  316. {$I-}
  317. erase(g);
  318. {$I+}
  319. RemoveFile:=(ioresult=0);
  320. end;
  321. function Copyfile(const fn1,fn2:string;append:boolean) : longint;
  322. const
  323. bufsize = 16384;
  324. var
  325. f,g : file;
  326. addsize,
  327. i : longint;
  328. buf : pointer;
  329. begin
  330. if Append then
  331. Verbose(V_Debug,'Appending '+fn1+' to '+fn2)
  332. else
  333. Verbose(V_Debug,'Copying '+fn1+' to '+fn2);
  334. assign(f,fn1);
  335. assign(g,fn2);
  336. {$I-}
  337. reset(f,1);
  338. {$I+}
  339. addsize:=0;
  340. if ioresult<>0 then
  341. Verbose(V_Error,'Can''t open '+fn1);
  342. if append then
  343. begin
  344. {$I-}
  345. reset(g,1);
  346. {$I+}
  347. if ioresult<>0 then
  348. append:=false
  349. else
  350. seek(g,filesize(g));
  351. end;
  352. if not append then
  353. begin
  354. {$I-}
  355. rewrite(g,1);
  356. {$I+}
  357. if ioresult<>0 then
  358. Verbose(V_Error,'Can''t open '+fn2+' for output');
  359. end;
  360. getmem(buf,bufsize);
  361. repeat
  362. blockread(f,buf^,bufsize,i);
  363. blockwrite(g,buf^,i);
  364. addsize:=addsize+i;
  365. until i<bufsize;
  366. freemem(buf,bufsize);
  367. close(f);
  368. close(g);
  369. CopyFile:=addsize;
  370. end;
  371. procedure AddLog(const logfile,s:string);
  372. var
  373. t : text;
  374. begin
  375. assign(t,logfile);
  376. {$I-}
  377. append(t);
  378. {$I+}
  379. if ioresult<>0 then
  380. begin
  381. {$I-}
  382. rewrite(t);
  383. {$I+}
  384. if ioresult<>0 then
  385. Verbose(V_Abort,'Can''t append to '+logfile);
  386. end;
  387. writeln(t,s);
  388. close(t);
  389. end;
  390. procedure ForceLog(const logfile:string);
  391. var
  392. t : text;
  393. begin
  394. assign(t,logfile);
  395. {$I-}
  396. append(t);
  397. {$I+}
  398. if ioresult<>0 then
  399. begin
  400. {$I-}
  401. rewrite(t);
  402. {$I+}
  403. if ioresult<>0 then
  404. Verbose(V_Abort,'Can''t Create '+logfile);
  405. end;
  406. close(t);
  407. end;
  408. function GetCompilerInfo(c:tcompinfo):boolean;
  409. function GetToken(var s:string):string;
  410. var
  411. i : longint;
  412. begin
  413. i:=pos(' ',s);
  414. if i=0 then
  415. i:=length(s)+1;
  416. GetToken:=Copy(s,1,i-1);
  417. Delete(s,1,i);
  418. end;
  419. var
  420. t : text;
  421. hs : string;
  422. begin
  423. GetCompilerInfo:=false;
  424. { Try to get all information in one call, this is
  425. supported in 1.1. Older compilers 1.0.x will only
  426. return the first info }
  427. case c of
  428. compver :
  429. begin
  430. if DefaultCompilerVersion<>'' then
  431. begin
  432. GetCompilerInfo:=true;
  433. exit;
  434. end;
  435. hs:='-iVTPTO';
  436. end;
  437. compcpu :
  438. begin
  439. if DefaultCompilerCPU<>'' then
  440. begin
  441. GetCompilerInfo:=true;
  442. exit;
  443. end;
  444. hs:='-iTPTOV';
  445. end;
  446. comptarget :
  447. begin
  448. if DefaultCompilerTarget<>'' then
  449. begin
  450. GetCompilerInfo:=true;
  451. exit;
  452. end;
  453. hs:='-iTOTPV';
  454. end;
  455. end;
  456. ExecuteRedir(CompilerBin,hs,'','out.'+UniqueSuffix,'');
  457. assign(t,'out.'+UniqueSuffix);
  458. {$I-}
  459. reset(t);
  460. readln(t,hs);
  461. close(t);
  462. erase(t);
  463. {$I+}
  464. if ioresult<>0 then
  465. Verbose(V_Error,'Can''t get Compiler Info')
  466. else
  467. begin
  468. Verbose(V_Debug,'Retrieved Compiler Info: "'+hs+'"');
  469. case c of
  470. compver :
  471. begin
  472. DefaultCompilerVersion:=GetToken(hs);
  473. DefaultCompilerCPU:=GetToken(hs);
  474. DefaultCompilerTarget:=GetToken(hs);
  475. end;
  476. compcpu :
  477. begin
  478. DefaultCompilerCPU:=GetToken(hs);
  479. DefaultCompilerTarget:=GetToken(hs);
  480. DefaultCompilerVersion:=GetToken(hs);
  481. end;
  482. comptarget :
  483. begin
  484. DefaultCompilerTarget:=GetToken(hs);
  485. DefaultCompilerCPU:=GetToken(hs);
  486. DefaultCompilerVersion:=GetToken(hs);
  487. end;
  488. end;
  489. GetCompilerInfo:=true;
  490. end;
  491. end;
  492. function GetCompilerVersion:boolean;
  493. const
  494. CompilerVersionDebugWritten : boolean = false;
  495. begin
  496. if CompilerVersion='' then
  497. begin
  498. GetCompilerVersion:=GetCompilerInfo(compver);
  499. CompilerVersion:=DefaultCompilerVersion;
  500. end
  501. else
  502. GetCompilerVersion:=true;
  503. if GetCompilerVersion and not CompilerVersionDebugWritten then
  504. begin
  505. Verbose(V_Debug,'Compiler Version: "'+CompilerVersion+'"');
  506. CompilerVersionDebugWritten:=true;
  507. end;
  508. end;
  509. function GetCompilerCPU:boolean;
  510. const
  511. CompilerCPUDebugWritten : boolean = false;
  512. begin
  513. if CompilerCPU='' then
  514. begin
  515. GetCompilerCPU:=GetCompilerInfo(compcpu);
  516. CompilerCPU:=lowercase(DefaultCompilerCPU);
  517. end
  518. else
  519. GetCompilerCPU:=true;
  520. if GetCompilerCPU and not CompilerCPUDebugWritten then
  521. begin
  522. Verbose(V_Debug,'Compiler CPU: "'+CompilerCPU+'"');
  523. CompilerCPUDebugWritten:=true;
  524. end;
  525. end;
  526. function GetCompilerTarget:boolean;
  527. const
  528. CompilerTargetDebugWritten : boolean = false;
  529. begin
  530. if CompilerTarget='' then
  531. begin
  532. GetCompilerTarget:=GetCompilerInfo(comptarget);
  533. CompilerTarget:=lowercase(DefaultCompilerTarget);
  534. end
  535. else
  536. GetCompilerTarget:=true;
  537. if GetCompilerTarget and not CompilerTargetDebugWritten then
  538. begin
  539. Verbose(V_Debug,'Compiler Target: "'+CompilerTarget+'"');
  540. CompilerTargetDebugWritten:=true;
  541. end;
  542. end;
  543. function CompilerFullTarget:string;
  544. begin
  545. if UseOSOnly then
  546. CompilerFullTarget:=CompilerTarget
  547. else
  548. CompilerFullTarget:=CompilerCPU+'-'+CompilerTarget;
  549. end;
  550. { Set the three constants above according to
  551. the current target }
  552. procedure SetTargetDirectoriesStyle;
  553. var
  554. LTarget : string;
  555. begin
  556. { Call this first to ensure that CompilerTarget is not empty }
  557. GetCompilerTarget;
  558. LTarget := CompilerTarget;
  559. TargetHasDosStyleDirectories :=
  560. (LTarget='emx') or
  561. (LTarget='go32v2') or
  562. (LTarget='nativent') or
  563. (LTarget='os2') or
  564. (LTarget='symbian') or
  565. (LTarget='watcom') or
  566. (LTarget='wdosx') or
  567. (LTarget='win32') or
  568. (LTarget='win64');
  569. TargetAmigaLike:=
  570. (LTarget='amiga') or
  571. (LTarget='morphos');
  572. TargetIsMacOS:=
  573. (LTarget='macos');
  574. { Base on whether UNIX is defined as default macro
  575. in extradefines in systesms/i_XXX.pas units }
  576. TargetIsUnix:=
  577. (LTarget='linux') or
  578. (LTarget='linux6432') or
  579. (LTarget='freebsd') or
  580. (LTarget='openbsd') or
  581. (LTarget='netbsd') or
  582. (LTarget='beos') or
  583. (LTarget='haiku') or
  584. (LTarget='solaris') or
  585. (LTarget='iphonesim') or
  586. (LTarget='darwin') or
  587. (LTarget='aix') or
  588. (LTarget='android');
  589. { Set ExeExt for CompilerTarget.
  590. This list has been set up 2011-06 using the information in
  591. compiler/system/i_XXX.pas units.
  592. We should update this list when adding new targets PM }
  593. if (TargetHasDosStyleDirectories) then
  594. ExeExt:='.exe'
  595. else if LTarget='atari' then
  596. ExeExt:='.tpp'
  597. else if LTarget='gba' then
  598. ExeExt:='.gba'
  599. else if LTarget='nds' then
  600. ExeExt:='.bin'
  601. else if (LTarget='netware') or (LTarget='netwlibc') then
  602. ExeExt:='.nlm'
  603. else if LTarget='wii' then
  604. ExeExt:='.dol'
  605. else if LTarget='wince' then
  606. ExeExt:='.exe';
  607. end;
  608. {$ifndef LIMIT83FS}
  609. { Set the UseOSOnly constant above according to
  610. the current target }
  611. procedure SetUseOSOnly;
  612. var
  613. LTarget : string;
  614. begin
  615. { Call this first to ensure that CompilerTarget is not empty }
  616. GetCompilerTarget;
  617. LTarget := CompilerTarget;
  618. UseOSOnly:= (LTarget='emx') or
  619. (LTarget='go32v2') or
  620. (LTarget='os2');
  621. end;
  622. {$endif not LIMIT83FS}
  623. procedure SetTargetCanCompileLibraries;
  624. var
  625. LTarget : string;
  626. begin
  627. { Call this first to ensure that CompilerTarget is not empty }
  628. GetCompilerTarget;
  629. LTarget := CompilerTarget;
  630. { Feel free to add other targets here }
  631. if (LTarget='go32v2') then
  632. TargetCanCompileLibraries:=false;
  633. end;
  634. function OutputFileName(Const s,ext:String):String;
  635. begin
  636. {$ifndef macos}
  637. OutputFileName:=OutputDir+'/'+ForceExtension(s,ext);
  638. {$else macos}
  639. OutputFileName:=ConcatMacPath(OutputDir,ForceExtension(s,ext));
  640. {$endif macos}
  641. end;
  642. function TestOutputFileName(Const pref,base,ext:String):String;
  643. begin
  644. {$ifndef macos}
  645. TestOutputFileName:=TestOutputDir+'/'+ForceExtension(pref+SplitFileName(base),ext);
  646. {$else macos}
  647. TestOutputFileName:=ConcatMacPath(TestOutputDir,ForceExtension(pref+SplitFileName(base),ext));
  648. {$endif macos}
  649. end;
  650. function TestLogFileName(Const pref,base,ext:String):String;
  651. var
  652. LogDir: String;
  653. begin
  654. LogDir:=TestOutputDir;
  655. {$ifndef macos}
  656. if UniqueSuffix<>'' then
  657. LogDir:=LogDir+'/..';
  658. TestLogFileName:=LogDir+'/'+ForceExtension(pref+SplitFileName(base),ext);
  659. {$else macos}
  660. if UniqueSuffix<>'' then
  661. LogDir:=LogDir+'::';
  662. TestLogFileName:=ConcatMacPath(LogDir,ForceExtension(pref+SplitFileName(base),ext));
  663. {$endif macos}
  664. end;
  665. function ExitWithInternalError(const OutName:string):boolean;
  666. var
  667. t : text;
  668. s : string;
  669. begin
  670. ExitWithInternalError:=false;
  671. { open logfile }
  672. assign(t,Outname);
  673. {$I-}
  674. reset(t);
  675. {$I+}
  676. if ioresult<>0 then
  677. exit;
  678. while not eof(t) do
  679. begin
  680. readln(t,s);
  681. if pos('Fatal: Internal error ',s)>0 then
  682. begin
  683. ExitWithInternalError:=true;
  684. break;
  685. end;
  686. end;
  687. close(t);
  688. end;
  689. { Takes each option from AddOptions list
  690. considered as a space separated list
  691. and adds the option to args
  692. unless option contains a percent sign,
  693. in that case, the option after % will be added
  694. to args only if CompilerTarget is listed in
  695. the string part before %.
  696. NOTE: this function does not check for
  697. quoted options...
  698. The list before % must of course contain no spaces. }
  699. procedure AppendOptions(AddOptions : string;var args : string);
  700. var
  701. endopt,percentpos : longint;
  702. opttarget, currentopt : string;
  703. begin
  704. Verbose(V_Debug,'AppendOptions called with AddOptions="'+AddOptions+'"');
  705. AddOptions:=trimspace(AddOptions);
  706. repeat
  707. endopt:=pos(' ',AddOptions);
  708. if endopt=0 then
  709. endopt:=length(AddOptions);
  710. currentopt:=trimspace(copy(AddOptions,1,endopt));
  711. AddOptions:=trimspace(copy(Addoptions,endopt+1,length(AddOptions)));
  712. if currentopt<>'' then
  713. begin
  714. percentpos:=pos('%',currentopt);
  715. if (percentpos=0) then
  716. begin
  717. Verbose(V_Debug,'Adding option="'+currentopt+'"');
  718. args:=args+' '+currentopt;
  719. end
  720. else
  721. begin
  722. opttarget:=lowercase(copy(currentopt,1,percentpos-1));
  723. if IsInList(CompilerTarget, opttarget) then
  724. begin
  725. Verbose(V_Debug,'Adding target specific option="'+currentopt+'" for '+opttarget);
  726. args:=args+' '+copy(currentopt,percentpos+1,length(currentopt))
  727. end
  728. else
  729. Verbose(V_Debug,'No matching target "'+currentopt+'"');
  730. end;
  731. end;
  732. until AddOptions='';
  733. end;
  734. { This function removes some incompatible
  735. options from TEST_OPT before adding them to
  736. the list of options passed to the compiler.
  737. %DELOPT=XYZ will remove XYZ exactly
  738. %DELOPT=XYZ* will remove all options starting with XYZ.
  739. NOTE: This fuinction does not handle quoted options. }
  740. function DelOptions(Pattern, opts : string) : string;
  741. var
  742. currentopt : string;
  743. optpos, endopt, startpos, endpos : longint;
  744. iswild : boolean;
  745. begin
  746. opts:=trimspace(opts);
  747. pattern:=trimspace(pattern);
  748. repeat
  749. endpos:=pos(' ',pattern);
  750. if endpos=0 then
  751. endpos:=length(pattern);
  752. currentopt:=trimspace(copy(pattern,1,endpos));
  753. pattern:=trimspace(copy(pattern,endpos+1,length(pattern)));
  754. if currentopt<>'' then
  755. begin
  756. if currentopt[length(currentopt)]='*' then
  757. begin
  758. iswild:=true;
  759. system.delete(currentopt,length(currentopt),1);
  760. end
  761. else
  762. iswild:=false;
  763. startpos:=1;
  764. repeat
  765. optpos:=pos(currentopt,copy(opts,startpos,length(opts)));
  766. if optpos>0 then
  767. begin
  768. { move to index in full opts string }
  769. optpos:=optpos+startpos-1;
  770. { compute position of end of opt }
  771. endopt:=optpos+length(currentopt);
  772. { use that end as start position for next round }
  773. startpos:=endopt;
  774. if iswild then
  775. begin
  776. while (opts[endopt]<>' ') and
  777. (endopt<length(opts)) do
  778. begin
  779. inc(endopt);
  780. inc(startpos);
  781. end;
  782. Verbose(V_Debug,'Pattern match found "'+currentopt+'*" in "'+opts+'"');
  783. system.delete(opts,optpos,endopt-optpos+1);
  784. Verbose(V_Debug,'After opts="'+opts+'"');
  785. end
  786. else
  787. begin
  788. if (endopt>length(opts)) or (opts[endopt]=' ') then
  789. begin
  790. Verbose(V_Debug,'Exact match found "'+currentopt+'" in "'+opts+'"');
  791. system.delete(opts,optpos,endopt-optpos+1);
  792. Verbose(V_Debug,'After opts="'+opts+'"');
  793. end
  794. else
  795. begin
  796. Verbose(V_Debug,'No exact match "'+currentopt+'" in "'+opts+'"');
  797. end;
  798. end;
  799. end;
  800. until optpos=0;
  801. end;
  802. until pattern='';
  803. DelOptions:=opts;
  804. end;
  805. function RunCompiler:boolean;
  806. var
  807. args,LocalExtraArgs,
  808. wpoargs : string;
  809. passnr,
  810. passes : longint;
  811. execres : boolean;
  812. EndTicks,
  813. StartTicks : int64;
  814. begin
  815. RunCompiler:=false;
  816. args:='-n -T'+CompilerTarget+' -Fu'+RTLUnitsDir;
  817. { the helper object files have been copied to the common directory }
  818. if UniqueSuffix<>'' then
  819. args:=args+' -Fo'+TestOutputDir+'/..';
  820. args:=args+' -FE'+TestOutputDir;
  821. if TargetIsMacOS then
  822. args:=args+' -WT '; {tests should be compiled as MPWTool}
  823. if Config.DelOptions<>'' then
  824. LocalExtraArgs:=DelOptions(Config.DelOptions,ExtraCompilerOpts)
  825. else
  826. LocalExtraArgs:=ExtraCompilerOpts;
  827. if LocalExtraArgs<>'' then
  828. args:=args+' '+LocalExtraArgs;
  829. if TargetIsUnix then
  830. begin
  831. { Add runtime library path to current dir to find .so files }
  832. if Config.NeedLibrary then
  833. begin
  834. if (CompilerTarget='darwin') or
  835. (CompilerTarget='aix') then
  836. args:=args+' -Fl'+TestOutputDir
  837. else
  838. { do not use single quote for -k as they are mishandled on
  839. Windows Shells }
  840. args:=args+' -Fl'+TestOutputDir+' -k-rpath -k.'
  841. end;
  842. end;
  843. if Config.NeedOptions<>'' then
  844. AppendOptions(Config.NeedOptions,args);
  845. wpoargs:='';
  846. if (Config.WpoPasses=0) or
  847. (Config.WpoParas='') then
  848. passes:=1
  849. else
  850. passes:=config.wpopasses+1;
  851. args:=args+' '+PPFile[current];
  852. for passnr:=1 to passes do
  853. begin
  854. if (passes>1) then
  855. begin
  856. wpoargs:=' -OW'+config.wpoparas+' -FW'+TestOutputFileName('',PPFile[current],'wp'+tostr(passnr));
  857. if (passnr>1) then
  858. wpoargs:=wpoargs+' -Ow'+config.wpoparas+' -Fw'+TestOutputFileName('',PPFile[current],'wp'+tostr(passnr-1));
  859. end;
  860. Verbose(V_Debug,'Executing '+compilerbin+' '+args+wpoargs);
  861. { also get the output from as and ld that writes to stderr sometimes }
  862. StartTicks:=GetMicroSTicks;
  863. {$ifndef macos}
  864. execres:=ExecuteRedir(CompilerBin,args+wpoargs,'',CompilerLogFile,'stdout');
  865. {$else macos}
  866. {Due to that Toolserver is not reentrant, we have to asm and link via script.}
  867. execres:=ExecuteRedir(CompilerBin,'-s '+args+wpoargs,'',CompilerLogFile,'stdout');
  868. if execres then
  869. execres:=ExecuteRedir(TestOutputDir + ':ppas','','',CompilerLogFile,'stdout');
  870. {$endif macos}
  871. EndTicks:=GetMicroSTicks;
  872. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  873. if BenchmarkInfo then
  874. begin
  875. Verbose(V_Normal,'Compilation took '+ToStr(EndTicks-StartTicks)+' us');
  876. end;
  877. { Error during execution? }
  878. if (not execres) and (ExecuteResult=0) then
  879. begin
  880. AddLog(FailLogFile,TestName);
  881. AddLog(ResLogFile,failed_to_compile+PPFileInfo[current]);
  882. AddLog(LongLogFile,line_separation);
  883. AddLog(LongLogFile,failed_to_compile+PPFileInfo[current]);
  884. if CopyFile(CompilerLogFile,LongLogFile,true)=0 then
  885. AddLog(LongLogFile,'IOStatus'+ToStr(IOStatus));
  886. { avoid to try again }
  887. AddLog(ExeLogFile,failed_to_compile+PPFileInfo[current]);
  888. Verbose(V_Warning,'IOStatus: '+ToStr(IOStatus));
  889. exit;
  890. end;
  891. { Check for internal error }
  892. if ExitWithInternalError(CompilerLogFile) then
  893. begin
  894. AddLog(FailLogFile,TestName);
  895. if Config.Note<>'' then
  896. AddLog(FailLogFile,Config.Note);
  897. AddLog(ResLogFile,failed_to_compile+PPFileInfo[current]+' internalerror generated');
  898. AddLog(LongLogFile,line_separation);
  899. AddLog(LongLogFile,failed_to_compile+PPFileInfo[current]);
  900. if Config.Note<>'' then
  901. AddLog(LongLogFile,Config.Note);
  902. if CopyFile(CompilerLogFile,LongLogFile,true)=0 then
  903. AddLog(LongLogFile,'Internal error in compiler');
  904. { avoid to try again }
  905. AddLog(ExeLogFile,failed_to_compile+PPFileInfo[current]);
  906. Verbose(V_Warning,'Internal error in compiler');
  907. exit;
  908. end;
  909. end;
  910. { Should the compile fail ? }
  911. if Config.ShouldFail then
  912. begin
  913. if ExecuteResult<>0 then
  914. begin
  915. AddLog(ResLogFile,success_compilation_failed+PPFileInfo[current]);
  916. { avoid to try again }
  917. AddLog(ExeLogFile,success_compilation_failed+PPFileInfo[current]);
  918. RunCompiler:=true;
  919. end
  920. else
  921. begin
  922. AddLog(FailLogFile,TestName);
  923. if Config.Note<>'' then
  924. AddLog(FailLogFile,Config.Note);
  925. AddLog(ResLogFile,failed_compilation_successful+PPFileInfo[current]);
  926. AddLog(LongLogFile,line_separation);
  927. AddLog(LongLogFile,failed_compilation_successful+PPFileInfo[current]);
  928. { avoid to try again }
  929. AddLog(ExeLogFile,failed_compilation_successful+PPFileInfo[current]);
  930. if Config.Note<>'' then
  931. AddLog(LongLogFile,Config.Note);
  932. CopyFile(CompilerLogFile,LongLogFile,true);
  933. end;
  934. end
  935. else
  936. begin
  937. if (ExecuteResult<>0) and
  938. (((Config.KnownCompileNote<>'') and (Config.KnownCompileError=0)) or
  939. ((Config.KnownCompileError<>0) and (ExecuteResult=Config.KnownCompileError))) then
  940. begin
  941. AddLog(FailLogFile,TestName+known_problem+Config.KnownCompileNote);
  942. AddLog(ResLogFile,failed_to_compile+PPFileInfo[current]+known_problem+Config.KnownCompileNote);
  943. AddLog(LongLogFile,line_separation);
  944. AddLog(LongLogFile,known_problem+Config.KnownCompileNote);
  945. AddLog(LongLogFile,failed_to_compile+PPFileInfo[current]+' ('+ToStr(ExecuteResult)+')');
  946. if Copyfile(CompilerLogFile,LongLogFile,true)=0 then
  947. AddLog(LongLogFile,known_problem+'exitcode: '+ToStr(ExecuteResult));
  948. Verbose(V_Warning,known_problem+'exitcode: '+ToStr(ExecuteResult));
  949. end
  950. else if ExecuteResult<>0 then
  951. begin
  952. AddLog(FailLogFile,TestName);
  953. if Config.Note<>'' then
  954. AddLog(FailLogFile,Config.Note);
  955. AddLog(ResLogFile,failed_to_compile+PPFileInfo[current]);
  956. AddLog(LongLogFile,line_separation);
  957. AddLog(LongLogFile,failed_to_compile+PPFileInfo[current]);
  958. if Config.Note<>'' then
  959. AddLog(LongLogFile,Config.Note);
  960. if CopyFile(CompilerLogFile,LongLogFile,true)=0 then
  961. AddLog(LongLogFile,'Exitcode: '+ToStr(ExecuteResult)+' (expected 0)');
  962. { avoid to try again }
  963. AddLog(ExeLogFile,failed_to_compile+PPFileInfo[current]);
  964. Verbose(V_Warning,'Exitcode: '+ToStr(ExecuteResult)+' (expected 0)');
  965. end
  966. else
  967. begin
  968. AddLog(ResLogFile,successfully_compiled+PPFileInfo[current]);
  969. RunCompiler:=true;
  970. end;
  971. end;
  972. end;
  973. function CheckTestExitCode(const OutName:string):boolean;
  974. var
  975. t : text;
  976. s : string;
  977. i,code : integer;
  978. begin
  979. CheckTestExitCode:=false;
  980. { open logfile }
  981. assign(t,Outname);
  982. {$I-}
  983. reset(t);
  984. {$I+}
  985. if ioresult<>0 then
  986. exit;
  987. while not eof(t) do
  988. begin
  989. readln(t,s);
  990. i:=pos('TestExitCode: ',s);
  991. if i>0 then
  992. begin
  993. delete(s,1,i+14-1);
  994. val(s,ExecuteResult,code);
  995. if code=0 then
  996. CheckTestExitCode:=true;
  997. break;
  998. end;
  999. end;
  1000. close(t);
  1001. end;
  1002. function LibraryExists(const PPFile : string; out FileName : string) : boolean;
  1003. begin
  1004. { Check if a dynamic library XXX was created }
  1005. { Windows XXX.dll style }
  1006. FileName:=TestOutputFilename('',PPFile,'dll');
  1007. if FileExists(FileName) then
  1008. begin
  1009. LibraryExists:=true;
  1010. exit;
  1011. end;
  1012. { Linux libXXX.so style }
  1013. FileName:=TestOutputFilename('lib',PPFile,'so');
  1014. if FileExists(FileName) then
  1015. begin
  1016. LibraryExists:=true;
  1017. exit;
  1018. end;
  1019. { Darwin libXXX.dylib style }
  1020. FileName:=TestOutputFilename('lib',PPFile,'dylib');
  1021. if FileExists(FileName) then
  1022. begin
  1023. LibraryExists:=true;
  1024. exit;
  1025. end;
  1026. { MacOS LibXXX style }
  1027. FileName:=TestOutputFilename('Lib',PPFile,'');
  1028. if FileExists(FileName) then
  1029. begin
  1030. LibraryExists:=true;
  1031. exit;
  1032. end;
  1033. { Netware wlic XXX.nlm style }
  1034. FileName:=TestOutputFilename('',PPFile,'nlm');
  1035. if FileExists(FileName) then
  1036. begin
  1037. LibraryExists:=true;
  1038. exit;
  1039. end;
  1040. { Amiga XXX.library style }
  1041. FileName:=TestOutputFilename('',PPFile,'library');
  1042. if FileExists(FileName) then
  1043. begin
  1044. LibraryExists:=true;
  1045. exit;
  1046. end;
  1047. LibraryExists:=false;
  1048. end;
  1049. function ExecuteRemote(const prog,args:string;out StartTicks,EndTicks : int64):boolean;
  1050. const
  1051. MaxTrials = 5;
  1052. var
  1053. Trials : longint;
  1054. Res : boolean;
  1055. begin
  1056. Verbose(V_Debug,'RemoteExecuting '+Prog+' '+args);
  1057. StartTicks:=GetMicroSTicks;
  1058. Res:=false;
  1059. Trials:=0;
  1060. While (Trials<MaxTrials) and not Res do
  1061. begin
  1062. inc(Trials);
  1063. Res:=ExecuteRedir(prog,args,'',EXELogFile,'stdout');
  1064. if not Res then
  1065. Verbose(V_Debug,'Call to '+prog+' failed: '+
  1066. 'IOStatus='+ToStr(IOStatus)+
  1067. ' RedirErrorOut='+ToStr(RedirErrorOut)+
  1068. ' RedirErrorIn='+ToStr(RedirErrorIn)+
  1069. ' RedirErrorError='+ToStr(RedirErrorError)+
  1070. ' ExecuteResult='+ToStr(ExecuteResult));
  1071. end;
  1072. if Trials>1 then
  1073. Verbose(V_Debug,'Done in '+tostr(trials)+' trials');
  1074. EndTicks:=GetMicroSTicks;
  1075. ExecuteRemote:=res;
  1076. end;
  1077. function ExecuteEmulated(const prog,args,FullExeLogFile:string;out StartTicks,EndTicks : int64):boolean;
  1078. begin
  1079. Verbose(V_Debug,'EmulatorExecuting '+Prog+' '+args);
  1080. StartTicks:=GetMicroSTicks;
  1081. ExecuteEmulated:=ExecuteRedir(prog,args,'',FullExeLogFile,'stdout');
  1082. EndTicks:=GetMicroSTicks;
  1083. end;
  1084. function MaybeCopyFiles(const FileToCopy : string) : boolean;
  1085. var
  1086. TestRemoteExe,
  1087. pref : string;
  1088. LocalFile, RemoteFile: string;
  1089. LocalPath: string;
  1090. i : integer;
  1091. execres : boolean;
  1092. EndTicks,
  1093. StartTicks : int64;
  1094. FileList : TStringList;
  1095. function BuildFileList: TStringList;
  1096. var
  1097. s : string;
  1098. index : longint;
  1099. begin
  1100. s:=Config.Files;
  1101. if length(s) = 0 then
  1102. begin
  1103. Result:=nil;
  1104. exit;
  1105. end;
  1106. Result:=TStringList.Create;
  1107. repeat
  1108. index:=pos(' ',s);
  1109. if index=0 then
  1110. LocalFile:=s
  1111. else
  1112. LocalFile:=copy(s,1,index-1);
  1113. Result.Add(LocalFile);
  1114. if index=0 then
  1115. break;
  1116. s:=copy(s,index+1,length(s)-index);
  1117. until false;
  1118. end;
  1119. begin
  1120. if RemoteAddr='' then
  1121. begin
  1122. If UniqueSuffix<>'' then
  1123. begin
  1124. FileList:=BuildFileList;
  1125. if assigned(FileList) then
  1126. begin
  1127. LocalPath:=SplitPath(PPFile[current]);
  1128. if Length(LocalPath) > 0 then
  1129. LocalPath:=LocalPath+'/';
  1130. for i:=0 to FileList.count-1 do
  1131. begin
  1132. LocalFile:=FileList[i];
  1133. CopyFile(LocalPath+LocalFile,TestOutputDir+'/'+LocalFile,false);
  1134. end;
  1135. FileList.Free;
  1136. end;
  1137. end;
  1138. exit(true);
  1139. end;
  1140. execres:=true;
  1141. { We don't want to create subdirs, remove paths from the test }
  1142. TestRemoteExe:=RemotePath+'/'+SplitFileName(FileToCopy);
  1143. if deBefore in DelExecutable then
  1144. ExecuteRemote(rshprog,RemoteRshParas+' rm -f '+TestRemoteExe,
  1145. StartTicks,EndTicks);
  1146. execres:=ExecuteRemote(rcpprog,RemotePara+' '+FileToCopy+' '+
  1147. RemotePathPrefix+TestRemoteExe,StartTicks,EndTicks);
  1148. if not execres then
  1149. begin
  1150. Verbose(V_normal, 'Could not copy executable '+FileToCopy);
  1151. exit(execres);
  1152. end;
  1153. FileList:=BuildFileList;
  1154. if assigned(FileList) then
  1155. begin
  1156. LocalPath:=SplitPath(PPFile[current]);
  1157. if Length(LocalPath) > 0 then
  1158. LocalPath:=LocalPath+'/';
  1159. for i:=0 to FileList.count-1 do
  1160. begin
  1161. LocalFile:=FileList[i];
  1162. RemoteFile:=RemotePath+'/'+SplitFileName(LocalFile);
  1163. LocalFile:=LocalPath+LocalFile;
  1164. if DoVerbose and (rcpprog='pscp') then
  1165. pref:='-v '
  1166. else
  1167. pref:='';
  1168. execres:=ExecuteRemote(rcpprog,pref+RemotePara+' '+LocalFile+' '+
  1169. RemotePathPrefix+RemoteFile,StartTicks,EndTicks);
  1170. if not execres then
  1171. begin
  1172. Verbose(V_normal, 'Could not copy required file '+LocalFile);
  1173. FileList.Free;
  1174. exit(false);
  1175. end;
  1176. end;
  1177. end;
  1178. FileList.Free;
  1179. MaybeCopyFiles:=execres;
  1180. end;
  1181. function RunExecutable:boolean;
  1182. const
  1183. {$ifdef unix}
  1184. CurrDir = './';
  1185. {$else}
  1186. CurrDir = '';
  1187. {$endif}
  1188. var
  1189. OldDir, s,
  1190. execcmd,
  1191. FullExeLogFile,
  1192. TestRemoteExe,
  1193. TestExe : string;
  1194. execres : boolean;
  1195. EndTicks,
  1196. StartTicks : int64;
  1197. begin
  1198. RunExecutable:=false;
  1199. execres:=true;
  1200. TestExe:=TestOutputFilename('',PPFile[current],ExeExt);
  1201. execres:=MaybeCopyFiles(TestExe);
  1202. if EmulatorName<>'' then
  1203. begin
  1204. { Get full name out log file, because we change the directory during
  1205. execution }
  1206. FullExeLogFile:=FExpand(EXELogFile);
  1207. {$I-}
  1208. GetDir(0,OldDir);
  1209. ChDir(TestOutputDir);
  1210. {$I+}
  1211. ioresult;
  1212. s:=CurrDir+SplitFileName(TestExe);
  1213. execres:=ExecuteEmulated(EmulatorName,s,FullExeLogFile,StartTicks,EndTicks);
  1214. {$I-}
  1215. ChDir(OldDir);
  1216. {$I+}
  1217. end
  1218. else if RemoteAddr<>'' then
  1219. begin
  1220. TestRemoteExe:=RemotePath+'/'+SplitFileName(TestExe);
  1221. { rsh doesn't pass the exitcode, use a second command to print the exitcode
  1222. on the remoteshell to stdout }
  1223. if DoVerbose and (rshprog='plink') then
  1224. execcmd:='-v '+RemoteRshParas
  1225. else
  1226. execcmd:=RemoteRshParas;
  1227. execcmd:=execcmd+' '+rquote+
  1228. 'chmod 755 '+TestRemoteExe+
  1229. ' ; cd '+RemotePath+' ; ';
  1230. { Using -rpath . at compile time does not seem
  1231. to work for programs copied over to remote machine,
  1232. at least not for FreeBSD.
  1233. Does this work for all shells? }
  1234. if Config.NeedLibrary then
  1235. begin
  1236. if RemoteShellNeedsExport then
  1237. execcmd:=execcmd+' LD_LIBRARY_PATH=.; export LD_LIBRARY_PATH;'
  1238. else
  1239. execcmd:=execcmd+' setenv LD_LIBRARY_PATH=.; ';
  1240. end;
  1241. if UseTimeout then
  1242. begin
  1243. if Config.Timeout=0 then
  1244. Config.Timeout:=DefaultTimeout;
  1245. str(Config.Timeout,s);
  1246. if (RemoteShellBase='bash') then
  1247. execcmd:=execcmd+'ulimit -t '+s+'; '
  1248. else
  1249. execcmd:=execcmd+'timeout -9 '+s;
  1250. end;
  1251. { as we moved to RemotePath, if path is not absolute
  1252. we need to use ./execfilename only }
  1253. if not isabsolute(TestRemoteExe) then
  1254. execcmd:=execcmd+' ./'+SplitFileName(TestRemoteExe)
  1255. else
  1256. execcmd:=execcmd+' '+TestRemoteExe;
  1257. execcmd:=execcmd+' ; echo "TestExitCode: $?"';
  1258. if (deAfter in DelExecutable) and
  1259. not Config.NeededAfter then
  1260. execcmd:=execcmd+' ; rm -f '+SplitFileName(TestRemoteExe);
  1261. execcmd:=execcmd+rquote;
  1262. execres:=ExecuteRemote(rshprog,execcmd,StartTicks,EndTicks);
  1263. { Check for TestExitCode error in output, sets ExecuteResult }
  1264. if not CheckTestExitCode(EXELogFile) then
  1265. Verbose(V_Debug,'Failed to check exit code for '+execcmd);
  1266. end
  1267. else
  1268. begin
  1269. { Get full name out log file, because we change the directory during
  1270. execution }
  1271. FullExeLogFile:=FExpand(EXELogFile);
  1272. Verbose(V_Debug,'Executing '+TestExe);
  1273. {$I-}
  1274. GetDir(0,OldDir);
  1275. ChDir(TestOutputDir);
  1276. {$I+}
  1277. ioresult;
  1278. { don't redirect interactive and graph programs }
  1279. StartTicks:=GetMicroSTicks;
  1280. if Config.IsInteractive or Config.UsesGraph then
  1281. execres:=ExecuteRedir(CurrDir+SplitFileName(TestExe),'','','','')
  1282. else
  1283. execres:=ExecuteRedir(CurrDir+SplitFileName(TestExe),'','',FullExeLogFile,'stdout');
  1284. EndTicks:=GetMicroSTicks;
  1285. {$I-}
  1286. ChDir(OldDir);
  1287. {$I+}
  1288. ioresult;
  1289. end;
  1290. { Error during execution? }
  1291. Verbose(V_Debug,'Exitcode '+ToStr(ExecuteResult));
  1292. if BenchmarkInfo then
  1293. begin
  1294. Verbose(V_Normal,'Execution took '+ToStr(EndTicks-StartTicks)+' us');
  1295. end;
  1296. if (not execres) and (ExecuteResult=0) then
  1297. begin
  1298. AddLog(FailLogFile,TestName);
  1299. AddLog(ResLogFile,failed_to_run+PPFileInfo[current]);
  1300. AddLog(LongLogFile,line_separation);
  1301. AddLog(LongLogFile,failed_to_run+PPFileInfo[current]);
  1302. if CopyFile(EXELogFile,LongLogFile,true)=0 then
  1303. AddLog(LongLogFile,'IOStatus: '+ToStr(IOStatus));
  1304. { avoid to try again }
  1305. AddLog(ExeLogFile,failed_to_run+PPFileInfo[current]);
  1306. Verbose(V_Warning,'IOStatus: '+ToStr(IOStatus));
  1307. exit;
  1308. end;
  1309. if ExecuteResult<>Config.ResultCode then
  1310. begin
  1311. if (ExecuteResult<>0) and
  1312. (ExecuteResult=Config.KnownRunError) then
  1313. begin
  1314. AddLog(FailLogFile,TestName+known_problem+Config.KnownRunNote);
  1315. AddLog(ResLogFile,failed_to_run+PPFileInfo[current]+known_problem+Config.KnownRunNote);
  1316. AddLog(LongLogFile,line_separation);
  1317. AddLog(LongLogFile,known_problem+Config.KnownRunNote);
  1318. AddLog(LongLogFile,failed_to_run+PPFileInfo[current]+' ('+ToStr(ExecuteResult)+')');
  1319. if Copyfile(EXELogFile,LongLogFile,true)=0 then
  1320. begin
  1321. AddLog(LongLogFile,known_problem+'exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  1322. AddLog(ExeLogFile,known_problem+'exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  1323. end;
  1324. Verbose(V_Warning,known_problem+'exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  1325. end
  1326. else
  1327. begin
  1328. AddLog(FailLogFile,TestName);
  1329. AddLog(ResLogFile,failed_to_run+PPFileInfo[current]);
  1330. AddLog(LongLogFile,line_separation);
  1331. AddLog(LongLogFile,failed_to_run+PPFileInfo[current]+' ('+ToStr(ExecuteResult)+')');
  1332. if Copyfile(EXELogFile,LongLogFile,true)=0 then
  1333. begin
  1334. AddLog(LongLogFile,'Exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  1335. AddLog(ExeLogFile,'Exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  1336. end;
  1337. Verbose(V_Warning,'Exitcode: '+ToStr(ExecuteResult)+' (expected '+ToStr(Config.ResultCode)+')');
  1338. end
  1339. end
  1340. else
  1341. begin
  1342. AddLog(ResLogFile,successfully_run+PPFileInfo[current]);
  1343. RunExecutable:=true;
  1344. end;
  1345. if (deAfter in DelExecutable) and not Config.NeededAfter then
  1346. begin
  1347. Verbose(V_Debug,'Deleting executable '+TestExe);
  1348. RemoveFile(TestExe);
  1349. RemoveFile(ForceExtension(TestExe,ObjExt));
  1350. RemoveFile(ForceExtension(TestExe,PPUExt));
  1351. end;
  1352. end;
  1353. { Try to collect information concerning the remote configuration
  1354. Currently only records RemoteShell name and sets
  1355. RemoteShellNeedsExport boolean variable }
  1356. procedure SetRemoteConfiguration;
  1357. var
  1358. f : text;
  1359. StartTicks,EndTicks : int64;
  1360. begin
  1361. if RemoteAddr='' then
  1362. exit;
  1363. if rshprog = 'adb' then
  1364. begin
  1365. RemoteShellNeedsExport:=true;
  1366. exit;
  1367. end;
  1368. ExeLogFile:='__remote.tmp';
  1369. ExecuteRemote(rshprog,RemoteRshParas+
  1370. ' "echo SHELL=${SHELL}"',StartTicks,EndTicks);
  1371. Assign(f,ExeLogFile);
  1372. Reset(f);
  1373. While not eof(f) do
  1374. begin
  1375. Readln(f,RemoteShellBase);
  1376. if pos('SHELL=',RemoteShellBase)>0 then
  1377. begin
  1378. RemoteShell:=TrimSpace(Copy(RemoteShellBase,pos('SHELL=',RemoteShellBase)+6,
  1379. length(RemoteShellBase)));
  1380. Verbose(V_Debug,'Remote shell is "'+RemoteShell+'"');
  1381. RemoteShellBase:=SplitFileBase(RemoteShell);
  1382. if (RemoteShellBase='bash') or (RemoteShellBase='sh') then
  1383. RemoteShellNeedsExport:=true;
  1384. end;
  1385. end;
  1386. Close(f);
  1387. end;
  1388. procedure getargs;
  1389. procedure helpscreen;
  1390. begin
  1391. writeln('dotest [Options] <File>');
  1392. writeln;
  1393. writeln('Options can be:');
  1394. writeln(' !ENV_NAME parse environment variable ENV_NAME for options');
  1395. writeln(' -A include ALL tests');
  1396. writeln(' -ADB use ADB to run tests');
  1397. writeln(' -B delete executable before remote upload');
  1398. writeln(' -C<compiler> set compiler to use');
  1399. writeln(' -D display execution time');
  1400. writeln(' -E execute test also');
  1401. writeln(' -G include graph tests');
  1402. writeln(' -I include interactive tests');
  1403. writeln(' -K include known bug tests');
  1404. writeln(' -L<ext> set extension of temporary files (prevent conflicts with parallel invocations)');
  1405. writeln(' -M<emulator> run the tests using the given emulator');
  1406. writeln(' -O use timeout wrapper for (remote) execution');
  1407. writeln(' -P<path> path to the tests tree on the remote machine');
  1408. writeln(' -R<remote> run the tests remotely with the given rsh/ssh address');
  1409. writeln(' -S use ssh instead of rsh');
  1410. writeln(' -T[cpu-]<os> run tests for target cpu and os');
  1411. writeln(' -U<remotepara>');
  1412. writeln(' pass additional parameter to remote program. Multiple -U can be used');
  1413. writeln(' -V be verbose');
  1414. writeln(' -W use putty compatible file names when testing (plink and pscp)');
  1415. writeln(' -X don''t use COMSPEC');
  1416. writeln(' -Y<opts> extra options passed to the compiler. Several -Y<opt> can be given.');
  1417. writeln(' -Z remove temporary files (executable,ppu,o)');
  1418. halt(1);
  1419. end;
  1420. procedure interpret_option (para : string);
  1421. var
  1422. ch : char;
  1423. j : longint;
  1424. begin
  1425. Verbose(V_Debug,'Interpreting option"'+para+'"');
  1426. ch:=Upcase(para[2]);
  1427. delete(para,1,2);
  1428. case ch of
  1429. 'A' :
  1430. if UpperCase(para) = 'DB' then
  1431. begin
  1432. rshprog:='adb';
  1433. rcpprog:='adb';
  1434. rquote:='';
  1435. if RemoteAddr = '' then
  1436. RemoteAddr:='1'; // fake remote addr (default device will be used)
  1437. end
  1438. else
  1439. begin
  1440. DoGraph:=true;
  1441. DoInteractive:=true;
  1442. DoKnown:=true;
  1443. DoAll:=true;
  1444. end;
  1445. 'B' : Include(DelExecutable,deBefore);
  1446. 'C' : CompilerBin:=Para;
  1447. 'D' : BenchMarkInfo:=true;
  1448. 'E' : DoExecute:=true;
  1449. 'G' : begin
  1450. DoGraph:=true;
  1451. if para='-' then
  1452. DoUsual:=false;
  1453. end;
  1454. 'I' : begin
  1455. DoInteractive:=true;
  1456. if para='-' then
  1457. DoUsual:=false;
  1458. end;
  1459. 'K' : begin
  1460. DoKnown:=true;
  1461. if para='-' then
  1462. DoUsual:=false;
  1463. end;
  1464. 'L' : begin
  1465. UniqueSuffix:=Para;
  1466. end;
  1467. 'M' : EmulatorName:=Para;
  1468. 'O' : UseTimeout:=true;
  1469. 'P' : RemotePath:=Para;
  1470. 'R' : RemoteAddr:=Para;
  1471. 'S' :
  1472. begin
  1473. rshprog:='ssh';
  1474. rcpprog:='scp';
  1475. end;
  1476. 'T' :
  1477. begin
  1478. j:=Pos('-',Para);
  1479. if j>0 then
  1480. begin
  1481. CompilerCPU:=Copy(Para,1,j-1);
  1482. CompilerTarget:=Copy(Para,j+1,length(para));
  1483. end
  1484. else
  1485. CompilerTarget:=Para
  1486. end;
  1487. 'U' :
  1488. RemotePara:=RemotePara+' '+Para;
  1489. 'V' : DoVerbose:=true;
  1490. 'W' :
  1491. begin
  1492. rshprog:='plink';
  1493. rcpprog:='pscp';
  1494. rquote:='"';
  1495. end;
  1496. 'X' : UseComSpec:=false;
  1497. 'Y' : ExtraCompilerOpts:= ExtraCompilerOpts +' '+ Para;
  1498. 'Z' : Include(DelExecutable,deAfter);
  1499. end;
  1500. end;
  1501. procedure interpret_env(arg : string);
  1502. var
  1503. para : string;
  1504. pspace : longint;
  1505. begin
  1506. Verbose(V_Debug,'Interpreting environment option"'+arg+'"');
  1507. { Get rid of leading '!' }
  1508. delete(arg,1,1);
  1509. arg:=getenv(arg);
  1510. Verbose(V_Debug,'Environment value is "'+arg+'"');
  1511. while (length(arg)>0) do
  1512. begin
  1513. while (length(arg)>0) and (arg[1]=' ') do
  1514. delete(arg,1,1);
  1515. pspace:=pos(' ',arg);
  1516. if pspace=0 then
  1517. pspace:=length(arg)+1;
  1518. para:=copy(arg,1,pspace-1);
  1519. if (length(para)>0) and (para[1]='-') then
  1520. interpret_option (para)
  1521. else
  1522. begin
  1523. PPFile.Insert(current,ForceExtension(Para,'pp'));
  1524. inc(current);
  1525. end;
  1526. delete(arg,1,pspace);
  1527. end;
  1528. end;
  1529. var
  1530. param : string;
  1531. i : longint;
  1532. begin
  1533. CompilerBin:='ppc386'+srcexeext;
  1534. for i:=1 to paramcount do
  1535. begin
  1536. param:=Paramstr(i);
  1537. if (param[1]='-') then
  1538. interpret_option(param)
  1539. else if (param[1]='!') then
  1540. interpret_env(param)
  1541. else
  1542. begin
  1543. PPFile.Insert(current,ForceExtension(Param,'pp'));
  1544. inc(current);
  1545. end;
  1546. end;
  1547. if current=0 then
  1548. HelpScreen;
  1549. { disable graph,interactive when running remote }
  1550. if RemoteAddr<>'' then
  1551. begin
  1552. DoGraph:=false;
  1553. DoInteractive:=false;
  1554. end;
  1555. { If we use PuTTY plink program with -load option,
  1556. the IP address or name should not be added to
  1557. the command line }
  1558. if (rshprog='plink') and (pos('-load',RemotePara)>0) then
  1559. RemoteRshParas:=RemotePara
  1560. else
  1561. if rshprog='adb' then
  1562. begin
  1563. if RemoteAddr <> '1' then
  1564. RemotePara:=Trim('-s ' + RemoteAddr + ' ' + RemotePara);
  1565. RemoteRshParas:=Trim(RemotePara + ' shell');
  1566. end
  1567. else
  1568. RemoteRshParas:=RemotePara+' '+RemoteAddr;
  1569. if rcpprog = 'adb' then
  1570. begin
  1571. RemotePathPrefix:='';
  1572. RemotePara:=Trim(RemotePara + ' push');
  1573. end
  1574. else
  1575. RemotePathPrefix:=RemoteAddr + ':';
  1576. end;
  1577. procedure RunTest;
  1578. var
  1579. PPDir,LibraryName,LogSuffix : string;
  1580. Res : boolean;
  1581. begin
  1582. Res:=GetConfig(PPFile[current],Config);
  1583. if Res then
  1584. begin
  1585. Res:=GetCompilerCPU;
  1586. Res:=GetCompilerTarget;
  1587. {$ifndef MACOS}
  1588. RTLUnitsDir:='tstunits/'+CompilerFullTarget;
  1589. {$else MACOS}
  1590. RTLUnitsDir:=':tstunits:'+CompilerFullTarget;
  1591. {$endif MACOS}
  1592. if not PathExists(RTLUnitsDir) then
  1593. Verbose(V_Abort,'Unit path "'+RTLUnitsDir+'" does not exists');
  1594. {$ifndef MACOS}
  1595. OutputDir:='output/'+CompilerFullTarget;
  1596. {$else MACOS}
  1597. OutputDir:=':output:'+CompilerFullTarget;
  1598. {$endif MACOS}
  1599. if not PathExists(OutputDir) then
  1600. Verbose(V_Abort,'Output path "'+OutputDir+'" does not exists');
  1601. { Make subdir in output if needed }
  1602. PPDir:=SplitPath(PPFile[current]);
  1603. if PPDir[length(PPDir)] in ['/','\'{$ifdef MACOS},':'{$endif MACOS}] then
  1604. Delete(PPDir,length(PPDir),1);
  1605. if PPDir<>'' then
  1606. begin
  1607. {$ifndef MACOS}
  1608. TestOutputDir:=OutputDir+'/'+PPDir;
  1609. if UniqueSuffix<>'' then
  1610. TestOutputDir:=TestOutputDir+'/'+UniqueSuffix;
  1611. {$else MACOS}
  1612. TestOutputDir:=OutputDir+PPDir;
  1613. if UniqueSuffix<>'' then
  1614. TestOutputDir:=TestOutputDir+':'+UniqueSuffix;
  1615. {$endif MACOS}
  1616. mkdirtree(TestOutputDir);
  1617. end
  1618. else
  1619. TestOutputDir:=OutputDir;
  1620. if UniqueSuffix<>'' then
  1621. LogSuffix:=UniqueSuffix
  1622. else
  1623. LogSuffix:=SplitBasePath(PPDir)+'log';
  1624. ResLogFile:=OutputFileName('log',LogSuffix);
  1625. LongLogFile:=OutputFileName('longlog',LogSuffix);
  1626. FailLogFile:=OutputFileName('faillist',LogSuffix);
  1627. ForceLog(ResLogFile);
  1628. ForceLog(LongLogFile);
  1629. ForceLog(FailLogFile);
  1630. { Per test logfiles }
  1631. CompilerLogFile:=TestLogFileName('',SplitFileName(PPFile[current]),'log');
  1632. ExeLogFile:=TestLogFileName('',SplitFileName(PPFile[current]),'elg');
  1633. Verbose(V_Debug,'Using Compiler logfile: '+CompilerLogFile);
  1634. Verbose(V_Debug,'Using Execution logfile: '+ExeLogFile);
  1635. end;
  1636. if Res then
  1637. begin
  1638. if Config.UsesGraph and (not DoGraph) then
  1639. begin
  1640. AddLog(ResLogFile,skipping_graph_test+PPFileInfo[current]);
  1641. { avoid a second attempt by writing to elg file }
  1642. AddLog(EXELogFile,skipping_graph_test+PPFileInfo[current]);
  1643. Verbose(V_Warning,skipping_graph_test);
  1644. Res:=false;
  1645. end;
  1646. end;
  1647. if Res then
  1648. begin
  1649. if Config.IsInteractive and (not DoInteractive) then
  1650. begin
  1651. { avoid a second attempt by writing to elg file }
  1652. AddLog(EXELogFile,skipping_interactive_test+PPFileInfo[current]);
  1653. AddLog(ResLogFile,skipping_interactive_test+PPFileInfo[current]);
  1654. Verbose(V_Warning,skipping_interactive_test);
  1655. Res:=false;
  1656. end;
  1657. end;
  1658. if Res then
  1659. begin
  1660. if Config.IsKnownCompileError and (not DoKnown) then
  1661. begin
  1662. { avoid a second attempt by writing to elg file }
  1663. AddLog(EXELogFile,skipping_known_bug+PPFileInfo[current]);
  1664. AddLog(ResLogFile,skipping_known_bug+PPFileInfo[current]);
  1665. Verbose(V_Warning,skipping_known_bug);
  1666. Res:=false;
  1667. end;
  1668. end;
  1669. if Res and not DoUsual then
  1670. res:=(Config.IsInteractive and DoInteractive) or
  1671. (Config.IsKnownRunError and DoKnown) or
  1672. (Config.UsesGraph and DoGraph);
  1673. if Res then
  1674. begin
  1675. if (Config.MinVersion<>'') and not DoAll then
  1676. begin
  1677. Verbose(V_Debug,'Required compiler version: '+Config.MinVersion);
  1678. Res:=GetCompilerVersion;
  1679. if CompilerVersion<Config.MinVersion then
  1680. begin
  1681. { avoid a second attempt by writing to elg file }
  1682. AddLog(EXELogFile,skipping_compiler_version_too_low+PPFileInfo[current]);
  1683. AddLog(ResLogFile,skipping_compiler_version_too_low+PPFileInfo[current]);
  1684. Verbose(V_Warning,'Compiler version too low '+CompilerVersion+' < '+Config.MinVersion);
  1685. Res:=false;
  1686. end;
  1687. end;
  1688. end;
  1689. if Res then
  1690. begin
  1691. if (Config.MaxVersion<>'') and not DoAll then
  1692. begin
  1693. Verbose(V_Debug,'Highest compiler version: '+Config.MaxVersion);
  1694. Res:=GetCompilerVersion;
  1695. if CompilerVersion>Config.MaxVersion then
  1696. begin
  1697. { avoid a second attempt by writing to elg file }
  1698. AddLog(EXELogFile,skipping_compiler_version_too_high+PPFileInfo[current]);
  1699. AddLog(ResLogFile,skipping_compiler_version_too_high+PPFileInfo[current]);
  1700. Verbose(V_Warning,'Compiler version too high '+CompilerVersion+' > '+Config.MaxVersion);
  1701. Res:=false;
  1702. end;
  1703. end;
  1704. end;
  1705. if Res then
  1706. begin
  1707. if Config.NeedCPU<>'' then
  1708. begin
  1709. Verbose(V_Debug,'Required compiler cpu: '+Config.NeedCPU);
  1710. if not IsInList(CompilerCPU,Config.NeedCPU) then
  1711. begin
  1712. { avoid a second attempt by writing to elg file }
  1713. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo[current]);
  1714. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo[current]);
  1715. Verbose(V_Warning,'Compiler cpu "'+CompilerCPU+'" is not in list "'+Config.NeedCPU+'"');
  1716. Res:=false;
  1717. end;
  1718. end;
  1719. end;
  1720. if Res then
  1721. begin
  1722. if Config.SkipCPU<>'' then
  1723. begin
  1724. Verbose(V_Debug,'Skip compiler cpu: '+Config.SkipCPU);
  1725. if IsInList(CompilerCPU,Config.SkipCPU) then
  1726. begin
  1727. { avoid a second attempt by writing to elg file }
  1728. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo[current]);
  1729. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo[current]);
  1730. Verbose(V_Warning,'Compiler cpu "'+CompilerCPU+'" is in list "'+Config.SkipCPU+'"');
  1731. Res:=false;
  1732. end;
  1733. end;
  1734. end;
  1735. if Res then
  1736. begin
  1737. if Config.SkipEmu<>'' then
  1738. begin
  1739. Verbose(V_Debug,'Skip emulator: '+emulatorname);
  1740. if IsInList(emulatorname,Config.SkipEmu) then
  1741. begin
  1742. { avoid a second attempt by writing to elg file }
  1743. AddLog(EXELogFile,skipping_other_cpu+PPFileInfo[current]);
  1744. AddLog(ResLogFile,skipping_other_cpu+PPFileInfo[current]);
  1745. Verbose(V_Warning,'Emulator "'+emulatorname+'" is in list "'+Config.SkipEmu+'"');
  1746. Res:=false;
  1747. end;
  1748. end;
  1749. end;
  1750. if Res then
  1751. begin
  1752. if Config.NeedTarget<>'' then
  1753. begin
  1754. Verbose(V_Debug,'Required compiler target: '+Config.NeedTarget);
  1755. if not IsInList(CompilerTarget,Config.NeedTarget) then
  1756. begin
  1757. { avoid a second attempt by writing to elg file }
  1758. AddLog(EXELogFile,skipping_other_target+PPFileInfo[current]);
  1759. AddLog(ResLogFile,skipping_other_target+PPFileInfo[current]);
  1760. Verbose(V_Warning,'Compiler target "'+CompilerTarget+'" is not in list "'+Config.NeedTarget+'"');
  1761. Res:=false;
  1762. end;
  1763. end;
  1764. end;
  1765. if Res then
  1766. begin
  1767. if Config.SkipTarget<>'' then
  1768. begin
  1769. Verbose(V_Debug,'Skip compiler target: '+Config.SkipTarget);
  1770. if IsInList(CompilerTarget,Config.SkipTarget) then
  1771. begin
  1772. { avoid a second attempt by writing to elg file }
  1773. AddLog(EXELogFile,skipping_other_target+PPFileInfo[current]);
  1774. AddLog(ResLogFile,skipping_other_target+PPFileInfo[current]);
  1775. Verbose(V_Warning,'Compiler target "'+CompilerTarget+'" is in list "'+Config.SkipTarget+'"');
  1776. Res:=false;
  1777. end;
  1778. end;
  1779. end;
  1780. if Res then
  1781. begin
  1782. { Use known bug, to avoid adding a new entry for this PM 2011-06-24 }
  1783. if Config.NeedLibrary and not TargetCanCompileLibraries then
  1784. begin
  1785. AddLog(EXELogFile,skipping_known_bug+PPFileInfo[current]);
  1786. AddLog(ResLogFile,skipping_known_bug+PPFileInfo[current]);
  1787. Verbose(V_Warning,'Compiler target "'+CompilerTarget+'" does not support library compilation');
  1788. Res:=false;
  1789. end;
  1790. end;
  1791. if Res then
  1792. begin
  1793. Res:=RunCompiler;
  1794. if Res and Config.NeedRecompile then
  1795. Res:=RunCompiler;
  1796. end;
  1797. if Res and (not Config.ShouldFail) then
  1798. begin
  1799. if (Config.NoRun) then
  1800. begin
  1801. { avoid a second attempt by writing to elg file }
  1802. AddLog(EXELogFile,skipping_run_test+PPFileInfo[current]);
  1803. AddLog(ResLogFile,skipping_run_test+PPFileInfo[current]);
  1804. Verbose(V_Debug,skipping_run_test);
  1805. if LibraryExists(PPFile[current],LibraryName) then
  1806. MaybeCopyFiles(LibraryName);
  1807. end
  1808. else if Config.IsKnownRunError and (not DoKnown) then
  1809. begin
  1810. { avoid a second attempt by writing to elg file }
  1811. AddLog(EXELogFile,skipping_known_bug+PPFileInfo[current]);
  1812. AddLog(ResLogFile,skipping_known_bug+PPFileInfo[current]);
  1813. Verbose(V_Warning,skipping_known_bug);
  1814. end
  1815. else
  1816. begin
  1817. if DoExecute then
  1818. begin
  1819. if FileExists(TestOutputFilename('',PPFile[current],'ppu')) or
  1820. FileExists(TestOutputFilename('',PPFile[current],'ppo')) or
  1821. FileExists(TestOutputFilename('',PPFile[current],'ppw')) then
  1822. begin
  1823. AddLog(ExeLogFile,skipping_run_unit+PPFileInfo[current]);
  1824. AddLog(ResLogFile,skipping_run_unit+PPFileInfo[current]);
  1825. Verbose(V_Debug,'Unit found, skipping run test')
  1826. end
  1827. else if LibraryExists(PPFile[current],LibraryName) then
  1828. begin
  1829. Verbose(V_Debug,'Library found, skipping run test');
  1830. MaybeCopyFiles(LibraryName);
  1831. end
  1832. else
  1833. Res:=RunExecutable;
  1834. end;
  1835. end;
  1836. end;
  1837. end;
  1838. begin
  1839. Current:=0;
  1840. PPFile:=TStringList.Create;
  1841. PPFile.Capacity:=10;
  1842. PPFileInfo:=TStringList.Create;
  1843. PPFileInfo.Capacity:=10;
  1844. GetArgs;
  1845. SetTargetDirectoriesStyle;
  1846. SetTargetCanCompileLibraries;
  1847. SetRemoteConfiguration;
  1848. {$ifdef LIMIT83fs}
  1849. UseOSOnly:=true;
  1850. {$else not LIMIT83fs}
  1851. SetUseOSOnly;
  1852. {$endif not LIMIT83fs}
  1853. Verbose(V_Debug,'Found '+ToStr(PPFile.Count)+' tests to run');
  1854. if current>0 then
  1855. for current:=0 to PPFile.Count-1 do
  1856. begin
  1857. SetPPFileInfo;
  1858. TestName:=Copy(PPFile[current],1,Pos('.pp',PPFile[current])-1);
  1859. Verbose(V_Normal,'Running test '+TestName+', file '+PPFile[current]);
  1860. RunTest;
  1861. end;
  1862. PPFile.Free;
  1863. PPFileInfo.Free;
  1864. end.