appmap 0.26.1 → 0.32.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -3
- data/CHANGELOG.md +37 -0
- data/README.md +170 -29
- data/Rakefile +1 -1
- data/exe/appmap +3 -1
- data/lib/appmap.rb +56 -35
- 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/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 +20 -38
- data/lib/appmap/trace.rb +19 -11
- 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/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 +39 -3
- data/spec/fixtures/hook/class_method.rb +0 -17
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
|