appmap 0.69.0 → 0.70.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/CHANGELOG.md +8 -0
- data/lib/appmap/class_map.rb +28 -13
- data/lib/appmap/config.rb +28 -9
- data/lib/appmap/hook.rb +24 -17
- data/lib/appmap/version.rb +1 -1
- data/spec/class_map_spec.rb +1 -1
- data/spec/fixtures/hook/pkg_a/a.rb +7 -0
- data/spec/fixtures/hook/protected_method.rb +29 -0
- data/spec/fixtures/hook/sub_packages.rb +7 -0
- data/spec/hook_spec.rb +134 -20
- data/spec/rails_recording_spec.rb +20 -20
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64006e414b4b6cece101a113b5b5359c370b77b96761cfcb02818c07e621d8c5
|
4
|
+
data.tar.gz: e7ab888c17031adb8ae993dae863539b32359e967c706b2cc2b13f1f2bb11761
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9b9fbf621b59dfb72875365d2c4485e174b4532b159d62854883e77fd741451f1e8ca4609b0a5323cccc562fcf31ead2ef19923bd3be3e6b0d5d28d5c188635
|
7
|
+
data.tar.gz: 4a079f0b5ae28e45a065187e0044446bdbef6a5a91df88f9072b71a825a18c86e3ba6eaf8dc54102b224eb16f3eae1ea0b9e3b8da3958b209bdd9f5d78d0ac50
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# [0.70.0](https://github.com/applandinc/appmap-ruby/compare/v0.69.0...v0.70.0) (2021-12-08)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* Hook protected methods ([a3722b5](https://github.com/applandinc/appmap-ruby/commit/a3722b504b8e5b8c032988b586b13bdd071fe577))
|
7
|
+
* Report sub-packages for nested folders ([dce709b](https://github.com/applandinc/appmap-ruby/commit/dce709b077fd64fc2b34f9abb30a65db529f824b))
|
8
|
+
|
1
9
|
# [0.69.0](https://github.com/applandinc/appmap-ruby/compare/v0.68.2...v0.69.0) (2021-12-01)
|
2
10
|
|
3
11
|
|
data/lib/appmap/class_map.rb
CHANGED
@@ -76,24 +76,39 @@ module AppMap
|
|
76
76
|
methods.each do |method|
|
77
77
|
add_function root, method
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
|
+
collapse_package = lambda do |package|
|
81
|
+
return unless package.type == 'package'
|
82
|
+
|
83
|
+
while package.children.length == 1 && package.children.all? { |child| child.type == 'package' }
|
84
|
+
child = package.children[0]
|
85
|
+
package.children.clear
|
86
|
+
child.children.each { |child| package.children << child }
|
87
|
+
package.name = [ package.name, child.name ].join('/')
|
88
|
+
end
|
89
|
+
package.tap do
|
90
|
+
package.children.map(&collapse_package)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
root.children.map(&collapse_package).map(&:to_h)
|
80
95
|
end
|
81
96
|
|
82
97
|
protected
|
83
98
|
|
84
99
|
def add_function(root, method)
|
85
|
-
object_infos =
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
object_infos = \
|
101
|
+
method.package.split('/').map do |name|
|
102
|
+
{
|
103
|
+
name: name,
|
104
|
+
type: 'package'
|
105
|
+
}
|
106
|
+
end + method.class_name.split('::').map do |name|
|
107
|
+
{
|
108
|
+
name: name,
|
109
|
+
type: 'class'
|
110
|
+
}
|
111
|
+
end
|
97
112
|
function_info = {
|
98
113
|
name: method.name,
|
99
114
|
type: 'function',
|
data/lib/appmap/config.rb
CHANGED
@@ -44,6 +44,21 @@ module AppMap
|
|
44
44
|
shallow
|
45
45
|
end
|
46
46
|
|
47
|
+
# Clones this package into a sub-package, if needed.
|
48
|
+
# For example, suppose the appmap.yml specifies package `app/models`. If some code in
|
49
|
+
# `app/models/dao/user.rb` is mapped, it will be associated with a sub-package
|
50
|
+
# `app/models/dao`.
|
51
|
+
def subpackage(location, config)
|
52
|
+
return self if gem
|
53
|
+
|
54
|
+
path = location.split('/')[0...-1].join('/')
|
55
|
+
clone.tap do |pkg|
|
56
|
+
pkg.name = path
|
57
|
+
pkg.path = path
|
58
|
+
config.packages << pkg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
47
62
|
class << self
|
48
63
|
# Builds a package for a path, such as `app/models` in a Rails app. Generally corresponds to a `path:` entry
|
49
64
|
# in appmap.yml. Also used for mapping specific methods via TargetMethods.
|
@@ -191,7 +206,7 @@ module AppMap
|
|
191
206
|
}.compact
|
192
207
|
|
193
208
|
handler_class = hook_decl['handler_class']
|
194
|
-
options[:handler_class] = Util
|
209
|
+
options[:handler_class] = Util.class_from_string(handler_class) if handler_class
|
195
210
|
|
196
211
|
package_hooks(methods, **options)
|
197
212
|
end
|
@@ -215,7 +230,7 @@ module AppMap
|
|
215
230
|
builtin = hook_decl['builtin']
|
216
231
|
|
217
232
|
package_options = {}
|
218
|
-
package_options[:labels] = Array(labels).map(&:to_s) if labels
|
233
|
+
package_options[:labels] = Array(labels).map(&:to_s) if labels
|
219
234
|
package_options[:require_name] = req
|
220
235
|
package_options[:require_name] ||= package if builtin
|
221
236
|
tm = TargetMethods.new(functions, Package.build_from_path(package, **package_options))
|
@@ -449,13 +464,17 @@ module AppMap
|
|
449
464
|
return unless location_file
|
450
465
|
|
451
466
|
location_file = AppMap::Util.normalize_path(location_file)
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
467
|
+
|
468
|
+
pkg = config
|
469
|
+
.packages
|
470
|
+
.select { |pkg| pkg.path }
|
471
|
+
.select do |pkg|
|
472
|
+
(location_file.index(pkg.path) == 0) &&
|
473
|
+
!pkg.exclude.find { |p| location_file.index(p) }
|
474
|
+
end
|
475
|
+
.min { |a, b| b.path <=> a.path } # Longest matching package first
|
476
|
+
|
477
|
+
pkg.subpackage(location_file, config) if pkg
|
459
478
|
end
|
460
479
|
end
|
461
480
|
|
data/lib/appmap/hook.rb
CHANGED
@@ -7,8 +7,10 @@ module AppMap
|
|
7
7
|
LOG = (ENV['APPMAP_DEBUG'] == 'true' || ENV['DEBUG'] == 'true')
|
8
8
|
LOG_HOOK = (ENV['DEBUG_HOOK'] == 'true')
|
9
9
|
|
10
|
-
OBJECT_INSTANCE_METHODS = %i[! != !~ <=> == === =~ __id__ __send__ class clone define_singleton_method display dup
|
11
|
-
|
10
|
+
OBJECT_INSTANCE_METHODS = %i[! != !~ <=> == === =~ __id__ __send__ class clone define_singleton_method display dup
|
11
|
+
enum_for eql? equal? extend freeze frozen? hash inspect instance_eval instance_exec instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method methods nil? object_id private_methods protected_methods public_method public_methods public_send remove_instance_variable respond_to? send singleton_class singleton_method singleton_methods taint tainted? tap then to_enum to_s to_h to_a trust untaint untrust untrusted? yield_self].freeze
|
12
|
+
OBJECT_STATIC_METHODS = %i[! != !~ < <= <=> == === =~ > >= __id__ __send__ alias_method allocate ancestors attr
|
13
|
+
attr_accessor attr_reader attr_writer autoload autoload? class class_eval class_exec class_variable_defined? class_variable_get class_variable_set class_variables clone const_defined? const_get const_missing const_set constants define_method define_singleton_method deprecate_constant display dup enum_for eql? equal? extend freeze frozen? hash include include? included_modules inspect instance_eval instance_exec instance_method instance_methods instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method method_defined? methods module_eval module_exec name new nil? object_id prepend private_class_method private_constant private_instance_methods private_method_defined? private_methods protected_instance_methods protected_method_defined? protected_methods public_class_method public_constant public_instance_method public_instance_methods public_method public_method_defined? public_methods public_send remove_class_variable remove_instance_variable remove_method respond_to? send singleton_class singleton_class? singleton_method singleton_methods superclass taint tainted? tap then to_enum to_s trust undef_method untaint untrust untrusted? yield_self].freeze
|
12
14
|
SLOW_PACKAGE_THRESHOLD = 0.05
|
13
15
|
|
14
16
|
@unbound_method_arity = ::UnboundMethod.instance_method(:arity)
|
@@ -29,7 +31,7 @@ module AppMap
|
|
29
31
|
def already_hooked?(method)
|
30
32
|
# After a method is defined, the statement "module_function <the-method>" can convert that method
|
31
33
|
# into a module (class) method. The method is hooked first when it's defined, then AppMap will attempt to
|
32
|
-
# hook it again when it's redefined as a module method. So we check the method source location - if it's
|
34
|
+
# hook it again when it's redefined as a module method. So we check the method source location - if it's
|
33
35
|
# part of the AppMap source tree, we ignore it.
|
34
36
|
method.source_location && method.source_location[0].index(__dir__) == 0
|
35
37
|
end
|
@@ -63,7 +65,7 @@ module AppMap
|
|
63
65
|
@notrace_paths = Set.new
|
64
66
|
# Locations that have already been visited.
|
65
67
|
@trace_locations = Set.new
|
66
|
-
@module_load_times = Hash.new {|memo,k| memo[k] = 0}
|
68
|
+
@module_load_times = Hash.new { |memo, k| memo[k] = 0 }
|
67
69
|
@slow_packages = Set.new
|
68
70
|
|
69
71
|
if ENV['APPMAP_PROFILE_HOOK'] == 'true'
|
@@ -90,18 +92,20 @@ module AppMap
|
|
90
92
|
end
|
91
93
|
|
92
94
|
# hook_builtins builds hooks for code that is built in to the Ruby standard library.
|
93
|
-
# No TracePoint events are emitted for builtins, so a separate hooking mechanism is needed.
|
95
|
+
# No TracePoint events are emitted for builtins, so a separate hooking mechanism is needed.
|
94
96
|
def hook_builtins
|
95
97
|
return unless self.class.hook_builtins?
|
96
98
|
|
97
99
|
hook_loaded_code = lambda do |hooks_by_class, builtin|
|
98
100
|
hooks_by_class.each do |class_name, hooks|
|
99
101
|
Array(hooks).each do |hook|
|
100
|
-
|
102
|
+
if builtin && hook.package.require_name && hook.package.require_name != 'ruby'
|
103
|
+
require hook.package.require_name
|
104
|
+
end
|
101
105
|
|
102
106
|
Array(hook.method_names).each do |method_name|
|
103
107
|
method_name = method_name.to_sym
|
104
|
-
base_cls = Util
|
108
|
+
base_cls = Util.class_from_string(class_name, must: false)
|
105
109
|
next unless base_cls
|
106
110
|
|
107
111
|
hook_method = lambda do |entry|
|
@@ -113,8 +117,10 @@ module AppMap
|
|
113
117
|
|
114
118
|
methods = []
|
115
119
|
methods << [ base_cls, base_cls.public_instance_method(method_name) ] rescue nil
|
120
|
+
methods << [ base_cls, base_cls.protected_instance_method(method_name) ] rescue nil
|
116
121
|
if base_cls.respond_to?(:singleton_class)
|
117
122
|
methods << [ base_cls.singleton_class, base_cls.singleton_class.public_instance_method(method_name) ] rescue nil
|
123
|
+
methods << [ base_cls.singleton_class, base_cls.singleton_class.protected_instance_method(method_name) ] rescue nil
|
118
124
|
end
|
119
125
|
methods.compact!
|
120
126
|
if methods.empty?
|
@@ -144,19 +150,19 @@ module AppMap
|
|
144
150
|
|
145
151
|
path = trace_point.path
|
146
152
|
enabled = !@notrace_paths.member?(path) && config.path_enabled?(path)
|
147
|
-
|
148
|
-
warn
|
153
|
+
unless enabled
|
154
|
+
warn 'Not hooking - path is not enabled' if Hook::LOG || Hook::LOG_HOOK
|
149
155
|
@notrace_paths << path
|
150
156
|
return
|
151
157
|
end
|
152
158
|
|
153
159
|
cls = trace_point.self
|
154
160
|
|
155
|
-
instance_methods = cls.public_instance_methods(false) - OBJECT_INSTANCE_METHODS
|
161
|
+
instance_methods = cls.public_instance_methods(false) + cls.protected_instance_methods(false) - OBJECT_INSTANCE_METHODS
|
156
162
|
# NoMethodError: private method `singleton_class' called for Rack::MiniProfiler:Class
|
157
163
|
class_methods = begin
|
158
164
|
if cls.respond_to?(:singleton_class)
|
159
|
-
cls.singleton_class.public_instance_methods(false) - instance_methods - OBJECT_STATIC_METHODS
|
165
|
+
cls.singleton_class.public_instance_methods(false) + cls.singleton_class.protected_instance_methods(false) - instance_methods - OBJECT_STATIC_METHODS
|
160
166
|
else
|
161
167
|
[]
|
162
168
|
end
|
@@ -172,12 +178,13 @@ module AppMap
|
|
172
178
|
|
173
179
|
next if method_id == :call
|
174
180
|
|
175
|
-
method =
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
+
method = \
|
182
|
+
begin
|
183
|
+
hook_cls.instance_method(method_id)
|
184
|
+
rescue NameError
|
185
|
+
warn "AppMap: Method #{hook_cls} #{fn} is not accessible: #{$!}" if LOG
|
186
|
+
next
|
187
|
+
end
|
181
188
|
|
182
189
|
next if self.class.already_hooked?(method)
|
183
190
|
|
data/lib/appmap/version.rb
CHANGED
data/spec/class_map_spec.rb
CHANGED
@@ -16,7 +16,7 @@ describe 'AppMap::ClassMap' do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def ruby_method(method)
|
19
|
-
AppMap::Trace::RubyMethod.new AppMap::Config::Package.new, method.receiver.class.name, method, false
|
19
|
+
AppMap::Trace::RubyMethod.new AppMap::Config::Package.new('pkg'), method.receiver.class.name, method, false
|
20
20
|
end
|
21
21
|
|
22
22
|
def dig_map(map, depth)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ProtectedMethod
|
4
|
+
def call_protected
|
5
|
+
protected_method
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
'Protected Method fixture'
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def call_protected
|
14
|
+
protected_method
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def protected_method
|
20
|
+
'self.protected'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def protected_method
|
27
|
+
'protected'
|
28
|
+
end
|
29
|
+
end
|
data/spec/hook_spec.rb
CHANGED
@@ -9,7 +9,7 @@ require 'diffy'
|
|
9
9
|
# empty. This make some of the expected YAML below easier to
|
10
10
|
# understand.
|
11
11
|
module ShowYamlNulls
|
12
|
-
def visit_NilClass(
|
12
|
+
def visit_NilClass(_o)
|
13
13
|
@emitter.scalar('null', nil, 'tag:yaml.org,2002:null', true, false, Psych::Nodes::Scalar::ANY)
|
14
14
|
end
|
15
15
|
end
|
@@ -18,10 +18,10 @@ Psych::Visitors::YAMLTree.prepend(ShowYamlNulls)
|
|
18
18
|
describe 'AppMap class Hooking', docker: false do
|
19
19
|
include_context 'collect events'
|
20
20
|
|
21
|
-
def invoke_test_file(file, setup: nil,
|
21
|
+
def invoke_test_file(file, setup: nil, packages: nil)
|
22
22
|
AppMap.configuration = nil
|
23
|
-
|
24
|
-
config = AppMap::Config.new('hook_spec', packages:
|
23
|
+
packages ||= [ AppMap::Config::Package.build_from_path(file) ]
|
24
|
+
config = AppMap::Config.new('hook_spec', packages: packages)
|
25
25
|
AppMap.configuration = config
|
26
26
|
tracer = nil
|
27
27
|
AppMap::Hook.new(config).enable do
|
@@ -153,7 +153,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
153
153
|
class_map = AppMap.class_map(tracer.event_methods).to_yaml
|
154
154
|
expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
|
155
155
|
---
|
156
|
-
- :name: spec/fixtures/hook
|
156
|
+
- :name: spec/fixtures/hook
|
157
157
|
:type: package
|
158
158
|
:children:
|
159
159
|
- :name: ClassWithLabel
|
@@ -166,7 +166,41 @@ describe 'AppMap class Hooking', docker: false do
|
|
166
166
|
:labels:
|
167
167
|
- has-fn-label
|
168
168
|
:comment: "# @label has-fn-label\\n"
|
169
|
-
|
169
|
+
YAML
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'reports sub-folders as distinct packages' do
|
173
|
+
_, tracer = invoke_test_file 'spec/fixtures/hook/sub_packages.rb',
|
174
|
+
packages: [ AppMap::Config::Package.build_from_path('spec/fixtures/hook') ] do
|
175
|
+
SubPackages.invoke_a
|
176
|
+
end
|
177
|
+
class_map = AppMap.class_map(tracer.event_methods).to_yaml
|
178
|
+
expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
|
179
|
+
---
|
180
|
+
- :name: spec/fixtures/hook
|
181
|
+
:type: package
|
182
|
+
:children:
|
183
|
+
- :name: SubPackages
|
184
|
+
:type: class
|
185
|
+
:children:
|
186
|
+
- :name: invoke_a
|
187
|
+
:type: function
|
188
|
+
:location: spec/fixtures/hook/sub_packages.rb:4
|
189
|
+
:static: true
|
190
|
+
- :name: pkg_a
|
191
|
+
:type: package
|
192
|
+
:children:
|
193
|
+
- :name: PkgA
|
194
|
+
:type: class
|
195
|
+
:children:
|
196
|
+
- :name: A
|
197
|
+
:type: class
|
198
|
+
:children:
|
199
|
+
- :name: hello
|
200
|
+
:type: function
|
201
|
+
:location: spec/fixtures/hook/pkg_a/a.rb:3
|
202
|
+
:static: true
|
203
|
+
YAML
|
170
204
|
end
|
171
205
|
|
172
206
|
it 'hooks an instance method that takes no arguments' do
|
@@ -210,7 +244,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
210
244
|
class_map = AppMap.class_map(tracer.event_methods).to_yaml
|
211
245
|
expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
|
212
246
|
---
|
213
|
-
- :name: spec/fixtures/hook
|
247
|
+
- :name: spec/fixtures/hook
|
214
248
|
:type: package
|
215
249
|
:children:
|
216
250
|
- :name: InstanceMethod
|
@@ -243,6 +277,92 @@ describe 'AppMap class Hooking', docker: false do
|
|
243
277
|
end
|
244
278
|
end
|
245
279
|
|
280
|
+
it 'records protected instance methods' do
|
281
|
+
events_yaml = <<~YAML
|
282
|
+
---
|
283
|
+
- :id: 1
|
284
|
+
:event: :call
|
285
|
+
:defined_class: ProtectedMethod
|
286
|
+
:method_id: call_protected
|
287
|
+
:path: spec/fixtures/hook/protected_method.rb
|
288
|
+
:lineno: 4
|
289
|
+
:static: false
|
290
|
+
:parameters: []
|
291
|
+
:receiver:
|
292
|
+
:class: ProtectedMethod
|
293
|
+
:value: Protected Method fixture
|
294
|
+
- :id: 2
|
295
|
+
:event: :call
|
296
|
+
:defined_class: ProtectedMethod
|
297
|
+
:method_id: protected_method
|
298
|
+
:path: spec/fixtures/hook/protected_method.rb
|
299
|
+
:lineno: 26
|
300
|
+
:static: false
|
301
|
+
:parameters: []
|
302
|
+
:receiver:
|
303
|
+
:class: ProtectedMethod
|
304
|
+
:value: Protected Method fixture
|
305
|
+
- :id: 3
|
306
|
+
:event: :return
|
307
|
+
:parent_id: 2
|
308
|
+
:return_value:
|
309
|
+
:class: String
|
310
|
+
:value: protected
|
311
|
+
- :id: 4
|
312
|
+
:event: :return
|
313
|
+
:parent_id: 1
|
314
|
+
:return_value:
|
315
|
+
:class: String
|
316
|
+
:value: protected
|
317
|
+
YAML
|
318
|
+
test_hook_behavior 'spec/fixtures/hook/protected_method.rb', events_yaml do
|
319
|
+
expect(ProtectedMethod.new.call_protected).to eq('protected')
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'records protected singleton (static) methods' do
|
324
|
+
events_yaml = <<~YAML
|
325
|
+
---
|
326
|
+
- :id: 1
|
327
|
+
:event: :call
|
328
|
+
:defined_class: ProtectedMethod
|
329
|
+
:method_id: call_protected
|
330
|
+
:path: spec/fixtures/hook/protected_method.rb
|
331
|
+
:lineno: 13
|
332
|
+
:static: true
|
333
|
+
:parameters: []
|
334
|
+
:receiver:
|
335
|
+
:class: Class
|
336
|
+
:value: ProtectedMethod
|
337
|
+
- :id: 2
|
338
|
+
:event: :call
|
339
|
+
:defined_class: ProtectedMethod
|
340
|
+
:method_id: protected_method
|
341
|
+
:path: spec/fixtures/hook/protected_method.rb
|
342
|
+
:lineno: 19
|
343
|
+
:static: true
|
344
|
+
:parameters: []
|
345
|
+
:receiver:
|
346
|
+
:class: Class
|
347
|
+
:value: ProtectedMethod
|
348
|
+
- :id: 3
|
349
|
+
:event: :return
|
350
|
+
:parent_id: 2
|
351
|
+
:return_value:
|
352
|
+
:class: String
|
353
|
+
:value: self.protected
|
354
|
+
- :id: 4
|
355
|
+
:event: :return
|
356
|
+
:parent_id: 1
|
357
|
+
:return_value:
|
358
|
+
:class: String
|
359
|
+
:value: self.protected
|
360
|
+
YAML
|
361
|
+
test_hook_behavior 'spec/fixtures/hook/protected_method.rb', events_yaml do
|
362
|
+
expect(ProtectedMethod.call_protected).to eq('self.protected')
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
246
366
|
it 'hooks an instance method that takes an argument' do
|
247
367
|
events_yaml = <<~YAML
|
248
368
|
---
|
@@ -483,7 +603,6 @@ describe 'AppMap class Hooking', docker: false do
|
|
483
603
|
end
|
484
604
|
end
|
485
605
|
|
486
|
-
|
487
606
|
it 'hooks an included method' do
|
488
607
|
events_yaml = <<~YAML
|
489
608
|
---
|
@@ -607,11 +726,9 @@ describe 'AppMap class Hooking', docker: false do
|
|
607
726
|
:lineno: 9
|
608
727
|
YAML
|
609
728
|
test_hook_behavior 'spec/fixtures/hook/exception_method.rb', events_yaml do
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
# don't let the exception fail the test
|
614
|
-
end
|
729
|
+
ExceptionMethod.new.raise_exception
|
730
|
+
rescue
|
731
|
+
# don't let the exception fail the test
|
615
732
|
end
|
616
733
|
end
|
617
734
|
|
@@ -639,16 +756,13 @@ describe 'AppMap class Hooking', docker: false do
|
|
639
756
|
:lineno: 59
|
640
757
|
YAML
|
641
758
|
test_hook_behavior 'spec/fixtures/hook/exception_method.rb', events_yaml do
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
# don't let the exception fail the test
|
646
|
-
end
|
759
|
+
ExceptionMethod.new.raise_illegal_utf8_message
|
760
|
+
rescue
|
761
|
+
# don't let the exception fail the test
|
647
762
|
end
|
648
763
|
end
|
649
764
|
|
650
765
|
context 'string conversions works for the receiver when' do
|
651
|
-
|
652
766
|
it 'is missing #to_s' do
|
653
767
|
events_yaml = <<~YAML
|
654
768
|
---
|
@@ -979,7 +1093,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
979
1093
|
end
|
980
1094
|
end
|
981
1095
|
|
982
|
-
it
|
1096
|
+
it 'preserves the arity of hooked methods' do
|
983
1097
|
invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
|
984
1098
|
expect(InstanceMethod.instance_method(:say_echo).arity).to be(1)
|
985
1099
|
expect(InstanceMethod.new.method(:say_echo).arity).to be(1)
|
@@ -157,31 +157,31 @@ describe 'Rails' do
|
|
157
157
|
)
|
158
158
|
|
159
159
|
expect(appmap['classMap']).to include hash_including(
|
160
|
-
'name' => 'app
|
160
|
+
'name' => 'app',
|
161
161
|
'children' => include(hash_including(
|
162
|
-
'name' => '
|
162
|
+
'name' => 'views',
|
163
163
|
'children' => include(hash_including(
|
164
|
-
'name' => '
|
165
|
-
'
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
164
|
+
'name' => 'app_views_users_index_html_haml',
|
165
|
+
'children' => include(hash_including(
|
166
|
+
'name' => 'render',
|
167
|
+
'type' => 'function',
|
168
|
+
'location' => 'app/views/users/index.html.haml',
|
169
|
+
'static' => true,
|
170
|
+
'labels' => [ 'mvc.template' ]
|
171
|
+
)))))))
|
172
172
|
expect(appmap['classMap']).to include hash_including(
|
173
|
-
'name' => 'app
|
173
|
+
'name' => 'app',
|
174
174
|
'children' => include(hash_including(
|
175
|
-
'name' => '
|
175
|
+
'name' => 'views',
|
176
176
|
'children' => include(hash_including(
|
177
|
-
'name' => '
|
178
|
-
'
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
177
|
+
'name' => 'app_views_layouts_application_html_haml',
|
178
|
+
'children' => include(hash_including(
|
179
|
+
'name' => 'render',
|
180
|
+
'type' => 'function',
|
181
|
+
'location' => 'app/views/layouts/application.html.haml',
|
182
|
+
'static' => true,
|
183
|
+
'labels' => [ 'mvc.template' ]
|
184
|
+
)))))))
|
185
185
|
end
|
186
186
|
end
|
187
187
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appmap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.70.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Gilpin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -3506,10 +3506,13 @@ files:
|
|
3506
3506
|
- spec/fixtures/hook/kwargs.rb
|
3507
3507
|
- spec/fixtures/hook/labels.rb
|
3508
3508
|
- spec/fixtures/hook/method_named_call.rb
|
3509
|
+
- spec/fixtures/hook/pkg_a/a.rb
|
3510
|
+
- spec/fixtures/hook/protected_method.rb
|
3509
3511
|
- spec/fixtures/hook/revoke_api_key.appmap.json
|
3510
3512
|
- spec/fixtures/hook/singleton_method.rb
|
3511
3513
|
- spec/fixtures/hook/spec/api_spec.rb
|
3512
3514
|
- spec/fixtures/hook/spec/user_spec.rb
|
3515
|
+
- spec/fixtures/hook/sub_packages.rb
|
3513
3516
|
- spec/fixtures/hook/user_page_scenario.appmap.json
|
3514
3517
|
- spec/fixtures/rack_users_app/.dockerignore
|
3515
3518
|
- spec/fixtures/rack_users_app/.gitignore
|