diff options
Diffstat (limited to 'spec/unit/puppet')
42 files changed, 1361 insertions, 118 deletions
diff --git a/spec/unit/puppet/parser/functions/any2array_spec.rb b/spec/unit/puppet/parser/functions/any2array_spec.rb new file mode 100644 index 0000000..b266e84 --- /dev/null +++ b/spec/unit/puppet/parser/functions/any2array_spec.rb @@ -0,0 +1,55 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the any2array function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("any2array").should == "function_any2array" + end + + it "should return an empty array if there is less than 1 argument" do + result = scope.function_any2array([]) + result.should(eq([])) + end + + it "should convert boolean true to [ true ] " do + result = scope.function_any2array([true]) + result.should(eq([true])) + end + + it "should convert one object to [object]" do + result = scope.function_any2array(['one']) + result.should(eq(['one'])) + end + + it "should convert multiple objects to [objects]" do + result = scope.function_any2array(['one', 'two']) + result.should(eq(['one', 'two'])) + end + + it "should return empty array it was called with" do + result = scope.function_any2array([[]]) + result.should(eq([])) + end + + it "should return one-member array it was called with" do + result = scope.function_any2array([['string']]) + result.should(eq(['string'])) + end + + it "should return multi-member array it was called with" do + result = scope.function_any2array([['one', 'two']]) + result.should(eq(['one', 'two'])) + end + + it "should return members of a hash it was called with" do + result = scope.function_any2array([{ 'key' => 'value' }]) + result.should(eq(['key', 'value'])) + end + + it "should return an empty array if it was called with an empty hash" do + result = scope.function_any2array([{ }]) + result.should(eq([])) + end +end diff --git a/spec/unit/puppet/parser/functions/base64_spec.rb b/spec/unit/puppet/parser/functions/base64_spec.rb new file mode 100755 index 0000000..5faa5e6 --- /dev/null +++ b/spec/unit/puppet/parser/functions/base64_spec.rb @@ -0,0 +1,34 @@ +#! /usr/bin/env ruby -S rspec + +require 'spec_helper' + +describe "the base64 function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("base64").should == "function_base64" + end + + it "should raise a ParseError if there are other than 2 arguments" do + expect { scope.function_base64([]) }.to(raise_error(Puppet::ParseError)) + expect { scope.function_base64(["asdf"]) }.to(raise_error(Puppet::ParseError)) + expect { scope.function_base64(["asdf","moo","cow"]) }.to(raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if argument 1 isn't 'encode' or 'decode'" do + expect { scope.function_base64(["bees","astring"]) }.to(raise_error(Puppet::ParseError, /first argument must be one of/)) + end + + it "should raise a ParseError if argument 2 isn't a string" do + expect { scope.function_base64(["encode",["2"]]) }.to(raise_error(Puppet::ParseError, /second argument must be a string/)) + end + + it "should encode a encoded string" do + result = scope.function_base64(["encode",'thestring']) + result.should =~ /\AdGhlc3RyaW5n\n\Z/ + end + it "should decode a base64 encoded string" do + result = scope.function_base64(["decode",'dGhlc3RyaW5n']) + result.should == 'thestring' + end +end diff --git a/spec/unit/puppet/parser/functions/concat_spec.rb b/spec/unit/puppet/parser/functions/concat_spec.rb new file mode 100644 index 0000000..123188b --- /dev/null +++ b/spec/unit/puppet/parser/functions/concat_spec.rb @@ -0,0 +1,15 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the concat function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should raise a ParseError if there is less than 1 arguments" do + lambda { scope.function_concat([]) }.should( raise_error(Puppet::ParseError)) + end + + it "should be able to concat an array" do + result = scope.function_concat([['1','2','3'],['4','5','6']]) + result.should(eq(['1','2','3','4','5','6'])) + end +end diff --git a/spec/unit/puppet/parser/functions/count_spec.rb b/spec/unit/puppet/parser/functions/count_spec.rb new file mode 100644 index 0000000..2453815 --- /dev/null +++ b/spec/unit/puppet/parser/functions/count_spec.rb @@ -0,0 +1,31 @@ +#! /usr/bin/env ruby -S rspec + +require 'spec_helper' + +describe "the count function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("count").should == "function_count" + end + + it "should raise a ArgumentError if there is more than 2 arguments" do + lambda { scope.function_count(['foo', 'bar', 'baz']) }.should( raise_error(ArgumentError)) + end + + it "should be able to count arrays" do + scope.function_count([["1","2","3"]]).should(eq(3)) + end + + it "should be able to count matching elements in arrays" do + scope.function_count([["1", "2", "2"], "2"]).should(eq(2)) + end + + it "should not count nil or empty strings" do + scope.function_count([["foo","bar",nil,""]]).should(eq(2)) + end + + it 'does not count an undefined hash key or an out of bound array index (which are both :undef)' do + expect(scope.function_count([["foo",:undef,:undef]])).to eq(1) + end +end diff --git a/spec/unit/puppet/parser/functions/deep_merge_spec.rb b/spec/unit/puppet/parser/functions/deep_merge_spec.rb new file mode 100644 index 0000000..f134701 --- /dev/null +++ b/spec/unit/puppet/parser/functions/deep_merge_spec.rb @@ -0,0 +1,105 @@ +#! /usr/bin/env ruby -S rspec + +require 'spec_helper' + +describe Puppet::Parser::Functions.function(:deep_merge) do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + describe 'when calling deep_merge from puppet' do + it "should not compile when no arguments are passed" do + pending("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./ + Puppet[:code] = '$x = deep_merge()' + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /wrong number of arguments/) + end + + it "should not compile when 1 argument is passed" do + pending("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./ + Puppet[:code] = "$my_hash={'one' => 1}\n$x = deep_merge($my_hash)" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /wrong number of arguments/) + end + end + + describe 'when calling deep_merge on the scope instance' do + it 'should require all parameters are hashes' do + expect { new_hash = scope.function_deep_merge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/) + expect { new_hash = scope.function_deep_merge([{}, 2])}.to raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) + end + + it 'should accept empty strings as puppet undef' do + expect { new_hash = scope.function_deep_merge([{}, ''])}.not_to raise_error + end + + it 'should be able to deep_merge two hashes' do + new_hash = scope.function_deep_merge([{'one' => '1', 'two' => '1'}, {'two' => '2', 'three' => '2'}]) + new_hash['one'].should == '1' + new_hash['two'].should == '2' + new_hash['three'].should == '2' + end + + it 'should deep_merge multiple hashes' do + hash = scope.function_deep_merge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}]) + hash['one'].should == '3' + end + + it 'should accept empty hashes' do + scope.function_deep_merge([{},{},{}]).should == {} + end + + it 'should deep_merge subhashes' do + hash = scope.function_deep_merge([{'one' => 1}, {'two' => 2, 'three' => { 'four' => 4 } }]) + hash['one'].should == 1 + hash['two'].should == 2 + hash['three'].should == { 'four' => 4 } + end + + it 'should append to subhashes' do + hash = scope.function_deep_merge([{'one' => { 'two' => 2 } }, { 'one' => { 'three' => 3 } }]) + hash['one'].should == { 'two' => 2, 'three' => 3 } + end + + it 'should append to subhashes 2' do + hash = scope.function_deep_merge([{'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }, {'two' => 'dos', 'three' => { 'five' => 5 } }]) + hash['one'].should == 1 + hash['two'].should == 'dos' + hash['three'].should == { 'four' => 4, 'five' => 5 } + end + + it 'should append to subhashes 3' do + hash = scope.function_deep_merge([{ 'key1' => { 'a' => 1, 'b' => 2 }, 'key2' => { 'c' => 3 } }, { 'key1' => { 'b' => 99 } }]) + hash['key1'].should == { 'a' => 1, 'b' => 99 } + hash['key2'].should == { 'c' => 3 } + end + + it 'should not change the original hashes' do + hash1 = {'one' => { 'two' => 2 } } + hash2 = { 'one' => { 'three' => 3 } } + hash = scope.function_deep_merge([hash1, hash2]) + hash1.should == {'one' => { 'two' => 2 } } + hash2.should == { 'one' => { 'three' => 3 } } + hash['one'].should == { 'two' => 2, 'three' => 3 } + end + + it 'should not change the original hashes 2' do + hash1 = {'one' => { 'two' => [1,2] } } + hash2 = { 'one' => { 'three' => 3 } } + hash = scope.function_deep_merge([hash1, hash2]) + hash1.should == {'one' => { 'two' => [1,2] } } + hash2.should == { 'one' => { 'three' => 3 } } + hash['one'].should == { 'two' => [1,2], 'three' => 3 } + end + + it 'should not change the original hashes 3' do + hash1 = {'one' => { 'two' => [1,2, {'two' => 2} ] } } + hash2 = { 'one' => { 'three' => 3 } } + hash = scope.function_deep_merge([hash1, hash2]) + hash1.should == {'one' => { 'two' => [1,2, {'two' => 2}] } } + hash2.should == { 'one' => { 'three' => 3 } } + hash['one'].should == { 'two' => [1,2, {'two' => 2} ], 'three' => 3 } + hash['one']['two'].should == [1,2, {'two' => 2}] + end + end +end diff --git a/spec/unit/puppet/parser/functions/delete_at_spec.rb b/spec/unit/puppet/parser/functions/delete_at_spec.rb index d8d9618..593cf45 100755 --- a/spec/unit/puppet/parser/functions/delete_at_spec.rb +++ b/spec/unit/puppet/parser/functions/delete_at_spec.rb @@ -16,4 +16,10 @@ describe "the delete_at function" do result = scope.function_delete_at([['a','b','c'],1]) result.should(eq(['a','c'])) end + + it "should not change origin array passed as argument" do + origin_array = ['a','b','c','d'] + result = scope.function_delete_at([origin_array, 1]) + origin_array.should(eq(['a','b','c','d'])) + end end diff --git a/spec/unit/puppet/parser/functions/delete_spec.rb b/spec/unit/puppet/parser/functions/delete_spec.rb index 2f29c93..1508a63 100755 --- a/spec/unit/puppet/parser/functions/delete_spec.rb +++ b/spec/unit/puppet/parser/functions/delete_spec.rb @@ -35,4 +35,22 @@ describe "the delete function" do result.should(eq({ 'a' => 1, 'c' => 3 })) end + it "should not change origin array passed as argument" do + origin_array = ['a','b','c','d'] + result = scope.function_delete([origin_array, 'b']) + origin_array.should(eq(['a','b','c','d'])) + end + + it "should not change the origin string passed as argument" do + origin_string = 'foobarbabarz' + result = scope.function_delete([origin_string,'bar']) + origin_string.should(eq('foobarbabarz')) + end + + it "should not change origin hash passed as argument" do + origin_hash = { 'a' => 1, 'b' => 2, 'c' => 3 } + result = scope.function_delete([origin_hash, 'b']) + origin_hash.should(eq({ 'a' => 1, 'b' => 2, 'c' => 3 })) + end + end diff --git a/spec/unit/puppet/parser/functions/delete_undef_values_spec.rb b/spec/unit/puppet/parser/functions/delete_undef_values_spec.rb new file mode 100644 index 0000000..b341d88 --- /dev/null +++ b/spec/unit/puppet/parser/functions/delete_undef_values_spec.rb @@ -0,0 +1,41 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the delete_undef_values function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("delete_undef_values").should == "function_delete_undef_values" + end + + it "should raise a ParseError if there is less than 1 argument" do + lambda { scope.function_delete_undef_values([]) }.should( raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if the argument is not Array nor Hash" do + lambda { scope.function_delete_undef_values(['']) }.should( raise_error(Puppet::ParseError)) + lambda { scope.function_delete_undef_values([nil]) }.should( raise_error(Puppet::ParseError)) + end + + it "should delete all undef items from Array and only these" do + result = scope.function_delete_undef_values([['a',:undef,'c','undef']]) + result.should(eq(['a','c','undef'])) + end + + it "should delete all undef items from Hash and only these" do + result = scope.function_delete_undef_values([{'a'=>'A','b'=>:undef,'c'=>'C','d'=>'undef'}]) + result.should(eq({'a'=>'A','c'=>'C','d'=>'undef'})) + end + + it "should not change origin array passed as argument" do + origin_array = ['a',:undef,'c','undef'] + result = scope.function_delete_undef_values([origin_array]) + origin_array.should(eq(['a',:undef,'c','undef'])) + end + + it "should not change origin hash passed as argument" do + origin_hash = { 'a' => 1, 'b' => :undef, 'c' => 'undef' } + result = scope.function_delete_undef_values([origin_hash]) + origin_hash.should(eq({ 'a' => 1, 'b' => :undef, 'c' => 'undef' })) + end +end diff --git a/spec/unit/puppet/parser/functions/delete_values_spec.rb b/spec/unit/puppet/parser/functions/delete_values_spec.rb new file mode 100644 index 0000000..8d7f231 --- /dev/null +++ b/spec/unit/puppet/parser/functions/delete_values_spec.rb @@ -0,0 +1,36 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the delete_values function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("delete_values").should == "function_delete_values" + end + + it "should raise a ParseError if there are fewer than 2 arguments" do + lambda { scope.function_delete_values([]) }.should( raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if there are greater than 2 arguments" do + lambda { scope.function_delete_values([[], 'foo', 'bar']) }.should( raise_error(Puppet::ParseError)) + end + + it "should raise a TypeError if the argument is not a hash" do + lambda { scope.function_delete_values([1,'bar']) }.should( raise_error(TypeError)) + lambda { scope.function_delete_values(['foo','bar']) }.should( raise_error(TypeError)) + lambda { scope.function_delete_values([[],'bar']) }.should( raise_error(TypeError)) + end + + it "should delete all instances of a value from a hash" do + result = scope.function_delete_values([{ 'a'=>'A', 'b'=>'B', 'B'=>'C', 'd'=>'B' },'B']) + result.should(eq({ 'a'=>'A', 'B'=>'C' })) + end + + it "should not change origin hash passed as argument" do + origin_hash = { 'a' => 1, 'b' => 2, 'c' => 3 } + result = scope.function_delete_values([origin_hash, 2]) + origin_hash.should(eq({ 'a' => 1, 'b' => 2, 'c' => 3 })) + end + +end diff --git a/spec/unit/puppet/parser/functions/difference_spec.rb b/spec/unit/puppet/parser/functions/difference_spec.rb new file mode 100644 index 0000000..9feff09 --- /dev/null +++ b/spec/unit/puppet/parser/functions/difference_spec.rb @@ -0,0 +1,19 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the difference function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("difference").should == "function_difference" + end + + it "should raise a ParseError if there are fewer than 2 arguments" do + lambda { scope.function_difference([]) }.should( raise_error(Puppet::ParseError) ) + end + + it "should return the difference between two arrays" do + result = scope.function_difference([["a","b","c"],["b","c","d"]]) + result.should(eq(["a"])) + end +end diff --git a/spec/unit/puppet/parser/functions/dirname_spec.rb b/spec/unit/puppet/parser/functions/dirname_spec.rb new file mode 100755 index 0000000..fb3b4fe --- /dev/null +++ b/spec/unit/puppet/parser/functions/dirname_spec.rb @@ -0,0 +1,24 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the dirname function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("dirname").should == "function_dirname" + end + + it "should raise a ParseError if there is less than 1 arguments" do + lambda { scope.function_dirname([]) }.should( raise_error(Puppet::ParseError)) + end + + it "should return dirname for an absolute path" do + result = scope.function_dirname(['/path/to/a/file.ext']) + result.should(eq('/path/to/a')) + end + + it "should return dirname for a relative path" do + result = scope.function_dirname(['path/to/a/file.ext']) + result.should(eq('path/to/a')) + end +end diff --git a/spec/unit/puppet/parser/functions/floor_spec.rb b/spec/unit/puppet/parser/functions/floor_spec.rb new file mode 100644 index 0000000..dbc8c77 --- /dev/null +++ b/spec/unit/puppet/parser/functions/floor_spec.rb @@ -0,0 +1,39 @@ +#! /usr/bin/env ruby -S rspec + +require 'spec_helper' + +describe "the floor function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("floor").should == "function_floor" + end + + it "should raise a ParseError if there is less than 1 argument" do + lambda { scope.function_floor([]) }.should( raise_error(Puppet::ParseError, /Wrong number of arguments/)) + end + + it "should should raise a ParseError if input isn't numeric (eg. String)" do + lambda { scope.function_floor(["foo"]) }.should( raise_error(Puppet::ParseError, /Wrong argument type/)) + end + + it "should should raise a ParseError if input isn't numeric (eg. Boolean)" do + lambda { scope.function_floor([true]) }.should( raise_error(Puppet::ParseError, /Wrong argument type/)) + end + + it "should return an integer when a numeric type is passed" do + result = scope.function_floor([12.4]) + result.is_a?(Integer).should(eq(true)) + end + + it "should return the input when an integer is passed" do + result = scope.function_floor([7]) + result.should(eq(7)) + end + + it "should return the largest integer less than or equal to the input" do + result = scope.function_floor([3.8]) + result.should(eq(3)) + end +end + diff --git a/spec/unit/puppet/parser/functions/fqdn_rotate_spec.rb b/spec/unit/puppet/parser/functions/fqdn_rotate_spec.rb index 4eb799d..2577723 100644 --- a/spec/unit/puppet/parser/functions/fqdn_rotate_spec.rb +++ b/spec/unit/puppet/parser/functions/fqdn_rotate_spec.rb @@ -19,7 +19,7 @@ describe "the fqdn_rotate function" do end it "should rotate a string to give the same results for one host" do - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice + scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice scope.function_fqdn_rotate(["abcdefg"]).should eql(scope.function_fqdn_rotate(["abcdefg"])) end diff --git a/spec/unit/puppet/parser/functions/get_module_path_spec.rb b/spec/unit/puppet/parser/functions/get_module_path_spec.rb index e761706..486bef6 100644 --- a/spec/unit/puppet/parser/functions/get_module_path_spec.rb +++ b/spec/unit/puppet/parser/functions/get_module_path_spec.rb @@ -15,11 +15,11 @@ describe Puppet::Parser::Functions.function(:get_module_path) do end it 'should only allow one argument' do - expect { scope.function_get_module_path([]) }.should raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) - expect { scope.function_get_module_path(['1','2','3']) }.should raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) + expect { scope.function_get_module_path([]) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) + expect { scope.function_get_module_path(['1','2','3']) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) end it 'should raise an exception when the module cannot be found' do - expect { scope.function_get_module_path(['foo']) }.should raise_error(Puppet::ParseError, /Could not find module/) + expect { scope.function_get_module_path(['foo']) }.to raise_error(Puppet::ParseError, /Could not find module/) end describe 'when locating a module' do let(:modulepath) { "/tmp/does_not_exist" } diff --git a/spec/unit/puppet/parser/functions/intersection_spec.rb b/spec/unit/puppet/parser/functions/intersection_spec.rb new file mode 100644 index 0000000..fd44f7f --- /dev/null +++ b/spec/unit/puppet/parser/functions/intersection_spec.rb @@ -0,0 +1,19 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the intersection function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("intersection").should == "function_intersection" + end + + it "should raise a ParseError if there are fewer than 2 arguments" do + lambda { scope.function_intersection([]) }.should( raise_error(Puppet::ParseError) ) + end + + it "should return the intersection of two arrays" do + result = scope.function_intersection([["a","b","c"],["b","c","d"]]) + result.should(eq(["b","c"])) + end +end diff --git a/spec/unit/puppet/parser/functions/is_bool_spec.rb b/spec/unit/puppet/parser/functions/is_bool_spec.rb new file mode 100644 index 0000000..c94e83a --- /dev/null +++ b/spec/unit/puppet/parser/functions/is_bool_spec.rb @@ -0,0 +1,44 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the is_bool function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("is_bool").should == "function_is_bool" + end + + it "should raise a ParseError if there is less than 1 arguments" do + lambda { scope.function_is_bool([]) }.should( raise_error(Puppet::ParseError)) + end + + it "should return true if passed a TrueClass" do + result = scope.function_is_bool([true]) + result.should(eq(true)) + end + + it "should return true if passed a FalseClass" do + result = scope.function_is_bool([false]) + result.should(eq(true)) + end + + it "should return false if passed the string 'true'" do + result = scope.function_is_bool(['true']) + result.should(eq(false)) + end + + it "should return false if passed the string 'false'" do + result = scope.function_is_bool(['false']) + result.should(eq(false)) + end + + it "should return false if passed an array" do + result = scope.function_is_bool([["a","b"]]) + result.should(eq(false)) + end + + it "should return false if passed a hash" do + result = scope.function_is_bool([{"a" => "b"}]) + result.should(eq(false)) + end +end diff --git a/spec/unit/puppet/parser/functions/is_function_available.rb b/spec/unit/puppet/parser/functions/is_function_available.rb new file mode 100644 index 0000000..d5669a7 --- /dev/null +++ b/spec/unit/puppet/parser/functions/is_function_available.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the is_function_available function" do + before :all do + Puppet::Parser::Functions.autoloader.loadall + end + + before :each do + @scope = Puppet::Parser::Scope.new + end + + it "should exist" do + Puppet::Parser::Functions.function("is_function_available").should == "function_is_function_available" + end + + it "should raise a ParseError if there is less than 1 arguments" do + lambda { @scope.function_is_function_available([]) }.should( raise_error(Puppet::ParseError)) + end + + it "should return false if a nonexistent function is passed" do + result = @scope.function_is_function_available(['jeff_mccunes_left_sock']) + result.should(eq(false)) + end + + it "should return true if an available function is passed" do + result = @scope.function_is_function_available(['require']) + result.should(eq(true)) + end + +end diff --git a/spec/unit/puppet/parser/functions/is_integer_spec.rb b/spec/unit/puppet/parser/functions/is_integer_spec.rb index 4335795..24141cc 100644 --- a/spec/unit/puppet/parser/functions/is_integer_spec.rb +++ b/spec/unit/puppet/parser/functions/is_integer_spec.rb @@ -17,6 +17,11 @@ describe "the is_integer function" do result.should(eq(true)) end + it "should return true if a negative integer" do + result = scope.function_is_integer(["-7"]) + result.should(eq(true)) + end + it "should return false if a float" do result = scope.function_is_integer(["3.2"]) result.should(eq(false)) @@ -31,4 +36,34 @@ describe "the is_integer function" do result = scope.function_is_integer([3*2]) result.should(eq(true)) end + + it "should return false if an array" do + result = scope.function_is_numeric([["asdf"]]) + result.should(eq(false)) + end + + it "should return false if a hash" do + result = scope.function_is_numeric([{"asdf" => false}]) + result.should(eq(false)) + end + + it "should return false if a boolean" do + result = scope.function_is_numeric([true]) + result.should(eq(false)) + end + + it "should return false if a whitespace is in the string" do + result = scope.function_is_numeric([" -1324"]) + result.should(eq(false)) + end + + it "should return false if it is zero prefixed" do + result = scope.function_is_numeric(["0001234"]) + result.should(eq(false)) + end + + it "should return false if it is wrapped inside an array" do + result = scope.function_is_numeric([[1234]]) + result.should(eq(false)) + end end diff --git a/spec/unit/puppet/parser/functions/is_numeric_spec.rb b/spec/unit/puppet/parser/functions/is_numeric_spec.rb index d7440fb..1df1497 100644 --- a/spec/unit/puppet/parser/functions/is_numeric_spec.rb +++ b/spec/unit/puppet/parser/functions/is_numeric_spec.rb @@ -36,4 +36,84 @@ describe "the is_numeric function" do result = scope.function_is_numeric(["asdf"]) result.should(eq(false)) end + + it "should return false if an array" do + result = scope.function_is_numeric([["asdf"]]) + result.should(eq(false)) + end + + it "should return false if an array of integers" do + result = scope.function_is_numeric([[1,2,3,4]]) + result.should(eq(false)) + end + + it "should return false if a hash" do + result = scope.function_is_numeric([{"asdf" => false}]) + result.should(eq(false)) + end + + it "should return false if a hash with numbers in it" do + result = scope.function_is_numeric([{1 => 2}]) + result.should(eq(false)) + end + + it "should return false if a boolean" do + result = scope.function_is_numeric([true]) + result.should(eq(false)) + end + + it "should return true if a negative float with exponent" do + result = scope.function_is_numeric(["-342.2315e-12"]) + result.should(eq(true)) + end + + it "should return false if a negative integer with whitespaces before/after the dash" do + result = scope.function_is_numeric([" - 751"]) + result.should(eq(false)) + end + +# it "should return true if a hexadecimal" do +# result = scope.function_is_numeric(["0x52F8c"]) +# result.should(eq(true)) +# end +# +# it "should return true if a hexadecimal with uppercase 0X prefix" do +# result = scope.function_is_numeric(["0X52F8c"]) +# result.should(eq(true)) +# end +# +# it "should return false if a hexadecimal without a prefix" do +# result = scope.function_is_numeric(["52F8c"]) +# result.should(eq(false)) +# end +# +# it "should return true if a octal" do +# result = scope.function_is_numeric(["0751"]) +# result.should(eq(true)) +# end +# +# it "should return true if a negative hexadecimal" do +# result = scope.function_is_numeric(["-0x52F8c"]) +# result.should(eq(true)) +# end +# +# it "should return true if a negative octal" do +# result = scope.function_is_numeric(["-0751"]) +# result.should(eq(true)) +# end +# +# it "should return false if a negative octal with whitespaces before/after the dash" do +# result = scope.function_is_numeric([" - 0751"]) +# result.should(eq(false)) +# end +# +# it "should return false if a bad hexadecimal" do +# result = scope.function_is_numeric(["0x23d7g"]) +# result.should(eq(false)) +# end +# +# it "should return false if a bad octal" do +# result = scope.function_is_numeric(["0287"]) +# result.should(eq(false)) +# end end diff --git a/spec/unit/puppet/parser/functions/loadyaml_spec.rb b/spec/unit/puppet/parser/functions/loadyaml_spec.rb new file mode 100644 index 0000000..fe16318 --- /dev/null +++ b/spec/unit/puppet/parser/functions/loadyaml_spec.rb @@ -0,0 +1,25 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the loadyaml function" do + include PuppetlabsSpec::Files + + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("loadyaml").should == "function_loadyaml" + end + + it "should raise a ParseError if there is less than 1 arguments" do + expect { scope.function_loadyaml([]) }.to raise_error(Puppet::ParseError) + end + + it "should convert YAML file to a data structure" do + yaml_file = tmpfilename ('yamlfile') + File.open(yaml_file, 'w') do |fh| + fh.write("---\n aaa: 1\n bbb: 2\n ccc: 3\n ddd: 4\n") + end + result = scope.function_loadyaml([yaml_file]) + result.should == {"aaa" => 1, "bbb" => 2, "ccc" => 3, "ddd" => 4 } + end +end diff --git a/spec/unit/puppet/parser/functions/merge_spec.rb b/spec/unit/puppet/parser/functions/merge_spec.rb index 79079b6..15a5d94 100644 --- a/spec/unit/puppet/parser/functions/merge_spec.rb +++ b/spec/unit/puppet/parser/functions/merge_spec.rb @@ -30,7 +30,7 @@ describe Puppet::Parser::Functions.function(:merge) do end it 'should accept empty strings as puppet undef' do - expect { new_hash = scope.function_merge([{}, ''])}.to raise_error + expect { new_hash = scope.function_merge([{}, ''])}.not_to raise_error end it 'should be able to merge two hashes' do diff --git a/spec/unit/puppet/parser/functions/num2bool_spec.rb b/spec/unit/puppet/parser/functions/num2bool_spec.rb index 640c689..b56196d 100644 --- a/spec/unit/puppet/parser/functions/num2bool_spec.rb +++ b/spec/unit/puppet/parser/functions/num2bool_spec.rb @@ -8,17 +8,60 @@ describe "the num2bool function" do Puppet::Parser::Functions.function("num2bool").should == "function_num2bool" end - it "should raise a ParseError if there is less than 1 arguments" do + it "should raise a ParseError if there are no arguments" do lambda { scope.function_num2bool([]) }.should( raise_error(Puppet::ParseError)) end - it "should return true if 1" do + it "should raise a ParseError if there are more than 1 arguments" do + lambda { scope.function_num2bool(["foo","bar"]) }.should( raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if passed something non-numeric" do + lambda { scope.function_num2bool(["xyzzy"]) }.should( raise_error(Puppet::ParseError)) + end + + it "should return true if passed string 1" do result = scope.function_num2bool(["1"]) result.should(be_true) end - it "should return false if 0" do + it "should return true if passed string 1.5" do + result = scope.function_num2bool(["1.5"]) + result.should(be_true) + end + + it "should return true if passed number 1" do + result = scope.function_num2bool([1]) + result.should(be_true) + end + + it "should return false if passed string 0" do result = scope.function_num2bool(["0"]) result.should(be_false) end + + it "should return false if passed number 0" do + result = scope.function_num2bool([0]) + result.should(be_false) + end + + it "should return false if passed string -1" do + result = scope.function_num2bool(["-1"]) + result.should(be_false) + end + + it "should return false if passed string -1.5" do + result = scope.function_num2bool(["-1.5"]) + result.should(be_false) + end + + it "should return false if passed number -1" do + result = scope.function_num2bool([-1]) + result.should(be_false) + end + + it "should return false if passed float -1.5" do + result = scope.function_num2bool([-1.5]) + result.should(be_false) + end end diff --git a/spec/unit/puppet/parser/functions/pick_default_spec.rb b/spec/unit/puppet/parser/functions/pick_default_spec.rb new file mode 100644 index 0000000..c9235b5 --- /dev/null +++ b/spec/unit/puppet/parser/functions/pick_default_spec.rb @@ -0,0 +1,58 @@ +#!/usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the pick_default function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("pick_default").should == "function_pick_default" + end + + it 'should return the correct value' do + scope.function_pick_default(['first', 'second']).should == 'first' + end + + it 'should return the correct value if the first value is empty' do + scope.function_pick_default(['', 'second']).should == 'second' + end + + it 'should skip empty string values' do + scope.function_pick_default(['', 'first']).should == 'first' + end + + it 'should skip :undef values' do + scope.function_pick_default([:undef, 'first']).should == 'first' + end + + it 'should skip :undefined values' do + scope.function_pick_default([:undefined, 'first']).should == 'first' + end + + it 'should return the empty string if it is the last possibility' do + scope.function_pick_default([:undef, :undefined, '']).should == '' + end + + it 'should return :undef if it is the last possibility' do + scope.function_pick_default(['', :undefined, :undef]).should == :undef + end + + it 'should return :undefined if it is the last possibility' do + scope.function_pick_default([:undef, '', :undefined]).should == :undefined + end + + it 'should return the empty string if it is the only possibility' do + scope.function_pick_default(['']).should == '' + end + + it 'should return :undef if it is the only possibility' do + scope.function_pick_default([:undef]).should == :undef + end + + it 'should return :undefined if it is the only possibility' do + scope.function_pick_default([:undefined]).should == :undefined + end + + it 'should error if no values are passed' do + expect { scope.function_pick_default([]) }.to raise_error(Puppet::Error, /Must receive at least one argument./) + end +end diff --git a/spec/unit/puppet/parser/functions/pick_spec.rb b/spec/unit/puppet/parser/functions/pick_spec.rb index 761db6b..f53fa80 100644..100755 --- a/spec/unit/puppet/parser/functions/pick_spec.rb +++ b/spec/unit/puppet/parser/functions/pick_spec.rb @@ -29,6 +29,6 @@ describe "the pick function" do end it 'should error if no values are passed' do - expect { scope.function_pick([]) }.to raise_error(Puppet::Error, /Must provide non empty value./) + expect { scope.function_pick([]) }.to( raise_error(Puppet::ParseError, "pick(): must receive at least one non empty value")) end end diff --git a/spec/unit/puppet/parser/functions/prefix_spec.rb b/spec/unit/puppet/parser/functions/prefix_spec.rb index 5cf592b..6e8ddc5 100644 --- a/spec/unit/puppet/parser/functions/prefix_spec.rb +++ b/spec/unit/puppet/parser/functions/prefix_spec.rb @@ -4,15 +4,24 @@ require 'spec_helper' describe "the prefix function" do let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - it "should exist" do - Puppet::Parser::Functions.function("prefix").should == "function_prefix" + it "raises a ParseError if there is less than 1 arguments" do + expect { scope.function_prefix([]) }.to raise_error(Puppet::ParseError, /number of arguments/) end - it "should raise a ParseError if there is less than 1 arguments" do - lambda { scope.function_prefix([]) }.should( raise_error(Puppet::ParseError)) + it "raises an error if the first argument is not an array" do + expect { + scope.function_prefix([Object.new]) + }.to raise_error(Puppet::ParseError, /expected first argument to be an Array/) end - it "should return a prefixed array" do + + it "raises an error if the second argument is not a string" do + expect { + scope.function_prefix([['first', 'second'], 42]) + }.to raise_error(Puppet::ParseError, /expected second argument to be a String/) + end + + it "returns a prefixed array" do result = scope.function_prefix([['a','b','c'], 'p']) result.should(eq(['pa','pb','pc'])) end diff --git a/spec/unit/puppet/parser/functions/range_spec.rb b/spec/unit/puppet/parser/functions/range_spec.rb index 42751f4..0e1ad37 100644 --- a/spec/unit/puppet/parser/functions/range_spec.rb +++ b/spec/unit/puppet/parser/functions/range_spec.rb @@ -4,31 +4,67 @@ require 'spec_helper' describe "the range function" do let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - it "should exist" do + it "exists" do Puppet::Parser::Functions.function("range").should == "function_range" end - it "should raise a ParseError if there is less than 1 arguments" do - lambda { scope.function_range([]) }.should( raise_error(Puppet::ParseError)) + it "raises a ParseError if there is less than 1 arguments" do + expect { scope.function_range([]) }.to raise_error Puppet::ParseError, /Wrong number of arguments.*0 for 1/ end - it "should return a letter range" do - result = scope.function_range(["a","d"]) - result.should(eq(['a','b','c','d'])) - end + describe 'with a letter range' do + it "returns a letter range" do + result = scope.function_range(["a","d"]) + result.should eq ['a','b','c','d'] + end + + it "returns a letter range given a step of 1" do + result = scope.function_range(["a","d","1"]) + result.should eq ['a','b','c','d'] + end - it "should return a number range" do - result = scope.function_range(["1","4"]) - result.should(eq([1,2,3,4])) + it "returns a stepped letter range" do + result = scope.function_range(["a","d","2"]) + result.should eq ['a','c'] + end + + it "returns a stepped letter range given a negative step" do + result = scope.function_range(["a","d","-2"]) + result.should eq ['a','c'] + end end - it "should work with padded hostname like strings" do - expected = ("host01".."host10").to_a - scope.function_range(["host01","host10"]).should eq expected + describe 'with a number range' do + it "returns a number range" do + result = scope.function_range(["1","4"]) + result.should eq [1,2,3,4] + end + + it "returns a number range given a step of 1" do + result = scope.function_range(["1","4","1"]) + result.should eq [1,2,3,4] + end + + it "returns a stepped number range" do + result = scope.function_range(["1","4","2"]) + result.should eq [1,3] + end + + it "returns a stepped number range given a negative step" do + result = scope.function_range(["1","4","-2"]) + result.should eq [1,3] + end end - it "should coerce zero padded digits to integers" do - expected = (0..10).to_a - scope.function_range(["00", "10"]).should eq expected + describe 'with a numeric-like string range' do + it "works with padded hostname like strings" do + expected = ("host01".."host10").to_a + scope.function_range(["host01","host10"]).should eq expected + end + + it "coerces zero padded digits to integers" do + expected = (0..10).to_a + scope.function_range(["00", "10"]).should eq expected + end end end diff --git a/spec/unit/puppet/parser/functions/str2bool_spec.rb b/spec/unit/puppet/parser/functions/str2bool_spec.rb index ef6350f..73c09c7 100644 --- a/spec/unit/puppet/parser/functions/str2bool_spec.rb +++ b/spec/unit/puppet/parser/functions/str2bool_spec.rb @@ -21,7 +21,7 @@ describe "the str2bool function" do result = scope.function_str2bool(["undef"]) result.should(eq(false)) end - + it "should return the boolean it was called with" do result = scope.function_str2bool([true]) result.should(eq(true)) diff --git a/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb b/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb index a692c31..df8fb8e 100644 --- a/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb +++ b/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb @@ -9,11 +9,11 @@ describe "the str2saltedsha512 function" do end it "should raise a ParseError if there is less than 1 argument" do - expect { scope.function_str2saltedsha512([]) }.should( raise_error(Puppet::ParseError) ) + expect { scope.function_str2saltedsha512([]) }.to( raise_error(Puppet::ParseError) ) end it "should raise a ParseError if there is more than 1 argument" do - expect { scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.should( raise_error(Puppet::ParseError) ) + expect { scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.to( raise_error(Puppet::ParseError) ) end it "should return a salted-sha512 password hash 136 characters in length" do @@ -22,7 +22,7 @@ describe "the str2saltedsha512 function" do end it "should raise an error if you pass a non-string password" do - expect { scope.function_str2saltedsha512([1234]) }.should( raise_error(Puppet::ParseError) ) + expect { scope.function_str2saltedsha512([1234]) }.to( raise_error(Puppet::ParseError) ) end it "should generate a valid password" do diff --git a/spec/unit/puppet/parser/functions/suffix_spec.rb b/spec/unit/puppet/parser/functions/suffix_spec.rb new file mode 100644 index 0000000..89ba3b8 --- /dev/null +++ b/spec/unit/puppet/parser/functions/suffix_spec.rb @@ -0,0 +1,27 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the suffix function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "raises a ParseError if there is less than 1 arguments" do + expect { scope.function_suffix([]) }.to raise_error(Puppet::ParseError, /number of arguments/) + end + + it "raises an error if the first argument is not an array" do + expect { + scope.function_suffix([Object.new]) + }.to raise_error(Puppet::ParseError, /expected first argument to be an Array/) + end + + it "raises an error if the second argument is not a string" do + expect { + scope.function_suffix([['first', 'second'], 42]) + }.to raise_error(Puppet::ParseError, /expected second argument to be a String/) + end + + it "returns a suffixed array" do + result = scope.function_suffix([['a','b','c'], 'p']) + result.should(eq(['ap','bp','cp'])) + end +end diff --git a/spec/unit/puppet/parser/functions/union_spec.rb b/spec/unit/puppet/parser/functions/union_spec.rb new file mode 100644 index 0000000..0d282ca --- /dev/null +++ b/spec/unit/puppet/parser/functions/union_spec.rb @@ -0,0 +1,19 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the union function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + Puppet::Parser::Functions.function("union").should == "function_union" + end + + it "should raise a ParseError if there are fewer than 2 arguments" do + lambda { scope.function_union([]) }.should( raise_error(Puppet::ParseError) ) + end + + it "should join two arrays together" do + result = scope.function_union([["a","b","c"],["b","c","d"]]) + result.should(eq(["a","b","c","d"])) + end +end diff --git a/spec/unit/puppet/parser/functions/uriescape_spec.rb b/spec/unit/puppet/parser/functions/uriescape_spec.rb index 371de46..7211c88 100644 --- a/spec/unit/puppet/parser/functions/uriescape_spec.rb +++ b/spec/unit/puppet/parser/functions/uriescape_spec.rb @@ -13,8 +13,8 @@ describe "the uriescape function" do end it "should uriescape a string" do - result = scope.function_uriescape([":/?#[]@!$&'()*+,;= "]) - result.should(eq('%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D%20')) + result = scope.function_uriescape([":/?#[]@!$&'()*+,;= \"{}"]) + result.should(eq(':/?%23[]@!$&\'()*+,;=%20%22%7B%7D')) end it "should do nothing if a string is already safe" do diff --git a/spec/unit/puppet/parser/functions/validate_array_spec.rb b/spec/unit/puppet/parser/functions/validate_array_spec.rb index 8eee72a..4b31cfd 100644 --- a/spec/unit/puppet/parser/functions/validate_array_spec.rb +++ b/spec/unit/puppet/parser/functions/validate_array_spec.rb @@ -9,12 +9,12 @@ describe Puppet::Parser::Functions.function(:validate_array) do %w{ true false }.each do |the_string| it "should not compile when #{the_string} is a string" do Puppet[:code] = "validate_array('#{the_string}')" - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/) end it "should not compile when #{the_string} is a bare word" do Puppet[:code] = "validate_array(#{the_string})" - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/) end end @@ -32,7 +32,7 @@ describe Puppet::Parser::Functions.function(:validate_array) do $foo = undef validate_array($foo) ENDofPUPPETcode - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/) end end end diff --git a/spec/unit/puppet/parser/functions/validate_augeas_spec.rb b/spec/unit/puppet/parser/functions/validate_augeas_spec.rb new file mode 100644 index 0000000..ab5c140 --- /dev/null +++ b/spec/unit/puppet/parser/functions/validate_augeas_spec.rb @@ -0,0 +1,102 @@ +require 'spec_helper' + +describe Puppet::Parser::Functions.function(:validate_augeas), :if => Puppet.features.augeas? do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + # The subject of these examplres is the method itself. + subject do + # This makes sure the function is loaded within each test + function_name = Puppet::Parser::Functions.function(:validate_augeas) + scope.method(function_name) + end + + context 'Using Puppet::Parser::Scope.new' do + + describe 'Garbage inputs' do + inputs = [ + [ nil ], + [ [ nil ] ], + [ { 'foo' => 'bar' } ], + [ { } ], + [ '' ], + [ "one", "one", "MSG to User", "4th arg" ], + ] + + inputs.each do |input| + it "validate_augeas(#{input.inspect}) should fail" do + expect { subject.call [input] }.to raise_error Puppet::ParseError + end + end + end + + describe 'Valid inputs' do + inputs = [ + [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns' ], + [ "proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns'], + ] + + inputs.each do |input| + it "validate_augeas(#{input.inspect}) should not fail" do + expect { subject.call input }.not_to raise_error + end + end + end + + describe "Valid inputs which should raise an exception without a message" do + # The intent here is to make sure valid inputs raise exceptions when they + # don't specify an error message to display. This is the behvior in + # 2.2.x and prior. + inputs = [ + [ "root:x:0:0:root\n", 'Passwd.lns' ], + [ "127.0.1.1\n", 'Hosts.lns' ], + ] + + inputs.each do |input| + it "validate_augeas(#{input.inspect}) should fail" do + expect { subject.call input }.to raise_error /validate_augeas.*?matched less than it should/ + end + end + end + + describe "Nicer Error Messages" do + # The intent here is to make sure the function returns the 3rd argument + # in the exception thrown + inputs = [ + [ "root:x:0:0:root\n", 'Passwd.lns', [], 'Failed to validate passwd content' ], + [ "127.0.1.1\n", 'Hosts.lns', [], 'Wrong hosts content' ], + ] + + inputs.each do |input| + it "validate_augeas(#{input.inspect}) should fail" do + expect { subject.call input }.to raise_error /#{input[2]}/ + end + end + end + + describe "Passing simple unit tests" do + inputs = [ + [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']], + [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']], + ] + + inputs.each do |input| + it "validate_augeas(#{input.inspect}) should fail" do + expect { subject.call input }.not_to raise_error + end + end + end + + describe "Failing simple unit tests" do + inputs = [ + [ "foobar:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']], + [ "root:x:0:0:root:/root:/bin/sh\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']], + ] + + inputs.each do |input| + it "validate_augeas(#{input.inspect}) should fail" do + expect { subject.call input }.to raise_error /testing path/ + end + end + end + end +end diff --git a/spec/unit/puppet/parser/functions/validate_bool_spec.rb b/spec/unit/puppet/parser/functions/validate_bool_spec.rb index 31ab8fb..261fb23 100644 --- a/spec/unit/puppet/parser/functions/validate_bool_spec.rb +++ b/spec/unit/puppet/parser/functions/validate_bool_spec.rb @@ -10,7 +10,7 @@ describe Puppet::Parser::Functions.function(:validate_bool) do it "should not compile when #{the_string} is a string" do Puppet[:code] = "validate_bool('#{the_string}')" - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/) end it "should compile when #{the_string} is a bare word" do @@ -22,12 +22,12 @@ describe Puppet::Parser::Functions.function(:validate_bool) do it "should not compile when an arbitrary string is passed" do Puppet[:code] = 'validate_bool("jeff and dan are awesome")' - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/) end it "should not compile when no arguments are passed" do Puppet[:code] = 'validate_bool()' - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /wrong number of arguments/) end it "should compile when multiple boolean arguments are passed" do @@ -45,7 +45,7 @@ describe Puppet::Parser::Functions.function(:validate_bool) do $bar = false validate_bool($foo, $bar, true, false, 'jeff') ENDofPUPPETcode - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/) end end end diff --git a/spec/unit/puppet/parser/functions/validate_cmd_spec.rb b/spec/unit/puppet/parser/functions/validate_cmd_spec.rb new file mode 100644 index 0000000..a86cb01 --- /dev/null +++ b/spec/unit/puppet/parser/functions/validate_cmd_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +TESTEXE = File.exists?('/usr/bin/test') ? '/usr/bin/test' : '/bin/test' +TOUCHEXE = File.exists?('/usr/bin/touch') ? '/usr/bin/touch' : '/bin/touch' + +describe Puppet::Parser::Functions.function(:validate_cmd) do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + subject do + function_name = Puppet::Parser::Functions.function(:validate_cmd) + scope.method(function_name) + end + + describe "with an explicit failure message" do + it "prints the failure message on error" do + expect { + subject.call ['', '/bin/false', 'failure message!'] + }.to raise_error Puppet::ParseError, /failure message!/ + end + end + + describe "on validation failure" do + it "includes the command error output" do + expect { + subject.call ['', "#{TOUCHEXE} /cant/touch/this"] + }.to raise_error Puppet::ParseError, /(cannot touch|o such file or)/ + end + + it "includes the command return value" do + expect { + subject.call ['', '/cant/run/this'] + }.to raise_error Puppet::ParseError, /returned 1\b/ + end + end + + describe "when performing actual validation" do + it "can positively validate file content" do + expect { subject.call ["non-empty", "#{TESTEXE} -s"] }.to_not raise_error + end + + it "can negatively validate file content" do + expect { + subject.call ["", "#{TESTEXE} -s"] + }.to raise_error Puppet::ParseError, /failed to validate.*test -s/ + end + end +end diff --git a/spec/unit/puppet/parser/functions/validate_hash_spec.rb b/spec/unit/puppet/parser/functions/validate_hash_spec.rb index f63db1d..a0c35c2 100644 --- a/spec/unit/puppet/parser/functions/validate_hash_spec.rb +++ b/spec/unit/puppet/parser/functions/validate_hash_spec.rb @@ -11,12 +11,12 @@ describe Puppet::Parser::Functions.function(:validate_hash) do it "should not compile when #{the_string} is a string" do Puppet[:code] = "validate_hash('#{the_string}')" - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/) end it "should not compile when #{the_string} is a bare word" do Puppet[:code] = "validate_hash(#{the_string})" - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/) end end @@ -35,10 +35,9 @@ describe Puppet::Parser::Functions.function(:validate_hash) do $foo = undef validate_hash($foo) ENDofPUPPETcode - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/) end end end - diff --git a/spec/unit/puppet/parser/functions/validate_ipv4_address_spec.rb b/spec/unit/puppet/parser/functions/validate_ipv4_address_spec.rb new file mode 100644 index 0000000..85536d3 --- /dev/null +++ b/spec/unit/puppet/parser/functions/validate_ipv4_address_spec.rb @@ -0,0 +1,64 @@ +#! /usr/bin/env/ruby -S rspec + +require "spec_helper" + +describe Puppet::Parser::Functions.function(:validate_ipv4_address) do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + describe "when calling validate_ipv4_address from puppet" do + describe "when given IPv4 address strings" do + it "should compile with one argument" do + Puppet[:code] = "validate_ipv4_address('1.2.3.4')" + scope.compiler.compile + end + + it "should compile with multiple arguments" do + Puppet[:code] = "validate_ipv4_address('1.2.3.4', '5.6.7.8')" + scope.compiler.compile + end + end + + describe "when given an IPv6 address" do + it "should not compile" do + Puppet[:code] = "validate_ipv4_address('3ffe:505')" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /not a valid IPv4 address/) + end + end + + describe "when given other strings" do + it "should not compile" do + Puppet[:code] = "validate_ipv4_address('hello', 'world')" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /not a valid IPv4 address/) + end + end + + describe "when given numbers" do + it "should not compile" do + Puppet[:code] = "validate_ipv4_address(1, 2)" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /is not a valid IPv4 address/) + end + end + + describe "when given booleans" do + it "should not compile" do + Puppet[:code] = "validate_ipv4_address(true, false)" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /is not a string/) + end + end + + it "should not compile when no arguments are passed" do + Puppet[:code] = "validate_ipv4_address()" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /wrong number of arguments/) + end + end +end diff --git a/spec/unit/puppet/parser/functions/validate_ipv6_address_spec.rb b/spec/unit/puppet/parser/functions/validate_ipv6_address_spec.rb new file mode 100644 index 0000000..1fe5304 --- /dev/null +++ b/spec/unit/puppet/parser/functions/validate_ipv6_address_spec.rb @@ -0,0 +1,67 @@ +#! /usr/bin/env/ruby -S rspec + +require "spec_helper" + +describe Puppet::Parser::Functions.function(:validate_ipv6_address) do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + describe "when calling validate_ipv6_address from puppet" do + describe "when given IPv6 address strings" do + it "should compile with one argument" do + Puppet[:code] = "validate_ipv6_address('3ffe:0505:0002::')" + scope.compiler.compile + end + + it "should compile with multiple arguments" do + Puppet[:code] = "validate_ipv6_address('3ffe:0505:0002::', '3ffe:0505:0001::')" + scope.compiler.compile + end + end + + describe "when given an ipv4 address" do + it "should not compile" do + Puppet[:code] = "validate_ipv6_address('1.2.3.4')" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/) + end + end + + describe "when given other strings" do + it "should not compile" do + Puppet[:code] = "validate_ipv6_address('hello', 'world')" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/) + end + end + + # 1.8.7 is EOL'd and also absolutely insane about ipv6 + unless RUBY_VERSION == '1.8.7' + describe "when given numbers" do + it "should not compile" do + Puppet[:code] = "validate_ipv6_address(1, 2)" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/) + end + end + end + + describe "when given booleans" do + it "should not compile" do + Puppet[:code] = "validate_ipv6_address(true, false)" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /is not a string/) + end + end + + it "should not compile when no arguments are passed" do + Puppet[:code] = "validate_ipv6_address()" + expect { + scope.compiler.compile + }.to raise_error(Puppet::ParseError, /wrong number of arguments/) + end + end +end diff --git a/spec/unit/puppet/parser/functions/validate_slength_spec.rb b/spec/unit/puppet/parser/functions/validate_slength_spec.rb index eccf908..851835f 100755 --- a/spec/unit/puppet/parser/functions/validate_slength_spec.rb +++ b/spec/unit/puppet/parser/functions/validate_slength_spec.rb @@ -9,40 +9,59 @@ describe "the validate_slength function" do Puppet::Parser::Functions.function("validate_slength").should == "function_validate_slength" end - it "should raise a ParseError if there is less than 2 arguments" do - expect { scope.function_validate_slength([]) }.to(raise_error(Puppet::ParseError)) - expect { scope.function_validate_slength(["asdf"]) }.to(raise_error(Puppet::ParseError)) - end + describe "validating the input argument types" do + it "raises an error if there are less than two arguments" do + expect { scope.function_validate_slength([]) }.to raise_error Puppet::ParseError, /Wrong number of arguments/ + end - it "should raise a ParseError if argument 2 doesn't convert to a fixnum" do - expect { scope.function_validate_slength(["moo",["2"]]) }.to(raise_error(Puppet::ParseError, /Couldn't convert whatever you passed/)) - end + it "raises an error if there are more than three arguments" do + expect { scope.function_validate_slength(['input', 1, 2, 3]) }.to raise_error Puppet::ParseError, /Wrong number of arguments/ + end - it "should raise a ParseError if argument 2 converted, but to 0, e.g. a string" do - expect { scope.function_validate_slength(["moo","monkey"]) }.to(raise_error(Puppet::ParseError, /please pass a positive number as max_length/)) - end + it "raises an error if the first argument is not a string" do + expect { scope.function_validate_slength([Object.new, 2, 1]) }.to raise_error Puppet::ParseError, /Expected first argument.*got .*Object/ + end - it "should raise a ParseError if argument 2 converted, but to 0" do - expect { scope.function_validate_slength(["moo","0"]) }.to(raise_error(Puppet::ParseError, /please pass a positive number as max_length/)) - end + it "raises an error if the second argument cannot be cast to an Integer" do + expect { scope.function_validate_slength(['input', Object.new]) }.to raise_error Puppet::ParseError, /Expected second argument.*got .*Object/ + end - it "should fail if string greater then size" do - expect { scope.function_validate_slength(["test", 2]) }.to(raise_error(Puppet::ParseError, /It should have been less than or equal to/)) - end + it "raises an error if the third argument cannot be cast to an Integer" do + expect { scope.function_validate_slength(['input', 1, Object.new]) }.to raise_error Puppet::ParseError, /Expected third argument.*got .*Object/ + end - it "should fail if you pass an array of something other than strings" do - expect { scope.function_validate_slength([["moo",["moo"],Hash.new["moo" => 7]], 7]) }.to(raise_error(Puppet::ParseError, /is not a string, it's a/)) + it "raises an error if the second argument is smaller than the third argument" do + expect { scope.function_validate_slength(['input', 1, 2]) }.to raise_error Puppet::ParseError, /Expected second argument to be larger than third argument/ + end end - it "should fail if you pass something other than a string or array" do - expect { scope.function_validate_slength([Hash.new["moo" => "7"],6]) }.to(raise_error(Puppet::ParseError), /please pass a string, or an array of strings/) - end + describe "validating the input string length" do + describe "when the input is a string" do + it "fails validation if the string is larger than the max length" do + expect { scope.function_validate_slength(['input', 1]) }.to raise_error Puppet::ParseError, /Expected length .* between 0 and 1, was 5/ + end - it "should not fail if string is smaller or equal to size" do - expect { scope.function_validate_slength(["test", 5]) }.to_not(raise_error(Puppet::ParseError)) - end + it "fails validation if the string is less than the min length" do + expect { scope.function_validate_slength(['input', 10, 6]) }.to raise_error Puppet::ParseError, /Expected length .* between 6 and 10, was 5/ + end + + it "doesn't raise an error if the string is under the max length" do + scope.function_validate_slength(['input', 10]) + end + + it "doesn't raise an error if the string is equal to the max length" do + scope.function_validate_slength(['input', 5]) + end + + it "doesn't raise an error if the string is equal to the min length" do + scope.function_validate_slength(['input', 10, 5]) + end + end - it "should not fail if array of string is are all smaller or equal to size" do - expect { scope.function_validate_slength([["moo","foo","bar"], 5]) }.to_not(raise_error(Puppet::ParseError)) + describe "when the input is an array" do + it "fails validation if one of the array elements is not a string" do + expect { scope.function_validate_slength([["a", "b", Object.new], 2]) }.to raise_error Puppet::ParseError, /Expected element at array position 2 .*String, got .*Object/ + end + end end end diff --git a/spec/unit/puppet/parser/functions/validate_string_spec.rb b/spec/unit/puppet/parser/functions/validate_string_spec.rb index f40bf2a..3b4fb3e 100644 --- a/spec/unit/puppet/parser/functions/validate_string_spec.rb +++ b/spec/unit/puppet/parser/functions/validate_string_spec.rb @@ -29,7 +29,7 @@ describe Puppet::Parser::Functions.function(:validate_string) do it "should not compile when #{the_string} is a bare word" do Puppet[:code] = "validate_string(#{the_string})" - expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a string/) + expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a string/) end end @@ -58,4 +58,3 @@ describe Puppet::Parser::Functions.function(:validate_string) do end end end - diff --git a/spec/unit/puppet/provider/file_line/ruby_spec.rb b/spec/unit/puppet/provider/file_line/ruby_spec.rb index 50f5840..c356bd2 100644 --- a/spec/unit/puppet/provider/file_line/ruby_spec.rb +++ b/spec/unit/puppet/provider/file_line/ruby_spec.rb @@ -3,33 +3,36 @@ require 'tempfile' provider_class = Puppet::Type.type(:file_line).provider(:ruby) describe provider_class do context "when adding" do - before :each do - # TODO: these should be ported over to use the PuppetLabs spec_helper - # file fixtures once the following pull request has been merged: - # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files + let :tmpfile do tmp = Tempfile.new('tmp') - @tmpfile = tmp.path + path = tmp.path tmp.close! - @resource = Puppet::Type::File_line.new( - {:name => 'foo', :path => @tmpfile, :line => 'foo'} + path + end + let :resource do + Puppet::Type::File_line.new( + {:name => 'foo', :path => tmpfile, :line => 'foo'} ) - @provider = provider_class.new(@resource) end + let :provider do + provider_class.new(resource) + end + it 'should detect if the line exists in the file' do - File.open(@tmpfile, 'w') do |fh| + File.open(tmpfile, 'w') do |fh| fh.write('foo') end - @provider.exists?.should be_true + provider.exists?.should be_true end it 'should detect if the line does not exist in the file' do - File.open(@tmpfile, 'w') do |fh| + File.open(tmpfile, 'w') do |fh| fh.write('foo1') end - @provider.exists?.should be_nil + provider.exists?.should be_nil end it 'should append to an existing file when creating' do - @provider.create - File.read(@tmpfile).chomp.should == 'foo' + provider.create + File.read(tmpfile).chomp.should == 'foo' end end @@ -52,38 +55,132 @@ describe provider_class do @provider = provider_class.new(@resource) end - it 'should raise an error if more than one line matches, and should not have modified the file' do - File.open(@tmpfile, 'w') do |fh| - fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") + describe 'using match' do + it 'should raise an error if more than one line matches, and should not have modified the file' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") + end + @provider.exists?.should be_nil + expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/) + File.read(@tmpfile).should eql("foo1\nfoo=blah\nfoo2\nfoo=baz") end - @provider.exists?.should be_nil - expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/) - File.read(@tmpfile).should eql("foo1\nfoo=blah\nfoo2\nfoo=baz") - end - it 'should replace a line that matches' do - File.open(@tmpfile, 'w') do |fh| - fh.write("foo1\nfoo=blah\nfoo2") + it 'should replace all lines that matches' do + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo = bar', + :match => '^foo\s*=.*$', + :multiple => true + } + ) + @provider = provider_class.new(@resource) + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") + end + @provider.exists?.should be_nil + @provider.create + File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2\nfoo = bar") end - @provider.exists?.should be_nil - @provider.create - File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2") - end - it 'should add a new line if no lines match' do - File.open(@tmpfile, 'w') do |fh| - fh.write("foo1\nfoo2") + + it 'should raise an error with invalid values' do + expect { + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo = bar', + :match => '^foo\s*=.*$', + :multiple => 'asgadga' + } + ) + }.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./) + end + + it 'should replace a line that matches' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo=blah\nfoo2") + end + @provider.exists?.should be_nil + @provider.create + File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2") + end + it 'should add a new line if no lines match' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo2") + end + @provider.exists?.should be_nil + @provider.create + File.read(@tmpfile).should eql("foo1\nfoo2\nfoo = bar\n") + end + it 'should do nothing if the exact line already exists' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo = bar\nfoo2") + end + @provider.exists?.should be_true + @provider.create + File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2") end - @provider.exists?.should be_nil - @provider.create - File.read(@tmpfile).should eql("foo1\nfoo2\nfoo = bar\n") end - it 'should do nothing if the exact line already exists' do - File.open(@tmpfile, 'w') do |fh| - fh.write("foo1\nfoo = bar\nfoo2") + + describe 'using after' do + let :resource do + Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'inserted = line', + :after => '^foo1', + } + ) + end + + let :provider do + provider_class.new(resource) + end + + context 'with one line matching the after expression' do + before :each do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") + end + end + + it 'inserts the specified line after the line matching the "after" expression' do + provider.create + File.read(@tmpfile).chomp.should eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo = baz") + end + end + + context 'with two lines matching the after expression' do + before :each do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz") + end + end + + it 'errors out stating "One or no line must match the pattern"' do + expect { provider.create }.to raise_error(Puppet::Error, /One or no line must match the pattern/) + end + end + + context 'with no lines matching the after expression' do + let :content do + "foo3\nfoo = blah\nfoo2\nfoo = baz\n" + end + + before :each do + File.open(@tmpfile, 'w') do |fh| + fh.write(content) + end + end + + it 'appends the specified line to the file' do + provider.create + File.read(@tmpfile).should eq(content << resource[:line] << "\n") + end end - @provider.exists?.should be_true - @provider.create - File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2") end end diff --git a/spec/unit/puppet/type/file_line_spec.rb b/spec/unit/puppet/type/file_line_spec.rb index 37f3861..34d5dad 100644 --- a/spec/unit/puppet/type/file_line_spec.rb +++ b/spec/unit/puppet/type/file_line_spec.rb @@ -37,13 +37,13 @@ describe Puppet::Type.type(:file_line) do file_line[:path].should == '/tmp/path' end it 'should not accept unqualified path' do - expect { file_line[:path] = 'file' }.should raise_error(Puppet::Error, /File paths must be fully qualified/) + expect { file_line[:path] = 'file' }.to raise_error(Puppet::Error, /File paths must be fully qualified/) end it 'should require that a line is specified' do - expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.should raise_error(Puppet::Error, /Both line and path are required attributes/) + expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.to raise_error(Puppet::Error, /Both line and path are required attributes/) end it 'should require that a file is specified' do - expect { Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'path') }.should raise_error(Puppet::Error, /Both line and path are required attributes/) + expect { Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'path') }.to raise_error(Puppet::Error, /Both line and path are required attributes/) end it 'should default to ensure => present' do file_line[:ensure].should eq :present |