From bfb0ff05dfa99ae4725d5eedb91bc26902d79995 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 15 Sep 2019 13:22:03 +0000 Subject: [PATCH] FpDebug: Test for stepping over an breakpoint that continues (condition/auto-continue/...) / stepping over recursive calls git-svn-id: trunk@61884 - --- .../test/testapps/StepOverPrg.pas | 14 +- .../lazdebuggerfp/test/teststepping.pas | 139 +++++++++++++++++- 2 files changed, 149 insertions(+), 4 deletions(-) diff --git a/components/lazdebuggers/lazdebuggerfp/test/testapps/StepOverPrg.pas b/components/lazdebuggers/lazdebuggerfp/test/testapps/StepOverPrg.pas index 623b7bddb6..3f6b1ceab9 100644 --- a/components/lazdebuggers/lazdebuggerfp/test/testapps/StepOverPrg.pas +++ b/components/lazdebuggers/lazdebuggerfp/test/testapps/StepOverPrg.pas @@ -29,6 +29,16 @@ begin x := 1; end; +Procedure MyNested(ALvl: Integer = 0); +begin + if ALvl > 3 then exit; + if ALvl = 0 then + x := 1; // TEST_BREAKPOINT=BrkNested + x := 3; MyNested(ALvl + 1); x := 4; if ALvl = 0 then // only reach "AfterNested" in most outer recurse + x := 2; // TEST_BREAKPOINT=AfterNested + x := 1; +end; + Procedure MySleep; begin Sleep(50); @@ -79,8 +89,10 @@ begin sleep(50); // TEST_BREAKPOINT=AfterStepSleepProc MyBrkDis; // TEST_BREAKPOINT=AfterStepSleep MyBrkHitCnt; // TEST_BREAKPOINT=AfterStepBrkDis - x := 1; // TEST_BREAKPOINT=AfterStepBrkHitCnt + MyBrkDis; // TEST_BREAKPOINT=AfterStepBrkHitCnt + x := 1; // TEST_BREAKPOINT=AfterStepBrkDisAgain x := 1; + MyNested; // TEST_BREAKPOINT=CallNested T1 := 0; diff --git a/components/lazdebuggers/lazdebuggerfp/test/teststepping.pas b/components/lazdebuggers/lazdebuggerfp/test/teststepping.pas index a183c7fd0f..531c1ec87e 100644 --- a/components/lazdebuggers/lazdebuggerfp/test/teststepping.pas +++ b/components/lazdebuggers/lazdebuggerfp/test/teststepping.pas @@ -27,12 +27,13 @@ type - TODO: ignored exception: caught caught outside the step (step to except/finally) *) procedure TestStepOver; + procedure TestStepOverInstr; end; implementation var - ControlTest, ControlTestStepOver: Pointer; + ControlTest, ControlTestStepOver, ControlTestStepOverInstr: Pointer; procedure TTestStepping.TestLocation(ATestName, ABrkName: String; ABreakHitCount: Integer); @@ -72,11 +73,11 @@ begin MainBrk := Debugger.SetBreakPoint(Src, 'BrkStart'); Debugger.SetBreakPoint(Src, 'BrkThreadCreateInStep'); Debugger.SetBreakPoint(Src, 'BrkInterfereByThread'); + Debugger.SetBreakPoint(Src, 'BrkNested'); BrkDis := Debugger.SetBreakPoint(Src, 'BrkDisabled'); BrkHitCnt := Debugger.SetBreakPoint(Src, 'BrkHitCnt'); BrkDis.Enabled := False; -BrkHitCnt.Enabled := False; BrkHitCnt.BreakHitCount := 999; AssertDebuggerNotInErrorState; @@ -85,41 +86,72 @@ BrkHitCnt.Enabled := False; TestLocation('Init', 'BrkStart'); ThreadIdMain := dbg.Threads.CurrentThreads.CurrentThreadId; + // Step over a line Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStep', 'AfterStep', -1); + // Step over a longer line Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStepLongLine', 'AfterStepLongLine', -1); + // Step over a subroutine call Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStepProc', 'AfterStepProc', -1); + // Step over a several subroutine calls Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStepProcLong', 'AfterStepProcLong', -1); + // Step over a subroutine call, with sleep Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStepSleepProc', 'AfterStepSleepProc', -1); + // Step over a call to sleep Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStepSleep', 'AfterStepSleep', -1); + // Step over a subroutine call, with a disabled breakpoint Debugger.RunToNextPause(dcStepOver); AssertDebuggerState(dsPause); TestLocation('At AfterStepBrkDis', 'AfterStepBrkDis', -1); + // Step over a subroutine call, with a breakpoint that continues 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); + TestEquals('No Hit for skipped break', 1, BrkHitCnt.HitCount); + BrkDis.Enabled := True; + // Step over a subroutine call, BUT STOP at the breakpoint within it + Debugger.RunToNextPause(dcStepOver); + AssertDebuggerState(dsPause); + TestLocation('At BrkDisabled', 'BrkDisabled', -1); + // And do another step + Debugger.RunToNextPause(dcStepOver); + AssertDebuggerState(dsPause); + + TestEquals('No Hit for disabled break', 1, BrkDis.HitCount); + TestEquals('No Hit for skipped break', 1, BrkHitCnt.HitCount); + + + // Step over a RECURSIVE subroutine call + Debugger.RunToNextPause(dcRun); + AssertDebuggerState(dsPause); + TestLocation('At BrkNested', 'BrkNested', -1); + + Debugger.RunToNextPause(dcStepOver); + AssertDebuggerState(dsPause); + Debugger.RunToNextPause(dcStepOver); + AssertDebuggerState(dsPause); + TestLocation('At AfterNested', 'AfterNested', -1); (* The debugger will encounter a thread create event, during the stepping @@ -148,6 +180,106 @@ BrkHitCnt.Enabled := False; TestEquals('ThreadId AfterInterfereByThread', ThreadIdMain, dbg.Threads.CurrentThreads.CurrentThreadId); + dbg.Stop; + finally + Debugger.ClearDebuggerMonitors; + Debugger.FreeDebugger; + + AssertTestErrors; + end; +end; + +procedure TTestStepping.TestStepOverInstr; + procedure StepInstrToNextLine(AName: String; MaxSteps: integer = 50); + var + lc: TDBGLocationRec; + begin + lc := Debugger.LazDebugger.GetLocation; + repeat + Debugger.RunToNextPause(dcStepOverInstr); + AssertDebuggerState(dsPause, 'step instr '+AName); + dec(MaxSteps); + until (lc.SrcLine <> Debugger.LazDebugger.GetLocation.SrcLine) or (MaxSteps <= 0); + end; + +var + ExeName: String; + MainBrk, BrkDis, BrkHitCnt: TDBGBreakPoint; + ThreadIdMain: Integer; +begin + if SkipTest then exit; + if not TestControlCanTest(ControlTestStepOverInstr) 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'); + Debugger.SetBreakPoint(Src, 'BrkNested'); + + BrkDis := Debugger.SetBreakPoint(Src, 'BrkDisabled'); + BrkHitCnt := Debugger.SetBreakPoint(Src, 'BrkHitCnt'); + BrkDis.Enabled := False; + BrkHitCnt.BreakHitCount := 999; + AssertDebuggerNotInErrorState; + + Debugger.RunToNextPause(dcRun); + AssertDebuggerState(dsPause); + TestLocation('Init', 'BrkStart'); + ThreadIdMain := dbg.Threads.CurrentThreads.CurrentThreadId; + + StepInstrToNextLine('Go to AfterStep'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStep', 'AfterStep', -1); + + StepInstrToNextLine('Go to AfterStepLongLine'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStepLongLine', 'AfterStepLongLine', -1); + + StepInstrToNextLine('Go to AfterStepProc'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStepProc', 'AfterStepProc', -1); + + StepInstrToNextLine('Go to AfterStepProcLong'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStepProcLong', 'AfterStepProcLong', -1); + + StepInstrToNextLine('Go to AfterStepSleepProc'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStepSleepProc', 'AfterStepSleepProc', -1); + + StepInstrToNextLine('Go to AfterStepSleep'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStepSleep', 'AfterStepSleep', -1); + + StepInstrToNextLine('Go to AfterStepBrkDis'); + AssertDebuggerState(dsPause); + TestLocation('At AfterStepBrkDis', 'AfterStepBrkDis', -1); + + StepInstrToNextLine('Go to AfterStepBrkHitCnt'); + 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); + + + Debugger.RunToNextPause(dcRun); + AssertDebuggerState(dsPause); + TestLocation('At BrkNested', 'BrkNested', -1); + + StepInstrToNextLine('Go to AfterNested 1'); + AssertDebuggerState(dsPause); + StepInstrToNextLine('Go to AfterNested 2'); + AssertDebuggerState(dsPause); + TestLocation('At AfterNested', 'AfterNested', -1); + + + dbg.Stop; finally Debugger.ClearDebuggerMonitors; @@ -163,5 +295,6 @@ initialization RegisterDbgTest(TTestStepping); ControlTest := TestControlRegisterTest('TTestStepping'); ControlTestStepOver := TestControlRegisterTest('TTestStepOver', ControlTest); + ControlTestStepOverInstr := TestControlRegisterTest('TTestStepOverInstr', ControlTest); end.