ruby-prof 1.8.0-x64-mswin64-140

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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +665 -0
  3. data/LICENSE +25 -0
  4. data/README.md +5 -0
  5. data/Rakefile +98 -0
  6. data/bin/ruby-prof +341 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +23 -0
  9. data/ext/ruby_prof/rp_allocation.c +327 -0
  10. data/ext/ruby_prof/rp_allocation.h +32 -0
  11. data/ext/ruby_prof/rp_call_tree.c +502 -0
  12. data/ext/ruby_prof/rp_call_tree.h +47 -0
  13. data/ext/ruby_prof/rp_call_trees.c +296 -0
  14. data/ext/ruby_prof/rp_call_trees.h +28 -0
  15. data/ext/ruby_prof/rp_measure_allocations.c +47 -0
  16. data/ext/ruby_prof/rp_measure_memory.c +46 -0
  17. data/ext/ruby_prof/rp_measure_process_time.c +64 -0
  18. data/ext/ruby_prof/rp_measure_wall_time.c +52 -0
  19. data/ext/ruby_prof/rp_measurement.c +359 -0
  20. data/ext/ruby_prof/rp_measurement.h +52 -0
  21. data/ext/ruby_prof/rp_method.c +551 -0
  22. data/ext/ruby_prof/rp_method.h +66 -0
  23. data/ext/ruby_prof/rp_profile.c +933 -0
  24. data/ext/ruby_prof/rp_profile.h +36 -0
  25. data/ext/ruby_prof/rp_stack.c +212 -0
  26. data/ext/ruby_prof/rp_stack.h +53 -0
  27. data/ext/ruby_prof/rp_thread.c +433 -0
  28. data/ext/ruby_prof/rp_thread.h +39 -0
  29. data/ext/ruby_prof/ruby_prof.c +50 -0
  30. data/ext/ruby_prof/ruby_prof.h +35 -0
  31. data/ext/ruby_prof/vc/ruby_prof.sln +39 -0
  32. data/ext/ruby_prof/vc/ruby_prof.vcxproj +158 -0
  33. data/lib/ruby-prof/assets/call_stack_printer.html.erb +711 -0
  34. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  35. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
  36. data/lib/ruby-prof/call_tree.rb +57 -0
  37. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  38. data/lib/ruby-prof/compatibility.rb +113 -0
  39. data/lib/ruby-prof/exclude_common_methods.rb +204 -0
  40. data/lib/ruby-prof/measurement.rb +17 -0
  41. data/lib/ruby-prof/method_info.rb +87 -0
  42. data/lib/ruby-prof/printers/abstract_printer.rb +156 -0
  43. data/lib/ruby-prof/printers/call_info_printer.rb +53 -0
  44. data/lib/ruby-prof/printers/call_stack_printer.rb +180 -0
  45. data/lib/ruby-prof/printers/call_tree_printer.rb +145 -0
  46. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  47. data/lib/ruby-prof/printers/flat_printer.rb +53 -0
  48. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -0
  49. data/lib/ruby-prof/printers/graph_printer.rb +113 -0
  50. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  51. data/lib/ruby-prof/profile.rb +70 -0
  52. data/lib/ruby-prof/rack.rb +105 -0
  53. data/lib/ruby-prof/task.rb +147 -0
  54. data/lib/ruby-prof/thread.rb +20 -0
  55. data/lib/ruby-prof/version.rb +3 -0
  56. data/lib/ruby-prof.rb +52 -0
  57. data/lib/unprof.rb +10 -0
  58. data/ruby-prof.gemspec +67 -0
  59. data/test/abstract_printer_test.rb +27 -0
  60. data/test/alias_test.rb +117 -0
  61. data/test/call_tree_builder.rb +126 -0
  62. data/test/call_tree_test.rb +94 -0
  63. data/test/call_tree_visitor_test.rb +27 -0
  64. data/test/call_trees_test.rb +66 -0
  65. data/test/compatibility_test.rb +49 -0
  66. data/test/duplicate_names_test.rb +32 -0
  67. data/test/dynamic_method_test.rb +50 -0
  68. data/test/enumerable_test.rb +23 -0
  69. data/test/exceptions_test.rb +24 -0
  70. data/test/exclude_methods_test.rb +363 -0
  71. data/test/exclude_threads_test.rb +48 -0
  72. data/test/fiber_test.rb +195 -0
  73. data/test/gc_test.rb +104 -0
  74. data/test/inverse_call_tree_test.rb +174 -0
  75. data/test/line_number_test.rb +426 -0
  76. data/test/marshal_test.rb +145 -0
  77. data/test/measure_allocations.rb +26 -0
  78. data/test/measure_allocations_test.rb +1172 -0
  79. data/test/measure_process_time_test.rb +3330 -0
  80. data/test/measure_times.rb +56 -0
  81. data/test/measure_wall_time_test.rb +635 -0
  82. data/test/measurement_test.rb +82 -0
  83. data/test/merge_test.rb +146 -0
  84. data/test/method_info_test.rb +100 -0
  85. data/test/multi_printer_test.rb +66 -0
  86. data/test/no_method_class_test.rb +15 -0
  87. data/test/pause_resume_test.rb +171 -0
  88. data/test/prime.rb +54 -0
  89. data/test/prime_script.rb +6 -0
  90. data/test/printer_call_stack_test.rb +27 -0
  91. data/test/printer_call_tree_test.rb +30 -0
  92. data/test/printer_flat_test.rb +99 -0
  93. data/test/printer_graph_html_test.rb +59 -0
  94. data/test/printer_graph_test.rb +40 -0
  95. data/test/printers_test.rb +178 -0
  96. data/test/printing_recursive_graph_test.rb +81 -0
  97. data/test/profile_test.rb +101 -0
  98. data/test/rack_test.rb +93 -0
  99. data/test/recursive_test.rb +796 -0
  100. data/test/scheduler.rb +363 -0
  101. data/test/singleton_test.rb +38 -0
  102. data/test/stack_printer_test.rb +61 -0
  103. data/test/start_stop_test.rb +106 -0
  104. data/test/test_helper.rb +21 -0
  105. data/test/thread_test.rb +229 -0
  106. data/test/unique_call_path_test.rb +123 -0
  107. data/test/yarv_test.rb +56 -0
  108. metadata +228 -0
