appmap 0.63.0 → 0.66.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42f7035cf2ee0f8595c813470df56fd34e77e41c70a9303165272ba252ea0d6d
4
- data.tar.gz: 728224dd6897ae1a0aee4cf12f8253fb6081eb1420e1caad99623d46d7b88613
3
+ metadata.gz: 1eecc28364d2832ecd593baed1c12a82d11bcd7f48945bebb59acd1d1830c254
4
+ data.tar.gz: ae096b7623cf2c59d9978b7d72676b797e2f7276adf2296d864434bea2a33605
5
5
  SHA512:
6
- metadata.gz: d2775d730040fd7d2c7603c0700fd6698b97addfec2f6156ad9602b158b6a461a70c21c53647ef51afa9cbe47f22c06b4218c9684664b367145373eebb1c709c
7
- data.tar.gz: f69c9a3674311f75a9a0d418f42331655c5225cdc6b2d3fc100d76d45894cdd94bdbb48ad7f400512acf684808f7cf4de4bce31b07b63a994f4f372f504db880
6
+ metadata.gz: 29f8d31824e2faf890cb35e895d5d165d5f083238f3a89aac00c95b8ac00289ca9647eaa4dc01a5b197f68f511f270a0d8f4f3fd6b4470be1d63df4cbda9274e
7
+ data.tar.gz: b59fc7043f6eb31af9680cccb104fb1dfe7f6370275b28f3ee4e7edc1070e85fd9828c2d681458b6812bc2feba323bb18508628ecdaea175d2e9947f06f48cba
data/.travis.yml CHANGED
@@ -1,9 +1,9 @@
1
1
  language: ruby
2
2
 
3
3
  rbenv:
4
- - 2.5
5
4
  - 2.6
6
5
  - 2.7
6
+ - 3.0
7
7
 
8
8
  addons:
9
9
  apt:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ # [0.66.0](https://github.com/applandinc/appmap-ruby/compare/v0.65.1...v0.66.0) (2021-09-28)
