diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb index ed36ab061..17f749068 100755 --- a/spec/unit/type_spec.rb +++ b/spec/unit/type_spec.rb @@ -1,796 +1,853 @@ #!/usr/bin/env rspec require 'spec_helper' describe Puppet::Type, :fails_on_windows => true do include PuppetSpec::Files it "should be Comparable" do a = Puppet::Type.type(:notify).new(:name => "a") b = Puppet::Type.type(:notify).new(:name => "b") c = Puppet::Type.type(:notify).new(:name => "c") [[a, b, c], [a, c, b], [b, a, c], [b, c, a], [c, a, b], [c, b, a]].each do |this| this.sort.should == [a, b, c] end a.should be < b a.should be < c b.should be > a b.should be < c c.should be > a c.should be > b [a, b, c].each {|x| a.should be <= x } [a, b, c].each {|x| c.should be >= x } b.should be_between(a, c) end it "should consider a parameter to be valid if it is a valid parameter" do Puppet::Type.type(:mount).should be_valid_parameter(:path) end it "should consider a parameter to be valid if it is a valid property" do Puppet::Type.type(:mount).should be_valid_parameter(:fstype) end it "should consider a parameter to be valid if it is a valid metaparam" do Puppet::Type.type(:mount).should be_valid_parameter(:noop) end it "should be able to retrieve a property by name" do resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) resource.property(:fstype).must be_instance_of(Puppet::Type.type(:mount).attrclass(:fstype)) end it "should be able to retrieve a parameter by name" do resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) resource.parameter(:name).must be_instance_of(Puppet::Type.type(:mount).attrclass(:name)) end it "should be able to retrieve a property by name using the :parameter method" do resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) resource.parameter(:fstype).must be_instance_of(Puppet::Type.type(:mount).attrclass(:fstype)) end it "should be able to retrieve all set properties" do resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) props = resource.properties props.should_not be_include(nil) [:fstype, :ensure, :pass].each do |name| props.should be_include(resource.parameter(name)) end end it "should have a method for setting default values for resources" do Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:set_default) end it "should do nothing for attributes that have no defaults and no specified value" do Puppet::Type.type(:mount).new(:name => "foo").parameter(:noop).should be_nil end it "should have a method for adding tags" do Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:tags) end it "should use the tagging module" do Puppet::Type.type(:mount).ancestors.should be_include(Puppet::Util::Tagging) end it "should delegate to the tagging module when tags are added" do resource = Puppet::Type.type(:mount).new(:name => "foo") resource.stubs(:tag).with(:mount) resource.expects(:tag).with(:tag1, :tag2) resource.tags = [:tag1,:tag2] end it "should add the current type as tag" do resource = Puppet::Type.type(:mount).new(:name => "foo") resource.stubs(:tag) resource.expects(:tag).with(:mount) resource.tags = [:tag1,:tag2] end it "should have a method to know if the resource is exported" do Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:exported?) end it "should have a method to know if the resource is virtual" do Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:virtual?) end it "should consider its version to be its catalog version" do resource = Puppet::Type.type(:mount).new(:name => "foo") catalog = Puppet::Resource::Catalog.new catalog.version = 50 catalog.add_resource resource resource.version.should == 50 end it "should consider its version to be zero if it has no catalog" do Puppet::Type.type(:mount).new(:name => "foo").version.should == 0 end it "should provide source_descriptors" do resource = Puppet::Type.type(:mount).new(:name => "foo") catalog = Puppet::Resource::Catalog.new catalog.version = 50 catalog.add_resource resource resource.source_descriptors.should == {:tags=>["mount", "foo"], :path=>"/Mount[foo]"} end it "should consider its type to be the name of its class" do Puppet::Type.type(:mount).new(:name => "foo").type.should == :mount end it "should use any provided noop value" do Puppet::Type.type(:mount).new(:name => "foo", :noop => true).must be_noop end it "should use the global noop value if none is provided" do Puppet[:noop] = true Puppet::Type.type(:mount).new(:name => "foo").must be_noop end it "should not be noop if in a non-host_config catalog" do resource = Puppet::Type.type(:mount).new(:name => "foo") catalog = Puppet::Resource::Catalog.new catalog.add_resource resource resource.should_not be_noop end describe "when creating an event" do before do @resource = Puppet::Type.type(:mount).new :name => "foo" end it "should have the resource's reference as the resource" do @resource.event.resource.should == "Mount[foo]" end it "should have the resource's log level as the default log level" do @resource[:loglevel] = :warning @resource.event.default_log_level.should == :warning end {:file => "/my/file", :line => 50, :tags => %{foo bar}}.each do |attr, value| it "should set the #{attr}" do @resource.stubs(attr).returns value @resource.event.send(attr).should == value end end it "should allow specification of event attributes" do @resource.event(:status => "noop").status.should == "noop" end end describe "when creating a provider" do before :each do @type = Puppet::Type.newtype(:provider_test_type) do newparam(:name) { isnamevar } newparam(:foo) newproperty(:bar) end end after :each do @type.provider_hash.clear end describe "when determining if instances of the type are managed" do it "should not consider audit only resources to be managed" do @type.new(:name => "foo", :audit => 'all').managed?.should be_false end it "should not consider resources with only parameters to be managed" do @type.new(:name => "foo", :foo => 'did someone say food?').managed?.should be_false end it "should consider resources with any properties set to be managed" do @type.new(:name => "foo", :bar => 'Let us all go there').managed?.should be_true end end it "should have documentation for the 'provider' parameter if there are providers" do @type.provide(:test_provider) @type.paramdoc(:provider).should =~ /`provider_test_type`[\s\r]+resource/ end it "should not have documentation for the 'provider' parameter if there are no providers" do expect { @type.paramdoc(:provider) }.to raise_error(NoMethodError) end it "should create a subclass of Puppet::Provider for the provider" do provider = @type.provide(:test_provider) provider.ancestors.should include(Puppet::Provider) end it "should use a parent class if specified" do parent_provider = @type.provide(:parent_provider) child_provider = @type.provide(:child_provider, :parent => parent_provider) child_provider.ancestors.should include(parent_provider) end it "should use a parent class if specified by name" do parent_provider = @type.provide(:parent_provider) child_provider = @type.provide(:child_provider, :parent => :parent_provider) child_provider.ancestors.should include(parent_provider) end it "should raise an error when the parent class can't be found" do expect { @type.provide(:child_provider, :parent => :parent_provider) }.to raise_error(Puppet::DevError, /Could not find parent provider.+parent_provider/) end it "should ensure its type has a 'provider' parameter" do @type.provide(:test_provider) @type.parameters.should include(:provider) end it "should remove a previously registered provider with the same name" do old_provider = @type.provide(:test_provider) new_provider = @type.provide(:test_provider) old_provider.should_not equal(new_provider) end it "should register itself as a provider for the type" do provider = @type.provide(:test_provider) provider.should == @type.provider(:test_provider) end it "should create a provider when a provider with the same name previously failed" do @type.provide(:test_provider) do raise "failed to create this provider" end rescue nil provider = @type.provide(:test_provider) provider.ancestors.should include(Puppet::Provider) provider.should == @type.provider(:test_provider) end end describe "when choosing a default provider" do it "should choose the provider with the highest specificity" do # Make a fake type type = Puppet::Type.newtype(:defaultprovidertest) do newparam(:name) do end end basic = type.provide(:basic) {} greater = type.provide(:greater) {} basic.stubs(:specificity).returns 1 greater.stubs(:specificity).returns 2 type.defaultprovider.should equal(greater) end end describe "when initializing" do describe "and passed a Puppet::Resource instance" do it "should set its title to the title of the resource if the resource type is equal to the current type" do resource = Puppet::Resource.new(:mount, "/foo", :parameters => {:name => "/other"}) Puppet::Type.type(:mount).new(resource).title.should == "/foo" end it "should set its title to the resource reference if the resource type is not equal to the current type" do resource = Puppet::Resource.new(:user, "foo") Puppet::Type.type(:mount).new(resource).title.should == "User[foo]" end [:line, :file, :catalog, :exported, :virtual].each do |param| it "should copy '#{param}' from the resource if present" do resource = Puppet::Resource.new(:mount, "/foo") resource.send(param.to_s + "=", "foo") resource.send(param.to_s + "=", "foo") Puppet::Type.type(:mount).new(resource).send(param).should == "foo" end end it "should copy any tags from the resource" do resource = Puppet::Resource.new(:mount, "/foo") resource.tag "one", "two" tags = Puppet::Type.type(:mount).new(resource).tags tags.should be_include("one") tags.should be_include("two") end it "should copy the resource's parameters as its own" do resource = Puppet::Resource.new(:mount, "/foo", :parameters => {:atboot => true, :fstype => "boo"}) params = Puppet::Type.type(:mount).new(resource).to_hash params[:fstype].should == "boo" params[:atboot].should == true end end describe "and passed a Hash" do it "should extract the title from the hash" do Puppet::Type.type(:mount).new(:title => "/yay").title.should == "/yay" end it "should work when hash keys are provided as strings" do Puppet::Type.type(:mount).new("title" => "/yay").title.should == "/yay" end it "should work when hash keys are provided as symbols" do Puppet::Type.type(:mount).new(:title => "/yay").title.should == "/yay" end it "should use the name from the hash as the title if no explicit title is provided" do Puppet::Type.type(:mount).new(:name => "/yay").title.should == "/yay" end it "should use the Resource Type's namevar to determine how to find the name in the hash" do yay = make_absolute('/yay') Puppet::Type.type(:file).new(:path => yay).title.should == yay end [:catalog].each do |param| it "should extract '#{param}' from the hash if present" do Puppet::Type.type(:mount).new(:name => "/yay", param => "foo").send(param).should == "foo" end end it "should use any remaining hash keys as its parameters" do resource = Puppet::Type.type(:mount).new(:title => "/foo", :catalog => "foo", :atboot => true, :fstype => "boo") resource[:fstype].must == "boo" resource[:atboot].must == true end end it "should fail if any invalid attributes have been provided" do lambda { Puppet::Type.type(:mount).new(:title => "/foo", :nosuchattr => "whatever") }.should raise_error(Puppet::Error) end it "should set its name to the resource's title if the resource does not have a :name or namevar parameter set" do resource = Puppet::Resource.new(:mount, "/foo") Puppet::Type.type(:mount).new(resource).name.should == "/foo" end it "should fail if no title, name, or namevar are provided" do lambda { Puppet::Type.type(:file).new(:atboot => true) }.should raise_error(Puppet::Error) end it "should set the attributes in the order returned by the class's :allattrs method" do Puppet::Type.type(:mount).stubs(:allattrs).returns([:name, :atboot, :noop]) resource = Puppet::Resource.new(:mount, "/foo", :parameters => {:name => "myname", :atboot => "myboot", :noop => "whatever"}) set = [] Puppet::Type.type(:mount).any_instance.stubs(:newattr).with do |param, hash| set << param true end.returns(stub_everything("a property")) Puppet::Type.type(:mount).new(resource) set[-1].should == :noop set[-2].should == :atboot end it "should always set the name and then default provider before anything else" do Puppet::Type.type(:mount).stubs(:allattrs).returns([:provider, :name, :atboot]) resource = Puppet::Resource.new(:mount, "/foo", :parameters => {:name => "myname", :atboot => "myboot"}) set = [] Puppet::Type.type(:mount).any_instance.stubs(:newattr).with do |param, hash| set << param true end.returns(stub_everything("a property")) Puppet::Type.type(:mount).new(resource) set[0].should == :name set[1].should == :provider end # This one is really hard to test :/ it "should set each default immediately if no value is provided" do defaults = [] Puppet::Type.type(:service).any_instance.stubs(:set_default).with { |value| defaults << value; true } Puppet::Type.type(:service).new :name => "whatever" defaults[0].should == :provider end it "should retain a copy of the originally provided parameters" do Puppet::Type.type(:mount).new(:name => "foo", :atboot => true, :noop => false).original_parameters.should == {:atboot => true, :noop => false} end it "should delete the name via the namevar from the originally provided parameters" do Puppet::Type.type(:file).new(:name => make_absolute('/foo')).original_parameters[:path].should be_nil end end it "should have a class method for converting a hash into a Puppet::Resource instance" do Puppet::Type.type(:mount).must respond_to(:hash2resource) end describe "when converting a hash to a Puppet::Resource instance" do before do @type = Puppet::Type.type(:mount) end it "should treat a :title key as the title of the resource" do @type.hash2resource(:name => "/foo", :title => "foo").title.should == "foo" end it "should use the name from the hash as the title if no explicit title is provided" do @type.hash2resource(:name => "foo").title.should == "foo" end it "should use the Resource Type's namevar to determine how to find the name in the hash" do @type.stubs(:key_attributes).returns([ :myname ]) @type.hash2resource(:myname => "foo").title.should == "foo" end [:catalog].each do |attr| it "should use any provided #{attr}" do @type.hash2resource(:name => "foo", attr => "eh").send(attr).should == "eh" end end it "should set all provided parameters on the resource" do @type.hash2resource(:name => "foo", :fstype => "boo", :boot => "fee").to_hash.should == {:name => "foo", :fstype => "boo", :boot => "fee"} end it "should not set the title as a parameter on the resource" do @type.hash2resource(:name => "foo", :title => "eh")[:title].should be_nil end it "should not set the catalog as a parameter on the resource" do @type.hash2resource(:name => "foo", :catalog => "eh")[:catalog].should be_nil end it "should treat hash keys equivalently whether provided as strings or symbols" do resource = @type.hash2resource("name" => "foo", "title" => "eh", "fstype" => "boo") resource.title.should == "eh" resource[:name].should == "foo" resource[:fstype].should == "boo" end end describe "when retrieving current property values" do before do @resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) @resource.property(:ensure).stubs(:retrieve).returns :absent end it "should fail if its provider is unsuitable" do @resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) @resource.provider.class.expects(:suitable?).returns false lambda { @resource.retrieve_resource }.should raise_error(Puppet::Error) end it "should return a Puppet::Resource instance with its type and title set appropriately" do result = @resource.retrieve_resource result.should be_instance_of(Puppet::Resource) result.type.should == "Mount" result.title.should == "foo" end it "should set the name of the returned resource if its own name and title differ" do @resource[:name] = "my name" @resource.title = "other name" @resource.retrieve_resource[:name].should == "my name" end it "should provide a value for all set properties" do values = @resource.retrieve_resource [:ensure, :fstype, :pass].each { |property| values[property].should_not be_nil } end it "should provide a value for 'ensure' even if no desired value is provided" do @resource = Puppet::Type.type(:file).new(:path => make_absolute("/my/file/that/can't/exist")) end it "should not call retrieve on non-ensure properties if the resource is absent and should consider the property absent" do @resource.property(:ensure).expects(:retrieve).returns :absent @resource.property(:fstype).expects(:retrieve).never @resource.retrieve_resource[:fstype].should == :absent end it "should include the result of retrieving each property's current value if the resource is present" do @resource.property(:ensure).expects(:retrieve).returns :present @resource.property(:fstype).expects(:retrieve).returns 15 @resource.retrieve_resource[:fstype] == 15 end end describe "#to_resource" do it "should return a Puppet::Resource that includes properties, parameters and tags" do type_resource = Puppet::Type.type(:mount).new( :ensure => :present, :name => "foo", :fstype => "bar", :remounts => true ) type_resource.tags = %w{bar baz} # If it's not a property it's a parameter type_resource.parameters[:remounts].should_not be_a(Puppet::Property) type_resource.parameters[:fstype].is_a?(Puppet::Property).should be_true type_resource.property(:ensure).expects(:retrieve).returns :present type_resource.property(:fstype).expects(:retrieve).returns 15 resource = type_resource.to_resource resource.should be_a Puppet::Resource resource[:fstype].should == 15 resource[:remounts].should == :true resource.tags.should =~ %w{foo bar baz mount} end end describe ".title_patterns" do describe "when there's one namevar" do before do @type_class = Puppet::Type.type(:notify) @type_class.stubs(:key_attributes).returns([:one]) end it "should have a default pattern for when there's one namevar" do patterns = @type_class.title_patterns patterns.length.should == 1 patterns[0].length.should == 2 end it "should have a regexp that captures the entire string" do patterns = @type_class.title_patterns string = "abc\n\tdef" patterns[0][0] =~ string $1.should == "abc\n\tdef" end end end describe "when in a catalog" do before do @catalog = Puppet::Resource::Catalog.new @container = Puppet::Type.type(:component).new(:name => "container") @one = Puppet::Type.type(:file).new(:path => make_absolute("/file/one")) @two = Puppet::Type.type(:file).new(:path => make_absolute("/file/two")) @catalog.add_resource @container @catalog.add_resource @one @catalog.add_resource @two @catalog.add_edge @container, @one @catalog.add_edge @container, @two end it "should have no parent if there is no in edge" do @container.parent.should be_nil end it "should set its parent to its in edge" do @one.parent.ref.should == @container.ref end after do @catalog.clear(true) end end it "should have a 'stage' metaparam" do Puppet::Type.metaparamclass(:stage).should be_instance_of(Class) end describe "#suitable?" do let(:type) { Puppet::Type.type(:file) } let(:resource) { type.new :path => tmpfile('suitable') } let(:provider) { resource.provider } it "should be suitable if its type doesn't use providers" do type.stubs(:paramclass).with(:provider).returns nil resource.should be_suitable end it "should be suitable if it has a provider which is suitable" do resource.should be_suitable end it "should not be suitable if it has a provider which is not suitable" do provider.class.stubs(:suitable?).returns false resource.should_not be_suitable end it "should be suitable if it does not have a provider and there is a default provider" do resource.stubs(:provider).returns nil resource.should be_suitable end it "should not be suitable if it doesn't have a provider and there is not default provider" do resource.stubs(:provider).returns nil type.stubs(:defaultprovider).returns nil resource.should_not be_suitable end end describe "::instances" do it "should not fail if no suitable providers are found" do fake_type = Puppet::Type.newtype(:type_spec_fake_type) do newparam(:name) do isnamevar end newproperty(:prop1) do end provide(:fake1) do confine :exists => '/no/such/file' mk_resource_methods end end expect { fake_type.instances }.should_not raise_error end end describe "::ensurable?" do before :each do class TestEnsurableType < Puppet::Type def exists?; end def create; end def destroy; end end end it "is true if the class has exists?, create, and destroy methods defined" do TestEnsurableType.should be_ensurable end it "is false if exists? is not defined" do TestEnsurableType.class_eval { remove_method(:exists?) } TestEnsurableType.should_not be_ensurable end it "is false if create is not defined" do TestEnsurableType.class_eval { remove_method(:create) } TestEnsurableType.should_not be_ensurable end it "is false if destroy is not defined" do TestEnsurableType.class_eval { remove_method(:destroy) } TestEnsurableType.should_not be_ensurable end end end describe Puppet::Type::RelationshipMetaparam do include PuppetSpec::Files it "should be a subclass of Puppet::Parameter" do Puppet::Type::RelationshipMetaparam.superclass.should equal(Puppet::Parameter) end it "should be able to produce a list of subclasses" do Puppet::Type::RelationshipMetaparam.should respond_to(:subclasses) end describe "when munging relationships", :fails_on_windows => true do before do @path = make_absolute('/foo') @resource = Puppet::Type.type(:mount).new :name => @path @metaparam = Puppet::Type.metaparamclass(:require).new :resource => @resource end it "should accept Puppet::Resource instances" do ref = Puppet::Resource.new(:file, @path) @metaparam.munge(ref)[0].should equal(ref) end it "should turn any string into a Puppet::Resource" do @metaparam.munge("File[/ref]")[0].should be_instance_of(Puppet::Resource) end end it "should be able to validate relationships" do Puppet::Type.metaparamclass(:require).new(:resource => mock("resource")).should respond_to(:validate_relationship) end it "should fail if any specified resource is not found in the catalog" do catalog = mock 'catalog' resource = stub 'resource', :catalog => catalog, :ref => "resource" param = Puppet::Type.metaparamclass(:require).new(:resource => resource, :value => %w{Foo[bar] Class[test]}) catalog.expects(:resource).with("Foo[bar]").returns "something" catalog.expects(:resource).with("Class[Test]").returns nil param.expects(:fail).with { |string| string.include?("Class[Test]") } param.validate_relationship end end describe Puppet::Type.metaparamclass(:check) do include PuppetSpec::Files it "should warn and create an instance of ':audit'" do file = Puppet::Type.type(:file).new :path => make_absolute('/foo') file.expects(:warning) file[:check] = :mode file[:audit].should == [:mode] end end describe Puppet::Type.metaparamclass(:audit) do include PuppetSpec::Files before do @resource = Puppet::Type.type(:file).new :path => make_absolute('/foo') end it "should default to being nil" do @resource[:audit].should be_nil end it "should specify all possible properties when asked to audit all properties" do @resource[:audit] = :all list = @resource.class.properties.collect { |p| p.name } @resource[:audit].should == list end it "should accept the string 'all' to specify auditing all possible properties" do @resource[:audit] = 'all' list = @resource.class.properties.collect { |p| p.name } @resource[:audit].should == list end it "should fail if asked to audit an invalid property" do lambda { @resource[:audit] = :foobar }.should raise_error(Puppet::Error) end it "should create an attribute instance for each auditable property" do @resource[:audit] = :mode @resource.parameter(:mode).should_not be_nil end it "should accept properties specified as a string" do @resource[:audit] = "mode" @resource.parameter(:mode).should_not be_nil end it "should not create attribute instances for parameters, only properties" do @resource[:audit] = :noop @resource.parameter(:noop).should be_nil end describe "when generating the uniqueness key" do it "should include all of the key_attributes in alphabetical order by attribute name" do Puppet::Type.type(:file).stubs(:key_attributes).returns [:path, :mode, :owner] Puppet::Type.type(:file).stubs(:title_patterns).returns( [ [ /(.*)/, [ [:path, lambda{|x| x} ] ] ] ] ) myfile = make_absolute('/my/file') res = Puppet::Type.type(:file).new( :title => myfile, :path => myfile, :owner => 'root', :content => 'hello' ) res.uniqueness_key.should == [ nil, 'root', myfile] end end + + context "type attribute bracket methods" do + after :each do Puppet::Type.rmtype(:attributes) end + let :type do + Puppet::Type.newtype(:attributes) do + newparam(:name) {} + end + end + + it "should work with parameters" do + type.newparam(:param) {} + instance = type.new(:name => 'test') + + expect { instance[:param] = true }.should_not raise_error + expect { instance["param"] = true }.should_not raise_error + instance[:param].should == true + instance["param"].should == true + end + + it "should work with meta-parameters" do + instance = type.new(:name => 'test') + + expect { instance[:noop] = true }.should_not raise_error + expect { instance["noop"] = true }.should_not raise_error + instance[:noop].should == true + instance["noop"].should == true + end + + it "should work with properties" do + type.newproperty(:property) {} + instance = type.new(:name => 'test') + + expect { instance[:property] = true }.should_not raise_error + expect { instance["property"] = true }.should_not raise_error + instance.property(:property).must be + instance.should(:property).must be_true + end + + it "should handle proprieties correctly" do + # Order of assignment is significant in this test. + props = {} + [:one, :two, :three].each {|prop| type.newproperty(prop) {} } + instance = type.new(:name => "test") + + instance[:one] = "boo" + one = instance.property(:one) + instance.properties.must == [one] + + instance[:three] = "rah" + three = instance.property(:three) + instance.properties.must == [one, three] + + instance[:two] = "whee" + two = instance.property(:two) + instance.properties.must == [one, two, three] + end + end end diff --git a/test/ral/manager/attributes.rb b/test/ral/manager/attributes.rb index c3e449e9e..a0a8c0048 100755 --- a/test/ral/manager/attributes.rb +++ b/test/ral/manager/attributes.rb @@ -1,296 +1,228 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../lib/puppettest') require 'puppettest' require 'mocha' class TestTypeAttributes < Test::Unit::TestCase include PuppetTest def mktype type = Puppet::Type.newtype(:faketype) {} cleanup { Puppet::Type.rmtype(:faketype) } type end - def test_bracket_methods - type = mktype - - # make a namevar - type.newparam(:name) {} - - # make a property - type.newproperty(:property) {} - - # and a param - type.newparam(:param) - - inst = type.new(:name => "yay") - - # Make sure we can set each of them, including a metaparam - [:param, :property, :noop].each do |param| - assert_nothing_raised("Failed to set symbol") do - inst[param] = true - end - - assert_nothing_raised("Failed to set string") do - inst[param.to_s] = true - end - - if param == :property - assert(inst.property(param), "did not get obj for #{param}") - - assert_equal( - true, inst.should(param), - - "should value did not get set") - else - assert_equal(true, inst[param], "did not get correct value for #{param} from symbol") - assert_equal(true, inst[param.to_s], "did not get correct value for #{param} from string") - end - end - end - - def test_properties - type = mktype - - # make a namevar - type.newparam(:name) {} - - # make a couple of properties - props = [:one, :two, :three] - props.each do |prop| - type.newproperty(prop) {} - end - - inst = type.new(:name => "yay") - - inst[:one] = "boo" - one = inst.property(:one) - assert(one, "did not get obj for one") - assert_equal([one], inst.send(:properties), "got wrong properties") - - inst[:three] = "rah" - three = inst.property(:three) - assert(three, "did not get obj for three") - assert_equal([one, three], inst.send(:properties), "got wrong properties") - - inst[:two] = "whee" - two = inst.property(:two) - assert(two, "did not get obj for two") - assert_equal([one, two, three], inst.send(:properties), "got wrong properties") - end - def attr_check(type) @num ||= 0 @num += 1 name = "name#{@num}" inst = type.new(:name => name) [:meta, :param, :prop].each do |name| klass = type.attrclass(name) assert(klass, "did not get class for #{name}") obj = yield inst, klass assert_instance_of(klass, obj, "did not get object back") assert_equal( "value", inst.value(klass.name), "value was not correct from value method") assert_equal("value", obj.value, "value was not correct") end end def test_newattr type = mktype type.newparam(:name) {} # Make one of each param type { :meta => :newmetaparam, :param => :newparam, :prop => :newproperty }.each do |name, method| assert_nothing_raised("Could not make #{name} of type #{method}") do type.send(method, name) {} end end # Now set each of them attr_check(type) do |inst, klass| property = inst.newattr(klass.name) property.value = "value" property end # Now try it passing the class in attr_check(type) do |inst, klass| property = inst.newattr(klass) property.value = "value" property end # Lastly, make sure we can create and then set, separately attr_check(type) do |inst, klass| obj = inst.newattr(klass.name) assert_nothing_raised("Could not set value after creation") do obj.value = "value" end # Make sure we can't create a new param object new_attr = inst.newattr(klass.name) assert_equal(new_attr, obj, "newattr should return the same object if called a second time") obj end end def test_alias_parameter type = mktype type.newparam(:name) {} type.newparam(:one) {} type.newproperty(:two) {} aliases = { :three => :one, :four => :two } aliases.each do |new, old| assert_nothing_raised("Could not create alias parameter #{new}") do type.set_attr_alias new => old end end aliases.each do |new, old| assert_equal(old, type.attr_alias(new), "did not return alias info for #{new}") end assert_nil(type.attr_alias(:name), "got invalid alias info for name") inst = type.new(:name => "my name") assert(inst, "could not create instance") aliases.each do |new, old| val = "value #{new}" assert_nothing_raised do inst[new] = val end case old when :one # param assert_equal( val, inst[new], "Incorrect alias value for #{new} in []") else assert_equal(val, inst.should(new), "Incorrect alias value for #{new} in should") end assert_equal(val, inst.value(new), "Incorrect alias value for #{new}") assert_equal(val, inst.value(old), "Incorrect orig value for #{old}") end end # Make sure newattr handles required features correctly. def test_newattr_and_required_features # Make a type with some features type = mktype type.feature :fone, "Something" type.feature :ftwo, "Something else" type.newparam(:name) {} # Make three properties: one with no requirements, one with one, and one with two none = type.newproperty(:none) {} one = type.newproperty(:one, :required_features => :fone) {} two = type.newproperty(:two, :required_features => [:fone, :ftwo]) {} # Now make similar providers nope = type.provide(:nope) {} maybe = type.provide(:maybe) { has_feature :fone} yep = type.provide(:yep) { has_features :fone, :ftwo} attrs = [:none, :one, :two] # Now make sure that we get warnings and no properties in those cases where our providers do not support the features requested [nope, maybe, yep].each_with_index do |prov, i| resource = type.new(:provider => prov.name, :name => "test#{i}", :none => "a", :one => "b", :two => "c") case prov.name when :nope yes = [:none] no = [:one, :two] when :maybe yes = [:none, :one] no = [:two] when :yep yes = [:none, :one, :two] no = [] end yes.each { |a| assert(resource.should(a), "Did not get value for #{a} in #{prov.name}") } no.each do |a| assert_nil(resource.should(a), "Got value for unsupported %s in %s" % [a, prov.name]) if Puppet::Util::Log.sendlevel?(:info) assert(@logs.find { |l| l.message =~ /not managing attribute #{a}/ and l.level == :debug }, "No warning about failed %s" % a) end end @logs.clear end end # Make sure the 'check' metaparam just ignores non-properties, rather than failing. def test_check_allows_parameters file = Puppet::Type.type(:file) klass = file.attrclass(:check) resource = file.new(:path => tempfile) inst = klass.new(:resource => resource) {:property => [:owner, :group], :parameter => [:ignore, :recurse], :metaparam => [:require, :subscribe]}.each do |attrtype, attrs| assert_nothing_raised("Could not set check to a single #{attrtype} value") do inst.value = attrs[0] end if attrtype == :property assert(resource.property(attrs[0]), "Check did not create property instance during single check") end assert_nothing_raised("Could not set check to multiple #{attrtype} values") do inst.value = attrs end if attrtype == :property assert(resource.property(attrs[1]), "Check did not create property instance during multiple check") end end # But make sure actually invalid attributes fail assert_raise(Puppet::Error, ":check did not fail on invalid attribute") do inst.value = :nosuchattr end end def test_check_ignores_unsupported_params type = Puppet::Type.newtype(:unsupported) do feature :nosuchfeat, "testing" newparam(:name) {} newproperty(:yep) {} newproperty(:nope, :required_features => :nosuchfeat) {} end $yep = :absent type.provide(:only) do def self.supports_parameter?(param) param.name != :nope end def yep $yep end def yep=(v) $yep = v end end cleanup { Puppet::Type.rmtype(:unsupported) } obj = type.new(:name => "test", :check => :yep) obj.stubs(:newattr).returns(stub_everything("newattr")) obj.expects(:newattr).with(:nope).never obj[:check] = :all end end