dotest.pp 59 KB

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