mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-02 14:39:45 +01:00
FpDebug: fix array with struct / tests
git-svn-id: trunk@44531 -
This commit is contained in:
parent
fc89c8dc99
commit
b9283584dc
@ -823,6 +823,7 @@ type
|
||||
FDataAddressDone: Boolean;
|
||||
protected
|
||||
procedure Reset; override;
|
||||
procedure ClearMembers;
|
||||
function GetFieldFlags: TFpDbgValueFieldFlags; override;
|
||||
function GetKind: TDbgSymbolKind; override;
|
||||
function GetAsCardinal: QWord; override;
|
||||
@ -2565,6 +2566,16 @@ procedure TFpDbgDwarfValueStructTypeCast.Reset;
|
||||
begin
|
||||
inherited Reset;
|
||||
FDataAddressDone := False;
|
||||
ClearMembers;
|
||||
end;
|
||||
|
||||
procedure TFpDbgDwarfValueStructTypeCast.ClearMembers;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if FMembers <> nil then
|
||||
for i := 0 to FMembers.Count - 1 do
|
||||
TDbgDwarfValueIdentifier(FMembers[i]).StructureValueInfo := nil;
|
||||
end;
|
||||
|
||||
function TFpDbgDwarfValueStructTypeCast.GetFieldFlags: TFpDbgValueFieldFlags;
|
||||
@ -2679,12 +2690,8 @@ begin
|
||||
end;
|
||||
|
||||
destructor TFpDbgDwarfValueStructTypeCast.Destroy;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if FMembers <> nil then
|
||||
for i := 0 to FMembers.Count - 1 do
|
||||
TDbgDwarfValueIdentifier(FMembers[i]).StructureValueInfo := nil;
|
||||
ClearMembers;
|
||||
FreeAndNil(FMembers);
|
||||
inherited Destroy;
|
||||
end;
|
||||
@ -2717,6 +2724,7 @@ begin
|
||||
if not HasTypeCastInfo then
|
||||
exit;
|
||||
|
||||
// TODO: Why store them all in list? They are hold by the type
|
||||
tmp := FTypeCastTargetType.Member[AIndex];
|
||||
if (tmp <> nil) then begin
|
||||
assert((tmp is TDbgDwarfValueIdentifier), 'TDbgDwarfStructTypeCastSymbolValue.GetMemberByName'+DbgSName(tmp));
|
||||
@ -2857,6 +2865,9 @@ end;
|
||||
|
||||
procedure TFpDbgDwarfValue.SetStructureValue(AValue: TFpDbgDwarfValue);
|
||||
begin
|
||||
if FStructureValue <> nil then
|
||||
Reset;
|
||||
|
||||
if FStructureValue = AValue then
|
||||
exit;
|
||||
|
||||
|
||||
@ -1,11 +1,78 @@
|
||||
unit TestWatchesUnitArray;
|
||||
{$mode objfpc}{$H+}{$NOTES off}
|
||||
|
||||
interface
|
||||
|
||||
uses sysutils, types;
|
||||
|
||||
procedure Test1;
|
||||
type
|
||||
TArrayClass1 = class;
|
||||
TArrayRec = packed record
|
||||
FieldInt1, FieldInt2: Integer;
|
||||
FieldDynInt1: array of Integer;
|
||||
FieldStatInt1: array [4..9] of Integer;
|
||||
FieldByte1: Byte;
|
||||
end;
|
||||
|
||||
implementation
|
||||
TArrayDynInt = array of Integer;
|
||||
TArrayDynClass = array of TArrayClass1;
|
||||
TArrayDynRec = array of TArrayRec;
|
||||
|
||||
TArrayDynDynInt = array of array of Integer;
|
||||
TArrayDynDynClass = array of array of TArrayClass1;
|
||||
TArrayDynDynRec = array of array of TArrayRec;
|
||||
|
||||
TArrayDynStatInt = array of array [1..5] of Integer;
|
||||
TArrayDynStatClass = array of array [1..5] of TArrayClass1;
|
||||
TArrayDynStatRec = array of array [1..5] of TArrayRec;
|
||||
|
||||
TArrayStatInt = array [-2..5] of Integer;
|
||||
TArrayStatClass = array [-2..5] of TArrayClass1;
|
||||
TArrayStatRec = array [-2..5] of TArrayRec;
|
||||
|
||||
TArrayStatStatInt = array [-9..-5] of array [1..5] of Integer;
|
||||
TArrayStatStatClass = array [-9..-5] of array [1..5] of TArrayClass1;
|
||||
TArrayStatStatRec = array [-9..-5] of array [1..5] of TArrayRec;
|
||||
|
||||
TArrayStatDynInt = array [-9..-5] of array of Integer;
|
||||
TArrayStatDynClass = array [-9..-5] of array of TArrayClass1;
|
||||
TArrayStatDynRec = array [-9..-5] of array of TArrayRec;
|
||||
|
||||
|
||||
{ TArrayClass1 }
|
||||
|
||||
TArrayClass1 = class
|
||||
public
|
||||
FieldInt1, FieldInt2: Integer;
|
||||
FieldDynAInt1: array of Integer;
|
||||
FieldStatAInt1: array [4..9] of Integer;
|
||||
|
||||
FieldDynInt1: TArrayDynInt;
|
||||
FieldDynClass1: TArrayDynClass;
|
||||
FieldDynRec1: TArrayDynRec;
|
||||
|
||||
FieldDynDynInt1: TArrayDynDynInt;
|
||||
FieldDynDynClass1: TArrayDynDynClass;
|
||||
FieldDynDynRec1: TArrayDynDynRec;
|
||||
|
||||
FieldDynStatInt1: TArrayDynStatInt;
|
||||
FieldDynStatClass1: TArrayDynStatClass;
|
||||
FieldDynStatRec1: TArrayDynStatRec;
|
||||
|
||||
FieldStatInt1: TArrayStatInt;
|
||||
FieldStatClass1: TArrayStatClass;
|
||||
FieldStatRec1: TArrayStatRec;
|
||||
|
||||
FieldStatStatInt1: TArrayStatStatInt;
|
||||
FieldStatStatClass1: TArrayStatStatClass;
|
||||
FieldStatStatRec1: TArrayStatStatRec;
|
||||
|
||||
FieldStatDynInt1: TArrayStatDynInt;
|
||||
FieldStatDynClass1: TArrayStatDynClass;
|
||||
FieldStatDynRec1: TArrayStatDynRec;
|
||||
|
||||
procedure Test1Method;
|
||||
end;
|
||||
|
||||
var
|
||||
ArrayGlob_DynInt1, ArrayGlob_DynInt2: array of Integer;
|
||||
@ -13,6 +80,12 @@ var
|
||||
ArrayGlob_StatInt2: array [-4..9] of Integer;
|
||||
|
||||
procedure Test1;
|
||||
|
||||
implementation
|
||||
|
||||
{ TArrayClass1 }
|
||||
|
||||
procedure TArrayClass1.Test1Method;
|
||||
begin
|
||||
ArrayGlob_DynInt2 := nil;
|
||||
|
||||
@ -37,8 +110,78 @@ begin
|
||||
ArrayGlob_StatInt2[1] := 3305;
|
||||
|
||||
|
||||
ArrayGlob_DynInt1[9] := -5511; // BREAK
|
||||
SetLength(FieldDynInt1, 5);
|
||||
FieldDynInt1[0] := 100;
|
||||
FieldDynInt1[1] := 101;
|
||||
FieldDynInt1[2] := 102;
|
||||
|
||||
SetLength(FieldDynClass1, 6);
|
||||
FieldDynClass1[0] := TArrayClass1.Create;
|
||||
FieldDynClass1[0].FieldInt1 := 98700;
|
||||
FieldDynClass1[0].FieldInt2 := 98701;
|
||||
SetLength(FieldDynClass1[0].FieldDynAInt1, 2);
|
||||
FieldDynClass1[0].FieldDynAInt1[0] := 9900;
|
||||
FieldDynClass1[0].FieldDynAInt1[1] := 9901;
|
||||
FieldDynClass1[1] := TArrayClass1.Create;
|
||||
FieldDynClass1[1].FieldInt1 := 88700;
|
||||
FieldDynClass1[1].FieldInt2 := 88701;
|
||||
SetLength(FieldDynClass1[1].FieldDynAInt1, 2);
|
||||
FieldDynClass1[1].FieldDynAInt1[0] := 8900;
|
||||
FieldDynClass1[1].FieldDynAInt1[1] := 8901;
|
||||
FieldDynClass1[2] := TArrayClass1.Create;
|
||||
FieldDynClass1[2].FieldInt1 := 78700;
|
||||
FieldDynClass1[2].FieldInt2 := 78701;
|
||||
SetLength(FieldDynClass1[2].FieldDynAInt1, 3);
|
||||
FieldDynClass1[2].FieldDynAInt1[0] := 7900;
|
||||
FieldDynClass1[2].FieldDynAInt1[1] := 7901;
|
||||
FieldDynClass1[2].FieldDynAInt1[2] := 7902;
|
||||
|
||||
SetLength(FieldDynRec1, 7);
|
||||
FieldDynRec1[0].FieldInt1 := 200;
|
||||
FieldDynRec1[0].FieldInt2 := 201;
|
||||
FieldDynRec1[1].FieldInt1 := 210;
|
||||
FieldDynRec1[1].FieldInt2 := 211;
|
||||
FieldDynRec1[2].FieldInt1 := 220;
|
||||
FieldDynRec1[2].FieldInt2 := 221;
|
||||
|
||||
SetLength(FieldDynDynInt1, 5,3);
|
||||
FieldDynDynInt1[0][0] := 1000;
|
||||
FieldDynDynInt1[0][1] := 1001;
|
||||
FieldDynDynInt1[0][2] := 1002;
|
||||
FieldDynDynInt1[0][3] := 1003;
|
||||
FieldDynDynInt1[1][0] := 1010;
|
||||
FieldDynDynInt1[1][1] := 1011;
|
||||
|
||||
SetLength(FieldDynDynClass1, 5,4);
|
||||
SetLength(FieldDynDynRec1, 5,6);
|
||||
|
||||
SetLength(FieldDynStatInt1, 3);
|
||||
SetLength(FieldDynStatClass1, 4);
|
||||
SetLength(FieldDynStatRec1, 5);
|
||||
|
||||
//SetLength(FieldStatInt1, );
|
||||
//SetLength(FieldStatClass1, );
|
||||
//SetLength(FieldStatRec1, );
|
||||
|
||||
//SetLength(FieldStatStatInt1, );
|
||||
//SetLength(FieldStatStatClass1, );
|
||||
//SetLength(FieldStatStatRec1, );
|
||||
|
||||
SetLength(FieldStatDynInt1[-9], 3);
|
||||
SetLength(FieldStatDynClass1[-9], 3);
|
||||
SetLength(FieldStatDynRec1[-9], 3);
|
||||
|
||||
|
||||
|
||||
ArrayGlob_DynInt1[9] := -5511; // BREAK
|
||||
end;
|
||||
|
||||
procedure Test1;
|
||||
var
|
||||
ArrayClass1: TArrayClass1;
|
||||
begin
|
||||
ArrayClass1 := TArrayClass1.Create;
|
||||
ArrayClass1.Test1Method;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
unit TestWatchesUnitSimple;
|
||||
{$mode objfpc}{$H+}{$NOTES off}
|
||||
|
||||
interface
|
||||
uses sysutils, types;
|
||||
@ -167,7 +168,10 @@ begin
|
||||
SimpleGlob_QWord4 := high(QWord);
|
||||
SimpleGlob_QWord5 := low(QWord);
|
||||
|
||||
|
||||
SimpleGlob_Single1 := 99.2;
|
||||
SimpleGlob_Double1 := 199.3;
|
||||
SimpleGlob_Ext1 := 299.4;
|
||||
SimpleGlob_Comp1 := -2;
|
||||
|
||||
|
||||
SimplePArg_Int1 := @SimpleArg_Int1;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
unit TestWatchesUnitStruct;
|
||||
{$mode objfpc}{$H+}{$NOTES off}
|
||||
|
||||
interface
|
||||
uses sysutils, types;
|
||||
|
||||
@ -10,11 +10,11 @@ uses
|
||||
GDBMIDebugger;
|
||||
|
||||
const
|
||||
BREAK_LINE_TestWatchesUnitSimple_1 = 178;
|
||||
BREAK_LINE_TestWatchesUnitSimple_2 = 185;
|
||||
BREAK_LINE_TestWatchesUnitSimple_3 = 192;
|
||||
BREAK_LINE_TestWatchesUnitSimple_1 = 182;
|
||||
BREAK_LINE_TestWatchesUnitSimple_2 = 189;
|
||||
BREAK_LINE_TestWatchesUnitSimple_3 = 196;
|
||||
|
||||
BREAK_LINE_TestWatchesUnitArray = 38;
|
||||
BREAK_LINE_TestWatchesUnitArray = 176;
|
||||
|
||||
type
|
||||
|
||||
@ -25,11 +25,6 @@ type
|
||||
FWatches: TWatches;
|
||||
|
||||
ExpectBreakSimple_1: TWatchExpectationArray;
|
||||
FSimplePArg_Int1, FAddrSimpleArg_Int1,
|
||||
FSimplePVArg_Int1, FAddrSimpleVArg_Int1,
|
||||
FSimplePLocal_Int1, FAddrSimpleLocal_Int1,
|
||||
FSimplePGlob_Int1, FAddrSimpleGlob_Int1: PWatchExpectation;
|
||||
|
||||
ExpectBreakSimple_2: TWatchExpectationArray;
|
||||
ExpectBreakSimple_3: TWatchExpectationArray;
|
||||
|
||||
@ -54,6 +49,8 @@ type
|
||||
function AddSimpleInt(AnExpr: string; AMtch: Int64; ATpNm: string): PWatchExpectation;
|
||||
function AddSimpleUInt(AnExpr: string; AMtch: QWord; ATpNm: string): PWatchExpectation;
|
||||
|
||||
procedure AdjustExpectToAddress(AWatchExp: PWatchExpectation);
|
||||
|
||||
procedure AddExpectSimple_1;
|
||||
procedure AddExpectSimple_2;
|
||||
procedure AddExpectSimple_3;
|
||||
@ -109,10 +106,22 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
{ TTestWatches }
|
||||
|
||||
procedure TTestWatches.AdjustExpectToAddress(AWatchExp: PWatchExpectation);
|
||||
var
|
||||
OtherWatchExp: PWatchExpectation;
|
||||
s: String;
|
||||
st: TSymbolType;
|
||||
begin
|
||||
OtherWatchExp := PWatchExpectation(AWatchExp^.UserData);
|
||||
if OtherWatchExp = nil then exit;;
|
||||
s := OtherWatchExp^.TheWatch.Values[1,0].Value;
|
||||
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
|
||||
for st := low(TSymbolType) to high(TSymbolType) do
|
||||
AWatchExp^.Result[st].ExpMatch := '\'+s;
|
||||
end;
|
||||
|
||||
procedure TTestWatches.DoDbgOutput(Sender: TObject; const AText: String);
|
||||
begin
|
||||
inherited DoDbgOutput(Sender, AText);
|
||||
@ -178,9 +187,11 @@ var
|
||||
i: Integer;
|
||||
s, s2, s2def: String;
|
||||
j: Integer;
|
||||
r: PWatchExpectation;
|
||||
begin
|
||||
FCurrentExpect := @ExpectBreakSimple_1;
|
||||
|
||||
{%region Int?Cardinal types}
|
||||
for i := 0 to 3 do begin
|
||||
s2def := '';
|
||||
case i of
|
||||
@ -338,26 +349,34 @@ begin
|
||||
AddSimpleInt(Format(s, ['SimpleField_Word1']), j+16, 'Word');
|
||||
AddSimpleInt(Format(s, ['SimpleField_DWord1']), j+17, 'LongWord');
|
||||
AddSimpleInt(Format(s, ['SimpleField_QWord1']), j+18, 'QWord');
|
||||
|
||||
//AddSimpleInt(Format(s, ['SimpleField_Single1']), 15, 'Byte');
|
||||
//AddSimpleInt(Format(s, ['SimpleField_Double1']), 15, 'Byte');
|
||||
//AddSimpleInt(Format(s, ['SimpleField_Ext1']), 15, 'Byte');
|
||||
end;
|
||||
{%region}
|
||||
|
||||
s := '%s';
|
||||
AddFmtDef(Format(s, ['SimpleGlob_Single1']), '^99\.(2|19)', skSimple, '', [fTpMtch]);
|
||||
AddFmtDef(Format(s, ['SimpleGlob_Double1']), '^199\.(3|29)', skSimple, '', [fTpMtch]);
|
||||
AddFmtDef(Format(s, ['SimpleGlob_Ext1']), '^299\.(4|39)', skSimple, '', [fTpMtch]);
|
||||
AddSimpleInt(Format(s, ['SimpleGlob_Comp1']), -2, '');
|
||||
|
||||
{%region AddressOf / Var param, hidden pointer}
|
||||
//SimplePArg_Int1, SimplePVArg_Int1, SimplePLocal_Int1, SimplePGlob_Int1: PLongInt;
|
||||
FSimplePArg_Int1 := AddFmtDef('SimplePArg_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
FAddrSimpleArg_Int1 := AddFmtDef('@SimpleArg_Int1', 'replaceme', skPointer, '');
|
||||
r := AddFmtDef('@SimpleArg_Int1', 'replaceme', skPointer, '');
|
||||
r^.OnBeforeTest := @AdjustExpectToAddress;
|
||||
r^.UserData := AddFmtDef('SimplePArg_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
|
||||
FSimplePVArg_Int1 := AddFmtDef('SimplePVArg_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
FAddrSimpleVArg_Int1 := AddFmtDef('@SimpleVArg_Int1', 'replaceme', skPointer, '');
|
||||
UpdResMinFpc(FAddrSimpleVArg_Int1, stSymAll, 020600);
|
||||
r := AddFmtDef('@SimpleVArg_Int1', 'replaceme', skPointer, '');
|
||||
r^.OnBeforeTest := @AdjustExpectToAddress;
|
||||
r^.UserData := AddFmtDef('SimplePVArg_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
UpdResMinFpc(r, stSymAll, 020600);
|
||||
|
||||
FSimplePLocal_Int1 := AddFmtDef('SimplePLocal_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
FAddrSimpleLocal_Int1 := AddFmtDef('@SimpleLocal_Int1', 'replaceme', skPointer, '');
|
||||
r := AddFmtDef('@SimpleLocal_Int1', 'replaceme', skPointer, '');
|
||||
r^.OnBeforeTest := @AdjustExpectToAddress;
|
||||
r^.UserData := AddFmtDef('SimplePLocal_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
|
||||
r := AddFmtDef('@SimpleGlob_Int1', 'replaceme', skPointer, '');
|
||||
r^.OnBeforeTest := @AdjustExpectToAddress;
|
||||
r^.UserData := AddFmtDef('SimplePGlob_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
|
||||
FSimplePGlob_Int1 := AddFmtDef('SimplePGlob_Int1', '\$[0-9A-F]', skPointer, '');
|
||||
FAddrSimpleGlob_Int1 := AddFmtDef('@SimpleGlob_Int1', 'replaceme', skPointer, '');
|
||||
{%region}
|
||||
|
||||
end;
|
||||
@ -437,6 +456,7 @@ begin
|
||||
AddSimpleInt('ArrayGlob_DynInt1[0]', 5511, M_Int);
|
||||
AddSimpleInt('ArrayGlob_DynInt1[19]', 5500, M_Int);
|
||||
|
||||
|
||||
AddFmtDef('ArrayGlob_StatInt1', '^[\(L].*6600, 6601, 6602',
|
||||
skArray, '', [fTpMtch]);
|
||||
AddSimpleInt('ArrayGlob_StatInt1[4]', 6600, M_Int);
|
||||
@ -445,27 +465,43 @@ begin
|
||||
AddFmtDef('ArrayGlob_StatInt1[10]', '', skSimple, M_Int, [fTpMtch]); // Just do not crash
|
||||
AddFmtDef('ArrayGlob_StatInt1[-1]', '', skSimple, M_Int, [fTpMtch]); // Just do not crash
|
||||
|
||||
|
||||
AddFmtDef('ArrayGlob_StatInt2', '^[\(L].*3300, 3301, 3302',
|
||||
skArray, '', [fTpMtch]);
|
||||
AddSimpleInt('ArrayGlob_StatInt2[-4]', 3300, M_Int);
|
||||
AddSimpleInt('ArrayGlob_StatInt2[0]', 3304, M_Int);
|
||||
|
||||
|
||||
// EMPTY dyn array = nil
|
||||
AddFmtDef('FieldDynInt1', '^[\(L].*100, 101, 102', skArray, '', [fTpMtch]);
|
||||
|
||||
|
||||
AddFmtDef('FieldDynClass1', '^[\(L].*?'+
|
||||
'\(.*FIELDINT1 = 98700;.*FIELDINT2 = 98701;.*FIELDDYNAINT1 = \(9900, 9901\);.*\), ' +
|
||||
'\(.*FIELDINT1 = 88700;.*FIELDINT2 = 88701;.*FIELDDYNAINT1 = \(8900, 8901\);.*\), ' +
|
||||
'\(.*FIELDINT1 = 78700;.*FIELDINT2 = 78701;.*FIELDDYNAINT1 = \(7900, 7901, 7902\);.*\)',
|
||||
skArray, '', [fTpMtch]);
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestWatches.RunTestWatches(NamePreFix: String; TestExeName, ExtraOpts: String;
|
||||
UsedUnits: array of TUsesDir);
|
||||
|
||||
var
|
||||
dbg: TGDBMIDebugger;
|
||||
Only: Integer;
|
||||
OnlyName, OnlyNamePart: String;
|
||||
|
||||
procedure SetBreak(AFileName: String; ALineNum: Integer);
|
||||
begin
|
||||
with dbg.BreakPoints.Add(AFileName, ALineNum) do begin
|
||||
InitialEnabled := True;
|
||||
Enabled := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
WListSimple1, WListSimple2, WListSimple3,
|
||||
WListArray1: TTestWatchArray;
|
||||
st: TSymbolType;
|
||||
s: String;
|
||||
|
||||
@ -497,30 +533,18 @@ begin
|
||||
dbg := StartGDB(AppDir, TestExeName);
|
||||
FWatches := Watches.Watches;
|
||||
|
||||
with dbg.BreakPoints.Add('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_1) do begin
|
||||
InitialEnabled := True;
|
||||
Enabled := True;
|
||||
end;
|
||||
with dbg.BreakPoints.Add('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_2) do begin
|
||||
InitialEnabled := True;
|
||||
Enabled := True;
|
||||
end;
|
||||
with dbg.BreakPoints.Add('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_3) do begin
|
||||
InitialEnabled := True;
|
||||
Enabled := True;
|
||||
end;
|
||||
with dbg.BreakPoints.Add('TestWatchesUnitArray.pas', BREAK_LINE_TestWatchesUnitArray) do begin
|
||||
InitialEnabled := True;
|
||||
Enabled := True;
|
||||
end;
|
||||
SetBreak('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_1);
|
||||
SetBreak('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_2);
|
||||
SetBreak('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_3);
|
||||
SetBreak('TestWatchesUnitArray.pas', BREAK_LINE_TestWatchesUnitArray);
|
||||
|
||||
if dbg.State = dsError then
|
||||
Fail(' Failed Init');
|
||||
|
||||
AddWatches(ExpectBreakSimple_1, WListSimple1, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSimple_2, WListSimple2, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSimple_3, WListSimple3, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakArray_1, WListArray1, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSimple_1, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSimple_2, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSimple_3, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakArray_1, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
(* Start debugging *)
|
||||
dbg.ShowConsole := True;
|
||||
@ -531,45 +555,25 @@ begin
|
||||
TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple_1', False);
|
||||
exit;
|
||||
end;
|
||||
|
||||
(* Hit first breakpoint: *)
|
||||
for st := low(TSymbolType) to high(TSymbolType) do begin
|
||||
s := FSimplePArg_Int1^.TheWatch.Values[1,0].Value;
|
||||
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
|
||||
FAddrSimpleArg_Int1^.Result[st].ExpMatch := '\'+s;
|
||||
|
||||
s := FSimplePVArg_Int1^.TheWatch.Values[1,0].Value;
|
||||
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
|
||||
FAddrSimpleVArg_Int1^.Result[st].ExpMatch := '\'+s;
|
||||
|
||||
s := FSimplePGlob_Int1^.TheWatch.Values[1,0].Value;
|
||||
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
|
||||
FAddrSimpleGlob_Int1^.Result[st].ExpMatch := '\'+s;
|
||||
|
||||
s := FSimplePLocal_Int1^.TheWatch.Values[1,0].Value;
|
||||
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
|
||||
FAddrSimpleLocal_Int1^.Result[st].ExpMatch := '\'+s;
|
||||
end;
|
||||
TestWatchList('Simple1',ExpectBreakSimple_1, WListSimple1, dbg, Only, OnlyName, OnlyNamePart);
|
||||
TestWatchList('Simple1',ExpectBreakSimple_1, dbg, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
|
||||
dbg.Run;
|
||||
if not TestTrue('State=Pause', dbg.State = dsPause) then begin
|
||||
if not TestTrue('State=Pause', dbg.State = dsPause) then begin
|
||||
TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple', False);
|
||||
exit;
|
||||
end;
|
||||
|
||||
(* Hit 2nd Simple breakpoint: *)
|
||||
TestWatchList('Simple2',ExpectBreakSimple_2, WListSimple2, dbg, Only, OnlyName, OnlyNamePart);
|
||||
TestWatchList('Simple2',ExpectBreakSimple_2, dbg, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
dbg.Run;
|
||||
if not TestTrue('State=Pause', dbg.State = dsPause) then begin
|
||||
if not TestTrue('State=Pause', dbg.State = dsPause) then begin
|
||||
TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple', False);
|
||||
exit;
|
||||
end;
|
||||
|
||||
(* Hit 3rd Simlpe breakpoint: *)
|
||||
TestWatchList('Simple3',ExpectBreakSimple_3, WListSimple3, dbg, Only, OnlyName, OnlyNamePart);
|
||||
TestWatchList('Simple3',ExpectBreakSimple_3, dbg, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
|
||||
// array
|
||||
@ -582,7 +586,7 @@ begin
|
||||
end;
|
||||
|
||||
(* Hit 11st Array breakpoint: *)
|
||||
TestWatchList('Array1',ExpectBreakArray_1, WListArray1, dbg, Only, OnlyName, OnlyNamePart);
|
||||
TestWatchList('Array1',ExpectBreakArray_1, dbg, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
dbg.Run;
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ begin
|
||||
{$ENDIF}
|
||||
FpcBuild.ShowWindow := swoHIDE;
|
||||
|
||||
CmdLine := FpcExe + ' -MObjFPC -FUlib -o'+ ExeName + ' ' + FpcOpts + ' ' + PrgName;
|
||||
CmdLine := FpcExe + ' -B -MObjFPC -FUlib -o'+ ExeName + ' ' + FpcOpts + ' ' + PrgName;
|
||||
debugln(['**** running compiler: ', CmdLine]);
|
||||
FpcBuild.CommandLine := CmdLine;
|
||||
FCommandLine := CmdLine;
|
||||
|
||||
@ -85,6 +85,8 @@ const
|
||||
WatchExpFlagSIgnTpName = [IgnStabs, IgnDwrf, IgnDwrf2, IgnDwrf2IfNoSet, IgnDwrf3, IgnTpName, IgnTpNameDw, IgnTpNameDw2, IgnTpNameDw3, IgnTpNameSt];
|
||||
|
||||
type
|
||||
PWatchExpectation= ^TWatchExpectation;
|
||||
TWatchExpectOnBeforeTest = procedure(AWatchExp: PWatchExpectation) of object;
|
||||
|
||||
TFullTypeMemberExpectationResult = record
|
||||
Name: string;
|
||||
@ -94,7 +96,6 @@ type
|
||||
end;
|
||||
TFullTypeMemberExpectationResultArray = array of TFullTypeMemberExpectationResult;
|
||||
|
||||
PWatchExpectation= ^TWatchExpectation;
|
||||
TWatchExpectationResult = record
|
||||
ExpMatch: string;
|
||||
ExpKind: TDBGSymbolKind;
|
||||
@ -111,22 +112,23 @@ type
|
||||
EvaluateFlags: TDBGEvaluateFlags;
|
||||
StackFrame: Integer;
|
||||
Result: Array [TSymbolType] of TWatchExpectationResult;
|
||||
|
||||
TheWatch: TTestWatch;
|
||||
UserData: Pointer;
|
||||
OnBeforeTest: TWatchExpectOnBeforeTest;
|
||||
end;
|
||||
TWatchExpectationArray = array of TWatchExpectation;
|
||||
|
||||
TTestWatchArray = Array of TTestWatch;
|
||||
|
||||
{ TTestWatchesBase }
|
||||
|
||||
TTestWatchesBase = class(TGDBTestCase)
|
||||
protected
|
||||
procedure TestWatch(Name: String; ADbg: TDebuggerIntf;
|
||||
AWatch: TTestWatch; Data: TWatchExpectation; WatchValue: String = '');
|
||||
procedure AddWatches(ExpectList: TWatchExpectationArray; var WatchList: TTestWatchArray;
|
||||
procedure AddWatches(ExpectList: TWatchExpectationArray;
|
||||
AWatches: TWatches;
|
||||
Only: Integer; OnlyName, OnlyNamePart: String);
|
||||
procedure TestWatchList(AName: String; ExpectList: TWatchExpectationArray; WatchList: TTestWatchArray;
|
||||
procedure TestWatchList(AName: String; ExpectList: TWatchExpectationArray;
|
||||
ADbg: TDebuggerIntf;
|
||||
Only: Integer; OnlyName, OnlyNamePart: String);
|
||||
end;
|
||||
@ -398,6 +400,8 @@ var
|
||||
|
||||
begin
|
||||
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];
|
||||
@ -513,9 +517,8 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray;
|
||||
var WatchList: TTestWatchArray; AWatches: TWatches; Only: Integer; OnlyName,
|
||||
OnlyNamePart: String);
|
||||
procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray; AWatches: TWatches;
|
||||
Only: Integer; OnlyName, OnlyNamePart: String);
|
||||
|
||||
function SkipTest(const Data: TWatchExpectation): Boolean;
|
||||
begin
|
||||
@ -535,22 +538,20 @@ procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
SetLength(WatchList, length(ExpectList));
|
||||
for i := low(ExpectList) to high(ExpectList) do begin
|
||||
if not MatchOnly(ExpectList[i], i) then continue;
|
||||
if not SkipTest(ExpectList[i]) then begin
|
||||
WatchList[i] := TTestWatch.Create(AWatches);
|
||||
WatchList[i].Expression := ExpectList[i].Expression;
|
||||
WatchList[i].DisplayFormat := ExpectList[i].DspFormat;
|
||||
WatchList[i].EvaluateFlags:= ExpectList[i].EvaluateFlags;
|
||||
WatchList[i].enabled := True;
|
||||
ExpectList[i].TheWatch := WatchList[i];
|
||||
ExpectList[i].TheWatch := TTestWatch.Create(AWatches);
|
||||
ExpectList[i].TheWatch.Expression := ExpectList[i].Expression;
|
||||
ExpectList[i].TheWatch.DisplayFormat := ExpectList[i].DspFormat;
|
||||
ExpectList[i].TheWatch.EvaluateFlags:= ExpectList[i].EvaluateFlags;
|
||||
ExpectList[i].TheWatch.enabled := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestWatchesBase.TestWatchList(AName: String; ExpectList: TWatchExpectationArray;
|
||||
WatchList: TTestWatchArray; ADbg: TDebuggerIntf; Only: Integer; OnlyName,
|
||||
ADbg: TDebuggerIntf; Only: Integer; OnlyName,
|
||||
OnlyNamePart: String);
|
||||
|
||||
function SkipTest(const Data: TWatchExpectation): Boolean;
|
||||
@ -574,7 +575,7 @@ begin
|
||||
for i := low(ExpectList) to high(ExpectList) do begin
|
||||
if not MatchOnly(ExpectList[i], i) then continue;
|
||||
if not SkipTest(ExpectList[i]) then
|
||||
TestWatch(AName + ' '+IntToStr(i)+' ', ADbg, WatchList[i], ExpectList[i]);
|
||||
TestWatch(AName + ' '+IntToStr(i)+' ', ADbg, ExpectList[i].TheWatch, ExpectList[i]);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
@ -1688,7 +1688,6 @@ var
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
WList, WListSub, WListArray: Array of TTestWatch;
|
||||
|
||||
begin
|
||||
TestBaseName := NamePreFix;
|
||||
@ -1735,9 +1734,9 @@ begin
|
||||
Fail(' Failed Init');
|
||||
|
||||
(* Create all watches *)
|
||||
AddWatches(ExpectBreakFoo, WList, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSubFoo, WListSub, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakFooArray, WListArray, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakFoo, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakSubFoo, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
AddWatches(ExpectBreakFooArray, FWatches, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
(* Start debugging *)
|
||||
dbg.ShowConsole := True;
|
||||
@ -1747,7 +1746,7 @@ begin
|
||||
then begin
|
||||
(* Hit first breakpoint: BREAK_LINE_FOOFUNC_NEST SubFoo -- (1st loop) Called with none nil data *)
|
||||
|
||||
TestWatchList('Brk1', ExpectBreakSubFoo, WListSub, dbg, Only, OnlyName, OnlyNamePart);
|
||||
TestWatchList('Brk1', ExpectBreakSubFoo, dbg, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
dbg.Run;
|
||||
end
|
||||
@ -1771,7 +1770,7 @@ begin
|
||||
for i := low(ExpectBreakFoo) to high(ExpectBreakFoo) do begin
|
||||
if not MatchOnly(ExpectBreakFoo[i], i) then continue;
|
||||
if not SkipTest(ExpectBreakFoo[i]) then
|
||||
TestWatch('Brk2 '+IntToStr(i)+' ', dbg, WList[i], ExpectBreakFoo[i]);
|
||||
TestWatch('Brk2 '+IntToStr(i)+' ', dbg, ExpectBreakFoo[i].TheWatch, ExpectBreakFoo[i]);
|
||||
end;
|
||||
|
||||
dbg.Run;
|
||||
@ -1782,7 +1781,7 @@ begin
|
||||
then begin
|
||||
(* Hit 2nd breakpoint: BREAK_LINE_FOOFUNC_ARRAY SubFoo_Watches -- (1st loop) Called with none nil data *)
|
||||
|
||||
TestWatchList('Brk3', ExpectBreakFooArray, WListArray, dbg, Only, OnlyName, OnlyNamePart);
|
||||
TestWatchList('Brk3', ExpectBreakFooArray, dbg, Only, OnlyName, OnlyNamePart);
|
||||
|
||||
dbg.Run;
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user