StepModeTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. using System.Collections.Generic;
  2. using Esprima.Ast;
  3. using Jint.Runtime.Debugger;
  4. using Xunit;
  5. namespace Jint.Tests.Runtime.Debugger
  6. {
  7. public class StepModeTests
  8. {
  9. /// <summary>
  10. /// Helper method to keep tests independent of line numbers, columns or other arbitrary assertions on
  11. /// the current statement. Steps through script with StepMode.Into until it reaches literal statement
  12. /// (or directive) 'source'. Then counts the steps needed to reach 'target' using the indicated StepMode.
  13. /// </summary>
  14. /// <param name="script">Script used as basis for test</param>
  15. /// <param name="stepMode">StepMode to use from source to target</param>
  16. /// <returns>Number of steps from source to target</returns>
  17. private static int StepsFromSourceToTarget(string script, StepMode stepMode)
  18. {
  19. var engine = new Engine(options => options
  20. .DebugMode()
  21. .InitialStepMode(StepMode.Into)
  22. .DebuggerStatementHandling(DebuggerStatementHandling.Script));
  23. int steps = 0;
  24. bool sourceReached = false;
  25. bool targetReached = false;
  26. engine.DebugHandler.Step += (sender, info) =>
  27. {
  28. if (sourceReached)
  29. {
  30. steps++;
  31. if (info.ReachedLiteral("target"))
  32. {
  33. // Stop stepping
  34. targetReached = true;
  35. return StepMode.None;
  36. }
  37. return stepMode;
  38. }
  39. else if (info.ReachedLiteral("source"))
  40. {
  41. sourceReached = true;
  42. return stepMode;
  43. }
  44. return StepMode.Into;
  45. };
  46. engine.Execute(script);
  47. // Make sure we actually reached the target
  48. Assert.True(targetReached);
  49. return steps;
  50. }
  51. [Fact]
  52. public void StepsIntoRegularFunctionCall()
  53. {
  54. var script = @"
  55. 'source';
  56. test(); // first step
  57. function test()
  58. {
  59. 'target'; // second step
  60. }";
  61. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
  62. }
  63. [Fact]
  64. public void StepsOverRegularFunctionCall()
  65. {
  66. var script = @"
  67. 'source';
  68. test();
  69. 'target';
  70. function test()
  71. {
  72. 'dummy';
  73. }";
  74. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
  75. }
  76. [Fact]
  77. public void StepsOutOfRegularFunctionCall()
  78. {
  79. var script = @"
  80. test();
  81. 'target';
  82. function test()
  83. {
  84. 'source';
  85. 'dummy';
  86. }";
  87. Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
  88. }
  89. [Fact]
  90. public void StepsIntoMemberFunctionCall()
  91. {
  92. var script = @"
  93. const obj = {
  94. test()
  95. {
  96. 'target'; // second step
  97. }
  98. };
  99. 'source';
  100. obj.test(); // first step";
  101. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
  102. }
  103. [Fact]
  104. public void StepsOverMemberFunctionCall()
  105. {
  106. var script = @"
  107. const obj = {
  108. test()
  109. {
  110. 'dummy';
  111. }
  112. };
  113. 'source';
  114. obj.test();
  115. 'target';";
  116. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
  117. }
  118. [Fact]
  119. public void StepsOutOfMemberFunctionCall()
  120. {
  121. var script = @"
  122. const obj = {
  123. test()
  124. {
  125. 'source';
  126. 'dummy';
  127. }
  128. };
  129. obj.test();
  130. 'target';";
  131. Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
  132. }
  133. [Fact]
  134. public void StepsIntoCallExpression()
  135. {
  136. var script = @"
  137. function test()
  138. {
  139. 'target'; // second step
  140. return 42;
  141. }
  142. 'source';
  143. const x = test(); // first step";
  144. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
  145. }
  146. [Fact]
  147. public void StepsOverCallExpression()
  148. {
  149. var script = @"
  150. function test()
  151. {
  152. 'dummy';
  153. return 42;
  154. }
  155. 'source';
  156. const x = test();
  157. 'target';";
  158. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
  159. }
  160. [Fact]
  161. public void StepsOutOfCallExpression()
  162. {
  163. var script = @"
  164. function test()
  165. {
  166. 'source';
  167. 'dummy';
  168. return 42;
  169. }
  170. const x = test();
  171. 'target';";
  172. Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
  173. }
  174. [Fact]
  175. public void StepsIntoGetAccessor()
  176. {
  177. var script = @"
  178. const obj = {
  179. get test()
  180. {
  181. 'target'; // second step
  182. return 144;
  183. }
  184. };
  185. 'source';
  186. const x = obj.test; // first step";
  187. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
  188. }
  189. [Fact]
  190. public void StepsOverGetAccessor()
  191. {
  192. var script = @"
  193. const obj = {
  194. get test()
  195. {
  196. return 144;
  197. }
  198. };
  199. 'source';
  200. const x = obj.test;
  201. 'target';";
  202. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
  203. }
  204. [Fact]
  205. public void StepsOutOfGetAccessor()
  206. {
  207. var script = @"
  208. const obj = {
  209. get test()
  210. {
  211. 'source';
  212. 'dummy';
  213. return 144;
  214. }
  215. };
  216. const x = obj.test;
  217. 'target';";
  218. Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
  219. }
  220. [Fact]
  221. public void StepsIntoSetAccessor()
  222. {
  223. var script = @"
  224. const obj = {
  225. set test(value)
  226. {
  227. 'target'; // second step
  228. this.value = value;
  229. }
  230. };
  231. 'source';
  232. obj.test = 37; // first step";
  233. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Into));
  234. }
  235. [Fact]
  236. public void StepsOverSetAccessor()
  237. {
  238. var script = @"
  239. const obj = {
  240. set test(value)
  241. {
  242. this.value = value;
  243. }
  244. };
  245. 'source';
  246. obj.test = 37;
  247. 'target';";
  248. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
  249. }
  250. [Fact]
  251. public void StepsOutOfSetAccessor()
  252. {
  253. var script = @"
  254. const obj = {
  255. set test(value)
  256. {
  257. 'source';
  258. 'dummy';
  259. this.value = value;
  260. }
  261. };
  262. obj.test = 37;
  263. 'target';";
  264. Assert.Equal(1, StepsFromSourceToTarget(script, StepMode.Out));
  265. }
  266. [Fact]
  267. public void ReturnPointIsAStep()
  268. {
  269. var script = @"
  270. function test()
  271. {
  272. 'source';
  273. }
  274. test();
  275. 'target';";
  276. Assert.Equal(2, StepsFromSourceToTarget(script, StepMode.Over));
  277. }
  278. [Fact]
  279. public void ReturnStatementIsAStep()
  280. {
  281. var script = @"
  282. function test()
  283. {
  284. 'source';
  285. return 'result';
  286. }
  287. test();
  288. 'target';";
  289. Assert.Equal(3, StepsFromSourceToTarget(script, StepMode.Over));
  290. }
  291. [Fact]
  292. public void StepOutOnlyStepsOutOneStackLevel()
  293. {
  294. var script = @"
  295. function test()
  296. {
  297. 'dummy';
  298. test2();
  299. 'target';
  300. }
  301. function test2()
  302. {
  303. 'source';
  304. 'dummy';
  305. 'dummy';
  306. }
  307. test();";
  308. var engine = new Engine(options => options.DebugMode());
  309. int step = 0;
  310. engine.DebugHandler.Step += (sender, info) =>
  311. {
  312. switch (step)
  313. {
  314. case 0:
  315. if (info.ReachedLiteral("source"))
  316. {
  317. step++;
  318. return StepMode.Out;
  319. }
  320. break;
  321. case 1:
  322. Assert.True(info.ReachedLiteral("target"));
  323. step++;
  324. break;
  325. }
  326. return StepMode.Into;
  327. };
  328. engine.Execute(script);
  329. }
  330. [Fact]
  331. public void StepOverDoesSinglestepAfterBreakpoint()
  332. {
  333. string script = @"
  334. test();
  335. function test()
  336. {
  337. 'dummy';
  338. debugger;
  339. 'target';
  340. }";
  341. var engine = new Engine(options => options
  342. .DebugMode()
  343. .DebuggerStatementHandling(DebuggerStatementHandling.Script));
  344. bool stepping = false;
  345. engine.DebugHandler.Break += (sender, info) =>
  346. {
  347. stepping = true;
  348. return StepMode.Over;
  349. };
  350. engine.DebugHandler.Step += (sender, info) =>
  351. {
  352. if (stepping)
  353. {
  354. Assert.True(info.ReachedLiteral("target"));
  355. }
  356. return StepMode.None;
  357. };
  358. engine.Execute(script);
  359. }
  360. [Fact]
  361. public void StepNotTriggeredWhenRunning()
  362. {
  363. string script = @"
  364. test();
  365. function test()
  366. {
  367. 'dummy';
  368. 'øummy';
  369. }";
  370. var engine = new Engine(options => options
  371. .DebugMode()
  372. .InitialStepMode(StepMode.Into));
  373. int stepCount = 0;
  374. engine.DebugHandler.Step += (sender, info) =>
  375. {
  376. stepCount++;
  377. // Start running after first step
  378. return StepMode.None;
  379. };
  380. engine.Execute(script);
  381. Assert.Equal(1, stepCount);
  382. }
  383. }
  384. }