Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
/Users/pbartels/.rvm/gems/ruby-1.9.2-p136/gems/rcov-0.9.9/lib/rcov/differential_analyzer.rb | 116 | 82 | 6.03%
|
7.32%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 module Rcov |
2 class DifferentialAnalyzer |
3 require 'thread' |
4 @@mutex = Mutex.new |
5 |
6 def initialize(install_hook_meth, remove_hook_meth, reset_meth) |
7 @cache_state = :wait |
8 @start_raw_data = data_default |
9 @end_raw_data = data_default |
10 @aggregated_data = data_default |
11 @install_hook_meth = install_hook_meth |
12 @remove_hook_meth= remove_hook_meth |
13 @reset_meth= reset_meth |
14 end |
15 |
16 # Execute the code in the given block, monitoring it in order to gather |
17 # information about which code was executed. |
18 def run_hooked |
19 install_hook |
20 yield |
21 ensure |
22 remove_hook |
23 end |
24 |
25 # Start monitoring execution to gather information. Such data will be |
26 # collected until #remove_hook is called. |
27 # |
28 # Use #run_hooked instead if possible. |
29 def install_hook |
30 @start_raw_data = raw_data_absolute |
31 Rcov::RCOV__.send(@install_hook_meth) |
32 @cache_state = :hooked |
33 @@mutex.synchronize{ self.class.hook_level += 1 } |
34 end |
35 |
36 # Stop collecting information. |
37 # #remove_hook will also stop collecting info if it is run inside a |
38 # #run_hooked block. |
39 def remove_hook |
40 @@mutex.synchronize do |
41 self.class.hook_level -= 1 |
42 Rcov::RCOV__.send(@remove_hook_meth) if self.class.hook_level == 0 |
43 end |
44 @end_raw_data = raw_data_absolute |
45 @cache_state = :done |
46 # force computation of the stats for the traced code in this run; |
47 # we cannot simply let it be if self.class.hook_level == 0 because |
48 # some other analyzer could install a hook, causing the raw_data_absolute |
49 # to change again. |
50 # TODO: lazy computation of raw_data_relative, only when the hook gets |
51 # activated again. |
52 raw_data_relative |
53 end |
54 |
55 # Remove the data collected so far. Further collection will start from |
56 # scratch. |
57 def reset |
58 @@mutex.synchronize do |
59 if self.class.hook_level == 0 |
60 # Unfortunately there's no way to report this as covered with rcov: |
61 # if we run the tests under rcov self.class.hook_level will be >= 1 ! |
62 # It is however executed when we run the tests normally. |
63 Rcov::RCOV__.send(@reset_meth) |
64 @start_raw_data = data_default |
65 @end_raw_data = data_default |
66 else |
67 @start_raw_data = @end_raw_data = raw_data_absolute |
68 end |
69 @raw_data_relative = data_default |
70 @aggregated_data = data_default |
71 end |
72 end |
73 |
74 protected |
75 |
76 def data_default |
77 raise "must be implemented by the subclass" |
78 end |
79 |
80 def self.hook_level |
81 raise "must be implemented by the subclass" |
82 end |
83 |
84 def raw_data_absolute |
85 raise "must be implemented by the subclass" |
86 end |
87 |
88 def aggregate_data(aggregated_data, delta) |
89 raise "must be implemented by the subclass" |
90 end |
91 |
92 def compute_raw_data_difference(first, last) |
93 raise "must be implemented by the subclass" |
94 end |
95 |
96 private |
97 |
98 def raw_data_relative |
99 case @cache_state |
100 when :wait |
101 return @aggregated_data |
102 when :hooked |
103 new_start = raw_data_absolute |
104 new_diff = compute_raw_data_difference(@start_raw_data, new_start) |
105 @start_raw_data = new_start |
106 when :done |
107 @cache_state = :wait |
108 new_diff = compute_raw_data_difference(@start_raw_data, |
109 @end_raw_data) |
110 end |
111 |
112 aggregate_data(@aggregated_data, new_diff) |
113 @aggregated_data |
114 end |
115 end |
116 end |
Generated on 2011-07-06 14:15:30 +1200 with rcov 0.9.8