mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-24 04:59:43 +01:00
FpDebug: tests for step over
git-svn-id: trunk@61879 -
This commit is contained in:
parent
c5fe550fbe
commit
1c5491c441
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -2630,9 +2630,12 @@ components/lazdebuggers/lazdebuggerfp/test/LazDebFpTest.lpi svneol=native#text/p
|
|||||||
components/lazdebuggers/lazdebuggerfp/test/LazDebFpTest.lpr svneol=native#text/plain
|
components/lazdebuggers/lazdebuggerfp/test/LazDebFpTest.lpr svneol=native#text/plain
|
||||||
components/lazdebuggers/lazdebuggerfp/test/fpclist.txt.sample svneol=native#text/plain
|
components/lazdebuggers/lazdebuggerfp/test/fpclist.txt.sample svneol=native#text/plain
|
||||||
components/lazdebuggers/lazdebuggerfp/test/testapps/BreakPointPrg.pas svneol=native#text/pascal
|
components/lazdebuggers/lazdebuggerfp/test/testapps/BreakPointPrg.pas svneol=native#text/pascal
|
||||||
|
components/lazdebuggers/lazdebuggerfp/test/testapps/BreakPointThread2Prg.pas svneol=native#text/pascal
|
||||||
components/lazdebuggers/lazdebuggerfp/test/testapps/BreakPointThreadPrg.pas svneol=native#text/pascal
|
components/lazdebuggers/lazdebuggerfp/test/testapps/BreakPointThreadPrg.pas svneol=native#text/pascal
|
||||||
|
components/lazdebuggers/lazdebuggerfp/test/testapps/StepOverPrg.pas svneol=native#text/pascal
|
||||||
components/lazdebuggers/lazdebuggerfp/test/testbase.pas svneol=native#text/pascal
|
components/lazdebuggers/lazdebuggerfp/test/testbase.pas svneol=native#text/pascal
|
||||||
components/lazdebuggers/lazdebuggerfp/test/testbreakpoint.pas svneol=native#text/pascal
|
components/lazdebuggers/lazdebuggerfp/test/testbreakpoint.pas svneol=native#text/pascal
|
||||||
|
components/lazdebuggers/lazdebuggerfp/test/teststepping.pas svneol=native#text/pascal
|
||||||
components/lazdebuggers/lazdebuggerfp/test/testvarious.pas svneol=native#text/pascal
|
components/lazdebuggers/lazdebuggerfp/test/testvarious.pas svneol=native#text/pascal
|
||||||
components/lazdebuggers/lazdebuggerfp/test/testwatches.pas svneol=native#text/pascal
|
components/lazdebuggers/lazdebuggerfp/test/testwatches.pas svneol=native#text/pascal
|
||||||
components/lazdebuggers/lazdebuggerfpdserver/fpdserverdebugger.pas svneol=native#text/plain
|
components/lazdebuggers/lazdebuggerfpdserver/fpdserverdebugger.pas svneol=native#text/plain
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
<PackageName Value="FCL"/>
|
<PackageName Value="FCL"/>
|
||||||
</Item5>
|
</Item5>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="5">
|
<Units Count="6">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
<Filename Value="LazDebFpTest.lpr"/>
|
<Filename Value="LazDebFpTest.lpr"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
@ -66,6 +66,11 @@
|
|||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
<UnitName Value="TestBreakPoint"/>
|
<UnitName Value="TestBreakPoint"/>
|
||||||
</Unit4>
|
</Unit4>
|
||||||
|
<Unit5>
|
||||||
|
<Filename Value="teststepping.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="TestStepping"/>
|
||||||
|
</Unit5>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ uses
|
|||||||
cthreads,
|
cthreads,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
TestDbgControlForm, Interfaces, Forms, GuiTestRunner, TestVarious,
|
TestDbgControlForm, Interfaces, Forms, GuiTestRunner, TestVarious,
|
||||||
TestWatches, TestBase, TestBreakPoint;
|
TestWatches, TestBase, TestBreakPoint, TestStepping;
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,102 @@
|
|||||||
|
program BreakPointThread2Prg;
|
||||||
|
{$asmMode intel}
|
||||||
|
uses
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
cthreads,
|
||||||
|
{$ENDIF}
|
||||||
|
sysutils, Classes;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TTestThread }
|
||||||
|
|
||||||
|
TTestThread = class(TThread)
|
||||||
|
procedure Execute; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TTestThread2 }
|
||||||
|
|
||||||
|
TTestThread2 = class(TThread)
|
||||||
|
procedure Execute; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
T1, x, BreakDummy: Integer;
|
||||||
|
|
||||||
|
label
|
||||||
|
testasmlbl1;
|
||||||
|
|
||||||
|
{ TTestThread }
|
||||||
|
|
||||||
|
procedure TTestThread.Execute;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
t: array [0..5] of TTestThread2;
|
||||||
|
begin
|
||||||
|
for i := 0 to high(t) do
|
||||||
|
t[i] := TTestThread2.Create(False);
|
||||||
|
InterLockedIncrement(T1);
|
||||||
|
while not Terminated do
|
||||||
|
for i := 0 to high(t) do begin
|
||||||
|
t[i].WaitFor;
|
||||||
|
t[i].Free;
|
||||||
|
t[i] := TTestThread2.Create(False);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TTestThread2 }
|
||||||
|
|
||||||
|
procedure TTestThread2.Execute;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
TTestThread.Create(False);
|
||||||
|
TTestThread.Create(False);
|
||||||
|
TTestThread.Create(False);
|
||||||
|
TTestThread.Create(False);
|
||||||
|
TTestThread.Create(False);
|
||||||
|
while InterLockedExchangeAdd(T1, 0) < 4 do
|
||||||
|
sleep(10);
|
||||||
|
|
||||||
|
BreakDummy := 1;
|
||||||
|
|
||||||
|
asm
|
||||||
|
nop // TEST_BREAKPOINT=BrkMainBegin
|
||||||
|
xor eax, eax
|
||||||
|
xor ebx, ebx
|
||||||
|
add eax, 20
|
||||||
|
testasmlbl1:
|
||||||
|
sub eax, 20
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain0
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain1
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain2
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain3
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain4
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain5
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain6
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain7
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain8
|
||||||
|
add eax, 1
|
||||||
|
add eax, 1 // TEST_BREAKPOINT=BrkMain9
|
||||||
|
add eax, 1
|
||||||
|
|
||||||
|
add ebx, 1
|
||||||
|
jmp testasmlbl1
|
||||||
|
|
||||||
|
nop
|
||||||
|
nop // TEST_BREAKPOINT=BrkMainEnd
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
program StepOverPrg;
|
||||||
|
{$asmMode intel}
|
||||||
|
uses
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
cthreads,
|
||||||
|
{$ENDIF}
|
||||||
|
sysutils, Classes;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TTestThread1 }
|
||||||
|
|
||||||
|
TTestThread1 = class(TThread)
|
||||||
|
procedure Execute; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
x, BreakDummy: Integer;
|
||||||
|
T1, T1Interfere: Integer;
|
||||||
|
T1Stop: Boolean;
|
||||||
|
|
||||||
|
|
||||||
|
label
|
||||||
|
testasmlbl1, testasmlbl2;
|
||||||
|
|
||||||
|
Procedure MyNorm;
|
||||||
|
begin
|
||||||
|
x := 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure MySleep;
|
||||||
|
begin
|
||||||
|
Sleep(50);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure MyBrkDis;
|
||||||
|
begin
|
||||||
|
x := 1; // TEST_BREAKPOINT=BrkDisabled
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure MyBrkHitCnt;
|
||||||
|
begin
|
||||||
|
x := 1; // TEST_BREAKPOINT=BrkHitCnt
|
||||||
|
end;
|
||||||
|
|
||||||
|
(* Try to step over a line, while another thread is also going through the line *)
|
||||||
|
Procedure MyInterfereByThread(a: Boolean = false);
|
||||||
|
Procedure MyInterfereSleep;
|
||||||
|
begin
|
||||||
|
if a then Sleep(10); // threads do not stop / while the test waits here, other threads should hit the calling line
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
if a then
|
||||||
|
x := 1; // TEST_BREAKPOINT=BrkInterfereByThread
|
||||||
|
if a then InterLockedExchange(T1Interfere, 0); while (InterLockedExchangeAdd(T1Interfere,0)=0) do begin MyInterfereSleep; if not a then break; end;
|
||||||
|
x := 1; // TEST_BREAKPOINT=AfterInterfereByThread
|
||||||
|
|
||||||
|
InterLockedIncrement(T1Interfere); // Other threads will increment
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TTestThread1 }
|
||||||
|
|
||||||
|
procedure TTestThread1.Execute;
|
||||||
|
begin
|
||||||
|
InterLockedIncrement(T1);
|
||||||
|
while not (Terminated or T1Stop) do MyInterfereByThread;
|
||||||
|
InterLockedDecrement(T1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
x := 1;
|
||||||
|
x := x + 1; // TEST_BREAKPOINT=BrkStart
|
||||||
|
x := x + 1; x := x + 2; x := x + 3; // TEST_BREAKPOINT=AfterStep
|
||||||
|
MyNorm(); // TEST_BREAKPOINT=AfterStepLongLine
|
||||||
|
x := 1; MyNorm(); x := x + 1; MyNorm(); x := x + 1; MyNorm(); x := x + 1; // TEST_BREAKPOINT=AfterStepProc
|
||||||
|
MySleep(); // TEST_BREAKPOINT=AfterStepProcLong
|
||||||
|
sleep(50); // TEST_BREAKPOINT=AfterStepSleepProc
|
||||||
|
MyBrkDis; // TEST_BREAKPOINT=AfterStepSleep
|
||||||
|
MyBrkHitCnt; // TEST_BREAKPOINT=AfterStepBrkDis
|
||||||
|
x := 1; // TEST_BREAKPOINT=AfterStepBrkHitCnt
|
||||||
|
x := 1;
|
||||||
|
|
||||||
|
|
||||||
|
T1 := 0;
|
||||||
|
T1Stop := False;
|
||||||
|
TTestThread1.Create(False); while not (InterLockedExchangeAdd(T1,0)=1) do x:=1; // TEST_BREAKPOINT=BrkThreadCreateInStep
|
||||||
|
x := 1; // TEST_BREAKPOINT=AfterThreadCreateInStep
|
||||||
|
|
||||||
|
(* Prepare for threads to interfare with the hidden breakpoint *)
|
||||||
|
// create a few threads to interfer
|
||||||
|
TTestThread1.Create(False); TTestThread1.Create(False); TTestThread1.Create(False);
|
||||||
|
TTestThread1.Create(False); TTestThread1.Create(False); TTestThread1.Create(False);
|
||||||
|
while not (InterLockedExchangeAdd(T1,0)>=5) do sleep(10); // at least 5 running
|
||||||
|
|
||||||
|
MyInterfereByThread(True);
|
||||||
|
T1Stop := True;
|
||||||
|
|
||||||
|
while not (InterLockedExchangeAdd(T1,0)<=1) do x:=1; // TEST_BREAKPOINT=BrkThreadExitInStep
|
||||||
|
x := 1; // TEST_BREAKPOINT=AfterThreadExitInStep
|
||||||
|
|
||||||
|
//sleep(500);
|
||||||
|
BreakDummy := 1;
|
||||||
|
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
@ -69,16 +69,23 @@ type
|
|||||||
// check that each brk point hit was reported (one per thread)
|
// check that each brk point hit was reported (one per thread)
|
||||||
procedure TestBreakThreadsHitBreak;
|
procedure TestBreakThreadsHitBreak;
|
||||||
|
|
||||||
(* TODO: All breakpoint-hits must be reported. Hits happening together with an event
|
(* Only ONE thread running the breakpoints. Plenty of events from other
|
||||||
in another thread must still be reported.
|
threads (including thread-exit).
|
||||||
|
Hit each breakpoint in order, WITHOUT ever re-hitting the last brk.
|
||||||
|
*HOPE* is that some events will happen while the main thread single steps
|
||||||
|
over a temp-removed break, and the single step has NOT yet moved.
|
||||||
|
So the single step will still need the brk to be tmp-removed when it
|
||||||
|
continues.
|
||||||
*)
|
*)
|
||||||
|
procedure TestBreakThreadsIgnoreOther;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
var
|
var
|
||||||
ControlTest, ControlTestBreak, ControlTestThreadNoSkip,
|
ControlTest, ControlTestBreak, ControlTestThreadNoSkip,
|
||||||
ControlTestThreadMove1, ControlTestThreadMove2, ControlTestThreadHit: Pointer;
|
ControlTestThreadMove1, ControlTestThreadMove2, ControlTestThreadHit,
|
||||||
|
ControlTestThreadIgnoreOther: Pointer;
|
||||||
|
|
||||||
procedure TTestBreakPoint.TestLocation(ATestName, ABrkName: String;
|
procedure TTestBreakPoint.TestLocation(ATestName, ABrkName: String;
|
||||||
ABreakHitCount: Integer);
|
ABreakHitCount: Integer);
|
||||||
@ -746,7 +753,7 @@ var
|
|||||||
MainBrk, Brk1, Brk2, Brk3, Brk4, Brk5: TDBGBreakPoint;
|
MainBrk, Brk1, Brk2, Brk3, Brk4, Brk5: TDBGBreakPoint;
|
||||||
begin
|
begin
|
||||||
if SkipTest then exit;
|
if SkipTest then exit;
|
||||||
if not TestControlCanTest(ControlTestThreadMove2) then exit;
|
if not TestControlCanTest(ControlTestThreadHit) then exit;
|
||||||
Src := GetCommonSourceFor(AppDir + 'BreakPointThreadPrg.pas');
|
Src := GetCommonSourceFor(AppDir + 'BreakPointThreadPrg.pas');
|
||||||
TestCompile(Src, ExeName);
|
TestCompile(Src, ExeName);
|
||||||
|
|
||||||
@ -804,15 +811,68 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestBreakPoint.TestBreakThreadsIgnoreOther;
|
||||||
|
var
|
||||||
|
ExeName: String;
|
||||||
|
i, j, ThreadIdMain: Integer;
|
||||||
|
Brk: array [0..9] of TDBGBreakPoint;
|
||||||
|
begin
|
||||||
|
if SkipTest then exit;
|
||||||
|
if not TestControlCanTest(ControlTestThreadIgnoreOther) then exit;
|
||||||
|
Src := GetCommonSourceFor(AppDir + 'BreakPointThread2Prg.pas');
|
||||||
|
TestCompile(Src, ExeName);
|
||||||
|
|
||||||
|
TestTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
|
||||||
|
dbg := Debugger.LazDebugger;
|
||||||
|
|
||||||
|
try
|
||||||
|
Debugger.SetBreakPoint(Src, 'BrkMainBegin');
|
||||||
|
for i := 0 to 9 do
|
||||||
|
Brk[i] := Debugger.SetBreakPoint(Src, 'BrkMain'+IntToStr(i));
|
||||||
|
AssertDebuggerNotInErrorState;
|
||||||
|
Debugger.RunToNextPause(dcRun);
|
||||||
|
AssertDebuggerState(dsPause, 'main init');
|
||||||
|
|
||||||
|
ThreadIdMain := dbg.Threads.CurrentThreads.CurrentThreadId;
|
||||||
|
|
||||||
|
|
||||||
|
for j := 1 to 70 do begin
|
||||||
|
for i := 0 to 9 do begin
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcRun);
|
||||||
|
AssertDebuggerState(dsPause, 'in loop');
|
||||||
|
TestEquals('ThreadId', ThreadIdMain, dbg.Threads.CurrentThreads.CurrentThreadId);
|
||||||
|
TestLocation('loop '+IntToStr(j)+', '+IntToStr(i), 'BrkMain'+IntToStr(i), j);
|
||||||
|
|
||||||
|
if i > 0 then
|
||||||
|
TestEquals('prev brk hitcnt '+IntToStr(j)+', '+IntToStr(i),
|
||||||
|
j, Debugger.BreakPointByName('BrkMain'+IntToStr(i)).HitCount)
|
||||||
|
else
|
||||||
|
TestEquals('prev brk hitcnt '+IntToStr(j)+', '+IntToStr(i),
|
||||||
|
j-1, Debugger.BreakPointByName('BrkMain9').HitCount);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
dbg.Stop;
|
||||||
|
finally
|
||||||
|
Debugger.ClearDebuggerMonitors;
|
||||||
|
Debugger.FreeDebugger;
|
||||||
|
|
||||||
|
AssertTestErrors;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|
||||||
RegisterDbgTest(TTestBreakPoint);
|
RegisterDbgTest(TTestBreakPoint);
|
||||||
ControlTest := TestControlRegisterTest('TTestBreak');
|
ControlTest := TestControlRegisterTest('TTestBreak');
|
||||||
ControlTestBreak := TestControlRegisterTest('TTestBreakPoint', ControlTest);
|
ControlTestBreak := TestControlRegisterTest('TTestBreakPoint', ControlTest);
|
||||||
ControlTestThreadNoSkip := TestControlRegisterTest('TTestBreakThreadNoSkip', ControlTest);
|
ControlTestThreadNoSkip := TestControlRegisterTest('TTestBreakThreadNoSkip', ControlTest);
|
||||||
ControlTestThreadMove1 := TestControlRegisterTest('TTestBreakThreadMove1', ControlTest);
|
ControlTestThreadMove1 := TestControlRegisterTest('TTestBreakThreadMove1', ControlTest);
|
||||||
ControlTestThreadMove2 := TestControlRegisterTest('TTestBreakThreadMove2', ControlTest);
|
ControlTestThreadMove2 := TestControlRegisterTest('TTestBreakThreadMove2', ControlTest);
|
||||||
ControlTestThreadHit := TestControlRegisterTest('TTestBreakThreadHit', ControlTest);
|
ControlTestThreadHit := TestControlRegisterTest('TTestBreakThreadHit', ControlTest);
|
||||||
|
ControlTestThreadIgnoreOther := TestControlRegisterTest('TTestBreakThreadIgnoreOther', ControlTest);
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|||||||
167
components/lazdebuggers/lazdebuggerfp/test/teststepping.pas
Normal file
167
components/lazdebuggers/lazdebuggerfp/test/teststepping.pas
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
unit TestStepping;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, math, TestDbgControl, TestDbgTestSuites,
|
||||||
|
TTestWatchUtilities, TestCommonSources, TestDbgConfig, TestOutputLogger,
|
||||||
|
DbgIntfDebuggerBase, DbgIntfBaseTypes, LazLoggerBase, Forms;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TTestStepping }
|
||||||
|
|
||||||
|
TTestStepping = class(TDBGTestCase)
|
||||||
|
protected
|
||||||
|
Src: TCommonSource;
|
||||||
|
Dbg: TDebuggerIntf;
|
||||||
|
procedure TestLocation(ATestName, ABrkName: String; ABreakHitCount: Integer = 1); // only line-number
|
||||||
|
function IsAtLocation(ABrkName: String): Boolean; // only line-number
|
||||||
|
published
|
||||||
|
(* Step over to work with various events happening during the step
|
||||||
|
- creation/exit of threads
|
||||||
|
- ignored breakpoints (same thread / other thread)
|
||||||
|
- TODO: ignored exception: caught inside the step
|
||||||
|
- TODO: ignored exception: caught caught outside the step (step to except/finally)
|
||||||
|
*)
|
||||||
|
procedure TestStepOver;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
var
|
||||||
|
ControlTest, ControlTestStepOver: Pointer;
|
||||||
|
|
||||||
|
procedure TTestStepping.TestLocation(ATestName, ABrkName: String;
|
||||||
|
ABreakHitCount: Integer);
|
||||||
|
var
|
||||||
|
lc: TDBGLocationRec;
|
||||||
|
begin
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
lc := Debugger.LazDebugger.GetLocation;
|
||||||
|
TestEquals(ATestName+' '+ABrkName+' Loc', Src.BreakPoints[ABrkName], lc.SrcLine);
|
||||||
|
if ABreakHitCount >= 0 then
|
||||||
|
TestEquals(ATestName+' '+ABrkName+' HitCnt', Debugger.BreakPointByName(ABrkName).HitCount, ABreakHitCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TTestStepping.IsAtLocation(ABrkName: String): Boolean;
|
||||||
|
var
|
||||||
|
lc: TDBGLocationRec;
|
||||||
|
begin
|
||||||
|
lc := Debugger.LazDebugger.GetLocation;
|
||||||
|
Result := Src.BreakPoints[ABrkName] = lc.SrcLine;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestStepping.TestStepOver;
|
||||||
|
var
|
||||||
|
ExeName: String;
|
||||||
|
MainBrk, BrkDis, BrkHitCnt: TDBGBreakPoint;
|
||||||
|
ThreadIdMain: Integer;
|
||||||
|
begin
|
||||||
|
if SkipTest then exit;
|
||||||
|
if not TestControlCanTest(ControlTestStepOver) then exit;
|
||||||
|
Src := GetCommonSourceFor(AppDir + 'StepOverPrg.pas');
|
||||||
|
TestCompile(Src, ExeName);
|
||||||
|
|
||||||
|
TestTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
|
||||||
|
dbg := Debugger.LazDebugger;
|
||||||
|
|
||||||
|
try
|
||||||
|
MainBrk := Debugger.SetBreakPoint(Src, 'BrkStart');
|
||||||
|
Debugger.SetBreakPoint(Src, 'BrkThreadCreateInStep');
|
||||||
|
Debugger.SetBreakPoint(Src, 'BrkInterfereByThread');
|
||||||
|
|
||||||
|
BrkDis := Debugger.SetBreakPoint(Src, 'BrkDisabled');
|
||||||
|
BrkHitCnt := Debugger.SetBreakPoint(Src, 'BrkHitCnt');
|
||||||
|
BrkDis.Enabled := False;
|
||||||
|
BrkHitCnt.Enabled := False;
|
||||||
|
BrkHitCnt.BreakHitCount := 999;
|
||||||
|
AssertDebuggerNotInErrorState;
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcRun);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('Init', 'BrkStart');
|
||||||
|
ThreadIdMain := dbg.Threads.CurrentThreads.CurrentThreadId;
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStep', 'AfterStep', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepLongLine', 'AfterStepLongLine', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepProc', 'AfterStepProc', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepProcLong', 'AfterStepProcLong', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepSleepProc', 'AfterStepSleepProc', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepSleep', 'AfterStepSleep', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepBrkDis', 'AfterStepBrkDis', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterStepBrkHitCnt', 'AfterStepBrkHitCnt', -1);
|
||||||
|
|
||||||
|
TestEquals('No Hit for disabled break', 0, BrkDis.HitCount);
|
||||||
|
//TestEquals('No Hit for skipped break', 1, BrkHitCnt.HitCount);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(* The debugger will encounter a thread create event, during the stepping
|
||||||
|
This will mean the main-loop's FCurrentThread is the new thread
|
||||||
|
*)
|
||||||
|
Debugger.RunToNextPause(dcRun);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At BrkThreadCreateInStep', 'BrkThreadCreateInStep', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterThreadCreateInStep', 'AfterThreadCreateInStep', -1);
|
||||||
|
TestEquals('ThreadId AfterThreadCreateInStep', ThreadIdMain, dbg.Threads.CurrentThreads.CurrentThreadId);
|
||||||
|
|
||||||
|
(* The debugger will step over a call.
|
||||||
|
Other threads will hit the FHiddenBreakpoint
|
||||||
|
*)
|
||||||
|
Debugger.RunToNextPause(dcRun);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At BrkInterfereByThread', 'BrkInterfereByThread', -1);
|
||||||
|
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
Debugger.RunToNextPause(dcStepOver);
|
||||||
|
AssertDebuggerState(dsPause);
|
||||||
|
TestLocation('At AfterInterfereByThread', 'AfterInterfereByThread', -1);
|
||||||
|
TestEquals('ThreadId AfterInterfereByThread', ThreadIdMain, dbg.Threads.CurrentThreads.CurrentThreadId);
|
||||||
|
|
||||||
|
|
||||||
|
dbg.Stop;
|
||||||
|
finally
|
||||||
|
Debugger.ClearDebuggerMonitors;
|
||||||
|
Debugger.FreeDebugger;
|
||||||
|
|
||||||
|
AssertTestErrors;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
RegisterDbgTest(TTestStepping);
|
||||||
|
ControlTest := TestControlRegisterTest('TTestStepping');
|
||||||
|
ControlTestStepOver := TestControlRegisterTest('TTestStepOver', ControlTest);
|
||||||
|
end.
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user