appmap 0.35.1 → 0.38.1

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +1 -1
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +10 -0
  5. data/CHANGELOG.md +22 -0
  6. data/README.md +14 -8
  7. data/Rakefile +3 -2
  8. data/appmap.gemspec +2 -1
  9. data/appmap.yml +1 -7
  10. data/lib/appmap.rb +2 -2
  11. data/lib/appmap/class_map.rb +20 -6
  12. data/lib/appmap/config.rb +66 -22
  13. data/lib/appmap/event.rb +21 -6
  14. data/lib/appmap/hook/method.rb +18 -12
  15. data/lib/appmap/rails/request_handler.rb +8 -1
  16. data/lib/appmap/railtie.rb +1 -1
  17. data/lib/appmap/rspec.rb +1 -1
  18. data/lib/appmap/trace.rb +18 -7
  19. data/lib/appmap/version.rb +2 -2
  20. data/spec/abstract_controller4_base_spec.rb +27 -28
  21. data/spec/abstract_controller_base_spec.rb +73 -38
  22. data/spec/class_map_spec.rb +36 -0
  23. data/spec/fixtures/hook/exception_method.rb +44 -0
  24. data/spec/fixtures/hook/instance_method.rb +4 -0
  25. data/spec/fixtures/{rails_users_app → rails5_users_app}/.dockerignore +0 -0
  26. data/spec/fixtures/{rails_users_app → rails5_users_app}/.gitignore +0 -0
  27. data/spec/fixtures/{rails_users_app → rails5_users_app}/.rspec +0 -0
  28. data/{.ruby-version → spec/fixtures/rails5_users_app/.ruby-version} +0 -0
  29. data/spec/fixtures/{rails_users_app → rails5_users_app}/Dockerfile +0 -0
  30. data/spec/fixtures/{rails_users_app → rails5_users_app}/Dockerfile.pg +0 -0
  31. data/spec/fixtures/rails5_users_app/Gemfile +51 -0
  32. data/spec/fixtures/{rails_users_app → rails5_users_app}/Rakefile +0 -0
  33. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/controllers/api/users_controller.rb +0 -0
  34. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/controllers/application_controller.rb +0 -0
  35. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/controllers/concerns/.keep +0 -0
  36. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/controllers/health_controller.rb +0 -0
  37. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/controllers/users_controller.rb +0 -0
  38. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/models/activerecord/user.rb +0 -0
  39. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/models/concerns/.keep +0 -0
  40. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/models/sequel/user.rb +0 -0
  41. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/views/layouts/application.html.haml +0 -0
  42. data/spec/fixtures/{rails_users_app → rails5_users_app}/app/views/users/index.html.haml +0 -0
  43. data/spec/fixtures/rails5_users_app/appmap.yml +4 -0
  44. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/appmap +0 -0
  45. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/byebug +0 -0
  46. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/gli +0 -0
  47. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/htmldiff +0 -0
  48. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/ldiff +0 -0
  49. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/nokogiri +0 -0
  50. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/rackup +0 -0
  51. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/rails +0 -0
  52. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/rake +0 -0
  53. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/rspec +0 -0
  54. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/ruby-parse +0 -0
  55. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/ruby-rewrite +0 -0
  56. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/sequel +0 -0
  57. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/setup +0 -0
  58. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/sprockets +0 -0
  59. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/thor +0 -0
  60. data/spec/fixtures/{rails_users_app → rails5_users_app}/bin/update +0 -0
  61. data/spec/fixtures/{rails_users_app → rails5_users_app}/config.ru +0 -0
  62. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/application.rb +0 -0
  63. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/boot.rb +0 -0
  64. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/credentials.yml.enc +0 -0
  65. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/database.yml +0 -0
  66. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/environment.rb +0 -0
  67. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/environments/development.rb +0 -0
  68. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/environments/production.rb +0 -0
  69. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/environments/test.rb +0 -0
  70. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/application_controller_renderer.rb +0 -0
  71. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/backtrace_silencers.rb +0 -0
  72. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/cors.rb +0 -0
  73. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/filter_parameter_logging.rb +0 -0
  74. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/inflections.rb +0 -0
  75. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/mime_types.rb +0 -0
  76. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/record_button.rb +0 -0
  77. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/initializers/wrap_parameters.rb +0 -0
  78. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/locales/en.yml +0 -0
  79. data/spec/fixtures/{rails_users_app → rails5_users_app}/config/routes.rb +0 -0
  80. data/spec/fixtures/{rails_users_app → rails5_users_app}/create_app +0 -0
  81. data/spec/fixtures/{rails_users_app → rails5_users_app}/db/migrate/20190728211408_create_users.rb +0 -0
  82. data/spec/fixtures/{rails_users_app → rails5_users_app}/db/schema.rb +0 -0
  83. data/spec/fixtures/{rails_users_app → rails5_users_app}/docker-compose.yml +0 -0
  84. data/spec/fixtures/{rails_users_app → rails5_users_app}/features/api_users.feature +0 -0
  85. data/spec/fixtures/{rails_users_app → rails5_users_app}/features/support/env.rb +0 -0
  86. data/spec/fixtures/{rails_users_app → rails5_users_app}/features/support/hooks.rb +0 -0
  87. data/spec/fixtures/{rails_users_app → rails5_users_app}/features/support/steps.rb +0 -0
  88. data/spec/fixtures/{rails_users_app → rails5_users_app}/lib/tasks/.keep +0 -0
  89. data/spec/fixtures/{rails_users_app → rails5_users_app}/log/.keep +0 -0
  90. data/spec/fixtures/{rails_users_app → rails5_users_app}/public/robots.txt +0 -0
  91. data/spec/fixtures/{rails_users_app → rails5_users_app}/spec/controllers/users_controller_api_spec.rb +1 -1
  92. data/spec/fixtures/rails5_users_app/spec/controllers/users_controller_spec.rb +16 -0
  93. data/spec/fixtures/{rails_users_app → rails5_users_app}/spec/models/user_spec.rb +0 -0
  94. data/spec/fixtures/{rails_users_app → rails5_users_app}/spec/rails_helper.rb +0 -0
  95. data/spec/fixtures/{rails_users_app → rails5_users_app}/spec/spec_helper.rb +0 -0
  96. data/spec/fixtures/{rails_users_app → rails5_users_app}/users_app/.gitignore +0 -0
  97. data/spec/fixtures/rails6_users_app/.dockerignore +1 -0
  98. data/spec/fixtures/rails6_users_app/.gitignore +39 -0
  99. data/spec/fixtures/rails6_users_app/.rspec +1 -0
  100. data/spec/fixtures/{rails_users_app → rails6_users_app}/.ruby-version +0 -0
  101. data/spec/fixtures/rails6_users_app/Dockerfile +29 -0
  102. data/spec/fixtures/rails6_users_app/Dockerfile.pg +3 -0
  103. data/spec/fixtures/{rails_users_app → rails6_users_app}/Gemfile +1 -1
  104. data/spec/fixtures/rails6_users_app/Rakefile +6 -0
  105. data/spec/fixtures/rails6_users_app/app/controllers/api/users_controller.rb +27 -0
  106. data/spec/fixtures/rails6_users_app/app/controllers/application_controller.rb +2 -0
  107. data/spec/fixtures/rails6_users_app/app/controllers/concerns/.keep +0 -0
  108. data/spec/fixtures/rails6_users_app/app/controllers/health_controller.rb +5 -0
  109. data/spec/fixtures/rails6_users_app/app/controllers/users_controller.rb +5 -0
  110. data/spec/fixtures/rails6_users_app/app/models/activerecord/user.rb +18 -0
  111. data/spec/fixtures/rails6_users_app/app/models/concerns/.keep +0 -0
  112. data/spec/fixtures/rails6_users_app/app/models/sequel/user.rb +25 -0
  113. data/spec/fixtures/rails6_users_app/app/views/layouts/application.html.haml +7 -0
  114. data/spec/fixtures/rails6_users_app/app/views/users/index.html.haml +7 -0
  115. data/spec/fixtures/rails6_users_app/appmap.yml +5 -0
  116. data/spec/fixtures/rails6_users_app/bin/appmap +29 -0
  117. data/spec/fixtures/rails6_users_app/bin/byebug +29 -0
  118. data/spec/fixtures/rails6_users_app/bin/gli +29 -0
  119. data/spec/fixtures/rails6_users_app/bin/htmldiff +29 -0
  120. data/spec/fixtures/rails6_users_app/bin/ldiff +29 -0
  121. data/spec/fixtures/rails6_users_app/bin/nokogiri +29 -0
  122. data/spec/fixtures/rails6_users_app/bin/rackup +29 -0
  123. data/spec/fixtures/rails6_users_app/bin/rails +4 -0
  124. data/spec/fixtures/rails6_users_app/bin/rake +29 -0
  125. data/spec/fixtures/rails6_users_app/bin/rspec +29 -0
  126. data/spec/fixtures/rails6_users_app/bin/ruby-parse +29 -0
  127. data/spec/fixtures/rails6_users_app/bin/ruby-rewrite +29 -0
  128. data/spec/fixtures/rails6_users_app/bin/sequel +29 -0
  129. data/spec/fixtures/rails6_users_app/bin/setup +25 -0
  130. data/spec/fixtures/rails6_users_app/bin/sprockets +29 -0
  131. data/spec/fixtures/rails6_users_app/bin/thor +29 -0
  132. data/spec/fixtures/rails6_users_app/bin/update +25 -0
  133. data/spec/fixtures/rails6_users_app/config.ru +5 -0
  134. data/spec/fixtures/rails6_users_app/config/application.rb +51 -0
  135. data/spec/fixtures/rails6_users_app/config/boot.rb +3 -0
  136. data/spec/fixtures/rails6_users_app/config/credentials.yml.enc +1 -0
  137. data/spec/fixtures/rails6_users_app/config/database.yml +18 -0
  138. data/spec/fixtures/rails6_users_app/config/environment.rb +5 -0
  139. data/spec/fixtures/rails6_users_app/config/environments/development.rb +40 -0
  140. data/spec/fixtures/rails6_users_app/config/environments/production.rb +68 -0
  141. data/spec/fixtures/rails6_users_app/config/environments/test.rb +36 -0
  142. data/spec/fixtures/rails6_users_app/config/initializers/application_controller_renderer.rb +8 -0
  143. data/spec/fixtures/rails6_users_app/config/initializers/backtrace_silencers.rb +7 -0
  144. data/spec/fixtures/rails6_users_app/config/initializers/cors.rb +16 -0
  145. data/spec/fixtures/rails6_users_app/config/initializers/filter_parameter_logging.rb +4 -0
  146. data/spec/fixtures/rails6_users_app/config/initializers/inflections.rb +16 -0
  147. data/spec/fixtures/rails6_users_app/config/initializers/mime_types.rb +4 -0
  148. data/spec/fixtures/rails6_users_app/config/initializers/record_button.rb +3 -0
  149. data/spec/fixtures/rails6_users_app/config/initializers/wrap_parameters.rb +9 -0
  150. data/spec/fixtures/rails6_users_app/config/locales/en.yml +33 -0
  151. data/spec/fixtures/rails6_users_app/config/routes.rb +11 -0
  152. data/spec/fixtures/rails6_users_app/create_app +27 -0
  153. data/spec/fixtures/rails6_users_app/db/migrate/20190728211408_create_users.rb +9 -0
  154. data/spec/fixtures/rails6_users_app/db/schema.rb +23 -0
  155. data/spec/fixtures/rails6_users_app/docker-compose.yml +28 -0
  156. data/spec/fixtures/rails6_users_app/features/api_users.feature +13 -0
  157. data/spec/fixtures/rails6_users_app/features/support/env.rb +4 -0
  158. data/spec/fixtures/rails6_users_app/features/support/hooks.rb +11 -0
  159. data/spec/fixtures/rails6_users_app/features/support/steps.rb +18 -0
  160. data/spec/fixtures/rails6_users_app/lib/tasks/.keep +0 -0
  161. data/spec/fixtures/rails6_users_app/log/.keep +0 -0
  162. data/spec/fixtures/rails6_users_app/public/robots.txt +1 -0
  163. data/spec/fixtures/rails6_users_app/spec/controllers/users_controller_api_spec.rb +29 -0
  164. data/spec/fixtures/rails6_users_app/spec/controllers/users_controller_spec.rb +16 -0
  165. data/spec/fixtures/rails6_users_app/spec/models/user_spec.rb +39 -0
  166. data/spec/fixtures/rails6_users_app/spec/rails_helper.rb +66 -0
  167. data/spec/fixtures/rails6_users_app/spec/spec_helper.rb +96 -0
  168. data/spec/fixtures/rails6_users_app/users_app/.gitignore +20 -0
  169. data/spec/hook_spec.rb +225 -18
  170. data/spec/rails_spec_helper.rb +5 -5
  171. data/spec/railtie_spec.rb +31 -32
  172. data/spec/record_sql_rails4_pg_spec.rb +47 -48
  173. data/spec/record_sql_rails_pg_spec.rb +62 -63
  174. data/spec/remote_recording_spec.rb +90 -89
  175. data/spec/rspec_feature_metadata_spec.rb +17 -18
  176. data/test/expectations/openssl_test_key_sign1.json +55 -0
  177. data/test/expectations/openssl_test_key_sign2.json +58 -0
  178. data/test/fixtures/gem_test/Gemfile +6 -0
  179. data/test/fixtures/gem_test/appmap.yml +3 -0
  180. data/test/fixtures/gem_test/test/to_param_test.rb +14 -0
  181. data/test/gem_test.rb +34 -0
  182. data/test/minitest_test.rb +2 -2
  183. data/test/openssl_test.rb +10 -117
  184. metadata +173 -80
  185. data/spec/fixtures/rails_users_app/appmap.yml +0 -3
