lazarus/test/testresult-db/importtestresults.pp
mattias 1dde630b38 examples: fixed compilation
git-svn-id: trunk@16357 -
2008-09-01 19:51:05 +00:00

565 lines
13 KiB
ObjectPascal

{
This file is part of the Free Pascal test suite.
Copyright (c) 2002 by the Free Pascal development team.
This program generates a digest
of the last tests run.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program 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.
**********************************************************************}
{$mode objfpc}
{$h+}
program importtestresults;
uses
sysutils,teststr,testu,tresults,dbtests,
dom, XMLRead, dateutils;
Var
StatusCount : Array[TTestStatus] of Integer;
UnknownLines : integer;
Procedure ExtractTestFileName(Var Line : string);
Var I : integer;
begin
I:=Pos(' ',Line);
If (I<>0) then
Line:=Copy(Line,1,I-1);
end;
Function Analyse(Var Line : string; Var Status : TTestStatus) : Boolean;
Var
TS : TTestStatus;
begin
Result:=False;
For TS:=FirstStatus to LastStatus do
begin
Result:=Pos(StatusText[TS],Line)=1;
If Result then
begin
Status:=TS;
Delete(Line,1,Length(StatusText[TS]));
ExtractTestFileName(Line);
Break;
end;
end;
end;
Type
TConfigOpt = (
coDatabaseName,
soHost,
coUserName,
coPassword,
coLogFile,
coOS,
coCPU,
coWidgetset,
coFPCVersion,
coDate,
coSubmitter,
coMachine,
coComment,
coTestSrcDir,
coRelSrcDir,
coVerbose
);
Const
ConfigStrings : Array [TConfigOpt] of string = (
'databasename',
'host',
'username',
'password',
'logfile',
'os',
'cpu',
'widgetset',
'fpcversion',
'date',
'submitter',
'machine',
'comment',
'testsrcdir',
'relsrcdir',
'verbose'
);
ConfigOpts : Array[TConfigOpt] of char
= ('d','h','u','p','l','o','c','w', 'v','t','s','m','C','S','r','V');
Var
TestOS,
TestCPU,
TestFPCVersion,
TestLazVersion,
TestWidgetSet,
DatabaseName,
HostName,
UserName,
Password,
ResultsFileName,
Submitter,
Machine,
Comment : String;
TestDate : TDateTime;
Procedure SetOpt (O : TConfigOpt; Value : string);
var
year,month,day,min,hour : word;
begin
Case O of
coDatabaseName : DatabaseName:=Value;
soHost : HostName:=Value;
coUserName : UserName:=Value;
coPassword : Password:=Value;
coLogFile : ResultsFileName:=Value;
coOS : TestOS:=Value;
coCPU : TestCPU:=Value;
coFPCVersion : TestFPCVersion:=Value;
coDate :
begin
{ Formated like YYYYMMDDhhmm }
if Length(value)=12 then
begin
year:=StrToInt(Copy(value,1,4));
month:=StrToInt(Copy(value,5,2));
day:=StrToInt(Copy(Value,7,2));
hour:=StrToInt(Copy(Value,9,2));
min:=StrToInt(Copy(Value,11,2));
TestDate:=EncodeDate(year,month,day)+EncodeTime(hour,min,0,0);
end
else
Verbose(V_Error,'Error in date format, use YYYYMMDDhhmm');
end;
coSubmitter : Submitter:=Value;
coMachine : Machine:=Value;
coComment : Comment:=Value;
coVerbose : DoVerbose:=true;
coTestSrcDir :
begin
TestSrcDir:=Value;
if (TestSrcDir<>'') and (TestSrcDir[length(TestSrcDir)]<>'/') then
TestSrcDir:=TestSrcDir+'/';
end;
coRelSrcDir :
begin
RelSrcDir:=Value;
if (RelSrcDir<>'') and (RelSrcDir[length(RelSrcDir)]<>'/') then
RelSrcDir:=RelSrcDir+'/';
if (RelSrcDir<>'') and (RelSrcDir[1]='/') then
RelSrcDir:=copy(RelSrcDir,2,length(RelSrcDir)-1);
end;
end;
end;
Function ProcessOption(S: String) : Boolean;
Var
N : String;
I : Integer;
co : TConfigOpt;
begin
Verbose(V_DEBUG,'Processing option: '+S);
I:=Pos('=',S);
Result:=(I<>0);
If Result then
begin
N:=Copy(S,1,I-1);
Delete(S,1,I);
For co:=low(TConfigOpt) to high(TConfigOpt) do
begin
Result:=CompareText(ConfigStrings[co],N)=0;
If Result then
Break;
end;
end;
If Result then
SetOpt(co,S)
else
Verbose(V_ERROR,'Unknown option : '+n+S);
end;
Procedure ProcessConfigfile(FN : String);
Var
F : Text;
S : String;
I : Integer;
begin
// Set the default value for old digests without RelSrcDir to the rtl/compiler
// testsuite
RelSrcDir:='tests/';
If Not FileExists(FN) Then
Exit;
Verbose(V_DEBUG,'Parsing config file: '+FN);
Assign(F,FN);
{$i-}
Reset(F);
If IOResult<>0 then
Exit;
{$I+}
While not(EOF(F)) do
begin
ReadLn(F,S);
S:=trim(S);
I:=Pos('#',S);
If I<>0 then
S:=Copy(S,1,I-1);
If (S<>'') then
ProcessOption(S);
end;
Close(F);
end;
Procedure ProcessCommandLine;
Var
I : Integer;
O : String;
c,co : TConfigOpt;
Found : Boolean;
begin
I:=1;
While I<=ParamCount do
begin
O:=ParamStr(I);
Found:=Length(O)=2;
If Found then
For co:=low(TConfigOpt) to high(TConfigOpt) do
begin
Found:=(O[2]=ConfigOpts[co]);
If Found then
begin
c:=co;
Break;
end;
end;
If Not Found then
Verbose(V_ERROR,'Illegal command-line option : '+O)
else
begin
Found:=(I<ParamCount);
If Not found then
Verbose(V_ERROR,'Option requires argument : '+O)
else
begin
inc(I);
O:=ParamStr(I);
SetOpt(c,o);
end;
end;
Inc(I);
end;
end;
Var
Doc: TXMLDocument;
TestCPUID : Integer;
TestOSID : Integer;
TestFPCVersionID : Integer;
TestLazVersionID : Integer;
TestWidgetSetID : Integer;
TestRunID : Integer;
TestCount, ErrorCount, FailureCount, IgnoreCount: integer;
Procedure GetIDs;
var
EnvNode: TDOMElement;
function GetEnvValue(const Name: string): string;
var
Node: TDomNode;
begin
Node := EnvNode.FindNode(Name);
if not assigned(Node) then
Verbose(V_Error,'No environment element for '+Name);
Result := Node.TextContent;
Verbose(V_Debug,format('Environment: retrieved %s=%s', [Name, Result]));
end;
function TryGetEnvValue(const Name, Default: string): string;
var
Node: TDomNode;
begin
Result:=Default;
Node := EnvNode.FindNode(Name);
if not assigned(Node) then
Verbose(V_DEBUG,'No environment element for '+Name)
else
Result := Node.TextContent;
Verbose(V_Debug,format('Environment: retrieved %s=%s', [Name, Result]));
end;
function GetDate: TDateTime;
var
Node: TDomNode;
begin
Result := 0;
Node := Doc.FirstChild.FindNode('DateTimeRan') as TDomElement;
if assigned(Node) then
Result := ScanDateTime('YYYY-MM-DD hh:nn:ss', Node.TextContent)
else
Verbose(V_Debug,'No DateTimeRan node');
end;
begin
EnvNode := Doc.FirstChild.FindNode('Environment') as TDomElement;
if not Assigned(EnvNode) then
Verbose(V_Error,'No environment element');
TestCPU := GetEnvValue('CPU');
TestCPUID := GetCPUId(TestCPU);
If TestCPUID=-1 then
Verbose(V_Error,'NO ID for CPU "'+TestCPU+'" found.');
TestOS := GetEnvValue('OS');
TestOSID := GetOSID(TestOS);
If TestOSID=-1 then
Verbose(V_Error,'NO ID for OS "'+TestOS+'" found.');
TestFPCVersion := GetEnvValue('FPCVersion');
TestFPCVersionID := GetFPCVersionID(TestFPCVersion);
If TestFPCVersionID=-1 then
Verbose(V_Error,'NO ID for fpc version "'+TestFPCVersion+'" found.');
TestLazVersion := GetEnvValue('LazVersion');
TestLazVersionID := GetLazVersionID(TestLazVersion);
If TestLazVersionID=-1 then
Verbose(V_Error,'NO ID for lazarus version "'+TestLazVersion+'" found.');
TestWidgetSet := GetEnvValue('WidgetSet');
TestWidgetSetID := GetWidgetSetID(TestWidgetSet);
If TestWidgetSetID=-1 then
Verbose(V_Error,'NO ID for fpc version "'+TestLazVersion+'" found.');
TestDate := GetDate;
Submitter:=TryGetEnvValue('Submitter', Submitter);
Machine:=TryGetEnvValue('Machine', Machine);
If (Round(TestDate)=0) then
Testdate:=Now;
TestRunID:=GetRunID(TestOSID,TestCPUID,TestFPCVersionID,TestLazVersionID, TestWidgetSetID, TestDate);
If (TestRunID=-1) then
begin
TestRunID:=AddRun(TestOSID,TestCPUID,TestFPCVersionID,TestLazVersionID,TestWidgetSetID,TestDate);
If TestRUnID=-1 then
Verbose(V_Error,'Could not insert new testrun record!');
end
else
CleanTestRun(TestRunID);
end;
procedure GetCounts;
Function GetIntValue(name: string): integer;
var
Node: TDomNode;
begin
Result := -2;
Node := Doc.FirstChild.FindNode(name);
if not assigned(Node) then
Verbose(V_Error,'No element for '+Name);
Result := StrToIntDef(Node.TextContent,-1);
Verbose(V_Debug,format('Environment: retrieved %s=%d', [Name, Result]));
end;
begin
TestCount := GetIntValue('NumberOfRunTests');
ErrorCount := GetIntValue('NumberOfErrors');
FailureCount := GetIntValue('NumberOfFailures');
IgnoreCount := GetIntValue('NumberOfIgnoredTests');
end;
Function GetLog(FN : String) : String;
begin
FN:=ChangeFileExt(FN,'.log');
If FileExists (FN) then
Result:=GetFileContents(FN)
else
Result:='';
end;
Function GetExecuteLog(FN : String) : String;
begin
FN:=ChangeFileExt(FN,'.elg');
If FileExists(FN) then
Result:=GetFileContents(FN)
else
Result:='';
end;
Procedure Processfile (FN: String);
var
logfile : text;
line : string;
TS : TTestStatus;
ID : integer;
Testlog : string;
begin
Assign(logfile,FN);
{$i-}
reset(logfile);
if ioresult<>0 then
Verbose(V_Error,'Unable to open log file'+ResultsFileName);
{$i+}
while not eof(logfile) do
begin
readln(logfile,line);
If analyse(line,TS) then
begin
Verbose(V_NORMAL,'Analysing result for test '+Line);
Inc(StatusCount[TS]);
// If Not ExpectRun[TS] then
//begin
//ID:=RequireTestID(Line);
//If (ID<>-1) then
//begin
//If Not (TestOK[TS] or TestSkipped[TS]) then
//begin
//TestLog:=GetExecuteLog(Line);
//if pos(failed_to_compile,TestLog)=1 then
//TestLog:=GetLog(Line);
//end
//else
//TestLog:='';
//AddTestResult(ID,TestRunID,Ord(TS),TestOK[TS],TestSkipped[TS],TestLog);
//end;
//end
end
else
Inc(UnknownLines);
end;
close(logfile);
end;
procedure ProcessTestListing;
procedure ProcessNodes(AParentNode: TDomNode; APath: string); forward;
procedure ProcessTestSuite(ATestSuiteElement: TDOMElement; APath: string);
var
Name: string;
begin
Name := ATestSuiteElement.GetAttribute('Name');
Verbose(V_NORMAL,'Analysing result for testsuite '+Name + ' at '+ APath);
ProcessNodes(ATestSuiteElement, APath + '|' + Name);
end;
procedure ProcessTest(ATestElement: TDOMElement; APath: string);
var
Name, FullName: string;
TestResult, TestLog: string;
TS: TTestStatus;
ID: LongInt;
begin
Name := ATestElement.GetAttribute('Name');
TestResult := ATestElement.GetAttribute('Result');
TestLog := '';
Verbose(V_NORMAL,'Analysing result for test '+Name);
FullName := APath + '|' + Name;
ID := RequireTestID(FullName);
TS:=GetTestStatus(TestResult);
Verbose(V_Debug,'Test result: '+TestResult+' TestStatus: '+IntToStr(ord(TS)));
if TS in [stFailed, stError] then
TestLog := ATestElement.FindNode('Message').TextContent;
AddTestResult(ID,TestRunID,Ord(TS),TestOK[TS],TestSkipped[TS],TestLog);
end;
procedure ProcessNodes(AParentNode: TDomNode; APath: string);
var
Node: TDomNode;
Element: TDomElement absolute Node;
begin
Node := AParentNode.FirstChild;
while assigned(Node) do
begin
if node is TDOMElement then
begin
if Element.TagName='TestSuite' then
ProcessTestSuite(Element, APath)
else if Element.TagName='Test' then
ProcessTest(Element, APath);
end;
Node := Node.NextSibling;
end;
end;
var
ListingNode: TDomNode;
begin
ListingNode := Doc.FirstChild.FindNode('TestListing');
if assigned(ListingNode) then
ProcessNodes(ListingNode, '');
end;
procedure ProcessResultsFile(FN: String);
begin
Verbose(V_Debug,'Start ProcessResultsFile');
if not FileExists(FN) then
Verbose(V_Error,'Results file "'+ResultsFileName+'" does not exist.');
ReadXMLFile(Doc, FN);
GetIDs;
GetCounts;
ProcessTestListing;
Doc.Free;
Verbose(V_Debug,'End ProcessResultsFile');
end;
procedure UpdateTestRun;
var
qry : string;
res : TQueryResult;
begin
qry:='UPDATE TESTRUN SET ';
//for i:=low(TTestStatus) to high(TTestStatus) do
//qry:=qry+format('%s=%d, ',[SQLField[i],StatusCount[i]]);
qry:=qry+format('TU_TESTCOUNT=%d, TU_ERRORCOUNT=%d, TU_FAILURECOUNT=%d, TU_IGNORECOUNT=%d,',
[TestCount, ErrorCount, FailureCount, IgnoreCount]);
qry:=qry+format(' TU_SUBMITTER="%s", TU_MACHINE="%s", TU_COMMENT="%s", TU_DATE="%s"',
[Submitter,Machine,Comment,SqlDate(TestDate)]);
qry:=qry+' WHERE TU_ID='+format('%d',[TestRunID]);
RunQuery(Qry,res)
end;
begin
DoVerbose := true;
ProcessConfigFile('dbdigest.cfg');
ProcessCommandLine;
If ResultsFileName<>'' then
begin
ConnectToDatabase(DatabaseName,HostName,UserName,Password);
ProcessResultsFile(ResultsFileName);
UpdateTestRun;
end
else
Verbose(V_ERROR,'Missing log file name');
end.