data/test/scheduler.rb ADDED
@@ -0,0 +1,363 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is an example and simplified scheduler for test purposes.
4
+ # It is not efficient for a large number of file descriptors as it uses IO.select().
5
+ # Production Fiber schedulers should use epoll/kqueue/etc.
6
+
7
+ require 'fiber'
8
+ require 'socket'
9
+
10
+ begin
11
+ require 'io/nonblock'
12
+ rescue LoadError
13
+ # Ignore.
14
+ end
15
+
16
+ class Scheduler
17
+ experimental = Warning[:experimental]
18
+ begin
19
+ Warning[:experimental] = false
20
+ IO::Buffer.new(0)
21
+ ensure
22
+ Warning[:experimental] = experimental
23
+ end
24
+
25
+ def initialize
26
+ @readable = {}
27
+ @writable = {}
28
+ @waiting = {}
29
+
30
+ @closed = false
31
+
32
+ @lock = Thread::Mutex.new
33
+ @blocking = Hash.new.compare_by_identity
34
+ @ready = []
35
+
36
+ @urgent = IO.pipe
37
+ end
38
+
39
+ attr :readable
40
+ attr :writable
41
+ attr :waiting
42
+
43
+ def next_timeout
44
+ _fiber, timeout = @waiting.min_by{|key, value| value}
45
+
46
+ if timeout
47
+ offset = timeout - current_time
48
+
49
+ if offset < 0
50
+ return 0
51
+ else
52
+ return offset
53
+ end
54
+ end
55
+ end
56
+
57
+ def run
58
+ # $stderr.puts [__method__, Fiber.current].inspect
59
+
60
+ while @readable.any? or @writable.any? or @waiting.any? or @blocking.any?
61
+ # Can only handle file descriptors up to 1024...
62
+ readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], next_timeout)
63
+
64
+ # puts "readable: #{readable}" if readable&.any?
65
+ # puts "writable: #{writable}" if writable&.any?
66
+
67
+ selected = {}
68
+
69
+ readable&.each do |io|
70
+ if fiber = @readable.delete(io)
71
+ @writable.delete(io) if @writable[io] == fiber
72
+ selected[fiber] = IO::READABLE
73
+ elsif io == @urgent.first
74
+ @urgent.first.read_nonblock(1024)
75
+ end
76
+ end
77
+
78
+ writable&.each do |io|
79
+ if fiber = @writable.delete(io)
80
+ @readable.delete(io) if @readable[io] == fiber
81
+ selected[fiber] = selected.fetch(fiber, 0) | IO::WRITABLE
82
+ end
83
+ end
84
+
85
+ selected.each do |fiber, events|
86
+ fiber.resume(events)
87
+ end
88
+
89
+ if @waiting.any?
90
+ time = current_time
91
+ waiting, @waiting = @waiting, {}
92
+
93
+ waiting.each do |fiber, timeout|
94
+ if fiber.alive?
95
+ if timeout <= time
96
+ fiber.resume
97
+ else
98
+ @waiting[fiber] = timeout
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ if @ready.any?
105
+ ready = nil
106
+
107
+ @lock.synchronize do
108
+ ready, @ready = @ready, []
109
+ end
110
+
111
+ ready.each do |fiber|
112
+ fiber.resume
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ def scheduler_close
119
+ close(true)
120
+ end
121
+
122
+ def close(internal = false)
123
+ # $stderr.puts [__method__, Fiber.current].inspect
124
+
125
+ unless internal
126
+ if Fiber.scheduler == self
127
+ return Fiber.set_scheduler(nil)
128
+ end
129
+ end
130
+
131
+ if @closed
132
+ raise "Scheduler already closed!"
133
+ end
134
+
135
+ self.run
136
+ ensure
137
+ if @urgent
138
+ @urgent.each(&:close)
139
+ @urgent = nil
140
+ end
141
+
142
+ @closed ||= true
143
+
144
+ # We freeze to detect any unintended modifications after the scheduler is closed:
145
+ self.freeze
146
+ end
147
+
148
+ def closed?
149
+ @closed
150
+ end
151
+
152
+ def current_time
153
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
154
+ end
155
+
156
+ def timeout_after(duration, klass, message, &block)
157
+ fiber = Fiber.current
158
+
159
+ self.fiber do
160
+ sleep(duration)
161
+
162
+ if fiber&.alive?
163
+ fiber.raise(klass, message)
164
+ end
165
+ end
166
+
167
+ begin
168
+ yield(duration)
169
+ ensure
170
+ fiber = nil
171
+ end
172
+ end
173
+
174
+ def process_wait(pid, flags)
175
+ # $stderr.puts [__method__, pid, flags, Fiber.current].inspect
176
+
177
+ # This is a very simple way to implement a non-blocking wait:
178
+ Thread.new do
179
+ Process::Status.wait(pid, flags)
180
+ end.value
181
+ end
182
+
183
+ def io_wait(io, events, duration)
184
+ # $stderr.puts [__method__, io, events, duration, Fiber.current].inspect
185
+
186
+ unless (events & IO::READABLE).zero?
187
+ @readable[io] = Fiber.current
188
+ end
189
+
190
+ unless (events & IO::WRITABLE).zero?
191
+ @writable[io] = Fiber.current
192
+ end
193
+
194
+ Fiber.yield
195
+ ensure
196
+ @readable.delete(io)
197
+ @writable.delete(io)
198
+ end
199
+
200
+ def io_select(...)
201
+ # Emulate the operation using a non-blocking thread:
202
+ Thread.new do
203
+ IO.select(...)
204
+ end.value
205
+ end
206
+
207
+ # Used for Kernel#sleep and Thread::Mutex#sleep
208
+ def kernel_sleep(duration = nil)
209
+ # $stderr.puts [__method__, duration, Fiber.current].inspect
210
+
211
+ self.block(:sleep, duration)
212
+
213
+ return true
214
+ end
215
+
216
+ # Used when blocking on synchronization (Thread::Mutex#lock,
217
+ # Thread::Queue#pop, Thread::SizedQueue#push, ...)
218
+ def block(blocker, timeout = nil)
219
+ # $stderr.puts [__method__, blocker, timeout].inspect
220
+
221
+ fiber = Fiber.current
222
+
223
+ if timeout
224
+ @waiting[fiber] = current_time + timeout
225
+ begin
226
+ Fiber.yield
227
+ ensure
228
+ # Remove from @waiting in the case #unblock was called before the timeout expired:
229
+ @waiting.delete(fiber)
230
+ end
231
+ else
232
+ @blocking[fiber] = true
233
+ begin
234
+ Fiber.yield
235
+ ensure
236
+ @blocking.delete(fiber)
237
+ end
238
+ end
239
+ end
240
+
241
+ # Used when synchronization wakes up a previously-blocked fiber
242
+ # (Thread::Mutex#unlock, Thread::Queue#push, ...).
243
+ # This might be called from another thread.
244
+ def unblock(blocker, fiber)
245
+ # $stderr.puts [__method__, blocker, fiber].inspect
246
+ # $stderr.puts blocker.backtrace.inspect
247
+ # $stderr.puts fiber.backtrace.inspect
248
+
249
+ @lock.synchronize do
250
+ @ready << fiber
251
+ end
252
+
253
+ io = @urgent.last
254
+ io.write_nonblock('.')
255
+ end
256
+
257
+ def fiber(&block)
258
+ fiber = Fiber.new(blocking: false, &block)
259
+
260
+ fiber.resume
261
+
262
+ return fiber
263
+ end
264
+
265
+ def address_resolve(hostname)
266
+ Thread.new do
267
+ Addrinfo.getaddrinfo(hostname, nil).map(&:ip_address).uniq
268
+ end.value
269
+ end
270
+ end
271
+
272
+ class IOBufferScheduler < Scheduler
273
+ EAGAIN = -Errno::EAGAIN::Errno
274
+
275
+ def io_read(io, buffer, length, offset)
276
+ total = 0
277
+ io.nonblock = true
278
+
279
+ while true
280
+ maximum_size = buffer.size - offset
281
+ result = blocking{buffer.read(io, maximum_size, offset)}
282
+
283
+ if result > 0
284
+ total += result
285
+ offset += result
286
+ break if total >= length
287
+ elsif result == 0
288
+ break
289
+ elsif result == EAGAIN
290
+ if length > 0
291
+ self.io_wait(io, IO::READABLE, nil)
292
+ else
293
+ return result
294
+ end
295
+ elsif result < 0
296
+ return result
297
+ end
298
+ end
299
+
300
+ return total
301
+ end
302
+
303
+ def io_write(io, buffer, length, offset)
304
+ total = 0
305
+ io.nonblock = true
306
+
307
+ while true
308
+ maximum_size = buffer.size - offset
309
+ result = blocking{buffer.write(io, maximum_size, offset)}
310
+
311
+ if result > 0
312
+ total += result
313
+ offset += result
314
+ break if total >= length
315
+ elsif result == 0
316
+ break
317
+ elsif result == EAGAIN
318
+ if length > 0
319
+ self.io_wait(io, IO::WRITABLE, nil)
320
+ else
321
+ return result
322
+ end
323
+ elsif result < 0
324
+ return result
325
+ end
326
+ end
327
+
328
+ return total
329
+ end
330
+
331
+ def blocking(&block)
332
+ Fiber.blocking(&block)
333
+ end
334
+ end
335
+
336
+ class BrokenUnblockScheduler < Scheduler
337
+ def unblock(blocker, fiber)
338
+ super
339
+
340
+ raise "Broken unblock!"
341
+ end
342
+ end
343
+
344
+ class SleepingUnblockScheduler < Scheduler
345
+ # This method is invoked when the thread is exiting.
346
+ def unblock(blocker, fiber)
347
+ super
348
+
349
+ # This changes the current thread state to `THREAD_RUNNING` which causes `thread_join_sleep` to hang.
350
+ sleep(0.1)
351
+ end
352
+ end
353
+
354
+ class SleepingBlockingScheduler < Scheduler
355
+ def kernel_sleep(duration = nil)
356
+ # Deliberaly sleep in a blocking state which can trigger a deadlock if the implementation is not correct.
357
+ Fiber.blocking{sleep 0.0001}
358
+
359
+ self.block(:sleep, duration)
360
+
361
+ return true
362
+ end
363
+ end
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'timeout'
6
+
7
+ # -- Test for bug [#5657]
8
+ # http://rubyforge.org/tracker/index.php?func=detail&aid=5657&group_id=1814&atid=7060
9
+
10
+
11
+ class A
12
+ attr_accessor :as
13
+ def initialize
14
+ @as = []
15
+ class << @as
16
+ def <<(an_a)
17
+ super
18
+ end
19
+ end
20
+ end
21
+
22
+ def <<(an_a)
23
+ @as << an_a
24
+ end
25
+ end
26
+
27
+ class SingletonTest < TestCase
28
+ def test_singleton
29
+ result = RubyProf::Profile.profile do
30
+ a = A.new
31
+ a << :first_thing
32
+ assert_equal(1, a.as.size)
33
+ end
34
+ printer = RubyProf::FlatPrinter.new(result)
35
+ output = ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT'] == "1" ? STDOUT : ''
36
+ printer.print(output)
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Test data
7
+ # A
8
+ # / \
9
+ # B C
10
+ # \
11
+ # B
12
+
13
+ class STPT
14
+ def a
15
+ 100.times{b}
16
+ 300.times{c}
17
+ c;c;c
18
+ end
19
+
20
+ def b
21
+ sleep 0
22
+ end
23
+
24
+ def c
25
+ 5.times{b}
26
+ end
27
+ end
28
+
29
+ class StackPrinterTest < TestCase
30
+ def test_stack_can_be_printed
31
+ start_time = Time.now
32
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
33
+ 5.times{STPT.new.a}
34
+ end
35
+
36
+ end_time = Time.now
37
+ expected_time = end_time - start_time
38
+
39
+ file_contents = nil
40
+ file_contents = print(result)
41
+ re = /Thread: (\d+)(, Fiber: (\d+))? \([\.0-9]+.[\.0-9]+% ~ ([\.0-9]+)\)/
42
+ assert_match(re, file_contents)
43
+ file_contents =~ re
44
+ actual_time = $4.to_f
45
+ assert_in_delta(expected_time, actual_time, 0.1)
46
+ end
47
+
48
+ private
49
+
50
+ def print(result)
51
+ test = caller.first =~ /in `(.*)'/ ? $1 : "test"
52
+ testfile_name = "#{Dir.tmpdir}/ruby_prof_#{test}.html"
53
+ # puts "printing to #{testfile_name}"
54
+ printer = RubyProf::CallStackPrinter.new(result)
55
+ File.open(testfile_name, "w") {|f| printer.print(f, :threshold => 0, :min_percent => 0, :title => "ruby_prof #{test}")}
56
+ system("open '#{testfile_name}'") if RUBY_PLATFORM =~ /darwin/ && ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT']=="1"
57
+ assert File.exist?(testfile_name), "#{testfile_name} does not exist"
58
+ assert File.readable?(testfile_name), "#{testfile_name} is no readable"
59
+ File.read(testfile_name)
60
+ end
61
+ end
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class StartStopTest < TestCase
7
+ def setup
8
+ super
9
+ # Need to use wall time for this test due to the sleep calls
10
+ @profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
11
+ end
12
+
13
+ def method1
14
+ @profile.start
15
+ method2
16
+ end
17
+
18
+ def method2
19
+ method3
20
+ end
21
+
22
+ def method3
23
+ sleep(2)
24
+ @result = @profile.stop
25
+ end
26
+
27
+ def test_extra_stop_should_raise
28
+ @profile.start
29
+ assert_raises(RuntimeError) do
30
+ @profile.start
31
+ end
32
+
33
+ @profile.stop # ok
34
+ assert_raises(RuntimeError) do
35
+ @profile.stop
36
+ end
37
+ end
38
+
39
+ def test_different_methods
40
+ method1
41
+
42
+ # Ruby prof should be stopped
43
+ assert_equal(false, @profile.running?)
44
+
45
+ methods = @result.threads.first.methods.sort.reverse
46
+ assert_equal(4, methods.length)
47
+
48
+ method = methods[0]
49
+ assert_equal('StartStopTest#method1', method.full_name)
50
+ assert_equal(1, method.called)
51
+ assert_in_delta(2, method.total_time, 0.05)
52
+ assert_in_delta(0, method.wait_time, 0.02)
53
+ assert_in_delta(0, method.self_time, 0.02)
54
+ assert_in_delta(2, method.children_time, 0.05)
55
+
56
+ assert_equal(1, method.call_trees.callees.length)
57
+ call_tree = method.call_trees.callees[0]
58
+ assert_equal('StartStopTest#method2', call_tree.target.full_name)
59
+
60
+ method = methods[1]
61
+ assert_equal('StartStopTest#method2', method.full_name)
62
+ assert_equal(1, method.called)
63
+ assert_in_delta(2, method.total_time, 0.05)
64
+ assert_in_delta(0, method.wait_time, 0.02)
65
+ assert_in_delta(0, method.self_time, 0.02)
66
+ assert_in_delta(2, method.children_time, 0.05)
67
+
68
+ assert_equal(1, method.call_trees.callers.length)
69
+ call_tree = method.call_trees.callers[0]
70
+ assert_equal('StartStopTest#method1', call_tree.parent.target.full_name)
71
+
72
+ assert_equal(1, method.call_trees.callees.length)
73
+ call_tree = method.call_trees.callees[0]
74
+ assert_equal('StartStopTest#method3', call_tree.target.full_name)
75
+
76
+ method = methods[2]
77
+ assert_equal('StartStopTest#method3', method.full_name)
78
+ assert_equal(1, method.called)
79
+ assert_in_delta(2, method.total_time, 0.05)
80
+ assert_in_delta(0, method.wait_time, 0.02)
81
+ assert_in_delta(0, method.self_time, 0.02)
82
+ assert_in_delta(2, method.children_time, 0.05)
83
+
84
+ assert_equal(1, method.call_trees.callers.length)
85
+ call_tree = method.call_trees.callers[0]
86
+ assert_equal('StartStopTest#method2', call_tree.parent.target.full_name)
87
+
88
+ assert_equal(1, method.call_trees.callees.length)
89
+ call_tree = method.call_trees.callees[0]
90
+ assert_equal('Kernel#sleep', call_tree.target.full_name)
91
+
92
+ method = methods[3]
93
+ assert_equal('Kernel#sleep', method.full_name)
94
+ assert_equal(1, method.called)
95
+ assert_in_delta(2, method.total_time, 0.05)
96
+ assert_in_delta(0, method.wait_time, 0.02)
97
+ assert_in_delta(2, method.self_time, 0.02)
98
+ assert_in_delta(0, method.children_time, 0.05)
99
+
100
+ assert_equal(1, method.call_trees.callers.length)
101
+ call_tree = method.call_trees.callers[0]
102
+ assert_equal('StartStopTest#method3', call_tree.parent.target.full_name)
103
+
104
+ assert_equal(0, method.call_trees.callees.length)
105
+ end
106
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: UTF-8
2
+
3
+ # To make testing/debugging easier test within this source tree versus an installed gem
4
+ require 'bundler/setup'
5
+
6
+ # Add ext directory to load path to make it easier to test locally built extensions
7
+ ext_path = File.expand_path(File.join(__dir__, '..', 'ext', 'ruby_prof'))
8
+ $LOAD_PATH.unshift(ext_path)
9
+
10
+ # Now load code
11
+ require 'ruby-prof'
12
+
13
+ # Disable minitest parallel tests. The problem is the thread switching will change test results
14
+ # (self vs wait time)
15
+ ENV["MT_CPU"] = "0" # New versions of minitest
16
+ ENV["N"] = "0" # Older versions of minitest
17
+
18
+ require 'minitest/autorun'
19
+ Minitest.load_plugins
20
+ class TestCase < Minitest::Test
21
+ end