@@ -39,6 +39,7 @@ module AppMap
39
39
  end
40
40
 
41
41
  defined_class = @defined_class
42
+ hook_package = self.hook_package
42
43
  hook_method = self.hook_method
43
44
  before_hook = self.method(:before_hook)
44
45
  after_hook = self.method(:after_hook)
@@ -48,29 +49,34 @@ module AppMap
48
49
  hook_class.instance_eval do
49
50
  hook_method_def = Proc.new do |*args, &block|
50
51
  instance_method = hook_method.bind(self).to_proc
52
+ call_instance_method = -> { instance_method.call(*args, &block) }
51
53
 
52
54
  # We may not have gotten the class for the method during
53
55
  # initialization (e.g. for a singleton method on an embedded
54
56
  # struct), so make sure we have it now.
55
- defined_class,_ = Hook.qualify_method_name(hook_method) unless defined_class
57
+ defined_class, = Hook.qualify_method_name(hook_method) unless defined_class
56
58
 
57
- hook_disabled = Thread.current[HOOK_DISABLE_KEY]
58
- enabled = true if !hook_disabled && AppMap.tracing.enabled?
59
- return instance_method.call(*args, &block) unless enabled
59
+ reentrant = Thread.current[HOOK_DISABLE_KEY]
60
+ disabled_by_shallow_flag = \
61
+ -> { hook_package&.shallow? && AppMap.tracing.last_package_for_current_thread == hook_package }
60
62
 
