appmap 0.57.1 → 0.60.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: 3e1ad8b152e2dbb26fd8b62042a4908f09c46b5dea88a9e05dc2a431b0fd2674
4
- data.tar.gz: 9fa1719c374839b8a7827265771d0db2e25e11a27860240bd17b5155ea7029ed
3
+ metadata.gz: 832f968242440a6bac78181dbb49ca1b34d75c37074810df66c3d1b1d546c0cf
4
+ data.tar.gz: 26ffec9cffe15f63dc661563ec7bee9c8b4659a54c0a8888dd797b6253518954
5
5
  SHA512:
6
- metadata.gz: e38b17165142f6e5c574ee0cfda832baf2f27ac0c66b90e979a88c5280f66b659e53e3f919a24eb72cd132be6ec321a01708fa73f4c9d54bdaedacc137202895
7
- data.tar.gz: 7d873528d6c51980d88816f74981da0d427697b4f720dfae9b34cd2ff616fd309935487c3187b603d44e2fa74930bbc90a5441f68c7f045829ffee6269cf7ebe
6
+ metadata.gz: '09eb7e68782f397a59a960ba617af180ee2d0746316db9b7d2c4cd011755e815205a5b484d0a90cd19224ab7f4be7231a96c664ea87e962c02372e155088cc82'
7
+ data.tar.gz: eea1765efb3ab76716d7c8c74f9f7b9d860923d815dab0bd003ecf8f07dc62ac6d3660e43ba0576b615bd6de094156e14e8a5be876dfe3851d4dc2c95cd82368
data/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ # [0.60.0](https://github.com/applandinc/appmap-ruby/compare/v0.59.2...v0.60.0) (2021-07-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * add agent-setup-validate command ([d9b3bc1](https://github.com/applandinc/appmap-ruby/commit/d9b3bc15e01bf89994aa67b0256dd69b9983be76))
7
+ * validate ruby version (+ better config loading validation) ([1756e6c](https://github.com/applandinc/appmap-ruby/commit/1756e6c30b5c44a033c23eb47c27c56732d12470))
8
+
9
+ ## [0.59.2](https://github.com/applandinc/appmap-ruby/compare/v0.59.1...v0.59.2) (2021-07-08)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * Remove improper reliance on Rails 'try' ([c6b5b16](https://github.com/applandinc/appmap-ruby/commit/c6b5b16a6963988e20bab5f88b99401e25691f3c))
15
+
16
+ ## [0.59.1](https://github.com/applandinc/appmap-ruby/compare/v0.59.0...v0.59.1) (2021-07-08)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * Events may be constructed in stages ([b0b23f5](https://github.com/applandinc/appmap-ruby/commit/b0b23f59a84158b8162424b84430894fe4278324))
22
+
23
+ # [0.59.0](https://github.com/applandinc/appmap-ruby/compare/v0.58.0...v0.59.0) (2021-07-07)
24
+
25
+
26
+ ### Features
27
+
28
+ * define commands as objects ([1b43203](https://github.com/applandinc/appmap-ruby/commit/1b432039040277e1b5349cc2f75aa436238ea873))
29
+
30
+ # [0.58.0](https://github.com/applandinc/appmap-ruby/compare/v0.57.1...v0.58.0) (2021-07-06)
31
+
32
+
33
+ ### Features
34
+
35
+ * Add `test_commands` sections to `appmap-agent-status` executable ([4cd8fe5](https://github.com/applandinc/appmap-ruby/commit/4cd8fe58acb4af72b7818db96de9e479562b9ea0))
36
+
1
37
  ## [0.57.1](https://github.com/applandinc/appmap-ruby/compare/v0.57.0...v0.57.1) (2021-07-02)
2
38
 
3
39
 
data/config-schema.yml ADDED
@@ -0,0 +1,57 @@
1
+ type: object
2
+ additionalProperties: false
3
+ required:
4
+ - name
5
+ properties:
6
+ name:
7
+ type: string
8
+ packages:
9
+ type: array
10
+ items:
11
+ anyOf:
12
+ - type: object
13
+ additionalProperties: false
14
+ required:
15
+ - path
16
+ properties:
17
+ path:
18
+ type: string
19
+ shallow:
20
+ type: boolean
21
+ exclude:
22
+ type: array
23
+ items:
24
+ type: string
25
+ - type: object
26
+ additionalProperties: false
27
+ required:
28
+ - gem
29
+ properties:
30
+ gem:
31
+ type: string
32
+ shallow:
33
+ type: boolean
34
+ exclude:
35
+ type: array
36
+ items:
37
+ type: string
38
+ exclude:
39
+ type: array
40
+ items:
41
+ type: string
42
+ functions:
43
+ type: array
44
+ items:
45
+ type: object
46
+ additionalProperties: false
47
+ properties:
48
+ package:
49
+ type: string
50
+ class:
51
+ type: string
52
+ function:
53
+ type: string
54
+ labels:
55
+ type: array
56
+ items:
57
+ type: string
@@ -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/validate'
7
+
8
+ @options = { config_file: AppMap::DEFAULT_CONFIG_FILE_PATH }
9
+
10
+ OptionParser.new do |parser|
11
+ parser.banner = 'Usage: appmap-agent-validate [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::Validate.new(@options[:config_file]).perform
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'json'
4
4
  require 'appmap/service/config_analyzer'
5
+ require 'appmap/service/integration_test_path_finder'
6
+ require 'appmap/service/test_command_provider'
5
7
 
6
8
  module AppMap
7
9
  module Command
@@ -11,22 +13,23 @@ module AppMap
11
13
  class Status < StatusStruct
12
14
  def perform
13
15
  status = {
14
- :properties => {
15
- :config => {
16
- :app => config_analyzer.app_name,
17
- :present => config_analyzer.present?,
18
- :valid => config_analyzer.valid?
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?
19
22
  },
20
- :project => {
21
- :agentVersion => AppMap::VERSION,
22
- :language => 'ruby',
23
- :remoteRecordingCapable => Gem.loaded_specs.has_key?('rails'),
24
- :integrationTests => false #TODO
23
+ project: {
24
+ agentVersion: AppMap::VERSION,
25
+ language: 'ruby',
26
+ remoteRecordingCapable: Gem.loaded_specs.has_key?('rails'),
27
+ integrationTests: Service::IntegrationTestPathFinder.count_paths > 0
25
28
  }
26
29
  }
27
30
  }
28
31
 
29
- puts status.to_json
32
+ puts JSON.pretty_generate(status)
30
33
  end
31
34
 
32
35
  private
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'appmap/service/validator/config_validator'
5
+
6
+ module AppMap
7
+ module Command
8
+ module AgentSetup
9
+ ValidateStruct = Struct.new(:config_file)
10
+
11
+ class Validate < ValidateStruct
12
+ def perform
13
+ puts JSON.pretty_generate(config_validator.valid? ? [] : config_validator.violations.map(&:to_h))
14
+ end
15
+
16
+ private
17
+
18
+ def config_validator
19
+ @validator ||= Service::Validator::ConfigValidator.new(config_file)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/appmap/event.rb CHANGED
@@ -119,6 +119,14 @@ module AppMap
119
119
  end
120
120
  end
121
121
  end
122
+
123
+ # An event may be partially constructed, and then completed at a later time. When the event
124
+ # is only partially constructed, it's not ready for serialization to the AppMap file.
125
+ #
126
+ # @return false until the event is fully constructed and available.
127
+ def ready?
128
+ true
129
+ end
122
130
 
123
131
  protected
124
132
 
@@ -240,7 +248,7 @@ module AppMap
240
248
  next_exception = exception
241
249
  exceptions = []
242
250
  while next_exception
243
- exception_backtrace = next_exception.backtrace_locations.try(:[], 0)
251
+ exception_backtrace = AppMap::Util.try(next_exception.backtrace_locations, :[], 0)
244
252
  exceptions << {
245
253
  class: best_class_name(next_exception),
246
254
  message: display_string(next_exception.message),
@@ -71,11 +71,16 @@ module AppMap
71
71
  attr_reader :render_instance
72
72
  # Path to the view template.
73
73
  attr_accessor :path
74
-
74
+ # Indicates when the event is fully constructed.
75
+ attr_accessor :ready
76
+
77
+ alias ready? ready
78
+
75
79
  def initialize(render_instance)
76
80
  super :call
77
81
 
78
82
  AppMap::Event::MethodEvent.build_from_invocation(:call, event: self)
83
+ @ready = false
79
84
  @render_instance = render_instance
80
85
  end
81
86
 
@@ -95,8 +100,7 @@ module AppMap
95
100
  object_id: render_instance.__id__,
96
101
  value: AppMap::Event::MethodEvent.display_string(render_instance)
97
102
  }
98
- h.compact
99
- end
103
+ end.compact
100
104
  end
101
105
  end
102
106
 
@@ -158,7 +162,8 @@ module AppMap
158
162
  end
159
163
 
160
164
  def handle_return(call_event_id, elapsed, return_value, exception)
161
- Array(Thread.current[TEMPLATE_RENDERER]).pop
165
+ template_call = Array(Thread.current[TEMPLATE_RENDERER]).pop
166
+ template_call.ready = true
162
167
 
163
168
  AppMap::Event::MethodReturnIgnoreValue.build_from_invocation(call_event_id, elapsed: elapsed)
164
169
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'appmap/service/validator/config_validator'
4
+
3
5
  module AppMap
4
6
  module Service
5
7
  class ConfigAnalyzer
@@ -7,11 +9,10 @@ module AppMap
7
9
 
8
10
  def initialize(config_file)
9
11
  @config_file = config_file
10
- @config = load_config
11
12
  end
12
13
 
13
14
  def app_name
14
- @config.to_h[:name] if present?
15
+ config_validator.config.to_h['name'] if present?
15
16
  end
16
17
 
17
18
  def present?
@@ -19,16 +20,14 @@ module AppMap
19
20
  end
20
21
 
21
22
  def valid?
22
- present? && @config.to_h.key?(:name) && @config.to_h.key?(:packages)
23
+ config_validator.valid?
23
24
  end
24
25
 
25
26
  private
26
27
 
27
- def load_config
28
- AppMap::Config.load_from_file @config_file if present?
29
- rescue
30
- nil
28
+ def config_validator
29
+ @validator ||= AppMap::Service::Validator::ConfigValidator.new(@config_file)
31
30
  end
32
31
  end
33
32
  end
34
- end
33
+ 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,77 @@
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: {
17
+ program: 'bundle',
18
+ args: %w[exec rspec] + integration_test_paths[:rspec].map { |path| "./#{path}" },
19
+ environment: {
20
+ APPMAP: 'true'
21
+ }
22
+ }
23
+ }
24
+ end
25
+
26
+ if TestFrameworkDetector.minitest_present? && !integration_test_paths[:minitest].empty?
27
+ commands += minitest_commands
28
+ end
29
+ if TestFrameworkDetector.cucumber_present? && !integration_test_paths[:cucumber].empty?
30
+ commands << {
31
+ framework: :cucumber,
32
+ command: {
33
+ program: 'bundle',
34
+ args: %w[exec cucumber],
35
+ environment: { APPMAP: 'true' }
36
+ }
37
+ }
38
+ end
39
+
40
+ commands
41
+ end
42
+
43
+ private
44
+
45
+ def minitest_commands
46
+ if Gem.loaded_specs.has_key?('rails')
47
+ [
48
+ {
49
+ framework: :minitest,
50
+ command: {
51
+ program: 'bundle',
52
+ args: %w[exec rails test] + integration_test_paths[:minitest].map { |path| "./#{path}" },
53
+ environment: { APPMAP: 'true' }
54
+ }
55
+ }
56
+ ]
57
+ else
58
+ integration_test_paths[:minitest].map do |path|
59
+ {
60
+ framework: :minitest,
61
+ command: {
62
+ program: 'bundle',
63
+ args: ['exec', 'ruby', "./#{path}"],
64
+ environment: { APPMAP: 'true' }
65
+ }
66
+ }
67
+ end
68
+ end
69
+ end
70
+
71
+ def integration_test_paths
72
+ @paths ||= Service::IntegrationTestPathFinder.find
73
+ end
74
+ end
75
+ end
76
+ end
77
+ 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
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap/service/validator/violation'
4
+
5
+ module AppMap
6
+ module Service
7
+ module Validator
8
+ class ConfigValidator
9
+ attr_reader :violations
10
+
11
+ def initialize(config_file)
12
+ @config_file = config_file
13
+ @violations = []
14
+ end
15
+
16
+ def config
17
+ parse_config
18
+ end
19
+
20
+ def valid?
21
+ validate_ruby_version
22
+ validate_config_presence
23
+ parse_config
24
+ validate_config_load
25
+ @violations.empty?
26
+ end
27
+
28
+ private
29
+
30
+ def present?
31
+ File.exist?(@config_file)
32
+ end
33
+
34
+ def parse_config
35
+ return unless present?
36
+
37
+ @config_data ||= YAML.load_file(@config_file)
38
+ rescue Psych::SyntaxError => e
39
+ @violations << Violation.error(
40
+ filename: @config_file,
41
+ message: 'AppMap configuration is not valid YAML',
42
+ detailed_message: e.message
43
+ )
44
+ nil
45
+ end
46
+
47
+ def validate_config_load
48
+ return unless @config_data
49
+
50
+ AppMap::Config.load(@config_data)
51
+ rescue StandardError => e
52
+ @violations << Violation.error(
53
+ filename: @config_file,
54
+ message: 'AppMap configuration could not be loaded',
55
+ detailed_message: e.message
56
+ )
57
+ nil
58
+ end
59
+
60
+ def validate_config_presence
61
+ unless present?
62
+ @violations << Violation.error(
63
+ filename: @config_file,
64
+ message: 'AppMap configuration file does not exist'
65
+ )
66
+ end
67
+ end
68
+
69
+ def validate_ruby_version
70
+ unless RUBY_VERSION =~ AppMap::SUPPORTED_RUBY_VERSIONS_REGEX
71
+ @violations << Violation.error(
72
+ message: "AppMap does not support Ruby #{RUBY_VERSION}. " \
73
+ "Supported versions are: #{AppMap::SUPPORTED_RUBY_VERSIONS.join(', ')}."
74
+ )
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppMap
4
+ module Service
5
+ module Validator
6
+ class Violation
7
+ attr_reader :level, :setting, :filename, :message, :detailed_message, :help_urls
8
+
9
+ class << self
10
+ def error(message:, setting: nil, filename: nil, detailed_message: nil, help_urls: nil)
11
+ self.new(
12
+ level: :error,
13
+ message: message,
14
+ setting: setting,
15
+ filename: filename,
16
+ detailed_message: detailed_message,
17
+ help_urls: help_urls
18
+ )
19
+ end
20
+
21
+ def warning(message:, setting: nil, filename: nil, detailed_message: nil, help_urls: nil)
22
+ self.new(
23
+ level: :warning,
24
+ message: message,
25
+ setting: setting,
26
+ filename: filename,
27
+ detailed_message: detailed_message,
28
+ help_urls: help_urls
29
+ )
30
+ end
31
+ end
32
+
33
+ def initialize(level:, message:, setting:, filename:, detailed_message:, help_urls:)
34
+ @level = level
35
+ @setting = setting
36
+ @filename = filename
37
+ @message = message
38
+ @detailed_message = detailed_message
39
+ @help_urls = help_urls
40
+ end
41
+
42
+ def to_h
43
+ instance_variables.each_with_object({}) do |var, hash|
44
+ hash[var.to_s.delete("@")] = self.instance_variable_get(var)
45
+ end.compact
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/appmap/trace.rb CHANGED
@@ -143,12 +143,12 @@ module AppMap
143
143
 
144
144
  # Whether there is an event available for processing.
145
145
  def event?
146
- !@events.empty?
146
+ !@events.empty? && @events.first.ready?
147
147
  end
148
148
 
149
149
  # Gets the next available event, if any.
150
150
  def next_event
151
- @events.shift
151
+ @events.shift if event?
152
152
  end
153
153
  end
154
154
  end
data/lib/appmap/util.rb CHANGED
@@ -183,6 +183,15 @@ module AppMap
183
183
  false
184
184
  end
185
185
 
186
+ # https://github.com/rails/rails/blob/8cd143900978902ed9bbba10b34099a3140de5c6/activesupport/lib/active_support/core_ext/object/try.rb
187
+ def try(obj, *methods)
188
+ return nil if methods.empty?
189
+
190
+ return nil unless obj.respond_to?(methods.first)
191
+
192
+ obj.public_send(*methods)
193
+ end
194
+
186
195
  def startup_message(msg)
187
196
  if defined?(::Rails) && defined?(::Rails.logger) && ::Rails.logger
188
197
  ::Rails.logger.info msg
@@ -3,10 +3,13 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.57.1'
6
+ VERSION = '0.60.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
12
+
10
13
  DEFAULT_APPMAP_DIR = 'tmp/appmap'.freeze
11
14
  DEFAULT_CONFIG_FILE_PATH = 'appmap.yml'.freeze
12
15
  end
@@ -1,2 +1,2 @@
1
- name: -123- %
2
- packages: ~{}~ ''
1
+ name: name
2
+ packages: [1,2,3]
@@ -0,0 +1,3 @@
1
+ name:
2
+ -
3
+ packages: "[]" asd
@@ -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
@@ -51,7 +51,7 @@ describe AppMap::Service::ConfigAnalyzer do
51
51
  end
52
52
 
53
53
  context 'with invalid YAML config' do
54
- let(:config_file) { 'spec/fixtures/config/invalid_config.yml'}
54
+ let(:config_file) { 'spec/fixtures/config/invalid_yaml_config.yml'}
55
55
 
56
56
  describe '.app_name' do
57
57
  it 'returns app name value from config' do
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'appmap/service/validator/violation'
5
+
6
+ describe AppMap::Service::Validator::Violation do
7
+ describe '.error' do
8
+ let(:message) { 'error' }
9
+
10
+ context 'with default parameters' do
11
+ subject { described_class.error(message: :message) }
12
+
13
+ it 'builds an error' do
14
+ expect(subject.level).to be :error
15
+ expect(subject.message).to be :message
16
+ end
17
+ end
18
+
19
+ context 'with default parameters' do
20
+ subject do
21
+ described_class.error(
22
+ message: :message,
23
+ setting: :setting,
24
+ filename: :filename,
25
+ detailed_message: :detailed_message,
26
+ help_urls: :help_urls
27
+ )
28
+ end
29
+
30
+ let(:filename) { 'filename' }
31
+ let(:setting) { 'setting' }
32
+ let(:detailed_message) { 'details' }
33
+ let(:help_urls) { %w[123 456] }
34
+
35
+ it 'builds an error' do
36
+ expect(subject.level).to be :error
37
+ expect(subject.message).to be :message
38
+ expect(subject.setting).to be :setting
39
+ expect(subject.detailed_message).to be :detailed_message
40
+ expect(subject.help_urls).to be :help_urls
41
+ end
42
+ end
43
+
44
+ describe '.warning' do
45
+ let(:message) { 'warning' }
46
+
47
+ context 'with default parameters' do
48
+ subject { described_class.warning(message: :message) }
49
+
50
+ it 'builds an error' do
51
+ expect(subject.level).to be :warning
52
+ expect(subject.message).to be :message
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#to_hash' do
58
+ subject { described_class.warning(message: :message) }
59
+
60
+ let(:message) { 'warning' }
61
+
62
+ it 'returns correct hash' do
63
+ expect(subject.to_h['level']).to be :warning
64
+ expect(subject.to_h['message']).to be :message
65
+ end
66
+ end
67
+ end
68
+ end
@@ -4,24 +4,78 @@
4
4
  require 'test_helper'
5
5
 
6
6
  class AgentSetupInitTest < Minitest::Test
7
- def test_status
7
+ def test_status_gem
8
8
  output = `./exe/appmap-agent-status`
9
9
  assert_equal 0, $CHILD_STATUS.exitstatus
10
10
  expected = {
11
- :properties => {
12
- :config => {
13
- :app => 'AppMap Rubygem',
14
- :present => true,
15
- :valid => true
11
+ test_commands: [],
12
+ properties: {
13
+ config: {
14
+ app: 'AppMap Rubygem',
15
+ present: true,
16
+ valid: true
16
17
  },
17
- :project => {
18
- :agentVersion => AppMap::VERSION,
19
- :language => 'ruby',
20
- :remoteRecordingCapable => false,
21
- :integrationTests => false
18
+ project: {
19
+ agentVersion: AppMap::VERSION,
20
+ language: 'ruby',
21
+ remoteRecordingCapable: false,
22
+ integrationTests: false
22
23
  }
23
24
  }
24
- }.to_json
25
- assert_equal expected, output.strip
25
+ }
26
+ assert_equal JSON.pretty_generate(expected), output.strip
27
+ end
28
+
29
+ def test_status_rails_app
30
+ output = `cd spec/fixtures/rails6_users_app && bundle exec ../../../exe/appmap-agent-status`
31
+ assert_equal 0, $CHILD_STATUS.exitstatus
32
+ expected = {
33
+ test_commands: [
34
+ {
35
+ framework: :rspec,
36
+ command: {
37
+ program: 'bundle',
38
+ args: %w[exec rspec ./spec/controllers],
39
+ environment: {
40
+ APPMAP: 'true'
41
+ }
42
+ }
43
+ },
44
+ {
45
+ framework: :minitest,
46
+ command: {
47
+ program: 'bundle',
48
+ args: %w[exec ruby ./test/controllers],
49
+ environment: {
50
+ APPMAP: 'true'
51
+ }
52
+ }
53
+ },
54
+ {
55
+ framework: :minitest,
56
+ command: {
57
+ program: 'bundle',
58
+ args: %w[exec ruby ./test/integration],
59
+ environment: {
60
+ APPMAP: 'true'
61
+ }
62
+ }
63
+ }
64
+ ],
65
+ properties: {
66
+ config: {
67
+ app: 'rails6_users_app',
68
+ present: true,
69
+ valid: false
70
+ },
71
+ project: {
72
+ agentVersion: AppMap::VERSION,
73
+ language: 'ruby',
74
+ remoteRecordingCapable: false,
75
+ integrationTests: true
76
+ }
77
+ }
78
+ }
79
+ assert_equal JSON.pretty_generate(expected), output.strip
26
80
  end
27
81
  end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'test_helper'
5
+
6
+ class AgentSetupValidateTest < Minitest::Test
7
+ NON_EXISTING_CONFIG_FILENAME = '123.yml'
8
+ INVALID_YAML_CONFIG_FILENAME = 'spec/fixtures/config/invalid_yaml_config.yml'
9
+ INVALID_CONFIG_FILENAME = 'spec/fixtures/config/invalid_config.yml'
10
+
11
+ def test_init_when_config_exists
12
+ output = `./exe/appmap-agent-validate`
13
+ assert_equal 0, $CHILD_STATUS.exitstatus
14
+ assert_equal JSON.pretty_generate([]), output.strip
15
+ end
16
+
17
+ def test_init_with_non_existing_config_file
18
+ output = `./exe/appmap-agent-validate -c #{NON_EXISTING_CONFIG_FILENAME}`
19
+ assert_equal 0, $CHILD_STATUS.exitstatus
20
+ expected = JSON.pretty_generate([
21
+ {
22
+ level: :error,
23
+ filename: NON_EXISTING_CONFIG_FILENAME,
24
+ message: 'AppMap configuration file does not exist'
25
+ }
26
+ ])
27
+ assert_equal expected, output.strip
28
+ end
29
+
30
+ def test_init_with_invalid_YAML
31
+ output = `./exe/appmap-agent-validate -c #{INVALID_YAML_CONFIG_FILENAME}`
32
+ assert_equal 0, $CHILD_STATUS.exitstatus
33
+ expected = JSON.pretty_generate([
34
+ {
35
+ level: :error,
36
+ filename: INVALID_YAML_CONFIG_FILENAME,
37
+ message: 'AppMap configuration is not valid YAML',
38
+ detailed_message: "(#{INVALID_YAML_CONFIG_FILENAME}): " \
39
+ 'did not find expected key while parsing a block mapping at line 1 column 1'
40
+ }
41
+ ])
42
+ assert_equal expected, output.strip
43
+ end
44
+
45
+ def test_init_with_invalid_data_config
46
+ output = `./exe/appmap-agent-validate -c #{INVALID_CONFIG_FILENAME}`
47
+ assert_equal 0, $CHILD_STATUS.exitstatus
48
+ expected = JSON.pretty_generate([
49
+ {
50
+ level: :error,
51
+ filename: INVALID_CONFIG_FILENAME,
52
+ message: 'AppMap configuration could not be loaded',
53
+ detailed_message: "no implicit conversion of String into Integer"
54
+ }
55
+ ])
56
+ assert_equal expected, output.strip
57
+ end
58
+ 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.57.1
4
+ version: 0.60.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-07-02 00:00:00.000000000 Z
11
+ date: 2021-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -296,6 +296,7 @@ email:
296
296
  executables:
297
297
  - appmap-agent-init
298
298
  - appmap-agent-status
299
+ - appmap-agent-validate
299
300
  - appmap-inspect
300
301
  extensions:
301
302
  - ext/appmap/extconf.rb
@@ -317,6 +318,7 @@ files:
317
318
  - Rakefile
318
319
  - appmap.gemspec
319
320
  - appmap.yml
321
+ - config-schema.yml
320
322
  - examples/install.rb
321
323
  - examples/mock_webapp/Gemfile
322
324
  - examples/mock_webapp/appmap.yml
@@ -326,6 +328,7 @@ files:
326
328
  - examples/mock_webapp/lib/mock_webapp/user.rb
327
329
  - exe/appmap-agent-init
328
330
  - exe/appmap-agent-status
331
+ - exe/appmap-agent-validate
329
332
  - exe/appmap-inspect
330
333
  - ext/appmap/appmap.c
331
334
  - ext/appmap/extconf.rb
@@ -334,6 +337,7 @@ files:
334
337
  - lib/appmap/class_map.rb
335
338
  - lib/appmap/command/agent_setup/init.rb
336
339
  - lib/appmap/command/agent_setup/status.rb
340
+ - lib/appmap/command/agent_setup/validate.rb
337
341
  - lib/appmap/command/inspect.rb
338
342
  - lib/appmap/command_error.rb
339
343
  - lib/appmap/config.rb
@@ -356,6 +360,11 @@ files:
356
360
  - lib/appmap/rspec.rb
357
361
  - lib/appmap/service/config_analyzer.rb
358
362
  - lib/appmap/service/guesser.rb
363
+ - lib/appmap/service/integration_test_path_finder.rb
364
+ - lib/appmap/service/test_command_provider.rb
365
+ - lib/appmap/service/test_framework_detector.rb
366
+ - lib/appmap/service/validator/config_validator.rb
367
+ - lib/appmap/service/validator/violation.rb
359
368
  - lib/appmap/swagger.rb
360
369
  - lib/appmap/swagger/configuration.rb
361
370
  - lib/appmap/swagger/markdown_descriptions.rb
@@ -370,6 +379,7 @@ files:
370
379
  - spec/config_spec.rb
371
380
  - spec/fixtures/config/incomplete_config.yml
372
381
  - spec/fixtures/config/invalid_config.yml
382
+ - spec/fixtures/config/invalid_yaml_config.yml
373
383
  - spec/fixtures/config/valid_config.yml
374
384
  - spec/fixtures/hook/.gitignore
375
385
  - spec/fixtures/hook/app/controllers/api/api_keys_controller.rb
@@ -543,6 +553,8 @@ files:
543
553
  - spec/fixtures/rails6_users_app/spec/models/user_spec.rb
544
554
  - spec/fixtures/rails6_users_app/spec/rails_helper.rb
545
555
  - spec/fixtures/rails6_users_app/spec/spec_helper.rb
556
+ - spec/fixtures/rails6_users_app/test/controllers/functional_calc_test.rb
557
+ - spec/fixtures/rails6_users_app/test/integration/integration_calc_test.rb
546
558
  - spec/fixtures/rails6_users_app/users_app/.gitignore
547
559
  - spec/hook_spec.rb
548
560
  - spec/open_spec.rb
@@ -553,11 +565,13 @@ files:
553
565
  - spec/record_sql_rails_pg_spec.rb
554
566
  - spec/remote_recording_spec.rb
555
567
  - spec/service/config_analyzer_spec.rb
568
+ - spec/service/validator/violation_spec.rb
556
569
  - spec/spec_helper.rb
557
570
  - spec/swagger/swagger_spec.rb
558
571
  - spec/util_spec.rb
559
572
  - test/agent_setup_init_test.rb
560
573
  - test/agent_setup_status_test.rb
574
+ - test/agent_setup_validate_test.rb
561
575
  - test/bundle_vendor_test.rb
562
576
  - test/cucumber_test.rb
563
577
  - test/expectations/openssl_test_key_sign1.json