dotest.pp 60 KB

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