61
- call_event, start_time = with_disabled_hook.() do
62
- before_hook.(self, defined_class, args)
63
+ enabled = true if AppMap.tracing.enabled? && !reentrant && !disabled_by_shallow_flag.call
64
+
65
+ return call_instance_method.call unless enabled
66
+
67
+ call_event, start_time = with_disabled_hook.call do
68
+ before_hook.call(self, defined_class, args)
63
69
  end
64
70
  return_value = nil
65
71
  exception = nil
66
72
  begin
67
- return_value = instance_method.(*args, &block)
73
+ return_value = call_instance_method.call
68
74
  rescue
69
75
  exception = $ERROR_INFO
70
76
  raise
71
77
  ensure
72
- with_disabled_hook.() do
73
- after_hook.(self, call_event, start_time, return_value, exception)
78
+ with_disabled_hook.call do
79
+ after_hook.call(self, call_event, start_time, return_value, exception)
74
80
  end
75
81
  end
76
82
  end
@@ -87,7 +93,7 @@ module AppMap
87
93
  [ call_event, TIME_NOW.call ]
88
94
  end
89
95
 
90
- def after_hook(receiver, call_event, start_time, return_value, exception)
96
+ def after_hook(_receiver, call_event, start_time, return_value, exception)
91
97
  require 'appmap/event'
