tcmoduleparser.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. unit tcmoduleparser;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, pastree, pscanner, pparser,
  6. tcbaseparser, testregistry;
  7. Type
  8. { TTestModuleParser }
  9. TTestModuleParser = class(TTestParser)
  10. private
  11. function GetIf: TInterfaceSection;
  12. function GetIm: TImplementationSection;
  13. function CheckUnit(AIndex: Integer; const AName: String; Section: TPasSection): TPasUnresolvedUnitRef;
  14. Protected
  15. Procedure ParseUnit;
  16. Procedure ParseProgram;
  17. Procedure ParseLibrary;
  18. Procedure AssertProgramError;
  19. Property ImplSection : TImplementationSection Read GetIm;
  20. Property IntfSection : TInterfaceSection Read GetIf;
  21. Published
  22. Procedure TestEmptyUnit;
  23. Procedure TestUnitOneUses;
  24. Procedure TestUnitTwoUses;
  25. Procedure TestUnitOneImplUses;
  26. Procedure TestUnitTwoImplUses;
  27. Procedure TestEmptyUnitInitialization;
  28. Procedure TestEmptyUnitFinalization;
  29. Procedure TestEmptyUnitInitializationFinalization;
  30. Procedure TestEmptyUnitBegin;
  31. Procedure TestEmptyProgram;
  32. Procedure TestEmptyProgramInputOUtput;
  33. Procedure TestEmptyProgramNoInitialization;
  34. Procedure TestEmptyProgramNoFinalization;
  35. Procedure TestEmptyProgramMissingBegin;
  36. Procedure TestEmptyProgramNoheader;
  37. Procedure TestEmptyProgramUses;
  38. Procedure TestEmptyProgramUsesTwoUnits;
  39. Procedure TestEmptyProgramUsesUnitIn;
  40. Procedure TestEmptyLibrary;
  41. Procedure TestEmptyLibraryUses;
  42. Procedure TestEmptyLibraryExports;
  43. Procedure TestEmptyLibraryExportsAlias;
  44. Procedure TestEmptyLibraryExportsIndex;
  45. Procedure TestEmptyLibraryExportsIndexAndName;
  46. Procedure TestEmptyLibraryExportsTwo;
  47. Procedure TestEmptyLibraryExportsTwoAlias;
  48. Procedure TestEmptyLibraryExportsTwoIndex;
  49. end;
  50. implementation
  51. { TTestModuleParser }
  52. function TTestModuleParser.GetIf: TInterfaceSection;
  53. begin
  54. Result:=Module.InterfaceSection;
  55. end;
  56. function TTestModuleParser.GetIm: TImplementationSection;
  57. begin
  58. Result:=Module.ImplementationSection;
  59. end;
  60. procedure TTestModuleParser.ParseUnit;
  61. begin
  62. EndSource;
  63. ParseModule;
  64. AssertNotNull('Have interface',Module.InterfaceSection);
  65. Declarations:=Module.InterfaceSection;
  66. AssertEquals('Interface section',TInterfaceSection,Declarations.ClassType);
  67. AssertNotNull('Have implmeentation',Module.ImplementationSection);
  68. AssertEquals('implementation section',TImplementationSection,Module.ImplementationSection.ClassType);
  69. AssertNotNull('Have interface units',IntfSection.UsesList);
  70. AssertNotNull('Have implementation units',ImplSection.UsesList);
  71. end;
  72. procedure TTestModuleParser.ParseProgram;
  73. begin
  74. EndSource;
  75. ParseModule;
  76. AssertEquals('Is program',TPasProgram,Module.ClassType);
  77. end;
  78. procedure TTestModuleParser.ParseLibrary;
  79. begin
  80. EndSource;
  81. ParseModule;
  82. AssertEquals('Is library',TPasLibrary,Module.ClassType);
  83. end;
  84. procedure TTestModuleParser.AssertProgramError;
  85. begin
  86. AssertException(EParserError,@ParseProgram)
  87. end;
  88. function TTestModuleParser.CheckUnit(AIndex: Integer; const AName: String;
  89. Section: TPasSection): TPasUnresolvedUnitRef;
  90. Var
  91. C : string;
  92. AList: TFPList;
  93. Clause: TPasUsesClause;
  94. begin
  95. Result:=nil;
  96. C:='Unit '+IntTostr(AIndex)+' ';
  97. AList:=Section.UsesList;
  98. AssertNotNull('Have useslist',AList);
  99. if (AIndex>=AList.Count) then
  100. Fail(Format('Index %d larger than unit list count %d',[AIndex,AList.Count ]));
  101. AssertNotNull('Have pascal element',AList[AIndex]);
  102. AssertEquals(C+'Correct class',TPasUnresolvedUnitRef,TObject(AList[AIndex]).CLassType);
  103. Clause:=Section.UsesClause;
  104. if AIndex>=length(Clause) then
  105. Fail(Format('Index %d larger than unit list count %d',[AIndex,length(Clause) ]));
  106. AssertNotNull('Have pascal element',Clause[AIndex]);
  107. AssertEquals(C+'Correct class',TPasUsesUnit,Clause[AIndex].ClassType);
  108. AssertNotNull(C+'Has Module',Clause[AIndex].Module);
  109. AssertEquals(C+'Correct module class',TPasUnresolvedUnitRef,Clause[AIndex].Module.ClassType);
  110. Result:=TPasUnresolvedUnitRef(Clause[AIndex].Module);
  111. AssertEquals(C+'Unit name correct',AName,Result.Name);
  112. end;
  113. procedure TTestModuleParser.TestEmptyUnit;
  114. begin
  115. StartUnit('unit1');
  116. StartImplementation;
  117. ParseUnit;
  118. AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
  119. AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
  120. CheckUnit(0,'System',IntfSection);
  121. AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
  122. AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
  123. end;
  124. procedure TTestModuleParser.TestUnitOneUses;
  125. begin
  126. StartUnit('unit1');
  127. UsesClause(['a']);
  128. StartImplementation;
  129. ParseUnit;
  130. AssertEquals('Two interface units',2,IntfSection.UsesList.Count);
  131. AssertEquals('Two interface units',2,length(IntfSection.UsesClause));
  132. CheckUnit(0,'System',IntfSection);
  133. CheckUnit(1,'a',IntfSection);
  134. AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
  135. AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
  136. end;
  137. procedure TTestModuleParser.TestUnitTwoUses;
  138. begin
  139. StartUnit('unit1');
  140. UsesClause(['a','b']);
  141. StartImplementation;
  142. ParseUnit;
  143. AssertEquals('Three interface units',3,IntfSection.UsesList.Count);
  144. AssertEquals('Three interface units',3,length(IntfSection.UsesClause));
  145. CheckUnit(0,'System',IntfSection);
  146. CheckUnit(1,'a',IntfSection);
  147. CheckUnit(2,'b',IntfSection);
  148. AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
  149. AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
  150. end;
  151. procedure TTestModuleParser.TestUnitOneImplUses;
  152. begin
  153. StartUnit('unit1');
  154. StartImplementation;
  155. UsesClause(['a']);
  156. ParseUnit;
  157. AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
  158. AssertEquals('One implementation units',1,length(ImplSection.UsesClause));
  159. CheckUnit(0,'a',ImplSection);
  160. AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
  161. AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
  162. CheckUnit(0,'System',IntfSection);
  163. end;
  164. procedure TTestModuleParser.TestUnitTwoImplUses;
  165. begin
  166. StartUnit('unit1');
  167. StartImplementation;
  168. UsesClause(['a','b']);
  169. ParseUnit;
  170. AssertEquals('One interface unit',1,IntfSection.UsesList.Count);
  171. AssertEquals('One interface unit',1,length(IntfSection.UsesClause));
  172. CheckUnit(0,'System',IntfSection);
  173. AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
  174. AssertEquals('Two implementation units',2,length(ImplSection.UsesClause));
  175. CheckUnit(0,'a',ImplSection);
  176. CheckUnit(1,'b',ImplSection);
  177. end;
  178. procedure TTestModuleParser.TestEmptyUnitInitialization;
  179. begin
  180. StartUnit('unit1');
  181. StartImplementation;
  182. Add('initialization');
  183. ParseUnit;
  184. AssertNotNull('Have initialization section',Module.InitializationSection);
  185. AssertNull('Have no finalization section',Module.FinalizationSection)
  186. end;
  187. procedure TTestModuleParser.TestEmptyUnitFinalization;
  188. begin
  189. StartUnit('unit1');
  190. StartImplementation;
  191. Add('finalization');
  192. ParseUnit;
  193. AssertNull('Have no initalization section',Module.InitializationSection);
  194. AssertNotNull('Have finalization section',Module.FinalizationSection)
  195. end;
  196. procedure TTestModuleParser.TestEmptyUnitInitializationFinalization;
  197. begin
  198. StartUnit('unit1');
  199. StartImplementation;
  200. Add('initialization');
  201. Add('finalization');
  202. ParseUnit;
  203. AssertNotNull('Have finalization section',Module.InitializationSection);
  204. AssertNotNull('Have finalization section',Module.FinalizationSection);
  205. end;
  206. procedure TTestModuleParser.TestEmptyUnitBegin;
  207. begin
  208. StartUnit('unit1');
  209. StartImplementation;
  210. Add('begin');
  211. ParseUnit;
  212. AssertNotNull('Have initialization section',Module.InitializationSection);
  213. AssertNull('Have no finalization section',Module.FinalizationSection)
  214. end;
  215. procedure TTestModuleParser.TestEmptyProgram;
  216. begin
  217. StartProgram('something');
  218. Add('begin');
  219. ParseProgram;
  220. end;
  221. procedure TTestModuleParser.TestEmptyProgramInputOUtput;
  222. begin
  223. StartProgram('something','input','output');
  224. Add('begin');
  225. ParseProgram;
  226. end;
  227. procedure TTestModuleParser.TestEmptyProgramNoInitialization;
  228. begin
  229. StartProgram('something','input','output');
  230. Add('initialization');
  231. AssertProgramError;
  232. end;
  233. procedure TTestModuleParser.TestEmptyProgramNoFinalization;
  234. begin
  235. StartProgram('something','input','output');
  236. Add('finalization');
  237. AssertProgramError;
  238. end;
  239. procedure TTestModuleParser.TestEmptyProgramMissingBegin;
  240. begin
  241. StartProgram('something','input','output');
  242. AssertProgramError;
  243. end;
  244. procedure TTestModuleParser.TestEmptyProgramNoheader;
  245. begin
  246. Add('begin');
  247. ParseProgram;
  248. end;
  249. procedure TTestModuleParser.TestEmptyProgramUses;
  250. begin
  251. UsesClause(['a']);
  252. Add('begin');
  253. ParseProgram;
  254. AssertEquals('Two interface units',2, PasProgram.ProgramSection.UsesList.Count);
  255. AssertEquals('Two interface units',2, length(PasProgram.ProgramSection.UsesClause));
  256. CheckUnit(0,'System',PasProgram.ProgramSection);
  257. CheckUnit(1,'a',PasProgram.ProgramSection);
  258. end;
  259. procedure TTestModuleParser.TestEmptyProgramUsesTwoUnits;
  260. begin
  261. UsesClause(['a','b']);
  262. Add('begin');
  263. ParseProgram;
  264. AssertEquals('Three interface units',3, PasProgram.ProgramSection.UsesList.Count);
  265. AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
  266. CheckUnit(0,'System',PasProgram.ProgramSection);
  267. CheckUnit(1,'a',PasProgram.ProgramSection);
  268. CheckUnit(2,'b',PasProgram.ProgramSection);
  269. end;
  270. procedure TTestModuleParser.TestEmptyProgramUsesUnitIn;
  271. Var
  272. U : TPasUnresolvedUnitRef;
  273. begin
  274. UsesClause(['a in ''../a.pas''','b']);
  275. Add('begin');
  276. ParseProgram;
  277. AssertEquals('Three interface unit',3, PasProgram.ProgramSection.UsesList.Count);
  278. AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
  279. CheckUnit(0,'System',PasProgram.ProgramSection);
  280. U:=CheckUnit(1,'a',PasProgram.ProgramSection);
  281. AssertEquals('Filename','''../a.pas''',U.FileName);
  282. CheckUnit(2,'b',PasProgram.ProgramSection);
  283. end;
  284. procedure TTestModuleParser.TestEmptyLibrary;
  285. begin
  286. StartLibrary('');
  287. ParseLibrary;
  288. AssertEquals('Correct class',TPasLibrary,Module.ClassType);
  289. end;
  290. procedure TTestModuleParser.TestEmptyLibraryUses;
  291. begin
  292. StartLibrary('');
  293. UsesClause(['a']);
  294. ParseLibrary;
  295. AssertEquals('Correct class',TPasLibrary,Module.ClassType);
  296. AssertEquals('Two interface units',2, PasLibrary.LibrarySection.UsesList.Count);
  297. AssertEquals('Two interface units',2, length(PasLibrary.LibrarySection.UsesClause));
  298. CheckUnit(0,'System',PasLibrary.LibrarySection);
  299. CheckUnit(1,'a',PasLibrary.LibrarySection);
  300. end;
  301. procedure TTestModuleParser.TestEmptyLibraryExports;
  302. begin
  303. StartLibrary('');
  304. UsesClause(['b']);
  305. Add('exports A;');
  306. ParseLibrary;
  307. AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
  308. AssertExportSymbol('Export symbol a',0,'A','',-1);
  309. end;
  310. procedure TTestModuleParser.TestEmptyLibraryExportsAlias;
  311. begin
  312. StartLibrary('');
  313. UsesClause(['b']);
  314. Add('exports A name ''c'';');
  315. ParseLibrary;
  316. AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
  317. AssertExportSymbol('Export symbol a',0,'A','c',-1);
  318. end;
  319. procedure TTestModuleParser.TestEmptyLibraryExportsIndex;
  320. begin
  321. StartLibrary('');
  322. UsesClause(['b']);
  323. Add('exports A index 23;');
  324. ParseLibrary;
  325. AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
  326. AssertExportSymbol('Export symbol a',0,'A','',23);
  327. end;
  328. procedure TTestModuleParser.TestEmptyLibraryExportsIndexAndName;
  329. begin
  330. StartLibrary('');
  331. UsesClause(['b']);
  332. Add('exports A index 23 name ''funa'';');
  333. ParseLibrary;
  334. AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
  335. AssertExportSymbol('Export symbol a',0,'A','funa',23);
  336. end;
  337. procedure TTestModuleParser.TestEmptyLibraryExportsTwo;
  338. begin
  339. StartLibrary('');
  340. UsesClause(['b']);
  341. Add('exports A , C;');
  342. ParseLibrary;
  343. AssertEquals('2 export symbol',2,PasLibrary.LibrarySection.ExportSymbols.Count);
  344. AssertExportSymbol('Export symbol a',0,'A','',-1);
  345. AssertExportSymbol('Export symbol C',1,'C','',-1);
  346. end;
  347. procedure TTestModuleParser.TestEmptyLibraryExportsTwoAlias;
  348. begin
  349. StartLibrary('');
  350. UsesClause(['b']);
  351. Add('exports A name ''de'', C;');
  352. ParseLibrary;
  353. AssertEquals('2 export symbol',2,PasLibrary.LibrarySection.ExportSymbols.Count);
  354. AssertExportSymbol('Export symbol a',0,'A','de',-1);
  355. AssertExportSymbol('Export symbol C',1,'C','',-1);
  356. end;
  357. procedure TTestModuleParser.TestEmptyLibraryExportsTwoIndex;
  358. begin
  359. StartLibrary('');
  360. UsesClause(['b']);
  361. Add('exports A index 23, C;');
  362. ParseLibrary;
  363. AssertEquals('2 export symbol',2,PasLibrary.LibrarySection.ExportSymbols.Count);
  364. AssertExportSymbol('Export symbol a',0,'A','',23);
  365. AssertExportSymbol('Export symbol C',1,'C','',-1);
  366. end;
  367. initialization
  368. RegisterTests([TTestModuleParser]);
  369. end.