{ 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 license. **********************************************************************} {$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:=ComposeDateTime(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:=(I0 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.