881c066fadefbc4c944a7742eeb2556a81e67da1
[packages/precise/mcollective.git] / spec / unit / ddl / base_spec.rb
1 #!/usr/bin/env rspec
2
3 require 'spec_helper'
4
5 module MCollective
6   module DDL
7     describe Base do
8       before :each do
9         Cache.delete!(:ddl) rescue nil
10         @ddl = DDL.new("rspec", :agent, false)
11         @ddl.metadata(:name => "name", :description => "description", :author => "author", :license => "license", :version => "version", :url => "url", :timeout => "timeout")
12       end
13
14       describe "#template_for_plugintype" do
15         it "should return the backward compat path for agent ddls" do
16           @ddl.template_for_plugintype.should == "rpc-help.erb"
17         end
18
19         it "should return correct new path for other ddls" do
20           @ddl.instance_variable_set("@plugintype", :data)
21           File.expects(:exists?).with("/etc/mcollective/data-help.erb").returns(true)
22           @ddl.template_for_plugintype.should == "data-help.erb"
23         end
24       end
25
26       describe "#help" do
27         it "should use conventional template paths when none is provided" do
28           File.expects(:read).with("/etc/mcollective/rpc-help.erb").returns("rspec")
29           File.expects(:read).with("/etc/mcollective/metadata-help.erb").returns("rspec")
30           @ddl.help.should == "rspec"
31         end
32
33         it "should use template from help template path when provided template name is not an absolute file path" do
34           File.expects(:read).with("/etc/mcollective/foo").returns("rspec")
35           File.expects(:read).with("/etc/mcollective/metadata-help.erb").returns("rspec")
36           @ddl.help("foo").should == "rspec"
37         end
38
39         it "should use supplied template path when one is provided" do
40           File.expects(:read).with("/foo").returns("rspec")
41           File.expects(:read).with("/etc/mcollective/metadata-help.erb").returns("rspec")
42           @ddl.help("/foo").should == "rspec"
43         end
44
45         it "should correctly execute the template with a valid binding" do
46           @ddl.instance_variable_set("@meta", "meta")
47           @ddl.instance_variable_set("@entities", "actions")
48           File.expects(:read).with("/template").returns("<%= meta %>:<%= entities %>")
49           File.expects(:read).with("/etc/mcollective/metadata-help.erb").returns("rspec")
50           @ddl.help("/template").should == "meta:actions"
51         end
52       end
53
54       describe "#validate_input_arguments" do
55         before :all do
56           Config.instance.stubs(:configured).returns(true)
57           Config.instance.stubs(:libdir).returns([File.join(File.dirname(__FILE__), "../../../plugins")])
58         end
59
60         it "should ensure strings are String" do
61           @ddl.action(:string, :description => "rspec")
62           @ddl.instance_variable_set("@current_entity", :string)
63           @ddl.input(:string, :prompt => "prompt", :description => "descr",
64                      :type => :string, :optional => true, :validation => "",
65                      :maxlength => 1)
66
67           expect {
68             @ddl.validate_input_argument(@ddl.entities[:string][:input], :string, 1)
69           }.to raise_code(:PLMC21, :input => :string, :error => "value should be a string")
70
71           @ddl.validate_input_argument(@ddl.entities[:string][:input], :string, "1")
72         end
73
74         it "should ensure strings are not longer than maxlength" do
75           @ddl.action(:string, :description => "rspec")
76           @ddl.instance_variable_set("@current_entity", :string)
77           @ddl.input(:string, :prompt => "prompt", :description => "descr",
78                      :type => :string, :optional => true, :validation => "",
79                      :maxlength => 1)
80
81           expect {
82             @ddl.validate_input_argument(@ddl.entities[:string][:input], :string, "too long")
83           }.to raise_code(:PLMC21, :input => :string, :error => "Input string is longer than 1 character(s)")
84
85           @ddl.validate_input_argument(@ddl.entities[:string][:input], :string, "1")
86         end
87
88         it "should validate strings using regular expressions" do
89           @ddl.action(:string, :description => "rspec")
90           @ddl.instance_variable_set("@current_entity", :string)
91           @ddl.input(:string, :prompt => "prompt", :description => "descr",
92                      :type => :string, :optional => true, :validation => "^regex$",
93                      :maxlength => 100)
94
95           expect {
96             @ddl.validate_input_argument(@ddl.entities[:string][:input], :string, "doesnt validate")
97           }.to raise_code(:PLMC21, :input => :string, :error => "value should match ^regex$")
98
99           @ddl.validate_input_argument(@ddl.entities[:string][:input], :string, "regex")
100         end
101
102         it "should validate list arguments correctly" do
103           @ddl.action(:list, :description => "rspec")
104           @ddl.instance_variable_set("@current_entity", :list)
105           @ddl.input(:list, :prompt => "prompt", :description => "descr",
106                      :type => :list, :optional => true, :list => [1,2])
107
108           expect {
109             @ddl.validate_input_argument(@ddl.entities[:list][:input], :list, 3)
110           }.to raise_code(:PLMC21, :input => :list, :error => "value should be one of 1, 2")
111
112           @ddl.validate_input_argument(@ddl.entities[:list][:input], :list, 1)
113         end
114
115         it "should validate boolean arguments correctly" do
116           @ddl.action(:bool, :description => "rspec")
117           @ddl.instance_variable_set("@current_entity", :bool)
118           @ddl.input(:bool, :prompt => "prompt", :description => "descr",
119                      :type => :boolean, :optional => true)
120
121           expect {
122             @ddl.validate_input_argument(@ddl.entities[:bool][:input], :bool, 3)
123           }.to raise_code(:PLMC21, :input => :bool, :error => "value should be a boolean")
124
125           @ddl.validate_input_argument(@ddl.entities[:bool][:input], :bool, true)
126           @ddl.validate_input_argument(@ddl.entities[:bool][:input], :bool, false)
127         end
128
129         it "should validate integer arguments correctly" do
130           @ddl.action(:test, :description => "rspec")
131           @ddl.instance_variable_set("@current_entity", :test)
132           @ddl.input(:int, :prompt => "prompt", :description => "descr",
133                      :type => :integer, :optional => true)
134
135           expect {
136             @ddl.validate_input_argument(@ddl.entities[:test][:input], :int, "1")
137           }.to raise_code(:PLMC21, :input => :int, :error => "value should be a integer")
138
139           expect {
140             @ddl.validate_input_argument(@ddl.entities[:test][:input], :int, 1.1)
141           }.to raise_code(:PLMC21, :input => :int, :error => "value should be a integer")
142
143           @ddl.validate_input_argument(@ddl.entities[:test][:input], :int, 1)
144         end
145
146         it "should validate float arguments correctly" do
147           @ddl.action(:test, :description => "rspec")
148           @ddl.instance_variable_set("@current_entity", :test)
149           @ddl.input(:float, :prompt => "prompt", :description => "descr",
150                      :type => :float, :optional => true)
151
152           expect {
153             @ddl.validate_input_argument(@ddl.entities[:test][:input], :float, "1")
154           }.to raise_code(:PLMC21, :input => :float, :error => "value should be a float")
155
156           expect {
157             @ddl.validate_input_argument(@ddl.entities[:test][:input], :float, 1)
158           }.to raise_code(:PLMC21, :input => :float, :error => "value should be a float")
159
160           @ddl.validate_input_argument(@ddl.entities[:test][:input], :float, 1.1)
161         end
162
163         it "should validate number arguments correctly" do
164           @ddl.action(:test, :description => "rspec")
165           @ddl.instance_variable_set("@current_entity", :test)
166           @ddl.input(:number, :prompt => "prompt", :description => "descr",
167                      :type => :number, :optional => true)
168
169           expect {
170             @ddl.validate_input_argument(@ddl.entities[:test][:input], :number, "1")
171           }.to raise_code(:PLMC21, :input => :number, :error => "value should be a number")
172
173           @ddl.validate_input_argument(@ddl.entities[:test][:input], :number, 1)
174           @ddl.validate_input_argument(@ddl.entities[:test][:input], :number, 1.1)
175         end
176       end
177
178       describe "#requires" do
179         it "should only accept hashes as arguments" do
180           expect { @ddl.requires(1) }.to raise_error(/should be a hash/)
181         end
182
183         it "should only accept valid requirement types" do
184           expect { @ddl.requires(:rspec => "1") }.to raise_error(/is not a valid requirement/)
185           @ddl.requires(:mcollective => "1.0.0")
186         end
187
188         it "should save the requirement" do
189           @ddl.requires(:mcollective => "1.0.0")
190
191           @ddl.requirements.should == {:mcollective => "1.0.0"}
192         end
193       end
194
195       describe "#validate_requirements" do
196         it "should fail for older versions of mcollective" do
197           Util.stubs(:mcollective_version).returns("0.1")
198           expect { @ddl.requires(:mcollective => "2.0") }.to raise_error(/requires.+version 2.0/)
199         end
200
201         it "should pass for newer versions of mcollective" do
202           Util.stubs(:mcollective_version).returns("2.0")
203           @ddl.requires(:mcollective => "0.1")
204           @ddl.validate_requirements.should == true
205         end
206
207         it "should bypass checks in development" do
208           Util.stubs(:mcollective_version).returns("@DEVELOPMENT_VERSION@")
209           @ddl.expects(:log_code).with(:PLMC19, anything, :warn)
210           @ddl.requires(:mcollective => "0.1")
211         end
212       end
213
214       describe "#loaddlfile" do
215         it "should raise the correct error when a ddl isnt present" do
216           @ddl.expects(:findddlfile).returns(false)
217           expect { @ddl.loadddlfile }.to raise_error("Can't find DDL for agent plugin 'rspec'")
218         end
219       end
220
221       describe "#findddlfile" do
222         it "should construct the correct ddl file name" do
223           Config.instance.expects(:libdir).returns(["/nonexisting"])
224           File.expects("exist?").with("/nonexisting/mcollective/agent/foo.ddl").returns(false)
225
226           @ddl.findddlfile("foo").should == false
227         end
228
229         it "should check each libdir for a ddl file" do
230           Config.instance.expects(:libdir).returns(["/nonexisting1", "/nonexisting2"])
231           File.expects("exist?").with("/nonexisting1/mcollective/agent/foo.ddl").returns(false)
232           File.expects("exist?").with("/nonexisting2/mcollective/agent/foo.ddl").returns(false)
233
234           @ddl.findddlfile("foo").should == false
235         end
236
237         it "should return the ddl file path if found" do
238           Config.instance.expects(:libdir).returns(["/nonexisting"])
239           File.expects("exist?").with("/nonexisting/mcollective/agent/foo.ddl").returns(true)
240           @ddl.expects(:log_code).with(:PLMC18, anything, :debug, :ddlname => "foo", :ddlfile => "/nonexisting/mcollective/agent/foo.ddl")
241
242           @ddl.findddlfile("foo").should == "/nonexisting/mcollective/agent/foo.ddl"
243         end
244
245         it "should default to the current plugin and type" do
246           Config.instance.expects(:libdir).returns(["/nonexisting"])
247           File.expects("exist?").with("/nonexisting/mcollective/agent/rspec.ddl").returns(true)
248
249           @ddl.findddlfile.should == "/nonexisting/mcollective/agent/rspec.ddl"
250         end
251       end
252
253       describe "#metadata" do
254         it "should ensure minimum parameters are given" do
255           [:name, :description, :author, :license, :version, :url, :timeout].each do |tst|
256             metadata = {:name => "name", :description => "description", :author => "author",
257                         :license => "license", :version => "version", :url => "url", :timeout => "timeout"}
258
259             metadata.delete(tst)
260
261             expect {
262               @ddl.metadata(metadata)
263             }.to raise_error("Metadata needs a :#{tst} property")
264           end
265         end
266
267         it "should should allow arbitrary metadata" do
268           metadata = {:name => "name", :description => "description", :author => "author", :license => "license",
269                       :version => "version", :url => "url", :timeout => "timeout", :foo => "bar"}
270
271           @ddl.metadata(metadata)
272           @ddl.meta.should == metadata
273         end
274       end
275
276       describe "#input" do
277         it "should ensure required properties are set" do
278           @ddl.action(:test, :description => "rspec")
279           @ddl.instance_variable_set("@current_entity", :test)
280
281           [:prompt, :description, :type, :optional].each do |arg|
282             args = {:prompt => "prompt", :description => "descr", :type => "type", :optional => true}
283             args.delete(arg)
284
285             expect {
286               @ddl.input(:test, args)
287             }.to raise_error("Input needs a :#{arg} property")
288           end
289
290           @ddl.input(:test, {:prompt => "prompt", :description => "descr", :type => "type", :optional => true})
291         end
292
293         it "should ensure strings have a validation and maxlength" do
294           @ddl.action(:test, :description => "rspec")
295           @ddl.instance_variable_set("@current_entity", :test)
296
297           expect {
298             @ddl.input(:test, :prompt => "prompt", :description => "descr",
299                        :type => :string, :optional => true)
300           }.to raise_error("Input type :string needs a :validation argument")
301
302           expect {
303             @ddl.input(:test, :prompt => "prompt", :description => "descr",
304                        :type => :string, :optional => true, :validation => 1)
305           }.to raise_error("Input type :string needs a :maxlength argument")
306
307           @ddl.input(:test, :prompt => "prompt", :description => "descr",
308                      :type => :string, :optional => true, :validation => 1, :maxlength => 1)
309         end
310
311         it "should ensure lists have a list argument" do
312           @ddl.action(:test, :description => "rspec")
313           @ddl.instance_variable_set("@current_entity", :test)
314
315           expect {
316             @ddl.input(:test, :prompt => "prompt", :description => "descr",
317                        :type => :list, :optional => true)
318           }.to raise_error("Input type :list needs a :list argument")
319
320           @ddl.input(:test, :prompt => "prompt", :description => "descr",
321                      :type => :list, :optional => true, :list => [])
322         end
323
324         it "should save correct data for a list input" do
325           @ddl.action(:test, :description => "rspec")
326           @ddl.instance_variable_set("@current_entity", :test)
327           @ddl.input(:test, :prompt => "prompt", :description => "descr",
328                      :type => :list, :optional => true, :list => [])
329
330           action = @ddl.action_interface(:test)
331
332           action[:input][:test][:prompt].should == "prompt"
333           action[:input][:test][:description].should == "descr"
334           action[:input][:test][:type].should == :list
335           action[:input][:test][:optional].should == true
336           action[:input][:test][:list].should == []
337         end
338
339         it "should save correct data for a string input" do
340           @ddl.action(:test, :description => "rspec")
341           @ddl.instance_variable_set("@current_entity", :test)
342           @ddl.input(:test, :prompt => "prompt", :description => "descr",
343                      :type => :string, :optional => true, :validation => "",
344                      :maxlength => 1)
345
346           action = @ddl.action_interface(:test)
347
348           action[:input][:test][:prompt].should == "prompt"
349           action[:input][:test][:description].should == "descr"
350           action[:input][:test][:type].should == :string
351           action[:input][:test][:optional].should == true
352           action[:input][:test][:validation].should == ""
353           action[:input][:test][:maxlength].should == 1
354         end
355       end
356
357       describe "#output" do
358         it "should ensure a :description is set" do
359           @ddl.action(:test, :description => "rspec")
360           @ddl.instance_variable_set("@current_entity", :test)
361
362           expect {
363             @ddl.output(:test, {})
364           }.to raise_error("Output test needs a description argument")
365         end
366
367         it "should ensure a :display_as is set" do
368           @ddl.action(:test, :description => "rspec")
369           @ddl.instance_variable_set("@current_entity", :test)
370
371           expect {
372             @ddl.output(:test, {:description => "rspec"})
373           }.to raise_error("Output test needs a display_as argument")
374         end
375
376         it "should save correct data for an output" do
377           @ddl.action(:test, :description => "rspec")
378           @ddl.instance_variable_set("@current_entity", :test)
379
380           @ddl.output(:test, {:description => "rspec", :display_as => "RSpec", :default => "default"})
381
382           action = @ddl.action_interface(:test)
383
384           action[:output][:test][:description].should == "rspec"
385           action[:output][:test][:display_as].should == "RSpec"
386           action[:output][:test][:default].should == "default"
387         end
388
389         it "should set unsupplied defaults to our internal unset representation" do
390           @ddl.action(:test, :description => "rspec")
391           @ddl.instance_variable_set("@current_entity", :test)
392
393           @ddl.output(:test, {:description => "rspec", :display_as => "RSpec"})
394
395           action = @ddl.action_interface(:test)
396
397           action[:output][:test][:default].should == nil
398         end
399       end
400
401     end
402   end
403 end