mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 11:24:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			526 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			526 lines
		
	
	
		
			12 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 digest;
 | 
						|
 | 
						|
uses
 | 
						|
  sysutils,teststr,testu,tresults,dbtests;
 | 
						|
 | 
						|
 | 
						|
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,
 | 
						|
  coPort,
 | 
						|
  coLogFile,
 | 
						|
  coOS,
 | 
						|
  coCPU,
 | 
						|
  coCategory,
 | 
						|
  coVersion,
 | 
						|
  coDate,
 | 
						|
  coSubmitter,
 | 
						|
  coMachine,
 | 
						|
  coComment,
 | 
						|
  coTestSrcDir,
 | 
						|
  coRelSrcDir,
 | 
						|
  coVerbose
 | 
						|
 );
 | 
						|
 | 
						|
{ Additional options only for dbdigest.cfg file }
 | 
						|
 | 
						|
TConfigAddOpt = (
 | 
						|
  coCompilerDate,
 | 
						|
  coCompilerFullVersion,
 | 
						|
  coSvnCompilerRevision,
 | 
						|
  coSvnTestsRevision,
 | 
						|
  coSvnRTLRevision,
 | 
						|
  coSvnPackagesRevision
 | 
						|
 );
 | 
						|
 | 
						|
Const
 | 
						|
 | 
						|
ConfigStrings : Array [TConfigOpt] of string = (
 | 
						|
  'databasename',
 | 
						|
  'host',
 | 
						|
  'username',
 | 
						|
  'password',
 | 
						|
  'port',
 | 
						|
  'logfile',
 | 
						|
  'os',
 | 
						|
  'cpu',
 | 
						|
  'category',
 | 
						|
  'version',
 | 
						|
  'date',
 | 
						|
  'submitter',
 | 
						|
  'machine',
 | 
						|
  'comment',
 | 
						|
  'testsrcdir',
 | 
						|
  'relsrcdir',
 | 
						|
  'verbose'
 | 
						|
);
 | 
						|
 | 
						|
ConfigAddStrings : Array [TConfigAddOpt] of string = (
 | 
						|
  'compilerdate',
 | 
						|
  'compilerfullversion',
 | 
						|
  'svncompilerrevision',
 | 
						|
  'svntestsrevision',
 | 
						|
  'svnrtlrevision',
 | 
						|
  'svnpackagesrevision'
 | 
						|
 );
 | 
						|
 | 
						|
ConfigAddCols : Array [TConfigAddOpt] of string = (
 | 
						|
  'TU_COMPILERDATE',
 | 
						|
  'TU_COMPILERFULLVERSION',
 | 
						|
  'TU_SVNCOMPILERREVISION',
 | 
						|
  'TU_SVNTESTSREVISION',
 | 
						|
  'TU_SVNRTLREVISION',
 | 
						|
  'TU_SVNPACKAGESREVISION'
 | 
						|
 );
 | 
						|
 | 
						|
ConfigOpts : Array[TConfigOpt] of char
 | 
						|
           = ('d','h','u','p','P','l','o','c','a','v','t','s','m','C','S','r','V');
 | 
						|
 | 
						|
Var
 | 
						|
  TestOS,
 | 
						|
  TestCPU,
 | 
						|
  TestVersion,
 | 
						|
  TestCategory,
 | 
						|
  DatabaseName,
 | 
						|
  HostName,
 | 
						|
  UserName,
 | 
						|
  Password,
 | 
						|
  Port,
 | 
						|
  LogFileName,
 | 
						|
  Submitter,
 | 
						|
  Machine,
 | 
						|
  Comment : String;
 | 
						|
  TestDate : TDateTime;
 | 
						|
  TestCompilerDate,
 | 
						|
  TestCompilerFullVersion,
 | 
						|
  TestSvnCompilerRevision,
 | 
						|
  TestSvnTestsRevision,
 | 
						|
  TestSvnRTLRevision,
 | 
						|
  TestSvnPackagesRevision : String;
 | 
						|
 | 
						|
Procedure SetAddOpt (O : TConfigAddOpt; Value : string);
 | 
						|
