diff options
| author | Matt Robinson <matt@puppetlabs.com> | 2011-02-02 16:47:53 -0800 |
|---|---|---|
| committer | Matt Robinson <matt@puppetlabs.com> | 2011-02-02 16:47:53 -0800 |
| commit | d4a468543f1f06d44efdb7e375284b0e65260caf (patch) | |
| tree | 2dff58c6e2af2cd682a1143af8494ee4bdf99964 /spec | |
| parent | 6d9cae2e9ca6a56506f679db02ba9abb30a4df91 (diff) | |
| parent | 876d0503dd93329a73e7f335c10a47330d745293 (diff) | |
Merge branch '2.6.x' into next
* 2.6.x: (46 commits)
Augmentation of tests for prior commit
Fix to fix for #5755 -- backref serialization issues in zaml
Fixed #5564 - Added some more fqdn_rand documentation
Fixed #4968 - Updated list of options turned on by --test in documentation
(#5061) - allow special hostclass/define variables to be evaluated as defaults.
(#6107) Fix an error when auditing a file with empty content
Remove already initialized constant warning from file_spec.rb tests
(#5566) Treat source only File checksums as syntax errors when used with content
Rename variable used in File type validation to be more clear
Remove invalid "timestamp" and "time", and add missing "ctime" File checksum types.
Remove order dependency when specifying source and checksum on File type
Bug #5755 -- ZAML generates extra newline in some hash backreferences.
bug #5681 -- code fix to handle AIX mount output
Bug #5681 -- parse AIX mount command output.
Spec for #5681 to allow parsing of AIX mount output in mount provider
Fixed #6091 - Changed POSIX path matching to allow multiple leading slashes
Bug #6091 -- test leading double-slash in filenames are allowed.
Fixed #6071 - Fixed typo and improved exec path error message
Fixed #6061 - Allowed -1 as password min/max age
Bug #6061 -- verify that negative {min,max}_password_age are accepted.
...
Manually Resolved Conflicts:
lib/puppet/util/zaml.rb
spec/unit/util/zaml_spec.rb
Diffstat (limited to 'spec')
22 files changed, 549 insertions, 76 deletions
diff --git a/spec/fixtures/unit/provider/mount/mount-output.aix.txt b/spec/fixtures/unit/provider/mount/mount-output.aix.txt new file mode 100644 index 000000000..54edb9c1c --- /dev/null +++ b/spec/fixtures/unit/provider/mount/mount-output.aix.txt @@ -0,0 +1,7 @@ +/dev/hd4 / jfs2 Nov 11 12:11 rw,log=/dev/hd8 +/dev/hd2 /usr jfs2 Nov 11 12:11 rw,log=/dev/hd8 +/dev/hd9var /var jfs2 Nov 11 12:11 rw,log=/dev/hd8 +/dev/hd3 /tmp jfs2 Nov 11 12:11 rw,log=/dev/hd8 +/dev/hd1 /home jfs2 Nov 11 12:11 rw,log=/dev/hd8 +/proc /proc procfs Nov 11 12:11 rw +/dev/hd10opt /opt jfs2 Nov 11 12:11 rw,log=/dev/hd8 diff --git a/spec/integration/reference/providers_spec.rb b/spec/integration/reference/providers_spec.rb index 8b95ca118..c2b1e17c5 100755 --- a/spec/integration/reference/providers_spec.rb +++ b/spec/integration/reference/providers_spec.rb @@ -11,7 +11,7 @@ describe reference do reference.should_not be_nil end - it "should be able to be rendered as text" do - lambda { reference.to_text }.should_not raise_error + it "should be able to be rendered as markdown" do + lambda { reference.to_markdown }.should_not raise_error end end diff --git a/spec/unit/application/doc_spec.rb b/spec/unit/application/doc_spec.rb index 0fd2c2084..f432184d3 100755 --- a/spec/unit/application/doc_spec.rb +++ b/spec/unit/application/doc_spec.rb @@ -48,10 +48,10 @@ describe Puppet::Application::Doc do @doc.options[:mode].should == :text end - it "should init format to to_rest" do + it "should init format to to_markdown" do @doc.preinit - @doc.options[:format].should == :to_rest + @doc.options[:format].should == :to_markdown end end diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index 65e48214c..65f06169c 100755 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -16,6 +16,25 @@ describe Puppet::Application do Puppet.settings.stubs(:parse) end + describe "finding" do + before do + @klass = Puppet::Application + @klass.stubs(:puts) + end + + it "should find classes in the namespace" do + @klass.find("Agent").should == @klass::Agent + end + + it "should not find classes outside the namespace" do + lambda { @klass.find("String") }.should raise_error(SystemExit) + end + + it "should exit if it can't find a class" do + lambda { @klass.find("ThisShallNeverEverEverExistAsdf") }.should raise_error(SystemExit) + end + end + describe ".run_mode" do it "should default to user" do @appclass.run_mode.name.should == :user diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb index 3a7c0b222..18f9a93b6 100755 --- a/spec/unit/parser/compiler_spec.rb +++ b/spec/unit/parser/compiler_spec.rb @@ -105,8 +105,15 @@ describe Puppet::Parser::Compiler do node.classes = %w{foo bar} compiler = Puppet::Parser::Compiler.new(node) - compiler.classlist.should include("foo") - compiler.classlist.should include("bar") + compiler.classlist.should =~ ['foo', 'bar'] + end + + it "should transform node class hashes into a class list" do + node = Puppet::Node.new("mynode") + node.classes = {'foo'=>{'one'=>'1'}, 'bar'=>{'two'=>'2'}} + compiler = Puppet::Parser::Compiler.new(node) + + compiler.classlist.should =~ ['foo', 'bar'] end it "should add a 'main' stage to the catalog" do @@ -185,6 +192,14 @@ describe Puppet::Parser::Compiler do @compiler.class.publicize_methods(:evaluate_node_classes) { @compiler.evaluate_node_classes } end + it "should evaluate any parameterized classes named in the node" do + classes = {'foo'=>{'1'=>'one'}, 'bar'=>{'2'=>'two'}} + @node.stubs(:classes).returns(classes) + @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope) + @compiler.compile + end + + it "should evaluate the main class if it exists" do compile_stub(:evaluate_main) main_class = @known_resource_types.add Puppet::Resource::Type.new(:hostclass, "") @@ -532,7 +547,7 @@ describe Puppet::Parser::Compiler do @compiler.add_collection(coll) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + lambda { @compiler.compile }.should raise_error Puppet::ParseError, 'Failed to realize virtual resources something' end it "should fail when there are unevaluated resource collections that refer to multiple specific resources" do @@ -541,7 +556,7 @@ describe Puppet::Parser::Compiler do @compiler.add_collection(coll) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + lambda { @compiler.compile }.should raise_error Puppet::ParseError, 'Failed to realize virtual resources one, two' end end @@ -566,6 +581,14 @@ describe Puppet::Parser::Compiler do @scope.expects(:find_hostclass).with("notfound").returns(nil) @compiler.evaluate_classes(%w{notfound}, @scope) end + # I wish it would fail + it "should log when it can't find class" do + klasses = {'foo'=>nil} + @node.classes = klasses + @compiler.topscope.stubs(:find_hostclass).with('foo').returns(nil) + Puppet.expects(:info).with('Could not find class foo for testnode') + @compiler.compile + end end describe "when evaluating found classes" do @@ -586,6 +609,68 @@ describe Puppet::Parser::Compiler do @compiler.evaluate_classes(%w{myclass}, @scope) end + it "should ensure each node class hash is in catalog and have appropriate parameters" do + klasses = {'foo'=>{'1'=>'one'}, 'bar::foo'=>{'2'=>'two'}, 'bar'=>{'1'=> [1,2,3], '2'=>{'foo'=>'bar'}}} + @node.classes = klasses + ast_obj = Puppet::Parser::AST::String.new(:value => 'foo') + klasses.each do |name, params| + klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => ast_obj, '2' => ast_obj}) + @compiler.topscope.known_resource_types.add klass + end + catalog = @compiler.compile + catalog.classes.should =~ ['foo', 'bar::foo', 'settings', 'bar'] + + r1 = catalog.resources.detect {|r| r.title == 'Foo' } + r1.to_hash.should == {:'1' => 'one', :'2' => 'foo'} + r1.tags. should =~ ['class', 'foo'] + + r2 = catalog.resources.detect {|r| r.title == 'Bar::Foo' } + r2.to_hash.should == {:'1' => 'foo', :'2' => 'two'} + r2.tags.should =~ ['bar::foo', 'class', 'bar', 'foo'] + + r2 = catalog.resources.detect {|r| r.title == 'Bar' } + r2.to_hash.should == {:'1' => [1,2,3], :'2' => {'foo'=>'bar'}} + r2.tags.should =~ ['class', 'bar'] + end + + it "should ensure each node class is in catalog and has appropriate tags" do + klasses = ['bar::foo'] + @node.classes = klasses + ast_obj = Puppet::Parser::AST::String.new(:value => 'foo') + klasses.each do |name| + klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => ast_obj, '2' => ast_obj}) + @compiler.topscope.known_resource_types.add klass + end + catalog = @compiler.compile + + r2 = catalog.resources.detect {|r| r.title == 'Bar::Foo' } + r2.tags.should =~ ['bar::foo', 'class', 'bar', 'foo'] + end + + it "should fail if required parameters are missing" do + klass = {'foo'=>{'1'=>'one'}} + @node.classes = klass + klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {'1' => nil, '2' => nil}) + @compiler.topscope.known_resource_types.add klass + lambda { @compiler.compile }.should raise_error Puppet::ParseError, "Must pass 2 to Class[Foo]" + end + + it "should fail if invalid parameters are passed" do + klass = {'foo'=>{'3'=>'one'}} + @node.classes = klass + klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {'1' => nil, '2' => nil}) + @compiler.topscope.known_resource_types.add klass + lambda { @compiler.compile }.should raise_error Puppet::ParseError, "Invalid parameter 3" + end + + it "should ensure class is in catalog without params" do + @node.classes = klasses = {'foo'=>nil} + foo = Puppet::Resource::Type.new(:hostclass, 'foo') + @compiler.topscope.known_resource_types.add foo + catalog = @compiler.compile + catalog.classes.should include 'foo' + end + it "should not evaluate the resources created for found classes unless asked" do @compiler.catalog.stubs(:tag) @@ -759,7 +844,7 @@ describe Puppet::Parser::Compiler do it "should fail if the compile is finished and resource overrides have not been applied" do @compiler.add_override(@override) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + lambda { @compiler.compile }.should raise_error Puppet::ParseError, 'Could not find resource(s) File[/foo] for overriding' end end end diff --git a/spec/unit/property/keyvalue_spec.rb b/spec/unit/property/keyvalue_spec.rb index 7666def56..a44d891d7 100644 --- a/spec/unit/property/keyvalue_spec.rb +++ b/spec/unit/property/keyvalue_spec.rb @@ -134,7 +134,7 @@ describe klass do end end - describe "when calling insync?" do + describe "when calling safe_insync?" do before do @provider = mock("provider") @property.stubs(:provider).returns(@provider) @@ -142,26 +142,26 @@ describe klass do end it "should return true unless @should is defined and not nil" do - @property.insync?("foo") == true + @property.safe_insync?("foo") == true end it "should return true if the passed in values is nil" do @property.should = "foo" - @property.insync?(nil) == true + @property.safe_insync?(nil) == true end it "should return true if hashified should value == (retrieved) value passed in" do @provider.stubs(:prop_name).returns({ :foo => "baz", :bar => "boo" }) @property.should = ["foo=baz", "bar=boo"] @property.expects(:inclusive?).returns(true) - @property.insync?({ :foo => "baz", :bar => "boo" }).must == true + @property.safe_insync?({ :foo => "baz", :bar => "boo" }).must == true end it "should return false if prepared value != should value" do @provider.stubs(:prop_name).returns({ "foo" => "bee", "bar" => "boo" }) @property.should = ["foo=baz", "bar=boo"] @property.expects(:inclusive?).returns(true) - @property.insync?({ "foo" => "bee", "bar" => "boo" }).must == false + @property.safe_insync?({ "foo" => "bee", "bar" => "boo" }).must == false end end end diff --git a/spec/unit/property/list_spec.rb b/spec/unit/property/list_spec.rb index 3e8cc5402..c6c5db10e 100644 --- a/spec/unit/property/list_spec.rb +++ b/spec/unit/property/list_spec.rb @@ -118,39 +118,39 @@ describe list_class do end end - describe "when calling insync?" do + describe "when calling safe_insync?" do it "should return true unless @should is defined and not nil" do - @property.must be_insync("foo") + @property.must be_safe_insync("foo") end it "should return true unless the passed in values is not nil" do @property.should = "foo" - @property.must be_insync(nil) + @property.must be_safe_insync(nil) end it "should call prepare_is_for_comparison with value passed in and should" do @property.should = "foo" @property.expects(:prepare_is_for_comparison).with("bar") @property.expects(:should) - @property.insync?("bar") + @property.safe_insync?("bar") end it "should return true if 'is' value is array of comma delimited should values" do @property.should = "bar,foo" @property.expects(:inclusive?).returns(true) - @property.must be_insync(["bar","foo"]) + @property.must be_safe_insync(["bar","foo"]) end it "should return true if 'is' value is :absent and should value is empty string" do @property.should = "" @property.expects(:inclusive?).returns(true) - @property.must be_insync([]) + @property.must be_safe_insync([]) end it "should return false if prepared value != should value" do @property.should = "bar,baz,foo" @property.expects(:inclusive?).returns(true) - @property.must_not be_insync(["bar","foo"]) + @property.must_not be_safe_insync(["bar","foo"]) end end diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb index 9ce03f6f0..256295574 100755 --- a/spec/unit/provider/mount_spec.rb +++ b/spec/unit/provider/mount_spec.rb @@ -120,6 +120,14 @@ describe Puppet::Provider::Mount do @mounter.should be_mounted end + it "should match mounted devices if the operating system is AIX" do + Facter.stubs(:value).with("operatingsystem").returns("AIX") + mount_data = File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'unit', 'provider', 'mount', 'mount-output.aix.txt')) + @mounter.expects(:mountcmd).returns(mount_data) + + @mounter.should be_mounted + end + it "should match ' on <name>' if the operating system is not Darwin, Solaris, or HP-UX" do Facter.stubs(:value).with("operatingsystem").returns("Debian") @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on / and stuff\n/dev/other/disk on /var and stuff") diff --git a/spec/unit/provider/nameservice/directoryservice_spec.rb b/spec/unit/provider/nameservice/directoryservice_spec.rb new file mode 100755 index 000000000..661899db9 --- /dev/null +++ b/spec/unit/provider/nameservice/directoryservice_spec.rb @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +# We use this as a reasonable way to obtain all the support infrastructure. +[:user, :group].each do |type_for_this_round| + provider_class = Puppet::Type.type(type_for_this_round).provider(:directoryservice) + + describe provider_class do + before do + @resource = stub("resource") + @provider = provider_class.new(@resource) + end + + it "[#6009] should handle nested arrays of members" do + current = ["foo", "bar", "baz"] + desired = ["foo", ["quux"], "qorp"] + group = 'example' + + @resource.stubs(:[]).with(:name).returns(group) + @resource.stubs(:[]).with(:auth_membership).returns(true) + @provider.instance_variable_set(:@property_value_cache_hash, + { :members => current }) + + %w{bar baz}.each do |del| + @provider.expects(:execute).once. + with([:dseditgroup, '-o', 'edit', '-n', '.', '-d', del, group]) + end + + %w{quux qorp}.each do |add| + @provider.expects(:execute).once. + with([:dseditgroup, '-o', 'edit', '-n', '.', '-a', add, group]) + end + + expect { @provider.set(:members, desired) }.should_not raise_error + end + end +end diff --git a/spec/unit/provider/package/freebsd_spec.rb b/spec/unit/provider/package/freebsd_spec.rb new file mode 100755 index 000000000..0d38a16cf --- /dev/null +++ b/spec/unit/provider/package/freebsd_spec.rb @@ -0,0 +1,55 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +provider_class = Puppet::Type.type(:package).provider(:freebsd) + +describe provider_class do + before :each do + # Create a mock resource + @resource = stub 'resource' + + # A catch all; no parameters set + @resource.stubs(:[]).returns(nil) + + # But set name and source + @resource.stubs(:[]).with(:name).returns "mypackage" + @resource.stubs(:[]).with(:ensure).returns :installed + + @provider = provider_class.new + @provider.resource = @resource + end + + it "should have an install method" do + @provider = provider_class.new + @provider.should respond_to(:install) + end + + describe "when installing" do + before :each do + @resource.stubs(:should).with(:ensure).returns(:installed) + end + + it "should install a package from a path to a directory" do + # For better or worse, trailing '/' is needed. --daniel 2011-01-26 + path = '/path/to/directory/' + @resource.stubs(:[]).with(:source).returns(path) + Puppet::Util::Execution.expects(:withenv).once.with({:PKG_PATH => path}).yields + @provider.expects(:pkgadd).once.with("mypackage") + + expect { @provider.install }.should_not raise_error + end + + %w{http https ftp}.each do |protocol| + it "should install a package via #{protocol}" do + # For better or worse, trailing '/' is needed. --daniel 2011-01-26 + path = "#{protocol}://localhost/" + @resource.stubs(:[]).with(:source).returns(path) + Puppet::Util::Execution.expects(:withenv).once.with({:PACKAGESITE => path}).yields + @provider.expects(:pkgadd).once.with('-r', "mypackage") + + expect { @provider.install }.should_not raise_error + end + end + end +end diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb index a22dc3572..e9c203526 100755 --- a/spec/unit/resource/type_spec.rb +++ b/spec/unit/resource/type_spec.rb @@ -261,6 +261,28 @@ describe Puppet::Resource::Type do @type = Puppet::Resource::Type.new(:hostclass, "foo") end + ['module_name', 'name', 'title'].each do |variable| + it "should allow #{variable} to be evaluated as param default" do + @type.instance_eval { @module_name = "bar" } + var = Puppet::Parser::AST::Variable.new({'value' => variable}) + @type.set_arguments :foo => var + @type.set_resource_parameters(@resource, @scope) + @scope.lookupvar('foo').should == 'bar' + end + end + + # this test is to clarify a crazy edge case + # if you specify these special names as params, the resource + # will override the special variables + it "resource should override defaults" do + @type.set_arguments :name => nil + @resource[:name] = 'foobar' + var = Puppet::Parser::AST::Variable.new({'value' => 'name'}) + @type.set_arguments :foo => var + @type.set_resource_parameters(@resource, @scope) + @scope.lookupvar('foo').should == 'foobar' + end + it "should set each of the resource's parameters as variables in the scope" do @type.set_arguments :foo => nil, :boo => nil @resource[:foo] = "bar" @@ -496,7 +518,7 @@ describe Puppet::Resource::Type do it "should evaluate the parent's resource" do @type.parent_type(@scope) - + @type.evaluate_code(@resource) @scope.class_scope(@parent_type).should_not be_nil @@ -504,7 +526,7 @@ describe Puppet::Resource::Type do it "should not evaluate the parent's resource if it has already been evaluated" do @parent_resource.evaluate - + @type.parent_type(@scope) @parent_resource.expects(:evaluate).never @@ -544,7 +566,7 @@ describe Puppet::Resource::Type do it "should not evaluate the parent's resource if it has already been evaluated" do @parent_resource.evaluate - + @type.parent_type(@scope) @parent_resource.expects(:evaluate).never @@ -574,7 +596,7 @@ describe Puppet::Resource::Type do @code = Puppet::Resource::TypeCollection.new("env") @code.add @top @code.add @middle - + @node.environment.stubs(:known_resource_types).returns(@code) end @@ -600,12 +622,36 @@ describe Puppet::Resource::Type do @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) end + it "should add specified parameters to the resource" do + @top.ensure_in_catalog(@scope, {'one'=>'1', 'two'=>'2'}) + @compiler.catalog.resource(:class, "top")['one'].should == '1' + @compiler.catalog.resource(:class, "top")['two'].should == '2' + end + + it "should not require params for a param class" do + @top.ensure_in_catalog(@scope, {}) + @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) + end + it "should evaluate the parent class if one exists" do @middle.ensure_in_catalog(@scope) @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) end + it "should evaluate the parent class if one exists" do + @middle.ensure_in_catalog(@scope, {}) + + @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) + end + + it "should fail if you try to create duplicate class resources" do + othertop = Puppet::Parser::Resource.new(:class, 'top',:source => @source, :scope => @scope ) + # add the same class resource to the catalog + @compiler.catalog.add_resource(othertop) + lambda { @top.ensure_in_catalog(@scope, {}) }.should raise_error(Puppet::Resource::Catalog::DuplicateResourceError) + end + it "should fail to evaluate if a parent class is defined but cannot be found" do othertop = Puppet::Resource::Type.new :hostclass, "something", :parent => "yay" @code.add othertop diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 32b03add1..8b7bfc3e6 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -98,6 +98,14 @@ describe Puppet::Resource do lambda { Puppet::Resource.new("foo") }.should raise_error(ArgumentError) end + it 'should fail if strict is set and type does not exist' do + lambda { Puppet::Resource.new('foo', 'title', {:strict=>true}) }.should raise_error(ArgumentError, 'Invalid resource type foo') + end + + it 'should fail if strict is set and class does not exist' do + lambda { Puppet::Resource.new('Class', 'foo', {:strict=>true}) }.should raise_error(ArgumentError, 'Could not find declared class foo') + end + it "should fail if the title is a hash and the type is not a valid resource reference string" do lambda { Puppet::Resource.new({:type => "foo", :title => "bar"}) }.should raise_error(ArgumentError, 'Puppet::Resource.new does not take a hash as the first argument. Did you mean ("foo", "bar") ?' diff --git a/spec/unit/type/file/content_spec.rb b/spec/unit/type/file/content_spec.rb index cde643fc8..9178c94bf 100755 --- a/spec/unit/type/file/content_spec.rb +++ b/spec/unit/type/file/content_spec.rb @@ -141,17 +141,20 @@ describe content do it "should return true if the resource shouldn't be a regular file" do @resource.expects(:should_be_file?).returns false - @content.must be_insync("whatever") + @content.should = "foo" + @content.must be_safe_insync("whatever") end it "should return false if the current content is :absent" do - @content.should_not be_insync(:absent) + @content.should = "foo" + @content.should_not be_safe_insync(:absent) end it "should return false if the file should be a file but is not present" do @resource.expects(:should_be_file?).returns true + @content.should = "foo" - @content.should_not be_insync(:absent) + @content.should_not be_safe_insync(:absent) end describe "and the file exists" do @@ -161,12 +164,12 @@ describe content do it "should return false if the current contents are different from the desired content" do @content.should = "some content" - @content.should_not be_insync("other content") + @content.should_not be_safe_insync("other content") end it "should return true if the sum for the current contents is the same as the sum for the desired content" do @content.should = "some content" - @content.must be_insync("{md5}" + Digest::MD5.hexdigest("some content")) + @content.must be_safe_insync("{md5}" + Digest::MD5.hexdigest("some content")) end describe "and Puppet[:show_diff] is set" do @@ -179,14 +182,14 @@ describe content do @content.expects(:diff).returns("my diff").once @content.expects(:print).with("my diff").once - @content.insync?("other content") + @content.safe_insync?("other content") end it "should not display a diff if the sum for the current contents is the same as the sum for the desired content" do @content.should = "some content" @content.expects(:diff).never - @content.insync?("{md5}" + Digest::MD5.hexdigest("some content")) + @content.safe_insync?("{md5}" + Digest::MD5.hexdigest("some content")) end end end @@ -199,17 +202,18 @@ describe content do it "should be insync if the file exists and the content is different" do @resource.stubs(:stat).returns mock('stat') - @content.must be_insync("whatever") + @content.must be_safe_insync("whatever") end it "should be insync if the file exists and the content is right" do @resource.stubs(:stat).returns mock('stat') - @content.must be_insync("something") + @content.must be_safe_insync("something") end it "should not be insync if the file does not exist" do - @content.should_not be_insync(:absent) + @content.should = "foo" + @content.should_not be_safe_insync(:absent) end end end @@ -457,5 +461,54 @@ describe content do describe "from a filebucket" do end + + # These are testing the implementation rather than the desired behaviour; while that bites, there are a whole + # pile of other methods in the File type that depend on intimate details of this implementation and vice-versa. + # If these blow up, you are gonna have to review the callers to make sure they don't explode! --daniel 2011-02-01 + describe "each_chunk_from should work" do + before do + @content = content.new(:resource => @resource) + end + + it "when content is a string" do + @content.each_chunk_from('i_am_a_string') { |chunk| chunk.should == 'i_am_a_string' } + end + + it "when no content, source, but ensure present" do + @resource[:ensure] = :present + @content.each_chunk_from(nil) { |chunk| chunk.should == '' } + end + + it "when no content, source, but ensure file" do + @resource[:ensure] = :file + @content.each_chunk_from(nil) { |chunk| chunk.should == '' } + end + + it "when no content or source" do + @content.expects(:read_file_from_filebucket).once.returns('im_a_filebucket') + @content.each_chunk_from(nil) { |chunk| chunk.should == 'im_a_filebucket' } + end + + it "when running as puppet apply" do + @content.class.expects(:standalone?).returns true + source_or_content = stubs('source_or_content') + source_or_content.expects(:content).once.returns :whoo + @content.each_chunk_from(source_or_content) { |chunk| chunk.should == :whoo } + end + + it "when running from source with a local file" do + source_or_content = stubs('source_or_content') + source_or_content.expects(:local?).returns true + @content.expects(:chunk_file_from_disk).with(source_or_content).once.yields 'woot' + @content.each_chunk_from(source_or_content) { |chunk| chunk.should == 'woot' } + end + + it "when running from source with a remote file" do + source_or_content = stubs('source_or_content') + source_or_content.expects(:local?).returns false + @content.expects(:chunk_file_from_source).with(source_or_content).once.yields 'woot' + @content.each_chunk_from(source_or_content) { |chunk| chunk.should == 'woot' } + end + end end end diff --git a/spec/unit/type/file/ensure_spec.rb b/spec/unit/type/file/ensure_spec.rb index ec53ed85a..dbb3a1053 100755 --- a/spec/unit/type/file/ensure_spec.rb +++ b/spec/unit/type/file/ensure_spec.rb @@ -41,44 +41,45 @@ describe property do end it "should always be in sync if replace is 'false' unless the file is missing" do + @ensure.should = :file @resource.expects(:replace?).returns false - @ensure.insync?(:link).should be_true + @ensure.safe_insync?(:link).should be_true end it "should be in sync if :ensure is set to :absent and the file does not exist" do @ensure.should = :absent - @ensure.must be_insync(:absent) + @ensure.must be_safe_insync(:absent) end it "should not be in sync if :ensure is set to :absent and the file exists" do @ensure.should = :absent - @ensure.should_not be_insync(:file) + @ensure.should_not be_safe_insync(:file) end it "should be in sync if a normal file exists and :ensure is set to :present" do @ensure.should = :present - @ensure.must be_insync(:file) + @ensure.must be_safe_insync(:file) end it "should be in sync if a directory exists and :ensure is set to :present" do @ensure.should = :present - @ensure.must be_insync(:directory) + @ensure.must be_safe_insync(:directory) end it "should be in sync if a symlink exists and :ensure is set to :present" do @ensure.should = :present - @ensure.must be_insync(:link) + @ensure.must be_safe_insync(:link) end it "should not be in sync if :ensure is set to :file and a directory exists" do @ensure.should = :file - @ensure.should_not be_insync(:directory) + @ensure.should_not be_safe_insync(:directory) end end end diff --git a/spec/unit/type/file/group_spec.rb b/spec/unit/type/file/group_spec.rb index 2283b57fa..956cd57e7 100755 --- a/spec/unit/type/file/group_spec.rb +++ b/spec/unit/type/file/group_spec.rb @@ -56,19 +56,19 @@ describe property do describe "when determining if the file is in sync" do it "should directly compare the group values if the desired group is an integer" do @group.should = [10] - @group.must be_insync(10) + @group.must be_safe_insync(10) end it "should treat numeric strings as integers" do @group.should = ["10"] - @group.must be_insync(10) + @group.must be_safe_insync(10) end it "should convert the group name to an integer if the desired group is a string" do @group.expects(:gid).with("foo").returns 10 @group.should = %w{foo} - @group.must be_insync(10) + @group.must be_safe_insync(10) end it "should not validate that groups exist when a group is specified as an integer" do @@ -80,12 +80,12 @@ describe property do @group.expects(:gid).with("foo").returns nil @group.should = %w{foo} - lambda { @group.insync?(10) }.should raise_error(Puppet::Error) + lambda { @group.safe_insync?(10) }.should raise_error(Puppet::Error) end it "should return false if the groups are not equal" do @group.should = [10] - @group.should_not be_insync(20) + @group.should_not be_safe_insync(20) end end diff --git a/spec/unit/type/file/owner_spec.rb b/spec/unit/type/file/owner_spec.rb index 8e136a187..bcb8e07d6 100755 --- a/spec/unit/type/file/owner_spec.rb +++ b/spec/unit/type/file/owner_spec.rb @@ -68,7 +68,7 @@ describe property do @provider.expects(:warnonce) @owner.should = [10] - @owner.must be_insync(20) + @owner.must be_safe_insync(20) end end @@ -77,24 +77,24 @@ describe property do end it "should be in sync if 'should' is not provided" do - @owner.must be_insync(10) + @owner.must be_safe_insync(10) end it "should directly compare the owner values if the desired owner is an integer" do @owner.should = [10] - @owner.must be_insync(10) + @owner.must be_safe_insync(10) end it "should treat numeric strings as integers" do @owner.should = ["10"] - @owner.must be_insync(10) + @owner.must be_safe_insync(10) end it "should convert the owner name to an integer if the desired owner is a string" do @provider.expects(:uid).with("foo").returns 10 @owner.should = %w{foo} - @owner.must be_insync(10) + @owner.must be_safe_insync(10) end it "should not validate that users exist when a user is specified as an integer" do @@ -106,12 +106,12 @@ describe property do @provider.expects(:uid).with("foo").returns nil @owner.should = %w{foo} - lambda { @owner.insync?(10) }.should raise_error(Puppet::Error) + lambda { @owner.safe_insync?(10) }.should raise_error(Puppet::Error) end it "should return false if the owners are not equal" do @owner.should = [10] - @owner.should_not be_insync(20) + @owner.should_not be_safe_insync(20) end end diff --git a/spec/unit/type/file/selinux_spec.rb b/spec/unit/type/file/selinux_spec.rb index 1ca59e9e7..043471dec 100644 --- a/spec/unit/type/file/selinux_spec.rb +++ b/spec/unit/type/file/selinux_spec.rb @@ -73,10 +73,10 @@ Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f @sel.sync end - it "should do nothing for insync? if no SELinux support" do + it "should do nothing for safe_insync? if no SELinux support" do @sel.should = %{newcontext} @sel.expects(:selinux_support?).returns false - @sel.insync?("oldcontext").should == true + @sel.safe_insync?("oldcontext").should == true end end end diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb index 31d3d6bc6..539782fd4 100755 --- a/spec/unit/type/file_spec.rb +++ b/spec/unit/type/file_spec.rb @@ -194,6 +194,23 @@ describe Puppet::Type.type(:file) do file = Puppet::Type::File.new(:path => "/") file[:path].should == "/" end + + it "should accept a double-slash at the start of the path" do + expect { + file = Puppet::Type::File.new(:path => "//tmp/xxx") + # REVISIT: This should be wrong, later. See the next test. + # --daniel 2011-01-31 + file[:path].should == '/tmp/xxx' + }.should_not raise_error + end + + # REVISIT: This is pending, because I don't want to try and audit the + # entire codebase to make sure we get this right. POSIX treats two (and + # exactly two) '/' characters at the start of the path specially. + # + # See sections 3.2 and 4.11, which allow DomainOS to be all special like + # and still have the POSIX branding and all. --daniel 2011-01-31 + it "should preserve the double-slash at the start of the path" end describe "on Microsoft Windows systems" do @@ -806,6 +823,73 @@ describe Puppet::Type.type(:file) do end end + describe "when specifying both source, and content properties" do + before do + @file[:source] = '/one' + @file[:content] = 'file contents' + end + + it "should raise an exception" do + lambda {@file.validate }.should raise_error(/You cannot specify more than one of/) + end + end + + describe "when using source" do + before do + @file[:source] = '/one' + end + Puppet::Type::File::ParameterChecksum.value_collection.values.reject {|v| v == :none}.each do |checksum_type| + describe "with checksum '#{checksum_type}'" do + before do + @file[:checksum] = checksum_type + end + + it 'should validate' do + + lambda { @file.validate }.should_not raise_error + end + end + end + + describe "with checksum 'none'" do + before do + @file[:checksum] = :none + end + + it 'should raise an exception when validating' do + lambda { @file.validate }.should raise_error(/You cannot specify source when using checksum 'none'/) + end + end + end + + describe "when using content" do + before do + @file[:content] = 'file contents' + end + + (Puppet::Type::File::ParameterChecksum.value_collection.values - SOURCE_ONLY_CHECKSUMS).each do |checksum_type| + describe "with checksum '#{checksum_type}'" do + before do + @file[:checksum] = checksum_type + end + + it 'should validate' do + lambda { @file.validate }.should_not raise_error + end + end + end + + SOURCE_ONLY_CHECKSUMS.each do |checksum_type| + describe "with checksum '#{checksum_type}'" do + it 'should raise an exception when validating' do + @file[:checksum] = checksum_type + + lambda { @file.validate }.should raise_error(/You cannot specify content when using checksum '#{checksum_type}'/) + end + end + end + end + describe "when returning resources with :eval_generate" do before do @graph = stub 'graph', :add_edge => nil @@ -1065,4 +1149,45 @@ describe Puppet::Type.type(:file) do end end + describe "when auditing" do + it "should not fail if creating a new file if group is not set" do + File.exists?(@path).should == false + file = Puppet::Type::File.new(:name => @path, :audit => "all", :content => "content") + catalog = Puppet::Resource::Catalog.new + catalog.add_resource(file) + + Puppet::Util::Storage.stubs(:store) # to prevent the catalog from trying to write state.yaml + transaction = catalog.apply + + transaction.report.resource_statuses["File[#{@path}]"].failed.should == false + File.exists?(@path).should == true + end + + it "should not log errors if creating a new file with ensure present and no content" do + File.exists?(@path).should == false + file = Puppet::Type::File.new(:name => @path, :audit => "content", :ensure => "present") + catalog = Puppet::Resource::Catalog.new + catalog.add_resource(file) + + Puppet::Util::Storage.stubs(:store) # to prevent the catalog from trying to write state.yaml + + catalog.apply + @logs.reject {|l| l.level == :notice }.should be_empty + end + end + + describe "when specifying both source and checksum" do + it 'should use the specified checksum when source is first' do + @file[:source] = '/foo' + @file[:checksum] = :md5lite + + @file[:checksum].should be :md5lite + end + it 'should use the specified checksum when source is last' do + @file[:checksum] = :md5lite + @file[:source] = '/foo' + + @file[:checksum].should be :md5lite + end + end end diff --git a/spec/unit/type/mount_spec.rb b/spec/unit/type/mount_spec.rb index 934c6f45f..3df8de903 100755 --- a/spec/unit/type/mount_spec.rb +++ b/spec/unit/type/mount_spec.rb @@ -184,22 +184,22 @@ describe Puppet::Type.type(:mount)::Ensure do it "should be insync if it is mounted and should be defined" do @ensure.should = :defined - @ensure.insync?(:mounted).should == true + @ensure.safe_insync?(:mounted).should == true end it "should be insync if it is unmounted and should be defined" do @ensure.should = :defined - @ensure.insync?(:unmounted).should == true + @ensure.safe_insync?(:unmounted).should == true end it "should be insync if it is mounted and should be present" do @ensure.should = :present - @ensure.insync?(:mounted).should == true + @ensure.safe_insync?(:mounted).should == true end it "should be insync if it is unmounted and should be present" do @ensure.should = :present - @ensure.insync?(:unmounted).should == true + @ensure.safe_insync?(:unmounted).should == true end end diff --git a/spec/unit/type/ssh_authorized_key_spec.rb b/spec/unit/type/ssh_authorized_key_spec.rb index 08c1eb2be..287fca3ab 100755 --- a/spec/unit/type/ssh_authorized_key_spec.rb +++ b/spec/unit/type/ssh_authorized_key_spec.rb @@ -134,7 +134,7 @@ describe ssh_authorized_key do it "should not raise spurious change events" do resource = @class.new(:name => "Test", :user => "root") target = File.expand_path("~root/.ssh/authorized_keys") - resource.property(:target).insync?(target).should == true + resource.property(:target).safe_insync?(target).should == true end end diff --git a/spec/unit/type/user_spec.rb b/spec/unit/type/user_spec.rb index b834f2011..117c90f1c 100755 --- a/spec/unit/type/user_spec.rb +++ b/spec/unit/type/user_spec.rb @@ -201,21 +201,21 @@ describe user do it "should return true if no 'should' values are set" do @gid = user.attrclass(:gid).new(:resource => @resource) - @gid.must be_insync(500) + @gid.must be_safe_insync(500) end it "should return true if any of the specified groups are equal to the current integer" do Puppet::Util.expects(:gid).with("foo").returns 300 Puppet::Util.expects(:gid).with("bar").returns 500 - @gid.must be_insync(500) + @gid.must be_safe_insync(500) end it "should return false if none of the specified groups are equal to the current integer" do Puppet::Util.expects(:gid).with("foo").returns 300 Puppet::Util.expects(:gid).with("bar").returns 500 - @gid.should_not be_insync(700) + @gid.should_not be_safe_insync(700) end end @@ -245,6 +245,34 @@ describe user do end end + describe "when managing minimum password age" do + before do + @age = user.attrclass(:password_min_age).new(:resource => @resource) + end + + it "should accept a negative minimum age" do + expect { @age.should = -1 }.should_not raise_error + end + + it "should fail with an empty minimum age" do + expect { @age.should = '' }.should raise_error(Puppet::Error) + end + end + + describe "when managing maximum password age" do + before do + @age = user.attrclass(:password_max_age).new(:resource => @resource) + end + + it "should accept a negative maximum age" do + expect { @age.should = -1 }.should_not raise_error + end + + it "should fail with an empty maximum age" do + expect { @age.should = '' }.should raise_error(Puppet::Error) + end + end + describe "when managing passwords" do before do @password = user.attrclass(:password).new(:resource => @resource, :should => "mypass") diff --git a/spec/unit/type/zpool_spec.rb b/spec/unit/type/zpool_spec.rb index db12459ab..be8cb12ba 100755 --- a/spec/unit/type/zpool_spec.rb +++ b/spec/unit/type/zpool_spec.rb @@ -38,27 +38,27 @@ describe vdev_property do it "should be insync if the devices are the same" do @property.should = ["dev1 dev2"] - @property.insync?(["dev2 dev1"]).must be_true + @property.safe_insync?(["dev2 dev1"]).must be_true end it "should be out of sync if the devices are not the same" do @property.should = ["dev1 dev3"] - @property.insync?(["dev2 dev1"]).must be_false + @property.safe_insync?(["dev2 dev1"]).must be_false end it "should be insync if the devices are the same and the should values are comma seperated" do @property.should = ["dev1", "dev2"] - @property.insync?(["dev2 dev1"]).must be_true + @property.safe_insync?(["dev2 dev1"]).must be_true end it "should be out of sync if the device is absent and should has a value" do @property.should = ["dev1", "dev2"] - @property.insync?(:absent).must be_false + @property.safe_insync?(:absent).must be_false end it "should be insync if the device is absent and should is absent" do @property.should = [:absent] - @property.insync?(:absent).must be_true + @property.safe_insync?(:absent).must be_true end end @@ -73,38 +73,38 @@ describe multi_vdev_property do it "should be insync if the devices are the same" do @property.should = ["dev1 dev2"] - @property.insync?(["dev2 dev1"]).must be_true + @property.safe_insync?(["dev2 dev1"]).must be_true end it "should be out of sync if the devices are not the same" do @property.should = ["dev1 dev3"] - @property.insync?(["dev2 dev1"]).must be_false + @property.safe_insync?(["dev2 dev1"]).must be_false end it "should be out of sync if the device is absent and should has a value" do @property.should = ["dev1", "dev2"] - @property.insync?(:absent).must be_false + @property.safe_insync?(:absent).must be_false end it "should be insync if the device is absent and should is absent" do @property.should = [:absent] - @property.insync?(:absent).must be_true + @property.safe_insync?(:absent).must be_true end describe "when there are multiple lists of devices" do it "should be in sync if each group has the same devices" do @property.should = ["dev1 dev2", "dev3 dev4"] - @property.insync?(["dev2 dev1", "dev3 dev4"]).must be_true + @property.safe_insync?(["dev2 dev1", "dev3 dev4"]).must be_true end it "should be out of sync if any group has the different devices" do @property.should = ["dev1 devX", "dev3 dev4"] - @property.insync?(["dev2 dev1", "dev3 dev4"]).must be_false + @property.safe_insync?(["dev2 dev1", "dev3 dev4"]).must be_false end it "should be out of sync if devices are in the wrong group" do @property.should = ["dev1 dev2", "dev3 dev4"] - @property.insync?(["dev2 dev3", "dev1 dev4"]).must be_false + @property.safe_insync?(["dev2 dev3", "dev1 dev4"]).must be_false end end end |
