Although Ruby's hashes preserve the insertion order, the ordering of
method coverage results is inherently nondeterministic, because they
are collected using `ObjectSpace`.
`throw TAG_BREAK` instruction makes a jump only if the continuation of
catch of TAG_BREAK exactly matches the instruction immediately following
the "send" instruction that is currently being executed. Otherwise, it
seems to determine break from proc-closure.
Branch coverage may insert some recording instructions after "send"
instruction, which broke the conditions for TAG_BREAK to work properly.
This change forces to set the continuation of catch of TAG_BREAK
immediately after "send" (or "invokesuper") instruction.
[Bug #18991]
At that commit, I fixed a wrong conditional expression that was always
true. However, that seemed to have caused a regression. [Bug #18906]
This change removes the condition to make the code always enabled.
It had been enabled until that commit, albeit unintentionally, and even
if it is enabled it only consumes a tiny bit of memory, so I believe it
is harmless. [Bug #18906]
If the type is ADJUST we don't want to treat it like an INSN so we have
to check the type before reading from `insn_info.events`.
[Bug #18001] [ruby-core:104371]
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
jump-jump optimization ignores the event flags of the jump instruction
being skipped, which leads to overlook of line events.
This changeset stops the wrong optimization when coverage measurement is
neabled and when the jump instruction has any event flag.
Note that this issue is not only for coverage but also for TracePoint,
and this change does not fix TracePoint.
However, fixing it fundamentally is tough (which requires revamp of
the compiler). This issue is critical in terms of coverage measurement,
but minor for TracePoint (ko1 said), so we here choose a stopgap
measurement.
[Bug #15980] [Bug #16397]
Note for backporters: this changeset can be viewed by `git diff -w`.
When copying `leave` insn, TRACE also should be copied if it is
present, but this optimization is trivial and not worth the
complexity. [ruby-core:91366] [Bug #15578]
4cae5353c05afd479de6
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Not only TRACE_ELEMENT but also INSN_ELEMENT may have events.
The old pc2branchindex was created using only events of TRACE_ELEMENTs.
This change uses events of INSN_ELEMENTs too for pc2branchindex table.
[Bug #15476]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66676 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
It wrongly used all linenos of ISeq#trace_points which includes not only
line events but also call, return, and other events. So, the result
included some linenos that can not be covered at all by line coverage.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This patch introduces "oneshot_lines" mode for `Coverage.start`, which
checks "whether each line was executed at least once or not", instead of
"how many times each line was executed". A hook for each line is fired
at most once, and after it is fired, the hook flag was removed; it runs
with zero overhead.
See [Feature #15022] in detail.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65195 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Line coverage was based on special instruction "tracecoverage".
Now, instead, it uses the mechanism of trace hook [Feature #14104].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64509 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The code fragments that initializes coverage data were scattered into
both parse.y and compile.c. parse.y allocated a coverage data, and
compile.c initialize the data.
To remove this cross-cutting concern, this change moves the allocation
from "coverage" function of parse.y to "rb_iseq_new_top" of iseq.c.
For the sake, parse.y just counts the line number of the original source
code, and the number is passed via rb_ast_body_t.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64508 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Before this change, coverage.so had failed to measure some multiple-line
code fragments. This is because removing trace instructions (#14104)
changed TracePoint's lineno (new lineno), and coverage counter array was
based on old lineno.
This change initializes coverage counter array based on new lineno.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61313 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* ext/coverage/coverage.c (test_method_coverage_for_define_method):
Add test cases for method coverages which test do-end block
define_method.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61165 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This change makes method coverage result have not only first lineno of
method defintion, but also code range (i.e. first lineno, first column,
last lineno, and last column).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61026 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Traditionally, method coverage measurement was implemented by inserting
`trace2` instruction to the head of method iseq. So, it just measured
methods defined by `def` keyword.
This commit drastically changes the measuring mechanism of method
coverage; at `RUBY_EVENT_CALL`, it keeps a hash from rb_method_entry_t*
to runs (i.e., it counts the runs per method entry), and at
`Coverage.result`, it creates the result hash by enumerating all
`rb_method_entry_t*` objects (by `ObjectSpace.each_object`).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61023 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (DECL_BRANCH_BASE, ADD_TRACE_BRANCH_COVERAGE): Add
a last location to arguments.
* compile.c (compile_if, compile_case, compile_case2, compile_loop, iseq_compile_each0):
Pass a last location to macros.
* ext/coverage/coverage.c (branch_coverage): Add a last location to
a return value.
* test/coverage/test_coverage.rb: Follow-up these changes.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60785 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* test/coverage/test_coverage.rb (test_branch_coverage_for_if_statement):
Add a test case for ternary operator.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60366 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* test/coverage/test_coverage.rb (test_branch_coverage_for_if_statement):
Add test cases for if/unless without else clauses.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60364 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Add `assert_coverage` to invoke Ruby script under coverage measurement
and to compare the result with an expected value.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60003 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
`unless` statement was a syntactic sugar for `if` statement,
which made the result of branch coverage hard to understand.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (iseq_compile_each0): pop trace for coverage only and
clear its corresponding line. [ruby-core:82726] [Bug #13886]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59828 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* test/coverage/test_coverage.rb (test_restarting_coverage): use
real directory path for the case $TMPDIR contains symlinks. on
macOS, it is defaulted to a path under /var which is a symlink
to /private/var.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59725 b2dd03c8-39d4-4d8f-98ff-823fe69b080e