ruby-prof 0.18.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +44 -1
  3. data/LICENSE +2 -2
  4. data/README.rdoc +1 -483
  5. data/Rakefile +3 -6
  6. data/bin/ruby-prof +111 -128
  7. data/ext/ruby_prof/extconf.rb +6 -38
  8. data/ext/ruby_prof/rp_aggregate_call_tree.c +41 -0
  9. data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
  10. data/ext/ruby_prof/rp_allocation.c +259 -0
  11. data/ext/ruby_prof/rp_allocation.h +31 -0
  12. data/ext/ruby_prof/rp_call_tree.c +353 -0
  13. data/ext/ruby_prof/rp_call_tree.h +43 -0
  14. data/ext/ruby_prof/rp_call_trees.c +266 -0
  15. data/ext/ruby_prof/rp_call_trees.h +29 -0
  16. data/ext/ruby_prof/rp_measure_allocations.c +25 -51
  17. data/ext/ruby_prof/rp_measure_memory.c +21 -56
  18. data/ext/ruby_prof/rp_measure_process_time.c +37 -43
  19. data/ext/ruby_prof/rp_measure_wall_time.c +40 -21
  20. data/ext/ruby_prof/rp_measurement.c +221 -0
  21. data/ext/ruby_prof/rp_measurement.h +50 -0
  22. data/ext/ruby_prof/rp_method.c +279 -439
  23. data/ext/ruby_prof/rp_method.h +33 -45
  24. data/ext/ruby_prof/rp_profile.c +902 -0
  25. data/ext/ruby_prof/rp_profile.h +36 -0
  26. data/ext/ruby_prof/rp_stack.c +163 -132
  27. data/ext/ruby_prof/rp_stack.h +18 -28
  28. data/ext/ruby_prof/rp_thread.c +192 -124
  29. data/ext/ruby_prof/rp_thread.h +18 -8
  30. data/ext/ruby_prof/ruby_prof.c +36 -778
  31. data/ext/ruby_prof/ruby_prof.h +11 -45
  32. data/ext/ruby_prof/vc/ruby_prof.vcxproj +18 -12
  33. data/lib/ruby-prof.rb +4 -21
  34. data/lib/ruby-prof/assets/call_stack_printer.html.erb +710 -0
  35. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  36. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
  37. data/lib/ruby-prof/call_tree.rb +57 -0
  38. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  39. data/lib/ruby-prof/compatibility.rb +37 -107
  40. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  41. data/lib/ruby-prof/measurement.rb +17 -0
  42. data/lib/ruby-prof/method_info.rb +47 -90
  43. data/lib/ruby-prof/printers/abstract_printer.rb +73 -50
  44. data/lib/ruby-prof/printers/call_info_printer.rb +24 -12
  45. data/lib/ruby-prof/printers/call_stack_printer.rb +66 -152
  46. data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
  47. data/lib/ruby-prof/printers/dot_printer.rb +5 -5
  48. data/lib/ruby-prof/printers/flat_printer.rb +6 -24
  49. data/lib/ruby-prof/printers/graph_html_printer.rb +6 -192
  50. data/lib/ruby-prof/printers/graph_printer.rb +11 -14
  51. data/lib/ruby-prof/printers/multi_printer.rb +66 -23
  52. data/lib/ruby-prof/profile.rb +10 -3
  53. data/lib/ruby-prof/thread.rb +5 -20
  54. data/lib/ruby-prof/version.rb +1 -1
  55. data/ruby-prof.gemspec +9 -2
  56. data/test/abstract_printer_test.rb +0 -27
  57. data/test/alias_test.rb +126 -0
  58. data/test/basic_test.rb +1 -86
  59. data/test/call_tree_visitor_test.rb +32 -0
  60. data/test/call_trees_test.rb +66 -0
  61. data/test/dynamic_method_test.rb +0 -2
  62. data/test/exclude_methods_test.rb +17 -12
  63. data/test/fiber_test.rb +214 -23
  64. data/test/gc_test.rb +105 -0
  65. data/test/inverse_call_tree_test.rb +175 -0
  66. data/test/line_number_test.rb +118 -40
  67. data/test/marshal_test.rb +115 -0
  68. data/test/measure_allocations.rb +30 -0
  69. data/test/measure_allocations_test.rb +361 -12
  70. data/test/measure_allocations_trace_test.rb +375 -0
  71. data/test/measure_memory_trace_test.rb +1101 -0
  72. data/test/measure_process_time_test.rb +757 -33
  73. data/test/measure_times.rb +56 -0
  74. data/test/measure_wall_time_test.rb +329 -149
  75. data/test/multi_printer_test.rb +1 -34
  76. data/test/pause_resume_test.rb +24 -15
  77. data/test/prime.rb +1 -1
  78. data/test/prime_script.rb +6 -0
  79. data/test/printer_call_stack_test.rb +28 -0
  80. data/test/printer_call_tree_test.rb +31 -0
  81. data/test/printer_flat_test.rb +68 -0
  82. data/test/printer_graph_html_test.rb +60 -0
  83. data/test/printer_graph_test.rb +41 -0
  84. data/test/printers_test.rb +32 -166
  85. data/test/printing_recursive_graph_test.rb +26 -72
  86. data/test/recursive_test.rb +68 -77
  87. data/test/stack_printer_test.rb +2 -15
  88. data/test/start_stop_test.rb +22 -25
  89. data/test/test_helper.rb +6 -261
  90. data/test/thread_test.rb +11 -54
  91. data/test/unique_call_path_test.rb +25 -107
  92. data/test/yarv_test.rb +1 -0
  93. metadata +43 -41
  94. data/examples/flat.txt +0 -50
  95. data/examples/graph.dot +0 -84
  96. data/examples/graph.html +0 -823
  97. data/examples/graph.txt +0 -139
  98. data/examples/multi.flat.txt +0 -23
  99. data/examples/multi.graph.html +0 -760
  100. data/examples/multi.grind.dat +0 -114
  101. data/examples/multi.stack.html +0 -547
  102. data/examples/stack.html +0 -547
  103. data/ext/ruby_prof/rp_call_info.c +0 -425
  104. data/ext/ruby_prof/rp_call_info.h +0 -53
  105. data/ext/ruby_prof/rp_measure.c +0 -40
  106. data/ext/ruby_prof/rp_measure.h +0 -45
  107. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
  108. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
  109. data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
  110. data/lib/ruby-prof/aggregate_call_info.rb +0 -76
  111. data/lib/ruby-prof/assets/call_stack_printer.css.html +0 -117
  112. data/lib/ruby-prof/assets/call_stack_printer.js.html +0 -385
  113. data/lib/ruby-prof/call_info.rb +0 -115
  114. data/lib/ruby-prof/call_info_visitor.rb +0 -40
  115. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
  116. data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
  117. data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
  118. data/test/aggregate_test.rb +0 -136
  119. data/test/block_test.rb +0 -74
  120. data/test/call_info_test.rb +0 -78
  121. data/test/call_info_visitor_test.rb +0 -31
  122. data/test/issue137_test.rb +0 -63
  123. data/test/measure_cpu_time_test.rb +0 -212
  124. data/test/measure_gc_runs_test.rb +0 -32
  125. data/test/measure_gc_time_test.rb +0 -36
  126. data/test/measure_memory_test.rb +0 -33
  127. data/test/method_elimination_test.rb +0 -84
  128. data/test/module_test.rb +0 -45
  129. data/test/stack_test.rb +0 -138
