PageRenderTime 31ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/test/coverage/test_coverage.rb

http://github.com/ruby/ruby
Ruby | 743 lines | 666 code | 72 blank | 5 comment | 27 complexity | 8d983985d3b7e88f8e3ec08d6e89a6c2 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: false
  2. require "test/unit"
  3. require "coverage"
  4. require "tmpdir"
  5. require "envutil"
  6. class TestCoverage < Test::Unit::TestCase
  7. def test_result_without_start
  8. assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not enabled/)
  9. Coverage.result
  10. p :NG
  11. end;
  12. end
  13. def test_peek_result_without_start
  14. assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not enabled/)
  15. Coverage.peek_result
  16. p :NG
  17. end;
  18. end
  19. def test_result_with_nothing
  20. assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], [])
  21. Coverage.start
  22. p Coverage.result
  23. end;
  24. end
  25. def test_coverage_running?
  26. assert_in_out_err(%w[-rcoverage], <<-"end;", ["false", "true", "true", "false"], [])
  27. p Coverage.running?
  28. Coverage.start
  29. p Coverage.running?
  30. Coverage.peek_result
  31. p Coverage.running?
  32. Coverage.result
  33. p Coverage.running?
  34. end;
  35. end
  36. def test_coverage_snapshot
  37. Dir.mktmpdir {|tmp|
  38. Dir.chdir(tmp) {
  39. File.open("test.rb", "w") do |f|
  40. f.puts <<-EOS
  41. def coverage_test_snapshot
  42. :ok
  43. end
  44. EOS
  45. end
  46. assert_in_out_err(%w[-rcoverage], <<-"end;", ["[1, 0, nil]", "[1, 1, nil]", "[1, 1, nil]"], [])
  47. Coverage.start
  48. tmp = Dir.pwd
  49. require tmp + "/test.rb"
  50. cov = Coverage.peek_result[tmp + "/test.rb"]
  51. coverage_test_snapshot
  52. cov2 = Coverage.peek_result[tmp + "/test.rb"]
  53. p cov
  54. p cov2
  55. p Coverage.result[tmp + "/test.rb"]
  56. end;
  57. }
  58. }
  59. end
  60. def test_restarting_coverage
  61. Dir.mktmpdir {|tmp|
  62. Dir.chdir(tmp) {
  63. tmp = Dir.pwd
  64. File.open("test.rb", "w") do |f|
  65. f.puts <<-EOS
  66. def coverage_test_restarting
  67. :ok
  68. end
  69. EOS
  70. end
  71. File.open("test2.rb", "w") do |f|
  72. f.puts <<-EOS
  73. itself
  74. EOS
  75. end
  76. exp1 = { "#{tmp}/test.rb" => [1, 0, nil] }.inspect
  77. exp2 = {}.inspect
  78. exp3 = { "#{tmp}/test2.rb" => [1] }.inspect
  79. assert_in_out_err(%w[-rcoverage], <<-"end;", [exp1, exp2, exp3], [])
  80. Coverage.start
  81. tmp = Dir.pwd
  82. require tmp + "/test.rb"
  83. p Coverage.result
  84. # Restart coverage but '/test.rb' is required before restart,
  85. # so coverage is not recorded.
  86. Coverage.start
  87. coverage_test_restarting
  88. p Coverage.result
  89. # Restart coverage and '/test2.rb' is required after restart,
  90. # so coverage is recorded.
  91. Coverage.start
  92. require tmp + "/test2.rb"
  93. p Coverage.result
  94. end;
  95. }
  96. }
  97. end
  98. def test_big_code
  99. Dir.mktmpdir {|tmp|
  100. Dir.chdir(tmp) {
  101. File.open("test.rb", "w") do |f|
  102. f.puts "__id__\n" * 10000
  103. f.puts "def ignore(x); end"
  104. f.puts "ignore([1"
  105. f.puts "])"
  106. end
  107. assert_in_out_err(%w[-rcoverage], <<-"end;", ["10003"], [])
  108. Coverage.start
  109. tmp = Dir.pwd
  110. require tmp + '/test.rb'
  111. p Coverage.result[tmp + '/test.rb'].size
  112. end;
  113. }
  114. }
  115. end
  116. def test_eval
  117. bug13305 = '[ruby-core:80079] [Bug #13305]'
  118. Dir.mktmpdir {|tmp|
  119. Dir.chdir(tmp) {
  120. File.open("test.rb", "w") do |f|
  121. f.puts 'REPEATS = 400'
  122. f.puts 'def add_method(target)'
  123. f.puts ' REPEATS.times do'
  124. f.puts ' target.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)'
  125. f.puts ' def foo'
  126. f.puts ' #{"\n" * rand(REPEATS)}'
  127. f.puts ' end'
  128. f.puts ' 1'
  129. f.puts ' RUBY'
  130. f.puts ' end'
  131. f.puts 'end'
  132. end
  133. assert_in_out_err(%w[-W0 -rcoverage], <<-"end;", ["[1, 1, 1, 400, nil, nil, nil, nil, nil, nil, nil]"], [], bug13305)
  134. Coverage.start
  135. tmp = Dir.pwd
  136. require tmp + '/test.rb'
  137. add_method(Class.new)
  138. p Coverage.result[tmp + "/test.rb"]
  139. end;
  140. }
  141. }
  142. end
  143. def test_nocoverage_optimized_line
  144. assert_ruby_status(%w[], "#{<<-"begin;"}\n#{<<-'end;'}")
  145. begin;
  146. def foo(x)
  147. x # optimized away
  148. nil
  149. end
  150. end;
  151. end
  152. def test_coverage_optimized_branch
  153. result = {
  154. :branches => {
  155. [:"&.", 0, 1, 0, 1, 8] => {
  156. [:then, 1, 1, 0, 1, 8] => 0,
  157. [:else, 2, 1, 0, 1, 8] => 1,
  158. },
  159. },
  160. }
  161. assert_coverage(<<~"end;", { branches: true }, result) # Bug #15476
  162. nil&.foo
  163. end;
  164. end
  165. def assert_coverage(code, opt, stdout)
  166. stdout = [stdout] unless stdout.is_a?(Array)
  167. stdout = stdout.map {|s| s.to_s }
  168. Dir.mktmpdir {|tmp|
  169. Dir.chdir(tmp) {
  170. File.write("test.rb", code)
  171. assert_in_out_err(%w[-W0 -rcoverage], <<-"end;", stdout, [])
  172. Coverage.start(#{ opt })
  173. tmp = Dir.pwd
  174. require tmp + '/test.rb'
  175. r = Coverage.result[tmp + "/test.rb"]
  176. if r[:methods]
  177. h = {}
  178. r[:methods].keys.sort_by {|key| key.drop(1) }.each do |key|
  179. h[key] = r[:methods][key]
  180. end
  181. r[:methods].replace h
  182. end
  183. p r
  184. end;
  185. }
  186. }
  187. end
  188. def test_line_coverage_for_multiple_lines
  189. result = {
  190. :lines => [nil, 1, nil, nil, nil, 1, nil, nil, nil, 1, nil, 1, nil, nil, nil, nil, 1, 1, nil, 1, nil, nil, nil, nil, 1]
  191. }
  192. assert_coverage(<<~"end;", { lines: true }, result) # Bug #14191
  193. FOO = [
  194. { foo: 'bar' },
  195. { bar: 'baz' }
  196. ]
  197. 'some string'.split
  198. .map(&:length)
  199. some =
  200. 'value'
  201. Struct.new(
  202. :foo,
  203. :bar
  204. ).new
  205. class Test
  206. def foo(bar)
  207. {
  208. foo: bar
  209. }
  210. end
  211. end
  212. Test.new.foo(Object.new)
  213. end;
  214. end
  215. def test_branch_coverage_for_if_statement
  216. result = {
  217. :branches => {
  218. [:if , 0, 2, 2, 6, 5] => {[:then, 1, 3, 4, 3, 5]=>2, [:else, 2, 5, 4, 5, 5]=>1},
  219. [:unless, 3, 8, 2, 12, 5] => {[:else, 4, 11, 4, 11, 5]=>2, [:then, 5, 9, 4, 9, 5]=>1},
  220. [:if , 6, 14, 2, 16, 5] => {[:then, 7, 15, 4, 15, 5]=>2, [:else, 8, 14, 2, 16, 5]=>1},
  221. [:unless, 9, 18, 2, 20, 5] => {[:else, 10, 18, 2, 20, 5]=>2, [:then, 11, 19, 4, 19, 5]=>1},
  222. [:if , 12, 22, 2, 22, 13] => {[:then, 13, 22, 2, 22, 3]=>2, [:else, 14, 22, 2, 22, 13]=>1},
  223. [:unless, 15, 23, 2, 23, 17] => {[:else, 16, 23, 2, 23, 17]=>2, [:then, 17, 23, 2, 23, 3]=>1},
  224. [:if , 18, 25, 2, 25, 16] => {[:then, 19, 25, 11, 25, 12]=>2, [:else, 20, 25, 15, 25, 16]=>1},
  225. }
  226. }
  227. assert_coverage(<<~"end;", { branches: true }, result)
  228. def foo(x)
  229. if x == 0
  230. 0
  231. else
  232. 1
  233. end
  234. unless x == 0
  235. 0
  236. else
  237. 1
  238. end
  239. if x == 0
  240. 0
  241. end
  242. unless x == 0
  243. 0
  244. end
  245. 0 if x == 0
  246. 0 unless x == 0
  247. x == 0 ? 0 : 1
  248. end
  249. foo(0)
  250. foo(0)
  251. foo(1)
  252. end;
  253. end
  254. def test_branch_coverage_for_while_statement
  255. result = {
  256. :branches => {
  257. [:while, 0, 2, 0, 4, 3] => {[:body, 1, 3, 2, 3, 8]=> 3},
  258. [:until, 2, 5, 0, 7, 3] => {[:body, 3, 6, 2, 6, 8]=>10},
  259. [:while, 4, 10, 0, 10, 18] => {[:body, 5, 10, 0, 10, 6]=> 3},
  260. [:until, 6, 11, 0, 11, 20] => {[:body, 7, 11, 0, 11, 6]=>10},
  261. }
  262. }
  263. assert_coverage(<<~"end;", { branches: true }, result)
  264. x = 3
  265. while x > 0
  266. x -= 1
  267. end
  268. until x == 10
  269. x += 1
  270. end
  271. y = 3
  272. y -= 1 while y > 0
  273. y += 1 until y == 10
  274. end;
  275. end
  276. def test_branch_coverage_for_case_statement
  277. result = {
  278. :branches => {
  279. [:case, 0, 2, 2, 7, 5] => {[:when, 1, 4, 4, 4, 5]=>2, [:when, 2, 6, 4, 6, 5]=>0, [:else, 3, 2, 2, 7, 5]=>1},
  280. [:case, 4, 9, 2, 14, 5] => {[:when, 5, 11, 4, 11, 5]=>2, [:when, 6, 13, 4, 13, 5]=>0, [:else, 7, 9, 2, 14, 5]=>1},
  281. [:case, 8, 16, 2, 23, 5] => {[:when, 9, 18, 4, 18, 5]=>2, [:when, 10, 20, 4, 20, 5]=>0, [:else, 11, 22, 4, 22, 10]=>1},
  282. [:case, 12, 25, 2, 32, 5] => {[:when, 13, 27, 4, 27, 5]=>2, [:when, 14, 29, 4, 29, 5]=>0, [:else, 15, 31, 4, 31, 10]=>1},
  283. }
  284. }
  285. assert_coverage(<<~"end;", { branches: true }, result)
  286. def foo(x)
  287. case x
  288. when 0
  289. 0
  290. when 1
  291. 1
  292. end
  293. case
  294. when x == 0
  295. 0
  296. when x == 1
  297. 1
  298. end
  299. case x
  300. when 0
  301. 0
  302. when 1
  303. 1
  304. else
  305. :other
  306. end
  307. case
  308. when x == 0
  309. 0
  310. when x == 1
  311. 1
  312. else
  313. :other
  314. end
  315. end
  316. foo(0)
  317. foo(0)
  318. foo(2)
  319. end;
  320. end
  321. def test_branch_coverage_for_pattern_matching
  322. result = {
  323. :branches=> {
  324. [:case, 0, 3, 4, 8, 7] => {[:in, 1, 5, 6, 5, 7]=>2, [:in, 2, 7, 6, 7, 7]=>0, [:else, 3, 3, 4, 8, 7]=>1},
  325. [:case, 4, 12, 2, 17, 5] => {[:in, 5, 14, 4, 14, 5]=>2, [:else, 6, 16, 4, 16, 5]=>1}},
  326. }
  327. assert_coverage(<<~"end;", { branches: true }, result)
  328. def foo(x)
  329. begin
  330. case x
  331. in 0
  332. 0
  333. in 1
  334. 1
  335. end
  336. rescue NoMatchingPatternError
  337. end
  338. case x
  339. in 0
  340. 0
  341. else
  342. 1
  343. end
  344. end
  345. foo(0)
  346. foo(0)
  347. foo(2)
  348. end;
  349. end
  350. def test_branch_coverage_for_safe_method_invocation
  351. result = {
  352. :branches=>{
  353. [:"&.", 0, 6, 0, 6, 6] => {[:then, 1, 6, 0, 6, 6]=>1, [:else, 2, 6, 0, 6, 6]=>0},
  354. [:"&.", 3, 7, 0, 7, 6] => {[:then, 4, 7, 0, 7, 6]=>0, [:else, 5, 7, 0, 7, 6]=>1},
  355. [:"&.", 6, 8, 0, 8, 10] => {[:then, 7, 8, 0, 8, 10]=>1, [:else, 8, 8, 0, 8, 10]=>0},
  356. [:"&.", 9, 9, 0, 9, 10] => {[:then, 10, 9, 0, 9, 10]=>0, [:else, 11, 9, 0, 9, 10]=>1},
  357. }
  358. }
  359. assert_coverage(<<~"end;", { branches: true }, result)
  360. class Dummy; def foo; end; def foo=(x); end; end
  361. a = Dummy.new
  362. b = nil
  363. c = Dummy.new
  364. d = nil
  365. a&.foo
  366. b&.foo
  367. c&.foo = 1
  368. d&.foo = 1
  369. end;
  370. end
  371. def test_method_coverage
  372. result = {
  373. :methods => {
  374. [Object, :bar, 2, 0, 3, 3] => 1,
  375. [Object, :baz, 4, 1, 4, 13] => 0,
  376. [Object, :foo, 1, 0, 1, 12] => 2,
  377. }
  378. }
  379. assert_coverage(<<~"end;", { methods: true }, result)
  380. def foo; end
  381. def bar
  382. end
  383. def baz; end
  384. foo
  385. foo
  386. bar
  387. end;
  388. end
  389. def test_method_coverage_for_define_method
  390. result = {
  391. :methods => {
  392. [Object, :a, 6, 18, 6, 25] => 2,
  393. [Object, :b, 7, 18, 8, 3] => 0,
  394. [Object, :bar, 2, 20, 3, 1] => 1,
  395. [Object, :baz, 4, 9, 4, 11] => 0,
  396. [Object, :foo, 1, 20, 1, 22] => 2,
  397. }
  398. }
  399. assert_coverage(<<~"end;", { methods: true }, result)
  400. define_method(:foo) {}
  401. define_method(:bar) {
  402. }
  403. f = proc {}
  404. define_method(:baz, &f)
  405. define_method(:a) do; end
  406. define_method(:b) do
  407. end
  408. foo
  409. foo
  410. bar
  411. a
  412. a
  413. end;
  414. end
  415. class DummyConstant < String
  416. def inspect
  417. self
  418. end
  419. end
  420. def test_method_coverage_for_alias
  421. _C = DummyConstant.new("C")
  422. _M = DummyConstant.new("M")
  423. code = <<~"end;"
  424. module M
  425. def foo
  426. end
  427. alias bar foo
  428. end
  429. class C
  430. include M
  431. def baz
  432. end
  433. alias qux baz
  434. end
  435. end;
  436. result = {
  437. :methods => {
  438. [_C, :baz, 8, 2, 9, 5] => 0,
  439. [_M, :foo, 2, 2, 3, 5] => 0,
  440. }
  441. }
  442. assert_coverage(code, { methods: true }, result)
  443. result = {
  444. :methods => {
  445. [_C, :baz, 8, 2, 9, 5] => 12,
  446. [_M, :foo, 2, 2, 3, 5] => 3,
  447. }
  448. }
  449. assert_coverage(code + <<~"end;", { methods: true }, result)
  450. obj = C.new
  451. 1.times { obj.foo }
  452. 2.times { obj.bar }
  453. 4.times { obj.baz }
  454. 8.times { obj.qux }
  455. end;
  456. end
  457. def test_method_coverage_for_singleton_class
  458. _singleton_Foo = DummyConstant.new("#<Class:Foo>")
  459. _Foo = DummyConstant.new("Foo")
  460. code = <<~"end;"
  461. class Foo
  462. def foo
  463. end
  464. alias bar foo
  465. def self.baz
  466. end
  467. class << self
  468. alias qux baz
  469. end
  470. end
  471. 1.times { Foo.new.foo }
  472. 2.times { Foo.new.bar }
  473. 4.times { Foo.baz }
  474. 8.times { Foo.qux }
  475. end;
  476. result = {
  477. :methods => {
  478. [_singleton_Foo, :baz, 5, 2, 6, 5] => 12,
  479. [_Foo, :foo, 2, 2, 3, 5] => 3,
  480. }
  481. }
  482. assert_coverage(code, { methods: true }, result)
  483. end
  484. def test_oneshot_line_coverage
  485. result = {
  486. :oneshot_lines => [2, 6, 10, 12, 17, 18, 25, 20]
  487. }
  488. assert_coverage(<<~"end;", { oneshot_lines: true }, result)
  489. FOO = [
  490. { foo: 'bar' }, # 2
  491. { bar: 'baz' }
  492. ]
  493. 'some string'.split # 6
  494. .map(&:length)
  495. some =
  496. 'value' # 10
  497. Struct.new( # 12
  498. :foo,
  499. :bar
  500. ).new
  501. class Test # 17
  502. def foo(bar) # 18
  503. {
  504. foo: bar # 20
  505. }
  506. end
  507. end
  508. Test.new.foo(Object.new) # 25
  509. end;
  510. end
  511. def test_clear_with_lines
  512. Dir.mktmpdir {|tmp|
  513. Dir.chdir(tmp) {
  514. File.open("test.rb", "w") do |f|
  515. f.puts "def foo(x)"
  516. f.puts " if x > 0"
  517. f.puts " :pos"
  518. f.puts " else"
  519. f.puts " :non_pos"
  520. f.puts " end"
  521. f.puts "end"
  522. end
  523. exp = [
  524. "{:lines=>[1, 0, 0, nil, 0, nil, nil]}",
  525. "{:lines=>[0, 1, 1, nil, 0, nil, nil]}",
  526. "{:lines=>[0, 1, 0, nil, 1, nil, nil]}",
  527. ]
  528. assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
  529. Coverage.start(lines: true)
  530. tmp = Dir.pwd
  531. f = tmp + "/test.rb"
  532. require f
  533. p Coverage.result(stop: false, clear: true)[f]
  534. foo(1)
  535. p Coverage.result(stop: false, clear: true)[f]
  536. foo(-1)
  537. p Coverage.result[f]
  538. end;
  539. }
  540. }
  541. end
  542. def test_clear_with_branches
  543. Dir.mktmpdir {|tmp|
  544. Dir.chdir(tmp) {
  545. File.open("test.rb", "w") do |f|
  546. f.puts "def foo(x)"
  547. f.puts " if x > 0"
  548. f.puts " :pos"
  549. f.puts " else"
  550. f.puts " :non_pos"
  551. f.puts " end"
  552. f.puts "end"
  553. end
  554. exp = [
  555. "{:branches=>{[:if, 0, 2, 2, 6, 5]=>{[:then, 1, 3, 4, 3, 8]=>0, [:else, 2, 5, 4, 5, 12]=>0}}}",
  556. "{:branches=>{[:if, 0, 2, 2, 6, 5]=>{[:then, 1, 3, 4, 3, 8]=>1, [:else, 2, 5, 4, 5, 12]=>0}}}",
  557. "{:branches=>{[:if, 0, 2, 2, 6, 5]=>{[:then, 1, 3, 4, 3, 8]=>0, [:else, 2, 5, 4, 5, 12]=>1}}}",
  558. "{:branches=>{[:if, 0, 2, 2, 6, 5]=>{[:then, 1, 3, 4, 3, 8]=>0, [:else, 2, 5, 4, 5, 12]=>1}}}",
  559. ]
  560. assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
  561. Coverage.start(branches: true)
  562. tmp = Dir.pwd
  563. f = tmp + "/test.rb"
  564. require f
  565. p Coverage.result(stop: false, clear: true)[f]
  566. foo(1)
  567. p Coverage.result(stop: false, clear: true)[f]
  568. foo(-1)
  569. p Coverage.result(stop: false, clear: true)[f]
  570. foo(-1)
  571. p Coverage.result(stop: false, clear: true)[f]
  572. end;
  573. }
  574. }
  575. end
  576. def test_clear_with_methods
  577. Dir.mktmpdir {|tmp|
  578. Dir.chdir(tmp) {
  579. File.open("test.rb", "w") do |f|
  580. f.puts "def foo(x)"
  581. f.puts " if x > 0"
  582. f.puts " :pos"
  583. f.puts " else"
  584. f.puts " :non_pos"
  585. f.puts " end"
  586. f.puts "end"
  587. end
  588. exp = [
  589. "{:methods=>{[Object, :foo, 1, 0, 7, 3]=>0}}",
  590. "{:methods=>{[Object, :foo, 1, 0, 7, 3]=>1}}",
  591. "{:methods=>{[Object, :foo, 1, 0, 7, 3]=>1}}",
  592. "{:methods=>{[Object, :foo, 1, 0, 7, 3]=>1}}"
  593. ]
  594. assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
  595. Coverage.start(methods: true)
  596. tmp = Dir.pwd
  597. f = tmp + "/test.rb"
  598. require f
  599. p Coverage.result(stop: false, clear: true)[f]
  600. foo(1)
  601. p Coverage.result(stop: false, clear: true)[f]
  602. foo(-1)
  603. p Coverage.result(stop: false, clear: true)[f]
  604. foo(-1)
  605. p Coverage.result(stop: false, clear: true)[f]
  606. end;
  607. }
  608. }
  609. end
  610. def test_clear_with_oneshot_lines
  611. Dir.mktmpdir {|tmp|
  612. Dir.chdir(tmp) {
  613. File.open("test.rb", "w") do |f|
  614. f.puts "def foo(x)"
  615. f.puts " if x > 0"
  616. f.puts " :pos"
  617. f.puts " else"
  618. f.puts " :non_pos"
  619. f.puts " end"
  620. f.puts "end"
  621. end
  622. exp = [
  623. "{:oneshot_lines=>[1]}",
  624. "{:oneshot_lines=>[2, 3]}",
  625. "{:oneshot_lines=>[5]}",
  626. "{:oneshot_lines=>[]}",
  627. ]
  628. assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
  629. Coverage.start(oneshot_lines: true)
  630. tmp = Dir.pwd
  631. f = tmp + "/test.rb"
  632. require f
  633. p Coverage.result(stop: false, clear: true)[f]
  634. foo(1)
  635. p Coverage.result(stop: false, clear: true)[f]
  636. foo(-1)
  637. p Coverage.result(stop: false, clear: true)[f]
  638. foo(-1)
  639. p Coverage.result(stop: false, clear: true)[f]
  640. end;
  641. }
  642. }
  643. end
  644. def test_line_stub
  645. Dir.mktmpdir {|tmp|
  646. Dir.chdir(tmp) {
  647. File.open("test.rb", "w") do |f|
  648. f.puts "def foo(x)"
  649. f.puts " if x > 0"
  650. f.puts " :pos"
  651. f.puts " else"
  652. f.puts " :non_pos"
  653. f.puts " end"
  654. f.puts "end"
  655. end
  656. assert_equal([0, 0, 0, nil, 0, nil, nil], Coverage.line_stub("test.rb"))
  657. }
  658. }
  659. end
  660. def test_stop_wrong_peephole_optimization
  661. result = {
  662. :lines => [1, 1, 1, nil]
  663. }
  664. assert_coverage(<<~"end;", { lines: true }, result)
  665. raise if 1 == 2
  666. while true
  667. break
  668. end
  669. end;
  670. end
  671. end