dotest.pp 60 KB

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