dotest.pp 58 KB

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