92
98
  elapsed = TIME_NOW.call - start_time
93
99
  return_event = \
@@ -95,12 +101,12 @@ module AppMap
95
101
  AppMap.tracing.record_event return_event
96
102
  end
97
103
 
98
- def with_disabled_hook(&fn)
104
+ def with_disabled_hook(&function)
99
105
  # Don't record functions, such as to_s and inspect, that might be called
100
106
  # by the fn. Otherwise there can be a stack overflow.
101
107
  Thread.current[HOOK_DISABLE_KEY] = true
102
108
  begin
103
- fn.call
109
+ function.call
104
110
  ensure
105
111
  Thread.current[HOOK_DISABLE_KEY] = false
106
112
  end
@@ -14,7 +14,14 @@ module AppMap
14
14
 
15
15
  @request_method = request.request_method
16
16
  @path_info = request.path_info.split('?')[0]
17
- @params = ActionDispatch::Http::ParameterFilter.new(::Rails.application.config.filter_parameters).filter(request.params)
17
+ # ActionDispatch::Http::ParameterFilter is deprecated
18
+ parameter_filter_cls = \
19
+ if defined?(ActiveSupport::ParameterFilter)
20
+ ActiveSupport::ParameterFilter
21
+ else
22
+ ActionDispatch::Http::ParameterFilter
23
+ end
24
+ @params = parameter_filter_cls.new(::Rails.application.config.filter_parameters).filter(request.params)
18
25
  end
