dotest.pp 60 KB

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