mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-02 09:03:41 +02:00
262 lines
7.0 KiB
ObjectPascal
262 lines
7.0 KiB
ObjectPascal
{ $Id$}
|
|
{ Copyright (C) 2007 Vincent Snijders
|
|
|
|
This source is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 2 of the License, or (at your option)
|
|
any later version.
|
|
|
|
This code is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
details.
|
|
|
|
A copy of the GNU General Public License is available on the World Wide Web
|
|
at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing
|
|
to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
MA 02111-1307, USA.
|
|
}
|
|
unit BugTestCase;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Math, process, fileutil, fpcunit, testregistry,
|
|
TestGlobals;
|
|
|
|
type
|
|
|
|
{ TBugTestCase }
|
|
|
|
TBugTestCase= class(TTestCase)
|
|
private
|
|
FPath: string;
|
|
FProjectFile: string;
|
|
public
|
|
constructor Create(APath, ATestName: string); reintroduce;
|
|
class function CreateSuite(Path: string) : TTestSuite;
|
|
published
|
|
procedure Compile;
|
|
procedure RunTestApp;
|
|
procedure CompareExpectations;
|
|
procedure HeaptrcLog;
|
|
end;
|
|
|
|
implementation
|
|
|
|
const
|
|
// Maximal number of bytes read from stream
|
|
READ_BYTES = 2048;
|
|
// Maximal run time for a test program
|
|
TIME_OUT = 30;
|
|
|
|
var
|
|
BufferedOutput: TMemoryStream; // a global variable is not nice, but it works.
|
|
|
|
procedure ReadOutput(AProcess:TProcess);
|
|
var
|
|
BytesRead: Integer;
|
|
n: Integer;
|
|
EndTime: TDateTime;
|
|
begin
|
|
BytesRead := 0;
|
|
BufferedOutput.Clear;
|
|
EndTime := Now + TIME_OUT / (24 * 60 * 60);
|
|
while AProcess.Running and (Now<EndTime) do
|
|
begin
|
|
// make sure we have room
|
|
BufferedOutput.SetSize(BytesRead + READ_BYTES);
|
|
|
|
// try reading it
|
|
{$IFNDEF VER2_0}
|
|
if AProcess.Output.NumBytesAvailable>0 then begin
|
|
n := AProcess.Output.Read((BufferedOutput.Memory + BytesRead)^, READ_BYTES);
|
|
Inc(BytesRead, n)
|
|
end
|
|
else
|
|
// no data, wait 100 ms
|
|
Sleep(100);
|
|
{$ELSE}
|
|
n := AProcess.Output.Read((BufferedOutput.Memory + BytesRead)^, READ_BYTES);
|
|
if n>0 then
|
|
Inc(BytesRead, n)
|
|
else
|
|
// no data, wait 100 ms
|
|
Sleep(100);
|
|
{$ENDIF}
|
|
end;
|
|
// read last part
|
|
repeat
|
|
// make sure we have room
|
|
BufferedOutput.SetSize(BytesRead + READ_BYTES);
|
|
// try reading it
|
|
{$IFNDEF VER2_0}
|
|
if AProcess.Output.NumBytesAvailable>0 then begin
|
|
n := AProcess.Output.Read((BufferedOutput.Memory + BytesRead)^, READ_BYTES);
|
|
Inc(BytesRead, n);
|
|
end
|
|
else
|
|
n := 0;
|
|
{$ELSE}
|
|
n := AProcess.Output.Read((BufferedOutput.Memory + BytesRead)^, READ_BYTES);
|
|
if n>0 then
|
|
Inc(BytesRead, n);
|
|
{$ENDIF}
|
|
until n <= 0;
|
|
BufferedOutput.SetSize(BytesRead);
|
|
end;
|
|
|
|
function FindProjectFile(APath: string):string;
|
|
var
|
|
SearchRec: TSearchRec;
|
|
begin
|
|
if FindFirst(AppendPathDelim(APath)+'*.lpi', faAnyFile, SearchRec)=0 then begin
|
|
repeat
|
|
if ExtractFileExt(SearchRec.Name)='.lpi' then
|
|
Result := SearchRec.Name;
|
|
until (Length(Result)>0) or (FindNext(SearchRec)<>0);
|
|
end;
|
|
FindClose(SearchRec);
|
|
if length(Result)>0 then
|
|
Result := AppendPathDelim(APath) + Result;
|
|
end;
|
|
|
|
procedure TBugTestCase.Compile;
|
|
var
|
|
LazBuildPath: string;
|
|
LazBuild: TProcess;
|
|
LazarusDir: String;
|
|
begin
|
|
AssertTrue('Project file '+ FProjectFile + ' does not exist',
|
|
FileExists(FProjectFile));
|
|
LazarusDir := ExpandFileName(ExtractFilePath(ParamStr(0)) + '../');
|
|
LazBuildPath := LazarusDir + 'lazbuild' + GetExeExt;
|
|
AssertTrue(LazBuildPath + ' does not exist', FileExists(LazBuildPath));
|
|
LazBuild := TProcess.Create(nil);
|
|
try
|
|
{$IFDEF windows}
|
|
LazBuild.Options := [poNewConsole];
|
|
{$ELSE}
|
|
LazBuild.Options := [poNoConsole];
|
|
{$ENDIF}
|
|
LazBuild.ShowWindow := swoHIDE;
|
|
LazBuild.CommandLine := LazBuildPath;
|
|
if Compiler<>'' then
|
|
LazBuild.CommandLine := LazBuild.CommandLine + ' --compiler='+Compiler;
|
|
LazBuild.CommandLine := LazBuild.CommandLine + ' ' + FProjectFile;
|
|
LazBuild.CurrentDirectory := FPath;
|
|
LazBuild.Execute;
|
|
LazBuild.WaitOnExit;
|
|
AssertEquals('Compilation failed: ExitCode', 0, LazBuild.ExitStatus);
|
|
finally
|
|
LazBuild.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBugTestCase.RunTestApp;
|
|
var
|
|
TestProcess : TProcess;
|
|
ExeName: string;
|
|
begin
|
|
ExeName := ChangeFileExt(FProjectFile, GetExeExt);
|
|
AssertTrue(ExeName + 'does not exist.', FileExists(ExeName));
|
|
TestProcess := TProcess.Create(nil);
|
|
try
|
|
TestProcess.CommandLine := ExeName + ' --runtest';
|
|
TestProcess.Options := [poUsePipes];
|
|
TestProcess.Execute;
|
|
try
|
|
ReadOutput(TestProcess);
|
|
AssertFalse('TestProcess did not auto-terminate', TestProcess.Running);
|
|
finally
|
|
TestProcess.Terminate(0);
|
|
end;
|
|
finally
|
|
TestProcess.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBugTestCase.CompareExpectations;
|
|
var
|
|
ExpectedFileName: string;
|
|
ExpectedLines: TStrings;
|
|
ActualLines: TStrings;
|
|
MinLineCount: integer;
|
|
i: integer;
|
|
begin
|
|
ExpectedFileName := AppendPathDelim(FPath) + 'expected.txt';
|
|
AssertTrue('File missing: '+ExpectedFileName, FileExists(ExpectedFileName));
|
|
ExpectedLines := nil;
|
|
ActualLines := nil;
|
|
try
|
|
ExpectedLines := TStringList.Create;
|
|
ExpectedLines.LoadFromFile(ExpectedFileName);
|
|
BufferedOutput.Position := 0;
|
|
ActualLines := TStringList.Create;
|
|
ActualLines.LoadFromStream(BufferedOutput);
|
|
MinLineCount := min(ExpectedLines.Count, ActualLines.Count);
|
|
for i := 0 to MinLineCount - 1 do begin
|
|
AssertEquals('Output difference on line '+IntToStr(i+1),
|
|
ExpectedLines[i], ActualLines[i]);
|
|
end;
|
|
AssertEquals('Difference in line count',
|
|
ExpectedLines.Count, ActualLines.Count);
|
|
finally
|
|
ExpectedLines.Free;
|
|
ActualLines.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBugTestCase.HeaptrcLog;
|
|
begin
|
|
|
|
end;
|
|
|
|
constructor TBugTestCase.Create(APath, ATestName: string);
|
|
begin
|
|
CreateWithName(ATestName);
|
|
FPath := APath;
|
|
FProjectFile := FindProjectFile(FPath);
|
|
end;
|
|
|
|
class function TBugTestCase.CreateSuite(Path: string): TTestSuite;
|
|
var
|
|
Directory: string;
|
|
begin
|
|
Directory := ExtractFileName(Path);
|
|
Result := TTestSuite.Create(Directory);
|
|
Result.AddTest(Create(Path, 'Compile'));
|
|
Result.AddTest(Create(Path, 'RunTestApp'));
|
|
Result.AddTest(Create(Path, 'CompareExpectations'));
|
|
Result.AddTest(Create(Path, 'HeaptrcLog'));
|
|
end;
|
|
|
|
procedure GatherTests;
|
|
var
|
|
ProgPath: string;
|
|
SearchRec: TSearchRec;
|
|
begin
|
|
ProgPath := ExtractFilePath(ParamStr(0)) + 'bugs' + pathdelim;
|
|
if FindFirst(ProgPath+'*', faAnyFile, SearchRec)=0 then
|
|
repeat
|
|
if (SearchRec.Attr and (faDirectory + faHidden)=faDirectory) and
|
|
(SearchRec.Name<>'.') and (SearchRec.Name<>'..') and
|
|
(SearchRec.Name<>'.svn')
|
|
then
|
|
BugsTestSuite.AddTest(
|
|
TBugTestCase.CreateSuite(ProgPath+SearchRec.Name));
|
|
until FindNext(SearchRec)<>0;
|
|
FindClose(SearchRec);
|
|
end;
|
|
|
|
initialization
|
|
GatherTests;
|
|
BufferedOutput := TMemoryStream.Create;
|
|
|
|
finalization
|
|
FreeAndNil(BufferedOutput);
|
|
end.
|
|
|