GdbmiDebugger, test: more output, to compare test results

git-svn-id: trunk@64959 -
This commit is contained in:
martin 2021-04-10 23:48:07 +00:00
parent 05d6300123
commit caeb20c1c4
7 changed files with 512 additions and 251 deletions

View File

@ -321,13 +321,13 @@ begin
i := high(QWord) - FStartTime + 1 + i;
if FTotalGDBInternalErrorCnt > 0
then Result := Result + '.gdb_intern_'+IntToStr(FTotalGDBInternalErrorCnt);
then Result := Result + '___gdb_intern.'+IntToStr(FTotalGDBInternalErrorCnt);
if FTotalDsErrorCrash > 0
then Result := Result + '.gdb_crash_'+IntToStr(FTotalDsErrorCrash);
then Result := Result + '___gdb_crash.'+IntToStr(FTotalDsErrorCrash);
if FTotalClassVsRecord > 0
then Result := Result + '.class_rec_'+IntToStr(FTotalClassVsRecord);
then Result := Result + '___class_re._'+IntToStr(FTotalClassVsRecord);
Result := Result + '.t_'+ IntToStr(i div 1000);
// Result := Result + '___time.'+ IntToStr(i div 1000);
end;
function TGDBTestCase.StartGDB(AppDir, TestExeName: String): TGDBMIDebugger;

View File

