spec/integration/util/rdoc/parser_spec.rb in puppet-3.3.2 vs spec/integration/util/rdoc/parser_spec.rb in puppet-3.4.0.rc1

- old
+ new

@@ -1,60 +1,261 @@ #! /usr/bin/env ruby require 'spec_helper' +require 'puppet/util/rdoc' -describe "RDoc::Parser", :if => Puppet.features.rdoc1? do +describe "RDoc::Parser" do require 'puppet_spec/files' include PuppetSpec::Files - before :all do - require 'puppet/resource/type_collection' - require 'puppet/util/rdoc/parser' - require 'puppet/util/rdoc' - require 'puppet/util/rdoc/code_objects' - require 'rdoc/options' - require 'rdoc/rdoc' + let(:document_all) { false } + let(:tmp_dir) { tmpdir('rdoc_parser_tmp') } + let(:doc_dir) { File.join(tmp_dir, 'doc') } + let(:manifests_dir) { File.join(tmp_dir, 'manifests') } + let(:modules_dir) { File.join(tmp_dir, 'modules') } + + let(:modules_and_manifests) do + { + :site => [ + File.join(manifests_dir, 'site.pp'), + <<-EOF +# The test class comment +class test { + # The virtual resource comment + @notify { virtual: } + # The a_notify_resource comment + notify { a_notify_resource: + message => "a_notify_resource message" + } +} + +# The includes_another class comment +class includes_another { + include another +} + +# The requires_another class comment +class requires_another { + require another +} + +# node comment +node foo { + include test + $a_var = "var_value" + realize Notify[virtual] + notify { bar: } +} + EOF + ], + :module_readme => [ + File.join(modules_dir, 'a_module', 'README'), + <<-EOF +The a_module README docs. + EOF + ], + :module_init => [ + File.join(modules_dir, 'a_module', 'manifests', 'init.pp'), + <<-EOF +# The a_module class comment +class a_module {} + +class another {} + EOF + ], + :module_type => [ + File.join(modules_dir, 'a_module', 'manifests', 'a_type.pp'), + <<-EOF +# The a_type type comment +define a_module::a_type() {} + EOF + ], + :module_plugin => [ + File.join(modules_dir, 'a_module', 'lib', 'puppet', 'type', 'a_plugin.rb'), + <<-EOF +# The a_plugin type comment +Puppet::Type.newtype(:a_plugin) do + @doc = "Not presented" +end + EOF + ], + :module_function => [ + File.join(modules_dir, 'a_module', 'lib', 'puppet', 'parser', 'a_function.rb'), + <<-EOF +# The a_function function comment +module Puppet::Parser::Functions + newfunction(:a_function, :type => :rvalue) do + return end +end + EOF + ], + :module_fact => [ + File.join(modules_dir, 'a_module', 'lib', 'facter', 'a_fact.rb'), + <<-EOF +# The a_fact fact comment +Facter.add("a_fact") do +end + EOF + ], + } + end - before :each do - tmpdir = tmpfile('rdoc_parser_tmp') - Dir.mkdir(tmpdir) - @parsedfile = File.join(tmpdir, 'init.pp') + def write_file(file, content) + FileUtils.mkdir_p(File.dirname(file)) + File.open(file, 'w') do |f| + f.puts(content) + end + end - File.open(@parsedfile, 'w') do |f| - f.puts '# comment' - f.puts 'class ::test {}' + def prepare_manifests_and_modules + modules_and_manifests.each do |key,array| + write_file(*array) end + end - @top_level = stub_everything 'toplevel', :file_relative_name => @parsedfile - @module = stub_everything 'module' - @puppet_top_level = RDoc::PuppetTopLevel.new(@top_level) - RDoc::PuppetTopLevel.stubs(:new).returns(@puppet_top_level) - @puppet_top_level.expects(:add_module).returns(@module) - @parser = RDoc::Parser.new(@top_level, @parsedfile, nil, Options.instance, RDoc::Stats.new) + def file_exists_and_matches_content(file, *content_patterns) + Puppet::FileSystem::File.exist?(file).should(be_true, "Cannot find #{file}") + content_patterns.each do |pattern| + content = File.read(file) + content.should match(pattern) + end end - after(:each) do - File.unlink(@parsedfile) + def some_file_exists_with_matching_content(glob, *content_patterns) + Dir.glob(glob).select do |f| + contents = File.read(f) + content_patterns.all? { |p| p.match(contents) } + end.should_not(be_empty, "Could not match #{content_patterns} in any of the files found in #{glob}") end - def get_test_class(toplevel) - # toplevel -> main -> test - toplevel.classes[0].classes[0] + before :each do + prepare_manifests_and_modules + Puppet.settings[:document_all] = document_all + Puppet.settings[:modulepath] = modules_dir + Puppet::Util::RDoc.rdoc(doc_dir, [modules_dir, manifests_dir]) end - it "should parse to RDoc data structure" do - @parser.expects(:document_class).with { |n,k,c| n == "::test" and k.is_a?(Puppet::Resource::Type) } - @parser.scan + module RdocTesters + def has_module_rdoc(module_name, *other_test_patterns) + file_exists_and_matches_content(module_path(module_name), /Module:? +#{module_name}/i, *other_test_patterns) + end + + def has_node_rdoc(module_name, node_name, *other_test_patterns) + file_exists_and_matches_content(node_path(module_name, node_name), /#{node_name}/, /node comment/, *other_test_patterns) + end + + def has_defined_type(module_name, type_name) + file_exists_and_matches_content(module_path(module_name), /#{type_name}.*?\(\s*\)/m, "The .*?#{type_name}.*? type comment") + end + + def has_class_rdoc(module_name, class_name, *other_test_patterns) + file_exists_and_matches_content(class_path(module_name, class_name), /#{class_name}.*? class comment/, *other_test_patterns) + end + + def has_plugin_rdoc(module_name, type, name) + file_exists_and_matches_content(plugin_path(module_name, type, name), /The .*?#{name}.*?\s*#{type} comment/m, /Type.*?#{type}/m) + end end - it "should get a PuppetClass for the main class" do - @parser.scan.classes[0].should be_a(RDoc::PuppetClass) + shared_examples_for :an_rdoc_site do + it "documents the __site__ module" do + has_module_rdoc("__site__") + end + + it "documents the __site__::test class" do + has_class_rdoc("__site__", "test") + end + + it "documents the __site__::foo node" do + has_node_rdoc("__site__", "foo") + end + + it "documents the a_module module" do + has_module_rdoc("a_module", /The .*?a_module.*? .*?README.*?docs/m) + end + + it "documents the a_module::a_module class" do + has_class_rdoc("a_module", "a_module") + end + + it "documents the a_module::a_type defined type" do + has_defined_type("a_module", "a_type") + end + + it "documents the a_module::a_plugin type" do + has_plugin_rdoc("a_module", :type, 'a_plugin') + end + + it "documents the a_module::a_function function" do + has_plugin_rdoc("a_module", :function, 'a_function') + end + + it "documents the a_module::a_fact fact" do + has_plugin_rdoc("a_module", :fact, 'a_fact') + end + + it "documents included classes" do + has_class_rdoc("__site__", "includes_another", /Included.*?another/m) + end end - it "should produce a PuppetClass whose name is test" do - get_test_class(@parser.scan).name.should == "test" + shared_examples_for :an_rdoc1_site do + it "documents required classes" do + has_class_rdoc("__site__", "requires_another", /Required Classes.*?another/m) + end + + it "documents realized resources" do + has_node_rdoc("__site__", "foo", /Realized Resources.*?Notify\[virtual\]/m) + end + + it "documents global variables" do + has_node_rdoc("__site__", "foo", /Global Variables.*?a_var.*?=.*?var_value/m) + end + + describe "when document_all is true" do + let(:document_all) { true } + + it "documents virtual resource declarations" do + has_class_rdoc("__site__", "test", /Resources.*?Notify\[virtual\]/m, /The virtual resource comment/) + end + + it "documents resources" do + has_class_rdoc("__site__", "test", /Resources.*?Notify\[a_notify_resource\]/m, /message => "a_notify_resource message"/, /The a_notify_resource comment/) + end + end end - it "should produce a PuppetClass whose comment is 'comment'" do - get_test_class(@parser.scan).comment.should == "comment\n" + describe "rdoc1 support", :if => Puppet.features.rdoc1? do + def module_path(module_name); "#{doc_dir}/classes/#{module_name}.html" end + def node_path(module_name, node_name); "#{doc_dir}/nodes/**/*.html" end + def class_path(module_name, class_name); "#{doc_dir}/classes/#{module_name}/#{class_name}.html" end + def plugin_path(module_name, type, name); "#{doc_dir}/plugins/#{name}.html" end + + include RdocTesters + + def has_node_rdoc(module_name, node_name, *other_test_patterns) + some_file_exists_with_matching_content(node_path(module_name, node_name), /#{node_name}/, /node comment/, *other_test_patterns) + end + + it_behaves_like :an_rdoc_site + it_behaves_like :an_rdoc1_site + + it "references nodes and classes in the __site__ module" do + file_exists_and_matches_content("#{doc_dir}/classes/__site__.html", /Node.*__site__::foo/, /Class.*__site__::test/) + end + + it "references functions, facts, and type plugins in the a_module module" do + file_exists_and_matches_content("#{doc_dir}/classes/a_module.html", /a_function/, /a_fact/, /a_plugin/, /Class.*a_module::a_module/) + end + end + + describe "rdoc2 support", :if => !Puppet.features.rdoc1? do + def module_path(module_name); "#{doc_dir}/#{module_name}.html" end + def node_path(module_name, node_name); "#{doc_dir}/#{module_name}/__nodes__/#{node_name}.html" end + def class_path(module_name, class_name); "#{doc_dir}/#{module_name}/#{class_name}.html" end + def plugin_path(module_name, type, name); "#{doc_dir}/#{module_name}/__#{type}s__.html" end + + include RdocTesters + + it_behaves_like :an_rdoc_site end end