3
require 'puppet/application/face_base'
6
class Puppet::Application::FaceBase::Basetest < Puppet::Application::FaceBase
9
describe Puppet::Application::FaceBase do
11
app = Puppet::Application::FaceBase::Basetest.new
12
app.command_line.stubs(:subcommand_name).returns('subcommand')
13
Puppet::Util::Log.stubs(:newdestination)
17
describe "#find_global_settings_argument" do
18
it "should not match --ca to --ca-location" do
19
option = mock('ca option', :optparse_args => ["--ca"])
20
Puppet.settings.expects(:each).yields(:ca, option)
22
app.find_global_settings_argument("--ca-location").should be_nil
26
describe "#parse_options" do
28
app.command_line.stubs(:args).returns %w{}
31
describe "with just an action" do
33
# We have to stub Signal.trap to avoid a crazy mess where we take
34
# over signal handling and make it impossible to cancel the test
37
# It would be nice to fix this elsewhere, but it is actually hard to
38
# capture this in rspec 2.5 and all. :( --daniel 2011-04-08
40
app.command_line.stubs(:args).returns %w{foo}
45
it "should set the face based on the type" do
46
app.face.name.should == :basetest
49
it "should find the action" do
51
app.action.name.should == :foo
55
it "should stop if the first thing found is not an action" do
56
app.command_line.stubs(:args).returns %w{banana count_args}
57
expect { app.run }.to exit_with 1
58
@logs.first.message.should =~ /has no 'banana' action/
61
it "should use the default action if not given any arguments" do
62
app.command_line.stubs(:args).returns []
63
action = stub(:options => [], :render_as => nil)
64
Puppet::Face[:basetest, '0.0.1'].expects(:get_default_action).returns(action)
67
app.action.should == action
68
app.arguments.should == [ { } ]
71
it "should use the default action if not given a valid one" do
72
app.command_line.stubs(:args).returns %w{bar}
73
action = stub(:options => [], :render_as => nil)
74
Puppet::Face[:basetest, '0.0.1'].expects(:get_default_action).returns(action)
77
app.action.should == action
78
app.arguments.should == [ 'bar', { } ]
81
it "should have no action if not given a valid one and there is no default action" do
82
app.command_line.stubs(:args).returns %w{bar}
83
Puppet::Face[:basetest, '0.0.1'].expects(:get_default_action).returns(nil)
85
expect { app.run }.to exit_with 1
86
@logs.first.message.should =~ /has no 'bar' action./
89
[%w{something_I_cannot_do},
90
%w{something_I_cannot_do argument}].each do |input|
91
it "should report unknown actions nicely" do
92
app.command_line.stubs(:args).returns input
93
Puppet::Face[:basetest, '0.0.1'].expects(:get_default_action).returns(nil)
95
expect { app.run }.to exit_with 1
96
@logs.first.message.should =~ /has no 'something_I_cannot_do' action/
100
[%w{something_I_cannot_do --unknown-option},
101
%w{something_I_cannot_do argument --unknown-option}].each do |input|
102
it "should report unknown actions even if there are unknown options" do
103
app.command_line.stubs(:args).returns input
104
Puppet::Face[:basetest, '0.0.1'].expects(:get_default_action).returns(nil)
106
expect { app.run }.to exit_with 1
107
@logs.first.message.should =~ /has no 'something_I_cannot_do' action/
111
it "should report a sensible error when options with = fail" do
112
app.command_line.stubs(:args).returns %w{--action=bar foo}
113
expect { app.preinit; app.parse_options }.
114
to raise_error OptionParser::InvalidOption, /invalid option: --action/
117
it "should fail if an action option is before the action" do
118
app.command_line.stubs(:args).returns %w{--action foo}
119
expect { app.preinit; app.parse_options }.
120
to raise_error OptionParser::InvalidOption, /invalid option: --action/
123
it "should fail if an unknown option is before the action" do
124
app.command_line.stubs(:args).returns %w{--bar foo}
125
expect { app.preinit; app.parse_options }.
126
to raise_error OptionParser::InvalidOption, /invalid option: --bar/
129
it "should fail if an unknown option is after the action" do
130
app.command_line.stubs(:args).returns %w{foo --bar}
131
expect { app.preinit; app.parse_options }.
132
to raise_error OptionParser::InvalidOption, /invalid option: --bar/
135
it "should accept --bar as an argument to a mandatory option after action" do
136
app.command_line.stubs(:args).returns %w{foo --mandatory --bar}
139
app.action.name.should == :foo
140
app.options.should == { :mandatory => "--bar" }
143
it "should accept --bar as an argument to a mandatory option before action" do
144
app.command_line.stubs(:args).returns %w{--mandatory --bar foo}
147
app.action.name.should == :foo
148
app.options.should == { :mandatory => "--bar" }
151
it "should not skip when --foo=bar is given" do
152
app.command_line.stubs(:args).returns %w{--mandatory=bar --bar foo}
153
expect { app.preinit; app.parse_options }.
154
to raise_error OptionParser::InvalidOption, /invalid option: --bar/
157
{ "boolean options before" => %w{--trace foo},
158
"boolean options after" => %w{foo --trace}
159
}.each do |name, args|
160
it "should accept global boolean settings #{name} the action" do
161
app.command_line.stubs(:args).returns args
164
Puppet[:trace].should be_true
168
{ "before" => %w{--syslogfacility user1 foo},
169
" after" => %w{foo --syslogfacility user1}
170
}.each do |name, args|
171
it "should accept global settings with arguments #{name} the action" do
172
app.command_line.stubs(:args).returns args
175
Puppet[:syslogfacility].should == "user1"
179
it "should handle application-level options", :'fails_on_ruby_1.9.2' => true do
180
app.command_line.stubs(:args).returns %w{--verbose return_true}
183
app.face.name.should == :basetest
188
it "should remove the action name from the arguments" do
189
app.command_line.stubs(:args).returns %w{--mandatory --bar foo}
193
app.arguments.should == [{ :mandatory => "--bar" }]
196
it "should pass positional arguments" do
197
app.command_line.stubs(:args).returns %w{--mandatory --bar foo bar baz quux}
201
app.arguments.should == ['bar', 'baz', 'quux', { :mandatory => "--bar" }]
207
app.stubs(:puts) # don't dump text to screen.
209
app.face = Puppet::Face[:basetest, '0.0.1']
210
app.action = app.face.get_action(:foo)
211
app.arguments = ["myname", "myarg"]
214
it "should send the specified verb and name to the face" do
215
app.face.expects(:foo).with(*app.arguments)
216
expect { app.main }.to exit_with 0
219
it "should lookup help when it cannot do anything else" do
221
Puppet::Face[:help, :current].expects(:help).with(:basetest)
222
expect { app.main }.to exit_with 1
225
it "should use its render method to render any result" do
226
app.expects(:render).with(app.arguments.length + 1)
227
expect { app.main }.to exit_with 0
231
describe "error reporting" do
233
app.stubs(:puts) # don't dump text to screen.
235
app.render_as = :json
236
app.face = Puppet::Face[:basetest, '0.0.1']
237
app.arguments = [{}] # we always have options in there...
240
it "should exit 0 when the action returns true" do
241
app.action = app.face.get_action :return_true
242
expect { app.main }.to exit_with 0
245
it "should exit 0 when the action returns false" do
246
app.action = app.face.get_action :return_false
247
expect { app.main }.to exit_with 0
250
it "should exit 0 when the action returns nil" do
251
app.action = app.face.get_action :return_nil
252
expect { app.main }.to exit_with 0
255
it "should exit non-0 when the action raises" do
256
app.action = app.face.get_action :return_raise
257
expect { app.main }.not_to exit_with 0
261
describe "#render" do
263
app.face = Puppet::Face[:basetest, '0.0.1']
264
app.action = app.face.get_action(:foo)
267
context "default rendering" do
268
before :each do app.setup end
270
["hello", 1, 1.0].each do |input|
271
it "should just return a #{input.class.name}" do
272
app.render(input).should == input
276
[[1, 2], ["one"], [{ 1 => 1 }]].each do |input|
277
it "should render #{input.class} using JSON" do
278
app.render(input).should == input.to_pson.chomp
282
it "should render a non-trivially-keyed Hash with using JSON" do
283
hash = { [1,2] => 3, [2,3] => 5, [3,4] => 7 }
284
app.render(hash).should == hash.to_pson.chomp
287
it "should render a {String,Numeric}-keyed Hash into a table" do
289
hash = { "one" => 1, "two" => [], "three" => {}, "four" => object,
292
# Gotta love ASCII-betical sort order. Hope your objects are better
293
# structured for display than my test one is. --daniel 2011-04-18
294
app.render(hash).should == <<EOT
297
four #{object.to_pson.chomp}
304
it "should render a hash nicely with a multi-line value" do
305
pending "Moving to PSON rather than PP makes this unsupportable."
307
"number" => { "1" => '1' * 40, "2" => '2' * 40, '3' => '3' * 40 },
308
"text" => { "a" => 'a' * 40, 'b' => 'b' * 40, 'c' => 'c' * 40 }
310
app.render(hash).should == <<EOT
311
number {"1"=>"1111111111111111111111111111111111111111",
312
"2"=>"2222222222222222222222222222222222222222",
313
"3"=>"3333333333333333333333333333333333333333"}
314
text {"a"=>"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
315
"b"=>"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
316
"c"=>"cccccccccccccccccccccccccccccccccccccccc"}
320
it "should invoke the action rendering hook while rendering" do
321
app.action.set_rendering_method_for(:console, proc { |value| "bi-winning!" })
322
app.render("bi-polar?").should == "bi-winning!"
325
it "should render JSON when asked for json" do
326
app.render_as = :json
327
json = app.render({ :one => 1, :two => 2 })
328
json.should =~ /"one":\s*1\b/
329
json.should =~ /"two":\s*2\b/
330
PSON.parse(json).should == { "one" => 1, "two" => 2 }
334
it "should fail early if asked to render an invalid format" do
335
app.command_line.stubs(:args).returns %w{--render-as interpretive-dance return_true}
336
# We shouldn't get here, thanks to the exception, and our expectation on
337
# it, but this helps us fail if that slips up and all. --daniel 2011-04-27
338
Puppet::Face[:help, :current].expects(:help).never
341
expect { app.run }.to exit_with 1
342
}.to have_printed(/I don't know how to render 'interpretive-dance'/)
345
it "should work if asked to render a NetworkHandler format" do
346
app.command_line.stubs(:args).returns %w{count_args a b c --render-as yaml}
348
expect { app.run }.to exit_with 0
349
}.to have_printed(/--- 3/)
352
it "should invoke when_rendering hook 's' when asked to render-as 's'" do
353
app.command_line.stubs(:args).returns %w{with_s_rendering_hook --render-as s}
354
app.action = app.face.get_action(:with_s_rendering_hook)
356
expect { app.run }.to exit_with 0
357
}.to have_printed(/you invoked the 's' rendering hook/)