logical-insight 0.4.0
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.
- data/History.txt +45 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.md +123 -0
- data/Rakefile +24 -0
- data/Thorfile +113 -0
- data/lib/insight.rb +17 -0
- data/lib/insight/app.rb +189 -0
- data/lib/insight/database.rb +186 -0
- data/lib/insight/enable-button.rb +43 -0
- data/lib/insight/filtered_backtrace.rb +45 -0
- data/lib/insight/instrumentation.rb +9 -0
- data/lib/insight/instrumentation/backstage.rb +10 -0
- data/lib/insight/instrumentation/client.rb +20 -0
- data/lib/insight/instrumentation/instrument.rb +109 -0
- data/lib/insight/instrumentation/package-definition.rb +58 -0
- data/lib/insight/instrumentation/probe-definition.rb +20 -0
- data/lib/insight/instrumentation/probe.rb +199 -0
- data/lib/insight/instrumentation/setup.rb +32 -0
- data/lib/insight/logger.rb +55 -0
- data/lib/insight/options.rb +102 -0
- data/lib/insight/panel.rb +119 -0
- data/lib/insight/panel_app.rb +31 -0
- data/lib/insight/panels-content.rb +22 -0
- data/lib/insight/panels-header.rb +18 -0
- data/lib/insight/panels/active_record_panel.rb +46 -0
- data/lib/insight/panels/cache_panel.rb +69 -0
- data/lib/insight/panels/cache_panel/panel_app.rb +46 -0
- data/lib/insight/panels/cache_panel/stats.rb +98 -0
- data/lib/insight/panels/log_panel.rb +54 -0
- data/lib/insight/panels/memory_panel.rb +32 -0
- data/lib/insight/panels/rails_info_panel.rb +19 -0
- data/lib/insight/panels/redis_panel.rb +42 -0
- data/lib/insight/panels/redis_panel/redis_extension.rb +23 -0
- data/lib/insight/panels/redis_panel/stats.rb +50 -0
- data/lib/insight/panels/request_variables_panel.rb +70 -0
- data/lib/insight/panels/speedtracer_panel.rb +89 -0
- data/lib/insight/panels/speedtracer_panel/trace-app.rb +52 -0
- data/lib/insight/panels/speedtracer_panel/tracer.rb +212 -0
- data/lib/insight/panels/sql_panel.rb +53 -0
- data/lib/insight/panels/sql_panel/panel_app.rb +37 -0
- data/lib/insight/panels/sql_panel/query.rb +94 -0
- data/lib/insight/panels/templates_panel.rb +58 -0
- data/lib/insight/panels/templates_panel/rendering.rb +81 -0
- data/lib/insight/panels/timer_panel.rb +40 -0
- data/lib/insight/params_signature.rb +61 -0
- data/lib/insight/public/__insight__/bookmarklet.html +10 -0
- data/lib/insight/public/__insight__/bookmarklet.js +223 -0
- data/lib/insight/public/__insight__/insight.css +235 -0
- data/lib/insight/public/__insight__/insight.js +123 -0
- data/lib/insight/public/__insight__/jquery-1.3.2.js +4376 -0
- data/lib/insight/public/__insight__/jquery.tablesorter.min.js +1 -0
- data/lib/insight/public/__insight__/spinner.gif +0 -0
- data/lib/insight/rack_static_bug_avoider.rb +16 -0
- data/lib/insight/redirect_interceptor.rb +25 -0
- data/lib/insight/render.rb +72 -0
- data/lib/insight/request-recorder.rb +23 -0
- data/lib/insight/toolbar.rb +63 -0
- data/lib/insight/views/enable-button.html.erb +1 -0
- data/lib/insight/views/error.html.erb +17 -0
- data/lib/insight/views/headers_fragment.html.erb +20 -0
- data/lib/insight/views/panels/active_record.html.erb +17 -0
- data/lib/insight/views/panels/cache.html.erb +93 -0
- data/lib/insight/views/panels/execute_sql.html.erb +32 -0
- data/lib/insight/views/panels/explain_sql.html.erb +32 -0
- data/lib/insight/views/panels/log.html.erb +21 -0
- data/lib/insight/views/panels/profile_sql.html.erb +32 -0
- data/lib/insight/views/panels/rails_info.html.erb +19 -0
- data/lib/insight/views/panels/redis.html.erb +46 -0
- data/lib/insight/views/panels/request_variables.html.erb +25 -0
- data/lib/insight/views/panels/speedtracer/serverevent.html.erb +10 -0
- data/lib/insight/views/panels/speedtracer/servertrace.html.erb +12 -0
- data/lib/insight/views/panels/speedtracer/traces.html.erb +18 -0
- data/lib/insight/views/panels/sql.html.erb +43 -0
- data/lib/insight/views/panels/templates.html.erb +6 -0
- data/lib/insight/views/panels/timer.html.erb +19 -0
- data/lib/insight/views/panels/view_cache.html.erb +19 -0
- data/lib/insight/views/redirect.html.erb +16 -0
- data/lib/insight/views/request_fragment.html.erb +25 -0
- data/lib/insight/views/toolbar.html.erb +29 -0
- data/lib/logical-insight.rb +1 -0
- data/spec/custom_matchers.rb +31 -0
- data/spec/fixtures/config.ru +8 -0
- data/spec/fixtures/dummy_panel.rb +2 -0
- data/spec/fixtures/sample_app.rb +72 -0
- data/spec/insight/panels/active_record_panel_spec.rb +42 -0
- data/spec/insight/panels/cache_panel_spec.rb +176 -0
- data/spec/insight/panels/log_panel_spec.rb +44 -0
- data/spec/insight/panels/memory_panel_spec.rb +19 -0
- data/spec/insight/panels/mongo_panel_spec_pending.rb +50 -0
- data/spec/insight/panels/rails_info_panel_spec.rb +27 -0
- data/spec/insight/panels/redis_panel_spec.rb +66 -0
- data/spec/insight/panels/sql_panel_spec.rb +145 -0
- data/spec/insight/panels/templates_panel_spec.rb +84 -0
- data/spec/insight/panels/timer_panel_spec.rb +36 -0
- data/spec/insight_spec.rb +141 -0
- data/spec/instrumentation_spec.rb +188 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +93 -0
- metadata +187 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Insight
|
|
2
|
+
describe "TemplatesPanel" do
|
|
3
|
+
before do
|
|
4
|
+
mock_constant("ActionView::Template")
|
|
5
|
+
reset_insight :panel_classes => [TemplatesPanel]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe "heading" do
|
|
9
|
+
it "displays the total rendering time" do
|
|
10
|
+
response = get_via_rack "/"
|
|
11
|
+
response.should have_heading("Templates: 0.00ms")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def mock_template(path)
|
|
16
|
+
template = stub("ActionView::Template")
|
|
17
|
+
template.stub!(:virtual_path => path)
|
|
18
|
+
template
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "content" do
|
|
22
|
+
it "displays the template paths" do
|
|
23
|
+
app.before_return do
|
|
24
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/show"))
|
|
25
|
+
end
|
|
26
|
+
response = get_via_rack "/"
|
|
27
|
+
response.should contain("users/show")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "displays the template children" do
|
|
31
|
+
app.before_return do
|
|
32
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/show")) do
|
|
33
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/toolbar"))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
response = get_via_rack "/"
|
|
37
|
+
response.should have_selector("li", :content => "users/show") do |li|
|
|
38
|
+
li.should contain("users/toolbar")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "for templates that rendered templates" do
|
|
43
|
+
it "displays the total time" do
|
|
44
|
+
app.before_return do
|
|
45
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/show")) do
|
|
46
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/toolbar"))
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
response = get_via_rack "/"
|
|
51
|
+
response.should have_selector("li", :content => "users/show") do |li|
|
|
52
|
+
li.should contain(TIME_MS_REGEXP)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "displays the exclusive time" do
|
|
57
|
+
app.before_return do
|
|
58
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/show")) do
|
|
59
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/toolbar"))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
response = get_via_rack "/"
|
|
64
|
+
response.should have_selector("li", :content => "users/show") do |li|
|
|
65
|
+
li.should contain(/\d\.\d{2} exclusive/)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "for leaf templates" do
|
|
71
|
+
it "does not display the exclusive time" do
|
|
72
|
+
app.before_return do
|
|
73
|
+
mock_method_call("ActionView::Template", :render, [], :instance, mock_template("users/show"))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
response = get_via_rack "/"
|
|
77
|
+
response.should contain("users/show") do |li|
|
|
78
|
+
li.should_not contain("exclusive")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Insight
|
|
2
|
+
describe "TimerPanel" do
|
|
3
|
+
before do
|
|
4
|
+
reset_insight :panel_classes => [TimerPanel]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
describe "heading" do
|
|
8
|
+
it "displays the elapsed time" do
|
|
9
|
+
response = get_via_rack "/"
|
|
10
|
+
response.should have_heading(TIME_MS_REGEXP)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "content" do
|
|
15
|
+
it "displays the user CPU time" do
|
|
16
|
+
response = get_via_rack "/"
|
|
17
|
+
response.should have_row("#timer", "User CPU time", TIME_MS_REGEXP)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "displays the system CPU time" do
|
|
21
|
+
response = get_via_rack "/"
|
|
22
|
+
response.should have_row("#timer", "System CPU time", TIME_MS_REGEXP)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "displays the total CPU time" do
|
|
26
|
+
response = get_via_rack "/"
|
|
27
|
+
response.should have_row("#timer", "Total CPU time", TIME_MS_REGEXP)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "displays the elapsed time" do
|
|
31
|
+
response = get_via_rack "/"
|
|
32
|
+
response.should have_row("#timer", "Elapsed time", TIME_MS_REGEXP)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
require 'logical-insight'
|
|
3
|
+
|
|
4
|
+
describe Insight do
|
|
5
|
+
before :each do
|
|
6
|
+
reset_insight
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "inserts the Insight toolbar" do
|
|
10
|
+
response = get "/"
|
|
11
|
+
response.should have_selector("div#insight")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "updates the Content-Length" do
|
|
15
|
+
response = get "/"
|
|
16
|
+
response["Content-Length"].should == response.body.size.to_s
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "serves the Insight assets under /__insight__/" do
|
|
20
|
+
response = get "/__insight__/insight.css"
|
|
21
|
+
response.should be_ok
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "modifies HTML responses with a charset" do
|
|
25
|
+
response = get "/", :content_type => "application/xhtml+xml; charset=utf-8"
|
|
26
|
+
response.should have_selector("div#insight")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "does not modify XMLHttpRequest responses" do
|
|
30
|
+
response = get "/", {}, { :xhr => true }
|
|
31
|
+
response.should_not have_selector("div#insight")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "modifies XHTML responses" do
|
|
35
|
+
response = get "/", :content_type => "application/xhtml+xml"
|
|
36
|
+
response.should have_selector("div#insight")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "does not modify non-HTML responses" do
|
|
40
|
+
response = get "/", :content_type => "text/csv"
|
|
41
|
+
response.should_not have_selector("div#insight")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "does not modify server errors" do
|
|
45
|
+
app.disable :raise_errors
|
|
46
|
+
response = get "/error"
|
|
47
|
+
app.enable :raise_errors
|
|
48
|
+
response.should_not have_selector("div#insight")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "redirected when not configured to intercept redirects" do
|
|
52
|
+
it "passes the redirect unmodified" do
|
|
53
|
+
response = get "/redirect"
|
|
54
|
+
response.status.should == 302
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "does not show the interception page" do
|
|
58
|
+
response = get "/redirect"
|
|
59
|
+
response.body.should_not contain("Location: /")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "does not insert the toolbar" do
|
|
63
|
+
header 'cookie', ""
|
|
64
|
+
response = get "/redirect"
|
|
65
|
+
response.should_not have_selector("div#insight")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "does not insert the toolbar if even toolbar requested" do
|
|
69
|
+
response = get "/redirect"
|
|
70
|
+
response.should_not have_selector("div#insight")
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "redirected when configured to intercept redirects" do
|
|
75
|
+
it "shows the interception page" do
|
|
76
|
+
response = get "/redirect", {}, "insight.intercept_redirects" => true
|
|
77
|
+
response.should have_selector("div#insight")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should provide a link to the target URL" do
|
|
81
|
+
response = get "/redirect", {}, "insight.intercept_redirects" => true
|
|
82
|
+
response.should have_selector("a[href='http://example.org/']")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "inserts the toolbar if requested" do
|
|
86
|
+
response = get "/redirect", {}, "insight.intercept_redirects" => true
|
|
87
|
+
response.should have_selector("div#insight")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "does not inserts the toolbar if not requested" do
|
|
91
|
+
header 'cookie', ""
|
|
92
|
+
response = get "/redirect", {}, "insight.intercept_redirects" => true
|
|
93
|
+
response.should_not have_selector("div#insight")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context "configured with an IP address restriction" do
|
|
98
|
+
before do
|
|
99
|
+
rack_env "insight.ip_masks", [IPAddr.new("127.0.0.1/255.255.255.0")]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "inserts the Insight toolbar when the IP matches" do
|
|
103
|
+
response = get_via_rack "/", {}, "REMOTE_ADDR" => "127.0.0.2"
|
|
104
|
+
response.should have_selector("div#insight")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "is disabled when the IP doesn't match" do
|
|
108
|
+
response = get_via_rack "/", {}, "REMOTE_ADDR" => "128.0.0.1"
|
|
109
|
+
response.should_not have_selector("div#insight")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "doesn't use any panels" do
|
|
113
|
+
DummyPanel.should_not_receive(:new)
|
|
114
|
+
rack_env "insight.panel_classes", [DummyPanel]
|
|
115
|
+
get_via_rack "/", {}, "REMOTE_ADDR" => "128.0.0.1"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "configured with a password" do
|
|
120
|
+
before do
|
|
121
|
+
rack_env "insight.password", "secret"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should insert the Insight toolbar when the password matches" do
|
|
125
|
+
sha = Digest::SHA1.hexdigest ["insight", "secret"].join(":")
|
|
126
|
+
set_cookie ["insight_enabled=1", "insight_password=#{sha}"]
|
|
127
|
+
response = get_via_rack "/"
|
|
128
|
+
response.should have_selector("div#insight")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should be disabled when the password doesn't match" do
|
|
132
|
+
response = get_via_rack "/"
|
|
133
|
+
response.should_not have_selector("div#insight")
|
|
134
|
+
end
|
|
135
|
+
it "doesn't use any panels" do
|
|
136
|
+
DummyPanel.should_not_receive(:new)
|
|
137
|
+
rack_env "insight.panel_classes", [DummyPanel]
|
|
138
|
+
get_via_rack "/"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
require 'insight/instrumentation'
|
|
2
|
+
require '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 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
|
+
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
|