dotest.pp 57 KB

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