@@ -1,267 +1,12 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require "rubygems"
4
- gem "minitest"
5
-
6
- # To make testing/debugging easier, test within this source tree versus an installed gem
7
- dir = File.dirname(__FILE__)
8
- root = File.expand_path(File.join(dir, '..'))
9
- lib = File.expand_path(File.join(root, 'lib'))
10
- ext = File.expand_path(File.join(root, 'ext', 'ruby_prof'))
11
-
12
- $LOAD_PATH << lib
13
- $LOAD_PATH << ext
14
-
15
- require 'ruby-prof'
16
-
17
- # stub deprecation warnings
18
- module RubyProf
19
- module SuppressDeprecationWarnings
20
- def deprecation_warning(*args)
21
- super if ENV['SHOW_RUBY_PROF_DEPRECATION_WARNINGS'] == '1'
22
- end
23
- end
24
- extend SuppressDeprecationWarnings
25
- end
3
+ # Disable minitest parallel tests. The problem is the thread switching will cahnge test results
4
+ # (self vs wait time)
5
+ ENV["N"] = "0"
26
6
 
7
+ require 'bundler/setup'
27
8
  require 'minitest/autorun'
9
+ require 'ruby-prof'
28
10
 
29
11
  class TestCase < Minitest::Test
30
- # I know this sucks, but ...
31
- def assert_nothing_raised(*)
32
- yield
33
- end
34
-
35
- def before_setup
36
- # make sure to exclude all threads except the one running the test
37
- # minitest allocates a thread pool and they would otherwise show
38
- # up in the profile data, breaking tests randomly
39
- RubyProf.exclude_threads = Thread.list.select{|t| t != Thread.current}
40
- end
41
-
42
- def after_teardown
43
- # reset exclude threads after testing
44
- RubyProf.exclude_threads = nil
45
- end
46
- end
47
-
48
- require File.expand_path('../prime', __FILE__)
49
-
50
- # Some classes used in measurement tests
51
- module RubyProf
52
- class C1
53
- def C1.hello
54
- sleep(0.1)
55
- end
56
-
57
- def hello
58
- sleep(0.2)
59
- end
60
- end
61
-
62
- module M1
63
- def hello
64
- sleep(0.3)
65
- end
66
- end
67
-
68
- class C2
69
- include M1
70
- extend M1
71
- end
72
-
73
- class C3
74
- def hello
75
- sleep(0.4)
76
- end
77
- end
78
-
79
- module M4
80
- def hello
81
- sleep(0.5)
82
- end
83
- end
84
-
85
- module M5
86
- include M4
87
- def goodbye
88
- hello
89
- end
90
- end
91
-
92
- class C6
93
- include M5
94
- def test
95
- goodbye
96
- end
97
- end
98
-
99
- class C7
100
- def self.busy_wait
101
- t = Time.now.to_f
102
- while Time.now.to_f - t < 0.1; end
103
- end
104
-
105
- def self.sleep_wait
106
- sleep 0.1
107
- end
108
-
109
- def busy_wait
110
- t = Time.now.to_f
111
- while Time.now.to_f - t < 0.2; end
112
- end
113
-
114
- def sleep_wait
115
- sleep 0.2
116
- end
117
- end
118
-
119
- module M7
120
- def busy_wait
121
- t = Time.now.to_f
122
- while Time.now.to_f - t < 0.3; end
123
- end
124
-
125
- def sleep_wait
126
- sleep 0.3
127
- end
128
- end
129
-
130
- class C8
131
- include M7
132
- extend M7
133
- end
134
-
135
- def self.ruby_major_version
136
- match = RUBY_VERSION.match(/(\d)\.(\d)/)
137
- return Integer(match[1])
138
- end
139
-
140
- def self.ruby_minor_version
141
- match = RUBY_VERSION.match(/(\d)\.(\d)/)
142
- return Integer(match[2])
143
- end
144
-
145
- def self.parent_object
146
- if ruby_major_version == 1 && ruby_minor_version == 8
147
- Object
148
- else
149
- BasicObject
150
- end
151
- end
152
-
153
- def self.ruby_2?
154
- ruby_major_version == 2
155
- end
156
-
157
- # store printer output in this directory
158
- def self.tmpdir
159
- path = File.expand_path('../../tmp', __FILE__)
160
- unless Dir.exist?(path)
161
- Dir.mkdir(path)
162
- end
163
- path
164
- end
165
- end
166
-
167
- module MemoryTestHelper
168
- def memory_test_helper
169
- result = RubyProf.profile {Array.new}
170
- total = result.threads.first.methods.inject(0) { |sum, m| sum + m.total_time }
171
- assert(total < 1_000_000, 'Total should not have subtract overflow error')
172
- total
173
- end
174
- end
175
-
176
- module PrinterTestHelper
177
- Metrics = Struct.new(:name, :total, :self_t, :wait, :child, :calls)
178
- class Metrics
179
- def pp
180
- "%s[total: %.2f, self: %.2f, wait: %.2f, child: %.2f, calls: %s]" %
181
- [name, total, self_t, wait, child, calls]
182
- end
183
- end
184
-
185
- Entry = Struct.new(:total_p, :self_p, :metrics, :parents, :children)
186
- class Entry
187
- def child(name)
188
- children.detect{|m| m.name == name}
189
- end
190
-
191
- def parent(name)
192
- parents.detect{|m| m.name == name}
193
- end
194
-
195
- def pp
196
- res = ""
197
- res << "NODE (total%%: %.2f, self%%: %.2f) %s\n" % [total_p, self_p, metrics.pp]
198
- res << " PARENTS:\n"
199
- parents.each {|m| res << " " + m.pp << "\n"}
200
- res << " CHILDREN:\n"
201
- children.each {|m| res << " " + m.pp << "\n"}
202
- res
203
- end
204
- end
205
-
206
- class MetricsArray < Array
207
- def metrics_for(name)
208
- detect {|e| e.metrics.name == name}
209
- end
210
-
211
- def pp(io = STDOUT)
212
- entries = map do |e|
213
- begin
214
- e.pp
215
- rescue
216
- puts $!.message + e.inspect
217
- ""
218
- end
219
- end
220
- io.puts entries.join("--------------------------------------------------\n")
221
- end
222
-
223
- def self.parse(str)
224
- res = new
225
- entry = nil
226
- relatives = []
227
- state = :preamble
228
-
229
- str.each_line do |l|
230
- line = l.chomp.strip
231
- if line =~ /-----/
232
- if state == :preamble
233
- state = :parsing_parents
234
- entry = Entry.new
235
- elsif state == :parsing_parents
236
- entry = Entry.new
237
- elsif state == :parsing_children
238
- entry.children = relatives
239
- res << entry
240
- entry = Entry.new
241
- relatives = []
242
- state = :parsing_parents
243
- end
244
- elsif line =~ /^\s*$/ || line =~ /indicates recursively called methods/
245
- next
246
- elsif state != :preamble
247
- elements = line.split(/\s+/)
248
- method = elements.pop
249
- numbers = elements[0..-2].map(&:to_f)
250
- metrics = Metrics.new(method, *numbers[-4..-1], elements[-1])
251
- if numbers.size == 6
252
- entry.metrics = metrics
253
- entry.total_p = numbers[0]
254
- entry.self_p = numbers[1]
255
- entry.parents = relatives
256
- entry.children = relatives = []
257
- state = :parsing_children
258
- res << entry
259
- else
260
- relatives << metrics
261
- end
262
- end
263
- end
264
- res
265
- end
266
- end
267
- end
12
+ end
@@ -75,10 +75,7 @@ class ThreadTest < TestCase
75
75
  assert_in_delta(0, method.self_time, 0.05)
