tcunitsearch.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2018 by Michael Van Canneyt
  4. Unit tests for Pascal-to-Javascript converter class.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************
  11. Examples:
  12. ./testpas2js --suite=TestCLI_UnitSearch.
  13. ./testpas2js --suite=TestUS_Program
  14. ./testpas2js --suite=TestUS_UsesEmptyFileFail
  15. }
  16. unit tcunitsearch;
  17. {$mode objfpc}{$H+}
  18. interface
  19. uses
  20. Classes, SysUtils, contnrs,
  21. fpcunit, testregistry,
  22. PScanner, Pas2jsFileUtils, Pas2jsCompiler, Pas2jsFileCache, Pas2jsLogger,
  23. tcmodules;
  24. type
  25. { TTestCompiler }
  26. TTestCompiler = class(TPas2jsCompiler)
  27. private
  28. FExitCode: longint;
  29. protected
  30. function GetExitCode: Longint; override;
  31. procedure SetExitCode(Value: Longint); override;
  32. end;
  33. { TCLIFile }
  34. TCLIFile = class
  35. public
  36. Filename: string;
  37. Source: string;
  38. Age: TPas2jsFileAgeTime;
  39. Attr: TPas2jsFileAttr;
  40. constructor Create(const aFilename, Src: string; aAge: TPas2jsFileAgeTime;
  41. aAttr: TPas2jsFileAttr);
  42. end;
  43. { TCLILogMsg }
  44. TCLILogMsg = class
  45. public
  46. Msg: string;
  47. MsgTxt: string;
  48. MsgType: TMessageType;
  49. MsgNumber: integer;
  50. MsgFile: string;
  51. MsgLine: integer;
  52. MsgCol: integer;
  53. end;
  54. { TCustomTestCLI }
  55. TCustomTestCLI = class(TTestCase)
  56. private
  57. FCurDate: TDateTime;
  58. FErrorCol: integer;
  59. FErrorFile: string;
  60. FErrorLine: integer;
  61. FErrorMsg: string;
  62. FErrorNumber: integer;
  63. FWorkDir: string;
  64. FCompilerExe: string;
  65. FCompiler: TTestCompiler;
  66. FDefaultFileAge: longint;
  67. FFiles: TObjectList; // list of TCLIFile
  68. FLogMsgs: TObjectList; // list ot TCLILogMsg
  69. FParams: TStringList;
  70. function GetExitCode: integer;
  71. function GetFiles(Index: integer): TCLIFile;
  72. function GetLogMsgs(Index: integer): TCLILogMsg;
  73. procedure SetExitCode(const AValue: integer);
  74. procedure SetWorkDir(const AValue: string);
  75. protected
  76. procedure SetUp; override;
  77. procedure TearDown; override;
  78. procedure DoLog(Sender: TObject; const Msg: String);
  79. Function OnReadDirectory(Dir: TPas2jsCachedDirectory): boolean; virtual;
  80. Function OnReadFile(aFilename: string; var aSource: string): boolean; virtual;
  81. procedure OnWriteFile(aFilename: string; Source: string); virtual;
  82. procedure WriteSources;
  83. public
  84. constructor Create; override;
  85. destructor Destroy; override;
  86. procedure Compile(const Args: array of string; ExpectedExitCode: longint = 0);
  87. property Compiler: TTestCompiler read FCompiler;
  88. property CompilerExe: string read FCompilerExe write FCompilerExe;
  89. property Params: TStringList read FParams;
  90. property Files[Index: integer]: TCLIFile read GetFiles; // files an directories
  91. function FileCount: integer;
  92. function FindFile(Filename: string): TCLIFile; // files and directories
  93. function ExpandFilename(const Filename: string): string;
  94. function AddFile(Filename, Source: string): TCLIFile;
  95. function AddFile(Filename: string; const SourceLines: array of string): TCLIFile;
  96. function AddUnit(Filename: string; const Intf, Impl: array of string): TCLIFile;
  97. function AddDir(Filename: string): TCLIFile;
  98. procedure AssertFileExists(Filename: string);
  99. property WorkDir: string read FWorkDir write SetWorkDir;
  100. property DefaultFileAge: longint read FDefaultFileAge write FDefaultFileAge;
  101. property ExitCode: integer read GetExitCode write SetExitCode;
  102. property LogMsgs[Index: integer]: TCLILogMsg read GetLogMsgs;
  103. function GetLogCount: integer;
  104. property ErrorMsg: string read FErrorMsg write FErrorMsg;
  105. property ErrorFile: string read FErrorFile write FErrorFile;
  106. property ErrorLine: integer read FErrorLine write FErrorLine;
  107. property ErrorCol: integer read FErrorCol write FErrorCol;
  108. property ErrorNumber: integer read FErrorNumber write FErrorNumber;
  109. property CurDate: TDateTime read FCurDate write FCurDate;
  110. end;
  111. { TTestCLI_UnitSearch }
  112. TTestCLI_UnitSearch = class(TCustomTestCLI)
  113. published
  114. procedure TestUS_Program;
  115. procedure TestUS_UsesEmptyFileFail;
  116. procedure TestUS_UsesInFile;
  117. procedure TestUS_UsesInFile_Duplicate;
  118. procedure TestUS_UsesInFile_IndirectDuplicate;
  119. end;
  120. function LinesToStr(const Lines: array of string): string;
  121. implementation
  122. function LinesToStr(const Lines: array of string): string;
  123. var
  124. i: Integer;
  125. begin
  126. Result:='';
  127. for i:=low(Lines) to high(Lines) do
  128. Result:=Result+Lines[i]+LineEnding;
  129. end;
  130. { TCLIFile }
  131. constructor TCLIFile.Create(const aFilename, Src: string;
  132. aAge: TPas2jsFileAgeTime; aAttr: TPas2jsFileAttr);
  133. begin
  134. Filename:=aFilename;
  135. Source:=Src;
  136. Age:=aAge;
  137. Attr:=aAttr;
  138. end;
  139. { TTestCompiler }
  140. function TTestCompiler.GetExitCode: Longint;
  141. begin
  142. Result:=FExitCode;
  143. end;
  144. procedure TTestCompiler.SetExitCode(Value: Longint);
  145. begin
  146. FExitCode:=Value;
  147. end;
  148. { TCustomTestCLI }
  149. function TCustomTestCLI.GetFiles(Index: integer): TCLIFile;
  150. begin
  151. Result:=TCLIFile(FFiles[Index]);
  152. end;
  153. function TCustomTestCLI.GetExitCode: integer;
  154. begin
  155. Result:=Compiler.ExitCode;
  156. end;
  157. function TCustomTestCLI.GetLogMsgs(Index: integer): TCLILogMsg;
  158. begin
  159. Result:=TCLILogMsg(FLogMsgs[Index]);
  160. end;
  161. procedure TCustomTestCLI.SetExitCode(const AValue: integer);
  162. begin
  163. Compiler.ExitCode:=AValue;
  164. end;
  165. procedure TCustomTestCLI.SetWorkDir(const AValue: string);
  166. var
  167. NewValue: String;
  168. begin
  169. NewValue:=IncludeTrailingPathDelimiter(ResolveDots(AValue));
  170. if FWorkDir=NewValue then Exit;
  171. FWorkDir:=NewValue;
  172. end;
  173. procedure TCustomTestCLI.SetUp;
  174. begin
  175. inherited SetUp;
  176. FDefaultFileAge:=DateTimeToFileDate(Now);
  177. {$IFDEF Windows}
  178. WorkDir:='P:\test';
  179. CompilerExe:='P:\bin\pas2js.exe';
  180. {$ELSE}
  181. WorkDir:='/home/user';
  182. CompilerExe:='/usr/bin/pas2js';
  183. {$ENDIF}
  184. FCompiler:=TTestCompiler.Create;
  185. Compiler.Log.OnLog:=@DoLog;
  186. Compiler.FileCache.DirectoryCache.OnReadDirectory:=@OnReadDirectory;
  187. Compiler.FileCache.OnReadFile:=@OnReadFile;
  188. Compiler.FileCache.OnWriteFile:=@OnWriteFile;
  189. end;
  190. procedure TCustomTestCLI.TearDown;
  191. begin
  192. FreeAndNil(FCompiler);
  193. FParams.Clear;
  194. FFiles.Clear;
  195. FLogMsgs.Clear;
  196. FErrorMsg:='';
  197. FErrorFile:='';
  198. FErrorLine:=0;
  199. FErrorCol:=0;
  200. FErrorNumber:=0;
  201. inherited TearDown;
  202. end;
  203. procedure TCustomTestCLI.DoLog(Sender: TObject; const Msg: String);
  204. var
  205. LogMsg: TCLILogMsg;
  206. begin
  207. {$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
  208. writeln('TCustomTestCLI.DoLog ',Msg,' File=',Compiler.Log.LastMsgFile,' Line=',Compiler.Log.LastMsgLine);
  209. {$ENDIF}
  210. LogMsg:=TCLILogMsg.Create;
  211. LogMsg.Msg:=Msg;
  212. LogMsg.MsgTxt:=Compiler.Log.LastMsgTxt;
  213. LogMsg.MsgType:=Compiler.Log.LastMsgType;
  214. LogMsg.MsgFile:=Compiler.Log.LastMsgFile;
  215. LogMsg.MsgLine:=Compiler.Log.LastMsgLine;
  216. LogMsg.MsgCol:=Compiler.Log.LastMsgCol;
  217. LogMsg.MsgNumber:=Compiler.Log.LastMsgNumber;
  218. FLogMsgs.Add(LogMsg);
  219. if (LogMsg.MsgType<=mtError) then
  220. begin
  221. if (ErrorFile='')
  222. or ((ErrorLine<1) and (LogMsg.MsgLine>0)) then
  223. begin
  224. ErrorMsg:=LogMsg.MsgTxt;
  225. ErrorFile:=LogMsg.MsgFile;
  226. ErrorLine:=LogMsg.MsgLine;
  227. ErrorCol:=LogMsg.MsgCol;
  228. end;
  229. end;
  230. end;
  231. function TCustomTestCLI.OnReadDirectory(Dir: TPas2jsCachedDirectory): boolean;
  232. var
  233. i: Integer;
  234. aFile: TCLIFile;
  235. Path: String;
  236. begin
  237. Path:=Dir.Path;
  238. //writeln('TCustomTestCLI.ReadDirectory START ',Path,' ',Dir.Count);
  239. Dir.Add('.',DefaultFileAge,faDirectory,4096);
  240. Dir.Add('..',DefaultFileAge,faDirectory,4096);
  241. for i:=0 to FileCount-1 do
  242. begin
  243. aFile:=Files[i];
  244. if CompareFilenames(ExtractFilePath(aFile.Filename),Path)<>0 then continue;
  245. //writeln('TCustomTestCLI.ReadDirectory ',aFile.Filename);
  246. Dir.Add(ExtractFileName(aFile.Filename),aFile.Age,aFile.Attr,length(aFile.Source));
  247. end;
  248. //writeln('TCustomTestCLI.ReadDirectory END ',Path,' ',Dir.Count);
  249. Result:=true;
  250. end;
  251. function TCustomTestCLI.OnReadFile(aFilename: string; var aSource: string
  252. ): boolean;
  253. var
  254. aFile: TCLIFile;
  255. begin
  256. aFile:=FindFile(aFilename);
  257. //writeln('TCustomTestCLI.ReadFile ',aFilename,' Found=',aFile<>nil);
  258. if aFile=nil then exit(false);
  259. if (faDirectory and aFile.Attr)>0 then
  260. begin
  261. {$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
  262. writeln('[20180224000557] TCustomTestCLI.OnReadFile ',aFilename);
  263. {$ENDIF}
  264. EPas2jsFileCache.Create('TCustomTestCLI.OnReadFile: reading directory '+aFilename);
  265. end;
  266. aSource:=aFile.Source;
  267. //writeln('TCustomTestCLI.OnReadFile ',aFile.Filename,' "',LeftStr(aFile.Source,50),'"');
  268. Result:=true;
  269. end;
  270. procedure TCustomTestCLI.OnWriteFile(aFilename: string; Source: string);
  271. var
  272. aFile: TCLIFile;
  273. {$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
  274. //i: Integer;
  275. {$ENDIF}
  276. begin
  277. aFile:=FindFile(aFilename);
  278. {$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
  279. writeln('TCustomTestCLI.WriteFile ',aFilename,' Found=',aFile<>nil,' SrcLen=',length(Source));
  280. {$ENDIF}
  281. if aFile<>nil then
  282. begin
  283. if (faDirectory and aFile.Attr)>0 then
  284. begin
  285. {$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
  286. writeln('[20180223175616] TCustomTestCLI.OnWriteFile ',aFilename);
  287. {$ENDIF}
  288. raise EPas2jsFileCache.Create('unable to write file to directory "'+aFilename+'"');
  289. end;
  290. end else
  291. begin
  292. {$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
  293. //writeln('TCustomTestCLI.OnWriteFile FFiles: ',FFiles.Count);
  294. //for i:=0 to FFiles.Count-1 do
  295. //begin
  296. // aFile:=TCLIFile(FFiles[i]);
  297. // writeln(' ',i,': Filename=',aFile.Filename,' ',CompareFilenames(aFile.Filename,aFilename),' Dir=',(aFile.Attr and faDirectory)>0,' Len=',length(aFile.Source));
  298. //end;
  299. {$ENDIF}
  300. aFile:=TCLIFile.Create(aFilename,'',0,0);
  301. FFiles.Add(aFile);
  302. end;
  303. aFile.Source:=Source;
  304. aFile.Attr:=faNormal;
  305. aFile.Age:=DateTimeToFileDate(CurDate);
  306. writeln('TCustomTestCLI.OnWriteFile ',aFile.Filename,' Found=',FindFile(aFilename)<>nil,' "',LeftStr(aFile.Source,50),'" ');
  307. end;
  308. procedure TCustomTestCLI.WriteSources;
  309. var
  310. i, j, aRow, aCol: Integer;
  311. aFile: TCLIFile;
  312. SrcLines: TStringList;
  313. Line, aFilename: String;
  314. IsSrc: Boolean;
  315. begin
  316. writeln('TCustomTestCLI.WriteSources START');
  317. aFilename:=ErrorFile;
  318. aRow:=ErrorLine;
  319. aCol:=ErrorCol;
  320. SrcLines:=TStringList.Create;
  321. try
  322. for i:=0 to FileCount-1 do
  323. begin
  324. aFile:=Files[i];
  325. if (faDirectory and aFile.Attr)>0 then continue;
  326. writeln('Testcode:-File="',aFile.Filename,'"----------------------------------:');
  327. SrcLines.Text:=aFile.Source;
  328. IsSrc:=ExtractFilename(aFile.Filename)=ExtractFileName(aFilename);
  329. for j:=1 to SrcLines.Count do
  330. begin
  331. Line:=SrcLines[j-1];
  332. if IsSrc and (j=aRow) then
  333. begin
  334. write('*');
  335. Line:=LeftStr(Line,aCol-1)+'|'+copy(Line,aCol,length(Line));
  336. end;
  337. writeln(Format('%:4d: ',[j]),Line);
  338. end;
  339. end;
  340. finally
  341. SrcLines.Free;
  342. end;
  343. end;
  344. constructor TCustomTestCLI.Create;
  345. begin
  346. inherited Create;
  347. FFiles:=TObjectList.Create(true);
  348. FLogMsgs:=TObjectList.Create(true);
  349. FParams:=TStringList.Create;
  350. CurDate:=Now;
  351. end;
  352. destructor TCustomTestCLI.Destroy;
  353. begin
  354. FreeAndNil(FFiles);
  355. FreeAndNil(FLogMsgs);
  356. FreeAndNil(FParams);
  357. inherited Destroy;
  358. end;
  359. procedure TCustomTestCLI.Compile(const Args: array of string;
  360. ExpectedExitCode: longint);
  361. var
  362. i: Integer;
  363. begin
  364. AssertEquals('Initial System.ExitCode',0,system.ExitCode);
  365. for i:=low(Args) to High(Args) do
  366. Params.Add(Args[i]);
  367. try
  368. try
  369. //writeln('TCustomTestCLI.Compile WorkDir=',WorkDir);
  370. Compiler.Run(CompilerExe,WorkDir,Params,false);
  371. except
  372. on E: ECompilerTerminate do
  373. begin
  374. {$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
  375. writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
  376. {$ENDIF}
  377. end;
  378. on E: Exception do
  379. begin
  380. {$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
  381. writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
  382. {$ENDIF}
  383. Fail('TCustomTestCLI.Compile '+E.ClassName+':'+E.Message);
  384. end;
  385. end;
  386. finally
  387. Compiler.Log.CloseOutputFile;
  388. end;
  389. if ExpectedExitCode<>ExitCode then
  390. begin
  391. WriteSources;
  392. AssertEquals('ExitCode',ExpectedExitCode,ExitCode);
  393. end;
  394. end;
  395. function TCustomTestCLI.FileCount: integer;
  396. begin
  397. Result:=FFiles.Count;
  398. end;
  399. function TCustomTestCLI.FindFile(Filename: string): TCLIFile;
  400. var
  401. i: Integer;
  402. begin
  403. Filename:=ExpandFilename(Filename);
  404. for i:=0 to FileCount-1 do
  405. if CompareFilenames(Files[i].Filename,Filename)=0 then
  406. exit(Files[i]);
  407. Result:=nil;
  408. end;
  409. function TCustomTestCLI.ExpandFilename(const Filename: string): string;
  410. begin
  411. Result:=SetDirSeparators(Filename);
  412. if not FilenameIsAbsolute(Result) then
  413. Result:=WorkDir+Result;
  414. Result:=ResolveDots(Result);
  415. end;
  416. function TCustomTestCLI.AddFile(Filename, Source: string): TCLIFile;
  417. begin
  418. Filename:=ExpandFilename(Filename);
  419. {$IFDEF VerbosePCUFiler}
  420. writeln('TCustomTestCLI.AddFile ',Filename);
  421. {$ENDIF}
  422. Result:=FindFile(Filename);
  423. if Result<>nil then
  424. raise Exception.Create('[20180224001050] TCustomTestCLI.AddFile already exists: '+Filename);
  425. Result:=TCLIFile.Create(Filename,Source,DefaultFileAge,faNormal);
  426. FFiles.Add(Result);
  427. AddDir(ExtractFilePath(Filename));
  428. end;
  429. function TCustomTestCLI.AddFile(Filename: string;
  430. const SourceLines: array of string): TCLIFile;
  431. begin
  432. Result:=AddFile(Filename,LinesToStr(SourceLines));
  433. end;
  434. function TCustomTestCLI.AddUnit(Filename: string; const Intf,
  435. Impl: array of string): TCLIFile;
  436. var
  437. Name: String;
  438. begin
  439. Name:=ExtractFilenameOnly(Filename);
  440. Result:=AddFile(Filename,
  441. 'unit '+Name+';'+LineEnding
  442. +'interface'+LineEnding
  443. +LinesToStr(Intf)
  444. +'implementation'+LineEnding
  445. +LinesToStr(Impl)
  446. +'end.'+LineEnding);
  447. end;
  448. function TCustomTestCLI.AddDir(Filename: string): TCLIFile;
  449. var
  450. p: Integer;
  451. Dir: String;
  452. aFile: TCLIFile;
  453. begin
  454. Result:=nil;
  455. Filename:=IncludeTrailingPathDelimiter(ExpandFilename(Filename));
  456. p:=length(Filename);
  457. while p>1 do
  458. begin
  459. if Filename[p]=PathDelim then
  460. begin
  461. Dir:=LeftStr(Filename,p-1);
  462. aFile:=FindFile(Dir);
  463. if Result=nil then
  464. Result:=aFile;
  465. if aFile=nil then
  466. begin
  467. {$IFDEF VerbosePCUFiler}
  468. writeln('TCustomTestCLI.AddDir add Dir=',Dir);
  469. {$ENDIF}
  470. FFiles.Add(TCLIFile.Create(Dir,'',DefaultFileAge,faDirectory));
  471. end
  472. else if (aFile.Attr and faDirectory)=0 then
  473. begin
  474. {$IFDEF VerbosePCUFiler}
  475. writeln('[20180224001036] TCustomTestCLI.AddDir file exists: Dir=',Dir);
  476. {$ENDIF}
  477. raise EPas2jsFileCache.Create('[20180224001036] TCustomTestCLI.AddDir Dir='+Dir);
  478. end;
  479. dec(p);
  480. end else
  481. dec(p);
  482. end;
  483. end;
  484. procedure TCustomTestCLI.AssertFileExists(Filename: string);
  485. var
  486. aFile: TCLIFile;
  487. begin
  488. aFile:=FindFile(Filename);
  489. AssertNotNull('File not found: '+Filename,aFile);
  490. end;
  491. function TCustomTestCLI.GetLogCount: integer;
  492. begin
  493. Result:=FLogMsgs.Count;
  494. end;
  495. { TTestCLI_UnitSearch }
  496. procedure TTestCLI_UnitSearch.TestUS_Program;
  497. begin
  498. AddUnit('system.pp',[''],['']);
  499. AddFile('test1.pas',[
  500. 'begin',
  501. 'end.']);
  502. Compile(['test1.pas','-va']);
  503. end;
  504. procedure TTestCLI_UnitSearch.TestUS_UsesEmptyFileFail;
  505. begin
  506. AddFile('system.pp','');
  507. AddFile('test1.pas',[
  508. 'begin',
  509. 'end.']);
  510. Compile(['test1.pas',''],ExitCodeSyntaxError);
  511. AssertEquals('ErrorMsg','Expected "unit"',ErrorMsg);
  512. end;
  513. procedure TTestCLI_UnitSearch.TestUS_UsesInFile;
  514. begin
  515. AddUnit('system.pp',[''],['']);
  516. AddUnit('unit1.pas',
  517. ['uses bird in ''unit2.pas'';',
  518. 'var a: longint;'],
  519. ['']);
  520. AddUnit('unit2.pas',
  521. ['var b: longint;'],
  522. ['']);
  523. AddFile('test1.pas',[
  524. 'uses foo in ''unit1.pas'', bar in ''unit2.pas'';',
  525. 'begin',
  526. ' bar.b:=foo.a;',
  527. ' a:=b;',
  528. 'end.']);
  529. Compile(['test1.pas','-Jc']);
  530. end;
  531. procedure TTestCLI_UnitSearch.TestUS_UsesInFile_Duplicate;
  532. begin
  533. AddUnit('system.pp',[''],['']);
  534. AddUnit('unit1.pas',
  535. ['var a: longint;'],
  536. ['']);
  537. AddUnit('sub/unit1.pas',
  538. ['var b: longint;'],
  539. ['']);
  540. AddFile('test1.pas',[
  541. 'uses foo in ''unit1.pas'', bar in ''sub/unit1.pas'';',
  542. 'begin',
  543. ' bar.b:=foo.a;',
  544. ' a:=b;',
  545. 'end.']);
  546. Compile(['test1.pas','-Jc'],ExitCodeSyntaxError);
  547. AssertEquals('ErrorMsg','Duplicate file found: "/home/user/sub/unit1.pas" and "/home/user/unit1.pas"',ErrorMsg);
  548. end;
  549. procedure TTestCLI_UnitSearch.TestUS_UsesInFile_IndirectDuplicate;
  550. begin
  551. AddUnit('system.pp',[''],['']);
  552. AddUnit('unit1.pas',
  553. ['var a: longint;'],
  554. ['']);
  555. AddUnit('sub/unit1.pas',
  556. ['var b: longint;'],
  557. ['']);
  558. AddUnit('unit2.pas',
  559. ['uses unit1 in ''unit1.pas'';'],
  560. ['']);
  561. AddFile('test1.pas',[
  562. 'uses unit2, foo in ''sub/unit1.pas'';',
  563. 'begin',
  564. 'end.']);
  565. Compile(['test1.pas','-Jc'],ExitCodeSyntaxError);
  566. AssertEquals('ErrorMsg','Duplicate file found: "/home/user/unit1.pas" and "/home/user/sub/unit1.pas"',ErrorMsg);
  567. end;
  568. Initialization
  569. RegisterTests([TTestCLI_UnitSearch]);
  570. end.