19
26
 
20
27
  def to_h
@@ -40,4 +40,4 @@ module AppMap
40
40
  end.call
41
41
  end
42
42
  end
43
- end
43
+ end unless ENV['APPMAP_INITIALIZE'] == 'false'
@@ -148,7 +148,7 @@ module AppMap
148
148
 
149
149
  AppMap::RSpec.add_event_methods @trace.event_methods
150
150
 
151
- class_map = AppMap.class_map(@trace.event_methods)
151
+ class_map = AppMap.class_map(@trace.event_methods, include_source: false)
152
152
 
153
153
  description = []
154
154
  scope = ScopeExample.new(example)
@@ -15,34 +15,38 @@ module AppMap
15
15
 
16
16
  class Tracing
17
17
  def initialize
18
- @tracing = []
18
+ @tracers = []
19
19
  end
20
20
 
21
21
  def empty?
22
- @tracing.empty?
22
+ @tracers.empty?
23
23
  end
24
24
 
25
25
  def trace(enable: true)
26
26
  Tracer.new.tap do |tracer|
27
- @tracing << tracer
27
+ @tracers << tracer
28
28
  tracer.enable if enable
29
29
  end
30
30
  end
31
31
 
32
32
  def enabled?
33
- @tracing.any?(&:enabled?)
33
+ @tracers.any?(&:enabled?)
34
+ end
35
+
36
+ def last_package_for_current_thread
37
+ @tracers.first&.last_package_for_current_thread
34
38
  end
35
39
 
36
40
  def record_event(event, package: nil, defined_class: nil, method: nil)
37
- @tracing.each do |tracer|
41
+ @tracers.each do |tracer|
38
42
  tracer.record_event(event, package: package, defined_class: defined_class, method: method)
39
43
  end
40
44
  end
41
45
 
42
46
  def delete(tracer)
43
- return unless @tracing.member?(tracer)
47
+ return unless @tracers.member?(tracer)
44
48
 
45
- @tracing.delete(tracer)
49
+ @tracers.delete(tracer)
46
50
  tracer.disable
47
51
  end
48
52
  end