76
76
  assert_in_delta(0, method.wait_time, 0.05)
77
77
  assert_in_delta(1, method.children_time, 0.05)
78
- assert_equal(1, method.call_infos.length)
79
- call_info = method.call_infos[0]
80
- assert_equal('ThreadTest#test_thread_timings', call_info.call_sequence)
81
- assert_equal(1, call_info.children.length)
78
+ assert_equal(0, method.call_trees.callers.length)
82
79
 
83
80
  method = methods[1]
84
81
  assert_equal('Kernel#sleep', method.full_name)
@@ -88,10 +85,8 @@ class ThreadTest < TestCase
88
85
  assert_in_delta(0, method.wait_time, 0.05)
89
86
  assert_in_delta(0, method.children_time, 0.05)
90
87
 
91
- assert_equal(1, method.call_infos.length)
92
- call_info = method.call_infos[0]
93
- assert_equal('ThreadTest#test_thread_timings->Kernel#sleep', call_info.call_sequence)
94
- assert_equal(0, call_info.children.length)
88
+ assert_equal(1, method.call_trees.callers.length)
89
+ assert_equal(0, method.call_trees.callees.length)
95
90
 
96
91
  # Check foreground thread
97
92
  rp_thread = result.threads.detect {|athread| athread.id == Thread.current.object_id}
