appmap 0.57.1 → 0.60.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: 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