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
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ class MeasurementTest < Minitest::Test
6
+ def test_initialize
7
+ measurement = RubyProf::Measurement.new(3.3, 2.2, 1.1, 4)
8
+ assert_equal(3.3, measurement.total_time)
9
+ assert_equal(2.2, measurement.self_time)
10
+ assert_equal(1.1, measurement.wait_time)
11
+ assert_equal(4, measurement.called)
12
+ end
13
+
14
+ def test_clone
15
+ measurement_1 = RubyProf::Measurement.new(3.3, 2.2, 1.1, 4)
16
+ measurement_2 = measurement_1.clone
17
+
18
+ refute(measurement_1.equal?(measurement_2))
19
+ refute(measurement_1.eql?(measurement_2))
20
+ refute(measurement_1 == measurement_2)
21
+
22
+ assert_equal(measurement_1.total_time, measurement_2.total_time)
23
+ assert_equal(measurement_1.self_time, measurement_2.self_time)
24
+ assert_equal(measurement_1.wait_time, measurement_2.wait_time)
25
+ assert_equal(measurement_1.called, measurement_2.called)
26
+ end
27
+
28
+ def test_dup
29
+ measurement_1 = RubyProf::Measurement.new(3.3, 2.2, 1.1, 4)
30
+ measurement_2 = measurement_1.dup
31
+
32
+ refute(measurement_1.equal?(measurement_2))
33
+ refute(measurement_1.eql?(measurement_2))
34
+ refute(measurement_1 == measurement_2)
35
+
36
+ assert_equal(measurement_1.total_time, measurement_2.total_time)
37
+ assert_equal(measurement_1.self_time, measurement_2.self_time)
38
+ assert_equal(measurement_1.wait_time, measurement_2.wait_time)
39
+ assert_equal(measurement_1.called, measurement_2.called)
40
+ end
41
+
42
+ def test_merge!
43
+ measurement1 = RubyProf::Measurement.new(3.3, 2.2, 1.1, 4)
44
+ measurement2 = RubyProf::Measurement.new(3, 2, 1, 3)
45
+
46
+ measurement1.merge!(measurement2)
47
+
48
+ assert_equal(6.3, measurement1.total_time)
49
+ assert_equal(4.2, measurement1.self_time)
50
+ assert_equal(2.1, measurement1.wait_time)
51
+ assert_equal(7, measurement1.called)
52
+
53
+ assert_equal(3, measurement2.total_time)
54
+ assert_equal(2, measurement2.self_time)
55
+ assert_equal(1, measurement2.wait_time)
56
+ assert_equal(3, measurement2.called)
57
+ end
58
+
59
+ def test_set_total_time
60
+ measurement = RubyProf::Measurement.new(4, 3, 1, 1)
61
+ measurement.total_time = 5.1
62
+ assert_equal(5.1, measurement.total_time)
63
+ end
64
+
65
+ def test_set_self_time
66
+ measurement = RubyProf::Measurement.new(4, 3, 1, 1)
67
+ measurement.self_time = 3.1
68
+ assert_equal(3.1, measurement.self_time)
69
+ end
70
+
71
+ def test_set_wait_time
72
+ measurement = RubyProf::Measurement.new(4, 3, 1, 1)
73
+ measurement.wait_time = 1.1
74
+ assert_equal(1.1, measurement.wait_time)
75
+ end
76
+
77
+ def test_set_called
78
+ measurement = RubyProf::Measurement.new(4, 3, 1, 1)
79
+ measurement.called = 2
80
+ assert_equal(2, measurement.called)
81
+ end
82
+ end
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.1.0')
7
+
8
+ require_relative './scheduler'
9
+
10
+ # -- Tests ----
11
+ class MergeTest < TestCase
12
+ def worker1
13
+ sleep(0.5)
14
+ end
15
+
16
+ def worker2
17
+ sleep(0.5)
18
+ sleep(0.5)
19
+ end
20
+
21
+ def worker3
22
+ sleep(0.5)
23
+ end
24
+
25
+ def concurrency_single_worker
26
+ scheduler = Scheduler.new
27
+ Fiber.set_scheduler(scheduler)
28
+
29
+ 3.times do
30
+ Fiber.schedule do
31
+ worker1
32
+ end
33
+ end
34
+ Fiber.scheduler.close
35
+ end
36
+
37
+ def concurrency_multiple_workers
38
+ scheduler = Scheduler.new
39
+ Fiber.set_scheduler(scheduler)
40
+
41
+ 3.times do |i|
42
+ Fiber.schedule do
43
+ method = "worker#{i + 1}".to_sym
44
+ send(method)
45
+ end
46
+ end
47
+ Fiber.scheduler.close
48
+ end
49
+
50
+ def test_single_worker_unmerged
51
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) { concurrency_single_worker }
52
+ assert_equal(4, result.threads.size)
53
+
54
+ thread = result.threads[0]
55
+ assert_in_delta(0.5, thread.call_tree.target.total_time, 0.1)
56
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
57
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
58
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
59
+
60
+ thread = result.threads[1]
61
+ assert_in_delta(0.5, thread.call_tree.target.total_time, 0.1)
62
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
63
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
64
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
65
+
66
+ thread = result.threads[2]
67
+ assert_in_delta(0.5, thread.call_tree.target.total_time, 0.1)
68
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
69
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
70
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
71
+
72
+ thread = result.threads[3]
73
+ assert_in_delta(0.5, thread.call_tree.target.total_time, 0.1)
74
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
75
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
76
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
77
+ end
78
+
79
+ def test_single_worker_merged
80
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) { concurrency_single_worker }
81
+ result.merge!
82
+
83
+ assert_equal(2, result.threads.size)
84
+
85
+ thread = result.threads[0]
86
+ assert_in_delta(0.5, thread.call_tree.target.total_time, 0.1)
87
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
88
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
89
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
90
+
91
+ thread = result.threads[1]
92
+ assert_in_delta(1.5, thread.call_tree.target.total_time, 0.1)
93
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
94
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
95
+ assert_in_delta(1.5, thread.call_tree.target.children_time, 0.1)
96
+ end
97
+
98
+ def test_multiple_workers_unmerged
99
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) { concurrency_multiple_workers }
100
+ assert_equal(4, result.threads.count)
101
+
102
+ thread = result.threads[0]
103
+ assert_in_delta(1.0, thread.call_tree.target.total_time, 0.1)
104
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
105
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
106
+ assert_in_delta(1.0, thread.call_tree.target.children_time, 0.1)
107
+
108
+ thread = result.threads[1]
109
+ assert_in_delta(1.0, thread.call_tree.target.total_time, 0.1)
110
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
111
+ assert_in_delta(0.5, thread.call_tree.target.wait_time, 0.1)
112
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
113
+
114
+ thread = result.threads[2]
115
+ assert_in_delta(1.0, thread.call_tree.target.total_time, 0.1)
116
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
117
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
118
+ assert_in_delta(1.0, thread.call_tree.target.children_time, 0.1)
119
+
120
+ thread = result.threads[3]
121
+ assert_in_delta(1.0, thread.call_tree.target.total_time, 0.1)
122
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
123
+ assert_in_delta(0.5, thread.call_tree.target.wait_time, 0.1)
124
+ assert_in_delta(0.5, thread.call_tree.target.children_time, 0.1)
125
+ end
126
+
127
+ def test_multiple_workers_merged
128
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) { concurrency_multiple_workers }
129
+ result.merge!
130
+
131
+ assert_equal(2, result.threads.count)
132
+
133
+ thread = result.threads[0]
134
+ assert_in_delta(1.0, thread.call_tree.target.total_time, 0.1)
135
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
136
+ assert_in_delta(0.0, thread.call_tree.target.wait_time, 0.1)
137
+ assert_in_delta(1.0, thread.call_tree.target.children_time, 0.1)
138
+
139
+ thread = result.threads[1]
140
+ assert_in_delta(3.0, thread.call_tree.target.total_time, 0.1)
141
+ assert_in_delta(0.0, thread.call_tree.target.self_time, 0.1)
142
+ assert_in_delta(1.0, thread.call_tree.target.wait_time, 0.1)
143
+ assert_in_delta(2.0, thread.call_tree.target.children_time, 0.1)
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+ require 'base64'
5
+
6
+ class MethodInfoTest < Minitest::Test
7
+ def test_initialize
8
+ method_info = RubyProf::MethodInfo.new(Base64, :encode64)
9
+ assert_equal("Base64", method_info.klass_name)
10
+ assert_equal(:encode64, method_info.method_name)
11
+ assert_equal("Base64#encode64", method_info.full_name)
12
+ assert_equal(0, method_info.klass_flags)
13
+ assert_match(/base64\.rb/, method_info.source_file)
14
+ assert_kind_of(Integer, method_info.line)
15
+ refute(method_info.recursive?)
16
+
17
+ assert_kind_of(RubyProf::Measurement, method_info.measurement)
18
+ assert_kind_of(RubyProf::CallTrees, method_info.call_trees)
19
+ assert_empty(method_info.allocations)
20
+ end
21
+
22
+ def test_initialize_nil_klass
23
+ error = assert_raises(NoMethodError) do
24
+ RubyProf::MethodInfo.new(nil, nil)
25
+ end
26
+
27
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.4')
28
+ assert_match(/undefined method `instance_method' for nil/, error.message)
29
+ else
30
+ assert_match(/undefined method 'instance_method' for nil/, error.message)
31
+ end
32
+ end
33
+
34
+ def test_initialize_nil_method_name
35
+ error = assert_raises(TypeError) do
36
+ RubyProf::MethodInfo.new(Base64, nil)
37
+ end
38
+ assert_equal("nil is not a symbol nor a string", error.to_s)
39
+ end
40
+
41
+ def test_initialize_unknown_location
42
+ method_info = RubyProf::MethodInfo.new(Array, :size)
43
+ assert_equal('Array', method_info.klass_name)
44
+ assert_equal(:size, method_info.method_name)
45
+ assert_nil(method_info.source_file)
46
+ assert_equal(0, method_info.line)
47
+ end
48
+
49
+ def test_measurement
50
+ method_info = RubyProf::MethodInfo.new(Base64, :encode64)
51
+ assert_equal(0, method_info.total_time)
52
+ assert_equal(0, method_info.self_time)
53
+ assert_equal(0, method_info.wait_time)
54
+ assert_equal(0, method_info.children_time)
55
+ assert_equal(0, method_info.called)
56
+ end
57
+
58
+ def test_compare
59
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :encode64)
60
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :encode64)
61
+ assert_equal(0, method_info_1 <=> method_info_2)
62
+
63
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :decode64)
64
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :encode64)
65
+ assert_equal(-1, method_info_1 <=> method_info_2)
66
+
67
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :encode64)
68
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :decode64)
69
+ assert_equal(1, method_info_1 <=> method_info_2)
70
+ end
71
+
72
+ def test_eql?
73
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :encode64)
74
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :encode64)
75
+ assert(method_info_1.eql?(method_info_2))
76
+ end
77
+
78
+ def test_equal?
79
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :encode64)
80
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :encode64)
81
+ refute(method_info_1.equal?(method_info_2))
82
+ end
83
+
84
+ def test_equality
85
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :encode64)
86
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :encode64)
87
+ assert(method_info_1 == method_info_2)
88
+ end
89
+
90
+ def test_hash
91
+ method_info_1 = RubyProf::MethodInfo.new(Base64, :encode64)
92
+ method_info_2 = RubyProf::MethodInfo.new(Base64, :encode64)
93
+ assert_equal(method_info_1.hash, method_info_2.hash)
94
+ end
95
+
96
+ def test_to_s
97
+ method_info = RubyProf::MethodInfo.new(Base64, :encode64)
98
+ assert_equal("Base64#encode64 (c: 0, tt: 0.0, st: 0.0, wt: 0.0, ct: 0.0)", method_info.to_s)
99
+ end
100
+ end
@@ -0,0 +1,66 @@
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 MSTPT
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 MultiPrinterTest < TestCase
30
+ def test_refuses_io_objects
31
+ # we don't need a real profile for this test
32
+ p = RubyProf::MultiPrinter.new nil
33
+ begin
34
+ p.print(STDOUT)
35
+ flunk "should have raised an ArgumentError"
36
+ rescue ArgumentError => e
37
+ assert_match(/IO/, e.to_s)
38
+ end
39
+ end
40
+
41
+ def test_refuses_non_hashes
42
+ # we don't need a real profile for this test
43
+ p = RubyProf::MultiPrinter.new nil
44
+ begin
45
+ p.print([])
46
+ flunk "should have raised an ArgumentError"
47
+ rescue ArgumentError => e
48
+ assert_match(/hash/, e.to_s)
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def print(result)
55
+ test = caller.first =~ /in `(.*)'/ ? $1 : "test"
56
+ path = Dir.tmpdir
57
+ profile = "ruby_prof_#{test}"
58
+ printer = RubyProf::MultiPrinter.new(result)
59
+ printer.print(:path => path, :profile => profile,
60
+ :threshold => 0, :min_percent => 0, :title => "ruby_prof #{test}")
61
+ if RUBY_PLATFORM =~ /darwin/ && ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT']=="1"
62
+ system("open '#{printer.stack_profile}'")
63
+ end
64
+ [File.read(printer.stack_profile), File.read(printer.graph_profile)]
65
+ end
66
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Make sure this works with no class or method
7
+ result = RubyProf::Profile.profile do
8
+ sleep 1
9
+ end
10
+
11
+ methods = result.threads.first.methods
12
+ global_method = methods.sort_by {|method| method.full_name}.first
13
+ if global_method.full_name != 'Kernel#sleep'
14
+ raise(RuntimeError, "Wrong method name. Expected: Global#[No method]. Actual: #{global_method.full_name}")
15
+ end
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require_relative 'measure_times'
6
+
7
+ class PauseResumeTest < TestCase
8
+ def test_pause_resume
9
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
10
+ # Measured
11
+ profile.start
12
+ RubyProf::C1.sleep_wait
13
+
14
+ # Not measured
15
+ profile.pause
16
+ sleep 1
17
+ RubyProf::C1.sleep_wait
18
+
19
+ # Measured
20
+ profile.resume
21
+ RubyProf::C1.sleep_wait
22
+
23
+ result = profile.stop
24
+
25
+ # Length should be 3:
26
+ # PauseResumeTest#test_pause_resume
27
+ # <Class::RubyProf::C1>#sleep_wait
28
+ # Kernel#sleep
29
+
30
+ methods = result.threads.first.methods.sort_by {|method_info| method_info.full_name}
31
+ # remove methods called by pause/resume
32
+ called_methods = ['Array#include?', 'Fixnum#==', 'Kernel#respond_to?', 'Kernel#respond_to_missing?']
33
+ methods.reject!{|m| called_methods.include?(m.full_name) }
34
+ # TODO: fix pause/resume to not include those methods in the first place
35
+ assert_equal(3, methods.length)
36
+
37
+ # Check the names
38
+ assert_equal('<Class::RubyProf::C1>#sleep_wait', methods[0].full_name)
39
+ assert_equal('Kernel#sleep', methods[1].full_name)
40
+ assert_equal('PauseResumeTest#test_pause_resume', methods[2].full_name)
41
+
42
+ # Check times
43
+ assert_in_delta(0.22, methods[0].total_time, 0.02)
44
+ assert_in_delta(0, methods[0].wait_time, 0.02)
45
+ assert_in_delta(0, methods[0].self_time, 0.02)
46
+
47
+ assert_in_delta(0.22, methods[1].total_time, 0.02)
48
+ assert_in_delta(0, methods[1].wait_time, 0.02)
49
+ assert_in_delta(0.22, methods[1].self_time, 0.02)
50
+
51
+ assert_in_delta(0.22, methods[2].total_time, 0.02)
52
+ assert_in_delta(0, methods[2].wait_time, 0.02)
53
+ assert_in_delta(0, methods[2].self_time, 0.02)
54
+ end
55
+
56
+ # pause/resume in the same frame
57
+ def test_pause_resume_1
58
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
59
+
60
+ profile.start
61
+ method_1a
62
+
63
+ profile.pause
64
+ method_1b
65
+
66
+ profile.resume
67
+ method_1c
68
+
69
+ result = profile.stop
70
+ assert_in_delta(0.65, result.threads[0].methods.select {|m| m.full_name =~ /test_pause_resume_1$/}[0].total_time, 0.05)
71
+ end
72
+ def method_1a; sleep 0.22 end
73
+ def method_1b; sleep 1 end
74
+ def method_1c; sleep 0.4 end
75
+
76
+ # pause in parent frame, resume in child
77
+ def test_pause_resume_2
78
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
79
+
80
+ profile.start
81
+ method_2a
82
+
83
+ profile.pause
84
+ sleep 0.5
85
+ method_2b(profile)
86
+
87
+ result = profile.stop
88
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_2$/}[0].total_time, 0.05)
89
+ end
90
+ def method_2a; sleep 0.22 end
91
+ def method_2b(profile); sleep 0.5; profile.resume; sleep 0.4 end
92
+
93
+ # pause in child frame, resume in parent
94
+ def test_pause_resume_3
95
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
96
+
97
+ profile.start
98
+ method_3a(profile)
99
+
100
+ sleep 0.5
101
+ profile.resume
102
+ method_3b
103
+
104
+ result = profile.stop
105
+ assert_in_delta(0.65, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_3$/}[0].total_time, 0.05)
106
+ end
107
+
108
+ def method_3a(profile)
109
+ sleep 0.22
110
+ profile.pause
111
+ sleep 0.5
112
+ end
113
+
114
+ def method_3b
115
+ sleep 0.4
116
+ end
117
+
118
+ def test_pause_seq
119
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
120
+ profile.start ; assert !profile.paused?
121
+ profile.pause ; assert profile.paused?
122
+ profile.resume; assert !profile.paused?
123
+ profile.pause ; assert profile.paused?
124
+ profile.pause ; assert profile.paused?
125
+ profile.resume; assert !profile.paused?
126
+ profile.resume; assert !profile.paused?
127
+ profile.stop ; assert !profile.paused?
128
+ end
129
+
130
+ def test_pause_block
131
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
132
+ profile.start
133
+ profile.pause
134
+ assert profile.paused?
135
+
136
+ times_block_invoked = 0
137
+ retval= profile.resume{
138
+ times_block_invoked += 1
139
+ 120 + times_block_invoked
140
+ }
141
+ assert_equal 1, times_block_invoked
142
+ assert profile.paused?
143
+
144
+ assert_equal 121, retval, "resume() should return the result of the given block."
145
+
146
+ profile.stop
147
+ end
148
+
149
+ def test_pause_block_with_error
150
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
151
+ profile.start
152
+ profile.pause
153
+ assert profile.paused?
154
+
155
+ begin
156
+ profile.resume{ raise }
157
+ flunk 'Exception expected.'
158
+ rescue
159
+ assert profile.paused?
160
+ end
161
+
162
+ profile.stop
163
+ end
164
+
165
+ def test_resume_when_not_paused
166
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
167
+ profile.start ; assert !profile.paused?
168
+ profile.resume; assert !profile.paused?
169
+ profile.stop ; assert !profile.paused?
170
+ end
171
+ end
data/test/prime.rb ADDED
@@ -0,0 +1,54 @@
1
+ # A silly little test program that finds prime numbers. It
2
+ # is intentionally badly designed to show off the use
3
+ # of ruby-prof.
4
+ #
5
+ # Source from http://people.cs.uchicago.edu/~bomb154/154/maclabs/profilers-lab/
6
+
7
+ def make_random_array(length, maxnum)
8
+ result = Array.new(length)
9
+ result.each_index do |i|
10
+ result[i] = rand(maxnum)
11
+ end
12
+
13
+ result
14
+ end
15
+
16
+ def is_prime(x)
17
+ y = 2
18
+ y.upto(x-1) do |i|
19
+ return false if (x % i) == 0
20
+ end
21
+ true
22
+ end
23
+
24
+ def find_primes(arr)
25
+ result = arr.select do |value|
26
+ is_prime(value)
27
+ end
28
+ result
29
+ end
30
+
31
+ def find_largest(primes)
32
+ largest = primes.first
33
+
34
+ # Intentionally use upto for example purposes
35
+ # (upto is also called from is_prime)
36
+ 0.upto(primes.length-1) do |i|
37
+ prime = primes[i]
38
+ if prime > largest
39
+ largest = prime
40
+ end
41
+ end
42
+ largest
43
+ end
44
+
45
+ def run_primes(length=10, maxnum=1_000)
46
+ # Create random numbers
47
+ random_array = make_random_array(length, maxnum)
48
+
49
+ # Find the primes
50
+ primes = find_primes(random_array)
51
+
52
+ # Find the largest primes
53
+ find_largest(primes)
54
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # This file is used to test bin/ruby-prof
5
+ require_relative './prime'
6
+ run_primes(100, 1_000_000)
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'fileutils'
6
+ require 'tmpdir'
7
+ require_relative 'prime'
8
+
9
+ # -- Tests ----
10
+ class PrinterCallStackTest < TestCase
11
+ def setup
12
+ super
13
+ # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
14
+ @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
15
+ run_primes(1000, 5000)
16
+ end
17
+ end
18
+
19
+ def test_graph_html_string
20
+ output = ''
21
+ printer = RubyProf::CallStackPrinter.new(@result)
22
+ printer.print(output)
23
+
24
+ assert_match(/<!DOCTYPE html>/i, output)
25
+ assert_match(/Object#run_primes/i, output)
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'fileutils'
6
+ require 'tmpdir'
7
+ require_relative 'prime'
8
+
9
+ # -- Tests ----
10
+ class PrinterCallTreeTest < TestCase
11
+ def setup
12
+ super
13
+ # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
14
+ @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
15
+ run_primes(1000, 5000)
16
+ end
17
+ end
18
+
19
+ def test_call_tree_string
20
+ printer = RubyProf::CallTreePrinter.new(@result)
21
+
22
+ printer.print(:path => Dir.tmpdir)
23
+ main_output_file_name = File.join(Dir.tmpdir, "callgrind.out.#{$$}")
24
+ assert(File.exist?(main_output_file_name))
25
+ output = File.read(main_output_file_name)
26
+ assert_match(/fn=Object::find_primes/i, output)
27
+ assert_match(/events: wall_time/i, output)
28
+ refute_match(/d\d\d\d\d\d/, output) # old bug looked [in error] like Object::run_primes(d5833116)
29
+ end
30
+ end