FpDebug, tests: More tests. Address-Of and typecast/convert

git-svn-id: trunk@61495 -
This commit is contained in:
martin 2019-06-30 19:16:51 +00:00
parent 29e1a3298f
commit 7da8446021
4 changed files with 368 additions and 114 deletions

View File

@ -14,16 +14,27 @@ type
{ TTestWatches }
TTestWatches = class(TDBGTestCase)
private
procedure RunToPause(var ABrk: TDBGBreakPoint);
published
procedure TestWatchesScope;
procedure TestWatchesValue;
procedure TestWatchesAddressOf;
procedure TestWatchesTypeCast;
end;
implementation
var
ControlTestWatch, ControlTestWatchScope, ControlTestWatchValue, ControlTestWatchAddressOf: Pointer;
ControlTestWatch, ControlTestWatchScope, ControlTestWatchValue,
ControlTestWatchAddressOf, ControlTestWatchTypeCast: Pointer;
procedure TTestWatches.RunToPause(var ABrk: TDBGBreakPoint);
begin
Debugger.RunToNextPause(dcRun);
AssertDebuggerState(dsPause);
ABrk.Enabled := False;
end;
procedure TTestWatches.TestWatchesScope;
@ -475,32 +486,28 @@ begin
(* ************ Nested Functions ************* *)
dbg.Run;
Debugger.WaitForFinishRun();
Debugger.RunToNextPause(dcRun);
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForFoo(t, 'Scope in FuncFooNestedTwice', 0);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun();
Debugger.RunToNextPause(dcRun);
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForFoo(t, 'Scope in FuncFooNestedTwice2', 0, True);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun();
Debugger.RunToNextPause(dcRun);
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForFoo(t, 'Scope in FuncFooNested', 1);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun();
Debugger.RunToNextPause(dcRun);
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForFoo(t, 'Scope in FuncFoo', 2);
@ -509,48 +516,42 @@ begin
(* ************ Class ************* *)
dbg.Run;
Debugger.WaitForFinishRun(); // MethodMainChildNestedTwice
Debugger.RunToNextPause(dcRun); // MethodMainChildNestedTwice
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in MethodMainChildNestedTwice', 0);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun(); // MethodMainChildNested
Debugger.RunToNextPause(dcRun); // MethodMainChildNested
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in MethodMainChildNested', 1);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun(); // MethodMainChild
Debugger.RunToNextPause(dcRun); // MethodMainChild
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in MethodMainChild', 2);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun(); // MethodMain
Debugger.RunToNextPause(dcRun); // MethodMain
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in MethodMain', 3);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun(); // MethodMainBase
Debugger.RunToNextPause(dcRun); // MethodMainBase
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in MethodMainBase', 4);
t.EvaluateWatches;
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun(); // MethodMainBaseBase
Debugger.RunToNextPause(dcRun); // MethodMainBaseBase
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in MethodMainBaseBase', 5);
@ -559,8 +560,7 @@ begin
(* ************ Program level ************* *)
dbg.Run;
Debugger.WaitForFinishRun();
Debugger.RunToNextPause(dcRun);
AssertDebuggerState(dsPause);
t.Clear;
AddWatchesForClassMethods(t, 'Scope in Prg', 6);
@ -840,7 +840,6 @@ end;
var
ExeName: String;
dbg: TDebuggerIntf;
t: TWatchExpectationList;
Src: TCommonSource;
BrkPrg, BrkFooBegin, BrkFoo, BrkFooVar, BrkFooVarBegin,
@ -854,7 +853,6 @@ begin
TestCompile(Src, ExeName);
AssertTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
dbg := Debugger.LazDebugger;
try
t := TWatchExpectationList.Create(Self);
@ -874,12 +872,7 @@ begin
(* ************ Nested Functions ************* *)
dbg.Run;
Debugger.WaitForFinishRun();
AssertDebuggerState(dsPause);
BrkPrg.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: Prg
RunToPause(BrkPrg);
t.Clear;
//t.Add( 'gvaString10[1]', weShortStr('Lbc1', 'ShortStr10'));
@ -907,12 +900,7 @@ begin
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun();
AssertDebuggerState(dsPause);
BrkFooBegin.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: FooBegin
RunToPause(BrkFooBegin);
t.Clear;
AddWatches(t, 'fooBegin local', 'fooloc', 002, 'C');
AddWatches(t, 'fooBegin args', 'arg', 001, 'B', tlParam);
@ -922,14 +910,9 @@ begin
//cl := Debugger.LazDebugger.GetLocation.SrcLine;
dbg.Run;
Debugger.WaitForFinishRun();
RunToPause(BrkFoo);
//// below might have been caused by the break on FooVarBegin, if there was no code.
//if (cl > 1) and (cl = Debugger.LazDebugger.GetLocation.SrcLine) then begin dbg.Run; Debugger.WaitForFinishRun(); end; // TODO: bug, stopping twice the same breakpoint
AssertDebuggerState(dsPause);
BrkFoo.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: Foo
t.Clear;
AddWatches(t, 'foo local', 'fooloc', 002, 'C');
AddWatches(t, 'foo args', 'arg', 001, 'B', tlParam);
@ -941,12 +924,7 @@ begin
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun();
AssertDebuggerState(dsPause);
BrkFooVarBegin.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: FooVarBegin
RunToPause(BrkFooVarBegin);
t.Clear;
AddWatches(t, 'foo var args', 'argvar', 001, 'B', tlParam);
t.EvaluateWatches;
@ -954,13 +932,7 @@ begin
// Registers are wrong in prologue.
dbg.Run;
Debugger.WaitForFinishRun();
//if (cl > 1) and (cl = Debugger.LazDebugger.GetLocation.SrcLine) then begin dbg.Run; Debugger.WaitForFinishRun(); end; // TODO: bug, stopping twice the same breakpoint
AssertDebuggerState(dsPause);
BrkFooVar.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: FooVar
RunToPause(BrkFooVar);
t.Clear;
AddWatches(t, 'foo var args', 'argvar', 001, 'B', tlParam);
AddWatches(t, 'foo var ArgMyClass1', 'ArgVarMyClass1.mc', 002, 'C');
@ -971,12 +943,7 @@ begin
t.CheckResults;
dbg.Run;
Debugger.WaitForFinishRun();
AssertDebuggerState(dsPause);
BrkFooConstRef.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: FooConstRef;
RunToPause(BrkFooConstRef);
t.Clear;
AddWatches(t, 'foo const ref args', 'argconstref', 001, 'B', tlParam);
t.EvaluateWatches;
@ -1233,7 +1200,6 @@ t.AddWithoutExpect(AName, p+'FiveDynArray'+e);
var
ExeName: String;
dbg: TDebuggerIntf;
t, tp: TWatchExpectationList;
Src: TCommonSource;
BrkPrg, BrkFoo, BrkFooVar, BrkFooConstRef: TDBGBreakPoint;
@ -1247,7 +1213,6 @@ begin
TestCompile(Src, ExeName);
AssertTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
dbg := Debugger.LazDebugger;
try
t := TWatchExpectationList.Create(Self);
@ -1261,12 +1226,7 @@ begin
(* ************ Nested Functions ************* *)
dbg.Run;
Debugger.WaitForFinishRun();
AssertDebuggerState(dsPause);
BrkPrg.Enabled := False;
TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// At BreakPoint: Prg
RunToPause(BrkPrg);
t.Clear;
AddWatches(t, 'glob const', '@gc', tlConst);
@ -1278,43 +1238,36 @@ begin
AddWatches(tp, 'glob var pointer', 'gvp_'); // pointer
CmpWatches(t, tp);
// TODO: field / field on nil object
RunToPause(BrkFoo);
t.Clear;
tp.Clear;
AddWatches(t, 'foo local', '@fooloc');
AddWatches(tp, 'foo local pointer', 'fooloc_pl_');
CmpWatches(t, tp);
t.Clear;
tp.Clear;
AddWatches(t, 'foo local', '@arg');
AddWatches(tp, 'foo local pointer', 'fooloc_pa_');
CmpWatches(t, tp);
RunToPause(BrkFooVar);
t.Clear;
tp.Clear;
AddWatches(t, 'foo var args', '@argvar', tlParam);
AddWatches(tp, 'foo var args pointer', 'fooloc_pv_');
CmpWatches(t, tp);
//RunToPause(BrkFooConstRef);
//t.Clear;
//AddWatches(t, 'foo const ref args', 'argconstref', tlParam);
//CmpWatches(t, tp);
// dbg.Run;
// Debugger.WaitForFinishRun();
// AssertDebuggerState(dsPause);
// BrkFoo.Enabled := False;
// TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// // At BreakPoint: Foo
// t.Clear;
// AddWatches(t, 'foo local', 'fooloc', 002, 'C');
// t.EvaluateWatches;
// //t.CheckResults;
//
//
// dbg.Run;
// Debugger.WaitForFinishRun();
// AssertDebuggerState(dsPause);
// BrkFooVar.Enabled := False;
// TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// // At BreakPoint: FooVar
// t.Clear;
// AddWatches(t, 'foo var args', 'argvar', 001, 'B', tlParam);
// AddWatches(t, 'foo var ArgMyBaseClass1', 'TMyClass(ArgVarMyClass2).mbc', 005, 'F');
// t.EvaluateWatches;
// //t.CheckResults;
//
//
// dbg.Run;
// Debugger.WaitForFinishRun();
// AssertDebuggerState(dsPause);
// BrkFooConstRef.Enabled := False;
// TestLogger.debugln(['line: ',Debugger.LazDebugger.GetLocation.SrcLine]);
// // At BreakPoint: FooConstRef;
// t.Clear;
// AddWatches(t, 'foo const ref args', 'argconstref', 001, 'B', tlParam);
// t.EvaluateWatches;
// //t.CheckResults;
//
finally
t.Free;
@ -1326,13 +1279,252 @@ begin
end;
end;
procedure TTestWatches.TestWatchesTypeCast;
type
TTestLoc = (tlAny, tlConst, tlParam, tlArrayWrap, tlPointer);
var
t2: TWatchExpectationList;
procedure AddWatchesConv(t: TWatchExpectationList; AName: String; APrefix: String; AOffs: Integer; AChr1: Char;
ALoc: TTestLoc = tlAny; APostFix: String = '');
function SignedIntAnd(AVal: Int64; AMask: Qword): Int64;
begin
Result := AVal and AMask;
if (Result and (AMask xor (AMask >> 1))) <> 0 then
Result := Result or (not AMask);
end;
const
UIntConvert: array[0..3] of record TypeName: String; Mask: qword; end = (
( TypeName: 'Byte'; Mask: $FF),
( TypeName: 'Word'; Mask: $FFFF),
( TypeName: 'LongWord'; Mask: $FFFFFFFF),
( TypeName: 'QWord'; Mask: qword($FFFFFFFFFFFFFFFF))
//( TypeName: 'Pointer'; Mask: ),
);
SIntConvert: array[0..3] of record TypeName: String; Mask: QWord; end = (
( TypeName: 'ShortInt'; Mask: $FF),
( TypeName: 'SmallInt'; Mask: $FFFF),
( TypeName: 'LongInt'; Mask: $FFFFFFFF),
( TypeName: 'Int64'; Mask: qword($FFFFFFFFFFFFFFFF))
);
var
p, e, tn: String;
i, n: Integer;
tm: QWord ;
begin
p := APrefix;
e := APostFix;
n := AOffs;
{$PUSH}{$Q-}{$R-}
for i := low(UIntConvert) to high(UIntConvert) do begin
tn := UIntConvert[i].TypeName;
tm := UIntConvert[i].Mask;
t.Add(AName+' '+tn, tn+'('+p+'Byte'+e+')', weCardinal(qword((1+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Word'+e+')', weCardinal(qword((100+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longword'+e+')', weCardinal(qword((1000+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'QWord'+e+')', weCardinal(qword((10000+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Shortint'+e+')', weCardinal(qword((50+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Smallint'+e+')', weCardinal(qword((500+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longint'+e+')', weCardinal(qword((5000+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Int64'+e+')', weCardinal(qword((50000+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'IntRange'+e+')', weCardinal(qword((-50+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'CardinalRange'+e+')', weCardinal(qword((50+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Byte_2'+e+')', weCardinal(qword((240+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Word_2'+e+')', weCardinal(qword((65501+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longword_2'+e+')', weCardinal(qword((4123456789+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'QWord_2'+e+')', weCardinal(qword((15446744073709551610+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Shortint_2'+e+')', weCardinal(qword((112+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Smallint_2'+e+')', weCardinal(qword((32012+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longint_2'+e+')', weCardinal(qword((20123456+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Int64_2'+e+')', weCardinal(qword((9123372036854775801+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Shortint_3'+e+')', weCardinal(qword((-112+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Smallint_3'+e+')', weCardinal(qword((-32012+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longint_3'+e+')', weCardinal(qword((-20123456+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Int64_3'+e+')', weCardinal(qword((-9123372036854775801+n) and tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Char'+e+')', weCardinal(ord(AChr1), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Char2'+e+')', weCardinal(ord(#0), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Char3'+e+')', weCardinal(ord(' '), tn, -1));
end;
for i := low(SIntConvert) to high(SIntConvert) do begin
tn := SIntConvert[i].TypeName;
tm := SIntConvert[i].Mask;
t.Add(AName+' '+tn, tn+'('+p+'Byte'+e+')', weInteger(SignedIntAnd(1+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Word'+e+')', weInteger(SignedIntAnd(100+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longword'+e+')', weInteger(SignedIntAnd(1000+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'QWord'+e+')', weInteger(SignedIntAnd(10000+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Shortint'+e+')', weInteger(SignedIntAnd(50+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Smallint'+e+')', weInteger(SignedIntAnd(500+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longint'+e+')', weInteger(SignedIntAnd(5000+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Int64'+e+')', weInteger(SignedIntAnd(50000+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'IntRange'+e+')', weInteger(SignedIntAnd(-50+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'CardinalRange'+e+')', weInteger(SignedIntAnd(50+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Byte_2'+e+')', weInteger(SignedIntAnd(240+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Word_2'+e+')', weInteger(SignedIntAnd(65501+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longword_2'+e+')', weInteger(SignedIntAnd(4123456789+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'QWord_2'+e+')', weInteger(SignedIntAnd(15446744073709551610+n, tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Shortint_2'+e+')', weInteger(SignedIntAnd(112+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Smallint_2'+e+')', weInteger(SignedIntAnd(32012+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longint_2'+e+')', weInteger(SignedIntAnd(20123456+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Int64_2'+e+')', weInteger(SignedIntAnd(9123372036854775801+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Shortint_3'+e+')', weInteger(SignedIntAnd(-112+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Smallint_3'+e+')', weInteger(SignedIntAnd(-32012+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Longint_3'+e+')', weInteger(SignedIntAnd(-20123456+n , tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Int64_3'+e+')', weInteger(SignedIntAnd(-9123372036854775801+n, tm), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Char'+e+')', weInteger(ord(AChr1), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Char2'+e+')', weInteger(ord(#0), tn, -1));
t.Add(AName+' '+tn, tn+'('+p+'Char3'+e+')', weInteger(ord(' '), tn, -1));
end;
{$POP}
t.Add(AName+' Char', 'Char('+p+'Byte'+e+')', weChar(Chr(1+n), 'Char'));
t.Add(AName+' Char', 'Char('+p+'FiveRec'+e+')', weMatch('.', skSimple)).ExpectError();
end;
procedure AddWatchesCast(t: TWatchExpectationList; AName: String; APrefix: String; AOffs: Integer; AChr1: Char;
ALoc: TTestLoc = tlAny; APostFix: String = '');
var
p, e, val: String;
Thread: Integer;
begin
p := APrefix;
e := APostFix;
t2.Clear;
if not(ALoc in [tlConst]) then begin
t2.AddWithoutExpect(AName, p+'Instance1_Int'+e);
t2.AddWithoutExpect(AName, p+'Ansi5_Int'+e);
t2.AddWithoutExpect(AName, p+'IntDynArray4_Int'+e);
t2.EvaluateWatches;
Thread := Debugger.Threads.Threads.CurrentThreadId;
val := t2.Tests[0]^.TstWatch.Values[Thread, 0].Value;
t.Add(AName+' Int', 'PtrUInt('+p+'Instance1'+e+')', weCardinal(StrToQWordDef(val, qword(-7)), 'PtrUInt', -1));
t.Add(AName+' TClass1', 'TClass1('+p+'Instance1_Int'+e+')', weMatch('FAnsi *=[ $0-9A-F()]*'''+AChr1+'T', skClass));
t.Add(AName+' TClass1', 'TClass1('+val+')', weMatch('FAnsi *=[ $0-9A-F()]*'''+AChr1+'T', skClass));
val := t2.Tests[1]^.TstWatch.Values[Thread, 0].Value;
t.Add(AName+' Ansi', 'PtrUInt('+p+'Ansi5'+e+')', weCardinal(StrToQWordDef(val, qword(-7)), 'PtrUInt', -1));
if not(Compiler.SymbolType in stDwarf3Up) then begin
t.Add(AName+' AnsiString', 'AnsiString('+p+'Ansi5_Int'+e+')',
weAnsiStr(AChr1+'bcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij')
).IgnKindPtr(stDwarf2) .IgnKind(stDwarf3Up);
t.Add(AName+' AnsiString', 'AnsiString('+val+')',
weAnsiStr(AChr1+'bcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij')
).IgnKindPtr(stDwarf2) .IgnKind(stDwarf3Up);
end;
val := t2.Tests[2]^.TstWatch.Values[Thread, 0].Value;
t.Add(AName+' DynArray', 'PtrUInt('+p+'IntDynArray4'+e+')', weCardinal(StrToQWordDef(val, qword(-7)), 'PtrUInt', -1));
if not(Compiler.SymbolType in stDwarf3Up) then begin
t.Add(AName, 'TIntDynArray('+p+'IntDynArray4_Int'+e+')', weDynArray(weInteger([12, 30+AOffs, 60]), 'TIntDynArray'));
t.Add(AName, 'TIntDynArray('+val+')', weDynArray(weInteger([12, 30+AOffs, 60]), 'TIntDynArray'));
end;
end;
t.Add(AName+' Cardinal', 'Cardinal('+p+'Rec3S'+e+')', weMatch('.', skSimple)).ExpectError();
t.Add(AName+' QWord', 'QWord('+p+'Rec3S'+e+')', weMatch('.', skSimple)).ExpectError();
t.Add(AName+' QWord', 'TRecord3QWord('+p+'Rec3S'+e+')', weMatch('a *=.*18446744073709551594.*b *=.*44.*c *= .', skRecord));
end;
var
ExeName: String;
t: TWatchExpectationList;
Src: TCommonSource;
BrkPrg, BrkFoo, BrkFooVar, BrkFooConstRef: TDBGBreakPoint;
begin
if SkipTest then exit;
if not TestControlCanTest(ControlTestWatchTypeCast) then exit;
t := nil;
t2 := nil;
Src := GetCommonSourceFor('WatchesValuePrg.Pas');
TestCompile(Src, ExeName);
AssertTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
try
t := TWatchExpectationList.Create(Self);
t2 := TWatchExpectationList.Create(Self);
t.AcceptSkSimple := [skInteger, skCardinal, skBoolean, skChar, skFloat, skString, skAnsiString, skCurrency, skVariant, skWideString];
t.AddTypeNameAlias('integer', 'integer|longint');
t.AddTypeNameAlias('ShortStr255', 'ShortStr255|ShortString');
t.AddTypeNameAlias('TEnumSub', 'TEnum|TEnumSub');
BrkPrg := Debugger.SetBreakPoint(Src, 'Prg');
BrkFoo := Debugger.SetBreakPoint(Src, 'Foo');
BrkFooVar := Debugger.SetBreakPoint(Src, 'FooVar');
BrkFooConstRef := Debugger.SetBreakPoint(Src, 'FooConstRef');
AssertDebuggerNotInErrorState;
(* ************ Nested Functions ************* *)
RunToPause(BrkPrg);
t.Clear;
AddWatchesConv(t, 'glob const', 'gc', 000, 'A', tlConst);
AddWatchesConv(t, 'glob var', 'gv', 001, 'B');
AddWatchesCast(t, 'glob const', 'gc', 000, 'A', tlConst);
AddWatchesCast(t, 'glob var', 'gv', 001, 'B');
AddWatchesCast(t, 'glob MyClass1', 'MyClass1.mc', 002, 'C');
AddWatchesCast(t, 'glob MyBaseClass1', 'MyClass1.mbc', 003, 'D');
AddWatchesCast(t, 'glob MyClass1', 'TMyClass(MyClass2).mc', 004, 'E');
AddWatchesCast(t, 'glob MyBaseClass1', 'TMyClass(MyClass2).mbc', 005, 'F');
AddWatchesCast(t, 'glob var dyn array of [0]', 'gva', 005, 'K', tlArrayWrap, '[0]' );
AddWatchesCast(t, 'glob var dyn array of [1]', 'gva', 006, 'L', tlArrayWrap, '[1]');
AddWatchesCast(t, 'glob var pointer', 'gvp_', 001, 'B', tlPointer, '^'); // pointer
t.EvaluateWatches;
t.CheckResults;
RunToPause(BrkFoo);
t.Clear;
AddWatchesCast(t, 'foo local', 'fooloc', 002, 'C');
t.EvaluateWatches;
t.CheckResults;
RunToPause(BrkFooVar);
t.Clear;
AddWatchesCast(t, 'foo var args', 'argvar', 001, 'B', tlParam);
AddWatchesCast(t, 'foo var ArgMyBaseClass1', 'TMyClass(ArgVarMyClass2).mbc', 005, 'F');
t.EvaluateWatches;
t.CheckResults;
RunToPause(BrkFooConstRef);
t.Clear;
AddWatchesCast(t, 'foo const ref args', 'argconstref', 001, 'B', tlParam);
t.EvaluateWatches;
t.CheckResults;
finally
t.Free;
t2.Free;
Debugger.ClearDebuggerMonitors;
Debugger.FreeDebugger;
AssertTestErrors;
end;
end;
initialization
RegisterDbgTest(TTestWatches);
ControlTestWatch := TestControlRegisterTest('TTestWatch');
ControlTestWatchScope := TestControlRegisterTest('Scope', ControlTestWatch);
ControlTestWatchValue := TestControlRegisterTest('Value', ControlTestWatch);
ControlTestWatchAddressOf := TestControlRegisterTest('AddressOf', ControlTestWatch);
ControlTestWatch := TestControlRegisterTest('TTestWatch');
ControlTestWatchScope := TestControlRegisterTest('Scope', ControlTestWatch);
ControlTestWatchValue := TestControlRegisterTest('Value', ControlTestWatch);
ControlTestWatchAddressOf := TestControlRegisterTest('AddressOf', ControlTestWatch);
ControlTestWatchTypeCast := TestControlRegisterTest('TypeCast', ControlTestWatch);
end.

View File

@ -11,8 +11,17 @@ program WatchesValuePrg;
uses sysutils, Classes;
type
{$ifdef CPU64}
PtrUInt = type QWord;
{$endif CPU64}
{$ifdef CPU32}
PtrUInt = type DWord;
{$endif CPU32}
var
BreakDummy: Integer;
BreakDummy: PtrUInt;
type
TIntRange = -300..300;
@ -56,6 +65,9 @@ type
TRecordFive = record a:longint; b: byte end;
TRecordFivePack = packed record a:longint; b: byte end;
TRecord3Int64 = record a,b,c: Int64; end;
TRecord3QWord = record a,b,c: QWord; end;
TFiveDynArray = array of record a:longint; b: byte end;
TFiveDynArrayPack = packed array of record a:longint; b: byte end;
TFivePackDynArray = array of packed record a:longint; b: byte end;
@ -74,6 +86,13 @@ type
TRecFivePackStatArray = array [2..4] of TRecordFivePack;
TRecFivePackStatPackArray = packed array [2..4] of TRecordFivePack;
TClass1 = class
public
FInt: integer;
FDynInt: TIntDynArray;
FAnsi: AnsiString;
end;
TEnum = (EnVal1, EnVal2, EnVal3, EnVal4);
TEnumSub = EnVal1..EnVal2;
TEnum2 = (EnVal21= 3, EnVal22=4, EnVal23=7, EnVal24=10, EnVal25=30);
@ -121,10 +140,21 @@ procedure Foo(
var
(* LOCATION: local var *)
TEST_PREPOCESS(WatchesValuePrgIdent.inc, pre__=fooloc, _OP_=:, (=;//, _O2_=:, _EQ_=, _BLOCK_=TestVar )
(* LOCATION: local var pointer <each type> FOR locals *)
TEST_PREPOCESS(WatchesValuePrgIdent.inc, pre__=fooloc_pl_, "_OP_=: ^", (=;//, "_O2_=: ^", _EQ_=, _BLOCK_=TestVar, _BLOCK2_=TestPointer )
(* LOCATION: local var pointer <each type> FOR args *)
TEST_PREPOCESS(WatchesValuePrgIdent.inc, pre__=fooloc_pa_, "_OP_=: ^", (=;//, "_O2_=: ^", _EQ_=, _BLOCK_=TestVar, _BLOCK2_=TestPointer )
//TODO MyClass
begin // TEST_BREAKPOINT=FooBegin
BreakDummy:= 1;
TEST_PREPOCESS(WatchesValuePrgIdent.inc,pre__=fooloc, ADD=2, CHR1='C', _OP_=:=, _O2_={, _EQ_=}:=, _pre2_=gc, _BLOCK_=TestAssign)
(* INIT: local var pointer <each type> *)
TEST_PREPOCESS(WatchesValuePrgIdent.inc,pre__=fooloc_pl_, _OP_={, _O2_={, _pre3_=@fooloc, "//@@=} :=", _BLOCK_=TestVar, _BLOCK2_=TestPointer) //}
TEST_PREPOCESS(WatchesValuePrgIdent.inc,pre__=fooloc_pa_, _OP_={, _O2_={, _pre3_=@arg, "//@@=} :=", _BLOCK_=TestVar, _BLOCK2_=TestPointer) //}
BreakDummy:= 1; // TEST_BREAKPOINT=Foo
end;
@ -136,7 +166,13 @@ procedure FooVar(
ArgVarMyClass2: TMyBaseClass;
Dummy: Integer
);
var
(* LOCATION: var params pointer <each type> FOR args *)
TEST_PREPOCESS(WatchesValuePrgIdent.inc, pre__=fooloc_pv_, "_OP_=: ^", (=;//, "_O2_=: ^", _EQ_=, _BLOCK_=TestVar, _BLOCK2_=TestPointer )
begin // TEST_BREAKPOINT=FooVarBegin
(* INIT: local var pointer <each type> *)
TEST_PREPOCESS(WatchesValuePrgIdent.inc,pre__=fooloc_pv_, _OP_={, _O2_={, _pre3_=@argvar, "//@@=} :=", _BLOCK_=TestVar, _BLOCK2_=TestPointer) //}
BreakDummy:= 1;
BreakDummy:= 1; // TEST_BREAKPOINT=FooVar
end;

View File

@ -60,6 +60,11 @@
pre__Ansi4{e} _OP_ TStrA (CHR1+'A'#0'B'#9'b'#10#13); //@@ _pre3_Ansi4;
pre__Ansi5{e} _OP_ AnsiString (CHR1+'bcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij'); //@@ _pre3_Ansi5;
pre__Ansi5_Int{e} _O2_ PtrUInt _EQ_ (0); //@@ _pre3_Ansi5_Int;
{$IFDEF TestAssign}
pre__Ansi5_Int{e} _OP_ PtrUInt(pre__Ansi5{e}); //@@ //}}
{$ENDIF}
pre__PChar{e} _OP_ PChar ( nil ); //@@ _pre3_PChar;
pre__PChar2{e} _OP_ TPChr ( nil ); //@@ _pre3_PChar2;
{$IFDEF TestAssign}
@ -124,6 +129,8 @@
pre__IntDynArray5{e} _OP_ TIntDynArray ( nil ); //@@ _pre3_IntDynArray5; // REAL CONST = nil
pre__IntDynArray4_Int{e} _O2_ PtrUInt _EQ_ (0); //@@ _pre3_IntDynArray4_Int;
{$IFnDEF TestPointer}
pre__AnsiDynArray{e} _O2_ array of AnsiString _EQ_ (nil); //@@ _pre3_AnsiDynArray; // open array if used as function arg;
pre__AnsiDynArray2{e} _O2_ array of AnsiString _EQ_ (nil); //@@ _pre3_AnsiDynArray2; // len = 3 // open array if used as function arg;
@ -184,6 +191,8 @@
pre__IntDynArray4{e}[1] _OP_ 30+ADD; //@@
pre__IntDynArray4{e}[2] _OP_ 60; //@@
pre__IntDynArray4_Int{e} _OP_ PtrUInt(pre__IntDynArray4{e}); //@@ //}}
SetLength(pre__AnsiDynArray2 {e}, 3); pre__AnsiDynArray2{e}[0] _OP_ 'N123'; //@@ // }
pre__AnsiDynArray2{e}[1] _OP_ CHR1+'ab'; //@@
pre__AnsiDynArray2{e}[2] _OP_ 'M'#9; //@@
@ -321,9 +330,23 @@
{$IFnDEF TestAssign}
pre__FiveRec{e} _O2_ TRecordFive _EQ_ (a:-22-ADD;b:44); //@@ _pre3_FiveRec;
pre__FiveRec{e} _O2_ TRecordFive _EQ_ (a:-22-ADD;b:44); //@@ _pre3_FiveRec;
pre__Rec3S{e} _O2_ TRecord3Int64 _EQ_ (a:-22;b:44;c:1000+ADD); //@@ _pre3_Rec3S;
pre__Rec3U{e} _O2_ TRecord3QWord _EQ_ (a:111;b:44;c:1000+ADD); //@@ _pre3_Rec3U;
{$ELSE}
pre__FiveRec{e} := _pre2_FiveRec; pre__FiveRec{e}.a := -22-ADD; //@@ _pre3_FiveRec; // }}
pre__FiveRec{e} := _pre2_FiveRec; pre__FiveRec{e}.a := -22-ADD; //@@ _pre3_FiveRec; // }}}
pre__Rec3S{e} := _pre2_Rec3S; pre__Rec3S{e}.c := 1000+ADD; //@@ _pre3_Rec3S; // }}}
pre__Rec3U{e} := _pre2_Rec3U; pre__Rec3U{e}.c := 1000+ADD; //@@ _pre3_Rec3U; // }}}
{$ENDIF}
pre__Instance1{e} _O2_ TClass1 _EQ_ (nil); //@@ _pre3_Instance1;
pre__Instance1_Int{e} _O2_ PtrUInt _EQ_ (0); //@@ _pre3_Instance1_Int;
{$IFDEF TestAssign}
pre__Instance1{e} := TClass1.Create; //@@
pre__Instance1{e}.FInt _OP_ 22+ADD; //@@
pre__Instance1{e}.FAnsi _OP_ CHR1+'T'; //@@
pre__Instance1_Int{e} _OP_ PtrUInt(pre__Instance1{e}); //@@ //}}
{$ENDIF}

View File

@ -414,7 +414,10 @@ begin
exit;
end;
Result := WaitForFinishRun(ATimeOut, AWaitForInternal);
with LazDebugger.GetLocation do DebugLnExit('<<< RunToNextPause Ending at %s %d @ %x %s', [SrcFile, SrcLine, Address, dbgs(LazDebugger.State)]);
with LazDebugger.GetLocation do begin
DebugLnExit('<<< RunToNextPause Ending at %s %d @ %x %s', [SrcFile, SrcLine, Address, dbgs(LazDebugger.State)]);
TestLogger.DebugLn('at %s %d @ %x %s', [SrcFile, SrcLine, Address, dbgs(LazDebugger.State)]);
end;
end;
function TTestDbgDebugger.WaitForFinishRun(ATimeOut: Integer;