StepModeTests.cs 12 KB

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