begin
 | 
						|
  Case O of
 | 
						|
    coCompilerDate:
 | 
						|
      TestCompilerDate:=Value;
 | 
						|
    coCompilerFullVersion:
 | 
						|
      TestCompilerFullVersion:=Value;
 | 
						|
    coSvnCompilerRevision:
 | 
						|
      TestSvnCompilerRevision:=Value;
 | 
						|
    coSvnTestsRevision:
 | 
						|
      TestSvnTestsRevision:=Value;
 | 
						|
    coSvnRTLRevision:
 | 
						|
      TestSvnRTLRevision:=Value;
 | 
						|
    coSvnPackagesRevision:
 | 
						|
      TestSvnPackagesRevision:=Value;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
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;
 | 
						|
    coPort         : Port:=Value;
 | 
						|
    coLogFile      : LogFileName:=Value;
 | 
						|
    coOS           : TestOS:=Value;
 | 
						|
    coCPU          : TestCPU:=Value;
 | 
						|
    coCategory     : TestCategory:=Value;
 | 
						|
    coVersion      : TestVersion:=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;
 | 
						|
  coa : TConfigAddOpt;
 | 
						|
 | 
						|
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
 | 
						|
        begin
 | 
						|
          SetOpt(co,S);
 | 
						|
          Exit;
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
    For coa:=low(TConfigAddOpt) to high(TConfigAddOpt) do
 | 
						|
      begin
 | 
						|
      Result:=CompareText(ConfigAddStrings[coa],N)=0;
 | 
						|
      If Result then
 | 
						|
        begin
 | 
						|
          SetAddOpt(coa,S);
 | 
						|
          Exit;
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  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
 | 
						|
  TestCPUID : Integer;
 | 
						|
  TestOSID  : Integer;
 | 
						|
  TestVersionID  : Integer;
 | 
						|
  TestCategoryID : Integer;
 | 
						|
  TestRunID : Integer;
 | 
						|
 | 
						|
Procedure GetIDs;
 | 
						|
 | 
						|
begin
 | 
						|
  TestCPUID := GetCPUId(TestCPU);
 | 
						|
  If TestCPUID=-1 then
 | 
						|
    Verbose(V_Error,'NO ID for CPU "'+TestCPU+'" found.');
 | 
						|
  TestOSID  := GetOSID(TestOS);
 | 
						|
  If TestOSID=-1 then
 | 
						|
    Verbose(V_Error,'NO ID for OS "'+TestOS+'" found.');
 | 
						|
  TestCategoryID := GetCategoryID(TestCategory);
 | 
						|
  If TestCategoryID=-1 then
 | 
						|
    begin
 | 
						|
//    Verbose(V_Error,'NO ID for Category "'+TestCategory+'" found.');
 | 
						|
    TestCategoryID:=1;
 | 
						|
    end;
 | 
						|
  TestVersionID  := GetVersionID(TestVersion);
 | 
						|
  If TestVersionID=-1 then
 | 
						|
    Verbose(V_Error,'NO ID for version "'+TestVersion+'" found.');
 | 
						|
  If (Round(TestDate)=0) then
 | 
						|
    Testdate:=Now;
 | 
						|
  TestRunID:=GetRunID(TestOSID,TestCPUID,TestVersionID,TestDate);
 | 
						|
  If (TestRunID=-1) then
 | 
						|
    begin
 | 
						|
    TestRunID:=AddRun(TestOSID,TestCPUID,TestVersionID,TestCategoryID,TestDate);
 | 
						|
    If TestRUnID=-1 then
 | 
						|
      Verbose(V_Error,'Could not insert new testrun record!');
 | 
						|
    end
 | 
						|
  else
 | 
						|
    CleanTestRun(TestRunID);
 | 
						|
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,prevLine : string;
 | 
						|
  TS,PrevTS : TTestStatus;
 | 
						|
  ID,PrevID : integer;
 | 
						|
  Testlog : string;
 | 
						|
  is_new : boolean;
 | 
						|
