appmap 0.43.0 → 0.47.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.releaserc.yml +11 -0
  3. data/.travis.yml +33 -2
  4. data/CHANGELOG.md +44 -0
  5. data/README.md +66 -11
  6. data/README_CI.md +29 -0
  7. data/Rakefile +4 -2
  8. data/appmap.gemspec +5 -3
  9. data/lib/appmap.rb +3 -7
  10. data/lib/appmap/class_map.rb +11 -22
  11. data/lib/appmap/command/record.rb +1 -1
  12. data/lib/appmap/config.rb +180 -67
  13. data/lib/appmap/cucumber.rb +1 -1
  14. data/lib/appmap/event.rb +29 -28
  15. data/lib/appmap/handler/function.rb +19 -0
  16. data/lib/appmap/handler/net_http.rb +107 -0
  17. data/lib/appmap/handler/rails/request_handler.rb +124 -0
  18. data/lib/appmap/handler/rails/sql_handler.rb +152 -0
  19. data/lib/appmap/handler/rails/template.rb +149 -0
  20. data/lib/appmap/hook.rb +111 -70
  21. data/lib/appmap/hook/method.rb +6 -8
  22. data/lib/appmap/middleware/remote_recording.rb +1 -1
  23. data/lib/appmap/minitest.rb +22 -20
  24. data/lib/appmap/railtie.rb +5 -5
  25. data/lib/appmap/record.rb +1 -1
  26. data/lib/appmap/rspec.rb +22 -21
  27. data/lib/appmap/trace.rb +47 -6
  28. data/lib/appmap/util.rb +57 -2
  29. data/lib/appmap/version.rb +2 -2
  30. data/package-lock.json +3 -3
  31. data/release.sh +17 -0
  32. data/spec/abstract_controller_base_spec.rb +76 -15
  33. data/spec/class_map_spec.rb +5 -13
  34. data/spec/config_spec.rb +33 -1
  35. data/spec/fixtures/hook/custom_instance_method.rb +11 -0
  36. data/spec/fixtures/hook/method_named_call.rb +11 -0
  37. data/spec/hook_spec.rb +143 -22
  38. data/spec/record_net_http_spec.rb +160 -0
  39. data/spec/spec_helper.rb +10 -0
  40. data/spec/util_spec.rb +18 -1
  41. data/test/expectations/openssl_test_key_sign1.json +2 -4
  42. data/test/gem_test.rb +1 -1
  43. data/test/rspec_test.rb +0 -13
  44. metadata +20 -14
  45. data/exe/appmap +0 -154
  46. data/lib/appmap/rails/request_handler.rb +0 -140
  47. data/lib/appmap/rails/sql_handler.rb +0 -150
  48. data/test/cli_test.rb +0 -116
data/lib/appmap/trace.rb CHANGED
@@ -2,14 +2,36 @@
2
2
 
3
3
  module AppMap
4
4
  module Trace
5
- class ScopedMethod < SimpleDelegator
6
- attr_reader :package, :defined_class, :static
5
+ class RubyMethod
6
+ attr_reader :class_name, :static
7
7
 
8
- def initialize(package, defined_class, method, static)
8
+ def initialize(package, class_name, method, static)
9
9
  @package = package
10
- @defined_class = defined_class
10
+ @class_name = class_name
11
+ @method = method
11
12
  @static = static
12
- super(method)
13
+ end
14
+
15
+ def source_location
16
+ @method.source_location
17
+ end
18
+
19
+ def comment
20
+ @method.comment
21
+ rescue MethodSource::SourceNotFoundError
22
+ nil
23
+ end
24
+
25
+ def package
26
+ @package.name
27
+ end
28
+
29
+ def name
30
+ @method.name
31
+ end
32
+
33
+ def labels
34
+ @package.labels
13
35
  end
14
36
  end
15
37
 
@@ -43,6 +65,12 @@ module AppMap
43
65
  end
44
66
  end
45
67
 
