dotest.pp 57 KB

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