@@ -110,10 +105,8 @@ class ThreadTest < TestCase
110
105
  assert_in_delta(0, method.wait_time, 0.05)
111
106
  assert_in_delta(1, method.children_time, 0.05)
112
107
 
113
- assert_equal(1, method.call_infos.length)
114
- call_info = method.call_infos[0]
115
- assert_equal('ThreadTest#test_thread_timings', call_info.call_sequence)
116
- assert_equal(2, call_info.children.length)
108
+ assert_equal(0, method.call_trees.callers.length)
109
+ assert_equal(2, method.call_trees.callees.length)
117
110
 
118
111
  method = methods[1]
119
112
  assert_equal('Thread#join', method.full_name)
@@ -123,10 +116,8 @@ class ThreadTest < TestCase
123
116
  assert_in_delta(1.0, method.wait_time, 0.05)
124
117
  assert_in_delta(0, method.children_time, 0.05)
125
118
 
126
- assert_equal(1, method.call_infos.length)
127
- call_info = method.call_infos[0]
128
- assert_equal('ThreadTest#test_thread_timings->Thread#join', call_info.call_sequence)
129
- assert_equal(0, call_info.children.length)
119
+ assert_equal(1, method.call_trees.callers.length)
120
+ assert_equal(0, method.call_trees.callees.length)
130
121
 