@ -407,125 +407,130 @@ var
end;
begin
if not TestTrue('Dbg did NOT enter dsError', ADbg.State <> dsError) then exit;
if Data.OnBeforeTest <> nil then Data.OnBeforeTest(@Data);
StartTestBlock;
try
if not TestTrue('Dbg did NOT enter dsError', ADbg.State <> dsError) then exit;
if Data.OnBeforeTest <> nil then Data.OnBeforeTest(@Data);
rx := nil;
Stack := Data.StackFrame;
DataRes := Data.Result[SymbolType];
IgnoreFlags := DataRes.Flgs * WatchExpFlagMask[SymbolType];
IgnoreAll := IgnoreFlags * WatchExpFlagSIgnAll <> [];
IgnoreData := IgnoreFlags * WatchExpFlagSIgnData <> [];
IgnoreKind := IgnoreFlags * WatchExpFlagSIgnKind <> [];
IgnoreKindPtr := IgnoreFlags * WatchExpFlagSIgnKindPtr <> [];
IgnoreTpName := IgnoreFlags * WatchExpFlagSIgnTpName <> [];
rx := nil;
Stack := Data.StackFrame;
DataRes := Data.Result[SymbolType];
IgnoreFlags := DataRes.Flgs * WatchExpFlagMask[SymbolType];
IgnoreAll := IgnoreFlags * WatchExpFlagSIgnAll <> [];
IgnoreData := IgnoreFlags * WatchExpFlagSIgnData <> [];
IgnoreKind := IgnoreFlags * WatchExpFlagSIgnKind <> [];
IgnoreKindPtr := IgnoreFlags * WatchExpFlagSIgnKindPtr <> [];
IgnoreTpName := IgnoreFlags * WatchExpFlagSIgnTpName <> [];
// Get Value
n := Data.TestName;
if n = '' then n := Data.Expression + ' (' + TWatchDisplayFormatNames[Data.DspFormat] + ', ' + dbgs(Data.EvaluateFlags) + ' RepCnt=' + dbgs(Data.RepeatCount) + ')';
Name := Name + ' ' + n + ' ::: '+adbg.GetLocation.SrcFile+' '+IntToStr(ADbg.GetLocation.SrcLine);
LogToFile('###### ' + Name + '###### '+LineEnding);
flag := AWatch <> nil; // test for typeinfo/kind // Awatch=nil > direct gdb command
IsValid := True;
HasTpInfo := True;
if flag then begin;
WV := AWatch.Values[1, Stack];// trigger read
s := WV.Value;
IsValid := WV.Validity = ddsValid;
HasTpInfo := IsValid and (WV.TypeInfo <> nil);
// flag := flag and IsValid;
end
else
s := WatchValue;
if not TestTrue('ADbg did NOT enter dsError', ADbg.State <> dsError) then exit;
// Check Data
f2 := True;
IgnoreText := ''; if IgnoreData then IgnoreText := 'Ignored by flag';
if IsValid = not(fTExpectError in DataRes.Flgs) then begin
rx := TRegExpr.Create;
rx.ModifierI := true;
rx.Expression := DataRes.ExpMatch;
if DataRes.ExpMatch <> ''
then f2 := TestTrue(Name + ' Matches "'+DataRes.ExpMatch + '", but was "' + s + '"', rx.Exec(s), DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
FreeAndNil(rx);
end else begin
f2 := TestTrue(Name + ' Matches "'+DataRes.ExpMatch + '", but STATE was <'+dbgs(WV.Validity)+'> Val="'+s+'"', False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
//exit; // failed Data, do not list others as potential unexpected success
end;
if (not f2) and IgnoreAll then exit; // failed Data, do not list others as potential unexpected success
// TypeInfo checks ?
if (not flag) or (DataRes.ExpTypeName = '') then exit;
// Check TypeInfo
s:='';
if HasTpInfo then WriteStr(s, WV.TypeInfo.Kind);
WriteStr(s2, DataRes.ExpKind);
IgnoreText := ''; if IgnoreKind then IgnoreText := 'Ignored by flag';
if IsValid and HasTpInfo then begin
if (not IgnoreKind) and IgnoreKindPtr and (WV.TypeInfo.Kind = skPointer) then IgnoreText := 'Ignored by flag (Kind may be Ptr)';
f2 := TestEquals(Name + ' Kind', s2, s, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
if ((s2='skClass') and (s = 'skRecord')) or ((s='skClass') and (s2 = 'skRecord')) then begin
TotalClassVsRecord := TotalClassVsRecord + 1;
end;
end else begin
f2 := TestTrue(Name + ' Kind is "'+s2+'", failed: STATE was <'+dbgs(WV.Validity)+'>, HasTypeInfo='+dbgs(HasTpInfo)+' Val="'+s+'"', False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end;
if (not f2) and IgnoreAll then exit; // failed Data, do not list others as potential unexpected success
// Check TypeName
IgnoreText := ''; if IgnoreTpName then IgnoreText := 'Ignored by flag';
if IsValid and HasTpInfo then begin
s:='';
if HasTpInfo then s := WV.TypeInfo.TypeName;
CmpNames(Name+' TypeName', DataRes.ExpTypeName, s, fTpMtch in DataRes.Flgs);
//if fTpMtch in DataRes.Flgs
//then begin
// rx := TRegExpr.Create;
// rx.ModifierI := true;
// rx.Expression := DataRes.ExpTypeName;
// TestTrue(Name + ' TypeName matches '+DataRes.ExpTypeName+' but was '+s, rx.Exec(s), DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
// FreeAndNil(rx);
// end
// else TestEquals(Name + ' TypeName', LowerCase(DataRes.ExpTypeName), LowerCase(s), DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end else begin
TestTrue(Name + ' TypeName matches '+DataRes.ExpTypeName+' but STATE was <'+dbgs(WV.Validity)+'> HasTypeInfo='+dbgs(HasTpInfo)+' Val="'+s+'"', False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end;
MemberTests := DataRes.FullTypesExpect;
if Length(MemberTests) > 0 then begin
if HasTpInfo then begin
for i := 0 to Length(MemberTests) - 1 do begin
j := WV.TypeInfo.Fields.Count - 1;
while (j >= 0) and (CompareText(WV.TypeInfo.Fields[j].Name, MemberTests[i].Name) <> 0) do dec(j);
TestTrue(Name + ' no members with name ' + MemberTests[i].Name,
(fTExpectNotFOund in MemberTests[i].Flgs) <> (j >= 0),
DataRes.MinGdb, DataRes.MinFpc, IgnoreText);;
if j >= 0 then begin
fld := WV.TypeInfo.Fields[j];
WriteStr(s, MemberTests[i].ExpKind);
WriteStr(s2, fld.DBGType.Kind);
if fld.DBGType <> nil then begin
TestTrue(Name + ' members with name ' + MemberTests[i].Name + ' type='
+ s + ' but was ' + s2,
MemberTests[i].ExpKind = fld.DBGType.Kind, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);;
CmpNames(Name + ' members with name ' + MemberTests[i].Name + 'TypeName',
MemberTests[i].ExpTypeName, fld.DBGType.TypeName, fTpMtch in MemberTests[i].Flgs);
end
else
TestTrue(Name + ' no dbgtype for members with name' + MemberTests[i].Name, False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);;
end;
end;
// Get Value
n := Data.TestName;
if n = '' then n := Data.Expression + ' (' + TWatchDisplayFormatNames[Data.DspFormat] + ', ' + dbgs(Data.EvaluateFlags) + ' RepCnt=' + dbgs(Data.RepeatCount) + ')';
Name := Name + ' ' + n + ' ::: '+adbg.GetLocation.SrcFile+' '+IntToStr(ADbg.GetLocation.SrcLine);
LogToFile('###### ' + Name + '###### '+LineEnding);
flag := AWatch <> nil; // test for typeinfo/kind // Awatch=nil > direct gdb command
IsValid := True;
HasTpInfo := True;
if flag then begin;
WV := AWatch.Values[1, Stack];// trigger read
s := WV.Value;
IsValid := WV.Validity = ddsValid;
HasTpInfo := IsValid and (WV.TypeInfo <> nil);
// flag := flag and IsValid;
end
else
TestTrue(Name + ' no typeinfo for members' , False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end;
s := WatchValue;
if not TestTrue('ADbg did NOT enter dsError', ADbg.State <> dsError) then exit;
// Check Data
f2 := True;
IgnoreText := ''; if IgnoreData then IgnoreText := 'Ignored by flag';
if IsValid = not(fTExpectError in DataRes.Flgs) then begin
rx := TRegExpr.Create;
rx.ModifierI := true;
rx.Expression := DataRes.ExpMatch;
if DataRes.ExpMatch <> ''
then f2 := TestTrue(Name + ' Matches "'+DataRes.ExpMatch + '", but was "' + s + '"', rx.Exec(s), DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
FreeAndNil(rx);
end else begin
f2 := TestTrue(Name + ' Matches "'+DataRes.ExpMatch + '", but STATE was <'+dbgs(WV.Validity)+'> Val="'+s+'"', False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
//exit; // failed Data, do not list others as potential unexpected success
end;
if (not f2) and IgnoreAll then exit; // failed Data, do not list others as potential unexpected success
// TypeInfo checks ?
if (not flag) or (DataRes.ExpTypeName = '') then exit;
// Check TypeInfo
s:='';
if HasTpInfo then WriteStr(s, WV.TypeInfo.Kind);
WriteStr(s2, DataRes.ExpKind);
IgnoreText := ''; if IgnoreKind then IgnoreText := 'Ignored by flag';
if IsValid and HasTpInfo then begin
if (not IgnoreKind) and IgnoreKindPtr and (WV.TypeInfo.Kind = skPointer) then IgnoreText := 'Ignored by flag (Kind may be Ptr)';
f2 := TestEquals(Name + ' Kind', s2, s, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
if ((s2='skClass') and (s = 'skRecord')) or ((s='skClass') and (s2 = 'skRecord')) then begin
TotalClassVsRecord := TotalClassVsRecord + 1;
end;
end else begin
f2 := TestTrue(Name + ' Kind is "'+s2+'", failed: STATE was <'+dbgs(WV.Validity)+'>, HasTypeInfo='+dbgs(HasTpInfo)+' Val="'+s+'"', False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end;
if (not f2) and IgnoreAll then exit; // failed Data, do not list others as potential unexpected success
// Check TypeName
IgnoreText := ''; if IgnoreTpName then IgnoreText := 'Ignored by flag';
if IsValid and HasTpInfo then begin
s:='';
if HasTpInfo then s := WV.TypeInfo.TypeName;
CmpNames(Name+' TypeName', DataRes.ExpTypeName, s, fTpMtch in DataRes.Flgs);
//if fTpMtch in DataRes.Flgs
//then begin
// rx := TRegExpr.Create;
// rx.ModifierI := true;
// rx.Expression := DataRes.ExpTypeName;
// TestTrue(Name + ' TypeName matches '+DataRes.ExpTypeName+' but was '+s, rx.Exec(s), DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
// FreeAndNil(rx);
// end
// else TestEquals(Name + ' TypeName', LowerCase(DataRes.ExpTypeName), LowerCase(s), DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end else begin
TestTrue(Name + ' TypeName matches '+DataRes.ExpTypeName+' but STATE was <'+dbgs(WV.Validity)+'> HasTypeInfo='+dbgs(HasTpInfo)+' Val="'+s+'"', False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end;
MemberTests := DataRes.FullTypesExpect;
if Length(MemberTests) > 0 then begin
if HasTpInfo then begin
for i := 0 to Length(MemberTests) - 1 do begin
j := WV.TypeInfo.Fields.Count - 1;
while (j >= 0) and (CompareText(WV.TypeInfo.Fields[j].Name, MemberTests[i].Name) <> 0) do dec(j);
TestTrue(Name + ' no members with name ' + MemberTests[i].Name,
(fTExpectNotFOund in MemberTests[i].Flgs) <> (j >= 0),
DataRes.MinGdb, DataRes.MinFpc, IgnoreText);;
if j >= 0 then begin
fld := WV.TypeInfo.Fields[j];
WriteStr(s, MemberTests[i].ExpKind);
WriteStr(s2, fld.DBGType.Kind);
if fld.DBGType <> nil then begin
TestTrue(Name + ' members with name ' + MemberTests[i].Name + ' type='
+ s + ' but was ' + s2,
MemberTests[i].ExpKind = fld.DBGType.Kind, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);;
CmpNames(Name + ' members with name ' + MemberTests[i].Name + 'TypeName',
MemberTests[i].ExpTypeName, fld.DBGType.TypeName, fTpMtch in MemberTests[i].Flgs);
end
else
TestTrue(Name + ' no dbgtype for members with name' + MemberTests[i].Name, False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);;
end;
end;
end
else
TestTrue(Name + ' no typeinfo for members' , False, DataRes.MinGdb, DataRes.MinFpc, IgnoreText);
end;
finally
EndTestBlock;
end;
end;
procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray; AWatches: TWatches;

View File

@ -996,8 +996,8 @@ end;
initialization
RegisterDbgTest(TTestExceptionAddrDirect);
RegisterDbgTest(TTestExceptionAddrInDirect);
RegisterDbgTest(TTestExceptionForceName);
RegisterDbgTest(TTestExceptionAddrInDirect, [stDwarfSet, stStabs]);
RegisterDbgTest(TTestExceptionForceName, [stDwarfSet, stStabs]);
ControlTestExceptionOne := TestControlRegisterTest('TTestExceptionOne');
ControlTestExceptionOneException := TestControlRegisterTest('Exception', ControlTestExceptionOne);

View File

@ -36,6 +36,8 @@ var
SetLogPathProc: TSetLogPath;
GetLogPathProc: TGetLogPath;
GetWriteLogProc: TGetWriteLog;
GetWriteReportProc: TGetWriteLog;
GetWriteOverviewProc: TGetWriteLog;
RegisterCompilerProc: TRegisterCompiler;
RegisterDebuggerProc: TRegisterDebugger;
RegisterTestProc: TRegisterTest;
@ -54,6 +56,8 @@ function TestControlRegisterTest(Name: String; Parent: Pointer = nil): Pointer;
procedure TestControlSetLogPath(path: string);
function TestControlGetLogPath: string;
function TestControlGetWriteLog: TWriteLogConfig;
function TestControlGetWriteReport: TWriteLogConfig;
function TestControlGetWriteOverView: TWriteLogConfig;
procedure TestControlRegisterCompilers(c: TBaseList);
procedure TestControlRegisterDebuggers(d: TBaseList);
@ -151,6 +155,22 @@ begin
Result := wlAlways;
end;
function TestControlGetWriteReport: TWriteLogConfig;
begin
Result := wlNever;
if GetWriteReportProc <> nil then
Result := GetWriteReportProc();
if (Result = wlOnError) and (TestControlGetWriteLog = wlAlways) then
Result := wlAlways;
end;
function TestControlGetWriteOverView: TWriteLogConfig;
begin
Result := wlNever;
if GetWriteOverviewProc <> nil then
Result := GetWriteOverviewProc();
end;
procedure TestControlRegisterCompilers(c: TBaseList);
var
i: Integer;

View File

@ -77,6 +77,32 @@ object DbgTestControlForm: TDbgTestControlForm
MaxLength = 0
TabOrder = 2
end
object CheckWriteReport: TCheckBox
AnchorSideLeft.Control = WriteLogsOnErr
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = CheckWriteLogs
Left = 216
Height = 19
Top = 1
Width = 91
BorderSpacing.Left = 6
Caption = 'Write Reports'
OnChange = CheckWriteReportChange
TabOrder = 3
end
object CheckWriteOverview: TCheckBox
AnchorSideLeft.Control = CheckWriteReport
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = CheckWriteLogs
Left = 313
Height = 19
Top = 1
Width = 100
BorderSpacing.Left = 6
Caption = 'Write Overview'
OnChange = CheckWriteOverviewChange
TabOrder = 4
end
end
object Panel2: TPanel
Left = 0
@ -265,74 +291,13 @@ object DbgTestControlForm: TDbgTestControlForm
end
end
object ilNodeStates: TImageList
left = 220
top = 380
Left = 220
Top = 380
Bitmap = {
4C69020000001000000010000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF000000FFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFF0000
00FFFFFFFFFFFFFFFFFFFFFFFFFF000000FF000000FF000000FFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFF0000
00FF000000FFFFFFFFFF000000FF000000FF000000FFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFF0000
00FF000000FF000000FF000000FF000000FFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFF000000FF000000FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFF000000FF000000FF000000FF0000
00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
00FF000000FFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000
4C7A020000001000000010000000520000000000000078DAFBFF9F7CC0000450
9A644C0BFD44BA7954FFA8FE41957E29C97F9482FFA3F99F28FD487A48D68FA6
07AF7E7473B0F899A07E7436B299C4EAC7A69758FFE3D24B4AF8E10ACFD1FC4F
DDFC0F003436B484
}
end
end

View File

@ -16,6 +16,8 @@ type
{ TDbgTestControlForm }
TDbgTestControlForm = class(TForm)
CheckWriteReport: TCheckBox;
CheckWriteOverview: TCheckBox;
chkDbg: TTreeView;
chkFpc: TTreeView;
chkSym: TCheckListBox;
@ -51,11 +53,13 @@ type
procedure btnTestAllClick(Sender: TObject);
procedure btnTestNoneClick(Sender: TObject);
procedure CheckWriteLogsChange(Sender: TObject);
procedure CheckWriteOverviewChange(Sender: TObject);
procedure CheckWriteReportChange(Sender: TObject);
procedure chkTestsMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
FWriteLogValCache: TWriteLogConfig;
FWriteLogIsCached: Boolean;
FWriteLogValCache, FWriteReportValCache, FWriteOverViewValCache: TWriteLogConfig;
FWriteLogIsCached, FWriteReportIsCached, FWriteOverViewIsCached: Boolean;
public
procedure DbgShow(Data: PtrInt);
end;
@ -163,6 +167,34 @@ begin
DbgTestControlForm.FWriteLogIsCached := True;
end;
function GetWriteReport: TWriteLogConfig;
begin
if DbgTestControlForm.FWriteReportIsCached then begin
Result := DbgTestControlForm.FWriteReportValCache;
exit;
end;
Result := wlNever;
if DbgTestControlForm.CheckWriteReport.Checked then
Result := wlOnError;
DbgTestControlForm.FWriteReportValCache := Result;
DbgTestControlForm.FWriteReportIsCached := True;
end;
function GetWriteOverview: TWriteLogConfig;
begin
if DbgTestControlForm.FWriteOverViewIsCached then begin
Result := DbgTestControlForm.FWriteOverViewValCache;
exit;
end;
Result := wlNever;
if DbgTestControlForm.CheckWriteOverview.Checked then
Result := wlAlways;
DbgTestControlForm.FWriteOverViewValCache := Result;
DbgTestControlForm.FWriteOverViewIsCached := True;
end;
procedure RegisterCompiler(name: string);
begin
DbgTestControlForm.chkFpc.Items.Add(nil, Name)
@ -259,6 +291,16 @@ begin
FWriteLogIsCached := False;
end;
procedure TDbgTestControlForm.CheckWriteOverviewChange(Sender: TObject);
begin
FWriteOverViewIsCached := False;
end;
procedure TDbgTestControlForm.CheckWriteReportChange(Sender: TObject);
begin
FWriteReportIsCached := False;
end;
procedure TDbgTestControlForm.DbgShow(Data: PtrInt);
var
s: TSymbolType;
@ -293,6 +335,8 @@ initialization
SetLogPathProc := @SetLogPath;
GetLogPathProc := @GetLogPath;
GetWriteLogProc := @GetWriteLog;
GetWriteReportProc := @GetWriteReport;
GetWriteOverviewProc := @GetWriteOverview;
RegisterCompilerProc := @RegisterCompiler;
RegisterDebuggerProc := @RegisterDebugger;
RegisterTestProc := @RegisterTest;

View File

@ -7,7 +7,7 @@ interface
uses
Classes, SysUtils, TTestDbgExecuteables, TestDbgControl, TestDbgConfig,
TestOutputLogger, TestCommonSources, LazFileUtils, LazLogger,
DbgIntfDebuggerBase, fpcunit, testregistry, RegExpr;
DbgIntfDebuggerBase, StrUtils, fpcunit, testregistry, RegExpr;
const
EqIgnoreCase = False; // for TestEquals(..., CaseSense, ...);
@ -17,23 +17,45 @@ type
TDBGTestsuite = class;
TDBGStates = set of TDBGState;
{ TDbgBaseTestsuite }
TDbgBaseTestsuite = class(TTestSuite)
private
FInRun: Integer;
FDirectParent: TDbgBaseTestsuite;
FOverviewReport: String;
procedure LogOverviewReport;
protected
procedure Clear; virtual;
public
procedure Run(AResult: TTestResult); override;
procedure RunTest(ATest: TTest; AResult: TTestResult); override;
procedure AddTest(ATest: TTest); overload; override;
procedure AddOverviewLog(Const AText: String);
end;
{ TDBGTestCase }
TDBGTestCase = class(TTestCase)
private
FParent: TDBGTestsuite;
FDirectParent: TDbgBaseTestsuite;
// TestResults
FTestBaseName: String;
FTestErrors, FIgnoredErrors, FUnexpectedSuccess: String;
FTestCnt, FTestErrorCnt, FIgnoredErrorCnt, FUnexpectedSuccessCnt, FSucessCnt: Integer;
FInTestBlock: integer;
FInTestBlockTxt: String;
FInTestBlockRes: (tbOk, tbErr, tbIgnore, tbUnexpected);
FTotalErrorCnt, FTotalIgnoredErrorCnt, FTotalUnexpectedSuccessCnt: Integer;
FRegX: TRegExpr;
// Logging
FLogLock: TRTLCriticalSection;
FLogFile: TLazLoggerFileHandle;
FLogFileCreated: Boolean;
FLogFileName: String;
FLogFile, FReportFile: TLazLoggerFileHandle;
FLogFileCreated, FReportFileCreated: Boolean;
FLogFileName, FReportFileName: String;
FLogBufferText: TStringList;
procedure InitLog;
procedure FinishLog;
@ -43,6 +65,8 @@ type
protected
FIgnoreReason: String;
// TestResults
procedure StartTestBlock;
procedure EndTestBlock;
procedure AddTestError (s: string; MinDbgVers: Integer = 0; AIgnoreReason: String = '');
procedure AddTestError (s: string; MinDbgVers: Integer; MinFpcVers: Integer;AIgnoreReason: String = '');
procedure AddTestSuccess(s: string; MinDbgVers: Integer = 0; AIgnoreReason: String = '');
@ -56,6 +80,7 @@ type
function GetLogFileName: String; virtual;
function GetFinalLogFileName: String; virtual;
procedure CreateLog;
procedure CreateReport;
// Debugln
procedure DoDbgOut(Sender: TObject; S: string; var Handled: Boolean); virtual;
procedure DoDebugln(Sender: TObject; S: string; var Handled: Boolean); virtual;
@ -117,7 +142,7 @@ type
{ TDBGTestWrapper }
TDBGTestWrapper = class(TTestSuite)
TDBGTestWrapper = class(TDbgBaseTestsuite)
private
FParent: TDBGTestsuite;
public
@ -127,18 +152,13 @@ type
{ TDBGTestsuite }
TDBGTestsuite = class(TTestSuite)
TDBGTestsuite = class(TDbgBaseTestsuite)
private
FCompiler: TTestDbgCompiler;
FDebugger: TTestDbgDebugger;
FInRun: Boolean;
protected
procedure Clear; virtual;
public
constructor Create(ACompiler: TTestDbgCompiler; ADebugger: TTestDbgDebugger); overload;
procedure RegisterDbgTest(ATestClass: TTestCaseClass);
procedure Run(AResult: TTestResult); override;
procedure RunTest(ATest: TTest; AResult: TTestResult); override;
property Compiler: TTestDbgCompiler read FCompiler;
property Debugger: TTestDbgDebugger read FDebugger;
@ -146,13 +166,93 @@ type
TDBGTestsuiteClass = class of TDBGTestsuite;
procedure RegisterDbgTest(ATestClass: TTestCaseClass);
procedure RegisterDbgTest(ATestClass: TTestCaseClass; ASymTypes: TSymbolTypes = []);
procedure CreateTestSuites(ACompilerList: TTestDbgCompilerList;
ADebuggerList: TTestDbgDebuggerList; ATestSuiteClass: TDBGTestsuiteClass);
implementation
{ TDbgBaseTestsuite }
procedure TDbgBaseTestsuite.LogOverviewReport;
var
oname: String;
FOview: TextFile;
begin
if FOverviewReport = '' then
exit;
if TestControlGetWriteOverView = wlAlways then begin
if DirectoryExistsUTF8(TestControlGetLogPath) then
oname := TestControlGetLogPath
else
oname := GetCurrentDirUTF8;
oname := oname + 'overview_' +
NameToFileName(DateTimeToStr(Now), False) +
'.txt';
AssignFile(FOView, oname);
Rewrite(FOView);
writeln(FOView, FOverviewReport);
CloseFile(FOView);
end;
FOverviewReport := '';
end;
procedure TDbgBaseTestsuite.Clear;
begin
//
end;
procedure TDbgBaseTestsuite.Run(AResult: TTestResult);
begin
inc(FInRun);
try
inherited Run(AResult);
finally
dec(FInRun);
if FInRun = 0 then begin
LogOverviewReport;
end;
Clear;
end;
end;
procedure TDbgBaseTestsuite.RunTest(ATest: TTest; AResult: TTestResult);
begin
inc(FInRun);
try
inherited RunTest(ATest, AResult);
finally
dec(FInRun);
if FInRun = 0 then begin
LogOverviewReport;
Clear;
end;
end;
end;
procedure TDbgBaseTestsuite.AddTest(ATest: TTest);
begin
inherited AddTest(ATest);
if ATest is TDbgBaseTestsuite then
TDbgBaseTestsuite(ATest).FDirectParent := Self
else
if ATest is TDBGTestCase then
TDBGTestCase(ATest).FDirectParent := Self;
end;
procedure TDbgBaseTestsuite.AddOverviewLog(const AText: String);
begin
if (FDirectParent <> nil) and (FDirectParent.FInRun > 0) then begin
FDirectParent.AddOverviewLog(AText);
exit;
end;
FOverviewReport := FOverviewReport + AText;
if (FInRun = 0) then
LogOverviewReport;
end;
{ TDBGTestCase }
function TDBGTestCase.GetCompiler: TTestDbgCompiler;
@ -165,6 +265,39 @@ begin
Result := Parent.Debugger;
end;
procedure TDBGTestCase.StartTestBlock;
begin
if FInTestBlock = 0 then begin
inc(FTestCnt);
FInTestBlockTxt := '';
FInTestBlockRes := tbOk;
end;
inc(FInTestBlock);
end;
procedure TDBGTestCase.EndTestBlock;
begin
dec(FInTestBlock);
if FInTestBlock = 0 then begin
case FInTestBlockRes of
tbErr: begin
FTestErrors := FTestErrors + FInTestBlockTxt;
inc(FTestErrorCnt);
end;
tbIgnore: begin
FIgnoredErrors := FIgnoredErrors + FInTestBlockTxt;
inc(FIgnoredErrorCnt);
end;
tbUnexpected: begin
FUnexpectedSuccess:= FUnexpectedSuccess + FInTestBlockTxt;
inc(FUnexpectedSuccessCnt);
end;
end;
FInTestBlockTxt := '';
FInTestBlockRes := tbOk;
end;
end;
procedure TDBGTestCase.AddTestError(s: string; MinDbgVers: Integer;
AIgnoreReason: String);
begin
@ -177,7 +310,8 @@ var
IgnoreReason: String;
i: Integer;
begin
inc(FTestCnt);
if FInTestBlock = 0 then
inc(FTestCnt);
IgnoreReason := '';
s := FTestBaseName + s;
if MinDbgVers > 0 then begin
@ -194,13 +328,26 @@ begin
if IgnoreReason = '' then
IgnoreReason := FIgnoreReason;
if IgnoreReason <> '' then begin
FIgnoredErrors := FIgnoredErrors + IntToStr(FTestCnt) + ': ' + '### '+IgnoreReason +' >>> '+s+LineEnding;
inc(FIgnoredErrorCnt);
end else begin
FTestErrors := FTestErrors + IntToStr(FTestCnt) + ': ' + s + LineEnding;
DebugLn(['!!!!! ERROR: ' + IntToStr(FTestCnt) + ': ' + s]);
inc(FTestErrorCnt);
if FInTestBlock > 0 then begin
if IgnoreReason <> '' then begin
FInTestBlockTxt := FInTestBlockTxt + IntToStr(FTestCnt) + ': ' + '### '+IgnoreReason +' >>> '+s+LineEnding;
if FInTestBlockRes in [tbOk, tbUnexpected] then
FInTestBlockRes := tbIgnore;
end else begin
FInTestBlockTxt := FInTestBlockTxt + IntToStr(FTestCnt) + ': ' + s + LineEnding;
FInTestBlockRes := tbErr;
DebugLn(['!!!!! ERROR: ' + IntToStr(FTestCnt) + ': ' + s]);
end;
end
else begin
if IgnoreReason <> '' then begin
FIgnoredErrors := FIgnoredErrors + IntToStr(FTestCnt) + ': ' + '### '+IgnoreReason +' >>> '+s+LineEnding;
inc(FIgnoredErrorCnt);
end else begin
FTestErrors := FTestErrors + IntToStr(FTestCnt) + ': ' + s + LineEnding;
DebugLn(['!!!!! ERROR: ' + IntToStr(FTestCnt) + ': ' + s]);
inc(FTestErrorCnt);
end;
end;
end;
@ -216,7 +363,8 @@ var
i: Integer;
begin
s := FTestBaseName + s;
inc(FTestCnt);
if FInTestBlock = 0 then
inc(FTestCnt);
if (MinDbgVers > 0) then begin
i := Debugger.Version;
if (i > 0) and (i < MinDbgVers) then
@ -232,8 +380,15 @@ begin
if AIgnoreReason <> '' then begin
s := '[OK] ' + s;
FUnexpectedSuccess:= FUnexpectedSuccess + IntToStr(FTestCnt) + ': ' + '### '+AIgnoreReason +' >>> '+s+LineEnding;
inc(FUnexpectedSuccessCnt);
if FInTestBlock > 0 then begin
FInTestBlockTxt := FInTestBlockTxt + IntToStr(FTestCnt) + ': ' + '### '+AIgnoreReason +' >>> '+s+LineEnding;
if FInTestBlockRes in [tbOk] then
FInTestBlockRes := tbUnexpected;
end
else begin
FUnexpectedSuccess:= FUnexpectedSuccess + IntToStr(FTestCnt) + ': ' + '### '+AIgnoreReason +' >>> '+s+LineEnding;
inc(FUnexpectedSuccessCnt);
end;
end
else
inc(FSucessCnt);
@ -257,12 +412,46 @@ begin
end;
procedure TDBGTestCase.AssertTestErrors;
function RemoveHexNumbers(txt: String): String;
var
i, j, n: Integer;
p, p2: SizeInt;
s: String;
begin
Result := txt;
i := 1;
j := 1;
n := 0;
p := PosEx('$', Result, i);
while p > 0 do begin
if p > n then j := 1;
n := PosSetEx([#10,#13], Result, p);
i := p+2;
p2 := p + 2;
while (p2 <= Length(Result)) and (Result[p2] in ['0'..'9', 'a'..'f', 'A'..'F']) do
inc(p2);
if p2 - p > 6 then begin
s := copy(Result, p, p2-p);
Result := StringReplace(Result, s, '$##HEX'+IntToStr(j)+'##', [rfReplaceAll, rfIgnoreCase]);
inc(j);
end;
p := PosEx('$', Result, i);
end;
end;
var
s, s1: String;
begin
s := FTestErrors;
s1 := Format('Failed: %d of %d - Ignored: %d Unexpected: %d - Success: %d',
s1 := Format('Failed: %4d of %5d - Ignored: %5d Unexpected: %4d - Success: %5d',
[FTestErrorCnt, FTestCnt, FIgnoredErrorCnt, FUnexpectedSuccessCnt, FSucessCnt ]);
FDirectParent.AddOverviewLog(Format('%-30s %14s %12s %7s %18s %s',
[TestName, Compiler.Name, SymbolTypeNames[Compiler.SymbolType],
CpuBitNames[Compiler.CpuBitType], Debugger.Name,
s1 + LineEnding]));
FTestErrors := '';
if GetLogActive or (FTestErrorCnt > 0) or (s <> '') then begin
LogError('***' + s1 + '***' +LineEnding);
@ -273,12 +462,27 @@ begin
LogError('================= Unexpected Success'+LineEnding);
LogError(FUnexpectedSuccess);
LogError('================='+LineEnding);
FIgnoredErrors := '';
FUnexpectedSuccess := '';
end;
if s <> '' then begin
if (TestControlGetWriteReport = wlAlways) or
( (TestControlGetWriteReport = wlOnError) and (
(FTestErrorCnt > 0) or (FIgnoredErrorCnt > 0) or (FUnexpectedSuccessCnt > 0)
))
then begin
CreateReport;
FReportFile.WriteLnToFile('***' + s1 + '***' +LineEnding);
FReportFile.WriteLnToFile('================= Failed:'+LineEnding);
FReportFile.WriteLnToFile(RemoveHexNumbers(s));
FReportFile.WriteLnToFile('================= Ignored'+LineEnding);
FReportFile.WriteLnToFile(RemoveHexNumbers(FIgnoredErrors));
FReportFile.WriteLnToFile('================= Unexpected Success'+LineEnding);
FReportFile.WriteLnToFile(RemoveHexNumbers(FUnexpectedSuccess));
FReportFile.WriteLnToFile('================='+LineEnding);
end;
FIgnoredErrors := '';
FUnexpectedSuccess := '';
if s <> '' then
Fail(s1+ LineEnding + s);
end;
end;
function TDBGTestCase.TestMatches(Expected, Got: string; ACaseSense: Boolean
@ -455,11 +659,11 @@ begin
Result := FLogFileName;
if (FTotalIgnoredErrorCnt + FIgnoredErrorCnt > 0)
then Result := Result + '.ignor_'+IntToStr(FTotalIgnoredErrorCnt + FIgnoredErrorCnt);
then Result := Result + '___ignor.'+IntToStr(FTotalIgnoredErrorCnt + FIgnoredErrorCnt);
if (FTotalUnexpectedSuccessCnt + FUnexpectedSuccessCnt > 0)
then Result := Result + '.unexp_'+IntToStr(FTotalUnexpectedSuccessCnt + FUnexpectedSuccessCnt);
then Result := Result + '___unexp.'+IntToStr(FTotalUnexpectedSuccessCnt + FUnexpectedSuccessCnt);
if (FTotalErrorCnt + FTestErrorCnt > 0)
then Result := Result + '.fail_'+IntToStr(FTotalErrorCnt + FTestErrorCnt);
then Result := Result + '___fail.'+IntToStr(FTotalErrorCnt + FTestErrorCnt);
end;
procedure TDBGTestCase.InitLog;
@ -509,6 +713,44 @@ begin
end;
end;
procedure TDBGTestCase.CreateReport;
var
name: String;
i: Integer;
dir: String;
begin
if FReportFileCreated then exit;
EnterCriticalsection(FLogLock);
try
if FReportFileCreated then exit;
name := GetLogFileName;
for i := 1 to length(name) do
if name[i] in ['/', '\', '*', '?', ':'] then
name[i] := '_';
if DirectoryExistsUTF8(TestControlGetLogPath) then
dir := TestControlGetLogPath
else
dir := GetCurrentDirUTF8;
FReportFileName := dir + name;
{$IFDEF Windows}
FReportFile := TLazLoggerFileHandleThreadSave.Create;
{$ELSE}
FReportFile := TLazLoggerFileHandleMainThread.Create;
{$ENDIF}
FReportFile.LogName := FReportFileName + '___fail.' + IntToStr(FTestErrorCnt) + '.report';
//AssignFile(FReportFile, FReportFileName + '.log.running');
//Rewrite(FReportFile);
FReportFileCreated := True;
finally
LeaveCriticalsection(FLogLock);
end;
end;
procedure TDBGTestCase.FinishLog;
var
NewName: String;
@ -521,6 +763,12 @@ begin
sleep(5);
RenameFileUTF8(FLogFileName + '.log.running', NewName + '.log');
end;
if FReportFileCreated then begin
CheckSynchronize(1);
FreeAndNil(FReportFile);
//CloseFile(FReportFile);
FReportFileCreated := False;
end;
FLogBufferText.Clear;
end;
@ -700,15 +948,9 @@ end;
{ TDBGTestsuite }
procedure TDBGTestsuite.Clear;
begin
//
end;
constructor TDBGTestsuite.Create(ACompiler: TTestDbgCompiler;
ADebugger: TTestDbgDebugger);
begin
FInRun := False;
FCompiler := ACompiler;
FDebugger := ADebugger;
inherited Create(ACompiler.FullName + ', ' + ADebugger.FullName);
@ -722,48 +964,33 @@ begin
AddTest(NewSuite);
end;
procedure TDBGTestsuite.Run(AResult: TTestResult);
begin
FInRun := True;
try
inherited Run(AResult);
finally
FInRun := False;
Clear;
end;
end;
var
MainTestSuite: TDbgBaseTestsuite;
procedure TDBGTestsuite.RunTest(ATest: TTest; AResult: TTestResult);
begin
try
inherited RunTest(ATest, AResult);
finally
if not FInRun then Clear;
end;
end;
procedure RegisterDbgTest(ATestClass: TTestCaseClass);
procedure RegisterDbgTest(ATestClass: TTestCaseClass; ASymTypes: TSymbolTypes);
var
Suite: TTestSuite;
i: Integer;
begin
Suite := GetTestRegistry;
//Suite := GetTestRegistry;
Suite := MainTestSuite;
for i := 0 to Suite.ChildTestCount - 1 do
if Suite.Test[i] is TDBGTestsuite then
TDBGTestsuite(Suite.Test[i]).RegisterDbgTest(ATestClass);
if (ASymTypes = []) or (TDBGTestsuite(Suite.Test[i]).Compiler.SymbolType in ASymTypes) then
TDBGTestsuite(Suite.Test[i]).RegisterDbgTest(ATestClass);
end;
procedure CreateTestSuites(ACompilerList: TTestDbgCompilerList;
ADebuggerList: TTestDbgDebuggerList; ATestSuiteClass: TDBGTestsuiteClass);
var
i, j: Integer;
r: TTestSuite;
begin
r := GetTestRegistry;
MainTestSuite := TDbgBaseTestsuite.Create;
GetTestRegistry.AddTest(MainTestSuite);
for i := 0 to ACompilerList.Count - 1 do
for j := 0 to ADebuggerList.Count - 1 do begin
if ADebuggerList[j].MatchesCompiler(ACompilerList[i]) then begin
r.AddTest(ATestSuiteClass.Create(ACompilerList[i], ADebuggerList[j]));
MainTestSuite.AddTest(ATestSuiteClass.Create(ACompilerList[i], ADebuggerList[j]));
end;
end;
end;