From 96c9e1cb06a593882cda2a6014e91bf6c367b0d2 Mon Sep 17 00:00:00 2001 From: Daniel Parks Date: Sun, 25 Sep 2022 05:53:17 -0700 Subject: [PATCH 1/3] Catch parse failures in `PuppetStrings::Json` tests Previously, the tests for `PuppetStrings::Json` (in json_spec.rb) parsed a variety of code samples and then queried YARD to test the results. If a sample failed to parse, an error might be outputted (see [issue #307][#307]), but no failure was registered by the testing harness. This adds simple checks to verify that the parses actually succeed. Unfortunately, one of the samples currently fails to parse, so this commit introduces a testing error. The subbsequent commit will fix it. [#307]: https://github.com/puppetlabs/puppet-strings/issues/307 --- spec/unit/puppet-strings/json_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/unit/puppet-strings/json_spec.rb b/spec/unit/puppet-strings/json_spec.rb index 614bdaec6..6b2e2a36f 100644 --- a/spec/unit/puppet-strings/json_spec.rb +++ b/spec/unit/puppet-strings/json_spec.rb @@ -7,7 +7,7 @@ describe PuppetStrings::Json do before :each do # Populate the YARD registry with both Puppet and Ruby source - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet) + expect(YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet).enumerator.length).to eq(2) # A simple class. # @todo Do a thing # @note Some note @@ -25,7 +25,7 @@ class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { } SOURCE - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet) if TEST_PUPPET_PLANS + expect(YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet).enumerator.length).to eq(1) if TEST_PUPPET_PLANS # A simple plan. # @param param1 First param. # @param param2 Second param. @@ -35,7 +35,7 @@ class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { SOURCE # Only include Puppet functions for 4.1+ - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet) if TEST_PUPPET_FUNCTIONS + expect(YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet).enumerator.length).to eq(1) if TEST_PUPPET_FUNCTIONS # A simple function. # @param param1 First param. # @param param2 Second param. @@ -46,7 +46,7 @@ class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { SOURCE # Only include Puppet types for 5.0+ - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby) if TEST_PUPPET_DATATYPES + expect(YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby).enumerator.length).to eq(1) if TEST_PUPPET_DATATYPES # Basic Puppet Data Type in Ruby # # @param msg A message parameter @@ -67,7 +67,7 @@ class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { end SOURCE - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :json) + expect(YARD::Parser::SourceParser.parse_string(<<-SOURCE, :json).enumerator.length).to eq(1) { "description": "Allows you to backup your database to local file.", "input_method": "stdin", @@ -92,7 +92,7 @@ class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { } SOURCE - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby) + expect(YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby).enumerator.length).to eq(6) Puppet::Parser::Functions.newfunction(:func3x, doc: <<-DOC An example 3.x function. @param [String] first The first parameter. From 1abe2ba0b6c716d5b3b99ca6085192b7505b49ce Mon Sep 17 00:00:00 2001 From: Daniel Parks Date: Sun, 25 Sep 2022 16:35:42 -0700 Subject: [PATCH 2/3] (#307) Fix plan parsing in JSON spec tests Previously, the parsing code activated task support in Puppet when it detected that it was parsing a file in a plans/ directory. This casued the JSON spec test for plans to fail because it parsed a string, which naturally had no file name to check. This turns on task support (and thus enables parsing plans) whenever the parser starts (assuming that task support is available). This helps avoid surprises to future users who need to parse plans from ruby code, such as in tests. --- lib/puppet-strings/yard/parsers/puppet/parser.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/puppet-strings/yard/parsers/puppet/parser.rb b/lib/puppet-strings/yard/parsers/puppet/parser.rb index 745fd26ed..a8c76b9e7 100644 --- a/lib/puppet-strings/yard/parsers/puppet/parser.rb +++ b/lib/puppet-strings/yard/parsers/puppet/parser.rb @@ -24,13 +24,11 @@ def initialize(source, filename) # rubocop:disable Lint/MissingSuper # @return [void] def parse begin - if @file.to_s.match?(%r{^plans|/plans/}) - if Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') < 0 - log.warn "Skipping #{@file}: Puppet Plans require Puppet 5 or greater." - return - end - Puppet[:tasks] = true if Puppet.settings.include?(:tasks) + if @file.to_s.match?(%r{^plans|/plans/}) && Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') < 0 + log.warn "Skipping #{@file}: Puppet Plans require Puppet 5 or greater." + return end + Puppet[:tasks] = true if Puppet.settings.include?(:tasks) @statements ||= (@visitor.visit(::Puppet::Pops::Parser::Parser.new.parse_string(source)) || []).compact rescue ::Puppet::ParseError => e log.error "Failed to parse #{@file}: #{e.message}" From f14c95e6b87e4bd54bd6e2cdb1caa6a80b301dee Mon Sep 17 00:00:00 2001 From: Daniel Parks Date: Sun, 25 Sep 2022 05:53:48 -0700 Subject: [PATCH 3/3] Add a plan test to parser_spec.rb Previously, none of the examples in parser_spec.rb included a Puppet plan. This adds a plan and verifies that it parses correctly. --- .../yard/parsers/puppet/parser_spec.rb | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb b/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb index a3baa0492..ec4d42616 100644 --- a/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb +++ b/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb @@ -140,6 +140,42 @@ class bar { end end + describe 'parsing puppet plans', if: TEST_PUPPET_PLANS do + # The parsing code actually checks this and sets a global (Puppet[:tasks]). + # Plan parsing will fail if it hasn't yet encountered a file under plans/. + let(:file) { 'plans/test.pp' } + let(:source) { <<~'SOURCE' } + # A simple plan. + # @param param1 First param. + # @param param2 Second param. + # @param param3 Third param. + plan plann(String $param1, $param2, Integer $param3 = 1) { + } + SOURCE + + it 'parses the puppet plan statement' do + spec_subject.parse + expect(spec_subject.enumerator.size).to eq(1) + statement = spec_subject.enumerator.first + expect(statement).to be_a(PuppetStrings::Yard::Parsers::Puppet::PlanStatement) + expect(statement.name).to eq('plann') + expect(statement.source).to eq(source.sub(%r{\A.*?\n([^#])}m, '\1').chomp) + expect(statement.file).to eq(file) + expect(statement.line).to eq(5) + expect(statement.docstring).to eq('A simple plan.') + expect(statement.parameters.size).to eq(3) + expect(statement.parameters[0].name).to eq('param1') + expect(statement.parameters[0].type).to eq('String') + expect(statement.parameters[0].value).to be_nil + expect(statement.parameters[1].name).to eq('param2') + expect(statement.parameters[1].type).to be_nil + expect(statement.parameters[1].value).to be_nil + expect(statement.parameters[2].name).to eq('param3') + expect(statement.parameters[2].type).to eq('Integer') + expect(statement.parameters[2].value).to eq('1') + end + end + describe 'parsing puppet functions', if: TEST_PUPPET_FUNCTIONS do let(:source) do <