dotest.pp 57 KB

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