mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-18 06:38:20 +02:00
409 lines
12 KiB
ObjectPascal
409 lines
12 KiB
ObjectPascal
unit tcmoduleparser;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, fpcunit, pastree, pscanner, pparser,
|
|
tcbaseparser, testregistry;
|
|
|
|
Type
|
|
{ TTestModuleParser }
|
|
|
|
TTestModuleParser = class(TTestParser)
|
|
private
|
|
function GetIf: TInterfaceSection;
|
|
function GetIm: TImplementationSection;
|
|
function CheckUnit(AIndex: Integer; const AName: String; Section: TPasSection): TPasUnresolvedUnitRef;
|
|
Protected
|
|
Procedure ParseUnit;
|
|
Procedure ParseProgram;
|
|
Procedure ParseLibrary;
|
|
Procedure AssertProgramError;
|
|
Property ImplSection : TImplementationSection Read GetIm;
|
|
Property IntfSection : TInterfaceSection Read GetIf;
|
|
Published
|
|
Procedure TestEmptyUnit;
|
|
Procedure TestUnitOneUses;
|
|
Procedure TestUnitTwoUses;
|
|
Procedure TestUnitOneImplUses;
|
|
Procedure TestUnitTwoImplUses;
|
|
Procedure TestEmptyUnitInitialization;
|
|
Procedure TestEmptyUnitFinalization;
|
|
Procedure TestEmptyUnitInitializationFinalization;
|
|
Procedure TestEmptyUnitBegin;
|
|
Procedure TestEmptyProgram;
|
|
Procedure TestEmptyProgramInputOUtput;
|
|
Procedure TestEmptyProgramNoInitialization;
|
|
Procedure TestEmptyProgramNoFinalization;
|
|
Procedure TestEmptyProgramMissingBegin;
|
|
Procedure TestEmptyProgramNoheader;
|
|
Procedure TestEmptyProgramUses;
|
|
Procedure TestEmptyProgramUsesTwoUnits;
|
|
Procedure TestEmptyProgramUsesUnitIn;
|
|
Procedure TestEmptyLibrary;
|
|
Procedure TestEmptyLibraryUses;
|
|
Procedure TestEmptyLibraryExports;
|
|
Procedure TestEmptyLibraryExportsAlias;
|
|
Procedure TestEmptyLibraryExportsIndex;
|
|
Procedure TestEmptyLibraryExportsTwo;
|
|
Procedure TestEmptyLibraryExportsTwoAlias;
|
|
Procedure TestEmptyLibraryExportsTwoIndex;
|
|
end;
|
|
|
|
implementation
|
|
{ TTestModuleParser }
|
|
|
|
function TTestModuleParser.GetIf: TInterfaceSection;
|
|
begin
|
|
Result:=Module.InterfaceSection;
|
|
end;
|
|
|
|
function TTestModuleParser.GetIm: TImplementationSection;
|
|
begin
|
|
Result:=Module.ImplementationSection;
|
|
end;
|
|
|
|
procedure TTestModuleParser.ParseUnit;
|
|
begin
|
|
EndSource;
|
|
ParseModule;
|
|
AssertNotNull('Have interface',Module.InterfaceSection);
|
|
Declarations:=Module.InterfaceSection;
|
|
AssertEquals('Interface section',TInterfaceSection,Declarations.ClassType);
|
|
AssertNotNull('Have implmeentation',Module.ImplementationSection);
|
|
AssertEquals('implementation section',TImplementationSection,Module.ImplementationSection.ClassType);
|
|
AssertNotNull('Have interface units',IntfSection.UsesList);
|
|
AssertNotNull('Have implementation units',ImplSection.UsesList);
|
|
end;
|
|
|
|
procedure TTestModuleParser.ParseProgram;
|
|
begin
|
|
EndSource;
|
|
ParseModule;
|
|
AssertEquals('Is program',TPasProgram,Module.ClassType);
|
|
end;
|
|
|
|
procedure TTestModuleParser.ParseLibrary;
|
|
begin
|
|
EndSource;
|
|
ParseModule;
|
|
AssertEquals('Is library',TPasLibrary,Module.ClassType);
|
|
end;
|
|
|
|
procedure TTestModuleParser.AssertProgramError;
|
|
begin
|
|
AssertException(EParserError,@ParseProgram)
|
|
end;
|
|
|
|
function TTestModuleParser.CheckUnit(AIndex: Integer; const AName: String;
|
|
Section: TPasSection): TPasUnresolvedUnitRef;
|
|
|
|
Var
|
|
C : string;
|
|
AList: TFPList;
|
|
Clause: TPasUsesClause;
|
|
|
|
begin
|
|
Result:=nil;
|
|
C:='Unit '+IntTostr(AIndex)+' ';
|
|
|
|
AList:=Section.UsesList;
|
|
AssertNotNull('Have useslist',AList);
|
|
if (AIndex>=AList.Count) then
|
|
Fail(Format('Index %d larger than unit list count %d',[AIndex,AList.Count ]));
|
|
AssertNotNull('Have pascal element',AList[AIndex]);
|
|
AssertEquals(C+'Correct class',TPasUnresolvedUnitRef,TObject(AList[AIndex]).CLassType);
|
|
|
|
Clause:=Section.UsesClause;
|
|
if AIndex>=length(Clause) then
|
|
Fail(Format('Index %d larger than unit list count %d',[AIndex,length(Clause) ]));
|
|
AssertNotNull('Have pascal element',Clause[AIndex]);
|
|
AssertEquals(C+'Correct class',TPasUsesUnit,Clause[AIndex].ClassType);
|
|
AssertNotNull(C+'Has Module',Clause[AIndex].Module);
|
|
AssertEquals(C+'Correct module class',TPasUnresolvedUnitRef,Clause[AIndex].Module.ClassType);
|
|
Result:=TPasUnresolvedUnitRef(Clause[AIndex].Module);
|
|
AssertEquals(C+'Unit name correct',AName,Result.Name);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyUnit;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
ParseUnit;
|
|
AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
|
|
AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
|
|
CheckUnit(0,'System',IntfSection);
|
|
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
|
AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestUnitOneUses;
|
|
begin
|
|
StartUnit('unit1');
|
|
UsesClause(['a']);
|
|
StartImplementation;
|
|
ParseUnit;
|
|
AssertEquals('Two interface units',2,IntfSection.UsesList.Count);
|
|
AssertEquals('Two interface units',2,length(IntfSection.UsesClause));
|
|
CheckUnit(0,'System',IntfSection);
|
|
CheckUnit(1,'a',IntfSection);
|
|
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
|
AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestUnitTwoUses;
|
|
begin
|
|
StartUnit('unit1');
|
|
UsesClause(['a','b']);
|
|
StartImplementation;
|
|
ParseUnit;
|
|
AssertEquals('Three interface units',3,IntfSection.UsesList.Count);
|
|
AssertEquals('Three interface units',3,length(IntfSection.UsesClause));
|
|
CheckUnit(0,'System',IntfSection);
|
|
CheckUnit(1,'a',IntfSection);
|
|
CheckUnit(2,'b',IntfSection);
|
|
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
|
AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestUnitOneImplUses;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
UsesClause(['a']);
|
|
ParseUnit;
|
|
AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
|
|
AssertEquals('One implementation units',1,length(ImplSection.UsesClause));
|
|
CheckUnit(0,'a',ImplSection);
|
|
AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
|
|
AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
|
|
CheckUnit(0,'System',IntfSection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestUnitTwoImplUses;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
UsesClause(['a','b']);
|
|
ParseUnit;
|
|
AssertEquals('One interface unit',1,IntfSection.UsesList.Count);
|
|
AssertEquals('One interface unit',1,length(IntfSection.UsesClause));
|
|
CheckUnit(0,'System',IntfSection);
|
|
AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
|
|
AssertEquals('Two implementation units',2,length(ImplSection.UsesClause));
|
|
CheckUnit(0,'a',ImplSection);
|
|
CheckUnit(1,'b',ImplSection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyUnitInitialization;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
Add('initialization');
|
|
ParseUnit;
|
|
AssertNotNull('Have initialization section',Module.InitializationSection);
|
|
AssertNull('Have no finalization section',Module.FinalizationSection)
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyUnitFinalization;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
Add('finalization');
|
|
ParseUnit;
|
|
AssertNull('Have no initalization section',Module.InitializationSection);
|
|
AssertNotNull('Have finalization section',Module.FinalizationSection)
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyUnitInitializationFinalization;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
Add('initialization');
|
|
Add('finalization');
|
|
ParseUnit;
|
|
AssertNotNull('Have finalization section',Module.InitializationSection);
|
|
AssertNotNull('Have finalization section',Module.FinalizationSection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyUnitBegin;
|
|
begin
|
|
StartUnit('unit1');
|
|
StartImplementation;
|
|
Add('begin');
|
|
ParseUnit;
|
|
AssertNotNull('Have initialization section',Module.InitializationSection);
|
|
AssertNull('Have no finalization section',Module.FinalizationSection)
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgram;
|
|
begin
|
|
StartProgram('something');
|
|
Add('begin');
|
|
ParseProgram;
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramInputOUtput;
|
|
begin
|
|
StartProgram('something','input','output');
|
|
Add('begin');
|
|
ParseProgram;
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramNoInitialization;
|
|
begin
|
|
StartProgram('something','input','output');
|
|
Add('initialization');
|
|
AssertProgramError;
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramNoFinalization;
|
|
begin
|
|
StartProgram('something','input','output');
|
|
Add('finalization');
|
|
AssertProgramError;
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramMissingBegin;
|
|
begin
|
|
StartProgram('something','input','output');
|
|
AssertProgramError;
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramNoheader;
|
|
begin
|
|
Add('begin');
|
|
ParseProgram;
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramUses;
|
|
begin
|
|
UsesClause(['a']);
|
|
Add('begin');
|
|
ParseProgram;
|
|
AssertEquals('Two interface units',2, PasProgram.ProgramSection.UsesList.Count);
|
|
AssertEquals('Two interface units',2, length(PasProgram.ProgramSection.UsesClause));
|
|
CheckUnit(0,'System',PasProgram.ProgramSection);
|
|
CheckUnit(1,'a',PasProgram.ProgramSection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramUsesTwoUnits;
|
|
begin
|
|
UsesClause(['a','b']);
|
|
Add('begin');
|
|
ParseProgram;
|
|
AssertEquals('Three interface units',3, PasProgram.ProgramSection.UsesList.Count);
|
|
AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
|
|
CheckUnit(0,'System',PasProgram.ProgramSection);
|
|
CheckUnit(1,'a',PasProgram.ProgramSection);
|
|
CheckUnit(2,'b',PasProgram.ProgramSection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyProgramUsesUnitIn;
|
|
|
|
Var
|
|
U : TPasUnresolvedUnitRef;
|
|
|
|
begin
|
|
UsesClause(['a in ''../a.pas''','b']);
|
|
Add('begin');
|
|
ParseProgram;
|
|
AssertEquals('Three interface unit',3, PasProgram.ProgramSection.UsesList.Count);
|
|
AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
|
|
CheckUnit(0,'System',PasProgram.ProgramSection);
|
|
U:=CheckUnit(1,'a',PasProgram.ProgramSection);
|
|
AssertEquals('Filename','''../a.pas''',U.FileName);
|
|
CheckUnit(2,'b',PasProgram.ProgramSection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibrary;
|
|
begin
|
|
StartLibrary('');
|
|
ParseLibrary;
|
|
AssertEquals('Correct class',TPasLibrary,Module.ClassType);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryUses;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['a']);
|
|
ParseLibrary;
|
|
AssertEquals('Correct class',TPasLibrary,Module.ClassType);
|
|
AssertEquals('Two interface units',2, PasLibrary.LibrarySection.UsesList.Count);
|
|
AssertEquals('Two interface units',2, length(PasLibrary.LibrarySection.UsesClause));
|
|
CheckUnit(0,'System',PasLibrary.LibrarySection);
|
|
CheckUnit(1,'a',PasLibrary.LibrarySection);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryExports;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['b']);
|
|
Add('exports A;');
|
|
ParseLibrary;
|
|
AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
|
|
AssertExportSymbol('Export symbol a',0,'A','',-1);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryExportsAlias;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['b']);
|
|
Add('exports A name ''c'';');
|
|
ParseLibrary;
|
|
AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
|
|
AssertExportSymbol('Export symbol a',0,'A','c',-1);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryExportsIndex;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['b']);
|
|
Add('exports A index 23;');
|
|
ParseLibrary;
|
|
AssertEquals('1 export symbol',1,PasLibrary.LibrarySection.ExportSymbols.Count);
|
|
AssertExportSymbol('Export symbol a',0,'A','',23);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryExportsTwo;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['b']);
|
|
Add('exports A , C;');
|
|
ParseLibrary;
|
|
AssertEquals('2 export symbol',2,PasLibrary.LibrarySection.ExportSymbols.Count);
|
|
AssertExportSymbol('Export symbol a',0,'A','',-1);
|
|
AssertExportSymbol('Export symbol C',1,'C','',-1);
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryExportsTwoAlias;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['b']);
|
|
Add('exports A name ''de'', C;');
|
|
ParseLibrary;
|
|
AssertEquals('2 export symbol',2,PasLibrary.LibrarySection.ExportSymbols.Count);
|
|
AssertExportSymbol('Export symbol a',0,'A','de',-1);
|
|
AssertExportSymbol('Export symbol C',1,'C','',-1);
|
|
|
|
end;
|
|
|
|
procedure TTestModuleParser.TestEmptyLibraryExportsTwoIndex;
|
|
begin
|
|
StartLibrary('');
|
|
UsesClause(['b']);
|
|
Add('exports A index 23, C;');
|
|
ParseLibrary;
|
|
AssertEquals('2 export symbol',2,PasLibrary.LibrarySection.ExportSymbols.Count);
|
|
AssertExportSymbol('Export symbol a',0,'A','',23);
|
|
AssertExportSymbol('Export symbol C',1,'C','',-1);
|
|
end;
|
|
|
|
initialization
|
|
RegisterTests([TTestModuleParser]);
|
|
|
|
end.
|
|
|