tcmoduleparser.pas 12 KB

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