appmap 0.31.0 → 0.34.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rbenv-gemsets +1 -0
- data/CHANGELOG.md +22 -0
- data/README.md +38 -4
- data/Rakefile +10 -3
- data/appmap.gemspec +5 -0
- data/ext/appmap/appmap.c +26 -0
- data/ext/appmap/extconf.rb +6 -0
- data/lib/appmap.rb +23 -10
- data/lib/appmap/class_map.rb +13 -7
- data/lib/appmap/config.rb +54 -30
- data/lib/appmap/cucumber.rb +19 -2
- data/lib/appmap/event.rb +25 -16
- data/lib/appmap/hook.rb +52 -77
- data/lib/appmap/hook/method.rb +103 -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/rspec.rb +1 -1
- data/lib/appmap/trace.rb +7 -7
- data/lib/appmap/util.rb +19 -0
- data/lib/appmap/version.rb +1 -1
- data/spec/abstract_controller4_base_spec.rb +1 -1
- data/spec/abstract_controller_base_spec.rb +9 -2
- data/spec/fixtures/hook/instance_method.rb +4 -0
- data/spec/fixtures/hook/singleton_method.rb +21 -12
- data/spec/hook_spec.rb +140 -44
- data/spec/open_spec.rb +19 -0
- data/spec/record_sql_rails_pg_spec.rb +56 -33
- data/test/cli_test.rb +12 -2
- data/test/fixtures/openssl_recorder/Gemfile +3 -0
- data/test/fixtures/openssl_recorder/appmap.yml +3 -0
- data/{spec/fixtures/hook/openssl_sign.rb → test/fixtures/openssl_recorder/lib/openssl_cert_sign.rb} +11 -4
- data/test/fixtures/openssl_recorder/lib/openssl_encrypt.rb +34 -0
- data/test/fixtures/openssl_recorder/lib/openssl_key_sign.rb +28 -0
- data/test/openssl_test.rb +203 -0
- data/test/test_helper.rb +1 -0
- metadata +58 -4
@@ -16,11 +16,11 @@ module AppMap
|
|
16
16
|
class HTTPServerRequest
|
17
17
|
include ContextKey
|
18
18
|
|
19
|
-
class Call < AppMap::Event::
|
19
|
+
class Call < AppMap::Event::MethodCall
|
20
20
|
attr_accessor :payload
|
21
21
|
|
22
|
-
def initialize(
|
23
|
-
super AppMap::Event.next_id_counter, :call,
|
22
|
+
def initialize(payload)
|
23
|
+
super AppMap::Event.next_id_counter, :call, Thread.current.object_id
|
24
24
|
|
25
25
|
self.payload = payload
|
26
26
|
end
|
@@ -47,7 +47,7 @@ module AppMap
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def call(_, started, finished, _, payload) # (name, started, finished, unique_id, payload)
|
50
|
-
event = Call.new(
|
50
|
+
event = Call.new(payload)
|
51
51
|
Thread.current[context_key] = Context.new(event.id, Time.now)
|
52
52
|
AppMap.tracing.record_event(event)
|
53
53
|
end
|
@@ -59,8 +59,8 @@ module AppMap
|
|
59
59
|
class Call < AppMap::Event::MethodReturnIgnoreValue
|
60
60
|
attr_accessor :payload
|
61
61
|
|
62
|
-
def initialize(
|
63
|
-
super AppMap::Event.next_id_counter, :return,
|
62
|
+
def initialize(payload, parent_id, elapsed)
|
63
|
+
super AppMap::Event.next_id_counter, :return, Thread.current.object_id
|
64
64
|
|
65
65
|
self.payload = payload
|
66
66
|
self.parent_id = parent_id
|
@@ -82,7 +82,7 @@ module AppMap
|
|
82
82
|
context = Thread.current[context_key]
|
83
83
|
Thread.current[context_key] = nil
|
84
84
|
|
85
|
-
event = Call.new(
|
85
|
+
event = Call.new(payload, context.id, Time.now - context.start_time)
|
86
86
|
AppMap.tracing.record_event(event)
|
87
87
|
end
|
88
88
|
end
|
@@ -5,11 +5,11 @@ require 'appmap/event'
|
|
5
5
|
module AppMap
|
6
6
|
module Rails
|
7
7
|
class SQLHandler
|
8
|
-
class SQLCall < AppMap::Event::
|
8
|
+
class SQLCall < AppMap::Event::MethodCall
|
9
9
|
attr_accessor :payload
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
super AppMap::Event.next_id_counter, :call,
|
11
|
+
def initialize(payload)
|
12
|
+
super AppMap::Event.next_id_counter, :call, Thread.current.object_id
|
13
13
|
|
14
14
|
self.payload = payload
|
15
15
|
end
|
@@ -20,7 +20,7 @@ module AppMap
|
|
20
20
|
sql: payload[:sql],
|
21
21
|
database_type: payload[:database_type]
|
22
22
|
}.tap do |sql_query|
|
23
|
-
%i[server_version
|
23
|
+
%i[server_version].each do |attribute|
|
24
24
|
sql_query[attribute] = payload[attribute] if payload[attribute]
|
25
25
|
end
|
26
26
|
end
|
@@ -29,8 +29,8 @@ module AppMap
|
|
29
29
|
end
|
30
30
|
|
31
31
|
class SQLReturn < AppMap::Event::MethodReturnIgnoreValue
|
32
|
-
def initialize(
|
33
|
-
super AppMap::Event.next_id_counter, :return,
|
32
|
+
def initialize(parent_id, elapsed)
|
33
|
+
super AppMap::Event.next_id_counter, :return, Thread.current.object_id
|
34
34
|
|
35
35
|
self.parent_id = parent_id
|
36
36
|
self.elapsed = elapsed
|
@@ -76,6 +76,8 @@ module AppMap
|
|
76
76
|
case database_type
|
77
77
|
when :postgres
|
78
78
|
ActiveRecord::Base.connection.postgresql_version
|
79
|
+
when :sqlite
|
80
|
+
ActiveRecord::Base.connection.database_version.to_s
|
79
81
|
else
|
80
82
|
warn "Unable to determine database version for #{database_type.inspect}"
|
81
83
|
end
|
@@ -133,9 +135,9 @@ module AppMap
|
|
133
135
|
|
134
136
|
SQLExaminer.examine payload, sql: sql
|
135
137
|
|
136
|
-
call = SQLCall.new(
|
138
|
+
call = SQLCall.new(payload)
|
137
139
|
AppMap.tracing.record_event(call)
|
138
|
-
AppMap.tracing.record_event(SQLReturn.new(
|
140
|
+
AppMap.tracing.record_event(SQLReturn.new(call.id, finished - started))
|
139
141
|
ensure
|
140
142
|
Thread.current[reentry_key] = nil
|
141
143
|
end
|
data/lib/appmap/rspec.rb
CHANGED
@@ -154,7 +154,7 @@ module AppMap
|
|
154
154
|
end
|
155
155
|
|
156
156
|
labels = labels.map(&:to_s).map(&:strip).reject(&:blank?).map(&:downcase).uniq
|
157
|
-
description.reject!(&:nil?).reject(&:blank?)
|
157
|
+
description.reject!(&:nil?).reject!(&:blank?)
|
158
158
|
default_description = description.last
|
159
159
|
description.reverse!
|
160
160
|
|
data/lib/appmap/trace.rb
CHANGED
@@ -14,34 +14,34 @@ module AppMap
|
|
14
14
|
|
15
15
|
class Tracing
|
16
16
|
def initialize
|
17
|
-
@
|
17
|
+
@tracing = []
|
18
18
|
end
|
19
19
|
|
20
20
|
def empty?
|
21
|
-
@
|
21
|
+
@tracing.empty?
|
22
22
|
end
|
23
23
|
|
24
24
|
def trace(enable: true)
|
25
25
|
Tracer.new.tap do |tracer|
|
26
|
-
@
|
26
|
+
@tracing << tracer
|
27
27
|
tracer.enable if enable
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
def enabled?
|
32
|
-
@
|
32
|
+
@tracing.any?(&:enabled?)
|
33
33
|
end
|
34
34
|
|
35
35
|
def record_event(event, defined_class: nil, method: nil)
|
36
|
-
@
|
36
|
+
@tracing.each do |tracer|
|
37
37
|
tracer.record_event(event, defined_class: defined_class, method: method)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
def delete(tracer)
|
42
|
-
return unless @
|
42
|
+
return unless @tracing.member?(tracer)
|
43
43
|
|
44
|
-
@
|
44
|
+
@tracing.delete(tracer)
|
45
45
|
tracer.disable
|
46
46
|
end
|
47
47
|
end
|
data/lib/appmap/util.rb
CHANGED
@@ -35,6 +35,25 @@ module AppMap
|
|
35
35
|
|
36
36
|
[ fname, extension ].join
|
37
37
|
end
|
38
|
+
|
39
|
+
# sanitize_event removes ephemeral values from an event, making
|
40
|
+
# events easier to compare across runs.
|
41
|
+
def sanitize_event(event, &block)
|
42
|
+
event.delete(:thread_id)
|
43
|
+
event.delete(:elapsed)
|
44
|
+
delete_object_id = ->(obj) { (obj || {}).delete(:object_id) }
|
45
|
+
delete_object_id.call(event[:receiver])
|
46
|
+
delete_object_id.call(event[:return_value])
|
47
|
+
(event[:parameters] || []).each(&delete_object_id)
|
48
|
+
(event[:exceptions] || []).each(&delete_object_id)
|
49
|
+
|
50
|
+
case event[:event]
|
51
|
+
when :call
|
52
|
+
event[:path] = event[:path].gsub(Gem.dir + '/', '')
|
53
|
+
end
|
54
|
+
|
55
|
+
event
|
56
|
+
end
|
38
57
|
end
|
39
58
|
end
|
40
59
|
end
|
data/lib/appmap/version.rb
CHANGED
@@ -48,11 +48,11 @@ describe 'AbstractControllerBase' do
|
|
48
48
|
|
49
49
|
expect(appmap).to match(<<-CREATE_CALL.strip)
|
50
50
|
event: call
|
51
|
+
thread_id: .*
|
51
52
|
defined_class: Api::UsersController
|
52
53
|
method_id: build_user
|
53
54
|
path: app/controllers/api/users_controller.rb
|
54
55
|
lineno: 23
|
55
|
-
thread_id: .*
|
56
56
|
static: false
|
57
57
|
parameters:
|
58
58
|
- name: params
|
@@ -47,17 +47,17 @@ 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
|
-
thread_id: .*
|
61
61
|
static: false
|
62
62
|
parameters:
|
63
63
|
- name: params
|
@@ -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
|
@@ -15,6 +15,20 @@ class SingletonMethod
|
|
15
15
|
'defined with self class scope'
|
16
16
|
end
|
17
17
|
|
18
|
+
module AddMethod
|
19
|
+
def self.included(base)
|
20
|
+
base.module_eval do
|
21
|
+
define_method "added_method" do
|
22
|
+
_added_method
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def _added_method
|
28
|
+
'defined by including a module'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
18
32
|
# When called, do_include calls +include+ to bring in the module
|
19
33
|
# AddMethod. AddMethod defines a new instance method, which gets
|
20
34
|
# added to the singleton class of SingletonMethod.
|
@@ -32,23 +46,18 @@ class SingletonMethod
|
|
32
46
|
end
|
33
47
|
end
|
34
48
|
end
|
35
|
-
|
36
|
-
def to_s
|
37
|
-
'Singleton Method fixture'
|
38
|
-
end
|
39
|
-
end
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
_added_method
|
50
|
+
STRUCT_TEST = Struct.new(:attr) do
|
51
|
+
class << self
|
52
|
+
def say_struct_singleton
|
53
|
+
'singleton for a struct'
|
46
54
|
end
|
47
55
|
end
|
48
56
|
end
|
49
57
|
|
50
|
-
def
|
51
|
-
'
|
58
|
+
def to_s
|
59
|
+
'Singleton Method fixture'
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
63
|
+
|
data/spec/hook_spec.rb
CHANGED
@@ -16,36 +16,18 @@ end
|
|
16
16
|
Psych::Visitors::YAMLTree.prepend(ShowYamlNulls)
|
17
17
|
|
18
18
|
describe 'AppMap class Hooking', docker: false do
|
19
|
+
require 'appmap/util'
|
19
20
|
def collect_events(tracer)
|
20
21
|
[].tap do |events|
|
21
22
|
while tracer.event?
|
22
23
|
events << tracer.next_event.to_h
|
23
24
|
end
|
24
|
-
end.map
|
25
|
-
event.delete(:thread_id)
|
26
|
-
event.delete(:elapsed)
|
27
|
-
delete_object_id = ->(obj) { (obj || {}).delete(:object_id) }
|
28
|
-
delete_object_id.call(event[:receiver])
|
29
|
-
delete_object_id.call(event[:return_value])
|
30
|
-
(event[:parameters] || []).each(&delete_object_id)
|
31
|
-
(event[:exceptions] || []).each(&delete_object_id)
|
32
|
-
|
33
|
-
case event[:event]
|
34
|
-
when :call
|
35
|
-
event[:path] = event[:path].gsub(Gem.dir + '/', '')
|
36
|
-
when :return
|
37
|
-
# These should be removed from the appmap spec
|
38
|
-
%i[defined_class method_id path lineno static].each do |obsolete_field|
|
39
|
-
event.delete(obsolete_field)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
event
|
43
|
-
end.to_yaml
|
25
|
+
end.map(&AppMap::Util.method(:sanitize_event)).to_yaml
|
44
26
|
end
|
45
27
|
|
46
28
|
def invoke_test_file(file, setup: nil, &block)
|
47
29
|
AppMap.configuration = nil
|
48
|
-
package = AppMap::Package.new(file
|
30
|
+
package = AppMap::Config::Package.new(file)
|
49
31
|
config = AppMap::Config.new('hook_spec', [ package ])
|
50
32
|
AppMap.configuration = config
|
51
33
|
tracer = nil
|
@@ -69,7 +51,8 @@ describe 'AppMap class Hooking', docker: false do
|
|
69
51
|
config, tracer = invoke_test_file(file, setup: setup, &block)
|
70
52
|
|
71
53
|
events = collect_events(tracer)
|
72
|
-
|
54
|
+
|
55
|
+
expect(Diffy::Diff.new(events_yaml, events).to_s).to eq('')
|
73
56
|
|
74
57
|
[ config, tracer ]
|
75
58
|
end
|
@@ -99,7 +82,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
99
82
|
:class: String
|
100
83
|
:value: default
|
101
84
|
YAML
|
102
|
-
|
85
|
+
test_hook_behavior 'spec/fixtures/hook/instance_method.rb', events_yaml do
|
103
86
|
expect(InstanceMethod.new.say_default).to eq('default')
|
104
87
|
end
|
105
88
|
end
|
@@ -117,7 +100,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
117
100
|
InstanceMethod.new.say_default
|
118
101
|
end
|
119
102
|
class_map = AppMap.class_map(tracer.event_methods).to_yaml
|
120
|
-
expect(Diffy::Diff.new(
|
103
|
+
expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
|
121
104
|
---
|
122
105
|
- :name: spec/fixtures/hook/instance_method.rb
|
123
106
|
:type: package
|
@@ -359,7 +342,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
359
342
|
:defined_class: SingletonMethod
|
360
343
|
:method_id: added_method
|
361
344
|
:path: spec/fixtures/hook/singleton_method.rb
|
362
|
-
:lineno:
|
345
|
+
:lineno: 21
|
363
346
|
:static: false
|
364
347
|
:parameters: []
|
365
348
|
:receiver:
|
@@ -367,10 +350,10 @@ describe 'AppMap class Hooking', docker: false do
|
|
367
350
|
:value: Singleton Method fixture
|
368
351
|
- :id: 2
|
369
352
|
:event: :call
|
370
|
-
:defined_class: AddMethod
|
353
|
+
:defined_class: SingletonMethod::AddMethod
|
371
354
|
:method_id: _added_method
|
372
355
|
:path: spec/fixtures/hook/singleton_method.rb
|
373
|
-
:lineno:
|
356
|
+
:lineno: 27
|
374
357
|
:static: false
|
375
358
|
:parameters: []
|
376
359
|
:receiver:
|
@@ -412,10 +395,44 @@ describe 'AppMap class Hooking', docker: false do
|
|
412
395
|
load 'spec/fixtures/hook/singleton_method.rb'
|
413
396
|
setup = -> { SingletonMethod.new_with_instance_method }
|
414
397
|
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml, setup: setup do |s|
|
398
|
+
# Make sure we're testing the right thing
|
399
|
+
say_instance_defined = s.method(:say_instance_defined)
|
400
|
+
expect(say_instance_defined.owner.to_s).to start_with('#<Class:#<SingletonMethod:')
|
401
|
+
|
402
|
+
# Verify the native extension works as expected
|
403
|
+
expect(AppMap::Hook.singleton_method_owner_name(say_instance_defined)).to eq('SingletonMethod')
|
404
|
+
|
415
405
|
expect(s.say_instance_defined).to eq('defined for an instance')
|
416
406
|
end
|
417
407
|
end
|
418
408
|
|
409
|
+
it 'hooks a singleton method on an embedded struct' do
|
410
|
+
events_yaml = <<~YAML
|
411
|
+
---
|
412
|
+
- :id: 1
|
413
|
+
:event: :call
|
414
|
+
:defined_class: SingletonMethod::STRUCT_TEST
|
415
|
+
:method_id: say_struct_singleton
|
416
|
+
:path: spec/fixtures/hook/singleton_method.rb
|
417
|
+
:lineno: 52
|
418
|
+
:static: true
|
419
|
+
:parameters: []
|
420
|
+
:receiver:
|
421
|
+
:class: Class
|
422
|
+
:value: SingletonMethod::STRUCT_TEST
|
423
|
+
- :id: 2
|
424
|
+
:event: :return
|
425
|
+
:parent_id: 1
|
426
|
+
:return_value:
|
427
|
+
:class: String
|
428
|
+
:value: singleton for a struct
|
429
|
+
YAML
|
430
|
+
|
431
|
+
test_hook_behavior 'spec/fixtures/hook/singleton_method.rb', events_yaml do
|
432
|
+
expect(SingletonMethod::STRUCT_TEST.say_struct_singleton).to eq('singleton for a struct')
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
419
436
|
it 'Reports exceptions' do
|
420
437
|
events_yaml = <<~YAML
|
421
438
|
---
|
@@ -456,20 +473,6 @@ describe 'AppMap class Hooking', docker: false do
|
|
456
473
|
end
|
457
474
|
end
|
458
475
|
|
459
|
-
context 'OpenSSL::X509::Certificate.sign' do
|
460
|
-
# OpenSSL::X509 is not being hooked.
|
461
|
-
# This might be because the class is being loaded before AppMap, and so the TracePoint
|
462
|
-
# set by AppMap doesn't see it.
|
463
|
-
xit 'is hooked' do
|
464
|
-
events_yaml = <<~YAML
|
465
|
-
---
|
466
|
-
YAML
|
467
|
-
test_hook_behavior 'spec/fixtures/hook/openssl_sign.rb', events_yaml do
|
468
|
-
expect(OpenSSLExample.example).to be_truthy
|
469
|
-
end
|
470
|
-
end
|
471
|
-
end
|
472
|
-
|
473
476
|
context 'ActiveSupport::SecurityUtils.secure_compare' do
|
474
477
|
it 'is hooked' do
|
475
478
|
events_yaml = <<~YAML
|
@@ -513,12 +516,52 @@ describe 'AppMap class Hooking', docker: false do
|
|
513
516
|
:class: Module
|
514
517
|
:value: ActiveSupport::SecurityUtils
|
515
518
|
- :id: 3
|
519
|
+
:event: :call
|
520
|
+
:defined_class: Digest::Instance
|
521
|
+
:method_id: digest
|
522
|
+
:path: Digest::Instance#digest
|
523
|
+
:static: false
|
524
|
+
:parameters:
|
525
|
+
- :name: arg
|
526
|
+
:class: String
|
527
|
+
:value: string
|
528
|
+
:kind: :rest
|
529
|
+
:receiver:
|
530
|
+
:class: Digest::SHA256
|
531
|
+
:value: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
532
|
+
- :id: 4
|
533
|
+
:event: :return
|
534
|
+
:parent_id: 3
|
535
|
+
:return_value:
|
536
|
+
:class: String
|
537
|
+
:value: "G2__)__qc____X____3_].\\x02y__.___/_"
|
538
|
+
- :id: 5
|
539
|
+
:event: :call
|
540
|
+
:defined_class: Digest::Instance
|
541
|
+
:method_id: digest
|
542
|
+
:path: Digest::Instance#digest
|
543
|
+
:static: false
|
544
|
+
:parameters:
|
545
|
+
- :name: arg
|
546
|
+
:class: String
|
547
|
+
:value: string
|
548
|
+
:kind: :rest
|
549
|
+
:receiver:
|
550
|
+
:class: Digest::SHA256
|
551
|
+
:value: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
552
|
+
- :id: 6
|
553
|
+
:event: :return
|
554
|
+
:parent_id: 5
|
555
|
+
:return_value:
|
556
|
+
:class: String
|
557
|
+
:value: "G2__)__qc____X____3_].\\x02y__.___/_"
|
558
|
+
- :id: 7
|
516
559
|
:event: :return
|
517
560
|
:parent_id: 2
|
518
561
|
:return_value:
|
519
562
|
:class: TrueClass
|
520
563
|
:value: 'true'
|
521
|
-
- :id:
|
564
|
+
- :id: 8
|
522
565
|
:event: :return
|
523
566
|
:parent_id: 1
|
524
567
|
:return_value:
|
@@ -559,8 +602,25 @@ describe 'AppMap class Hooking', docker: false do
|
|
559
602
|
:static: true
|
560
603
|
:labels:
|
561
604
|
- security
|
605
|
+
- crypto
|
606
|
+
- :name: openssl
|
607
|
+
:type: package
|
608
|
+
:children:
|
609
|
+
- :name: Digest
|
610
|
+
:type: class
|
611
|
+
:children:
|
612
|
+
- :name: Instance
|
613
|
+
:type: class
|
614
|
+
:children:
|
615
|
+
- :name: digest
|
616
|
+
:type: function
|
617
|
+
:location: Digest::Instance#digest
|
618
|
+
:static: false
|
619
|
+
:labels:
|
620
|
+
- security
|
621
|
+
- crypto
|
562
622
|
YAML
|
563
|
-
|
623
|
+
|
564
624
|
config, tracer = invoke_test_file 'spec/fixtures/hook/compare.rb' do
|
565
625
|
expect(Compare.compare('string', 'string')).to be_truthy
|
566
626
|
end
|
@@ -570,7 +630,43 @@ describe 'AppMap class Hooking', docker: false do
|
|
570
630
|
expect(entry[:name]).to eq('secure_compare')
|
571
631
|
spec = Gem::Specification.find_by_name('activesupport')
|
572
632
|
entry[:location].gsub!(spec.base_dir + '/', '')
|
573
|
-
expect(Diffy::Diff.new(cm.to_yaml
|
633
|
+
expect(Diffy::Diff.new(classmap_yaml, cm.to_yaml).to_s).to eq('')
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
it "doesn't cause expectations on Time.now to fail" do
|
638
|
+
events_yaml = <<~YAML
|
639
|
+
---
|
640
|
+
- :id: 1
|
641
|
+
:event: :call
|
642
|
+
:defined_class: InstanceMethod
|
643
|
+
:method_id: say_the_time
|
644
|
+
:path: spec/fixtures/hook/instance_method.rb
|
645
|
+
:lineno: 24
|
646
|
+
:static: false
|
647
|
+
:parameters: []
|
648
|
+
:receiver:
|
649
|
+
:class: InstanceMethod
|
650
|
+
:value: Instance Method fixture
|
651
|
+
- :id: 2
|
652
|
+
:event: :return
|
653
|
+
:parent_id: 1
|
654
|
+
:return_value:
|
655
|
+
:class: String
|
656
|
+
:value: '2020-01-01 00:00:00 +0000'
|
657
|
+
YAML
|
658
|
+
test_hook_behavior 'spec/fixtures/hook/instance_method.rb', events_yaml do
|
659
|
+
require 'timecop'
|
660
|
+
begin
|
661
|
+
tz = ENV['TZ']
|
662
|
+
ENV['TZ'] = 'UTC'
|
663
|
+
Timecop.freeze(Time.utc('2020-01-01')) do
|
664
|
+
expect(Time).to receive(:now).exactly(3).times.and_call_original
|
665
|
+
expect(InstanceMethod.new.say_the_time).to be
|
666
|
+
end
|
667
|
+
ensure
|
668
|
+
ENV['TZ'] = tz
|
669
|
+
end
|
574
670
|
end
|
575
671
|
end
|
576
672
|
end
|