123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- using Jint.Runtime.Debugger;
- namespace Jint.Tests.Runtime.Debugger;
- public class StepModeTests
- {
- /// <summary>
- /// Helper method to keep tests independent of line numbers, columns or other arbitrary assertions on
- /// the current statement. Steps through script with StepMode.Into until it reaches literal statement
- /// (or directive) 'source'. Then counts the steps needed to reach 'target' using the indicated StepMode.
- /// </summary>
- /// <param name="script">Script used as basis for test</param>
- /// <param name="stepMode">StepMode to use from source to target</param>
- /// <returns>Number of steps from source to target</returns>
- private static int StepsFromSourceToTarget(string script, StepMode stepMode)
- {
- var engine = new Engine(options => options
- .DebugMode()
- .InitialStepMode(StepMode.Into)
- .DebuggerStatementHandling(DebuggerStatementHandling.Script));
- int steps = 0;
- bool sourceReached = false;
- bool targetReached = false;
- engine.Debugger.Step += (sender, info) =>
- {
- if (sourceReached)
- {
- steps++;
- if (info.ReachedLiteral("target"))
- {
- // Stop stepping
- targetReached = true;
- return StepMode.None;
- }
- return stepMode;
- }
- else if (info.ReachedLiteral("source"))
- {
- sourceReached = true;
- return stepMode;
- }
- return StepMode.Into;
- };
- engine.Execute(script);
-
- // Make sure we actually reached the target
- Assert.True(targetReached);
- return steps;
- }
- [Fact]
- public void StepsIntoRegularFunctionCall()
- {
- var script = @"
- 'source';
- test(); // first step
- function test()
- {
- 'target'; // second step
- }";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
- }
- [Fact]
- public void StepsOverRegularFunctionCall()
- {
- var script = @"
- 'source';
- test();
- 'target';
- function test()
- {
- 'dummy';
- }";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void StepsOutOfRegularFunctionCall()
- {
- var script = @"
- test();
- 'target';
- function test()
- {
- 'source';
- 'dummy';
- }";
- Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
- }
- [Fact]
- public void StepsIntoMemberFunctionCall()
- {
- var script = @"
- const obj = {
- test()
- {
- 'target'; // second step
- }
- };
- 'source';
- obj.test(); // first step";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
- }
- [Fact]
- public void StepsOverMemberFunctionCall()
- {
- var script = @"
- const obj = {
- test()
- {
- 'dummy';
- }
- };
- 'source';
- obj.test();
- 'target';";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void StepsOutOfMemberFunctionCall()
- {
- var script = @"
- const obj = {
- test()
- {
- 'source';
- 'dummy';
- }
- };
- obj.test();
- 'target';";
- Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
- }
- [Fact]
- public void StepsIntoCallExpression()
- {
- var script = @"
- function test()
- {
- 'target'; // second step
- return 42;
- }
- 'source';
- const x = test(); // first step";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
- }
- [Fact]
- public void StepsOverCallExpression()
- {
- var script = @"
- function test()
- {
- 'dummy';
- return 42;
- }
- 'source';
- const x = test();
- 'target';";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void StepsOutOfCallExpression()
- {
- var script = @"
- function test()
- {
- 'source';
- 'dummy';
- return 42;
- }
- const x = test();
- 'target';";
- Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
- }
- [Fact]
- public void StepsIntoGetAccessor()
- {
- var script = @"
- const obj = {
- get test()
- {
- 'target'; // second step
- return 144;
- }
- };
- 'source';
- const x = obj.test; // first step";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
- }
- [Fact]
- public void StepsOverGetAccessor()
- {
- var script = @"
- const obj = {
- get test()
- {
- return 144;
- }
- };
- 'source';
- const x = obj.test;
- 'target';";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void StepsOutOfGetAccessor()
- {
- var script = @"
- const obj = {
- get test()
- {
- 'source';
- 'dummy';
- return 144;
- }
- };
- const x = obj.test;
- 'target';";
- Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
- }
- [Fact]
- public void StepsIntoSetAccessor()
- {
- var script = @"
- const obj = {
- set test(value)
- {
- 'target'; // second step
- this.value = value;
- }
- };
- 'source';
- obj.test = 37; // first step";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
- }
- [Fact]
- public void StepsOverSetAccessor()
- {
- var script = @"
- const obj = {
- set test(value)
- {
- this.value = value;
- }
- };
- 'source';
- obj.test = 37;
- 'target';";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void StepsOutOfSetAccessor()
- {
- var script = @"
- const obj = {
- set test(value)
- {
- 'source';
- 'dummy';
- this.value = value;
- }
- };
- obj.test = 37;
- 'target';";
- Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
- }
- [Fact]
- public void ReturnPointIsAStep()
- {
- var script = @"
- function test()
- {
- 'source';
- }
- test();
- 'target';";
- Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void ReturnStatementIsAStep()
- {
- var script = @"
- function test()
- {
- 'source';
- return 'result';
- }
- test();
- 'target';";
- Assert.Equal(3, StepsFromSourceToTarget(script, StepMode.Over));
- }
- [Fact]
- public void StepOutOnlyStepsOutOneStackLevel()
- {
- var script = @"
- function test()
- {
- 'dummy';
- test2();
- 'target';
- }
- function test2()
- {
- 'source';
- 'dummy';
- 'dummy';
- }
- test();";
- var engine = new Engine(options => options.DebugMode());
- int step = 0;
- engine.Debugger.Step += (sender, info) =>
- {
- switch (step)
- {
- case 0:
- if (info.ReachedLiteral("source"))
- {
- step++;
- return StepMode.Out;
- }
- break;
- case 1:
- Assert.True(info.ReachedLiteral("target"));
- step++;
- break;
- }
- return StepMode.Into;
- };
- engine.Execute(script);
- }
- [Fact]
- public void StepOverDoesSinglestepAfterBreakpoint()
- {
- string script = @"
- test();
- function test()
- {
- 'dummy';
- debugger;
- 'target';
- }";
- var engine = new Engine(options => options
- .DebugMode()
- .DebuggerStatementHandling(DebuggerStatementHandling.Script));
- bool stepping = false;
- engine.Debugger.Break += (sender, info) =>
- {
- stepping = true;
- return StepMode.Over;
- };
- engine.Debugger.Step += (sender, info) =>
- {
- if (stepping)
- {
- Assert.True(info.ReachedLiteral("target"));
- }
- return StepMode.None;
- };
- engine.Execute(script);
- }
- [Fact]
- public void StepNotTriggeredWhenRunning()
- {
- string script = @"
- test();
- function test()
- {
- 'dummy';
- 'dummy';
- }";
- var engine = new Engine(options => options
- .DebugMode()
- .InitialStepMode(StepMode.Into));
- int stepCount = 0;
- engine.Debugger.Step += (sender, info) =>
- {
- stepCount++;
- // Start running after first step
- return StepMode.None;
- };
- engine.Execute(script);
- Assert.Equal(1, stepCount);
- }
- [Fact]
- public void SkipIsTriggeredWhenRunning()
- {
- string script = @"
- 'step';
- 'skip';
- 'skip';
- debugger;
- 'step';
- 'step';
- ";
- var engine = new Engine(options => options
- .DebugMode()
- .DebuggerStatementHandling(DebuggerStatementHandling.Script)
- .InitialStepMode(StepMode.Into));
- int stepCount = 0;
- int skipCount = 0;
- engine.Debugger.Step += (sender, info) =>
- {
- Assert.True(TestHelpers.IsLiteral(info.CurrentNode, "step"));
- stepCount++;
- // Start running after first step
- return stepCount == 1 ? StepMode.None : StepMode.Into;
- };
- engine.Debugger.Skip += (sender, info) =>
- {
- Assert.True(TestHelpers.IsLiteral(info.CurrentNode, "skip"));
- skipCount++;
- return StepMode.None;
- };
- engine.Debugger.Break += (sender, info) =>
- {
- // Back to stepping after debugger statement
- return StepMode.Into;
- };
- engine.Execute(script);
- Assert.Equal(2, skipCount);
- Assert.Equal(3, stepCount);
- }
- }
|