68
+ def record_method(method)
69
+ @tracers.each do |tracer|
70
+ tracer.record_method(method)
71
+ end
72
+ end
73
+
46
74
  def delete(tracer)
47
75
  return unless @tracers.member?(tracer)
48
76
 
@@ -82,10 +110,23 @@ module AppMap
82
110
 
83
111
  @last_package_for_thread[Thread.current.object_id] = package if package
84
112
  @events << event
85
- @methods << Trace::ScopedMethod.new(package, defined_class, method, event.static) \
113
+ static = event.static if event.respond_to?(:static)
114
+ @methods << Trace::RubyMethod.new(package, defined_class, method, static) \
86
115
  if package && defined_class && method && (event.event == :call)
87
116
  end
88
117
 
118
+ # +method+ should be duck-typed to respond to the following:
119
+ # * package
120
+ # * defined_class
121
+ # * name
122
+ # * static
123
+ # * comment
124
+ # * labels
125
+ # * source_location
126
+ def record_method(method)
127
+ @methods << method
128
+ end
129
+
89
130
  # Gets the last package which was observed on the current thread.
90
131
  def last_package_for_current_thread
91
132
  @last_package_for_thread[Thread.current.object_id]
data/lib/appmap/util.rb CHANGED
@@ -61,8 +61,16 @@ module AppMap
61
61
  delete_object_id = ->(obj) { (obj || {}).delete(:object_id) }
62
62
  delete_object_id.call(event[:receiver])
63
63
  delete_object_id.call(event[:return_value])
64
- (event[:parameters] || []).each(&delete_object_id)
65
- (event[:exceptions] || []).each(&delete_object_id)
64
+ %i[parameters exceptions message].each do |field|
65
+ (event[field] || []).each(&delete_object_id)
66
+ end
67
+ %i[http_client_request http_client_response http_server_request http_server_response].each do |field|
68
+ headers = event.dig(field, :headers)
69
+ next unless headers
70
+
71
+ headers['Date'] = '<instanceof date>' if headers['Date']
72
+ headers['Server'] = headers['Server'].match(/^(\w+)/)[0] if headers['Server']
73
+ end
66
74
 
67
75
  case event[:event]
68
76
  when :call
@@ -71,6 +79,53 @@ module AppMap
71
79
 
72
80
  event
73
81
  end
82
+
83
+ def select_headers(env)
84
+ # Rack prepends HTTP_ to all client-sent headers.
85
+ matching_headers = env
86
+ .select { |k,v| k.start_with? 'HTTP_'}
87
+ .reject { |k,v| v.blank? }
88
+ .each_with_object({}) do |kv, memo|
89
+ key = kv[0].sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
90
+ value = kv[1]
91
+ memo[key] = value
92
+ end
93
+ matching_headers.blank? ? nil : matching_headers
94
+ end
95
+
96
+ def normalize_path(path)
97
+ if path.index(Dir.pwd) == 0
98
+ path[Dir.pwd.length + 1..-1]
99
+ else
100
+ path
101
+ end
102
+ end
103
+
104
+ # Convert a Rails-style path from /org/:org_id(.:format)
105
+ # to Swagger-style paths like /org/{org_id}
106
+ def swaggerize_path(path)
107
+ path = path.split('(.')[0]
108
+ tokens = path.split('/')
109
+ tokens.map do |token|
110
+ token.gsub /^:(.*)/, '{\1}'
111
+ end.join('/')
112
+ end
113
+
114
+ # Atomically writes AppMap data to +filename+.
115
+ def write_appmap(filename, appmap)
116
+ require 'fileutils'
117
+ require 'tmpdir'
118
+
119
+ # This is what Ruby Tempfile does; but we don't want the file to be unlinked.
120
+ mode = File::RDWR | File::CREAT | File::EXCL
121
+ ::Dir::Tmpname.create([ 'appmap_', '.json' ]) do |tmpname|
122
+ tempfile = File.open(tmpname, mode)
123
+ tempfile.write(appmap)
124
+ tempfile.close
125
+ # Atomically move the tempfile into place.
126
+ FileUtils.mv tempfile.path, filename
127
+ end
128
+ end
74
129
  end
75
130
  end
76
131
  end
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.43.0'
6
+ VERSION = '0.47.0'
7
7
 
8
- APPMAP_FORMAT_VERSION = '1.4'
8
+ APPMAP_FORMAT_VERSION = '1.5.0'
9
9
  end
data/package-lock.json CHANGED
@@ -551,9 +551,9 @@
551
551
  }
552
552
  },
553
553
  "lodash": {
554
- "version": "4.17.19",
555
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
556
- "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
554
+ "version": "4.17.21",
555
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
556
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
557
557
  },
558
558
  "longest": {
559
559
  "version": "1.0.1",
data/release.sh ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ # using bash wrapper as Rake blows up in `require/extentiontask` (line 10)
3
+
4
+ RELEASE_FLAGS=""
5
+ if [ ! -z "$TRAVIS_REPO_SLUG" ]; then
6
+ RELEASE_FLAGS="-r git+https://github.com/${TRAVIS_REPO_SLUG}.git"
7
+ fi
8
+
9
+ if [ ! -z "$GEM_ALTERNATIVE_NAME" ]; then
10
+ echo "Release: GEM_ALTERNATIVE_NAME=$GEM_ALTERNATIVE_NAME"
11
+ else
12
+ echo "No GEM_ALTERNATIVE_NAME is provided, releasing gem with default name ('appmap')"
13
+ fi
14
+
15
+ set -x
16
+ exec semantic-release $RELEASE_FLAGS
17
+
@@ -27,6 +27,8 @@ describe 'Rails' do
27
27
  end
28
28
 
29
29
  let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
30
+ let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
31
+ let(:appmap) { JSON.parse File.read(appmap_json_path) }
30
32
  let(:events) { appmap['events'] }
31
33
 
32
34
  describe 'an API route' do
@@ -35,16 +37,12 @@ describe 'Rails' do
35
37
  'Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json'
36
38
  end
37
39
 
38
- it 'inventory file is printed' do
39
- expect(File).to exist(File.join(tmpdir, 'appmap/rspec/Inventory.appmap.json'))
40
- end
41
-
42
40
  it 'http_server_request is recorded in the appmap' do
43
41
  expect(events).to include(
44
42
  hash_including(
45
43
  'http_server_request' => hash_including(
46
44
  'request_method' => 'POST',
47
- 'normalized_path_info' => '/api/users(.:format)',
45
+ 'normalized_path_info' => '/api/users',
48
46
  'path_info' => '/api/users'
49
47
  ),
50
48
  'message' => include(
@@ -69,8 +67,8 @@ describe 'Rails' do
69
67
  expect(events).to include(
70
68
  hash_including(
71
69
  'http_server_response' => hash_including(
72
- 'status' => 201,
73
- 'mime_type' => 'application/json; charset=utf-8'
70
+ 'status_code' => 201,
71
+ 'mime_type' => 'application/json; charset=utf-8',
74
72
  )
75
73
  )
76
74
  )
@@ -146,7 +144,49 @@ describe 'Rails' do
146
144
  end
147
145
 
148
146
  describe 'a UI route' do
149
- describe 'rendering a page' do
147
+ describe 'rendering a page using a template file' do
148
+ let(:appmap_json_file) do
149
+ 'UsersController_GET_users_lists_the_users.appmap.json'
150
+ end
151
+
152
+ it 'records the template file' do
153
+ expect(events).to include hash_including(
154
+ 'event' => 'call',
155
+ 'defined_class' => 'app_views_users_index_html_haml',
156
+ 'method_id' => 'render',
157
+ 'path' => 'app/views/users/index.html.haml'
158
+ )
159
+
160
+ expect(appmap['classMap']).to include hash_including(
161
+ 'name' => 'app/views',
162
+ 'children' => include(hash_including(
163
+ 'name' => 'app_views_users_index_html_haml',
164
+ 'children' => include(hash_including(
165
+ 'name' => 'render',
166
+ 'type' => 'function',
167
+ 'location' => 'app/views/users/index.html.haml',
168
+ 'static' => true,
169
+ 'labels' => [ 'mvc.template' ]
170
+ ))
171
+ ))
172
+ )
173
+ expect(appmap['classMap']).to include hash_including(
174
+ 'name' => 'app/views',
175
+ 'children' => include(hash_including(
176
+ 'name' => 'app_views_layouts_application_html_haml',
177
+ 'children' => include(hash_including(
178
+ 'name' => 'render',
179
+ 'type' => 'function',
180
+ 'location' => 'app/views/layouts/application.html.haml',
181
+ 'static' => true,
182
+ 'labels' => [ 'mvc.template' ]
183
+ ))
184
+ ))
185
+ )
186
+ end
187
+ end
188
+
189
+ describe 'rendering a page using a text template' do
150
190
  let(:appmap_json_file) do
151
191
  'UsersController_GET_users_login_shows_the_user.appmap.json'
152
192
  end
@@ -157,25 +197,46 @@ describe 'Rails' do
157
197
  'http_server_request' => {
158
198
  'request_method' => 'GET',
159
199
  'path_info' => '/users/alice',
160
- 'normalized_path_info' => '/users/:id(.:format)'
200
+ 'normalized_path_info' => '/users/{id}',
201
+ 'headers' => {
202
+ 'Host' => 'test.host',
203
+ 'User-Agent' => 'Rails Testing'
204
+ }
161
205
  }
162
206
  )
163
207
  )
164
208
  end
165
209
 
210
+ it 'ignores the text template' do
211
+ expect(events).to_not include hash_including(
212
+ 'event' => 'call',
213
+ 'method_id' => 'render',
214
+ 'render_template' => anything
215
+ )
216
+
217
+ expect(appmap['classMap']).to_not include hash_including(
218
+ 'name' => 'views',
219
+ 'children' => include(hash_including(
220
+ 'name' => 'ViewTemplate',
221
+ 'children' => include(hash_including(
222
+ 'name' => 'render',
223
+ 'type' => 'function',
224
+ 'location' => 'text template'
225
+ ))
226
+ ))
227
+ )
228
+ end
229
+
166
230
  it 'records and labels view rendering' do
167
231
  expect(events).to include hash_including(
168
232
  'event' => 'call',
169
233
  'thread_id' => Numeric,
170
- 'defined_class' => 'ActionView::Renderer',
171
- 'method_id' => 'render',
172
- 'path' => String,
173
- 'lineno' => Integer,
174
- 'static' => false
234
+ 'defined_class' => 'inline_template',
235
+ 'method_id' => 'render'
175
236
  )
176
237
 
177
238
  expect(appmap['classMap']).to include hash_including(
178
- 'name' => 'action_view',
239
+ 'name' => 'actionview',
179
240
  'children' => include(hash_including(
180
241
  'name' => 'ActionView',
181
242
  'children' => include(hash_including(
@@ -4,18 +4,10 @@ require 'spec_helper'
4
4
 
5
5
  describe 'AppMap::ClassMap' do
6
6
  describe '.build_from_methods' do
7
- it 'includes source code if available' do
8
- map = AppMap.class_map([scoped_method(method(:test_method))])
7
+ it 'includes method comment' do
8
+ map = AppMap.class_map([ruby_method((method :test_method))])
9
9
  function = dig_map(map, 5)[0]
10
- expect(function[:source]).to include 'test method body'
11
- expect(function[:comment]).to include 'test method comment'
12
- end
13
-
14
- it 'can omit source code even if available' do
15
- map = AppMap.class_map([scoped_method((method :test_method))], include_source: false)
16
- function = dig_map(map, 5)[0]
17
- expect(function).to_not include(:source)
18
- expect(function).to_not include(:comment)
10
+ expect(function).to include(:comment)
19
11
  end
20
12
 
21
13
  # test method comment
@@ -23,8 +15,8 @@ describe 'AppMap::ClassMap' do
23
15
  'test method body'
24
16
  end
25
17
 
26
- def scoped_method(method)
27
- AppMap::Trace::ScopedMethod.new AppMap::Config::Package.new, method.receiver.class.name, method, false
18
+ def ruby_method(method)
19
+ AppMap::Trace::RubyMethod.new AppMap::Config::Package.new, method.receiver.class.name, method, false
28
20
  end
29
21
 
30
22
  def dig_map(map, depth)
data/spec/config_spec.rb CHANGED
@@ -17,10 +17,42 @@ describe AppMap::Config, docker: false do
17
17
  path: 'path-2',
18
18
  exclude: [ 'exclude-1' ]
19
19
  }
20
+ ],
21
+ functions: [
22
+ {
23
+ package: 'pkg',
24
+ class: 'cls',
25
+ function: 'fn',
26
+ label: 'lbl'
27
+ }
20
28
  ]
21
29
  }.deep_stringify_keys!
22
30
  config = AppMap::Config.load(config_data)
23
31
 
24
- expect(config.to_h.deep_stringify_keys!).to eq(config_data)
32
+ config_expectation = {
33
+ exclude: [],
34
+ name: 'test',
35
+ packages: [
36
+ {
37
+ path: 'path-1',
38
+ handler_class: 'AppMap::Handler::Function'
39
+ },
40
+ {
41
+ path: 'path-2',
42
+ handler_class: 'AppMap::Handler::Function',
43
+ exclude: [ 'exclude-1' ]
44
+ }
45
+ ],
46
+ functions: [
47
+ {
48
+ package: 'pkg',
49
+ class: 'cls',
50
+ functions: [ :fn ],
51
+ labels: ['lbl']
52
+ }
53
+ ]
54
+ }.deep_stringify_keys!
55
+
56
+ expect(config.to_h.deep_stringify_keys!).to eq(config_expectation)
25
57
  end
26
58
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CustomInstanceMethod
4
+ def to_s
5
+ 'CustomInstance Method fixture'
6
+ end
7
+
8
+ def say_default
9
+ 'default'
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MethodNamedCall
4
+ def to_s
5
+ 'MethodNamedCall'
6
+ end
7
+
8
+ def call(a, b, c, d, e)
9
+ [ a, b, c, d, e ].join(' ')
10
+ end
11
+ end
data/spec/hook_spec.rb CHANGED
@@ -16,14 +16,7 @@ end
16
16
  Psych::Visitors::YAMLTree.prepend(ShowYamlNulls)
17
17
 
18
18
  describe 'AppMap class Hooking', docker: false do
19
- require 'appmap/util'
20
- def collect_events(tracer)
21
- [].tap do |events|
22
- while tracer.event?
23
- events << tracer.next_event.to_h
24
- end
25
- end.map(&AppMap::Util.method(:sanitize_event))
26
- end
19
+ include_context 'collect events'
27
20
 
28
21
  def invoke_test_file(file, setup: nil, &block)
29
22
  AppMap.configuration = nil
@@ -64,11 +57,144 @@ describe 'AppMap class Hooking', docker: false do
64
57
  it 'excludes named classes and methods' do
65
58
  load 'spec/fixtures/hook/exclude.rb'
66
59
  package = AppMap::Config::Package.build_from_path('spec/fixtures/hook/exclude.rb')
67
- config = AppMap::Config.new('hook_spec', [ package ], %w[ExcludeTest])
60
+ config = AppMap::Config.new('hook_spec', [ package ], exclude: %w[ExcludeTest])
68
61
  AppMap.configuration = config
69
62
 
70
- expect(config.never_hook?(ExcludeTest.new.method(:instance_method))).to be_truthy
71
- expect(config.never_hook?(ExcludeTest.method(:cls_method))).to be_truthy
63
+ expect(config.never_hook?(ExcludeTest, ExcludeTest.new.method(:instance_method))).to be_truthy
64
+ expect(config.never_hook?(ExcludeTest, ExcludeTest.method(:cls_method))).to be_truthy
65
+ end
66
+
67
+ it "handles an instance method named 'call' without issues" do
68
+ events_yaml = <<~YAML
69
+ ---
70
+ - :id: 1
71
+ :event: :call
72
+ :defined_class: MethodNamedCall
73
+ :method_id: call
74
+ :path: spec/fixtures/hook/method_named_call.rb
75
+ :lineno: 8
76
+ :static: false
77
+ :parameters:
78
+ - :name: :a
79
+ :class: Integer
80
+ :value: '1'
81
+ :kind: :req
82
+ - :name: :b
83
+ :class: Integer
84
+ :value: '2'
85
+ :kind: :req
86
+ - :name: :c
87
+ :class: Integer
88
+ :value: '3'
89
+ :kind: :req
90
+ - :name: :d
91
+ :class: Integer
92
+ :value: '4'
93
+ :kind: :req
94
+ - :name: :e
95
+ :class: Integer
96
+ :value: '5'
97
+ :kind: :req
98
+ :receiver:
99
+ :class: MethodNamedCall
100
+ :value: MethodNamedCall
101
+ - :id: 2
102
+ :event: :return
103
+ :parent_id: 1
104
+ :return_value:
105
+ :class: String
106
+ :value: 1 2 3 4 5
107
+ YAML
108
+
109
+ _, tracer = test_hook_behavior 'spec/fixtures/hook/method_named_call.rb', events_yaml do
110
+ expect(MethodNamedCall.new.call(1, 2, 3, 4, 5)).to eq('1 2 3 4 5')
111
+ end
112
+ class_map = AppMap.class_map(tracer.event_methods)
113
+ expect(Diffy::Diff.new(<<~CLASSMAP, YAML.dump(class_map)).to_s).to eq('')
114
+ ---
115
+ - :name: spec/fixtures/hook/method_named_call.rb
116
+ :type: package
117
+ :children:
118
+ - :name: MethodNamedCall
119
+ :type: class
120
+ :children:
121
+ - :name: call
122
+ :type: function
123
+ :location: spec/fixtures/hook/method_named_call.rb:8
124
+ :static: false
125
+ CLASSMAP
126
+ end
127
+
128
+ it 'can custom hook and label a function' do
129
+ events_yaml = <<~YAML
130
+ ---
131
+ - :id: 1
132
+ :event: :call
133
+ :defined_class: CustomInstanceMethod
134
+ :method_id: say_default
135
+ :path: spec/fixtures/hook/custom_instance_method.rb
136
+ :lineno: 8
137
+ :static: false
138
+ :parameters: []
139
+ :receiver:
140
+ :class: CustomInstanceMethod
141
+ :value: CustomInstance Method fixture
142
+ - :id: 2
143
+ :event: :return
144
+ :parent_id: 1
145
+ :return_value:
146
+ :class: String
147
+ :value: default
148
+ YAML
149
+
150
+ config = AppMap::Config.load({
151
+ functions: [
152
+ {
153
+ package: 'hook_spec',
154
+ class: 'CustomInstanceMethod',
155
+ functions: [ :say_default ],
156
+ labels: ['cowsay']
157
+ }
158
+ ]
159
+ }.deep_stringify_keys)
160
+
161
+ load 'spec/fixtures/hook/custom_instance_method.rb'
162
+ hook_cls = CustomInstanceMethod
163
+ method = hook_cls.instance_method(:say_default)
164
+
165
+ require 'appmap/hook/method'
166
+ package = config.lookup_package(hook_cls, method)
167
+ expect(package).to be
168
+ hook_method = AppMap::Hook::Method.new(package, hook_cls, method)
169
+ hook_method.activate
170
+
171
+ tracer = AppMap.tracing.trace
172
+ AppMap::Event.reset_id_counter
173
+ begin
174
+ expect(CustomInstanceMethod.new.say_default).to eq('default')
175
+ ensure
176
+ AppMap.tracing.delete(tracer)
177
+ end
178
+
179
+ events = collect_events(tracer).to_yaml
180
+
181
+ expect(Diffy::Diff.new(events_yaml, events).to_s).to eq('')
182
+ class_map = AppMap.class_map(tracer.event_methods)
183
+ expect(Diffy::Diff.new(<<~CLASSMAP, YAML.dump(class_map)).to_s).to eq('')
184
+ ---
185
+ - :name: hook_spec
186
+ :type: package
187
+ :children:
188
+ - :name: CustomInstanceMethod
189
+ :type: class
190
+ :children:
191
+ - :name: say_default
192
+ :type: function
193
+ :location: spec/fixtures/hook/custom_instance_method.rb:8
194
+ :static: false
195
+ :labels:
196
+ - cowsay
197
+ CLASSMAP
72
198
  end
73
199
 
74
200
  it 'parses labels from comments' do
@@ -91,9 +217,6 @@ describe 'AppMap class Hooking', docker: false do
91
217
  :labels:
92
218
  - has-fn-label
93
219
  :comment: "# @label has-fn-label\\n"
94
- :source: |2
95
- def fn_with_label
96
- end
97
220
  YAML
98
221
  end
99
222
 
@@ -127,8 +250,8 @@ describe 'AppMap class Hooking', docker: false do
127
250
  _, tracer = invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
128
251
  InstanceMethod.new.say_default
129
252
  end
130
- expect(tracer.event_methods.to_a.map(&:defined_class)).to eq([ 'InstanceMethod' ])
131
- expect(tracer.event_methods.to_a.map(&:to_s)).to eq([ InstanceMethod.public_instance_method(:say_default).to_s ])
253
+ expect(tracer.event_methods.to_a.map(&:class_name)).to eq([ 'InstanceMethod' ])
254
+ expect(tracer.event_methods.to_a.map(&:name)).to eq([ InstanceMethod.public_instance_method(:say_default).name ])
132
255
  end
133
256
 
134
257
  it 'builds a class map of invoked methods' do
@@ -148,10 +271,6 @@ describe 'AppMap class Hooking', docker: false do
148
271
  :type: function
149
272
  :location: spec/fixtures/hook/instance_method.rb:8
150
273
  :static: false
151
- :source: |2
152
- def say_default
153
- 'default'
154
- end
155
274
  YAML
156
275
  end
157
276
 
@@ -744,8 +863,11 @@ describe 'AppMap class Hooking', docker: false do
744
863
  _, _, events = test_hook_behavior 'spec/fixtures/hook/compare.rb', nil do
745
864
  expect(Compare.compare('string', 'string')).to be_truthy
746
865
  end
866
+
747
867
  secure_compare_event = YAML.load(events).find { |evt| evt[:defined_class] == 'ActiveSupport::SecurityUtils' }
868
+ expect(secure_compare_event).to be_truthy
748
869
  secure_compare_event.delete(:lineno)
870
+ secure_compare_event.delete(:path)
749
871
 
750
872
  expect(Diffy::Diff.new(<<~YAML, secure_compare_event.to_yaml).to_s).to eq('')
751
873
  ---
@@ -753,7 +875,6 @@ describe 'AppMap class Hooking', docker: false do
753
875
  :event: :call
754
876
  :defined_class: ActiveSupport::SecurityUtils
755
877
  :method_id: secure_compare
756
- :path: lib/active_support/security_utils.rb
757
878
  :static: true
758
879
  :parameters:
759
880
  - :name: :a
@@ -837,7 +958,7 @@ describe 'AppMap class Hooking', docker: false do
837
958
  entry = cm[1][:children][0][:children][0][:children][0]
838
959
  # Sanity check, make sure we got the right one
839
960
  expect(entry[:name]).to eq('secure_compare')
840
- expect(entry[:labels]).to eq(%w[provider.secure_compare])
961
+ expect(entry[:labels]).to eq(%w[crypto.secure_compare])
841
962
  end
842
963
  end
843
964