@@ -52,6 +56,7 @@ module AppMap
52
56
  # Records the events which happen in a program.
53
57
  def initialize
54
58
  @events = []
59
+ @last_package_for_thread = {}
55
60
  @methods = Set.new
56
61
  @enabled = false
57
62
  end
@@ -75,11 +80,17 @@ module AppMap
75
80
  def record_event(event, package: nil, defined_class: nil, method: nil)
76
81
  return unless @enabled
77
82
 
83
+ @last_package_for_thread[Thread.current.object_id] = package if package
78
84
  @events << event
79
85
  @methods << Trace::ScopedMethod.new(package, defined_class, method, event.static) \
80
86
  if package && defined_class && method && (event.event == :call)
81
87
  end
82
88
 
89
+ # Gets the last package which was observed on the current thread.
90
+ def last_package_for_current_thread
91
+ @last_package_for_thread[Thread.current.object_id]
92
+ end
93
+
83
94
  # Gets a unique list of the methods that were invoked by the program.
84
95
  def event_methods
85
96
  @methods.to_a
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.35.1'
6
+ VERSION = '0.38.1'
7
7
 
8
- APPMAP_FORMAT_VERSION = '1.2'
8
+ APPMAP_FORMAT_VERSION = '1.3'
9
9
  end
@@ -1,52 +1,50 @@
1
1
  require 'rails_spec_helper'
2
2
 
3
3
  describe 'AbstractControllerBase' do
4
- before(:all) { @fixture_dir = 'spec/fixtures/rails4_users_app' }
5
- include_examples 'Rails app pg database'
6
-
7
- around(:each) do |example|
8
- FileUtils.rm_rf tmpdir
9
- FileUtils.mkdir_p tmpdir
10
- cmd = "docker-compose run --rm -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:8"
11
- run_cmd cmd, chdir: @fixture_dir
4
+ include_context 'Rails app pg database', 'spec/fixtures/rails4_users_app' do
5
+ around(:each) do |example|
6
+ FileUtils.rm_rf tmpdir
7
+ FileUtils.mkdir_p tmpdir
8
+ cmd = "docker-compose run --rm -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:8"
9
+ run_cmd cmd, chdir: fixture_dir
12
10
 
13
- example.run
14
- end
11
+ example.run
12
+ end
15
13
 
16
- let(:tmpdir) { 'tmp/spec/AbstractControllerBase' }
17
- let(:appmap_json) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json') }
14
+ let(:tmpdir) { 'tmp/spec/AbstractControllerBase' }
15
+ let(:appmap_json) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json') }
18
16
 
19
- describe 'testing with rspec' do
20
- it 'Message fields are recorded in the appmap' do
21
- expect(File).to exist(appmap_json)
22
- appmap = JSON.parse(File.read(appmap_json)).to_yaml
17
+ describe 'testing with rspec' do
18
+ it 'Message fields are recorded in the appmap' do
19
+ expect(File).to exist(appmap_json)
20
+ appmap = JSON.parse(File.read(appmap_json)).to_yaml
23
21
 
24
- expect(appmap).to include(<<-MESSAGE.strip)
22
+ expect(appmap).to include(<<-MESSAGE.strip)
25
23
  message:
26
24
  - name: login
27
25
  class: String
28
26
  value: alice
29
27
  object_id:
30
- MESSAGE
28
+ MESSAGE
31
29
 
32
- expect(appmap).to include(<<-MESSAGE.strip)
30
+ expect(appmap).to include(<<-MESSAGE.strip)
33
31
  - name: password
34
32
  class: String
35
33
  value: "[FILTERED]"
36
34
  object_id:
37
- MESSAGE
35
+ MESSAGE
38
36
 
39
- expect(appmap).to include(<<-SERVER_REQUEST.strip)
37
+ expect(appmap).to include(<<-SERVER_REQUEST.strip)
40
38
  http_server_request:
41
39
  request_method: POST
42
40
  path_info: "/api/users"