131
122
  method = methods[2]
132
123
  assert_equal('<Class::Thread>#new', method.full_name)
@@ -136,10 +127,8 @@ class ThreadTest < TestCase
136
127
  assert_in_delta(0, method.wait_time, 0.05)
137
128
  assert_in_delta(0, method.children_time, 0.05)
138
129
 
139
- assert_equal(1, method.call_infos.length)
140
- call_info = method.call_infos[0]
141
- assert_equal('ThreadTest#test_thread_timings-><Class::Thread>#new', call_info.call_sequence)
142
- assert_equal(1, call_info.children.length)
130
+ assert_equal(1, method.call_trees.callers.length)
131
+ assert_equal(1, method.call_trees.callees.length)
143
132
 
144
133
  method = methods[3]
145
134
  assert_equal('Thread#initialize', method.full_name)
@@ -149,39 +138,7 @@ class ThreadTest < TestCase
149
138
  assert_in_delta(0, method.wait_time, 0.05)
150
139
  assert_in_delta(0, method.children_time, 0.05)
151
140
 
152
- assert_equal(1, method.call_infos.length)
153
- call_info = method.call_infos[0]
154
- assert_equal('ThreadTest#test_thread_timings-><Class::Thread>#new->Thread#initialize', call_info.call_sequence)
155
- assert_equal(0, call_info.children.length)
156
- end
157
-
158
- # useless test: what does it test?
159
- def test_thread_back_and_forth
160
- result = nil
161
- seconds = Benchmark.realtime do
162
- result = RubyProf.profile do
163
- a = Thread.new { 100_000.times { sleep 0 }}
164
- b = Thread.new { 100_000.times { sleep 0 }}
165
- a.join
166
- b.join
167
- end
168
- end
169
- methods = result.threads.map {|thread| thread.methods}
170
- timings = methods.flatten.sort
171
- assert(timings[-1].total_time < seconds)
172
- end
173
-
174
- # useless test: what does it test?
175
- def test_thread
176
- RubyProf.profile do
177
- begin
178
- Timeout::timeout(2) do
179
- while true
180
- next
181
- end
182
- end
183
- rescue Timeout::Error
184
- end
185
- end
141
+ assert_equal(1, method.call_trees.callers.length)
142
+ assert_equal(0, method.call_trees.callees.length)
186
143
  end
187
144
  end
@@ -27,24 +27,15 @@ end
27
27
 
28
28
  # -- Tests ----
29
29
  class UniqueCallPathTest < TestCase
30
- def test_root_method
30
+ def test_root
31
31
  unique_call_path = UniqueCallPath.new
32
32
 
33
33
  result = RubyProf.profile do
34
34
  unique_call_path.method_a(1)
35
35
  end
36
36
 
37
- root_methods = Array.new
38
- result.threads.each do |thread|
39
- thread.methods.each do | m |
40
- if m.root?
41
- root_methods.push(m)
42
- end
43
- end
44
- end
45
-
46
- assert_equal(1, root_methods.length)
47
- assert_equal("UniqueCallPathTest#test_root_method", root_methods[0].full_name)
37
+ root_call_info = result.threads.first.call_tree
38
+ assert_equal("UniqueCallPathTest#test_root", root_call_info.target.full_name)
48
39
  end
49
40
 
50
41
  def test_root_children
@@ -55,25 +46,8 @@ class UniqueCallPathTest < TestCase
55
46
  unique_call_path.method_k(2)
56
47
  end
57
48
 
58
- root_methods = Array.new
59
- result.threads.each do |thread|
60
- thread.methods.each do | m |
61
- if m.root?
62
- root_methods.push(m)
63
- end
64
- end
65
- end
66
-
67
- assert_equal(1, root_methods.length)
68
-
69
- root_children = Array.new
70
- root_methods[0].children.each do | c |
71
- if c.parent.target.eql?(root_methods[0])
72
- root_children.push(c)
73
- end
74
- end
75
-
76
- children = root_children.sort do |c1, c2|
49
+ root_call_info = result.threads.first.call_tree
50
+ children = root_call_info.children.sort do |c1, c2|
77
51
  c1.target.full_name <=> c2.target.full_name
78
52
  end
79
53
 
