dotest.pp 58 KB

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