appmap 0.27.0 → 0.33.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -3
- data/CHANGELOG.md +37 -0
- data/README.md +170 -29
- data/Rakefile +1 -1
- data/appmap.gemspec +1 -0
- data/exe/appmap +3 -1
- data/lib/appmap.rb +54 -38
- data/lib/appmap/algorithm/stats.rb +2 -1
- data/lib/appmap/class_map.rb +21 -28
- data/lib/appmap/command/record.rb +2 -61
- data/lib/appmap/config.rb +89 -0
- data/lib/appmap/cucumber.rb +89 -0
- data/lib/appmap/event.rb +28 -19
- data/lib/appmap/hook.rb +56 -128
- data/lib/appmap/hook/method.rb +78 -0
- data/lib/appmap/metadata.rb +62 -0
- data/lib/appmap/middleware/remote_recording.rb +2 -6
- data/lib/appmap/minitest.rb +141 -0
- data/lib/appmap/open.rb +57 -0
- data/lib/appmap/rails/action_handler.rb +7 -7
- data/lib/appmap/rails/sql_handler.rb +10 -8
- data/lib/appmap/railtie.rb +2 -2
- data/lib/appmap/record.rb +27 -0
- data/lib/appmap/rspec.rb +9 -37
- data/lib/appmap/trace.rb +18 -10
- data/lib/appmap/util.rb +59 -0
- data/lib/appmap/version.rb +1 -1
- data/package-lock.json +3 -3
- data/spec/abstract_controller4_base_spec.rb +1 -1
- data/spec/abstract_controller_base_spec.rb +9 -2
- data/spec/config_spec.rb +3 -3
- data/spec/fixtures/hook/compare.rb +7 -0
- data/spec/fixtures/hook/singleton_method.rb +54 -0
- data/spec/fixtures/rails_users_app/Gemfile +1 -0
- data/spec/fixtures/rails_users_app/features/api_users.feature +13 -0
- data/spec/fixtures/rails_users_app/features/support/env.rb +4 -0
- data/spec/fixtures/rails_users_app/features/support/hooks.rb +11 -0
- data/spec/fixtures/rails_users_app/features/support/steps.rb +18 -0
- data/spec/hook_spec.rb +228 -53
- data/spec/open_spec.rb +19 -0
- data/spec/rails_spec_helper.rb +2 -0
- data/spec/record_sql_rails_pg_spec.rb +56 -33
- data/spec/rspec_feature_metadata_spec.rb +2 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/util_spec.rb +21 -0
- data/test/cli_test.rb +4 -4
- data/test/cucumber_test.rb +72 -0
- data/test/fixtures/cucumber4_recorder/Gemfile +5 -0
- data/test/fixtures/cucumber4_recorder/appmap.yml +3 -0
- data/test/fixtures/cucumber4_recorder/features/say_hello.feature +5 -0
- data/test/fixtures/cucumber4_recorder/features/support/env.rb +5 -0
- data/test/fixtures/cucumber4_recorder/features/support/hooks.rb +11 -0
- data/test/fixtures/cucumber4_recorder/features/support/steps.rb +9 -0
- data/test/fixtures/cucumber4_recorder/lib/hello.rb +7 -0
- data/test/fixtures/cucumber_recorder/Gemfile +5 -0
- data/test/fixtures/cucumber_recorder/appmap.yml +3 -0
- data/test/fixtures/cucumber_recorder/features/say_hello.feature +5 -0
- data/test/fixtures/cucumber_recorder/features/support/env.rb +5 -0
- data/test/fixtures/cucumber_recorder/features/support/hooks.rb +11 -0
- data/test/fixtures/cucumber_recorder/features/support/steps.rb +9 -0
- data/test/fixtures/cucumber_recorder/lib/hello.rb +7 -0
- data/test/fixtures/minitest_recorder/Gemfile +5 -0
- data/test/fixtures/minitest_recorder/appmap.yml +3 -0
- data/test/fixtures/minitest_recorder/lib/hello.rb +5 -0
- data/test/fixtures/minitest_recorder/test/hello_test.rb +12 -0
- data/test/fixtures/process_recorder/appmap.yml +3 -0
- data/test/fixtures/process_recorder/hello.rb +9 -0
- data/test/minitest_test.rb +38 -0
- data/test/record_process_test.rb +35 -0
- data/test/test_helper.rb +1 -0
- metadata +55 -3
- data/spec/fixtures/hook/class_method.rb +0 -17
@@ -47,18 +47,18 @@ describe 'AbstractControllerBase' do
|
|
47
47
|
SERVER_REQUEST
|
48
48
|
end
|
49
49
|
|
50
|
-
it '
|
50
|
+
it 'properly captures method parameters in the appmap' do
|
51
51
|
expect(File).to exist(appmap_json)
|
52
52
|
appmap = JSON.parse(File.read(appmap_json)).to_yaml
|
53
53
|
|
54
54
|
expect(appmap).to match(<<-CREATE_CALL.strip)
|
55
55
|
event: call
|
56
|
+
thread_id: .*
|
56
57
|
defined_class: Api::UsersController
|
57
58
|
method_id: build_user
|
58
59
|
path: app/controllers/api/users_controller.rb
|
59
60
|
lineno: 23
|
60
61
|
static: false
|
61
|
-
thread_id: .*
|
62
62
|
parameters:
|
63
63
|
- name: params
|
64
64
|
class: ActiveSupport::HashWithIndifferentAccess
|
@@ -68,5 +68,12 @@ describe 'AbstractControllerBase' do
|
|
68
68
|
receiver:
|
69
69
|
CREATE_CALL
|
70
70
|
end
|
71
|
+
|
72
|
+
it 'returns a minimal event' do
|
73
|
+
expect(File).to exist(appmap_json)
|
74
|
+
appmap = JSON.parse(File.read(appmap_json))
|
75
|
+
event = appmap['events'].find { |event| event['event'] == 'return' && event['return_value'] }
|
76
|
+
expect(event.keys).to eq(%w[id event thread_id parent_id elapsed return_value])
|
77
|
+
end
|
71
78
|
end
|
72
79
|
end
|
data/spec/config_spec.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'rails_spec_helper'
|
4
4
|
require 'active_support/core_ext'
|
5
|
-
require 'appmap/
|
5
|
+
require 'appmap/config'
|
6
6
|
|
7
|
-
describe AppMap::
|
7
|
+
describe AppMap::Config, docker: false do
|
8
8
|
it 'loads from a Hash' do
|
9
9
|
config_data = {
|
10
10
|
name: 'test',
|
@@ -18,7 +18,7 @@ describe AppMap::Hook::Config do
|
|
18
18
|
}
|
19
19
|
]
|
20
20
|
}.deep_stringify_keys!
|
21
|
-
config = AppMap::
|
21
|
+
config = AppMap::Config.load(config_data)
|
22
22
|
|
23
23
|
expect(config.to_h.deep_stringify_keys!).to eq(config_data)
|
24
24
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SingletonMethod
|
4
|
+
class << self
|
5
|
+
def say_default
|
6
|
+
'default'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def SingletonMethod.say_class_defined
|
11
|
+
'defined with explicit class scope'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.say_self_defined
|
15
|
+
'defined with self class scope'
|
16
|
+
end
|
17
|
+
|
18
|
+
# When called, do_include calls +include+ to bring in the module
|
19
|
+
# AddMethod. AddMethod defines a new instance method, which gets
|
20
|
+
# added to the singleton class of SingletonMethod.
|
21
|
+
def do_include
|
22
|
+
class << self
|
23
|
+
SingletonMethod.include(AddMethod)
|
24
|
+
end
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.new_with_instance_method
|
29
|
+
SingletonMethod.new.tap do |m|
|
30
|
+
def m.say_instance_defined
|
31
|
+
'defined for an instance'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
'Singleton Method fixture'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module AddMethod
|
42
|
+
def self.included(base)
|
43
|
+
base.module_eval do
|
44
|
+
define_method "added_method" do
|
45
|
+
_added_method
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def _added_method
|
51
|
+
'defined by including a module'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -39,6 +39,7 @@ appmap_options = \
|
|
39
39
|
gem 'appmap', appmap_options
|
40
40
|
|
41
41
|
group :development, :test do
|
42
|
+
gem 'cucumber-rails', require: false
|
42
43
|
gem 'rspec-rails'
|
43
44
|
# Required for Sequel, since without ActiveRecord, the Rails transactional fixture support
|
44
45
|
# isn't activated.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: /api/users
|
2
|
+
|
3
|
+
@appmap-disable
|
4
|
+
Scenario: A user can be created
|
5
|
+
When I create a user
|
6
|
+
Then the response status should be 201
|
7
|
+
|
8
|
+
Scenario: When a user is created, it should be in the user list
|
9
|
+
Given I create a user
|
10
|
+
And the response status should be 201
|
11
|
+
When I list the users
|
12
|
+
Then the response status should be 200
|
13
|
+
And the response should include the user
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
When 'I create a user' do
|
4
|
+
@response = post '/api/users', login: 'alice'
|
5
|
+
end
|
6
|
+
|
7
|
+
Then(/the response status should be (\d+)/) do |status|
|
8
|
+
expect(@response.status).to eq(status.to_i)
|
9
|
+
end
|
10
|
+
|
11
|
+
When 'I list the users' do
|
12
|
+
@response = get '/api/users'
|
13
|
+
@users = JSON.parse(@response.body)
|
14
|
+
end
|
15
|
+
|
16
|
+
Then 'the response should include the user' do
|
17
|
+
expect(@users.map { |u| u['login'] }).to include('alice')
|
18
|
+
end
|
data/spec/hook_spec.rb
CHANGED
@@ -5,49 +5,50 @@ require 'appmap/hook'
|
|
5
5
|
require 'appmap/event'
|
6
6
|
require 'diffy'
|
7
7
|
|
8
|
-
|
8
|
+
# Show nulls as the literal +null+, rather than just leaving the field
|
9
|
+
# empty. This make some of the expected YAML below easier to
|
10
|
+
# understand.
|
11
|
+
module ShowYamlNulls
|
12
|
+
def visit_NilClass(o)
|
13
|
+
@emitter.scalar('null', nil, 'tag:yaml.org,2002:null', true, false, Psych::Nodes::Scalar::ANY)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
Psych::Visitors::YAMLTree.prepend(ShowYamlNulls)
|
17
|
+
|
18
|
+
describe 'AppMap class Hooking', docker: false do
|
19
|
+
require 'appmap/util'
|
9
20
|
def collect_events(tracer)
|
10
21
|
[].tap do |events|
|
11
22
|
while tracer.event?
|
12
23
|
events << tracer.next_event.to_h
|
13
24
|
end
|
14
|
-
end.map
|
15
|
-
event.delete(:thread_id)
|
16
|
-
event.delete(:elapsed)
|
17
|
-
delete_object_id = ->(obj) { (obj || {}).delete(:object_id) }
|
18
|
-
delete_object_id.call(event[:receiver])
|
19
|
-
delete_object_id.call(event[:return_value])
|
20
|
-
(event[:parameters] || []).each(&delete_object_id)
|
21
|
-
(event[:exceptions] || []).each(&delete_object_id)
|
22
|
-
|
23
|
-
if event[:event] == :return
|
24
|
-
# These should be removed from the appmap spec
|
25
|
-
%i[defined_class method_id path lineno static].each do |obsolete_field|
|
26
|
-
event.delete(obsolete_field)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
event
|
30
|
-
end.to_yaml
|
25
|
+
end.map(&AppMap::Util.method(:sanitize_event)).to_yaml
|
31
26
|
end
|
32
27
|
|
33
|
-
def invoke_test_file(file, &block)
|
34
|
-
|
35
|
-
|
36
|
-
AppMap::
|
37
|
-
|
38
|
-
tracer =
|
39
|
-
AppMap::
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
28
|
+
def invoke_test_file(file, setup: nil, &block)
|
29
|
+
AppMap.configuration = nil
|
30
|
+
package = AppMap::Package.new(file, nil, [])
|
31
|
+
config = AppMap::Config.new('hook_spec', [ package ])
|
32
|
+
AppMap.configuration = config
|
33
|
+
tracer = nil
|
34
|
+
AppMap::Hook.new(config).enable do
|
35
|
+
setup_result = setup.call if setup
|
36
|
+
|
37
|
+
tracer = AppMap.tracing.trace
|
38
|
+
AppMap::Event.reset_id_counter
|
39
|
+
begin
|
40
|
+
load file
|
41
|
+
yield setup_result
|
42
|
+
ensure
|
43
|
+
AppMap.tracing.delete(tracer)
|
44
|
+
end
|
45
45
|
end
|
46
|
+
|
46
47
|
[ config, tracer ]
|
47
48
|
end
|
48
49
|
|
49
|
-
def test_hook_behavior(file, events_yaml, &block)
|
50
|
-
config, tracer = invoke_test_file(file, &block)
|
50
|
+
def test_hook_behavior(file, events_yaml, setup: nil, &block)
|
51
|
+
config, tracer = invoke_test_file(file, setup: setup, &block)
|
51
52
|
|
52
53
|
events = collect_events(tracer)
|
53
54
|
expect(Diffy::Diff.new(events, events_yaml).to_s).to eq('')
|
@@ -55,6 +56,10 @@ describe 'AppMap class Hooking' do
|
|
55
56
|
[ config, tracer ]
|
56
57
|
end
|
57
58
|
|
59
|
+
after do
|
60
|
+
AppMap.configuration = nil
|
61
|
+
end
|
62
|
+
|
58
63
|
it 'hooks an instance method that takes no arguments' do
|
59
64
|
events_yaml = <<~YAML
|
60
65
|
---
|
@@ -76,7 +81,7 @@ describe 'AppMap class Hooking' do
|
|
76
81
|
:class: String
|
77
82
|
:value: default
|
78
83
|
YAML
|
79
|
-
|
84
|
+
test_hook_behavior 'spec/fixtures/hook/instance_method.rb', events_yaml do
|
80
85
|
expect(InstanceMethod.new.say_default).to eq('default')
|
81
86
|
end
|
82
87
|
end
|
@@ -86,14 +91,14 @@ describe 'AppMap class Hooking' do
|
|
86
91
|
InstanceMethod.new.say_default
|
87
92
|
end
|
88
93
|
expect(tracer.event_methods.to_a.map(&:defined_class)).to eq([ 'InstanceMethod' ])
|
89
|
-
expect(tracer.event_methods.to_a.map(&:
|
94
|
+
expect(tracer.event_methods.to_a.map(&:to_s)).to eq([ InstanceMethod.public_instance_method(:say_default).to_s ])
|
90
95
|
end
|
91
96
|
|
92
97
|
it 'builds a class map of invoked methods' do
|
93
|
-
|
98
|
+
_, tracer = invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
|
94
99
|
InstanceMethod.new.say_default
|
95
100
|
end
|
96
|
-
class_map = AppMap.class_map(
|
101
|
+
class_map = AppMap.class_map(tracer.event_methods).to_yaml
|
97
102
|
expect(Diffy::Diff.new(class_map, <<~YAML).to_s).to eq('')
|
98
103
|
---
|
99
104
|
- :name: spec/fixtures/hook/instance_method.rb
|
@@ -202,7 +207,7 @@ describe 'AppMap class Hooking' do
|
|
202
207
|
:parameters:
|
203
208
|
- :name: :kw
|
204
209
|
:class: NilClass
|
205
|
-
:value:
|
210
|
+
:value: null
|
206
211
|
:kind: :key
|
207
212
|
:receiver:
|
208
213
|
:class: InstanceMethod
|
@@ -232,7 +237,7 @@ describe 'AppMap class Hooking' do
|
|
232
237
|
:parameters:
|
233
238
|
- :name: :block
|
234
239
|
:class: NilClass
|
235
|
-
:value:
|
240
|
+
:value: null
|
236
241
|
:kind: :block
|
237
242
|
:receiver:
|
238
243
|
:class: InstanceMethod
|
@@ -254,15 +259,15 @@ describe 'AppMap class Hooking' do
|
|
254
259
|
---
|
255
260
|
- :id: 1
|
256
261
|
:event: :call
|
257
|
-
:defined_class:
|
262
|
+
:defined_class: SingletonMethod
|
258
263
|
:method_id: say_default
|
259
|
-
:path: spec/fixtures/hook/
|
264
|
+
:path: spec/fixtures/hook/singleton_method.rb
|
260
265
|
:lineno: 5
|
261
266
|
:static: true
|
262
267
|
:parameters: []
|
263
268
|
:receiver:
|
264
269
|
:class: Class
|
265
|
-
:value:
|
270
|
+
:value: SingletonMethod
|
266
271
|
- :id: 2
|
267
272
|
:event: :return
|
268
273
|
:parent_id: 1
|
@@ -270,8 +275,8 @@ describe 'AppMap class Hooking' do
|
|
270
275
|
:class: String
|
271
276
|
:value: default
|
272
277
|
YAML
|
273
|
-
test_hook_behavior 'spec/fixtures/hook/
|
274
|
-
expect(
|
278
|
+
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
|
279
|
+
expect(SingletonMethod.say_default).to eq('default')
|
275
280
|
end
|
276
281
|
end
|
277
282
|
|
@@ -280,15 +285,15 @@ describe 'AppMap class Hooking' do
|
|
280
285
|
---
|
281
286
|
- :id: 1
|
282
287
|
:event: :call
|
283
|
-
:defined_class:
|
288
|
+
:defined_class: SingletonMethod
|
284
289
|
:method_id: say_class_defined
|
285
|
-
:path: spec/fixtures/hook/
|
290
|
+
:path: spec/fixtures/hook/singleton_method.rb
|
286
291
|
:lineno: 10
|
287
292
|
:static: true
|
288
293
|
:parameters: []
|
289
294
|
:receiver:
|
290
295
|
:class: Class
|
291
|
-
:value:
|
296
|
+
:value: SingletonMethod
|
292
297
|
- :id: 2
|
293
298
|
:event: :return
|
294
299
|
:parent_id: 1
|
@@ -296,8 +301,8 @@ describe 'AppMap class Hooking' do
|
|
296
301
|
:class: String
|
297
302
|
:value: defined with explicit class scope
|
298
303
|
YAML
|
299
|
-
test_hook_behavior 'spec/fixtures/hook/
|
300
|
-
expect(
|
304
|
+
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
|
305
|
+
expect(SingletonMethod.say_class_defined).to eq('defined with explicit class scope')
|
301
306
|
end
|
302
307
|
end
|
303
308
|
|
@@ -306,15 +311,15 @@ describe 'AppMap class Hooking' do
|
|
306
311
|
---
|
307
312
|
- :id: 1
|
308
313
|
:event: :call
|
309
|
-
:defined_class:
|
314
|
+
:defined_class: SingletonMethod
|
310
315
|
:method_id: say_self_defined
|
311
|
-
:path: spec/fixtures/hook/
|
316
|
+
:path: spec/fixtures/hook/singleton_method.rb
|
312
317
|
:lineno: 14
|
313
318
|
:static: true
|
314
319
|
:parameters: []
|
315
320
|
:receiver:
|
316
321
|
:class: Class
|
317
|
-
:value:
|
322
|
+
:value: SingletonMethod
|
318
323
|
- :id: 2
|
319
324
|
:event: :return
|
320
325
|
:parent_id: 1
|
@@ -322,8 +327,74 @@ describe 'AppMap class Hooking' do
|
|
322
327
|
:class: String
|
323
328
|
:value: defined with self class scope
|
324
329
|
YAML
|
325
|
-
test_hook_behavior 'spec/fixtures/hook/
|
326
|
-
expect(
|
330
|
+
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
|
331
|
+
expect(SingletonMethod.say_self_defined).to eq('defined with self class scope')
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
it 'hooks an included method' do
|
337
|
+
events_yaml = <<~YAML
|
338
|
+
---
|
339
|
+
- :id: 1
|
340
|
+
:event: :call
|
341
|
+
:defined_class: SingletonMethod
|
342
|
+
:method_id: added_method
|
343
|
+
:path: spec/fixtures/hook/singleton_method.rb
|
344
|
+
:lineno: 44
|
345
|
+
:static: false
|
346
|
+
:parameters: []
|
347
|
+
:receiver:
|
348
|
+
:class: SingletonMethod
|
349
|
+
:value: Singleton Method fixture
|
350
|
+
- :id: 2
|
351
|
+
:event: :call
|
352
|
+
:defined_class: AddMethod
|
353
|
+
:method_id: _added_method
|
354
|
+
:path: spec/fixtures/hook/singleton_method.rb
|
355
|
+
:lineno: 50
|
356
|
+
:static: false
|
357
|
+
:parameters: []
|
358
|
+
:receiver:
|
359
|
+
:class: SingletonMethod
|
360
|
+
:value: Singleton Method fixture
|
361
|
+
- :id: 3
|
362
|
+
:event: :return
|
363
|
+
:parent_id: 2
|
364
|
+
:return_value:
|
365
|
+
:class: String
|
366
|
+
:value: defined by including a module
|
367
|
+
- :id: 4
|
368
|
+
:event: :return
|
369
|
+
:parent_id: 1
|
370
|
+
:return_value:
|
371
|
+
:class: String
|
372
|
+
:value: defined by including a module
|
373
|
+
YAML
|
374
|
+
|
375
|
+
load 'spec/fixtures/hook/singleton_method.rb'
|
376
|
+
setup = -> { SingletonMethod.new.do_include }
|
377
|
+
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml, setup: setup do |s|
|
378
|
+
expect(s.added_method).to eq('defined by including a module')
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
it "doesn't hook a singleton method defined for an instance" do
|
383
|
+
# Ideally, Ruby would fire a TracePoint event when a singleton
|
384
|
+
# class gets created by defining a method on an instance. It
|
385
|
+
# currently doesn't, though, so there's no way for us to hook such
|
386
|
+
# a method.
|
387
|
+
#
|
388
|
+
# This example will fail if Ruby's behavior changes at some point
|
389
|
+
# in the future.
|
390
|
+
events_yaml = <<~YAML
|
391
|
+
--- []
|
392
|
+
YAML
|
393
|
+
|
394
|
+
load 'spec/fixtures/hook/singleton_method.rb'
|
395
|
+
setup = -> { SingletonMethod.new_with_instance_method }
|
396
|
+
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml, setup: setup do |s|
|
397
|
+
expect(s.say_instance_defined).to eq('defined for an instance')
|
327
398
|
end
|
328
399
|
end
|
329
400
|
|
@@ -366,4 +437,108 @@ describe 'AppMap class Hooking' do
|
|
366
437
|
expect { ExceptionMethod.new.raise_exception }.to raise_exception
|
367
438
|
end
|
368
439
|
end
|
440
|
+
|
441
|
+
context 'ActiveSupport::SecurityUtils.secure_compare' do
|
442
|
+
it 'is hooked' do
|
443
|
+
events_yaml = <<~YAML
|
444
|
+
---
|
445
|
+
- :id: 1
|
446
|
+
:event: :call
|
447
|
+
:defined_class: Compare
|
448
|
+
:method_id: compare
|
449
|
+
:path: spec/fixtures/hook/compare.rb
|
450
|
+
:lineno: 4
|
451
|
+
:static: true
|
452
|
+
:parameters:
|
453
|
+
- :name: :s1
|
454
|
+
:class: String
|
455
|
+
:value: string
|
456
|
+
:kind: :req
|
457
|
+
- :name: :s2
|
458
|
+
:class: String
|
459
|
+
:value: string
|
460
|
+
:kind: :req
|
461
|
+
:receiver:
|
462
|
+
:class: Class
|
463
|
+
:value: Compare
|
464
|
+
- :id: 2
|
465
|
+
:event: :call
|
466
|
+
:defined_class: ActiveSupport::SecurityUtils
|
467
|
+
:method_id: secure_compare
|
468
|
+
:path: gems/activesupport-6.0.3.2/lib/active_support/security_utils.rb
|
469
|
+
:lineno: 26
|
470
|
+
:static: true
|
471
|
+
:parameters:
|
472
|
+
- :name: :a
|
473
|
+
:class: String
|
474
|
+
:value: string
|
475
|
+
:kind: :req
|
476
|
+
- :name: :b
|
477
|
+
:class: String
|
478
|
+
:value: string
|
479
|
+
:kind: :req
|
480
|
+
:receiver:
|
481
|
+
:class: Module
|
482
|
+
:value: ActiveSupport::SecurityUtils
|
483
|
+
- :id: 3
|
484
|
+
:event: :return
|
485
|
+
:parent_id: 2
|
486
|
+
:return_value:
|
487
|
+
:class: TrueClass
|
488
|
+
:value: 'true'
|
489
|
+
- :id: 4
|
490
|
+
:event: :return
|
491
|
+
:parent_id: 1
|
492
|
+
:return_value:
|
493
|
+
:class: TrueClass
|
494
|
+
:value: 'true'
|
495
|
+
YAML
|
496
|
+
|
497
|
+
test_hook_behavior 'spec/fixtures/hook/compare.rb', events_yaml do
|
498
|
+
expect(Compare.compare('string', 'string')).to be_truthy
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'gets labeled in the classmap' do
|
503
|
+
classmap_yaml = <<~YAML
|
504
|
+
---
|
505
|
+
- :name: spec/fixtures/hook/compare.rb
|
506
|
+
:type: package
|
507
|
+
:children:
|
508
|
+
- :name: Compare
|
509
|
+
:type: class
|
510
|
+
:children:
|
511
|
+
- :name: compare
|
512
|
+
:type: function
|
513
|
+
:location: spec/fixtures/hook/compare.rb:4
|
514
|
+
:static: true
|
515
|
+
- :name: active_support
|
516
|
+
:type: package
|
517
|
+
:children:
|
518
|
+
- :name: ActiveSupport
|
519
|
+
:type: class
|
520
|
+
:children:
|
521
|
+
- :name: SecurityUtils
|
522
|
+
:type: class
|
523
|
+
:children:
|
524
|
+
- :name: secure_compare
|
525
|
+
:type: function
|
526
|
+
:location: gems/activesupport-6.0.3.2/lib/active_support/security_utils.rb:26
|
527
|
+
:static: true
|
528
|
+
:labels:
|
529
|
+
- security
|
530
|
+
YAML
|
531
|
+
|
532
|
+
config, tracer = invoke_test_file 'spec/fixtures/hook/compare.rb' do
|
533
|
+
expect(Compare.compare('string', 'string')).to be_truthy
|
534
|
+
end
|
535
|
+
cm = AppMap::ClassMap.build_from_methods(config, tracer.event_methods)
|
536
|
+
entry = cm[1][:children][0][:children][0][:children][0]
|
537
|
+
# Sanity check, make sure we got the right one
|
538
|
+
expect(entry[:name]).to eq('secure_compare')
|
539
|
+
spec = Gem::Specification.find_by_name('activesupport')
|
540
|
+
entry[:location].gsub!(spec.base_dir + '/', '')
|
541
|
+
expect(Diffy::Diff.new(cm.to_yaml, classmap_yaml).to_s).to eq('')
|
542
|
+
end
|
543
|
+
end
|
369
544
|
end
|