appmap 0.34.0 → 0.35.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.
@@ -22,7 +22,7 @@ describe 'AppMap class Hooking', docker: false do
22
22
  while tracer.event?
23
23
  events << tracer.next_event.to_h
24
24
  end
25
- end.map(&AppMap::Util.method(:sanitize_event)).to_yaml
25
+ end.map(&AppMap::Util.method(:sanitize_event))
26
26
  end
27
27
 
28
28
  def invoke_test_file(file, setup: nil, &block)
@@ -50,7 +50,7 @@ describe 'AppMap class Hooking', docker: false do
50
50
  def test_hook_behavior(file, events_yaml, setup: nil, &block)
51
51
  config, tracer = invoke_test_file(file, setup: setup, &block)
52
52
 
53
- events = collect_events(tracer)
53
+ events = collect_events(tracer).to_yaml
54
54
 
55
55
  expect(Diffy::Diff.new(events_yaml, events).to_s).to eq('')
56
56
 
@@ -342,7 +342,7 @@ describe 'AppMap class Hooking', docker: false do
342
342
  :defined_class: SingletonMethod
343
343
  :method_id: added_method
344
344
  :path: spec/fixtures/hook/singleton_method.rb
345
- :lineno: 44
345
+ :lineno: 21
346
346
  :static: false
347
347
  :parameters: []
348
348
  :receiver:
@@ -350,10 +350,10 @@ describe 'AppMap class Hooking', docker: false do
350
350
  :value: Singleton Method fixture
351
351
  - :id: 2
352
352
  :event: :call
353
- :defined_class: AddMethod
353
+ :defined_class: SingletonMethod::AddMethod
354
354
  :method_id: _added_method
355
355
  :path: spec/fixtures/hook/singleton_method.rb
356
- :lineno: 50
356
+ :lineno: 27
357
357
  :static: false
358
358
  :parameters: []
359
359
  :receiver:
@@ -395,10 +395,44 @@ describe 'AppMap class Hooking', docker: false do
395
395
  load 'spec/fixtures/hook/singleton_method.rb'
396
396
  setup = -> { SingletonMethod.new_with_instance_method }
397
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
+
398
405
  expect(s.say_instance_defined).to eq('defined for an instance')
399
406
  end
400
407
  end
401
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
+
402
436
  it 'Reports exceptions' do
403
437
  events_yaml = <<~YAML
404
438
  ---
@@ -466,7 +500,7 @@ describe 'AppMap class Hooking', docker: false do
466
500
  :event: :call
467
501
  :defined_class: ActiveSupport::SecurityUtils
468
502
  :method_id: secure_compare
469
- :path: gems/activesupport-6.0.3.2/lib/active_support/security_utils.rb
503
+ :path: lib/active_support/security_utils.rb
470
504
  :lineno: 26
471
505
  :static: true
472
506
  :parameters:
@@ -564,7 +598,7 @@ describe 'AppMap class Hooking', docker: false do
564
598
  :children:
565
599
  - :name: secure_compare
566
600
  :type: function
567
- :location: gems/activesupport-6.0.3.2/lib/active_support/security_utils.rb:26
601
+ :location: lib/active_support/security_utils.rb:26
568
602
  :static: true
569
603
  :labels:
570
604
  - security
@@ -590,7 +624,7 @@ describe 'AppMap class Hooking', docker: false do
590
624
  config, tracer = invoke_test_file 'spec/fixtures/hook/compare.rb' do
591
625
  expect(Compare.compare('string', 'string')).to be_truthy
592
626
  end
593
- cm = AppMap::ClassMap.build_from_methods(config, tracer.event_methods)
627
+ cm = AppMap::Util.sanitize_paths(AppMap::ClassMap.build_from_methods(tracer.event_methods))
594
628
  entry = cm[1][:children][0][:children][0][:children][0]
595
629
  # Sanity check, make sure we got the right one
596
630
  expect(entry[:name]).to eq('secure_compare')
@@ -599,4 +633,47 @@ describe 'AppMap class Hooking', docker: false do
599
633
  expect(Diffy::Diff.new(classmap_yaml, cm.to_yaml).to_s).to eq('')
600
634
  end
601
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
670
+ end
671
+ end
672
+
673
+ it "preserves the arity of hooked methods" do
674
+ invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
675
+ expect(InstanceMethod.instance_method(:say_echo).arity).to be(1)
676
+ expect(InstanceMethod.new.method(:say_echo).arity).to be(1)
677
+ end
678
+ end
602
679
  end
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.34.0
4
+ version: 0.35.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: 2020-08-21 00:00:00.000000000 Z
11
+ date: 2020-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake-compiler
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: climate_control
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -248,16 +262,46 @@ dependencies:
248
262
  - - "~>"
249
263
  - !ruby/object:Gem::Version
250
264
  version: '4.0'
265
+ - !ruby/object:Gem::Dependency
266
+ name: timecop
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - ">="
277
+ - !ruby/object:Gem::Version
278
+ version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: hashie
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
251
293
  description:
252
294
  email:
253
295
  - kgilpin@gmail.com
254
296
  executables:
255
297
  - appmap
256
- extensions: []
298
+ extensions:
299
+ - ext/appmap/extconf.rb
257
300
  extra_rdoc_files: []
258
301
  files:
259
302
  - ".dockerignore"
260
303
  - ".gitignore"
304
+ - ".rbenv-gemsets"
261
305
  - ".rubocop.yml"
262
306
  - ".ruby-version"
263
307
  - ".travis.yml"
@@ -277,6 +321,8 @@ files:
277
321
  - examples/mock_webapp/lib/mock_webapp/request.rb
278
322
  - examples/mock_webapp/lib/mock_webapp/user.rb
279
323
  - exe/appmap
324
+ - ext/appmap/appmap.c
325
+ - ext/appmap/extconf.rb
280
326
  - lib/appmap.rb
281
327
  - lib/appmap/algorithm/prune_class_map.rb
282
328
  - lib/appmap/algorithm/stats.rb
@@ -292,7 +338,7 @@ files:
292
338
  - lib/appmap/middleware/remote_recording.rb
293
339
  - lib/appmap/minitest.rb
294
340
  - lib/appmap/open.rb
295
- - lib/appmap/rails/action_handler.rb
341
+ - lib/appmap/rails/request_handler.rb
296
342
  - lib/appmap/rails/sql_handler.rb
297
343
  - lib/appmap/railtie.rb
298
344
  - lib/appmap/record.rb
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'appmap/event'
4
-
5
- module AppMap
6
- module Rails
7
- module ActionHandler
8
- Context = Struct.new(:id, :start_time)
9
-
10
- module ContextKey
11
- def context_key
12
- "#{HTTPServerRequest.name}#call"
13
- end
14
- end
15
-
16
- class HTTPServerRequest
17
- include ContextKey
18
-
19
- class Call < AppMap::Event::MethodCall
20
- attr_accessor :payload
21
-
22
- def initialize(payload)
23
- super AppMap::Event.next_id_counter, :call, Thread.current.object_id
24
-
25
- self.payload = payload
26
- end
27
-
28
- def to_h
29
- super.tap do |h|
30
- h[:http_server_request] = {
31
- request_method: payload[:method],
32
- path_info: payload[:path]
33
- }
34
-
35
- params = payload[:params]
36
- h[:message] = params.keys.map do |key|
37
- val = params[key]
38
- {
39
- name: key,
40
- class: val.class.name,
41
- value: self.class.display_string(val),
42
- object_id: val.__id__
43
- }
44
- end
45
- end
46
- end
47
- end
48
-
49
- def call(_, started, finished, _, payload) # (name, started, finished, unique_id, payload)
50
- event = Call.new(payload)
51
- Thread.current[context_key] = Context.new(event.id, Time.now)
52
- AppMap.tracing.record_event(event)
53
- end
54
- end
55
-
56
- class HTTPServerResponse
57
- include ContextKey
58
-
59
- class Call < AppMap::Event::MethodReturnIgnoreValue
60
- attr_accessor :payload
61
-
62
- def initialize(payload, parent_id, elapsed)
63
- super AppMap::Event.next_id_counter, :return, Thread.current.object_id
64
-
65
- self.payload = payload
66
- self.parent_id = parent_id
67
- self.elapsed = elapsed
68
- end
69
-
70
- def to_h
71
- super.tap do |h|
72
- h[:http_server_response] = {
73
- status: payload[:status]
74
- }
75
- end
76
- end
77
- end
78
-
79
- def call(_, started, finished, _, payload) # (name, started, finished, unique_id, payload)
80
- return unless Thread.current[context_key]
81
-
82
- context = Thread.current[context_key]
83
- Thread.current[context_key] = nil
84
-
85
- event = Call.new(payload, context.id, Time.now - context.start_time)
86
- AppMap.tracing.record_event(event)
87
- end
88
- end
89
- end
90
- end
91
- end