begin
 | 
						|
  Assign(logfile,FN);
 | 
						|
  PrevId:=-1;
 | 
						|
  PrevLine:='';
 | 
						|
  is_new:=false;
 | 
						|
  PrevTS:=low(TTestStatus);
 | 
						|
{$i-}
 | 
						|
  reset(logfile);
 | 
						|
  if ioresult<>0 then
 | 
						|
    Verbose(V_Error,'Unable to open log file'+logfilename);
 | 
						|
{$i+}
 | 
						|
  while not eof(logfile) do
 | 
						|
    begin
 | 
						|
    readln(logfile,line);
 | 
						|
    If analyse(line,TS) then
 | 
						|
      begin
 | 
						|
      Verbose(V_NORMAL,'Analysing result for test '+Line);
 | 
						|
      If Not ExpectRun[TS] then
 | 
						|
        begin
 | 
						|
        ID:=RequireTestID(Line);
 | 
						|
        if (PrevID<>-1) and (PrevID<>ID) then
 | 
						|
          begin
 | 
						|
            { This can only happen if a Successfully compiled message
 | 
						|
              is not followed by any other line about the same test }
 | 
						|
            TestLog:='';
 | 
						|
            AddTestResult(PrevID,TestRunId,ord(PrevTS),
 | 
						|
              TestOK[PrevTS],TestSkipped[PrevTS],TestLog,is_new);
 | 
						|
            Verbose(V_Warning,'Orphaned test: "'+prevline+'"');
 | 
						|
          end;
 | 
						|
        PrevID:=-1;
 | 
						|
        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 can fail for test that contain %recompile 
 | 
						|
            as the same }
 | 
						|
          if AddTestResult(ID,TestRunID,Ord(TS),TestOK[TS],
 | 
						|
               TestSkipped[TS],TestLog,is_new) <> -1 then
 | 
						|
            begin
 | 
						|
              if is_new then
 | 
						|
                Inc(StatusCount[TS])
 | 
						|
              else
 | 
						|
                Verbose(V_Debug,'Test: "'+line+'" was updated');
 | 
						|
            end
 | 
						|
          else
 | 
						|
            begin
 | 
						|
              Verbose(V_Warning,'Test: "'+line+'" already registered');
 | 
						|
            end;
 | 
						|
              
 | 
						|
          end;
 | 
						|
        end
 | 
						|
      else  
 | 
						|
        begin
 | 
						|
          Inc(StatusCount[TS]);
 | 
						|
          PrevTS:=TS;
 | 
						|
          PrevID:=RequireTestID(line);
 | 
						|
          PrevLine:=line;
 | 
						|
        end;
 | 
						|
 
 | 
						|
      end
 | 
						|
    else
 | 
						|
      begin
 | 
						|
        Inc(UnknownLines);
 | 
						|
        Verbose(V_Warning,'Unknown line: "'+line+'"');
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  close(logfile);
 | 
						|
end;
 | 
						|
 | 
						|
procedure UpdateTestRun;
 | 
						|
 | 
						|
  var
 | 
						|
     i : TTestStatus;
 | 
						|
     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]]);
 | 
						|
    if TestCompilerDate<>'' then
 | 
						|
      qry:=qry+format('%s="%s", ',[ConfigAddCols[coCompilerDate],EscapeSQL(TestCompilerDate)]);
 | 
						|
    if TestCompilerFullVersion<>'' then
 | 
						|
      qry:=qry+format('%s="%s", ',[ConfigAddCols[coCompilerFullVersion],EscapeSQL(TestCompilerFullVersion)]);
 | 
						|
    if TestSvnCompilerRevision<>'' then
 | 
						|
      qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnCompilerRevision],EscapeSQL(TestSvnCompilerRevision)]);
 | 
						|
    if TestSvnTestsRevision<>'' then
 | 
						|
      qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnTestsRevision],EscapeSQL(TestSvnTestsRevision)]);
 | 
						|
    if TestSvnRTLRevision<>'' then
 | 
						|
      qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnRTLRevision],EscapeSQL(TestSvnRTLRevision)]);
 | 
						|
    if TestSvnPackagesRevision<>'' then
 | 
						|
      qry:=qry+format('%s="%s", ',[ConfigAddCols[coSvnPackagesRevision],EscapeSQL(TestSvnPackagesRevision)]);
 | 
						|
 | 
						|
    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
 | 
						|
  ProcessConfigFile('dbdigest.cfg');
 | 
						|
  ProcessCommandLine;
 | 
						|
  If LogFileName<>'' then
 | 
						|
    begin
 | 
						|
    ConnectToDatabase(DatabaseName,HostName,UserName,Password,Port);
 | 
						|
    GetIDs;
 | 
						|
    ProcessFile(LogFileName);
 | 
						|
    UpdateTestRun;
 | 
						|
    end
 | 
						|
  else
 | 
						|
    Verbose(V_ERROR,'Missing log file name');
 | 
						|
end.
 |