Explorar el Código

* Unit Tests for scanner

git-svn-id: trunk@19798 -
michael hace 13 años
padre
commit
aa625a23e6

+ 3 - 0
.gitattributes

@@ -2211,6 +2211,9 @@ packages/fcl-passrc/src/paswrite.pp svneol=native#text/plain
 packages/fcl-passrc/src/pparser.pp svneol=native#text/plain
 packages/fcl-passrc/src/pscanner.pp svneol=native#text/plain
 packages/fcl-passrc/src/readme.txt svneol=native#text/plain
+packages/fcl-passrc/tests/tcscanner.pas svneol=native#text/plain
+packages/fcl-passrc/tests/testpassrc.lpi svneol=native#text/plain
+packages/fcl-passrc/tests/testpassrc.lpr svneol=native#text/plain
 packages/fcl-process/Makefile svneol=native#text/plain
 packages/fcl-process/Makefile.fpc svneol=native#text/plain
 packages/fcl-process/fpmake.pp svneol=native#text/plain

+ 1265 - 0
packages/fcl-passrc/tests/tcscanner.pas

@@ -0,0 +1,1265 @@
+unit tcscanner;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, typinfo, fpcunit, testutils, testregistry, pscanner, pparser;
+
+type
+
+  { TTestTokenFinder }
+
+  TTestTokenFinder = class(TTestCase)
+  Published
+    Procedure TestFind;
+  end;
+
+  { TTestStreamLineReader }
+
+
+  TTestStreamLineReader = class(TTestCase)
+  Private
+    FReader: TStreamLineReader;
+  Protected
+    procedure NewSource(Const Source : string);
+    Procedure TestLine(Const ALine : String; ExpectEOF : Boolean = True);
+    procedure TearDown; override;
+  Published
+    Procedure TestCreate;
+    Procedure TestEOF;
+    Procedure TestEmptyLine;
+    Procedure TestEmptyLineCR;
+    Procedure TestEmptyLineLF;
+    Procedure TestEmptyLineCRLF;
+    Procedure TestEmptyLineLFCR;
+    Procedure TestOneLine;
+    Procedure TestTwoLines;
+  end;
+
+  { TTestScanner }
+  TTestScanner= class(TTestCase)
+  Private
+    FScanner : TPascalScanner;
+    FResolver : TStreamResolver;
+  protected
+    procedure SetUp; override; 
+    procedure TearDown; override;
+    Function TokenToString(tk : TToken) : string;
+    Procedure AssertEquals(Msg : String; Expected,Actual : TToken); overload;
+    procedure NewSource(Const Source : string; DoClear : Boolean = True);
+    Procedure DoTestToken(t : TToken; Const ASource : String; Const CheckEOF : Boolean = True);
+    Procedure TestToken(t : TToken; Const ASource : String; Const CheckEOF : Boolean = True);
+    Procedure TestTokens(t : array of TToken; Const ASource : String; Const CheckEOF : Boolean = True;Const DoClear : Boolean = True);
+  published
+    procedure TestEOF;
+    procedure TestWhitespace;
+    procedure TestComment1;
+    procedure TestComment2;
+    procedure TestComment3;
+    procedure TestNestedComment1;
+    procedure TestNestedComment2;
+    procedure TestNestedComment3;
+    procedure TestNestedComment4;
+    procedure TestIdentifier;
+    procedure TestString;
+    procedure TestNumber;
+    procedure TestChar;
+    procedure TestBraceOpen;
+    procedure TestBraceClose;
+    procedure TestMul;
+    procedure TestPlus;
+    procedure TestComma;
+    procedure TestMinus;
+    procedure TestDot;
+    procedure TestDivision;
+    procedure TestColon;
+    procedure TestSemicolon;
+    procedure TestLessThan;
+    procedure TestEqual;
+    procedure TestGreaterThan;
+    procedure TestAt;
+    procedure TestSquaredBraceOpen;
+    procedure TestSquaredBraceClose;
+    procedure TestCaret;
+    procedure TestBackslash;
+    procedure TestDotDot;
+    procedure TestAssign;
+    procedure TestNotEqual;
+    procedure TestLessEqualThan;
+    procedure TestGreaterEqualThan;
+    procedure TestPower;
+    procedure TestSymmetricalDifference;
+    procedure TestAbsolute;
+    procedure TestAnd;
+    procedure TestArray;
+    procedure TestAs;
+    procedure TestAsm;
+    procedure TestBegin;
+    procedure TestBitpacked;
+    procedure TestCase;
+    procedure TestClass;
+    procedure TestConst;
+    procedure TestConstructor;
+    procedure TestDestructor;
+    procedure TestDiv;
+    procedure TestDo;
+    procedure TestDownto;
+    procedure TestElse;
+    procedure TestEnd;
+    procedure TestExcept;
+    procedure TestExports;
+    procedure TestFalse;
+    procedure TestFile;
+    procedure TestFinalization;
+    procedure TestFinally;
+    procedure TestFor;
+    procedure TestFunction;
+    procedure TestGeneric;
+    procedure TestGoto;
+    procedure TestIf;
+    procedure TestImplementation;
+    procedure TestIn;
+    procedure TestInherited;
+    procedure TestInitialization;
+    procedure TestInline;
+    procedure TestInterface;
+    procedure TestIs;
+    procedure TestLabel;
+    procedure TestLibrary;
+    procedure TestMod;
+    procedure TestNil;
+    procedure TestNot;
+    procedure TestObject;
+    procedure TestOf;
+    procedure TestOn;
+    procedure TestOperator;
+    procedure TestOr;
+    procedure TestPacked;
+    procedure TestProcedure;
+    procedure TestProgram;
+    procedure TestProperty;
+    procedure TestRaise;
+    procedure TestRecord;
+    procedure TestRepeat;
+    procedure TestResourceString;
+    procedure TestSelf;
+    procedure TestSet;
+    procedure TestShl;
+    procedure TestShr;
+    procedure TestSpecialize;
+    procedure TestThen;
+    procedure TestThreadvar;
+    procedure TestTo;
+    procedure TestTrue;
+    procedure TestTry;
+    procedure TestType;
+    procedure TestUnit;
+    procedure TestUntil;
+    procedure TestUses;
+    procedure TestVar;
+    procedure TestWhile;
+    procedure TestWith;
+    procedure TestXor;
+    procedure TestLineEnding;
+    procedure TestTab;
+    Procedure TestTokenSeries;
+    Procedure TestTokenSeriesNoWhiteSpace;
+    Procedure TestTokenSeriesComments;
+    Procedure TestTokenSeriesNoComments;
+    Procedure TestDefine1;
+    Procedure TestDefine2;
+    Procedure TestDefine3;
+    Procedure TestDefine4;
+    Procedure TestDefine5;
+    Procedure TestDefine6;
+    Procedure TestDefine7;
+    Procedure TestDefine8;
+    Procedure TestDefine9;
+    Procedure TestDefine10;
+    Procedure TestDefine11;
+    Procedure TestDefine12;
+    Procedure TestInclude;
+  end;
+
+implementation
+
+{ TTestTokenFinder }
+
+procedure TTestTokenFinder.TestFind;
+
+Var
+  tk,tkr : TToken;
+  S : string;
+  B : Boolean;
+
+begin
+  For tk:=tkAbsolute to tkXor do
+    begin
+    S:=tokenInfos[tk];
+    B:=IsNamedToken(S,tkr);
+    AssertEquals('Token '+S+' is a token',true,B);
+    AssertEquals('Token '+S+' returns correct token',Ord(tk),Ord(tkr));
+    end;
+end;
+
+{ TTestStreamLineReader }
+
+procedure TTestStreamLineReader.NewSource(Const Source: string);
+begin
+  FReader:=TStringStreamLineReader.Create('afile',Source);
+end;
+
+procedure TTestStreamLineReader.TestLine(const ALine: String; ExpectEOF: Boolean);
+begin
+  AssertNotNull('Have reader',FReader);
+  AssertEquals('Reading source line',ALine,FReader.ReadLine);
+  if ExpectEOF then
+    AssertEquals('End of file reached',True,FReader.IsEOF);
+end;
+
+procedure TTestStreamLineReader.TearDown;
+begin
+  inherited TearDown;
+  If Assigned(FReader) then
+    FreeAndNil(Freader);
+end;
+
+procedure TTestStreamLineReader.TestCreate;
+begin
+  FReader:=TStreamLineReader.Create('afile');
+  AssertEquals('Correct filename','afile',FReader.FileName);
+  AssertEquals('Initially empty',True,FReader.isEOF);
+end;
+
+procedure TTestStreamLineReader.TestEOF;
+begin
+  NewSource('');
+  AssertEquals('Empty stream',True,FReader.IsEOF);
+end;
+
+procedure TTestStreamLineReader.TestEmptyLine;
+begin
+  NewSource('');
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineCR;
+begin
+  NewSource(#13);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineLF;
+begin
+  NewSource(#10);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineCRLF;
+begin
+  NewSource(#13#10);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestEmptyLineLFCR;
+begin
+  NewSource(#10#13);
+  TestLine('',False);
+  TestLine('');
+end;
+
+procedure TTestStreamLineReader.TestOneLine;
+
+Const
+    S = 'a line with text';
+begin
+  NewSource(S);
+  TestLine(S);
+end;
+
+procedure TTestStreamLineReader.TestTwoLines;
+Const
+    S = 'a line with text';
+begin
+  NewSource(S+sLineBreak+S);
+  TestLine(S,False);
+  TestLine(S);
+end;
+
+{ ---------------------------------------------------------------------
+  TTestScanner
+  ---------------------------------------------------------------------}
+
+procedure TTestScanner.SetUp;
+begin
+  FResolver:=TStreamResolver.Create;
+  FResolver.OwnsStreams:=True;
+  FScanner:=TPascalScanner.Create(FResolver);
+  // Do nothing
+end; 
+
+procedure TTestScanner.TearDown; 
+begin
+  FreeAndNil(FScanner);
+  FreeAndNil(FResolver);
+end;
+
+function TTestScanner.TokenToString(tk: TToken): string;
+begin
+  Result:=GetEnumName(TypeInfo(TToken),Ord(tk));
+end;
+
+procedure TTestScanner.AssertEquals(Msg: String; Expected, Actual: TToken);
+begin
+  AssertEquals(Msg,TokenToString(Expected),TokenToString(Actual));
+end;
+
+procedure TTestScanner.NewSource(const Source: string; DoClear : Boolean = True);
+begin
+  if DoClear then
+    FResolver.Clear;
+  FResolver.AddStream('afile.pp',TStringStream.Create(Source));
+  FScanner.OpenFile('afile.pp');
+end;
+
+procedure TTestScanner.DoTestToken(t: TToken; const ASource: String;
+  Const CheckEOF: Boolean);
+
+Var
+  tk : ttoken;
+
+begin
+  NewSource(ASource);
+  tk:=FScanner.FetchToken;
+  AssertEquals('Read token equals expected token.',t,tk);
+  if CheckEOF then
+    begin
+    tk:=FScanner.FetchToken;
+    if (tk=tkLineEnding) and not (t in [tkEOF,tkLineEnding]) then
+      tk:=FScanner.FetchToken;
+    AssertEquals('EOF reached.',tkEOF,FScanner.FetchToken);
+    end;
+end;
+
+procedure TTestScanner.TestToken(t: TToken; const ASource: String; Const CheckEOF: Boolean);
+Var
+  S : String;
+begin
+  DoTestToken(t,ASource);
+  if (ASource<>'') then
+    begin
+    S:=ASource;
+    S[1]:=Upcase(S[1]);
+    DoTestToken(t,S);
+    end;
+  DoTestToken(t,UpperCase(ASource));
+  DoTestToken(t,LowerCase(ASource));
+end;
+
+procedure TTestScanner.TestTokens(t: array of TToken; const ASource: String;
+  const CheckEOF: Boolean;Const DoClear : Boolean = True);
+Var
+  tk : ttoken;
+  i : integer;
+
+begin
+  NewSource(ASource,DoClear);
+  For I:=Low(t) to High(t) do
+    begin
+    tk:=FScanner.FetchToken;
+    AssertEquals(Format('Read token %d equals expected token.',[i]),t[i],tk);
+    end;
+  if CheckEOF then
+    begin
+    tk:=FScanner.FetchToken;
+    if (tk=tkLineEnding) then
+      tk:=FScanner.FetchToken;
+    AssertEquals('EOF reached.',tkEOF,FScanner.FetchToken);
+    end;
+end;
+
+procedure TTestScanner.TestEOF;
+begin
+  TestToken(tkEOF,'')
+end;
+
+procedure TTestScanner.TestWhitespace;
+
+begin
+  TestToken(tkWhitespace,' ');
+  TestToken(tkWhitespace,' ');
+end;
+
+
+procedure TTestScanner.TestComment1;
+
+begin
+  TestToken(tkComment,'{ comment }');
+end;
+
+
+procedure TTestScanner.TestComment2;
+
+begin
+  TestToken(tkComment,'(* comment *)');
+end;
+
+
+procedure TTestScanner.TestComment3;
+
+begin
+  TestToken(tkComment,'//');
+end;
+
+procedure TTestScanner.TestNestedComment1;
+begin
+  TestToken(tkComment,'// { comment } ');
+end;
+
+procedure TTestScanner.TestNestedComment2;
+begin
+  TestToken(tkComment,'(* { comment } *)');
+end;
+
+procedure TTestScanner.TestNestedComment3;
+begin
+  TestToken(tkComment,'{ { comment } }');
+end;
+
+procedure TTestScanner.TestNestedComment4;
+begin
+  TestToken(tkComment,'{ (* comment *) }');
+end;
+
+
+procedure TTestScanner.TestIdentifier;
+
+begin
+  TestToken(tkIdentifier,'identifier');
+end;
+
+
+procedure TTestScanner.TestString;
+
+begin
+  TestToken(pscanner.tkString,'''A string''');
+end;
+
+
+procedure TTestScanner.TestNumber;
+
+begin
+  TestToken(tkNumber,'123');
+end;
+
+
+procedure TTestScanner.TestChar;
+
+begin
+  TestToken(pscanner.tkChar,'#65 ', false);
+end;
+
+
+procedure TTestScanner.TestBraceOpen;
+
+begin
+  TestToken(tkBraceOpen,'(');
+end;
+
+
+procedure TTestScanner.TestBraceClose;
+
+begin
+  TestToken(tkBraceClose,')');
+end;
+
+
+procedure TTestScanner.TestMul;
+
+begin
+  TestToken(tkMul,'*');
+end;
+
+
+procedure TTestScanner.TestPlus;
+
+begin
+  TestToken(tkPlus,'+');
+end;
+
+
+procedure TTestScanner.TestComma;
+
+begin
+  TestToken(tkComma,',');
+end;
+
+
+procedure TTestScanner.TestMinus;
+
+begin
+  TestToken(tkMinus,'-');
+end;
+
+
+procedure TTestScanner.TestDot;
+
+begin
+  TestToken(tkDot,'.');
+end;
+
+
+procedure TTestScanner.TestDivision;
+
+begin
+  TestToken(tkDivision,'/');
+end;
+
+
+procedure TTestScanner.TestColon;
+
+begin
+  TestToken(tkColon,':');
+end;
+
+
+procedure TTestScanner.TestSemicolon;
+
+begin
+  TestToken(tkSemicolon,';');
+end;
+
+
+procedure TTestScanner.TestLessThan;
+
+begin
+  TestToken(tkLessThan,'<');
+end;
+
+
+procedure TTestScanner.TestEqual;
+
+begin
+  TestToken(tkEqual,'=');
+end;
+
+
+procedure TTestScanner.TestGreaterThan;
+
+begin
+  TestToken(tkGreaterThan,'>');
+end;
+
+
+procedure TTestScanner.TestAt;
+
+begin
+  TestToken(tkAt,'@');
+end;
+
+
+procedure TTestScanner.TestSquaredBraceOpen;
+
+begin
+  TestToken(tkSquaredBraceOpen,'[');
+end;
+
+
+procedure TTestScanner.TestSquaredBraceClose;
+
+begin
+  TestToken(tkSquaredBraceClose,']');
+end;
+
+
+procedure TTestScanner.TestCaret;
+
+begin
+  TestToken(tkCaret,'^');
+end;
+
+
+procedure TTestScanner.TestBackslash;
+
+begin
+  TestToken(tkBackslash,'\');
+end;
+
+
+procedure TTestScanner.TestDotDot;
+
+begin
+  TestToken(tkDotDot,'..');
+end;
+
+
+procedure TTestScanner.TestAssign;
+
+begin
+  TestToken(tkAssign,':=');
+end;
+
+
+procedure TTestScanner.TestNotEqual;
+
+begin
+  TestToken(tkNotEqual,'<>');
+end;
+
+
+procedure TTestScanner.TestLessEqualThan;
+
+begin
+  TestToken(tkLessEqualThan,'<=');
+end;
+
+
+procedure TTestScanner.TestGreaterEqualThan;
+
+begin
+  TestToken(tkGreaterEqualThan,'>=');
+end;
+
+
+procedure TTestScanner.TestPower;
+
+begin
+  TestToken(tkPower,'**');
+end;
+
+
+procedure TTestScanner.TestSymmetricalDifference;
+
+begin
+  TestToken(tkSymmetricalDifference,'><');
+end;
+
+
+procedure TTestScanner.TestAbsolute;
+
+begin
+  TestToken(tkabsolute,'absolute');
+end;
+
+
+procedure TTestScanner.TestAnd;
+
+begin
+  TestToken(tkand,'and');
+end;
+
+
+procedure TTestScanner.TestArray;
+
+begin
+  TestToken(tkarray,'array');
+end;
+
+
+procedure TTestScanner.TestAs;
+
+begin
+  TestToken(tkas,'as');
+end;
+
+
+procedure TTestScanner.TestAsm;
+
+begin
+  TestToken(tkasm,'asm');
+end;
+
+
+procedure TTestScanner.TestBegin;
+
+begin
+  TestToken(tkbegin,'begin');
+end;
+
+
+procedure TTestScanner.TestBitpacked;
+
+begin
+  TestToken(tkbitpacked,'bitpacked');
+end;
+
+
+procedure TTestScanner.TestCase;
+
+begin
+  TestToken(tkcase,'case');
+end;
+
+
+procedure TTestScanner.TestClass;
+
+begin
+  TestToken(tkclass,'class');
+end;
+
+
+procedure TTestScanner.TestConst;
+
+begin
+  TestToken(tkconst,'const');
+end;
+
+
+procedure TTestScanner.TestConstructor;
+
+begin
+  TestToken(tkconstructor,'constructor');
+end;
+
+
+procedure TTestScanner.TestDestructor;
+
+begin
+  TestToken(tkdestructor,'destructor');
+end;
+
+
+procedure TTestScanner.TestDiv;
+
+begin
+  TestToken(tkdiv,'div');
+end;
+
+
+procedure TTestScanner.TestDo;
+
+begin
+  TestToken(tkdo,'do');
+end;
+
+
+procedure TTestScanner.TestDownto;
+
+begin
+  TestToken(tkdownto,'downto');
+end;
+
+
+procedure TTestScanner.TestElse;
+
+begin
+  TestToken(tkelse,'else');
+end;
+
+
+procedure TTestScanner.TestEnd;
+
+begin
+  TestToken(tkend,'end');
+end;
+
+
+procedure TTestScanner.TestExcept;
+
+begin
+  TestToken(tkexcept,'except');
+end;
+
+
+procedure TTestScanner.TestExports;
+
+begin
+  TestToken(tkexports,'exports');
+end;
+
+
+procedure TTestScanner.TestFalse;
+
+begin
+  TestToken(tkfalse,'false');
+end;
+
+
+procedure TTestScanner.TestFile;
+
+begin
+  TestToken(tkfile,'file');
+end;
+
+
+procedure TTestScanner.TestFinalization;
+
+begin
+  TestToken(tkfinalization,'finalization');
+end;
+
+
+procedure TTestScanner.TestFinally;
+
+begin
+  TestToken(tkfinally,'finally');
+end;
+
+
+procedure TTestScanner.TestFor;
+
+begin
+  TestToken(tkfor,'for');
+end;
+
+
+procedure TTestScanner.TestFunction;
+
+begin
+  TestToken(tkfunction,'function');
+end;
+
+
+procedure TTestScanner.TestGeneric;
+
+begin
+  TestToken(tkgeneric,'generic');
+end;
+
+
+procedure TTestScanner.TestGoto;
+
+begin
+  TestToken(tkgoto,'goto');
+end;
+
+
+procedure TTestScanner.TestIf;
+
+begin
+  TestToken(tkif,'if');
+end;
+
+
+procedure TTestScanner.TestImplementation;
+
+begin
+  TestToken(tkimplementation,'implementation');
+end;
+
+
+procedure TTestScanner.TestIn;
+
+begin
+  TestToken(tkin,'in');
+end;
+
+
+procedure TTestScanner.TestInherited;
+
+begin
+  TestToken(tkinherited,'inherited');
+end;
+
+
+procedure TTestScanner.TestInitialization;
+
+begin
+  TestToken(tkinitialization,'initialization');
+end;
+
+
+procedure TTestScanner.TestInline;
+
+begin
+  TestToken(tkinline,'inline');
+end;
+
+
+procedure TTestScanner.TestInterface;
+
+begin
+  TestToken(tkinterface,'interface');
+end;
+
+
+procedure TTestScanner.TestIs;
+
+begin
+  TestToken(tkis,'is');
+end;
+
+
+procedure TTestScanner.TestLabel;
+
+begin
+  TestToken(tklabel,'label');
+end;
+
+
+procedure TTestScanner.TestLibrary;
+
+begin
+  TestToken(tklibrary,'library');
+end;
+
+
+procedure TTestScanner.TestMod;
+
+begin
+  TestToken(tkmod,'mod');
+end;
+
+
+procedure TTestScanner.TestNil;
+
+begin
+  TestToken(tknil,'nil');
+end;
+
+
+procedure TTestScanner.TestNot;
+
+begin
+  TestToken(tknot,'not');
+end;
+
+
+procedure TTestScanner.TestObject;
+
+begin
+  TestToken(tkobject,'object');
+end;
+
+
+procedure TTestScanner.TestOf;
+
+begin
+  TestToken(tkof,'of');
+end;
+
+
+procedure TTestScanner.TestOn;
+
+begin
+  TestToken(tkon,'on');
+end;
+
+
+procedure TTestScanner.TestOperator;
+
+begin
+  TestToken(tkoperator,'operator');
+end;
+
+
+procedure TTestScanner.TestOr;
+
+begin
+  TestToken(tkor,'or');
+end;
+
+
+procedure TTestScanner.TestPacked;
+
+begin
+  TestToken(tkpacked,'packed');
+end;
+
+
+procedure TTestScanner.TestProcedure;
+
+begin
+  TestToken(tkprocedure,'procedure');
+end;
+
+
+procedure TTestScanner.TestProgram;
+
+begin
+  TestToken(tkprogram,'program');
+end;
+
+
+procedure TTestScanner.TestProperty;
+
+begin
+  TestToken(tkproperty,'property');
+end;
+
+
+procedure TTestScanner.TestRaise;
+
+begin
+  TestToken(tkraise,'raise');
+end;
+
+
+procedure TTestScanner.TestRecord;
+
+begin
+  TestToken(tkrecord,'record');
+end;
+
+
+procedure TTestScanner.TestRepeat;
+
+begin
+  TestToken(tkrepeat,'repeat');
+end;
+
+
+procedure TTestScanner.TestResourceString;
+
+begin
+  TestToken(tkResourceString,'resourcestring');
+end;
+
+
+procedure TTestScanner.TestSelf;
+
+begin
+  TestToken(tkself,'self');
+end;
+
+
+procedure TTestScanner.TestSet;
+
+begin
+  TestToken(tkset,'set');
+end;
+
+
+procedure TTestScanner.TestShl;
+
+begin
+  TestToken(tkshl,'shl');
+end;
+
+
+procedure TTestScanner.TestShr;
+
+begin
+  TestToken(tkshr,'shr');
+end;
+
+
+procedure TTestScanner.TestSpecialize;
+
+begin
+  TestToken(tkspecialize,'specialize');
+end;
+
+
+procedure TTestScanner.TestThen;
+
+begin
+  TestToken(tkthen,'then');
+end;
+
+
+procedure TTestScanner.TestThreadvar;
+
+begin
+  TestToken(tkthreadvar,'threadvar');
+end;
+
+
+procedure TTestScanner.TestTo;
+
+begin
+  TestToken(tkto,'to');
+end;
+
+
+procedure TTestScanner.TestTrue;
+
+begin
+  TestToken(tktrue,'true');
+end;
+
+
+procedure TTestScanner.TestTry;
+
+begin
+  TestToken(tktry,'try');
+end;
+
+
+procedure TTestScanner.TestType;
+
+begin
+  TestToken(tktype,'type');
+end;
+
+
+procedure TTestScanner.TestUnit;
+
+begin
+  TestToken(tkunit,'unit');
+end;
+
+
+procedure TTestScanner.TestUntil;
+
+begin
+  TestToken(tkuntil,'until');
+end;
+
+
+procedure TTestScanner.TestUses;
+
+begin
+  TestToken(tkuses,'uses');
+end;
+
+
+procedure TTestScanner.TestVar;
+
+begin
+  TestToken(tkvar,'var');
+end;
+
+
+procedure TTestScanner.TestWhile;
+
+begin
+  TestToken(tkwhile,'while');
+end;
+
+
+procedure TTestScanner.TestWith;
+
+begin
+  TestToken(tkwith,'with');
+end;
+
+
+procedure TTestScanner.TestXor;
+
+begin
+  TestToken(tkxor,'xor');
+end;
+
+
+procedure TTestScanner.TestLineEnding;
+
+begin
+  TestToken(tkLineEnding,#10);
+end;
+
+
+procedure TTestScanner.TestTab;
+
+begin
+  TestToken(tkTab,#9);
+end;
+
+procedure TTestScanner.TestTokenSeries;
+begin
+  TestTokens([tkin,tkWhitespace,tkOf,tkWhiteSpace,tkthen,tkWhiteSpace,tkIdentifier],'in of then aninteger')
+end;
+
+procedure TTestScanner.TestTokenSeriesNoWhiteSpace;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkin,tkOf,tkthen,tkIdentifier],'in of then aninteger')
+end;
+
+procedure TTestScanner.TestTokenSeriesComments;
+begin
+  TestTokens([tkin,tkWhitespace,tkOf,tkWhiteSpace,tkComment,tkWhiteSpace,tkIdentifier],'in of {then} aninteger')
+end;
+
+procedure TTestScanner.TestTokenSeriesNoComments;
+begin
+  FScanner.SkipComments:=True;
+  TestTokens([tkin,tkWhitespace,tkOf,tkWhiteSpace,tkWhiteSpace,tkIdentifier],'in of {then} aninteger')
+end;
+
+procedure TTestScanner.TestDefine1;
+begin
+  TestTokens([tkComment],'{$IFDEF NEVER} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine2;
+
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  TestTokens([tkComment,tkWhitespace,tkOf,tkWhitespace,tkcomment],'{$IFDEF ALWAYS} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine3;
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  TestTokens([tkComment,tkWhitespace,tkOf,tkWhitespace,tkcomment],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine4;
+begin
+  TestTokens([tkComment,tkWhitespace,tkin,tkWhitespace,tkcomment],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine5;
+begin
+  FScanner.SkipComments:=True;
+  TestTokens([tkLineEnding],'{$IFDEF NEVER} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine6;
+
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkOf,tkWhitespace],'{$IFDEF ALWAYS} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine7;
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkOf,tkWhitespace],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine8;
+begin
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkin,tkWhitespace],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine9;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([],'{$IFDEF NEVER} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine10;
+
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  TestTokens([tkWhitespace,tkOf,tkWhitespace],'{$IFDEF ALWAYS} of {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine11;
+begin
+  FSCanner.Defines.Add('ALWAYS');
+  FScanner.SkipComments:=True;
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkOf],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestDefine12;
+begin
+  FScanner.SkipComments:=True;
+  FScanner.SkipWhiteSpace:=True;
+  TestTokens([tkin],'{$IFDEF ALWAYS} of {$ELSE} in {$ENDIF}');
+end;
+
+procedure TTestScanner.TestInclude;
+begin
+  FResolver.AddStream('myinclude.inc',TStringStream.Create('if true then'));
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkIf,tkTrue,tkThen],'{$I myinclude.inc}',True,False);
+end;
+
+
+
+
+initialization
+  RegisterTests([TTestTokenFinder,TTestStreamLineReader,TTestScanner]);
+end.
+

+ 82 - 0
packages/fcl-passrc/tests/testpassrc.lpi

@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="testpassrc.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testpassrc"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="tcscanner.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcscanner"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+    </SearchPaths>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CompilerMessages>
+        <UseMsgFile Value="True"/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 25 - 0
packages/fcl-passrc/tests/testpassrc.lpr

@@ -0,0 +1,25 @@
+program testpassrc;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, tcscanner;
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+  // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.