appmap 0.63.0 → 0.66.0

Sign up to get free protection for your applications and to get access to all the features.
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