rack-insight 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +1 -0
  3. data/.simplecov +4 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG +58 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +82 -0
  8. data/LICENSE +24 -0
  9. data/README.md +189 -0
  10. data/Rakefile +27 -0
  11. data/TODO +7 -0
  12. data/lib/rack-insight.rb +1 -0
  13. data/lib/rack/insight.rb +19 -0
  14. data/lib/rack/insight/app.rb +198 -0
  15. data/lib/rack/insight/config.rb +30 -0
  16. data/lib/rack/insight/database.rb +193 -0
  17. data/lib/rack/insight/enable-button.rb +43 -0
  18. data/lib/rack/insight/filtered_backtrace.rb +45 -0
  19. data/lib/rack/insight/instrumentation.rb +9 -0
  20. data/lib/rack/insight/instrumentation/backstage.rb +10 -0
  21. data/lib/rack/insight/instrumentation/client.rb +20 -0
  22. data/lib/rack/insight/instrumentation/instrument.rb +109 -0
  23. data/lib/rack/insight/instrumentation/package-definition.rb +58 -0
  24. data/lib/rack/insight/instrumentation/probe-definition.rb +20 -0
  25. data/lib/rack/insight/instrumentation/probe.rb +196 -0
  26. data/lib/rack/insight/instrumentation/setup.rb +32 -0
  27. data/lib/rack/insight/logger.rb +53 -0
  28. data/lib/rack/insight/options.rb +116 -0
  29. data/lib/rack/insight/panel.rb +135 -0
  30. data/lib/rack/insight/panel_app.rb +31 -0
  31. data/lib/rack/insight/panels-content.rb +22 -0
  32. data/lib/rack/insight/panels-header.rb +18 -0
  33. data/lib/rack/insight/panels/active_record_panel.rb +46 -0
  34. data/lib/rack/insight/panels/active_resource_panel.rb +48 -0
  35. data/lib/rack/insight/panels/active_resource_panel/query.rb +27 -0
  36. data/lib/rack/insight/panels/cache_panel.rb +68 -0
  37. data/lib/rack/insight/panels/cache_panel/panel_app.rb +46 -0
  38. data/lib/rack/insight/panels/cache_panel/stats.rb +90 -0
  39. data/lib/rack/insight/panels/log_panel.rb +53 -0
  40. data/lib/rack/insight/panels/memory_panel.rb +36 -0
  41. data/lib/rack/insight/panels/mongo_panel.rb +41 -0
  42. data/lib/rack/insight/panels/mongo_panel/mongo_extension.rb +24 -0
  43. data/lib/rack/insight/panels/mongo_panel/stats.rb +46 -0
  44. data/lib/rack/insight/panels/rails_info_panel.rb +19 -0
  45. data/lib/rack/insight/panels/redis_panel.rb +42 -0
  46. data/lib/rack/insight/panels/redis_panel/redis_extension.rb +23 -0
  47. data/lib/rack/insight/panels/redis_panel/stats.rb +50 -0
  48. data/lib/rack/insight/panels/request_variables_panel.rb +70 -0
  49. data/lib/rack/insight/panels/speedtracer_panel.rb +89 -0
  50. data/lib/rack/insight/panels/speedtracer_panel/profiling.rb +29 -0
  51. data/lib/rack/insight/panels/speedtracer_panel/trace-app.rb +52 -0
  52. data/lib/rack/insight/panels/speedtracer_panel/tracer.rb +213 -0
  53. data/lib/rack/insight/panels/sphinx_panel.rb +41 -0
  54. data/lib/rack/insight/panels/sphinx_panel/stats.rb +94 -0
  55. data/lib/rack/insight/panels/sql_panel.rb +53 -0
  56. data/lib/rack/insight/panels/sql_panel/panel_app.rb +37 -0
  57. data/lib/rack/insight/panels/sql_panel/query.rb +94 -0
  58. data/lib/rack/insight/panels/templates_panel.rb +58 -0
  59. data/lib/rack/insight/panels/templates_panel/rendering.rb +81 -0
  60. data/lib/rack/insight/panels/timer_panel.rb +40 -0
  61. data/lib/rack/insight/params_signature.rb +61 -0
  62. data/lib/rack/insight/path-filter.rb +23 -0
  63. data/lib/rack/insight/public/__insight__/bookmarklet.html +10 -0
  64. data/lib/rack/insight/public/__insight__/bookmarklet.js +223 -0
  65. data/lib/rack/insight/public/__insight__/insight.css +235 -0
  66. data/lib/rack/insight/public/__insight__/insight.js +127 -0
  67. data/lib/rack/insight/public/__insight__/jquery-1.3.2.js +4376 -0
  68. data/lib/rack/insight/public/__insight__/jquery.tablesorter.min.js +1 -0
  69. data/lib/rack/insight/public/__insight__/spinner.gif +0 -0
  70. data/lib/rack/insight/rack_static_bug_avoider.rb +16 -0
  71. data/lib/rack/insight/redirect_interceptor.rb +25 -0
  72. data/lib/rack/insight/render.rb +72 -0
  73. data/lib/rack/insight/request-recorder.rb +22 -0
  74. data/lib/rack/insight/rspec_matchers.rb +33 -0
  75. data/lib/rack/insight/toolbar.rb +69 -0
  76. data/lib/rack/insight/version.rb +7 -0
  77. data/lib/rack/insight/views/enable-button.html.erb +21 -0
  78. data/lib/rack/insight/views/error.html.erb +17 -0
  79. data/lib/rack/insight/views/headers_fragment.html.erb +20 -0
  80. data/lib/rack/insight/views/panels/active_record.html.erb +17 -0
  81. data/lib/rack/insight/views/panels/active_resource.html.erb +47 -0
  82. data/lib/rack/insight/views/panels/cache.html.erb +93 -0
  83. data/lib/rack/insight/views/panels/execute_sql.html.erb +32 -0
  84. data/lib/rack/insight/views/panels/explain_sql.html.erb +32 -0
  85. data/lib/rack/insight/views/panels/log.html.erb +21 -0
  86. data/lib/rack/insight/views/panels/mongo.html.erb +32 -0
  87. data/lib/rack/insight/views/panels/profile_sql.html.erb +32 -0
  88. data/lib/rack/insight/views/panels/rails_info.html.erb +19 -0
  89. data/lib/rack/insight/views/panels/redis.html.erb +46 -0
  90. data/lib/rack/insight/views/panels/request_variables.html.erb +25 -0
  91. data/lib/rack/insight/views/panels/speedtracer/serverevent.html.erb +10 -0
  92. data/lib/rack/insight/views/panels/speedtracer/servertrace.html.erb +12 -0
  93. data/lib/rack/insight/views/panels/speedtracer/traces.html.erb +18 -0
  94. data/lib/rack/insight/views/panels/sphinx.html.erb +32 -0
  95. data/lib/rack/insight/views/panels/sql.html.erb +43 -0
  96. data/lib/rack/insight/views/panels/templates.html.erb +6 -0
  97. data/lib/rack/insight/views/panels/timer.html.erb +19 -0
  98. data/lib/rack/insight/views/panels/view_cache.html.erb +19 -0
  99. data/lib/rack/insight/views/redirect.html.erb +16 -0
  100. data/lib/rack/insight/views/request_fragment.html.erb +25 -0
  101. data/lib/rack/insight/views/toolbar.html.erb +29 -0
  102. data/rack-insight.gemspec +40 -0
  103. data/spec/custom_matchers.rb +0 -0
  104. data/spec/fixtures/config.ru +8 -0
  105. data/spec/fixtures/dummy_panel.rb +2 -0
  106. data/spec/fixtures/sample_app.rb +72 -0
  107. data/spec/fixtures/star_trek_panel.rb +1 -0
  108. data/spec/insight_spec.rb +163 -0
  109. data/spec/instrumentation_spec.rb +188 -0
  110. data/spec/rack/insight/config_spec.rb +20 -0
  111. data/spec/rack/insight/panels/active_record_panel_spec.rb +43 -0
  112. data/spec/rack/insight/panels/active_resource_panel_spec.rb +40 -0
  113. data/spec/rack/insight/panels/cache_panel_spec.rb +178 -0
  114. data/spec/rack/insight/panels/log_panel_spec.rb +44 -0
  115. data/spec/rack/insight/panels/memory_panel_spec.rb +21 -0
  116. data/spec/rack/insight/panels/mongo_panel_spec_pending.rb +52 -0
  117. data/spec/rack/insight/panels/rails_info_panel_spec.rb +29 -0
  118. data/spec/rack/insight/panels/redis_panel_spec.rb +67 -0
  119. data/spec/rack/insight/panels/speedtracer_panel_spec.rb +86 -0
  120. data/spec/rack/insight/panels/sql_panel_spec.rb +146 -0
  121. data/spec/rack/insight/panels/templates_panel_spec.rb +86 -0
  122. data/spec/rack/insight/panels/timer_panel_spec.rb +38 -0
  123. data/spec/rcov.opts +1 -0
  124. data/spec/spec.opts +1 -0
  125. data/spec/spec_helper.rb +111 -0
  126. metadata +380 -0
@@ -0,0 +1,25 @@
1
+ <div id="request_<%=request_id%>">
2
+ <% panels.each do |panel| %>
3
+ <% if panel.has_content? %>
4
+ <div class="panel_content" id="<%= panel.name %>">
5
+ <div class="panel_controls">
6
+ <form action="#">
7
+ <select id="request_id_menu" name="current_request">
8
+ <% requests.sort{|l,r| r[:id] <=> l[:id]}.each do |request| %>
9
+ <option value="<%= request[:id] %>" <%= request[:id] == request_id ? "selected" : "" %>>
10
+ <%= request[:id] %>: <%= request[:method] %> <%= request[:path] %>
11
+ </option>
12
+ <% end %>
13
+ </select>
14
+ </form>
15
+ <a href="" class="rack-insight_close">Close</a>
16
+ </div>
17
+ <% begin %>
18
+ <%= panel.content_for_request(request_id) %>
19
+ <% rescue Object => ex %>
20
+ <%= "Error #{ex.class.name}: #{ex.message} <!-- #{ex.backtrace[0..5]} -->" %>
21
+ <% end %>
22
+ </div>
23
+ <% end %>
24
+ <% end %>
25
+ </div>
@@ -0,0 +1,29 @@
1
+ <script type="text/javascript" charset="utf-8">
2
+ if (typeof jQuery == 'undefined') {
3
+ var jquery_url = '/__insight__/jquery-1.3.2.js';
4
+ document.write(unescape('%3Cscript src="' + jquery_url + '" type="text/javascript"%3E%3C/script%3E'));
5
+ }
6
+ </script>
7
+ <script type="text/javascript" src="/__insight__/jquery.tablesorter.min.js"></script>
8
+ <script type="text/javascript" src="/__insight__/bookmarklet.js"></script>
9
+ <script type="text/javascript" src="/__insight__/insight.js"></script>
10
+ <style type="text/css" media="screen">
11
+ @import url(/__insight__/insight.css);
12
+ </style>
13
+ <script>
14
+ $(function($) {
15
+ $.insight.request_id = <%= request_id %>
16
+ })
17
+ </script>
18
+
19
+ <div id="rack-insight" class="rack-insight_top">
20
+ <div id="rack-insight_toolbar">
21
+ <ul class="panels">
22
+ <%= headers_fragment %>
23
+ </ul>
24
+ </div>
25
+
26
+ <%= request_fragment %>
27
+
28
+ <div id="rack-insight_debug_window" class="panel_content"></div>
29
+ </div>
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rack/insight/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = %q{rack-insight}
6
+ s.version = Rack::Insight::VERSION
7
+
8
+ s.authors = ["Peter Boling", "Evan Dorn", "Judson Lester", "Bryan Helmkamp"]
9
+ s.email = %w{peter.boling@gmail.com evan@lrdesign.com judson@lrdesign.com bryan@brynary.com}
10
+ s.extra_rdoc_files = [
11
+ "README.md",
12
+ "LICENSE",
13
+ "CHANGELOG"
14
+ ]
15
+
16
+ s.files = `git ls-files`.split($\)
17
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
+ s.require_paths = ["lib"]
20
+
21
+ s.homepage = "https://github.com/pboling/rack-insight"
22
+ s.summary = %q{Debugging toolbar for Rack applications implemented as
23
+ middleware.}
24
+ s.description = %q{Debugging toolbar for Rack applications implemented as
25
+ middleware. Based on logical-insight and rack-bug. }
26
+
27
+ s.add_runtime_dependency("rack")
28
+ s.add_runtime_dependency("uuidtools", ">= 2.1.2") # incurs far fewer dependencies that the uuid gem, and no shell forking
29
+ s.add_runtime_dependency("sqlite3", ">= 1.3.3")
30
+ s.add_development_dependency "redcarpet"
31
+ s.add_development_dependency(%q<reek>, [">= 1.2.8"])
32
+ s.add_development_dependency(%q<roodi>, [">= 2.1.0"])
33
+ s.add_development_dependency(%q<rake>, [">= 0"])
34
+ s.add_development_dependency "rspec", ">= 2.11.0"
35
+ s.add_development_dependency "sinatra"
36
+ s.add_development_dependency "webrat"
37
+ s.add_development_dependency "ruby-debug19"
38
+
39
+
40
+ end
File without changes
@@ -0,0 +1,8 @@
1
+ require "rubygems"
2
+
3
+ $LOAD_PATH.unshift File.dirname(__FILE__)
4
+ require "sample_app"
5
+
6
+ #Example usage, but moved inside sample app for easier testing
7
+ #use Rack::Bug, :password => "secret"
8
+ run SampleApp
@@ -0,0 +1,2 @@
1
+ class DummyPanel < Rack::Insight::Panel
2
+ end
@@ -0,0 +1,72 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
2
+ require "sinatra/base"
3
+ require 'logger'
4
+
5
+ RAILS_ENV = "development" unless defined?(RAILS_ENV)
6
+ log_to = RAILS_ENV == "test" ? StringIO.new : STDOUT
7
+ LOGGER = Logger.new(log_to)
8
+
9
+ class SampleApp < Sinatra::Base
10
+ class OneLastThing
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ st,hd,bd = @app.call(env)
17
+ unless SampleApp.before_returning.nil?
18
+ SampleApp.before_returning.call
19
+ SampleApp.before_returning = nil
20
+ end
21
+ return st,hd,bd
22
+ end
23
+ end
24
+
25
+ class << self
26
+ attr_accessor :insight_app
27
+ attr_accessor :before_returning
28
+ def before_return(&block)
29
+ self.before_returning = block
30
+ end
31
+ end
32
+
33
+
34
+
35
+ use Rack::Insight::App, :log_path => "rack-insight-test.log", :on_initialize => proc {|app|
36
+ self.insight_app = app
37
+ }
38
+ use OneLastThing
39
+
40
+ set :environment, 'test'
41
+
42
+ configure :test do
43
+ set :raise_errors, true
44
+ end
45
+
46
+ get "/redirect" do
47
+ redirect "/"
48
+ end
49
+
50
+ get "/error" do
51
+ raise "Error!"
52
+ end
53
+
54
+ get "/" do
55
+ if params[:content_type]
56
+ headers["Content-Type"] = params[:content_type]
57
+ end
58
+ LOGGER.error "I am a log message"
59
+ <<-HTML
60
+ <html>
61
+ <head>
62
+ </head>
63
+ <body>
64
+ <p>Hello</p>
65
+ <p><a href="__insight__/bookmarklet.html">Page with bookmarklet for enabling Rack::Insight</a></p>
66
+ <p><a href="/error">Page with an error to check insight not rescuing errors</a></p>
67
+ </body>
68
+ </html>
69
+ HTML
70
+ end
71
+
72
+ end
@@ -0,0 +1 @@
1
+ class StarTrekPanel < Rack::Insight::Panel; end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::Insight do
4
+ before :each do
5
+ reset_insight
6
+ end
7
+
8
+ it "inserts the Rack::Insight toolbar" do
9
+ response = get "/"
10
+ response.should have_selector("div#rack-insight")
11
+ end
12
+
13
+ it "updates the Content-Length" do
14
+ response = get "/"
15
+ response["Content-Length"].should == response.body.size.to_s
16
+ end
17
+
18
+ it "serves the Rack::Insight assets under /__insight__/" do
19
+ response = get "/__insight__/insight.css"
20
+ response.should be_ok
21
+ end
22
+
23
+ it "modifies HTML responses with a charset" do
24
+ response = get "/", :content_type => "application/xhtml+xml; charset=utf-8"
25
+ response.should have_selector("div#rack-insight")
26
+ end
27
+
28
+ it "does not modify XMLHttpRequest responses" do
29
+ response = get "/", {}, { :xhr => true }
30
+ response.should_not have_selector("div#rack-insight")
31
+ end
32
+
33
+ it "modifies XHTML responses" do
34
+ response = get "/", :content_type => "application/xhtml+xml"
35
+ response.should have_selector("div#rack-insight")
36
+ end
37
+
38
+ it "does not modify non-HTML responses" do
39
+ response = get "/", :content_type => "text/csv"
40
+ response.should_not have_selector("div#rack-insight")
41
+ end
42
+
43
+ it "does not modify server errors" do
44
+ app.disable :raise_errors
45
+ response = get "/error"
46
+ app.enable :raise_errors
47
+ response.should_not have_selector("div#rack-insight")
48
+ end
49
+
50
+ context "redirected when not configured to intercept redirects" do
51
+ it "passes the redirect unmodified" do
52
+ response = get "/redirect"
53
+ response.status.should == 302
54
+ end
55
+
56
+ it "does not show the interception page" do
57
+ response = get "/redirect"
58
+ response.body.should_not contain("Location: /")
59
+ end
60
+
61
+ it "does not insert the toolbar" do
62
+ header 'cookie', ""
63
+ response = get "/redirect"
64
+ response.should_not have_selector("div#rack-insight")
65
+ end
66
+
67
+ it "does not insert the toolbar if even toolbar requested" do
68
+ response = get "/redirect"
69
+ response.should_not have_selector("div#rack-insight")
70
+ end
71
+ end
72
+
73
+ context "redirected when configured to intercept redirects" do
74
+ before :each do
75
+ app.insight_app.intercept_redirects = true
76
+ end
77
+
78
+ it "shows the interception page" do
79
+ response = get "/redirect"
80
+ response.should have_selector("div#rack-insight")
81
+ end
82
+
83
+ it "should provide a link to the target URL" do
84
+ response = get "/redirect"
85
+ response.should have_selector("a[href='http://example.org/']")
86
+ end
87
+
88
+ it "inserts the toolbar if requested" do
89
+ response = get "/redirect"
90
+ response.should have_selector("div#rack-insight")
91
+ end
92
+
93
+ it "does not inserts the toolbar if not requested" do
94
+ header 'cookie', ""
95
+ response = get "/redirect"
96
+ response.should_not have_selector("div#rack-insight")
97
+ end
98
+ end
99
+
100
+ context "configured with an IP address restriction" do
101
+ before do
102
+ app.insight_app.ip_masks = [IPAddr.new("127.0.0.1/255.255.255.0")]
103
+ end
104
+
105
+ it "inserts the Rack::Insight toolbar when the IP matches" do
106
+ response = get_via_rack "/", {}, "REMOTE_ADDR" => "127.0.0.2"
107
+ response.should have_selector("div#rack-insight")
108
+ end
109
+
110
+ it "is disabled when the IP doesn't match" do
111
+ response = get_via_rack "/", {}, "REMOTE_ADDR" => "128.0.0.1"
112
+ response.should_not have_selector("div#rack-insight")
113
+ end
114
+
115
+ it "doesn't use any panels" do
116
+ DummyPanel.should_not_receive(:new)
117
+ app.insight_app.panel_classes = [DummyPanel]
118
+ get_via_rack "/", {}, "REMOTE_ADDR" => "128.0.0.1"
119
+ end
120
+ end
121
+
122
+ context "configured with a password" do
123
+ before do
124
+ app.insight_app.password = "secret"
125
+ end
126
+
127
+ it "should insert the Rack::Insight toolbar when the password matches" do
128
+ sha = Digest::SHA1.hexdigest ["rack-insight", "secret"].join(":")
129
+ set_cookie ["rack-insight_enabled=1", "rack-insight_password=#{sha}"]
130
+ response = get_via_rack "/"
131
+ response.should have_selector("div#rack-insight")
132
+ end
133
+
134
+ it "should be disabled when the password doesn't match" do
135
+ response = get_via_rack "/"
136
+ response.should_not have_selector("div#rack-insight")
137
+ end
138
+ it "doesn't use any panels" do
139
+ DummyPanel.should_not_receive(:new)
140
+ app.insight_app.panel_classes = [DummyPanel]
141
+ get_via_rack "/"
142
+ end
143
+ end
144
+
145
+ context "configured with a SQLite database file path" do
146
+ before do
147
+ # We need to pass the SQLite database file path to the gem
148
+ require 'fileutils'
149
+ FileUtils.rm_rf("my_custom_db_path.sqlite") #because it doesn't count if it's already there
150
+ reset_insight :database_path => 'my_custom_db_path.sqlite'
151
+ end
152
+
153
+ it "should create a database at the path specified in the options" do
154
+ File.exist?('my_custom_db_path.sqlite').should be_true
155
+ end
156
+
157
+ after do
158
+ FileUtils.rm_rf("my_custom_db_path.sqlite")
159
+ reset_insight :database_path => nil
160
+ end
161
+
162
+ end
163
+ end
@@ -0,0 +1,188 @@
1
+ require 'rack/insight/instrumentation'
2
+ require 'rack/insight/instrumentation/setup'
3
+
4
+ class One
5
+ def initialize(arry)
6
+ @array = arry
7
+ end
8
+
9
+ def self.record_self(array)
10
+ array << self
11
+ end
12
+
13
+ def self.a_class_method(array)
14
+ yield(array)
15
+ end
16
+
17
+ def an_instance_method()
18
+ yield(@array)
19
+ end
20
+ end
21
+
22
+ module Mod
23
+ def module_method(array)
24
+ yield(array)
25
+ end
26
+ end
27
+
28
+ class Two < One
29
+ def an_instance_method
30
+ super
31
+ end
32
+
33
+ def self.a_class_method(array)
34
+ super
35
+ end
36
+ end
37
+
38
+ describe "Setting up probes" do
39
+ let :method_calls do [] end
40
+ let :method_subject do [] end
41
+ let :recording_list do [] end
42
+
43
+ let :test_collector do
44
+ collector = Object.new
45
+ collector.extend Rack::Insight::Instrumentation::Client
46
+ collector.instance_variable_set("@calls", method_calls)
47
+ def collector.after_detect(method_call, timing, arguments, results)
48
+ @calls << [method_call, timing, arguments, results]
49
+ end
50
+ collector
51
+ end
52
+
53
+ let :instrument_setup do
54
+ Rack::Insight::Instrumentation::Setup.new(nil)
55
+ end
56
+
57
+ let :fake_env do
58
+ {}
59
+ end
60
+
61
+ before :each do
62
+ test_collector.probe(test_collector) do
63
+ instrument "One" do
64
+ instance_probe :an_instance_method
65
+ class_probe :a_class_method
66
+ class_probe :record_self
67
+ class_probe :allocate
68
+ end
69
+ end
70
+ instrument_setup.setup(fake_env)
71
+ end
72
+
73
+ after :each do
74
+ instrument_setup.teardown(fake_env, 200, {}, "")
75
+ end
76
+
77
+ # Test cases:
78
+ #
79
+ # Methods are called on
80
+ # instance
81
+ # class
82
+ # modules
83
+ #
84
+ # Methods are defined/probed at/called on
85
+ # Called on:
86
+ # obj: instance of class C
87
+ #
88
+ # Defined:
89
+ # class C
90
+ # super class B
91
+ # class C and parent B (overridden)
92
+ # module Mc - included in C
93
+ # class C and Mc
94
+ # module Mb - included in B
95
+ # class C and Mb
96
+ # module Me - extended in obj
97
+ # Me and C - Me overrides C
98
+ #
99
+ # Probed:
100
+ # On C
101
+ # On B
102
+ # On Mc, Mb, Me
103
+ #
104
+ # Not interfere with:
105
+ # Arguments
106
+ # Blocks
107
+ # Return Values
108
+ # Exceptions
109
+ #
110
+
111
+ it "should catch class methods defined on a superclass" do
112
+ #expect do
113
+ One.allocate
114
+ #end.to change(method_calls.length).by(1)
115
+ method_calls.last[0].method.should == :allocate
116
+ end
117
+
118
+ it "should not interfere with instance method call on One" do
119
+ expect do
120
+ One.new(method_subject).an_instance_method{|arr| arr << __LINE__}
121
+ end.to change{method_subject.length}.by(1)
122
+ end
123
+
124
+ it "should not interfere with class method call" do
125
+ expect do
126
+ One.a_class_method(method_subject){|arr| arr << __LINE__}
127
+ end.to change{method_subject.length}.by(1)
128
+ end
129
+
130
+ it "should collect calls made on One#an_instance_method" do
131
+ expect do
132
+ One.new(method_subject).an_instance_method{|arr| arr << __LINE__}
133
+ end.to change{method_calls.length}.by(1)
134
+ method_calls.last[0].method.should == :an_instance_method
135
+ end
136
+
137
+ it "should collect calls made on One#a_class_method" do
138
+ expect do
139
+ One.a_class_method(method_subject){|arr| arr << __LINE__}
140
+ end.to change{method_calls.length}.by(1)
141
+ method_calls.last[0].method.should == :a_class_method
142
+ end
143
+
144
+ it "should not mess with receive of class methods" do
145
+ One.record_self(recording_list)
146
+ recording_list.should include(One)
147
+ end
148
+
149
+ it "should not mess with receive of class methods on subclasses" do
150
+ Two.record_self(recording_list)
151
+ recording_list.should include(Two)
152
+ end
153
+
154
+
155
+ it "should not interfere with instance method call on Two" do
156
+ expect do
157
+ Two.new(method_subject).an_instance_method{|arr| arr << __LINE__}
158
+ end.to change{method_subject.length}.by(1)
159
+ end
160
+
161
+ it "should not interfere with class method call" do
162
+ expect do
163
+ Two.a_class_method(method_subject){|arr| arr << __LINE__}
164
+ end.to change{method_subject.length}.by(1)
165
+ end
166
+
167
+ it "should collect calls made on Two#an_instance_method" do
168
+ expect do
169
+ Two.new(method_subject).an_instance_method{|arr| arr << __LINE__}
170
+ end.to change{method_calls.length}.by(2)
171
+ method_calls.each do |method_call|
172
+ method_call[0].method.should == :an_instance_method
173
+ end
174
+
175
+ method_calls.map{|mc| mc[0].context}.should include("One", "Two")
176
+ end
177
+
178
+ it "should collect calls made on Two#a_class_method" do
179
+ expect do
180
+ Two.a_class_method(method_subject){|arr| arr << __LINE__}
181
+ end.to change{method_calls.length}.by(2)
182
+ method_calls.each do |method_call|
183
+ method_call[0].method.should == :a_class_method
184
+ end
185
+
186
+ method_calls.map{|mc| mc[0].context}.should include("One", "Two")
187
+ end
188
+ end