dotest.pp 61 KB

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