2
+
3
+
4
+ ### Features
5
+
6
+ * Add option for explicit 'require' in function config ([1cf6c2a](https://github.com/applandinc/appmap-ruby/commit/1cf6c2aed8ee2d89c900f2959484b88b6fd3eb93))
7
+ * Builtin code such as Ruby Logger can be hooked via appmap.yml ([779c9e5](https://github.com/applandinc/appmap-ruby/commit/779c9e5e4177d58ea7b63e663e7c5a0810a78c60))
8
+
9
+ ## [0.65.1](https://github.com/applandinc/appmap-ruby/compare/v0.65.0...v0.65.1) (2021-09-16)
10
+
11
+
12
+ ### Performance Improvements
13
+
14
+ * Cache method metadata ([d11e0f3](https://github.com/applandinc/appmap-ruby/commit/d11e0f3361057b7cada204656ca833c12bb704c1))
15
+ * Don't scan the backtrace on every SQL query ([9bb7457](https://github.com/applandinc/appmap-ruby/commit/9bb74576d24f7954a388f09f33e69ae9d11a4188))
16
+
17
+ # [0.65.0](https://github.com/applandinc/appmap-ruby/compare/v0.64.0...v0.65.0) (2021-09-14)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * Require fileutils as needed ([790c3a8](https://github.com/applandinc/appmap-ruby/commit/790c3a88b0e69581e0e4f73b7a92f46448b3cdd8))
23
+
24
+
25
+ ### Features
26
+
27
+ * Add support for Ruby 3.0, and drop Ruby 2.5 ([eba14e1](https://github.com/applandinc/appmap-ruby/commit/eba14e1669bdf50dc51ce8623c5d586edfdb1a2f))
28
+
29
+ # [0.64.0](https://github.com/applandinc/appmap-ruby/compare/v0.63.0...v0.64.0) (2021-08-24)
30
+
31
+
32
+ ### Features
33
+
34
+ * Show config file name in validation messages ([95520f8](https://github.com/applandinc/appmap-ruby/commit/95520f83a2b27fae6a3d5751cc1a4a1180c2dc25))
35
+
1
36
  # [0.63.0](https://github.com/applandinc/appmap-ruby/compare/v0.62.1...v0.63.0) (2021-08-24)
2
37
 
3
38
 
data/README.md CHANGED
@@ -117,11 +117,11 @@ root@6fab5f89125f:/src/app# bundle
117
117
  ```
118
118
 
119
119
  At this point, the bundle is built with the `appmap` gem located in `/src/appmap`, which is volume-mounted from the host.
120
- So you can edit the fixture code and the appmap code and run test commands such as `rspec` and `cucumber` in the container.
120
+ So you can edit the fixture code and the appmap code and run test commands such as `rspec` in the container.
121
121
  For example:
122
122
 
123
123
  ```sh-session
124
- root@6fab5f89125f:/src/app# bundle exec rspec
124
+ root@6fab5f89125f:/src/app# APPMAP=true bundle exec rspec
125
125
  Configuring AppMap from path appmap.yml
126
126
  ....
127
127
 
data/Rakefile CHANGED
@@ -28,7 +28,7 @@ namespace 'gem' do
28
28
  end
29
29
  end
30
30
 
31
- RUBY_VERSIONS=%w[2.5 2.6 2.7].select do |version|
31
+ RUBY_VERSIONS=%w[2.6 2.7 3.0].select do |version|
32
32
  travis_ruby_version = ENV['TRAVIS_RUBY_VERSION']
33
33
  next true unless travis_ruby_version
34
34
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'yaml'
4
5
  require 'appmap/service/guesser'
5
6
 
6
7
  module AppMap
data/lib/appmap/config.rb CHANGED
@@ -117,13 +117,15 @@ module AppMap
117
117
  # entry in appmap.yml. When the Config is initialized, each Function is converted into
118
118
  # a Package and TargetMethods. It's called a Function rather than a Method, because Function
119
119
  # is the AppMap terminology.
120
- Function = Struct.new(:package, :cls, :labels, :function_names) do # :nodoc:
120
+ Function = Struct.new(:package, :cls, :labels, :function_names, :builtin, :package_name) do # :nodoc:
121
121
  def to_h
122
122
  {
123
123
  package: package,
124
+ package_name: package_name,
124
125
  class: cls,
125
126
  labels: labels,
126
- functions: function_names.map(&:to_sym)
127
+ functions: function_names.map(&:to_sym),
128
+ builtin: builtin
127
129
  }.compact
128
130
  end
129
131
  end
@@ -244,7 +246,7 @@ module AppMap
244
246
  @depends_config = depends_config
245
247
  @hook_paths = Set.new(packages.map(&:path))
246
248
  @exclude = exclude
247
- @builtin_hooks = BUILTIN_HOOKS
249
+ @builtin_hooks = BUILTIN_HOOKS.dup
248
250
  @functions = functions
249
251
 
250
252
  @hooked_methods = METHOD_HOOKS.each_with_object(Hash.new { |h,k| h[k] = [] }) do |cls_target_methods, hooked_methods|
@@ -254,7 +256,15 @@ module AppMap
254
256
  functions.each do |func|
255
257
  package_options = {}
256
258
  package_options[:labels] = func.labels if func.labels
257
- @hooked_methods[func.cls] << TargetMethods.new(func.function_names, Package.build_from_path(func.package, package_options))
259
+ package_options[:package_name] = func.package_name
260
+ package_options[:package_name] ||= func.package if func.builtin
261
+ hook = TargetMethods.new(func.function_names, Package.build_from_path(func.package, **package_options))
262
+ if func.builtin
263
+ @builtin_hooks[func.cls] ||= []
264
+ @builtin_hooks[func.cls] << hook
265
+ else
266
+ @hooked_methods[func.cls] << hook
267
+ end
258
268
  end
259
269
 
260
270
  @hooked_methods.each_value do |hooks|
@@ -300,6 +310,7 @@ module AppMap
300
310
  MISSING_FILE_MSG
301
311
  {}
302
312
  end
313
+
303
314
  load(config_data).tap do |config|
304
315
  config_yaml = {
305
316
  'name' => config.name,
@@ -324,15 +335,22 @@ module AppMap
324
335
 
325
336
  if config_data['functions']
326
337
  config_params[:functions] = config_data['functions'].map do |function_data|
327
- package = function_data['package']
328
- cls = function_data['class']
329
- functions = function_data['function'] || function_data['functions']
330
- raise %q(AppMap config 'function' element should specify 'package', 'class' and 'function' or 'functions') unless package && cls && functions
338
+ function_name = function_data['name']
339
+ package, cls, functions = []
340
+ if function_name
341
+ package, cls, _, function = Util.parse_function_name(function_name)
342
+ functions = Array(function)
343
+ else
344
+ package = function_data['package']
345
+ cls = function_data['class']
346
+ functions = function_data['function'] || function_data['functions']
347
+ raise %q(AppMap config 'function' element should specify 'package', 'class' and 'function' or 'functions') unless package && cls && functions
348
+ end
331
349
 
332
350
  functions = Array(functions).map(&:to_sym)
333
351
  labels = function_data['label'] || function_data['labels']
334
352
  labels = Array(labels).map(&:to_s) if labels
335
- Function.new(package, cls, labels, functions)
353
+ Function.new(package, cls, labels, functions, function_data['builtin'], function_data['require'])
336
354
  end
337
355
  end
338
356
 
@@ -367,7 +385,7 @@ module AppMap
367
385
  config_params[:depends_config] = depends_config
368
386
  end
369
387
 
370
- Config.new name, config_params
388
+ Config.new name, **config_params
371
389
  end
372
390
  end
373
391
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'appmap/util'
4
+ require 'fileutils'
4
5
 
5
6
  module AppMap
6
7
  module Cucumber
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module AppMap
2
4
  module Depends
3
5
  module Util
data/lib/appmap/event.rb CHANGED
@@ -53,7 +53,7 @@ module AppMap
53
53
  @times[best_class_name(value)] += elapsed
54
54
  end
55
55
 
56
- encode_dislay_string(value_string)
56
+ encode_display_string(value_string)
57
57
  end
58
58
 
59
59
  def object_properties(hash_like)
@@ -77,7 +77,7 @@ module AppMap
77
77
  value_cls.name
78
78
  end
79
79
 
80
- def encode_dislay_string(value)
80
+ def encode_display_string(value)
81
81
  (value||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
82
82
  end
83
83
 
@@ -138,22 +138,46 @@ module AppMap
138
138
  class MethodCall < MethodEvent
139
139
  attr_accessor :defined_class, :method_id, :path, :lineno, :parameters, :receiver, :static
140
140
 
141
+ MethodMetadata = Struct.new(:defined_class, :method_id, :path, :lineno, :static)
142
+
143
+ @@method_metadata = {}
144
+
141
145
  class << self
146
+ private
147
+
148
+ def method_metadata(defined_class, method, receiver)
149
+ result = @@method_metadata[method]
150
+ return result if result
151
+
152
+ result = MethodMetadata.new
153
+ result.static = receiver.is_a?(Module)
154
+ result.defined_class = defined_class
155
+ result.method_id = method.name.to_s
156
+ if method.source_location
157
+ path = method.source_location[0]
158
+ path = path[Dir.pwd.length + 1..-1] if path.index(Dir.pwd) == 0
159
+ result.path = path
160
+ result.lineno = method.source_location[1]
161
+ else
162
+ result.path = [ defined_class, result.static ? '.' : '#', method.name ].join
163
+ end
164
+ @@method_metadata[method] = result
165
+ end
166
+
167
+ public
168
+
142
169
  def build_from_invocation(defined_class, method, receiver, arguments, event: MethodCall.new)
143
170
  event ||= MethodCall.new
144
171
  defined_class ||= 'Class'
172
+
145
173
  event.tap do
146
- static = receiver.is_a?(Module)
147
- event.defined_class = defined_class
148
- event.method_id = method.name.to_s
149
- if method.source_location
150
- path = method.source_location[0]
151
- path = path[Dir.pwd.length + 1..-1] if path.index(Dir.pwd) == 0
152
- event.path = path
153
- event.lineno = method.source_location[1]
154
- else
155
- event.path = [ defined_class, static ? '.' : '#', method.name ].join
156
- end
174
+ metadata = method_metadata(defined_class, method, receiver)
175
+
176
+ event.defined_class = metadata.defined_class
177
+ event.method_id = metadata.method_id
178
+ event.path = metadata.path
179
+ event.lineno = metadata.lineno
180
+ event.static = metadata.static
157
181
 
158
182
  # Check if the method has key parameters. If there are any they'll always be last.
159
183
  # If yes, then extract it from arguments.
@@ -186,7 +210,7 @@ module AppMap
186
210
  object_id: receiver.__id__,
187
211
  value: display_string(receiver)
188
212
  }
189
- event.static = static
213
+
190
214
  MethodEvent.build_from_invocation(:call, event: event)
191
215
  end
192
216
  end
@@ -109,34 +109,6 @@ module AppMap
109
109
  begin
110
110
  sql = payload[:sql].strip
111
111
 
112
- # Detect whether a function call within a specified filename is present in the call stack.
113
- find_in_backtrace = lambda do |file_name, function_name = nil|
114
- Thread.current.backtrace.find do |line|
115
- tokens = line.split(':')
116
- matches_file = tokens.find { |t| t.rindex(file_name) == (t.length - file_name.length) }
117
- matches_function = function_name.nil? || tokens.find { |t| t == "in `#{function_name}'" }
118
- matches_file && matches_function
119
- end
120
- end
121
-
122
- # Ignore SQL calls which are made while establishing a new connection.
123
- #
124
- # Example:
125
- # /path/to/ruby/2.6.0/gems/sequel-5.20.0/lib/sequel/connection_pool.rb:122:in `make_new'
126
- return if find_in_backtrace.call('lib/sequel/connection_pool.rb', 'make_new')
127
- # lib/active_record/connection_adapters/abstract/connection_pool.rb:811:in `new_connection'
128
- return if find_in_backtrace.call('lib/active_record/connection_adapters/abstract/connection_pool.rb', 'new_connection')
129
-
130
- # Ignore SQL calls which are made while inspecting the DB schema.
131
- #
132
- # Example:
133
- # /path/to/ruby/2.6.0/gems/sequel-5.20.0/lib/sequel/model/base.rb:812:in `get_db_schema'
134
- return if find_in_backtrace.call('lib/sequel/model/base.rb', 'get_db_schema')
135
- # /usr/local/bundle/gems/activerecord-5.2.3/lib/active_record/model_schema.rb:466:in `load_schema!'
136
- return if find_in_backtrace.call('lib/active_record/model_schema.rb', 'load_schema!')
137
- return if find_in_backtrace.call('lib/active_model/attribute_methods.rb', 'define_attribute_methods')
138
- return if find_in_backtrace.call('lib/active_record/connection_adapters/schema_cache.rb')
139
-
140
112
  SQLExaminer.examine payload, sql: sql
141
113
 
142
114
  call = SQLCall.new(payload)
data/lib/appmap/hook.rb CHANGED
@@ -89,7 +89,7 @@ module AppMap
89
89
 
90
90
  config.builtin_hooks.each do |class_name, hooks|
91
91
  Array(hooks).each do |hook|
92
- require hook.package.package_name if hook.package.package_name
92
+ require hook.package.package_name if hook.package.package_name && hook.package.package_name != 'ruby'
93
93
  Array(hook.method_names).each do |method_name|
94
94
  method_name = method_name.to_sym
95
95
  base_cls = class_from_string.(class_name)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'appmap/util'
4
+ require 'fileutils'
4
5
  require 'active_support'
5
6
  require 'active_support/core_ext'
6
7
 
data/lib/appmap/rspec.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'appmap/util'
4
4
  require 'set'
5
+ require 'fileutils'
5
6
 
6
7
  module AppMap
7
8
  # Integration of AppMap with RSpec. When enabled with APPMAP=true, the AppMap tracer will
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'appmap/service/validator/violation'
4
+ require 'yaml'
4
5
 
5
6
  module AppMap
6
7
  module Service
@@ -39,7 +40,7 @@ module AppMap
39
40
  rescue Psych::SyntaxError => e
40
41
  @violations << Violation.error(
41
42
  filename: @config_file,
42
- message: 'AppMap configuration is not valid YAML',
43
+ message: "AppMap configuration #{@config_file} is not valid YAML",
43
44
  detailed_message: e.message
44
45
  )
45
46
  nil
@@ -52,7 +53,7 @@ module AppMap
52
53
  rescue StandardError => e
53
54
  @violations << Violation.error(
54
55
  filename: @config_file,
55
- message: 'AppMap configuration could not be loaded',
56
+ message: "AppMap configuration #{@config_file} could not be loaded",
56
57
  detailed_message: e.message
57
58
  )
58
59
  nil
@@ -62,7 +63,7 @@ module AppMap
62
63
  unless present?
63
64
  @violations << Violation.error(
64
65
  filename: @config_file,
65
- message: 'AppMap configuration file does not exist'
66
+ message: "AppMap configuration #{@config_file} file does not exist"
66
67
  )
67
68
  end
68
69
  end
@@ -76,7 +77,10 @@ module AppMap
76
77
  end
77
78
 
78
79
  def validate_ruby_version
79
- unless RUBY_VERSION =~ AppMap::SUPPORTED_RUBY_VERSIONS_REGEX
80
+ major, minor, _ = RUBY_VERSION.split('.')
81
+ version = [ major, minor ].join('.')
82
+
83
+ unless AppMap::SUPPORTED_RUBY_VERSIONS.member?(version)
80
84
  @violations << Violation.error(
81
85
  message: "AppMap does not support Ruby #{RUBY_VERSION}. " \
82
86
  "Supported versions are: #{AppMap::SUPPORTED_RUBY_VERSIONS.join(', ')}."
@@ -1,5 +1,6 @@
1
1
  require 'rake'
2
2
  require 'yaml'
3
+ require 'fileutils'
3
4
  require 'appmap/node_cli'
4
5
  require 'appmap/swagger/markdown_descriptions'
5
6
  require 'appmap/swagger/stable'
data/lib/appmap/util.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler'
4
+ require 'fileutils'
4
5
 
5
6
  module AppMap
6
7
  module Util
@@ -20,6 +21,16 @@ module AppMap
20
21
  WHITE = "\e[37m"
21
22
 
22
23
  class << self
24
+ def parse_function_name(name)
25
+ package_tokens = name.split('/')
26
+
27
+ class_and_name = package_tokens.pop
28
+ class_name, function_name, static = class_and_name.include?('.') ? class_and_name.split('.', 2) + [ true ] : class_and_name.split('#', 2) + [ false ]
29
+
30
+ raise "Malformed fully-qualified function name #{name}" unless function_name
31
+ [ package_tokens.empty? ? 'ruby' : package_tokens.join('/'), class_name, static, function_name ]
32
+ end
33
+
23
34
  # scenario_filename builds a suitable file name from a scenario name.
24
35
  # Special characters are removed, and the file name is truncated to fit within
25
36
  # shell limitations.
@@ -130,7 +141,6 @@ module AppMap
130
141
 
131
142
  # Atomically writes AppMap data to +filename+.
132
143
  def write_appmap(filename, appmap)
133
- require 'fileutils'
134
144
  require 'tmpdir'
135
145
 
136
146
  # This is what Ruby Tempfile does; but we don't want the file to be unlinked.
@@ -3,12 +3,11 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.63.0'
6
+ VERSION = '0.66.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.5.1'
9
9
 
10
- SUPPORTED_RUBY_VERSIONS_REGEX = /^2\.[567]\./.freeze
11
- SUPPORTED_RUBY_VERSIONS = %w[2.5 2.6 2.7].freeze
10
+ SUPPORTED_RUBY_VERSIONS = %w[2.6 2.7 3.0].freeze
12
11
 
13
12
  DEFAULT_APPMAP_DIR = 'tmp/appmap'.freeze
14
13
  DEFAULT_CONFIG_FILE_PATH = 'appmap.yml'.freeze
data/spec/config_spec.rb CHANGED
@@ -55,6 +55,34 @@ describe AppMap::Config, docker: false do
55
55
  expect(config.to_h.deep_stringify_keys!).to eq(config_expectation)
56
56
  end
57
57
 
58
+ it 'interprets a function in canonical name format' do
59
+ config_data = {
60
+ name: 'test',
61
+ packages: [],
62
+ functions: [
63
+ {
64
+ name: 'pkg/cls#fn',
65
+ }
66
+ ]
67
+ }.deep_stringify_keys!
68
+ config = AppMap::Config.load(config_data)
69
+
70
+ config_expectation = {
71
+ exclude: [],
72
+ name: 'test',
73
+ packages: [],
74
+ functions: [
75
+ {
76
+ package: 'pkg',
77
+ class: 'cls',
78
+ functions: [ :fn ],
79
+ }
80
+ ]
81
+ }.deep_stringify_keys!
82
+
83
+ expect(config.to_h.deep_stringify_keys!).to eq(config_expectation)
84
+ end
85
+
58
86
  context do
59
87
  let(:warnings) { @warnings ||= [] }
60
88
  let(:warning) { warnings.join }
@@ -55,7 +55,7 @@ describe 'Depends API' do
55
55
  describe '.inspect_test_files' do
56
56
  it 'reports metadata, added, removed, changed, failed' do
57
57
  test_report = api.inspect_test_files(appmap_dir: DEPENDS_TEST_DIR, test_file_patterns: %w[spec/fixtures/depends/spec/*_spec.rb])
58
- expect(test_report.metadata_files).to eq(%w[spec/fixtures/depends/user_page_scenario/metadata.json spec/fixtures/depends/revoke_api_key/metadata.json])
58
+ expect(test_report.metadata_files.sort).to eq(%w[spec/fixtures/depends/revoke_api_key/metadata.json spec/fixtures/depends/user_page_scenario/metadata.json])
59
59
  expect(test_report.added).to be_empty
60
60
  expect(test_report.removed).to be_empty
61
61
  expect(test_report.changed).to be_empty
@@ -5,3 +5,7 @@ packages:
5
5
  - path: app/controllers
6
6
  labels: [ mvc.controller ]
7
7
  - gem: sequel
8
+ functions:
9
+ - name: logger/Logger::LogDevice#write
10
+ builtin: true
11
+ label: log
@@ -7,7 +7,7 @@ gem 'haml-rails'
7
7
 
8
8
  gem 'activerecord', require: false
9
9
  gem 'pg'
10
- gem 'sequel', '= 5.20.0', require: false
10
+ gem 'sequel', '>= 5.43.0', require: false
11
11
  gem 'sequel-rails', require: false
12
12
  gem 'sequel_secure_password', require: false
13
13
 
@@ -5,6 +5,10 @@ packages:
5
5
  - path: app/controllers
6
6
  labels: [ mvc.controller ]
7
7
  - gem: sequel
8
+ functions:
9
+ - name: logger/Logger::LogDevice#write
10
+ builtin: true
11
+ label: log
8
12
  swagger:
9
13
  project_version: 1.1.0
10
14
  output_dir: tmp/swagger
@@ -15,7 +15,7 @@ services:
15
15
  dockerfile: Dockerfile
16
16
  image: rails6-app:${RUBY_VERSION}
17
17
  command:
18
- [ "./bin/rails", "server", "-b", "0.0.0.0", "webrick" ]
18
+ [ "./bin/rails", "server", "-b", "0.0.0.0", "-u", "webrick" ]
19
19
  environment:
20
20
  RAILS_ENV:
21
21
  ORM_MODULE:
data/spec/hook_spec.rb CHANGED
@@ -987,10 +987,12 @@ describe 'AppMap class Hooking', docker: false do
987
987
  end
988
988
 
989
989
  describe 'kwargs handling' do
990
- # https://github.com/applandinc/appmap-ruby/issues/153
991
- it 'empty hash for **kwrest can be proxied as a regular function argument', github_issue: 153 do
992
- invoke_test_file 'spec/fixtures/hook/kwargs.rb' do
993
- expect(Kwargs.has_kwrest_calls_no_kwargs(nil, {})).to eq({})
990
+ if ruby_2?
991
+ # https://github.com/applandinc/appmap-ruby/issues/153
992
+ it 'empty hash for **kwrest can be proxied as a regular function argument', github_issue: 153 do
993
+ invoke_test_file 'spec/fixtures/hook/kwargs.rb' do
994
+ expect(Kwargs.has_kwrest_calls_no_kwargs(nil, {})).to eq({})
995
+ end
994
996
  end
995
997
  end
996
998
  end
@@ -1,7 +1,14 @@
1
1
  require 'rails_spec_helper'
2
2
 
3
+ def default_rails_versions
4
+ ruby_2? ? [ 5, 6 ] : [ 6 ]
5
+ end
6
+
7
+ # Rails5 doesn't work with Ruby 3.x
8
+ RailsVersions = ENV['RAILS_VERSIONS'] || default_rails_versions
9
+
3
10
  describe 'Rails' do
4
- %w[5 6].each do |rails_major_version| # rubocop:disable Metrics/BlockLength
11
+ RailsVersions.each do |rails_major_version| # rubocop:disable Metrics/BlockLength
5
12
  context "#{rails_major_version}" do
6
13
  include_context 'Rails app pg database', "spec/fixtures/rails#{rails_major_version}_users_app" unless use_existing_data?
7
14
  include_context 'rails integration test setup'
@@ -88,6 +95,15 @@ describe 'Rails' do
88
95
  )
89
96
  end
90
97
 
98
+ it 'captures log events' do
99
+ expect(events).to include hash_including(
100
+ 'event' => 'call',
101
+ 'defined_class' => 'Logger::LogDevice',
102
+ 'method_id' => 'write',
103
+ 'static' => false
104
+ )
105
+ end
106
+
91
107
  context 'with an object-style message' do
92
108
  let(:appmap_json_file) { 'Api_UsersController_POST_api_users_with_required_parameters_with_object-style_parameters_creates_a_user.appmap.json' }
93
109
 
@@ -239,7 +255,7 @@ describe 'Rails' do
239
255
  end
240
256
 
241
257
  describe 'with default appmap.yml' do
242
- include_context 'Rails app pg database', "spec/fixtures/rails5_users_app" unless use_existing_data?
258
+ include_context 'Rails app pg database', "spec/fixtures/rails6_users_app" unless use_existing_data?
243
259
  include_context 'rails integration test setup'
244
260
 
245
261
  def run_spec(spec_name)
data/spec/railtie_spec.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rails_spec_helper'
2
2
 
3
3
  describe 'AppMap tracer via Railtie' do
4
- include_context 'Rails app pg database', 'spec/fixtures/rails5_users_app' do
4
+ include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
5
5
  let(:env) { {} }
6
6
 
7
7
  let(:cmd) { %(docker-compose run --rm -e RAILS_ENV=development -e APPMAP app ./bin/rails r "puts AppMap.instance_variable_get('@configuration').nil?") }
@@ -10,13 +10,13 @@ describe 'AppMap tracer via Railtie' do
10
10
  Open3.capture3(env, cmd, chdir: fixture_dir).tap do |result|
11
11
  unless result[2] == 0
12
12
  warn <<~STDERR
13
- Failed to run rails5_users_app container
13
+ Failed to run rails6_users_app container
14
14
  <<< Output:
15
15
  #{result[0]}
16
16
  #{result[1]}
17
17
  >>> End of output
18
18
  STDERR
19
- raise 'Failed to run rails5_users_app container'
19
+ raise 'Failed to run rails6_users_app container'
20
20
  end
21
21
  end
22
22
  end
@@ -1,7 +1,7 @@
1
1
  require 'rails_spec_helper'
2
2
 
3
3
  describe 'SQL events' do
4
- include_context 'Rails app pg database', 'spec/fixtures/rails5_users_app' do
4
+ include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
5
5
  around(:each) do |example|
6
6
  FileUtils.rm_rf tmpdir
7
7
  FileUtils.mkdir_p tmpdir
@@ -3,9 +3,9 @@ require 'net/http'
3
3
  require 'socket'
4
4
 
5
5
  describe 'remote recording', :order => :defined do
6
- include_context 'Rails app pg database', 'spec/fixtures/rails5_users_app' do
6
+ include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
7
7
  before(:all) do
8
- fixture_dir = 'spec/fixtures/rails5_users_app'
8
+ fixture_dir = 'spec/fixtures/rails6_users_app'
9
9
  start_cmd = 'docker-compose up -d app'
10
10
  run_cmd({ 'ORM_MODULE' => 'sequel', 'APPMAP' => 'true' }, start_cmd, chdir: fixture_dir)
11
11
  Dir.chdir fixture_dir do
@@ -44,7 +44,7 @@ describe 'remote recording', :order => :defined do
44
44
  end
45
45
 
46
46
  after(:all) do
47
- fixture_dir = 'spec/fixtures/rails5_users_app'
47
+ fixture_dir = 'spec/fixtures/rails6_users_app'
48
48
  run_cmd 'docker-compose rm -fs app', chdir: fixture_dir
49
49
  end
50
50
 
data/spec/spec_helper.rb CHANGED
@@ -21,6 +21,10 @@ def use_existing_data?
21
21
  ENV['USE_EXISTING_DATA'] == 'true'
22
22
  end
23
23
 
24
+ def ruby_2?
25
+ RUBY_VERSION.split('.')[0].to_i == 2
26
+ end
27
+
24
28
  shared_context 'collect events' do
25
29
  def collect_events(tracer)
26
30
  [].tap do |events|
@@ -30,7 +30,7 @@ class AgentSetupValidateTest < Minitest::Test
30
30
  {
31
31
  level: :error,
32
32
  filename: NON_EXISTING_CONFIG_FILENAME,
33
- message: 'AppMap configuration file does not exist'
33
+ message: "AppMap configuration #{NON_EXISTING_CONFIG_FILENAME} file does not exist"
34
34
  }
35
35
  ])
36
36
  assert_equal expected, output.strip
@@ -47,7 +47,7 @@ class AgentSetupValidateTest < Minitest::Test
47
47
  {
48
48
  level: :error,
49
49
  filename: INVALID_YAML_CONFIG_FILENAME,
50
- message: 'AppMap configuration is not valid YAML',
50
+ message: "AppMap configuration #{INVALID_YAML_CONFIG_FILENAME} is not valid YAML",
51
51
  detailed_message: "(#{INVALID_YAML_CONFIG_FILENAME}): " \
52
52
  'did not find expected key while parsing a block mapping at line 1 column 1'
53
53
  }
@@ -66,7 +66,7 @@ class AgentSetupValidateTest < Minitest::Test
66
66
  {
67
67
  level: :error,
68
68
  filename: INVALID_CONFIG_FILENAME,
69
- message: 'AppMap configuration could not be loaded',
69
+ message: "AppMap configuration #{INVALID_CONFIG_FILENAME} could not be loaded",
70
70
  detailed_message: "no implicit conversion of String into Integer"
71
71
  }
72
72
  ])
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.63.0
4
+ version: 0.66.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-08-24 00:00:00.000000000 Z
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport