appmap 0.54.4 → 0.58.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: 13450fa6c0ff3576dc48e27f35355e3eb4bd4ed70aac677af1235b8b8b8ce793
4
- data.tar.gz: 2c08a504d3e6a467d212630290205ecab9391c64a33831574df43cb8526ab0ad
3
+ metadata.gz: ca5a16a5edc35706d33aa6ec21e45b5641aa9342b6fc5ab03ada141556c2b859
4
+ data.tar.gz: 7a4b5b6ff0c504814b7eccebba46a739cc4e00fcf6eb1e5492ef7f52d2f887d6
5
5
  SHA512:
6
- metadata.gz: 49585b5fba1c9b7a0aabffd6dfc44fb051532fd9fe96d35a0176c6bcf382a51df948bfac8f1f0d3db474917f5587dbf07e90de9c9097d3de9a1650a1632f8fd6
7
- data.tar.gz: aa489a3dc598dfc2c16ee3a6167e53683e5564870c3b1ed0552e9e0ba0d758da2d1c442059bee3efbe57206f9088a98ca7c271d8550f52ed5d18d0aa2a039635
6
+ metadata.gz: 5267e3ba0827671d825ca0bb0323965ae0d8b5c0ac772f95721227af2b66a3a2d2843f7813a4f1faff997e49cd83dc4b7d78a57cb3b4852cfd6fbe63290aa223
7
+ data.tar.gz: cdb60a38a5d9c836a159c9473a7bf42e06589926ec7011b5978add71dca14ef6fd8acc807d7ef745e3d17ab908e38eca49bfbb3094c5b48a97d4084d9a2f34d8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,47 @@
1
+ # [0.58.0](https://github.com/applandinc/appmap-ruby/compare/v0.57.1...v0.58.0) (2021-07-06)
2
+
3
+
4
+ ### Features
5
+
6
+ * Add `test_commands` sections to `appmap-agent-status` executable ([4cd8fe5](https://github.com/applandinc/appmap-ruby/commit/4cd8fe58acb4af72b7818db96de9e479562b9ea0))
7
+
8
+ ## [0.57.1](https://github.com/applandinc/appmap-ruby/compare/v0.57.0...v0.57.1) (2021-07-02)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * rename agentVersionPorject to agentVersion ([905fc5d](https://github.com/applandinc/appmap-ruby/commit/905fc5dd643411deb94f8a1087bcdb3a562d218a))
14
+
15
+ # [0.57.0](https://github.com/applandinc/appmap-ruby/compare/v0.56.0...v0.57.0) (2021-06-29)
16
+
17
+
18
+ ### Features
19
+
20
+ * Update init command to return JSON ([1f93e89](https://github.com/applandinc/appmap-ruby/commit/1f93e8909684e1018f513d69adfde2a5d0bf6bc9))
21
+
22
+ # [0.56.0](https://github.com/applandinc/appmap-ruby/compare/v0.55.0...v0.56.0) (2021-06-28)
23
+
24
+
25
+ ### Features
26
+
27
+ * add appmap-agent-status executable with config/project properties ([043f845](https://github.com/applandinc/appmap-ruby/commit/043f8453a2533a6e172d1cd23fcde04f19e73173))
28
+
29
+ # [0.55.0](https://github.com/applandinc/appmap-ruby/compare/v0.54.4...v0.55.0) (2021-06-28)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * Avoid calling == ([f30ed9f](https://github.com/applandinc/appmap-ruby/commit/f30ed9f309753252df35e372d925db3b914260d4))
35
+ * Log dynamic loading of appmap helpers at info level ([15dcd3c](https://github.com/applandinc/appmap-ruby/commit/15dcd3c913fa1c32aea034b28ddae59668efa217))
36
+ * Remove dynamic loading of rake and rspec helpers ([6790970](https://github.com/applandinc/appmap-ruby/commit/67909702f3c8a52081ef1e23a87c292908883334))
37
+
38
+
39
+ ### Features
40
+
41
+ * APPMAP_PROFILE_DISPLAY_STRING and APPMAP_OBJECT_STRING ([3f5daa8](https://github.com/applandinc/appmap-ruby/commit/3f5daa890bfbfd39b7f825794d0c43da509b3201))
42
+ * Package name to require can be specified when hooking a gem ([fcc5eb6](https://github.com/applandinc/appmap-ruby/commit/fcc5eb691a0330444560eb4c2afe7fc3c4c8afa8))
43
+ * Profile packaging hooking ([c020a31](https://github.com/applandinc/appmap-ruby/commit/c020a312f4545348ec7cc302443269c57a7fc026))
44
+
1
45
  ## [0.54.4](https://github.com/applandinc/appmap-ruby/compare/v0.54.3...v0.54.4) (2021-06-27)
2
46
 
3
47
 
@@ -5,10 +5,10 @@ require 'optparse'
5
5
  require 'appmap'
6
6
  require 'appmap/command/agent_setup/init'
7
7
 
8
- @options = {:config_file => AppMap::DEFAULT_CONFIG_FILE_PATH}
8
+ @options = { config_file: AppMap::DEFAULT_CONFIG_FILE_PATH }
9
9
 
10
10
  OptionParser.new do |parser|
11
- parser.banner = 'Usage: bundle exec exe/appmap-agent-init [options]'
11
+ parser.banner = 'Usage: appmap-agent-init [options]'
12
12
 
13
13
  description = "AppMap configuration file path (default: #{AppMap::DEFAULT_CONFIG_FILE_PATH})"
14
14
  parser.on('-c', '--config=FILEPATH', description) do |filepath|
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+ require 'appmap'
6
+ require 'appmap/command/agent_setup/status'
7
+
8
+ @options = { config_file: AppMap::DEFAULT_CONFIG_FILE_PATH }
9
+
10
+ OptionParser.new do |parser|
11
+ parser.banner = 'Usage: appmap-agent-status [options]'
12
+
13
+ description = "AppMap configuration file path (default: #{AppMap::DEFAULT_CONFIG_FILE_PATH})"
14
+ parser.on('-c', '--config=FILEPATH', description) do |filepath|
15
+ @options[:config_file] = filepath
16
+ end
17
+ end.parse!
18
+
19
+ AppMap::Command::AgentSetup::Status.new(@options[:config_file]).perform
data/lib/appmap.rb CHANGED
@@ -28,11 +28,9 @@ lambda do
28
28
  INITIALIZERS = {
29
29
  # In a Rails app, Rails is always defined by the time the other gems are loaded. Therefore, we
30
30
  # don't try and trap the loading of Rails itself here.
31
- 'RSpec' => Initializer.new('AppMap::RSpec', 'appmap/rspec', 'rspec-core'),
31
+ # Emperically, Rake and RSpec are also defined before appmap is loaded whenever a Rake task or
32
+ # RSpec tests are being run. Therefore, the only hook we need here is Minitest.
32
33
  'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest'),
33
- 'Rake' => [
34
- Initializer.new('AppMap::Swagger', 'appmap/swagger', 'rake')
35
- ]
36
34
  }
37
35
 
38
36
  TracePoint.new(:class) do |tp|
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fileutils'
3
+ require 'json'
4
4
  require 'appmap/service/guesser'
5
- require 'appmap/util'
6
5
 
7
6
  module AppMap
8
7
  module Command
@@ -11,32 +10,19 @@ module AppMap
11
10
 
12
11
  class Init < InitStruct
13
12
  def perform
14
- if File.exist?(config_file)
15
- puts AppMap::Util.color(%(The AppMap config file #{config_file} already exists.), :magenta)
16
- return
17
- end
18
-
19
- ensure_directory_exists
20
-
21
13
  config = {
22
14
  'name' => Service::Guesser.guess_name,
23
15
  'packages' => Service::Guesser.guess_paths.map { |path| { 'path' => path } }
24
16
  }
25
- content = YAML.dump(config).gsub("---\n", '')
26
17
 
27
- File.write(config_file, content)
28
- puts AppMap::Util.color(
29
- %(The following AppMap config file #{config_file} has been created:),
30
- :green
31
- )
32
- puts content
33
- end
34
-
35
- private
18
+ result = {
19
+ configuration: {
20
+ filename: config_file,
21
+ contents: YAML.dump(config)
22
+ }
23
+ }
36
24
 
37
- def ensure_directory_exists
38
- dirname = File.dirname(config_file)
39
- FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
25
+ puts JSON.pretty_generate(result)
40
26
  end
41
27
  end
42
28
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'appmap/service/config_analyzer'
5
+ require 'appmap/service/integration_test_path_finder'
6
+ require 'appmap/service/test_command_provider'
7
+
8
+ module AppMap
9
+ module Command
10
+ module AgentSetup
11
+ StatusStruct = Struct.new(:config_file)
12
+
13
+ class Status < StatusStruct
14
+ def perform
15
+ status = {
16
+ test_commands: Service::TestCommandProvider.all,
17
+ properties: {
18
+ config: {
19
+ app: config_analyzer.app_name,
20
+ present: config_analyzer.present?,
21
+ valid: config_analyzer.valid?
22
+ },
23
+ project: {
24
+ agentVersion: AppMap::VERSION,
25
+ language: 'ruby',
26
+ remoteRecordingCapable: Gem.loaded_specs.has_key?('rails'),
27
+ integrationTests: Service::IntegrationTestPathFinder.count_paths > 0
28
+ }
29
+ }
30
+ }
31
+
32
+ puts JSON.pretty_generate(status)
33
+ end
34
+
35
+ private
36
+
37
+ def config_analyzer
38
+ @config_analyzer ||= Service::ConfigAnalyzer.new(config_file)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
data/lib/appmap/config.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
3
4
  require 'yaml'
4
5
  require 'appmap/util'
5
6
  require 'appmap/handler/net_http'
@@ -343,7 +344,7 @@ module AppMap
343
344
  shallow = package['shallow']
344
345
  # shallow is true by default for gems
345
346
  shallow = true if shallow.nil?
346
- Package.build_from_gem(gem, exclude: package['exclude'] || [], shallow: shallow)
347
+ Package.build_from_gem(gem, package_name: package['package'], exclude: package['exclude'] || [], shallow: shallow)
347
348
  else
348
349
  Package.build_from_path(path, exclude: package['exclude'] || [], shallow: package['shallow'])
349
350
  end
data/lib/appmap/event.rb CHANGED
@@ -29,11 +29,31 @@ module AppMap
29
29
 
30
30
  # Gets a display string for a value. This is not meant to be a machine deserializable value.
31
31
  def display_string(value)
32
- return nil unless value
32
+ return nil if value.equal?(nil)
33
33
 
34
+ # With setting APPMAP_PROFILE_DISPLAY_STRING, stringifying this class is shown to take 9 seconds(!) of a 17 second test run.
35
+ return nil if best_class_name(value) == 'ActiveSupport::Callbacks::Filters::Environment'
36
+
37
+ if @times.nil? && ENV['APPMAP_PROFILE_DISPLAY_STRING'] == 'true'
38
+ @times = Hash.new {|memo,key| memo[key] = 0}
39
+ Thread.new do
40
+ sleep 0.5
41
+ while true
42
+ warn @times.to_a.sort{|a,b| b[1] <=> a[1]}[0..9].join("\n")
43
+ sleep 3
44
+ end
45
+ end
46
+ end
47
+
48
+ start = Time.now
34
49
  value_string = custom_display_string(value) || default_display_string(value)
35
50
 
36
- (value_string||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
51
+ if @times
52
+ elapsed = Time.now - start
53
+ @times[best_class_name(value)] += elapsed
54
+ end
55
+
56
+ encode_dislay_string(value_string)
37
57
  end
38
58
 
39
59
  def object_properties(hash_like)
@@ -57,8 +77,16 @@ module AppMap
57
77
  value_cls.name
58
78
  end
59
79
 
80
+ def encode_dislay_string(value)
81
+ (value||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
82
+ end
83
+
60
84
  def custom_display_string(value)
61
85
  case value
86
+ when NilClass, TrueClass, FalseClass, Numeric, Time, Date
87
+ value.to_s
88
+ when String
89
+ value[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
62
90
  when File
63
91
  "#{value.class}[path=#{value.path}]"
64
92
  when Net::HTTP
@@ -71,6 +99,8 @@ module AppMap
71
99
  end
72
100
 
73
101
  def default_display_string(value)
102
+ return nil if ENV['APPMAP_OBJECT_STRING'] == 'false'
103
+
74
104
  last_resort_string = lambda do
75
105
  warn "AppMap encountered an error inspecting a #{value.class.name}: #{$!.message}"
76
106
  '*Error inspecting variable*'
data/lib/appmap/hook.rb CHANGED
@@ -9,6 +9,7 @@ module AppMap
9
9
 
10
10
  OBJECT_INSTANCE_METHODS = %i[! != !~ <=> == === =~ __id__ __send__ class clone define_singleton_method display dup enum_for eql? equal? extend freeze frozen? hash inspect instance_eval instance_exec instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method methods nil? object_id private_methods protected_methods public_method public_methods public_send remove_instance_variable respond_to? send singleton_class singleton_method singleton_methods taint tainted? tap then to_enum to_s to_h to_a trust untaint untrust untrusted? yield_self].freeze
11
11
  OBJECT_STATIC_METHODS = %i[! != !~ < <= <=> == === =~ > >= __id__ __send__ alias_method allocate ancestors attr attr_accessor attr_reader attr_writer autoload autoload? class class_eval class_exec class_variable_defined? class_variable_get class_variable_set class_variables clone const_defined? const_get const_missing const_set constants define_method define_singleton_method deprecate_constant display dup enum_for eql? equal? extend freeze frozen? hash include include? included_modules inspect instance_eval instance_exec instance_method instance_methods instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method method_defined? methods module_eval module_exec name new nil? object_id prepend private_class_method private_constant private_instance_methods private_method_defined? private_methods protected_instance_methods protected_method_defined? protected_methods public_class_method public_constant public_instance_method public_instance_methods public_method public_method_defined? public_methods public_send remove_class_variable remove_instance_variable remove_method respond_to? send singleton_class singleton_class? singleton_method singleton_methods superclass taint tainted? tap then to_enum to_s trust undef_method untaint untrust untrusted? yield_self].freeze
12
+ SLOW_PACKAGE_THRESHOLD = 0.05
12
13
 
13
14
  @unbound_method_arity = ::UnboundMethod.instance_method(:arity)
14
15
  @method_arity = ::Method.instance_method(:arity)
@@ -49,6 +50,27 @@ module AppMap
49
50
  @notrace_paths = Set.new
50
51
  # Locations that have already been visited.
51
52
  @trace_locations = Set.new
53
+ @module_load_times = Hash.new {|memo,k| memo[k] = 0}
54
+ @slow_packages = Set.new
55
+
56
+ if ENV['APPMAP_PROFILE_HOOK'] == 'true'
57
+ Thread.new do
58
+ sleep 1
59
+ while true
60
+ @module_load_times
61
+ .keys
62
+ .select { |key| !@slow_packages.member?(key) }
63
+ .each do |key|
64
+ elapsed = @module_load_times[key]
65
+ if elapsed >= SLOW_PACKAGE_THRESHOLD
66
+ @slow_packages.add(key)
67
+ warn "AppMap: Package #{key} took #{@module_load_times[key]} seconds to hook"
68
+ end
69
+ end
70
+ sleep 5
71
+ end
72
+ end
73
+ end
52
74
 
53
75
  @trace_end = TracePoint.new(:end, &method(:trace_end))
54
76
  @trace_end.enable(&block)
@@ -157,6 +179,7 @@ module AppMap
157
179
  end
158
180
  end
159
181
 
182
+ start = Time.now
160
183
  instance_methods.each(&hook.(cls))
161
184
  begin
162
185
  # NoMethodError: private method `singleton_class' called for Rack::MiniProfiler:Class
@@ -166,6 +189,11 @@ module AppMap
166
189
  # uninitialized constant Faraday::Connection
167
190
  warn "NameError in #{__FILE__}: #{$!.message}"
168
191
  end
192
+ elapsed = Time.now - start
193
+ if location.index(Bundler.bundle_path.to_s) == 0
194
+ package_tokens = location[Bundler.bundle_path.to_s.length + 1..-1].split('/')
195
+ @module_load_times[package_tokens[1]] += elapsed
196
+ end
169
197
  end
170
198
  end
171
199
  end
@@ -49,9 +49,14 @@ module AppMap
49
49
 
50
50
  hook_method_def = Proc.new do |*args, &block|
51
51
  instance_method = hook_method.bind(self).to_proc
52
+
53
+ is_array_containing_empty_hash = ->(obj) {
54
+ obj.is_a?(Array) && obj.length == 1 && obj[0].is_a?(Hash) && obj[0].size == 0
55
+ }
56
+
52
57
  call_instance_method = -> {
53
58
  # https://github.com/applandinc/appmap-ruby/issues/153
54
- if Util.ruby_minor_version >= 2.7 && args == ARRAY_OF_EMPTY_HASH && hook_method.arity == 1
59
+ if Util.ruby_minor_version >= 2.7 && is_array_containing_empty_hash.(args) && hook_method.arity == 1
55
60
  instance_method.call({}, &block)
56
61
  else
57
62
  instance_method.call(*args, &block)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppMap
4
+ module Service
5
+ class ConfigAnalyzer
6
+ attr_reader :config_error
7
+
8
+ def initialize(config_file)
9
+ @config_file = config_file
10
+ @config = load_config
11
+ end
12
+
13
+ def app_name
14
+ @config.to_h[:name] if present?
15
+ end
16
+
17
+ def present?
18
+ File.exist?(@config_file)
19
+ end
20
+
21
+ def valid?
22
+ present? && @config.to_h.key?(:name) && @config.to_h.key?(:packages)
23
+ end
24
+
25
+ private
26
+
27
+ def load_config
28
+ AppMap::Config.load_from_file @config_file if present?
29
+ rescue
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap/service/test_framework_detector'
4
+
5
+ module AppMap
6
+ module Service
7
+ class IntegrationTestPathFinder
8
+ class << self
9
+ def find
10
+ @paths ||= begin
11
+ paths = { rspec: [], minitest: [], cucumber: [] }
12
+ paths[:rspec] = find_rspec_paths if TestFrameworkDetector.rspec_present?
13
+ paths[:minitest] = find_minitest_paths if TestFrameworkDetector.minitest_present?
14
+ paths[:cucumber] = find_cucumber_paths if TestFrameworkDetector.cucumber_present?
15
+ paths
16
+ end
17
+ end
18
+
19
+ def count_paths
20
+ find.flatten(2).length - 3
21
+ end
22
+
23
+ private
24
+
25
+ def find_rspec_paths
26
+ find_non_empty_paths(%w[spec/controllers spec/requests spec/integration spec/api spec/features spec/system])
27
+ end
28
+
29
+
30
+ def find_minitest_paths
31
+ find_non_empty_paths(%w[test/controllers test/integration])
32
+ end
33
+
34
+ def find_cucumber_paths
35
+ find_non_empty_paths(%w[features])
36
+ end
37
+
38
+ def find_non_empty_paths(paths)
39
+ paths.select { |path| Dir.exist?(path) && !Dir.empty?(path) }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap/service/test_framework_detector'
4
+ require 'appmap/service/integration_test_path_finder'
5
+
6
+ module AppMap
7
+ module Service
8
+ class TestCommandProvider
9
+ class << self
10
+ def all
11
+ commands = []
12
+
13
+ if TestFrameworkDetector.rspec_present? && !integration_test_paths[:rspec].empty?
14
+ commands << {
15
+ framework: :rspec,
16
+ command: "APPMAP=true bundle exec rspec #{integration_test_paths[:rspec].join(' ')}"
17
+ }
18
+ end
19
+
20
+ if TestFrameworkDetector.minitest_present? && !integration_test_paths[:minitest].empty?
21
+ commands << {
22
+ framework: :minitest,
23
+ command: minitest_command
24
+ }
25
+ end
26
+
27
+ if TestFrameworkDetector.cucumber_present? && !integration_test_paths[:cucumber].empty?
28
+ commands << {
29
+ framework: :cucumber,
30
+ command: 'APPMAP=true bundle exec cucumber'
31
+ }
32
+ end
33
+
34
+ commands
35
+ end
36
+
37
+ private
38
+
39
+ def minitest_command
40
+ if Gem.loaded_specs.has_key?('rails')
41
+ "APPMAP=true bundle exec rails test #{integration_test_paths[:minitest].join(' ')}"
42
+ else
43
+ subcommands = integration_test_paths[:minitest].map { |path| "APPMAP=true bundle exec ruby #{path}" }
44
+ subcommands.join(' && ')
45
+ end
46
+ end
47
+
48
+ def integration_test_paths
49
+ @paths ||= Service::IntegrationTestPathFinder.find
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppMap
4
+ module Service
5
+ class TestFrameworkDetector
6
+ class << self
7
+ def rspec_present?
8
+ Gem.loaded_specs.has_key?('rspec-core')
9
+ end
10
+
11
+ def minitest_present?
12
+ Gem.loaded_specs.has_key?('minitest')
13
+ end
14
+
15
+ def cucumber_present?
16
+ Gem.loaded_specs.has_key?('cucumber')
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/appmap/util.rb CHANGED
@@ -185,7 +185,7 @@ module AppMap
185
185
 
186
186
  def startup_message(msg)
187
187
  if defined?(::Rails) && defined?(::Rails.logger) && ::Rails.logger
188
- ::Rails.logger.debug msg
188
+ ::Rails.logger.info msg
189
189
  elsif ENV['DEBUG'] == 'true'
190
190
  warn msg
191
191
  end
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.54.4'
6
+ VERSION = '0.58.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.5.1'
9
9
 
@@ -0,0 +1 @@
1
+ name: app
@@ -0,0 +1,2 @@
1
+ name: -123- %
2
+ packages: ~{}~ ''
@@ -0,0 +1,3 @@
1
+ name: appmap
2
+ packages:
3
+ - path: app/models
@@ -0,0 +1,10 @@
1
+ # minitest_calc_test_unit_format_spec.rb
2
+
3
+ require "minitest/autorun"
4
+
5
+ class FunctionalCalcTest < Minitest::Test
6
+ def test_add
7
+ puts 'functional'
8
+ assert_equal 2 + 2, 4
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # minitest_calc_test_unit_format_spec.rb
2
+
3
+ require "minitest/autorun"
4
+
5
+ class IntegrationCalcTest < Minitest::Test
6
+ class CalcTest < Minitest::Test
7
+ def test_add
8
+ puts 'integration'
9
+ assert_equal 2 + 2, 4
10
+ end
11
+ end
12
+ end
data/spec/hook_spec.rb CHANGED
@@ -970,7 +970,7 @@ describe 'AppMap class Hooking', docker: false do
970
970
  tz = ENV['TZ']
971
971
  ENV['TZ'] = 'UTC'
972
972
  Timecop.freeze(Time.utc('2020-01-01')) do
973
- expect(Time).to receive(:now).exactly(3).times.and_call_original
973
+ expect(Time).to receive(:now).at_least(3).times.and_call_original
974
974
  expect(InstanceMethod.new.say_the_time).to be
975
975
  end
976
976
  ensure
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'appmap/service/config_analyzer'
5
+
6
+ describe AppMap::Service::ConfigAnalyzer do
7
+ subject { described_class.new(config_file) }
8
+
9
+ context 'with non-existing config' do
10
+ let(:config_file) { 'spec/fixtures/config/non_existing_config.yml'}
11
+
12
+ describe '.app_name' do
13
+ it 'returns nil' do
14
+ expect(subject.app_name).to be_nil
15
+ end
16
+ end
17
+
18
+ describe '.is_valid?' do
19
+ it 'returns false' do
20
+ expect(subject.valid?).to be_falsey
21
+ end
22
+ end
23
+
24
+ describe '.is_present?' do
25
+ it 'returns false' do
26
+ expect(subject.present?).to be_falsey
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'with valid config' do
32
+ let(:config_file) { 'spec/fixtures/config/valid_config.yml'}
33
+
34
+ describe '.app_name' do
35
+ it 'returns app name value from config' do
36
+ expect(subject.app_name).to eq('appmap')
37
+ end
38
+ end
39
+
40
+ describe '.is_valid?' do
41
+ it 'returns true' do
42
+ expect(subject.valid?).to be_truthy
43
+ end
44
+ end
45
+
46
+ describe '.is_present?' do
47
+ it 'returns true' do
48
+ expect(subject.present?).to be_truthy
49
+ end
50
+ end
51
+ end
52
+
53
+ context 'with invalid YAML config' do
54
+ let(:config_file) { 'spec/fixtures/config/invalid_config.yml'}
55
+
56
+ describe '.app_name' do
57
+ it 'returns app name value from config' do
58
+ expect(subject.app_name).to be_nil
59
+ end
60
+ end
61
+
62
+ describe '.is_valid?' do
63
+ it 'returns false' do
64
+ expect(subject.valid?).to be_falsey
65
+ end
66
+ end
67
+
68
+ describe '.is_present?' do
69
+ it 'return true' do
70
+ expect(subject.present?).to be_truthy
71
+ end
72
+ end
73
+ end
74
+
75
+ context 'with incomplete config' do
76
+ let(:config_file) { 'spec/fixtures/config/incomplete_config.yml'}
77
+
78
+ describe '.app_name' do
79
+ it 'returns nil' do
80
+ expect(subject.app_name).to eq('app')
81
+ end
82
+ end
83
+
84
+ describe '.is_valid?' do
85
+ it 'guesses paths and returns true ' do
86
+ expect(subject.valid?).to be_truthy
87
+ end
88
+ end
89
+
90
+ describe '.is_present?' do
91
+ it 'returns true' do
92
+ expect(subject.present?).to be_truthy
93
+ end
94
+ end
95
+ end
96
+ end
@@ -5,8 +5,8 @@ require 'test_helper'
5
5
 
6
6
  class AgentSetupInitTest < Minitest::Test
7
7
  CONFIG_FILENAME = '123.yml'
8
- SUBFOLDER_CONFIG_FILEPATH = 'conf/123.yml'
9
- EXPECTED_CONFIG_CONTENT = %(name: appmap-ruby
8
+ EXPECTED_CONFIG_CONTENT = %(---
9
+ name: appmap-ruby
10
10
  packages:
11
11
  - path: lib
12
12
  )
@@ -14,24 +14,24 @@ packages:
14
14
  def test_init_when_config_exists
15
15
  output = `./exe/appmap-agent-init`
16
16
  assert_equal 0, $CHILD_STATUS.exitstatus
17
- assert_includes output, 'The AppMap config file appmap.yml already exists.'
17
+ expected = JSON.pretty_generate({
18
+ configuration: {
19
+ filename: 'appmap.yml',
20
+ contents: EXPECTED_CONFIG_CONTENT
21
+ }
22
+ })
23
+ assert_equal expected, output.strip
18
24
  end
19
25
 
20
26
  def test_init_with_custom_config_filename
21
27
  output = `./exe/appmap-agent-init -c #{CONFIG_FILENAME}`
22
28
  assert_equal 0, $CHILD_STATUS.exitstatus
23
- assert_includes output, "The following AppMap config file #{CONFIG_FILENAME} has been created:"
24
- assert_equal EXPECTED_CONFIG_CONTENT, File.read(CONFIG_FILENAME)
25
- ensure
26
- File.delete(CONFIG_FILENAME) if File.exist?(CONFIG_FILENAME)
27
- end
28
-
29
- def test_init_with_custom_config_file_in_subfolder
30
- output = `./exe/appmap-agent-init --config=#{SUBFOLDER_CONFIG_FILEPATH}`
31
- assert_equal 0, $CHILD_STATUS.exitstatus
32
- assert_includes output, "The following AppMap config file #{SUBFOLDER_CONFIG_FILEPATH} has been created:"
33
- assert_equal EXPECTED_CONFIG_CONTENT, File.read(SUBFOLDER_CONFIG_FILEPATH)
34
- ensure
35
- File.delete(SUBFOLDER_CONFIG_FILEPATH) if File.exist?(SUBFOLDER_CONFIG_FILEPATH)
29
+ expected = JSON.pretty_generate({
30
+ configuration: {
31
+ filename: CONFIG_FILENAME,
32
+ contents: EXPECTED_CONFIG_CONTENT
33
+ }
34
+ })
35
+ assert_equal expected, output.strip
36
36
  end
37
37
  end
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'test_helper'
5
+
6
+ class AgentSetupInitTest < Minitest::Test
7
+ def test_status_gem
8
+ output = `./exe/appmap-agent-status`
9
+ assert_equal 0, $CHILD_STATUS.exitstatus
10
+ expected = {
11
+ test_commands: [],
12
+ properties: {
13
+ config: {
14
+ app: 'AppMap Rubygem',
15
+ present: true,
16
+ valid: true
17
+ },
18
+ project: {
19
+ agentVersion: AppMap::VERSION,
20
+ language: 'ruby',
21
+ remoteRecordingCapable: false,
22
+ integrationTests: false
23
+ }
24
+ }
25
+ }
26
+ assert_equal JSON.pretty_generate(expected), output.strip
27
+ end
28
+
29
+ def test_status_rails_app
30
+ def test_status
31
+ output = `cd spec/fixtures/rails6_users_app && bundle exec ../../../exe/appmap-agent-status`
32
+ assert_equal 0, $CHILD_STATUS.exitstatus
33
+ expected = {
34
+ test_commands: [
35
+ {
36
+ framework: :rspec,
37
+ command: 'APPMAP=true bundle exec rspec spec/controllers'
38
+ },
39
+ {
40
+ framework: :minitest,
41
+ command: 'APPMAP=true bundle exec ruby test/controllers && APPMAP=true bundle exec ruby test/integration'
42
+ },
43
+ {
44
+ framework: :cucumber,
45
+ command: 'APPMAP=true bundle exec cucumber'
46
+ }
47
+ ],
48
+ properties: {
49
+ config: {
50
+ app: nil,
51
+ present: true,
52
+ valid: true
53
+ },
54
+ project: {
55
+ agentVersion: AppMap::VERSION,
56
+ language: 'ruby',
57
+ remoteRecordingCapable: false,
58
+ integrationTests: true
59
+ }
60
+ }
61
+ }
62
+ assert_equal JSON.pretty_generate(expected), output.strip
63
+ end
64
+ end
65
+ 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.54.4
4
+ version: 0.58.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-06-27 00:00:00.000000000 Z
11
+ date: 2021-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -295,6 +295,7 @@ email:
295
295
  - kgilpin@gmail.com
296
296
  executables:
297
297
  - appmap-agent-init
298
+ - appmap-agent-status
298
299
  - appmap-inspect
299
300
  extensions:
300
301
  - ext/appmap/extconf.rb
@@ -324,6 +325,7 @@ files:
324
325
  - examples/mock_webapp/lib/mock_webapp/request.rb
325
326
  - examples/mock_webapp/lib/mock_webapp/user.rb
326
327
  - exe/appmap-agent-init
328
+ - exe/appmap-agent-status
327
329
  - exe/appmap-inspect
328
330
  - ext/appmap/appmap.c
329
331
  - ext/appmap/extconf.rb
@@ -331,6 +333,7 @@ files:
331
333
  - lib/appmap/agent.rb
332
334
  - lib/appmap/class_map.rb
333
335
  - lib/appmap/command/agent_setup/init.rb
336
+ - lib/appmap/command/agent_setup/status.rb
334
337
  - lib/appmap/command/inspect.rb
335
338
  - lib/appmap/command_error.rb
336
339
  - lib/appmap/config.rb
@@ -351,7 +354,11 @@ files:
351
354
  - lib/appmap/railtie.rb
352
355
  - lib/appmap/record.rb
353
356
  - lib/appmap/rspec.rb
357
+ - lib/appmap/service/config_analyzer.rb
354
358
  - lib/appmap/service/guesser.rb
359
+ - lib/appmap/service/integration_test_path_finder.rb
360
+ - lib/appmap/service/test_command_provider.rb
361
+ - lib/appmap/service/test_framework_detector.rb
355
362
  - lib/appmap/swagger.rb
356
363
  - lib/appmap/swagger/configuration.rb
357
364
  - lib/appmap/swagger/markdown_descriptions.rb
@@ -364,6 +371,9 @@ files:
364
371
  - release.sh
365
372
  - spec/class_map_spec.rb
366
373
  - spec/config_spec.rb
374
+ - spec/fixtures/config/incomplete_config.yml
375
+ - spec/fixtures/config/invalid_config.yml
376
+ - spec/fixtures/config/valid_config.yml
367
377
  - spec/fixtures/hook/.gitignore
368
378
  - spec/fixtures/hook/app/controllers/api/api_keys_controller.rb
369
379
  - spec/fixtures/hook/app/controllers/organizations_controller.rb
@@ -536,6 +546,8 @@ files:
536
546
  - spec/fixtures/rails6_users_app/spec/models/user_spec.rb
537
547
  - spec/fixtures/rails6_users_app/spec/rails_helper.rb
538
548
  - spec/fixtures/rails6_users_app/spec/spec_helper.rb
549
+ - spec/fixtures/rails6_users_app/test/controllers/functional_calc_test.rb
550
+ - spec/fixtures/rails6_users_app/test/integration/integration_calc_test.rb
539
551
  - spec/fixtures/rails6_users_app/users_app/.gitignore
540
552
  - spec/hook_spec.rb
541
553
  - spec/open_spec.rb
@@ -545,10 +557,12 @@ files:
545
557
  - spec/record_net_http_spec.rb
546
558
  - spec/record_sql_rails_pg_spec.rb
547
559
  - spec/remote_recording_spec.rb
560
+ - spec/service/config_analyzer_spec.rb
548
561
  - spec/spec_helper.rb
549
562
  - spec/swagger/swagger_spec.rb
550
563
  - spec/util_spec.rb
551
564
  - test/agent_setup_init_test.rb
565
+ - test/agent_setup_status_test.rb
552
566
  - test/bundle_vendor_test.rb
553
567
  - test/cucumber_test.rb
554
568
  - test/expectations/openssl_test_key_sign1.json