43
- SERVER_REQUEST
44
- end
45
- it 'Properly captures method parameters in the appmap' do
46
- expect(File).to exist(appmap_json)
47
- appmap = JSON.parse(File.read(appmap_json)).to_yaml
41
+ SERVER_REQUEST
42
+ end
43
+ it 'Properly captures method parameters in the appmap' do
44
+ expect(File).to exist(appmap_json)
45
+ appmap = JSON.parse(File.read(appmap_json)).to_yaml
48
46
 
49
- expect(appmap).to match(<<-CREATE_CALL.strip)
47
+ expect(appmap).to match(<<-CREATE_CALL.strip)
50
48
  event: call
51
49
  thread_id: .*
52
50
  defined_class: Api::UsersController
@@ -61,7 +59,8 @@ describe 'AbstractControllerBase' do
61
59
  value: '{"login"=>"alice"}'
62
60
  kind: req
63
61
  receiver:
64
- CREATE_CALL
62
+ CREATE_CALL
63
+ end
65
64
  end
66
65
  end
67
66
  end
@@ -1,63 +1,67 @@
1
1
  require 'rails_spec_helper'
2
2
 
3
3
  describe 'AbstractControllerBase' do
4
- before(:all) { @fixture_dir = 'spec/fixtures/rails_users_app' }
5
- include_context 'Rails app pg database'
4
+ shared_examples 'rails version' do |rails_major_version|
5
+ include_context 'Rails app pg database', "spec/fixtures/rails#{rails_major_version}_users_app" do
6
+ def run_spec(spec_name)
7
+ cmd = "docker-compose run --rm -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec #{spec_name}"
8
+ run_cmd cmd, chdir: fixture_dir
9
+ end
6
10
 
7
- around(:each) do |example|
8
- FileUtils.rm_rf tmpdir
9
- FileUtils.mkdir_p tmpdir
10
- cmd = "docker-compose run --rm -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:8"
11
- run_cmd cmd, chdir: @fixture_dir
11
+ before do
12
+ FileUtils.rm_rf tmpdir
13
+ FileUtils.mkdir_p tmpdir
14
+ run_spec spec_name
15
+ end
12
16
 
13
- example.run
14
- end
17
+ let(:tmpdir) { 'tmp/spec/AbstractControllerBase' }
15
18
 
16
- let(:tmpdir) { 'tmp/spec/AbstractControllerBase' }
17
- let(:appmap_json) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json') }
19
+ describe 'testing with rspec' do
20
+ let(:spec_name) { 'spec/controllers/users_controller_api_spec.rb:8' }
21
+ let(:appmap_json_file) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json') }
18
22
 
19
- describe 'testing with rspec' do
20
- it 'inventory file is printed' do
21
- expect(File).to exist(File.join(tmpdir, 'appmap/rspec/Inventory.appmap.json'))
22
- end
23
+ describe 'creating a user' do
24
+ it 'inventory file is printed' do
25
+ expect(File).to exist(File.join(tmpdir, 'appmap/rspec/Inventory.appmap.json'))
26
+ end
23
27
 
24
- it 'message fields are recorded in the appmap' do
25
- expect(File).to exist(appmap_json)
26
- appmap = JSON.parse(File.read(appmap_json)).to_yaml
28
+ it 'message fields are recorded in the appmap' do
29
+ expect(File).to exist(appmap_json_file)
30
+ appmap = JSON.parse(File.read(appmap_json_file)).to_yaml
27
31
 
28
- expect(appmap).to include(<<-MESSAGE.strip)
32
+ expect(appmap).to include(<<-MESSAGE.strip)
29
33
  message:
30
34
  - name: login
31
35
  class: String
32
36
  value: alice
33
37
  object_id:
34
- MESSAGE
38
+ MESSAGE
35
39
 
36
- expect(appmap).to include(<<-MESSAGE.strip)
40
+ expect(appmap).to include(<<-MESSAGE.strip)
37
41
  - name: password
38
42
  class: String
39
43
  value: "[FILTERED]"
40
44
  object_id:
41
- MESSAGE
45
+ MESSAGE
42
46
 
43
- expect(appmap).to include(<<-SERVER_REQUEST.strip)
47
+ expect(appmap).to include(<<-SERVER_REQUEST.strip)
44
48
  http_server_request:
45
49
  request_method: POST
46
50
  path_info: "/api/users"
47
- SERVER_REQUEST
51
+ SERVER_REQUEST
48
52
 
49
- expect(appmap).to include(<<-SERVER_RESPONSE.strip)
53
+ expect(appmap).to include(<<-SERVER_RESPONSE.strip)
50
54
  http_server_response:
51
55
  status: 201
52
56
  mime_type: application/json; charset=utf-8
53
- SERVER_RESPONSE
54
- end
57
+ SERVER_RESPONSE
58
+ end
55
59
 
56
- it 'properly captures method parameters in the appmap' do
57
- expect(File).to exist(appmap_json)
58
- appmap = JSON.parse(File.read(appmap_json)).to_yaml
60
+ it 'properly captures method parameters in the appmap' do
61
+ expect(File).to exist(appmap_json_file)
62
+ appmap = JSON.parse(File.read(appmap_json_file)).to_yaml
59
63
 
60
- expect(appmap).to match(<<-CREATE_CALL.strip)
64
+ expect(appmap).to match(<<-CREATE_CALL.strip)
61
65
  event: call
62
66
  thread_id: .*
63
67
  defined_class: Api::UsersController
@@ -72,14 +76,45 @@ describe 'AbstractControllerBase' do
72
76
  value: '{"login"=>"alice"}'
73
77
  kind: req
74
78
  receiver:
75
- CREATE_CALL
76
- end
79
+ CREATE_CALL
80
+ end
81
+
82
+ it 'returns a minimal event' do
83
+ expect(File).to exist(appmap_json_file)
84
+ appmap = JSON.parse(File.read(appmap_json_file))
85
+ event = appmap['events'].find { |event| event['event'] == 'return' && event['return_value'] }
86
+ expect(event.keys).to eq(%w[id event thread_id parent_id elapsed return_value])
87
+ end
88
+ end
89
+
90
+ describe 'listing users' do
91
+ let(:spec_name) { 'spec/controllers/users_controller_spec.rb:11' }
92
+ let(:appmap_json_file) { File.join(tmpdir, 'appmap/rspec/UsersController_GET_users_lists_the_users.appmap.json') }
93
+ it 'records and labels view rendering' do
94
+ expect(File).to exist(appmap_json_file)
95
+ appmap = JSON.parse(File.read(appmap_json_file)).to_yaml
77
96
 
78
- it 'returns a minimal event' do
79
- expect(File).to exist(appmap_json)
80
- appmap = JSON.parse(File.read(appmap_json))
81
- event = appmap['events'].find { |event| event['event'] == 'return' && event['return_value'] }
82
- expect(event.keys).to eq(%w[id event thread_id parent_id elapsed return_value])
97
+ expect(appmap).to match(<<-VIEW_CALL.strip)
98
+ event: call
99
+ thread_id: .*
100
+ defined_class: ActionView::Renderer
101
+ method_id: render
102
+ path: .*
103
+ lineno: .*
104
+ static: false
105
+ VIEW_CALL
106
+
107
+ expect(appmap).to match(<<-VIEW_LABEL.strip)
108
+ labels:
109
+ - view
110
+ VIEW_LABEL
111
+ end
112
+ end
113
+ end
83
114
  end
84
115
  end
116
+
117
+ %w[5 6].each do |version|
118
+ it_behaves_like 'rails version', version
119
+ end
85
120
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'AppMap::ClassMap' do
6
+ describe '.build_from_methods' do
7
+ it 'includes source code if available' do
8
+ map = AppMap.class_map([scoped_method(method(:test_method))])
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)
19
+ end
20
+
21
+ # test method comment
22
+ def test_method
23
+ 'test method body'
24
+ end
25
+
26
+ def scoped_method(method)
27
+ AppMap::Trace::ScopedMethod.new AppMap::Config::Package.new, method.receiver.class.name, method, false
28
+ end
29
+
30
+ def dig_map(map, depth)
31
+ return map if depth == 0
32
+
33
+ dig_map map[0][:children], depth - 1
34
+ end
35
+ end
36
+ end