dotest.pp 58 KB

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