@@ -90,67 +64,23 @@ class UniqueCallPathTest < TestCase
90
64
  unique_call_path.method_k(2)
91
65
  end
92
66
 
93
- root_methods = Array.new
94
- result.threads.each do |thread|
95
- thread.methods.each do | m |
96
- if m.root?
97
- root_methods.push(m)
98
- end
99
- end
100
- end
101
-
102
- assert_equal(1, root_methods.length)
103
- method = root_methods[0]
104
- assert_equal('UniqueCallPathTest#test_children_of', method.full_name)
67
+ root_call_info = result.threads.first.call_tree
68
+ assert_equal("UniqueCallPathTest#test_children_of", root_call_info.target.full_name)
105
69
 
106
- call_info_a = nil
107
- root_methods[0].children.each do | c |
108
- if c.target.full_name == "UniqueCallPath#method_a"
109
- call_info_a = c
110
- break
111
- end
70
+ call_info_a = root_call_info.children.detect do |call_tree|
71
+ call_tree.target.full_name == "UniqueCallPath#method_a"
112
72
  end
73
+ refute_nil(call_info_a)
113
74
 
114
- assert !call_info_a.nil?
115
-
116
- children_of_a = Array.new
117
-
118
- call_info_a.children.each do | c |
75
+ children_of_a = call_info_a.children.inject(Array.new) do |array, c|
119
76
  if c.parent.eql?(call_info_a)
120
- children_of_a.push(c)
77
+ array << c
121
78
  end
79
+ array
122
80
  end
123
81
 
124
- assert_equal(2, call_info_a.target.children.length)
125
-
126
- children_of_a = children_of_a.sort do |c1, c2|
127
- c1.target.full_name <=> c2.target.full_name
128
- end
129
-
130
- assert_equal(1, children_of_a.length)
131
- assert_equal("UniqueCallPath#method_b", children_of_a[0].target.full_name)
132
- end
133
-
134
- def test_id2ref
135
- unique_call_path = UniqueCallPath.new
136
-
137
- result = RubyProf.profile do
138
- unique_call_path.method_a(1)
139
- end
140
-
141
- root_methods = Array.new
142
- result.threads.each do |thread|
143
- thread.methods.each do | m |
144
- if m.root?
145
- root_methods.push(m)
146
- end
147
- end
148
- end
149
-
150
- child = root_methods[0].children[0]
151
-
152
- refute_equal(0, child.object_id)
153
- #assert_equal(RubyProf::CallInfo.id2ref(child.id).target.full_name, child.target.full_name)
82
+ assert_equal(1, call_info_a.children.length)
83
+ assert_equal("UniqueCallPath#method_b", call_info_a.children.first.target.full_name)
154
84
  end
155
85
 
156
86
  def test_unique_path
@@ -161,35 +91,23 @@ class UniqueCallPathTest < TestCase
161
91
  unique_call_path.method_k(1)
162
92
  end
163
93
 
164
- root_methods = Array.new
165
- result.threads.each do |thread|
166
- thread.methods.each do | m |
167
- if m.root?
168
- root_methods.push(m)
169
- end
170
- end
171
- end
172
-
173
- assert_equal(1, root_methods.length)
94
+ root_call_info = result.threads.first.call_tree
95
+ assert_equal("UniqueCallPathTest#test_unique_path", root_call_info.target.full_name)
174
96
 
175
- call_info_a = nil
176
- root_methods[0].children.each do | c |
177
- if c.target.full_name == "UniqueCallPath#method_a"
178
- call_info_a = c
179
- break
180
- end
97
+ call_info_a = root_call_info.children.detect do |call_tree|
98
+ call_tree.target.full_name == "UniqueCallPath#method_a"
181
99
  end
100
+ refute_nil(call_info_a)
182
101
 
183
- assert !call_info_a.nil?
184
-
185
- children_of_a = Array.new
186
- call_info_a.children.each do |c|
102
+ children_of_a = call_info_a.children.reduce(Array.new) do |array, c|
187
103
  if c.parent.eql?(call_info_a)
188
- children_of_a.push(c)
104
+ array << c
189
105
  end
106
+ array
190
107
  end
191
108
 
192
- assert_equal(2, call_info_a.target.children.length)
109
+ assert_equal(1, call_info_a.children.length)
110
+ assert_equal(1, children_of_a.length)
193
111
 
194
112
  children_of_a = children_of_a.sort do |c1, c2|
195
113
  c1.target.full_name <=> c2.target.full_name