1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
#! /usr/bin/env ruby
require 'spec_helper'
require 'puppet/util/rdoc'
describe "RDoc::Parser" do
require 'puppet_spec/files'
include PuppetSpec::Files
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
def write_file(file, content)
FileUtils.mkdir_p(File.dirname(file))
File.open(file, 'w') do |f|
f.puts(content)
end
end
def prepare_manifests_and_modules
modules_and_manifests.each do |key,array|
write_file(*array)
end
end
def file_exists_and_matches_content(file, *content_patterns)
Puppet::FileSystem.exist?(file).should(be_true, "Cannot find #{file}")
content_patterns.each do |pattern|
content = File.read(file)
content.should match(pattern)
end
end
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
around(:each) do |example|
env = Puppet::Node::Environment.create(:doc_test_env, [modules_dir], manifests_dir)
Puppet.override({:environments => Puppet::Environments::Static.new(env), :current_environment => env}) do
example.run
end
end
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
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
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
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
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
|