airbnb-ruby-prof 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. data/CHANGES +483 -0
  2. data/LICENSE +25 -0
  3. data/README.rdoc +426 -0
  4. data/Rakefile +51 -0
  5. data/bin/ruby-prof +279 -0
  6. data/bin/ruby-prof-check-trace +45 -0
  7. data/examples/flat.txt +50 -0
  8. data/examples/graph.dot +84 -0
  9. data/examples/graph.html +823 -0
  10. data/examples/graph.txt +139 -0
  11. data/examples/multi.flat.txt +23 -0
  12. data/examples/multi.graph.html +760 -0
  13. data/examples/multi.grind.dat +114 -0
  14. data/examples/multi.stack.html +547 -0
  15. data/examples/stack.html +547 -0
  16. data/ext/ruby_prof/extconf.rb +67 -0
  17. data/ext/ruby_prof/rp_call_info.c +374 -0
  18. data/ext/ruby_prof/rp_call_info.h +59 -0
  19. data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
  20. data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
  21. data/ext/ruby_prof/rp_measure.c +71 -0
  22. data/ext/ruby_prof/rp_measure.h +56 -0
  23. data/ext/ruby_prof/rp_measure_allocations.c +74 -0
  24. data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
  25. data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
  26. data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
  27. data/ext/ruby_prof/rp_measure_memory.c +75 -0
  28. data/ext/ruby_prof/rp_measure_process_time.c +69 -0
  29. data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
  30. data/ext/ruby_prof/rp_method.c +717 -0
  31. data/ext/ruby_prof/rp_method.h +79 -0
  32. data/ext/ruby_prof/rp_stack.c +221 -0
  33. data/ext/ruby_prof/rp_stack.h +81 -0
  34. data/ext/ruby_prof/rp_thread.c +312 -0
  35. data/ext/ruby_prof/rp_thread.h +36 -0
  36. data/ext/ruby_prof/ruby_prof.c +800 -0
  37. data/ext/ruby_prof/ruby_prof.h +64 -0
  38. data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
  39. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
  40. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
  41. data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
  42. data/lib/ruby-prof.rb +63 -0
  43. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  45. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  46. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  47. data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
  48. data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
  49. data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
  50. data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
  51. data/lib/ruby-prof/call_info.rb +111 -0
  52. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  53. data/lib/ruby-prof/compatibility.rb +186 -0
  54. data/lib/ruby-prof/method_info.rb +109 -0
  55. data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
  56. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  57. data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
  58. data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
  59. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  60. data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
  61. data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
  62. data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
  63. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  64. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
  65. data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
  66. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  67. data/lib/ruby-prof/printers/multi_printer.rb +58 -0
  68. data/lib/ruby-prof/profile.rb +22 -0
  69. data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
  70. data/lib/ruby-prof/rack.rb +95 -0
  71. data/lib/ruby-prof/task.rb +147 -0
  72. data/lib/ruby-prof/thread.rb +35 -0
  73. data/lib/ruby-prof/version.rb +4 -0
  74. data/lib/ruby-prof/walker.rb +95 -0
  75. data/lib/unprof.rb +10 -0
  76. data/ruby-prof.gemspec +56 -0
  77. data/test/aggregate_test.rb +136 -0
  78. data/test/basic_test.rb +128 -0
  79. data/test/block_test.rb +74 -0
  80. data/test/call_info_test.rb +78 -0
  81. data/test/call_info_visitor_test.rb +31 -0
  82. data/test/duplicate_names_test.rb +32 -0
  83. data/test/dynamic_method_test.rb +55 -0
  84. data/test/enumerable_test.rb +21 -0
  85. data/test/exceptions_test.rb +16 -0
  86. data/test/exclude_methods_test.rb +146 -0
  87. data/test/exclude_threads_test.rb +53 -0
  88. data/test/fiber_test.rb +79 -0
  89. data/test/issue137_test.rb +63 -0
  90. data/test/line_number_test.rb +71 -0
  91. data/test/measure_allocations_test.rb +26 -0
  92. data/test/measure_cpu_time_test.rb +213 -0
  93. data/test/measure_gc_runs_test.rb +32 -0
  94. data/test/measure_gc_time_test.rb +36 -0
  95. data/test/measure_memory_test.rb +33 -0
  96. data/test/measure_process_time_test.rb +63 -0
  97. data/test/measure_wall_time_test.rb +255 -0
  98. data/test/module_test.rb +45 -0
  99. data/test/multi_measure_test.rb +38 -0
  100. data/test/multi_printer_test.rb +83 -0
  101. data/test/no_method_class_test.rb +15 -0
  102. data/test/pause_resume_test.rb +166 -0
  103. data/test/prime.rb +54 -0
  104. data/test/printers_test.rb +255 -0
  105. data/test/printing_recursive_graph_test.rb +127 -0
  106. data/test/rack_test.rb +93 -0
  107. data/test/recursive_test.rb +212 -0
  108. data/test/singleton_test.rb +38 -0
  109. data/test/stack_printer_test.rb +65 -0
  110. data/test/stack_test.rb +138 -0
  111. data/test/start_stop_test.rb +112 -0
  112. data/test/test_helper.rb +264 -0
  113. data/test/thread_test.rb +187 -0
  114. data/test/unique_call_path_test.rb +202 -0
  115. data/test/yarv_test.rb +55 -0
  116. metadata +211 -0
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class MeasureGCRunsTest < TestCase
7
+ include MemoryTestHelper
8
+
9
+ def test_gc_runs_mode
10
+ RubyProf::measure_mode = RubyProf::GC_RUNS
11
+ assert_equal(RubyProf::GC_RUNS, RubyProf::measure_mode)
12
+ end
13
+
14
+ def test_gc_runs_enabled_defined
15
+ assert(defined?(RubyProf::GC_RUNS_ENABLED))
16
+ end
17
+
18
+ if RubyProf::GC_RUNS_ENABLED
19
+ def test_gc_runs
20
+ t = RubyProf.measure_gc_runs
21
+ assert_kind_of Integer, t
22
+
23
+ GC.enable_stats if GC.respond_to?(:enable_stats)
24
+ GC.start
25
+
26
+ u = RubyProf.measure_gc_runs
27
+ assert u > t, [t, u].inspect
28
+ RubyProf::measure_mode = RubyProf::GC_RUNS
29
+ memory_test_helper
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class MeasureGCTimeTest < TestCase
7
+ include MemoryTestHelper
8
+
9
+ def test_gc_time_mode
10
+ RubyProf::measure_mode = RubyProf::GC_TIME
11
+ assert_equal(RubyProf::GC_TIME, RubyProf::measure_mode)
12
+ end
13
+
14
+ def test_gc_time_enabled_defined
15
+ assert(defined?(RubyProf::GC_TIME_ENABLED))
16
+ end
17
+
18
+ if RubyProf::GC_TIME_ENABLED
19
+ def test_gc_time
20
+ RubyProf::measure_mode = RubyProf::GC_TIME
21
+ RubyProf.enable_gc_stats_if_needed
22
+
23
+ t = RubyProf.measure_gc_time
24
+ assert_kind_of Float, t
25
+
26
+ GC.start
27
+
28
+ u = RubyProf.measure_gc_time
29
+ assert u > t, [t, u].inspect
30
+
31
+ memory_test_helper
32
+ ensure
33
+ RubyProf.disable_gc_stats_if_needed
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class MeasureMemoryTest < TestCase
7
+ include MemoryTestHelper
8
+
9
+ def test_memory_mode
10
+ RubyProf::measure_mode = RubyProf::MEMORY
11
+ assert_equal(RubyProf::MEMORY, RubyProf::measure_mode)
12
+ end
13
+
14
+ def test_memory_enabled_defined
15
+ assert(defined?(RubyProf::MEMORY_ENABLED))
16
+ end
17
+
18
+ if RubyProf::MEMORY_ENABLED
19
+ def test_memory
20
+ RubyProf::measure_mode = RubyProf::MEMORY
21
+ RubyProf.enable_gc_stats_if_needed
22
+ t = RubyProf.measure_memory
23
+ assert_kind_of Float, t
24
+ u = RubyProf.measure_memory
25
+ assert_operator u, :>, t
26
+ total = memory_test_helper
27
+ assert(total > 0, 'Should measure more than zero kilobytes of memory usage')
28
+ refute_equal(0, total % 1, 'Should not truncate fractional kilobyte measurements')
29
+ ensure
30
+ RubyProf.disable_gc_stats_if_needed
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class MeasureProcessTimeTest < TestCase
7
+ def setup
8
+ # Need to fix this for linux (windows works since PROCESS_TIME is WALL_TIME anyway)
9
+ RubyProf::measure_mode = RubyProf::PROCESS_TIME
10
+ end
11
+
12
+ def test_mode
13
+ assert_equal(RubyProf::PROCESS_TIME, RubyProf::measure_mode)
14
+ end
15
+
16
+ def test_process_time_enabled_defined
17
+ assert(defined?(RubyProf::PROCESS_TIME_ENABLED))
18
+ end
19
+
20
+ def test_primes
21
+ start = Process.times
22
+ result = RubyProf.profile do
23
+ run_primes(10000)
24
+ end
25
+ finish = Process.times
26
+
27
+ total_time = (finish.utime - start.utime) + (finish.stime - start.stime)
28
+
29
+ thread = result.threads.first
30
+ assert_in_delta(total_time, thread.total_time, 0.03)
31
+
32
+ methods = result.threads.first.methods.sort.reverse
33
+
34
+ expected_number_of_methods =
35
+ case RUBY_VERSION
36
+ when /^1\.9\.3/ then 16
37
+ when /^2\.0/ then 15
38
+ when /^2\.(1|2)/ then 14
39
+ else 13
40
+ end
41
+ # puts methods.map(&:full_name).inspect
42
+ assert_equal expected_number_of_methods, methods.length
43
+
44
+ # Check times
45
+ assert_equal("MeasureProcessTimeTest#test_primes", methods[0].full_name)
46
+ assert_in_delta(total_time, methods[0].total_time, 0.02)
47
+ assert_in_delta(0.0, methods[0].wait_time, 0.01)
48
+ assert_in_delta(0.0, methods[0].self_time, 0.01)
49
+
50
+ assert_equal("Object#run_primes", methods[1].full_name)
51
+ assert_in_delta(total_time, methods[1].total_time, 0.02)
52
+ assert_in_delta(0.0, methods[1].wait_time, 0.01)
53
+ assert_in_delta(0.0, methods[1].self_time, 0.01)
54
+
55
+ assert_equal("Object#find_primes", methods[2].full_name)
56
+ assert_equal("Array#select", methods[3].full_name)
57
+ assert_equal("Object#is_prime", methods[4].full_name)
58
+ assert_equal("Integer#upto", methods[5].full_name)
59
+ assert_equal("Object#make_random_array", methods[6].full_name)
60
+ assert_equal("Array#each_index", methods[7].full_name)
61
+ assert_equal("Kernel#rand", methods[8].full_name)
62
+ end
63
+ end
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class MeasureWallTimeTest < TestCase
7
+ def setup
8
+ # Need to use wall time for this test due to the sleep calls
9
+ RubyProf::measure_mode = RubyProf::WALL_TIME
10
+ end
11
+
12
+ def test_mode
13
+ RubyProf::measure_mode = RubyProf::WALL_TIME
14
+ assert_equal(RubyProf::WALL_TIME, RubyProf::measure_mode)
15
+ end
16
+
17
+ def test_wall_time_enabled_defined
18
+ assert(defined?(RubyProf::WALL_TIME_ENABLED))
19
+ end
20
+
21
+ def test_class_methods
22
+ result = RubyProf.profile do
23
+ RubyProf::C1.hello
24
+ end
25
+
26
+ thread = result.threads.first
27
+ assert_in_delta(0.1, thread.total_time, 0.01)
28
+
29
+ top_methods = thread.top_methods
30
+ assert_equal(1, top_methods.count)
31
+ assert_equal("MeasureWallTimeTest#test_class_methods", top_methods[0].full_name)
32
+
33
+ # Length should be 3:
34
+ # MeasureWallTimeTest#test_class_methods
35
+ # <Class::RubyProf::C1>#hello
36
+ # Kernel#sleep
37
+
38
+ methods = result.threads.first.methods.sort.reverse
39
+ assert_equal(3, methods.length)
40
+
41
+ # Check the names
42
+ assert_equal('MeasureWallTimeTest#test_class_methods', methods[0].full_name)
43
+ assert_equal('<Class::RubyProf::C1>#hello', methods[1].full_name)
44
+ assert_equal('Kernel#sleep', methods[2].full_name)
45
+
46
+ # Check times
47
+ assert_in_delta(0.1, methods[0].total_time, 0.01)
48
+ assert_in_delta(0, methods[0].wait_time, 0.01)
49
+ assert_in_delta(0, methods[0].self_time, 0.01)
50
+
51
+ assert_in_delta(0.1, methods[1].total_time, 0.01)
52
+ assert_in_delta(0, methods[1].wait_time, 0.01)
53
+ assert_in_delta(0, methods[1].self_time, 0.01)
54
+
55
+ assert_in_delta(0.1, methods[2].total_time, 0.01)
56
+ assert_in_delta(0, methods[2].wait_time, 0.01)
57
+ assert_in_delta(0.1, methods[2].self_time, 0.01)
58
+ end
59
+
60
+ def test_instance_methods
61
+ result = RubyProf.profile do
62
+ RubyProf::C1.new.hello
63
+ end
64
+
65
+ thread = result.threads.first
66
+ assert_in_delta(0.2, thread.total_time, 0.01)
67
+
68
+ top_methods = thread.top_methods
69
+ assert_equal(1, top_methods.count)
70
+ assert_equal("MeasureWallTimeTest#test_instance_methods", top_methods[0].full_name)
71
+
72
+ # Methods called
73
+ # MeasureWallTimeTest#test_instance_methods
74
+ # Class.new
75
+ # Class:Object#allocate
76
+ # for Object#initialize
77
+ # C1#hello
78
+ # Kernel#sleep
79
+
80
+ methods = result.threads.first.methods.sort.reverse
81
+ assert_equal(RubyProf.ruby_2? ? 5 : 6, methods.length)
82
+ names = methods.map(&:full_name)
83
+ assert_equal('MeasureWallTimeTest#test_instance_methods', names[0])
84
+ assert_equal('RubyProf::C1#hello', names[1])
85
+ assert_equal('Kernel#sleep', names[2])
86
+ assert_equal('Class#new', names[3])
87
+
88
+ # order can differ
89
+ assert(names.include?("#{RubyProf.parent_object}#initialize"))
90
+ unless RubyProf.ruby_2?
91
+ assert(names.include?("<Class::#{RubyProf.parent_object}>#allocate"))
92
+ end
93
+
94
+ # Check times
95
+ assert_in_delta(0.2, methods[0].total_time, 0.02)
96
+ assert_in_delta(0, methods[0].wait_time, 0.02)
97
+ assert_in_delta(0, methods[0].self_time, 0.02)
98
+
99
+ assert_in_delta(0.2, methods[1].total_time, 0.02)
100
+ assert_in_delta(0, methods[1].wait_time, 0.02)
101
+ assert_in_delta(0, methods[1].self_time, 0.02)
102
+
103
+ assert_in_delta(0.2, methods[2].total_time, 0.02)
104
+ assert_in_delta(0, methods[2].wait_time, 0.02)
105
+ assert_in_delta(0.2, methods[2].self_time, 0.02)
106
+
107
+ assert_in_delta(0, methods[3].total_time, 0.01)
108
+ assert_in_delta(0, methods[3].wait_time, 0.01)
109
+ assert_in_delta(0, methods[3].self_time, 0.01)
110
+
111
+ assert_in_delta(0, methods[4].total_time, 0.01)
112
+ assert_in_delta(0, methods[4].wait_time, 0.01)
113
+ assert_in_delta(0, methods[4].self_time, 0.01)
114
+
115
+ unless RubyProf.ruby_2?
116
+ assert_in_delta(0, methods[5].total_time, 0.01)
117
+ assert_in_delta(0, methods[5].wait_time, 0.01)
118
+ assert_in_delta(0, methods[5].self_time, 0.01)
119
+ end
120
+ end
121
+
122
+ def test_module_methods
123
+ result = RubyProf.profile do
124
+ RubyProf::C2.hello
125
+ end
126
+
127
+ thread = result.threads.first
128
+ assert_in_delta(0.3, thread.total_time, 0.01)
129
+
130
+ top_methods = thread.top_methods
131
+ assert_equal(1, top_methods.count)
132
+ assert_equal("MeasureWallTimeTest#test_module_methods", top_methods[0].full_name)
133
+
134
+ # Methods:
135
+ # MeasureWallTimeTest#test_module_methods
136
+ # M1#hello
137
+ # Kernel#sleep
138
+
139
+ methods = result.threads.first.methods.sort.reverse
140
+ assert_equal(3, methods.length)
141
+
142
+ assert_equal('MeasureWallTimeTest#test_module_methods', methods[0].full_name)
143
+ assert_equal('RubyProf::M1#hello', methods[1].full_name)
144
+ assert_equal('Kernel#sleep', methods[2].full_name)
145
+
146
+ # Check times
147
+ assert_in_delta(0.3, methods[0].total_time, 0.1)
148
+ assert_in_delta(0, methods[0].wait_time, 0.02)
149
+ assert_in_delta(0, methods[0].self_time, 0.02)
150
+
151
+ assert_in_delta(0.3, methods[1].total_time, 0.1)
152
+ assert_in_delta(0, methods[1].wait_time, 0.02)
153
+ assert_in_delta(0, methods[1].self_time, 0.02)
154
+
155
+ assert_in_delta(0.3, methods[2].total_time, 0.1)
156
+ assert_in_delta(0, methods[2].wait_time, 0.02)
157
+ assert_in_delta(0.3, methods[2].self_time, 0.1)
158
+ end
159
+
160
+ def test_module_instance_methods
161
+ result = RubyProf.profile do
162
+ RubyProf::C2.new.hello
163
+ end
164
+
165
+ thread = result.threads.first
166
+ assert_in_delta(0.3, thread.total_time, 0.01)
167
+
168
+ top_methods = thread.top_methods
169
+ assert_equal(1, top_methods.count)
170
+ assert_equal("MeasureWallTimeTest#test_module_instance_methods", top_methods[0].full_name)
171
+
172
+ # Methods:
173
+ # MeasureWallTimeTest#test_module_instance_methods
174
+ # Class#new
175
+ # <Class::Object>#allocate
176
+ # Object#initialize
177
+ # M1#hello
178
+ # Kernel#sleep
179
+
180
+ methods = result.threads.first.methods.sort.reverse
181
+ assert_equal(RubyProf.ruby_2? ? 5 : 6, methods.length)
182
+ names = methods.map(&:full_name)
183
+ assert_equal('MeasureWallTimeTest#test_module_instance_methods', names[0])
184
+ assert_equal('RubyProf::M1#hello', names[1])
185
+ assert_equal('Kernel#sleep', names[2])
186
+ assert_equal('Class#new', names[3])
187
+
188
+ # order can differ
189
+ assert(names.include?("#{RubyProf.parent_object}#initialize"))
190
+ unless RubyProf.ruby_2?
191
+ assert(names.include?("<Class::#{RubyProf.parent_object}>#allocate"))
192
+ end
193
+
194
+ # Check times
195
+ assert_in_delta(0.3, methods[0].total_time, 0.1)
196
+ assert_in_delta(0, methods[0].wait_time, 0.1)
197
+ assert_in_delta(0, methods[0].self_time, 0.1)
198
+
199
+ assert_in_delta(0.3, methods[1].total_time, 0.02)
200
+ assert_in_delta(0, methods[1].wait_time, 0.01)
201
+ assert_in_delta(0, methods[1].self_time, 0.01)
202
+
203
+ assert_in_delta(0.3, methods[2].total_time, 0.02)
204
+ assert_in_delta(0, methods[2].wait_time, 0.01)
205
+ assert_in_delta(0.3, methods[2].self_time, 0.02)
206
+
207
+ assert_in_delta(0, methods[3].total_time, 0.01)
208
+ assert_in_delta(0, methods[3].wait_time, 0.01)
209
+ assert_in_delta(0, methods[3].self_time, 0.01)
210
+
211
+ assert_in_delta(0, methods[4].total_time, 0.01)
212
+ assert_in_delta(0, methods[4].wait_time, 0.01)
213
+ assert_in_delta(0, methods[4].self_time, 0.01)
214
+
215
+ unless RubyProf.ruby_2?
216
+ assert_in_delta(0, methods[5].total_time, 0.01)
217
+ assert_in_delta(0, methods[5].wait_time, 0.01)
218
+ assert_in_delta(0, methods[5].self_time, 0.01)
219
+ end
220
+ end
221
+
222
+ def test_singleton
223
+ c3 = RubyProf::C3.new
224
+
225
+ class << c3
226
+ def hello
227
+ end
228
+ end
229
+
230
+ result = RubyProf.profile do
231
+ c3.hello
232
+ end
233
+
234
+ thread = result.threads.first
235
+ assert_in_delta(0.0, thread.total_time, 0.01)
236
+
237
+ top_methods = thread.top_methods
238
+ assert_equal(1, top_methods.count)
239
+ assert_equal("MeasureWallTimeTest#test_singleton", top_methods[0].full_name)
240
+
241
+ methods = result.threads.first.methods.sort.reverse
242
+ assert_equal(2, methods.length)
243
+
244
+ assert_equal('MeasureWallTimeTest#test_singleton', methods[0].full_name)
245
+ assert_equal('<Object::RubyProf::C3>#hello', methods[1].full_name)
246
+
247
+ assert_in_delta(0, methods[0].total_time, 0.01)
248
+ assert_in_delta(0, methods[0].wait_time, 0.01)
249
+ assert_in_delta(0, methods[0].self_time, 0.01)
250
+
251
+ assert_in_delta(0, methods[1].total_time, 0.01)
252
+ assert_in_delta(0, methods[1].wait_time, 0.01)
253
+ assert_in_delta(0, methods[1].self_time, 0.01)
254
+ end
255
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Need to use wall time for this test due to the sleep calls
7
+ RubyProf::measure_mode = RubyProf::WALL_TIME
8
+
9
+ module Foo
10
+ def Foo::hello
11
+ sleep(0.5)
12
+ end
13
+ end
14
+
15
+ module Bar
16
+ def Bar::hello
17
+ sleep(0.5)
18
+ Foo::hello
19
+ end
20
+
21
+ def hello
22
+ sleep(0.5)
23
+ Bar::hello
24
+ end
25
+ end
26
+
27
+ include Bar
28
+
29
+ class ModuleTest < TestCase
30
+ def test_nested_modules
31
+ result = RubyProf.profile do
32
+ hello
33
+ end
34
+
35
+ methods = result.threads.first.methods
36
+
37
+ # Length should be 5
38
+ assert_equal(5, methods.length)
39
+
40
+ # these methods should be in there... (hard to tell order though).
41
+ for name in ['ModuleTest#test_nested_modules','Bar#hello','Kernel#sleep','<Module::Bar>#hello','<Module::Foo>#hello']
42
+ assert methods.map(&:full_name).include?( name )
43
+ end
44
+ end
45
+ end