2
0

dotest.pp 59 KB

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