diff options
author | Luke Kanies <luke@reductivelabs.com> | 2010-01-29 20:57:21 -0600 |
---|---|---|
committer | test branch <puppet-dev@googlegroups.com> | 2010-02-17 06:50:53 -0800 |
commit | 7089446697ad550c22012bc2b5572030727d67e1 (patch) | |
tree | 40d160f11839fe6e20311186ded4e621d23e1242 /spec | |
parent | 4871c909cd28c82b64d0b62d8a27e62737d8733d (diff) | |
download | puppet-7089446697ad550c22012bc2b5572030727d67e1.tar.gz puppet-7089446697ad550c22012bc2b5572030727d67e1.tar.xz puppet-7089446697ad550c22012bc2b5572030727d67e1.zip |
Removing Resource::Reference classes
This commit is hopefully less messy than it
first appears, but it's certainly cross-cutting.
The reason for all of this is that we previously only
looked up builtin resource types from outside the parser,
but now that the defined resource types are available globally
via environments, we can push that lookup code to Resource.
Once we do that, however, we have to have environment and
namespace information in every resource.
Here I remove the Resource::Reference classes (except
the AST class), and use Resource instances instead. I
did this because the shared code between the two classes
got incredibly complicated, such that they should have had
a hierarchical relationship disallowed by their constants.
This complexity convinced me just to get rid of References
entirely.
I also make Puppet::Parser::Resource a subclass
of Puppet::Resource.
There are still broken tests in test/, but this was a big
enough commit I wanted to get it in.
Signed-off-by: Luke Kanies <luke@reductivelabs.com>
Diffstat (limited to 'spec')
24 files changed, 565 insertions, 449 deletions
diff --git a/spec/integration/application/puppet.rb b/spec/integration/application/puppet.rb index 1342f3c5f..cfafc9c0c 100755 --- a/spec/integration/application/puppet.rb +++ b/spec/integration/application/puppet.rb @@ -14,7 +14,7 @@ describe "Puppet" do it "should be able to apply catalogs provided in a file in pson" do file_to_create = tmpfile("pson_catalog") catalog = Puppet::Resource::Catalog.new - resource = Puppet::Resource.new(:file, file_to_create, :content => "my stuff") + resource = Puppet::Resource.new(:file, file_to_create, :parameters => {:content => "my stuff"}) catalog.add_resource resource manifest = tmpfile("manifest") diff --git a/spec/integration/indirector/catalog/compiler.rb b/spec/integration/indirector/catalog/compiler.rb index 16102cafe..b4067a6bb 100755 --- a/spec/integration/indirector/catalog/compiler.rb +++ b/spec/integration/indirector/catalog/compiler.rb @@ -8,6 +8,7 @@ Puppet::Resource::Catalog.indirection.terminus(:compiler) describe Puppet::Resource::Catalog::Compiler do before do + Facter.stubs(:value).returns "something" @catalog = Puppet::Resource::Catalog.new @one = Puppet::Resource.new(:file, "/one") diff --git a/spec/unit/configurer.rb b/spec/unit/configurer.rb index 9fc46affd..48a197a37 100755 --- a/spec/unit/configurer.rb +++ b/spec/unit/configurer.rb @@ -84,6 +84,7 @@ describe Puppet::Configurer, "when executing a catalog run" do before do Puppet.settings.stubs(:use).returns(true) @agent = Puppet::Configurer.new + @agent.stubs(:prepare) @agent.stubs(:facts_for_uploading).returns({}) @agent.stubs(:retrieve_catalog).returns Puppet::Resource::Catalog.new @@ -122,7 +123,7 @@ describe Puppet::Configurer, "when executing a catalog run" do it "should log a failure and do nothing if no catalog can be retrieved" do @agent.expects(:retrieve_catalog).returns nil - Puppet.expects(:err) + Puppet.expects(:err).with "Could not retrieve catalog; skipping run" @agent.run end diff --git a/spec/unit/indirector/catalog/compiler.rb b/spec/unit/indirector/catalog/compiler.rb index d11daaa96..8339d1861 100755 --- a/spec/unit/indirector/catalog/compiler.rb +++ b/spec/unit/indirector/catalog/compiler.rb @@ -11,7 +11,7 @@ describe Puppet::Resource::Catalog::Compiler do before do Puppet::Rails.stubs(:init) Facter.stubs(:to_hash).returns({}) - Facter.stubs(:[]).returns(Facter::Util::Fact.new("something")) + Facter.stubs(:value).returns(Facter::Util::Fact.new("something")) end describe "when initializing" do @@ -44,7 +44,7 @@ describe Puppet::Resource::Catalog::Compiler do describe "and storeconfigs is enabled" do before do - Puppet.settings[:storeconfigs] = true + Puppet.settings.expects(:value).with(:storeconfigs).returns true end it "should initialize Rails if it is available" do @@ -141,11 +141,11 @@ describe Puppet::Resource::Catalog::Compiler do describe "when extracting facts from the request" do before do + Facter.stubs(:value).returns "something" @compiler = Puppet::Resource::Catalog::Compiler.new @request = stub 'request', :options => {} @facts = stub 'facts', :save => nil - Facter.stubs(:value).returns "something" end it "should do nothing if no facts are provided" do diff --git a/spec/unit/parser/ast/resource.rb b/spec/unit/parser/ast/resource.rb index b257cb116..391f4c770 100755 --- a/spec/unit/parser/ast/resource.rb +++ b/spec/unit/parser/ast/resource.rb @@ -9,16 +9,15 @@ describe Puppet::Parser::AST::Resource do @title = stub_everything 'title' @compiler = stub_everything 'compiler' @scope = Puppet::Parser::Scope.new(:compiler => @compiler) - @param1 = stub_everything 'parameter', :is_a? => true @scope.stubs(:resource).returns(stub_everything) - @params = ast::ASTArray.new( :children => [@param1]) - @resource = ast::Resource.new(:title => @title, :type => "Resource", :params => @params ) + @resource = ast::Resource.new(:title => @title, :type => "Resource", :params => ast::ASTArray.new(:children => []) ) @resource.stubs(:qualified_type).returns("Resource") - Puppet::Parser::Resource.stubs(:new).returns(stub_everything) end it "should evaluate all its parameters" do - @param1.expects(:safeevaluate).with(@scope) + param = stub 'param' + param.expects(:safeevaluate).with(@scope).returns Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", :source => stub("source")) + @resource.stubs(:params).returns [param] @resource.evaluate(@scope) end @@ -49,10 +48,10 @@ describe Puppet::Parser::AST::Resource do title_array.stubs(:flatten).returns([@title]) titles.stubs(:safeevaluate).with(@scope).returns(title_array) - Puppet::Parser::Resource.expects(:new).with { |hash| hash[:title] == @title } - @resource.title = titles - @resource.evaluate(@scope) + result = @resource.evaluate(@scope) + result[0].should be_instance_of(Puppet::Parser::Resource) + result[0].title.should == @title end it "should handover resources to the compiler" do @@ -77,18 +76,18 @@ describe Puppet::Parser::AST::Resource do title_array.stubs(:flatten).returns([@title]) titles.stubs(:safeevaluate).with(@scope).returns(title_array) - Puppet::Parser::Resource.stubs(:new).returns(resource) - @compiler.stubs(:add_resource).with(resource) + @compiler.stubs(:add_resource) @resource.title = titles - @resource.evaluate(@scope).should == [resource] + @resource.evaluate(@scope)[0].should be_instance_of(Puppet::Parser::Resource) end it "should generate virtual resources if it is virtual" do @resource.virtual = true - Puppet::Parser::Resource.expects(:new).with { |hash| hash[:virtual] == true } + result = @resource.evaluate(@scope) + result[0].should be_virtual @resource.evaluate(@scope) end @@ -96,8 +95,8 @@ describe Puppet::Parser::AST::Resource do it "should generate virtual and exported resources if it is exported" do @resource.exported = true - Puppet::Parser::Resource.expects(:new).with { |hash| hash[:virtual] == true and hash[:exported] == true } - - @resource.evaluate(@scope) + result = @resource.evaluate(@scope) + result[0].should be_virtual + result[0].should be_exported end end diff --git a/spec/unit/parser/ast/resource_reference.rb b/spec/unit/parser/ast/resource_reference.rb index 10d9678c3..ee42694b9 100755 --- a/spec/unit/parser/ast/resource_reference.rb +++ b/spec/unit/parser/ast/resource_reference.rb @@ -10,54 +10,31 @@ describe Puppet::Parser::AST::ResourceReference do @scope = Puppet::Parser::Scope.new() end - def newref(title, type) + def newref(type, title) title = stub 'title', :safeevaluate => title ref = Puppet::Parser::AST::ResourceReference.new(:type => type, :title => title) end - it "should evaluate correctly reference to builtin types" do - newref("/tmp/yay", "File").evaluate(@scope).to_s.should == "File[/tmp/yay]" + it "should correctly produce reference strings" do + newref("File", "/tmp/yay").evaluate(@scope).to_s.should == "File[/tmp/yay]" end - %{ "one::two" "one-two"}.each do |type| - it "should evaluate correctly reference to define" do - klass = stub 'klass', :title => "three", :name => type - @scope.stubs(:find_definition).returns(klass) - - newref("three", type).evaluate(@scope).to_ref.should == Puppet::Parser::Resource::Reference.new( :type => type, :title => "three" ).to_ref - end + it "should produce a single resource when the title evaluates to a string" do + newref("File", "/tmp/yay").evaluate(@scope).should == Puppet::Resource.new("file", "/tmp/yay") end - it "should be able to call qualified_class" do - klass = stub 'klass', :title => "three", :name => "one" - @scope.expects(:find_hostclass).with("one").returns(klass) - newref("three","class").qualified_class(@scope,"one").should == "one" - end - - it "should be able to find qualified classes when evaluating" do - klass = stub 'klass', :title => "one", :name => "one" - @scope.stubs(:find_hostclass).returns(klass) - - evaled = newref("one", "class").evaluate(@scope) - evaled.type.should == "Class" - evaled.title.should == "one" - end - - it "should return an array of reference if given an array of titles" do + it "should return an array of resources if given an array of titles" do titles = mock 'titles', :safeevaluate => ["title1","title2"] - ref = ast::ResourceReference.new( :title => titles, :type => "Resource" ) - ref.stubs(:qualified_type).with(@scope).returns("Resource") - - ref.evaluate(@scope).should have(2).elements + ref = ast::ResourceReference.new( :title => titles, :type => "File" ) + ref.evaluate(@scope).should == [ + Puppet::Resource.new("file", "title1"), + Puppet::Resource.new("file", "title2") + ] end - it "should qualify class of all titles for Class resource references" do - titles = mock 'titles', :safeevaluate => ["title1","title2"] - ref = ast::ResourceReference.new( :title => titles, :type => "Class" ) - ref.expects(:qualified_class).with(@scope,"title1").returns("class") - ref.expects(:qualified_class).with(@scope,"title2").returns("class") - - ref.evaluate(@scope) + it "should pass its scope's namespaces to all created resource references" do + @scope.add_namespace "foo" + newref("File", "/tmp/yay").evaluate(@scope).namespaces.should == ["foo"] end it "should return a correct representation when converting to string" do diff --git a/spec/unit/parser/collector.rb b/spec/unit/parser/collector.rb index 7f88bf754..9c2d722e5 100755 --- a/spec/unit/parser/collector.rb +++ b/spec/unit/parser/collector.rb @@ -52,11 +52,10 @@ end describe Puppet::Parser::Collector, "when collecting specific virtual resources" do before do @scope = mock 'scope' - @resource_type = mock 'resource_type' @vquery = mock 'vquery' @equery = mock 'equery' - @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @equery, @vquery, :virtual) + @collector = Puppet::Parser::Collector.new(@scope, "resource_type", @equery, @vquery, :virtual) end it "should not fail when it does not find any resources to collect" do diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb index 333046c77..6fd4d1fb5 100755 --- a/spec/unit/parser/compiler.rb +++ b/spec/unit/parser/compiler.rb @@ -174,10 +174,9 @@ describe Puppet::Parser::Compiler do it "should evaluate the main class if it exists" do compile_stub(:evaluate_main) - main_class = mock 'main_class' + main_class = @known_resource_types.add Puppet::Resource::Type.new(:hostclass, "") main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } @compiler.topscope.expects(:source=).with(main_class) - @known_resource_types.stubs(:find_hostclass).with("", "").returns(main_class) @compiler.compile end @@ -185,7 +184,7 @@ describe Puppet::Parser::Compiler do it "should create a new, empty 'main' if no main class exists" do compile_stub(:evaluate_main) @compiler.compile - @known_resource_types.find_hostclass("", "").should be_instance_of(Puppet::Resource::Type) + @known_resource_types.find_hostclass([""], "").should be_instance_of(Puppet::Resource::Type) end it "should evaluate any node classes" do @@ -252,7 +251,7 @@ describe Puppet::Parser::Compiler do it "should call finish() on all resources" do # Add a resource that does respond to :finish - resource = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish" + resource = Puppet::Parser::Resource.new "file", "finish", :scope => @scope resource.expects(:finish) @compiler.add_resource(@scope, resource) @@ -268,12 +267,12 @@ describe Puppet::Parser::Compiler do it "should call finish() in add_resource order" do resources = sequence('resources') - resource1 = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish1" + resource1 = Puppet::Parser::Resource.new "file", "finish1", :scope => @scope resource1.expects(:finish).in_sequence(resources) @compiler.add_resource(@scope, resource1) - resource2 = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish2" + resource2 = Puppet::Parser::Resource.new "file", "finish2", :scope => @scope resource2.expects(:finish).in_sequence(resources) @compiler.add_resource(@scope, resource2) diff --git a/spec/unit/parser/functions/defined.rb b/spec/unit/parser/functions/defined.rb new file mode 100755 index 000000000..0da8c4a31 --- /dev/null +++ b/spec/unit/parser/functions/defined.rb @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe "the 'defined' function" do + + before :each do + @scope = Puppet::Parser::Scope.new() + @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo")) + @scope.compiler = @compiler + end + + it "should exist" do + Puppet::Parser::Functions.function("defined").should == "function_defined" + end + + it "should be true when the name is defined as a class" do + @scope.known_resource_types.add Puppet::Resource::Type.new(:hostclass, "yayness") + @scope.function_defined("yayness").should be_true + end + + it "should be true when the name is defined as a definition" do + @scope.known_resource_types.add Puppet::Resource::Type.new(:definition, "yayness") + @scope.function_defined("yayness").should be_true + end + + it "should be true when the name is defined as a builtin type" do + @scope.function_defined("file").should be_true + end + + + it "should be true when any of the provided names are defined" do + @scope.known_resource_types.add Puppet::Resource::Type.new(:definition, "yayness") + @scope.function_defined(["meh", "yayness", "booness"]).should be_true + end + + it "should be false when a single given name is not defined" do + @scope.function_defined("meh").should be_false + end + + it "should be false when none of the names are defined" do + @scope.function_defined(["meh", "yayness", "booness"]).should be_false + end + + it "should be true when a resource reference is provided and the resource is in the catalog" do + resource = Puppet::Resource.new("file", "/my/file") + @compiler.add_resource(@scope, resource) + @scope.function_defined(resource).should be_true + end +end diff --git a/spec/unit/parser/functions/require.rb b/spec/unit/parser/functions/require.rb index 924990a5d..1d9ce931c 100755 --- a/spec/unit/parser/functions/require.rb +++ b/spec/unit/parser/functions/require.rb @@ -28,7 +28,7 @@ describe "the require function" do end it "should set the 'require' prarameter on the resource to a resource reference" do - @resource.expects(:set_parameter).with { |name, value| name == :require and value[0].is_a?(Puppet::Parser::Resource::Reference) } + @resource.expects(:set_parameter).with { |name, value| name == :require and value[0].is_a?(Puppet::Resource) } @scope.stubs(:function_include) @scope.function_require("myclass") end diff --git a/spec/unit/parser/functions/tag.rb b/spec/unit/parser/functions/tag.rb new file mode 100755 index 000000000..5fb467e59 --- /dev/null +++ b/spec/unit/parser/functions/tag.rb @@ -0,0 +1,24 @@ +#! /usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe "the 'tag' function" do + + before :each do + @scope = Puppet::Parser::Scope.new() + end + + it "should exist" do + Puppet::Parser::Functions.function(:tag).should == "function_tag" + end + + it "should tag the resource with any provided tags" do + resource = Puppet::Parser::Resource.new(:file, "/file", :scope => @scope) + @scope.expects(:resource).returns resource + + @scope.function_tag ["one", "two"] + + resource.should be_tagged("one") + resource.should be_tagged("two") + end +end diff --git a/spec/unit/parser/parser.rb b/spec/unit/parser/parser.rb index 84749c3fb..8cc29c9b8 100755 --- a/spec/unit/parser/parser.rb +++ b/spec/unit/parser/parser.rb @@ -429,6 +429,12 @@ describe Puppet::Parser do @krt.hostclass("foobar").parent.should == "yayness" end + it "should correctly set the parent class for multiple classes at a time" do + @parser.parse("class foobar inherits yayness {}\nclass boo inherits bar {}") + @krt.hostclass("foobar").parent.should == "yayness" + @krt.hostclass("boo").parent.should == "bar" + end + it "should define the code when some is provided" do @parser.parse("class foobar { $var = val }") @krt.hostclass("foobar").code.should_not be_nil @@ -451,5 +457,15 @@ describe Puppet::Parser do @krt.add(Puppet::Resource::Type.new(:hostclass, "foobar", :arguments => {"biz" => nil})) lambda { @parser.parse("class { foobar: biz => stuff }") }.should_not raise_error end + + it "should correctly mark exported resources as exported" do + @parser.parse("@@file { '/file': }") + @krt.hostclass("").code[0].exported.should be_true + end + + it "should correctly mark virtual resources as virtual" do + @parser.parse("@file { '/file': }") + @krt.hostclass("").code[0].virtual.should be_true + end end end diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb index bb3001c8e..0c70c817e 100755 --- a/spec/unit/parser/resource.rb +++ b/spec/unit/parser/resource.rb @@ -19,7 +19,7 @@ describe Puppet::Parser::Resource do args[:source] ||= "source" args[:scope] ||= stub('scope', :source => mock('source')) - {:type => "resource", :title => "testing", :source => "source", :scope => "scope"}.each do |param, value| + {:source => "source", :scope => "scope"}.each do |param, value| args[param] ||= value end @@ -30,7 +30,7 @@ describe Puppet::Parser::Resource do args[:params] = paramify(args[:source], params) end - Puppet::Parser::Resource.new(args) + Puppet::Parser::Resource.new("resource", "testing", args) end def param(name, value, source) @@ -61,19 +61,31 @@ describe Puppet::Parser::Resource do Puppet::Parser::Resource.ancestors.should be_include(Puppet::FileCollection::Lookup) end + it "should get its environment from its scope" do + scope = stub 'scope', :source => stub("source") + scope.expects(:environment).returns "foo" + Puppet::Parser::Resource.new("file", "whatever", :scope => scope).environment.should == "foo" + end + + it "should get its namespaces from its scope" do + scope = stub 'scope', :source => stub("source") + scope.expects(:namespaces).returns %w{one two} + Puppet::Parser::Resource.new("file", "whatever", :scope => scope).namespaces.should == %w{one two} + end + it "should be isomorphic if it is builtin and models an isomorphic type" do Puppet::Type.type(:file).expects(:isomorphic?).returns(true) - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true + @resource = Puppet::Parser::Resource.new("file", "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true end it "should not be isomorphic if it is builtin and models a non-isomorphic type" do Puppet::Type.type(:file).expects(:isomorphic?).returns(false) - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_false + @resource = Puppet::Parser::Resource.new("file", "whatever", :scope => @scope, :source => @source).isomorphic?.should be_false end it "should be isomorphic if it is not builtin" do newdefine "whatever" - @resource = Puppet::Parser::Resource.new(:type => "whatever", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true + @resource = Puppet::Parser::Resource.new("whatever", "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true end it "should have a array-indexing method for retrieving parameter values" do @@ -89,77 +101,68 @@ describe Puppet::Parser::Resource do end it "should be able to use the indexing operator to access parameters" do - resource = Puppet::Parser::Resource.new(:type => "resource", :title => "testing", :source => "source", :scope => "scope") + resource = Puppet::Parser::Resource.new("resource", "testing", :source => "source", :scope => "scope") resource["foo"] = "bar" resource["foo"].should == "bar" end it "should return the title when asked for a parameter named 'title'" do - Puppet::Parser::Resource.new(:type => "resource", :title => "testing", :source => "source", :scope => "scope")[:title].should == "testing" + Puppet::Parser::Resource.new("resource", "testing", :source => "source", :scope => "scope")[:title].should == "testing" end describe "when initializing" do before do - @arguments = {:type => "resource", :title => "testing", :scope => stub('scope', :source => mock('source'))} + @arguments = {:scope => stub('scope', :source => mock('source'))} end - [:type, :title, :scope].each do |name| - it "should fail unless #{name.to_s} is specified" do - try = @arguments.dup - try.delete(name) - lambda { Puppet::Parser::Resource.new(try) }.should raise_error(ArgumentError) - end + it "should fail unless #{name.to_s} is specified" do + lambda { Puppet::Parser::Resource.new('file', '/my/file') }.should raise_error(ArgumentError) end it "should set the reference correctly" do - res = Puppet::Parser::Resource.new(@arguments) + res = Puppet::Parser::Resource.new("resource", "testing", @arguments) res.ref.should == "Resource[testing]" end it "should be tagged with user tags" do tags = [ "tag1", "tag2" ] @arguments[:params] = [ param(:tag, tags , :source) ] - res = Puppet::Parser::Resource.new(@arguments) + res = Puppet::Parser::Resource.new("resource", "testing", @arguments) (res.tags & tags).should == tags end end describe "when refering to a resource with name canonicalization" do before do - @arguments = {:type => "file", :title => "/path/", :scope => stub('scope', :source => mock('source'))} + @arguments = {:scope => stub('scope', :source => mock('source'))} end it "should canonicalize its own name" do - res = Puppet::Parser::Resource.new(@arguments) + res = Puppet::Parser::Resource.new("file", "/path/", @arguments) res.ref.should == "File[/path]" end end describe "when evaluating" do - before do - @type = Puppet::Parser::Resource - - @definition = newdefine "mydefine" - @class = newclass "myclass" - @nodedef = newnode("mynode") - end - it "should evaluate the associated AST definition" do - res = @type.new(:type => "mydefine", :title => "whatever", :scope => @scope, :source => @source) - @definition.expects(:evaluate_code).with(res) + definition = newdefine "mydefine" + res = Puppet::Parser::Resource.new("mydefine", "whatever", :scope => @scope, :source => @source) + definition.expects(:evaluate_code).with(res) res.evaluate end it "should evaluate the associated AST class" do - res = @type.new(:type => "class", :title => "myclass", :scope => @scope, :source => @source) + @class = newclass "myclass" + res = Puppet::Parser::Resource.new("class", "myclass", :scope => @scope, :source => @source) @class.expects(:evaluate_code).with(res) res.evaluate end it "should evaluate the associated AST node" do - res = @type.new(:type => "node", :title => "mynode", :scope => @scope, :source => @source) - @nodedef.expects(:evaluate_code).with(res) + nodedef = newnode("mynode") + res = Puppet::Parser::Resource.new("node", "mynode", :scope => @scope, :source => @source) + nodedef.expects(:evaluate_code).with(res) res.evaluate end end @@ -169,7 +172,7 @@ describe Puppet::Parser::Resource do @class = newclass "myclass" @nodedef = newnode("mynode") - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source) + @resource = Puppet::Parser::Resource.new("file", "whatever", :scope => @scope, :source => @source) end it "should do nothing if it has already been finished" do @@ -292,7 +295,7 @@ describe Puppet::Parser::Resource do before do @scope_resource = stub 'scope_resource', :tags => %w{srone srtwo} @scope = stub 'scope', :resource => @scope_resource - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "yay", :scope => @scope, :source => mock('source')) + @resource = Puppet::Parser::Resource.new("file", "yay", :scope => @scope, :source => mock('source')) end it "should get tagged with the resource type" do @@ -304,19 +307,19 @@ describe Puppet::Parser::Resource do end it "should get tagged with each name in the title if the title is a qualified class name" do - resource = Puppet::Parser::Resource.new(:type => "file", :title => "one::two", :scope => @scope, :source => mock('source')) + resource = Puppet::Parser::Resource.new("file", "one::two", :scope => @scope, :source => mock('source')) resource.tags.should be_include("one") resource.tags.should be_include("two") end it "should get tagged with each name in the type if the type is a qualified class name" do - resource = Puppet::Parser::Resource.new(:type => "one::two", :title => "whatever", :scope => @scope, :source => mock('source')) + resource = Puppet::Parser::Resource.new("one::two", "whatever", :scope => @scope, :source => mock('source')) resource.tags.should be_include("one") resource.tags.should be_include("two") end it "should not get tagged with non-alphanumeric titles" do - resource = Puppet::Parser::Resource.new(:type => "file", :title => "this is a test", :scope => @scope, :source => mock('source')) + resource = Puppet::Parser::Resource.new("file", "this is a test", :scope => @scope, :source => mock('source')) resource.tags.should_not be_include("this is a test") end @@ -496,26 +499,26 @@ describe Puppet::Parser::Resource do @parser_resource.to_resource.virtual.should be_true end - it "should convert any parser resource references to Puppet::Resource::Reference instances" do - ref = Puppet::Parser::Resource::Reference.new(:title => "/my/file", :type => "file") + it "should convert any parser resource references to Puppet::Resource instances" do + ref = Puppet::Resource.new("file", "/my/file") @parser_resource = mkresource :source => @source, :params => {:foo => "bar", :fee => ref} result = @parser_resource.to_resource - result[:fee].should == Puppet::Resource::Reference.new(:file, "/my/file") + result[:fee].should == Puppet::Resource.new(:file, "/my/file") end - it "should convert any parser resource references to Puppet::Resource::Reference instances even if they are in an array" do - ref = Puppet::Parser::Resource::Reference.new(:title => "/my/file", :type => "file") + it "should convert any parser resource references to Puppet::Resource instances even if they are in an array" do + ref = Puppet::Resource.new("file", "/my/file") @parser_resource = mkresource :source => @source, :params => {:foo => "bar", :fee => ["a", ref]} result = @parser_resource.to_resource - result[:fee].should == ["a", Puppet::Resource::Reference.new(:file, "/my/file")] + result[:fee].should == ["a", Puppet::Resource.new(:file, "/my/file")] end - it "should convert any parser resource references to Puppet::Resource::Reference instances even if they are in an array of array, and even deeper" do - ref1 = Puppet::Parser::Resource::Reference.new(:title => "/my/file1", :type => "file") - ref2 = Puppet::Parser::Resource::Reference.new(:title => "/my/file2", :type => "file") + it "should convert any parser resource references to Puppet::Resource instances even if they are in an array of array, and even deeper" do + ref1 = Puppet::Resource.new("file", "/my/file1") + ref2 = Puppet::Resource.new("file", "/my/file2") @parser_resource = mkresource :source => @source, :params => {:foo => "bar", :fee => ["a", [ref1,ref2]]} result = @parser_resource.to_resource - result[:fee].should == ["a", Puppet::Resource::Reference.new(:file, "/my/file1"), Puppet::Resource::Reference.new(:file, "/my/file2")] + result[:fee].should == ["a", Puppet::Resource.new(:file, "/my/file1"), Puppet::Resource.new(:file, "/my/file2")] end it "should fail if the same param is declared twice" do @@ -531,4 +534,52 @@ describe Puppet::Parser::Resource do end.should raise_error(Puppet::ParseError) end end + + describe "when validating" do + it "should check each parameter" do + resource = Puppet::Parser::Resource.new :foo, "bar", :scope => stub("scope"), :source => stub("source") + resource[:one] = :two + resource[:three] = :four + resource.expects(:validate_parameter).with(:one) + resource.expects(:validate_parameter).with(:three) + resource.send(:validate) + end + + it "should raise a parse error when there's a failure" do + resource = Puppet::Parser::Resource.new :foo, "bar", :scope => stub("scope"), :source => stub("source") + resource[:one] = :two + resource.expects(:validate_parameter).with(:one).raises ArgumentError + lambda { resource.send(:validate) }.should raise_error(Puppet::ParseError) + end + end + + describe "when setting parameters" do + before do + @source = newclass "foobar" + @resource = Puppet::Parser::Resource.new :foo, "bar", :scope => stub("scope"), :source => @source + end + + it "should accept Param instances and add them to the parameter list" do + param = Puppet::Parser::Resource::Param.new :name => "foo", :value => "bar", :source => @source + @resource.set_parameter(param) + @resource["foo"].should == "bar" + end + + it "should fail when provided a parameter name but no value" do + lambda { @resource.set_parameter("myparam") }.should raise_error(ArgumentError) + end + + it "should use its source when provided a parameter name and value" do + @resource.set_parameter("myparam", "myvalue") + @resource["myparam"].should == "myvalue" + end + end + + # part of #629 -- the undef keyword. Make sure 'undef' params get skipped. + it "should not include 'undef' parameters when converting itself to a hash" do + resource = Puppet::Parser::Resource.new "file", "/tmp/testing", :source => mock("source"), :scope => mock("scope") + resource[:owner] = :undef + resource[:mode] = "755" + resource.to_hash[:owner].should be_nil + end end diff --git a/spec/unit/parser/resource/reference.rb b/spec/unit/parser/resource/reference.rb deleted file mode 100755 index a38604226..000000000 --- a/spec/unit/parser/resource/reference.rb +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -describe Puppet::Parser::Resource::Reference do - before do - @type = Puppet::Parser::Resource::Reference - end - - it "should get its environment from its scope" do - env = stub 'environment' - scope = stub 'scope', :environment => env - @type.new(:title => "foo", :type => "bar", :scope => scope).environment.should equal(env) - end - - it "should use the resource type collection helper to find its known resource types" do - Puppet::Parser::Resource::Reference.ancestors.should include(Puppet::Resource::TypeCollectionHelper) - end - - it "should use the file lookup module" do - Puppet::Parser::Resource::Reference.ancestors.should be_include(Puppet::FileCollection::Lookup) - end - - it "should require a type" do - proc { @type.new(:title => "yay") }.should raise_error(Puppet::DevError) - end - - it "should require a title" do - proc { @type.new(:type => "file") }.should raise_error(Puppet::DevError) - end - - it "should know when it refers to a builtin type" do - ref = @type.new(:type => "file", :title => "/tmp/yay") - ref.builtin?.should be_true - ref.builtintype.should equal(Puppet::Type.type(:file)) - end - - it "should return a downcased relationship-style resource reference for defined types" do - ref = @type.new(:type => "file", :title => "/tmp/yay") - ref.to_ref.should == ["file", "/tmp/yay"] - end - - it "should return a capitalized relationship-style resource reference for defined types" do - ref = @type.new(:type => "whatever", :title => "/tmp/yay") - ref.to_ref.should == ["Whatever", "/tmp/yay"] - end - - it "should return a resource reference string when asked" do - ref = @type.new(:type => "file", :title => "/tmp/yay") - ref.to_s.should == "File[/tmp/yay]" - end - - it "should canonize resource reference types" do - ref = @type.new(:type => "foo::bar", :title => "/tmp/yay") - ref.to_s.should == "Foo::Bar[/tmp/yay]" - end - - it "should canonize resource reference values" do - ref = @type.new(:type => "file", :title => "/tmp/yay/") - ref.to_s.should == "File[/tmp/yay]" - end - - it "should canonize resource reference values without order dependencies" do - args = [[:title, "/tmp/yay/"], [:type, "file"]] - ref = @type.new(args) - ref.to_s.should == "File[/tmp/yay]" - end - -end - -describe Puppet::Parser::Resource::Reference, " when modeling defined types" do - def newclass(name) - @known_resource_types.add Puppet::Resource::Type.new(:hostclass, name) - end - - def newdefine(name) - @known_resource_types.add Puppet::Resource::Type.new(:definition, name) - end - - def newnode(name) - @known_resource_types.add Puppet::Resource::Type.new(:node, name) - end - - before do - @type = Puppet::Parser::Resource::Reference - - @known_resource_types = Puppet::Resource::TypeCollection.new("myenv") - @definition = newdefine("mydefine") - @class = newclass("myclass") - @nodedef = newnode("mynode") - @node = Puppet::Node.new("yaynode") - - @compiler = Puppet::Parser::Compiler.new(@node) - @compiler.environment.stubs(:known_resource_types).returns @known_resource_types - end - - it "should be able to find defined types" do - ref = @type.new(:type => "mydefine", :title => "/tmp/yay", :scope => @compiler.topscope) - ref.builtin?.should be_false - ref.definedtype.should equal(@definition) - end - - it "should be able to find classes" do - ref = @type.new(:type => "class", :title => "myclass", :scope => @compiler.topscope) - ref.builtin?.should be_false - ref.definedtype.should equal(@class) - end - - it "should be able to find nodes" do - ref = @type.new(:type => "node", :title => "mynode", :scope => @compiler.topscope) - ref.builtin?.should be_false - ref.definedtype.object_id.should == @nodedef.object_id - end - - it "should only look for fully qualified classes" do - top = newclass "top" - sub = newclass "other::top" - - scope = @compiler.topscope.class.new(:parent => @compiler.topscope, :namespace => "other", :compiler => @compiler) - - ref = @type.new(:type => "class", :title => "top", :scope => scope) - ref.definedtype.name.should equal(top.name) - end - - it "should only look for fully qualified definitions" do - top = newdefine "top" - sub = newdefine "other::top" - - scope = @compiler.topscope.class.new(:parent => @compiler.topscope, :namespace => "other", :compiler => @compiler) - - ref = @type.new(:type => "top", :title => "foo", :scope => scope) - ref.definedtype.name.should equal(top.name) - end -end diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb index 799d05766..3d648fedf 100755 --- a/spec/unit/parser/scope.rb +++ b/spec/unit/parser/scope.rb @@ -8,6 +8,7 @@ describe Puppet::Parser::Scope do # This is necessary so we don't try to use the compiler to discover our parent. @topscope.parent = nil @scope = Puppet::Parser::Scope.new() + @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo")) @scope.parent = @topscope end @@ -104,7 +105,7 @@ describe Puppet::Parser::Scope do def create_class_scope(name) klass = newclass(name) - Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => @scope, :source => mock('source')).evaluate + Puppet::Parser::Resource.new("class", name, :scope => @scope, :source => mock('source')).evaluate return @scope.class_scope(klass) end @@ -315,6 +316,114 @@ describe Puppet::Parser::Scope do @scope.strinterp('==${10}==').should == "==value==" end + + describe "with qualified variables" do + before do + @scopes = {} + klass = @scope.known_resource_types.add(Puppet::Resource::Type.new(:hostclass, "")) + Puppet::Parser::Resource.new("class", :main, :scope => @scope, :source => mock('source')).evaluate + @scopes[""] = @scope.compiler.class_scope(klass) + @scopes[""].setvar("test", "value") + + %w{one one::two one::two::three}.each do |name| + klass = @scope.known_resource_types.add(Puppet::Resource::Type.new(:hostclass, name)) + Puppet::Parser::Resource.new("class", name, :scope => @scope, :source => mock('source')).evaluate + @scopes[name] = @scope.compiler.class_scope(klass) + @scopes[name].setvar("test", "value-#{name.sub(/.+::/,'')}") + end + end + { + "===${one::two::three::test}===" => "===value-three===", + "===$one::two::three::test===" => "===value-three===", + "===${one::two::test}===" => "===value-two===", + "===$one::two::test===" => "===value-two===", + "===${one::test}===" => "===value-one===", + "===$one::test===" => "===value-one===", + "===${::test}===" => "===value===", + "===$::test===" => "===value===" + }.each do |input, output| + it "should parse '#{input}' correctly" do + @scope.strinterp(input).should == output + end + end + end + + tests = { + "===${test}===" => "===value===", + "===${test} ${test} ${test}===" => "===value value value===", + "===$test ${test} $test===" => "===value value value===", + "===\\$test===" => "===$test===", + '===\\$test string===' => "===$test string===", + '===$test string===' => "===value string===", + '===a testing $===' => "===a testing $===", + '===a testing \$===' => "===a testing $===", + "===an escaped \\\n carriage return===" => "===an escaped carriage return===", + '\$' => "$", + '\s' => "\s", + '\t' => "\t", + '\n' => "\n" + } + + tests.each do |input, output| + it "should parse '#{input}' correctly" do + @scope.setvar("test", "value") + @scope.strinterp(input).should == output + end + end + + # #523 + %w{d f h l w z}.each do |l| + it "should parse '#{l}' when escaped" do + string = "\\" + l + @scope.strinterp(string).should == string + end + end + end + + def test_strinterp + # Make and evaluate our classes so the qualified lookups work + parser = mkparser + klass = parser.newclass("") + scope = mkscope(:parser => parser) + Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => scope, :source => mock('source')).evaluate + + assert_nothing_raised { + scope.setvar("test","value") + } + + scopes = {"" => scope} + + %w{one one::two one::two::three}.each do |name| + klass = parser.newclass(name) + Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => scope, :source => mock('source')).evaluate + scopes[name] = scope.compiler.class_scope(klass) + scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,'')) + end + + assert_equal("value", scope.lookupvar("::test"), "did not look up qualified value correctly") + tests.each do |input, output| + assert_nothing_raised("Failed to scan %s" % input.inspect) do + assert_equal(output, scope.strinterp(input), + 'did not parserret %s correctly' % input.inspect) + end + end + + logs = [] + Puppet::Util::Log.close + Puppet::Util::Log.newdestination(logs) + + # #523 + %w{d f h l w z}.each do |l| + string = "\\" + l + assert_nothing_raised do + assert_equal(string, scope.strinterp(string), + 'did not parserret %s correctly' % string) + end + + assert(logs.detect { |m| m.message =~ /Unrecognised escape/ }, + "Did not get warning about escape sequence with %s" % string) + logs.clear + end end describe "when setting ephemeral vars from matches" do @@ -357,4 +466,50 @@ describe Puppet::Parser::Scope do @scope.lookupvar("foo").should == "" end end + + it "should use its namespaces to find hostclasses" do + klass = @scope.known_resource_types.add Puppet::Resource::Type.new(:hostclass, "a::b::c") + @scope.add_namespace "a::b" + @scope.find_hostclass("c").should equal(klass) + end + + it "should use its namespaces to find definitions" do + define = @scope.known_resource_types.add Puppet::Resource::Type.new(:definition, "a::b::c") + @scope.add_namespace "a::b" + @scope.find_definition("c").should equal(define) + end + + describe "when managing defaults" do + it "should be able to set and lookup defaults" do + param = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param) + @scope.lookupdefaults(:mytype).should == {:myparam => param} + end + + it "should fail if a default is already defined and a new default is being defined" do + param = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param) + lambda { @scope.setdefaults(:mytype, param) }.should raise_error(Puppet::ParseError) + end + + it "should return multiple defaults at once" do + param1 = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param1) + param2 = Puppet::Parser::Resource::Param.new(:name => :other, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param2) + + @scope.lookupdefaults(:mytype).should == {:myparam => param1, :other => param2} + end + + it "should look up defaults defined in parent scopes" do + param1 = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param1) + + child_scope = @scope.newscope + param2 = Puppet::Parser::Resource::Param.new(:name => :other, :value => "myvalue", :source => stub("source")) + child_scope.setdefaults(:mytype, param2) + + child_scope.lookupdefaults(:mytype).should == {:myparam => param1, :other => param2} + end + end end diff --git a/spec/unit/rails/param_value.rb b/spec/unit/rails/param_value.rb index 26e87fec2..070ac82ea 100755 --- a/spec/unit/rails/param_value.rb +++ b/spec/unit/rails/param_value.rb @@ -42,7 +42,7 @@ describe "Puppet::Rails::ParamValue" do end it "should not convert Resource References into strings" do - ref = Puppet::Resource::Reference.new(:file, "/file") + ref = Puppet::Resource.new(:file, "/file") Puppet::Rails::ParamValue.from_parser_param(:myparam, ref)[0][:value].should == ref end end diff --git a/spec/unit/resource.rb b/spec/unit/resource.rb index 73bbfd865..c97cd634f 100755 --- a/spec/unit/resource.rb +++ b/spec/unit/resource.rb @@ -12,71 +12,89 @@ describe Puppet::Resource do end end - describe "when initializing" do - it "should require the type and title" do - lambda { Puppet::Resource.new }.should raise_error(ArgumentError) - end + it "should have a :title attribute" do + Puppet::Resource.new(:file, "foo").title.should == "foo" + end - it "should create a resource reference with its type and title" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).with("file", "/f").returns ref - Puppet::Resource.new("file", "/f") - end + it "should require the type and title" do + lambda { Puppet::Resource.new }.should raise_error(ArgumentError) + end - it "should tag itself with its type" do - Puppet::Resource.new("file", "/f").should be_tagged("file") - end + it "should canonize types to capitalized strings" do + Puppet::Resource.new(:file, "foo").type.should == "File" + end - it "should tag itself with its title if the title is a valid tag" do - Puppet::Resource.new("file", "bar").should be_tagged("bar") - end + it "should canonize qualified types so all strings are capitalized" do + Puppet::Resource.new("foo::bar", "foo").type.should == "Foo::Bar" + end - it "should not tag itself with its title if the title is a not valid tag" do - Puppet::Resource.new("file", "/bar").should_not be_tagged("/bar") - end + it "should tag itself with its type" do + Puppet::Resource.new("file", "/f").should be_tagged("file") + end - it "should allow setting of attributes" do - Puppet::Resource.new("file", "/bar", :file => "/foo").file.should == "/foo" - Puppet::Resource.new("file", "/bar", :exported => true).should be_exported - end + it "should tag itself with its title if the title is a valid tag" do + Puppet::Resource.new("file", "bar").should be_tagged("bar") end - it "should use the resource reference to determine its type" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:type).returns "mytype" - resource.type.should == "mytype" + it "should not tag itself with its title if the title is a not valid tag" do + Puppet::Resource.new("file", "/bar").should_not be_tagged("/bar") end - it "should use its resource reference to determine its title" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:title).returns "mytitle" - resource.title.should == "mytitle" + it "should allow setting of attributes" do + Puppet::Resource.new("file", "/bar", :file => "/foo").file.should == "/foo" + Puppet::Resource.new("file", "/bar", :exported => true).should be_exported end - it "should use its resource reference to determine whether it is builtin" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:builtin_type?).returns "yep" - resource.builtin_type?.should == "yep" + it "should set its type to 'Class' and its title to the passed title if the passed type is :component and the title has no square brackets in it" do + ref = Puppet::Resource.new(:component, "foo") + ref.type.should == "Class" + ref.title.should == "foo" end - it "should call its builtin_type? method when 'builtin?' is called" do - resource = Puppet::Resource.new("file", "/f") - resource.expects(:builtin_type?).returns "foo" - resource.builtin?.should == "foo" + it "should interpret the title as a reference and assign appropriately if the type is :component and the title contains square brackets" do + ref = Puppet::Resource.new(:component, "foo::bar[yay]") + ref.type.should == "Foo::Bar" + ref.title.should == "yay" end - it "should use its resource reference to produce its canonical reference string" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:to_s).returns "Foo[bar]" - resource.ref.should == "Foo[bar]" + it "should set the type to 'Class' if it is nil and the title contains no square brackets" do + ref = Puppet::Resource.new(nil, "yay") + ref.type.should == "Class" + ref.title.should == "yay" + end + + it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains square brackets" do + ref = Puppet::Resource.new(nil, "foo::bar[yay]") + ref.type.should == "Foo::Bar" + ref.title.should == "yay" + end + + it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains nested square brackets" do + ref = Puppet::Resource.new(nil, "foo::bar[baz[yay]]") + ref.type.should == "Foo::Bar" + ref.title.should =="baz[yay]" + end + + it "should interpret the type as a reference and assign appropriately if the title is nil and the type contains square brackets" do + ref = Puppet::Resource.new("foo::bar[baz]") + ref.type.should == "Foo::Bar" + ref.title.should =="baz" + end + + it "should be able to extract its information from a Puppet::Type instance" do + ral = Puppet::Type.type(:file).new :path => "/foo" + ref = Puppet::Resource.new(ral) + ref.type.should == "File" + ref.title.should == "/foo" + end + + + it "should fail if the title is nil and the type is not a valid resource reference string" do + lambda { Puppet::Resource.new("foo") }.should raise_error(ArgumentError) + end + + it "should be able to produce a backward-compatible reference array" do + Puppet::Resource.new("foobar", "/f").to_trans_ref.should == %w{Foobar /f} end it "should be taggable" do @@ -94,12 +112,16 @@ describe Puppet::Resource do Puppet::Resource.new("file", "/my/file", :environment => :foo).environment.name.should == :foo end - it "should support a namespace attribute" do - Puppet::Resource.new("file", "/my/file", :namespace => :foo).namespace.should == :foo + it "should support specifying namespaces" do + Puppet::Resource.new("file", "/my/file", :namespaces => [:foo]).namespaces.should == [:foo] + end + + it "should convert namespaces to an array if not specified as one" do + Puppet::Resource.new("file", "/my/file", :namespaces => :foo).namespaces.should == [:foo] end - it "should default to a namespace of an empty string" do - Puppet::Resource.new("file", "/my/file").namespace.should == "" + it "should default to a single amespace of an empty string" do + Puppet::Resource.new("file", "/my/file").namespaces.should == [""] end it "should be able to look up its resource type when the type is a builtin resource" do @@ -130,16 +152,16 @@ describe Puppet::Resource do resource.resource_type.should equal(klass) end - it "should use its namespace when looking up defined resource types" do - resource = Puppet::Resource.new("bar", "/my/file", :namespace => "foo") + it "should use its namespaces when looking up defined resource types" do + resource = Puppet::Resource.new("bar", "/my/file", :namespaces => ["foo"]) type = Puppet::Resource::Type.new(:definition, "foo::bar") resource.environment.known_resource_types.add type resource.resource_type.should equal(type) end - it "should use its namespace when looking up host classes" do - resource = Puppet::Resource.new("class", "bar", :namespace => "foo") + it "should use its namespaces when looking up host classes" do + resource = Puppet::Resource.new("class", "bar", :namespaces => ["foo"]) type = Puppet::Resource::Type.new(:hostclass, "foo::bar") resource.environment.known_resource_types.add type @@ -171,6 +193,30 @@ describe Puppet::Resource do resource[:yay] = true end + it "should be considered equivalent to another resource if their type and title match and no parameters are set" do + Puppet::Resource.new("file", "/f").should == Puppet::Resource.new("file", "/f") + end + + it "should be considered equivalent to another resource if their type, title, and parameters are equal" do + Puppet::Resource.new("file", "/f", :parameters => {:foo => "bar"}).should == Puppet::Resource.new("file", "/f", :parameters => {:foo => "bar"}) + end + + it "should not be considered equivalent to another resource if their type and title match but parameters are different" do + Puppet::Resource.new("file", "/f", :parameters => {:fee => "baz"}).should_not == Puppet::Resource.new("file", "/f", :parameters => {:foo => "bar"}) + end + + it "should not be considered equivalent to a non-resource" do + Puppet::Resource.new("file", "/f").should_not == "foo" + end + + it "should not be considered equivalent to another resource if their types do not match" do + Puppet::Resource.new("file", "/f").should_not == Puppet::Resource.new("exec", "/f") + end + + it "should not be considered equivalent to another resource if their titles do not match" do + Puppet::Resource.new("file", "/foo").should_not == Puppet::Resource.new("file", "/f") + end + describe "when managing parameters" do before do @resource = Puppet::Resource.new("file", "/my/file") @@ -305,7 +351,10 @@ describe Puppet::Resource do end it "should set :name to the title if :name is not present for non-builtin types" do + krt = Puppet::Resource::TypeCollection.new("myenv") + krt.add Puppet::Resource::Type.new(:definition, :foo) resource = Puppet::Resource.new :foo, "bar" + resource.stubs(:known_resource_types).returns krt resource.to_hash[:name].should == "bar" end end @@ -334,25 +383,19 @@ describe Puppet::Resource do end describe "when converting to a RAL resource" do - before do - @resource = Puppet::Resource.new("file", "/my/file") - @resource["one"] = "test" - @resource["two"] = "other" - end - - it "should use the resource type's :create method to create the resource if the resource is of a builtin type" do - type = mock 'resource type' - type.expects(:new).with(@resource).returns(:myresource) - Puppet::Type.expects(:type).with(@resource.type).returns(type) - @resource.to_ral.should == :myresource + it "should use the resource type's :new method to create the resource if the resource is of a builtin type" do + resource = Puppet::Resource.new("file", "/my/file") + result = resource.to_ral + result.should be_instance_of(Puppet::Type.type(:file)) + result[:path].should == "/my/file" end it "should convert to a component instance if the resource type is not of a builtin type" do - component = mock 'component type' - Puppet::Type::Component.expects(:new).with(@resource).returns "meh" + resource = Puppet::Resource.new("foobar", "somename") + result = resource.to_ral - Puppet::Type.expects(:type).with(@resource.type).returns(nil) - @resource.to_ral.should == "meh" + result.should be_instance_of(Puppet::Type.type(:component)) + result.title.should == "Foobar[somename]" end end @@ -450,13 +493,13 @@ describe Puppet::Resource do end it "should convert resource references into the backward-compatible form" do - @resource[:foo] = Puppet::Resource::Reference.new(:file, "/f") - @resource.to_trans["foo"].should == %w{file /f} + @resource[:foo] = Puppet::Resource.new(:file, "/f") + @resource.to_trans["foo"].should == %w{File /f} end it "should convert resource references into the backward-compatible form even when within arrays" do - @resource[:foo] = ["a", Puppet::Resource::Reference.new(:file, "/f")] - @resource.to_trans["foo"].should == ["a", %w{file /f}] + @resource[:foo] = ["a", Puppet::Resource.new(:file, "/f")] + @resource.to_trans["foo"].should == ["a", %w{File /f}] end end end @@ -618,4 +661,16 @@ describe Puppet::Resource do Puppet::Resource.new("file", "/my/file").name.should == "File//my/file" end end + + describe "when resolving resources with a catalog" do + it "should resolve all resources using the catalog" do + catalog = mock 'catalog' + resource = Puppet::Resource.new("foo::bar", "yay") + resource.catalog = catalog + + catalog.expects(:resource).with("Foo::Bar[yay]").returns(:myresource) + + resource.resolve.should == :myresource + end + end end diff --git a/spec/unit/resource/catalog.rb b/spec/unit/resource/catalog.rb index e2fe72489..6c6af24ce 100755 --- a/spec/unit/resource/catalog.rb +++ b/spec/unit/resource/catalog.rb @@ -109,7 +109,7 @@ describe Puppet::Resource::Catalog, "when compiling" do end def mkresource(type, name) - Puppet::Parser::Resource.new(:type => type, :title => name, :source => @source, :scope => @scope) + Puppet::Parser::Resource.new(type, name, :source => @source, :scope => @scope) end it "should always create a TransBucket for the 'main' class" do diff --git a/spec/unit/resource/reference.rb b/spec/unit/resource/reference.rb deleted file mode 100755 index 7a9704508..000000000 --- a/spec/unit/resource/reference.rb +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../spec_helper' - -require 'puppet/resource/reference' - -describe Puppet::Resource::Reference do - it "should have a :title attribute" do - Puppet::Resource::Reference.new(:file, "foo").title.should == "foo" - end - - it "should canonize types to capitalized strings" do - Puppet::Resource::Reference.new(:file, "foo").type.should == "File" - end - - it "should canonize qualified types so all strings are capitalized" do - Puppet::Resource::Reference.new("foo::bar", "foo").type.should == "Foo::Bar" - end - - it "should set its type to 'Class' and its title to the passed title if the passed type is :component and the title has no square brackets in it" do - ref = Puppet::Resource::Reference.new(:component, "foo") - ref.type.should == "Class" - ref.title.should == "foo" - end - - it "should interpret the title as a reference and assign appropriately if the type is :component and the title contains square brackets" do - ref = Puppet::Resource::Reference.new(:component, "foo::bar[yay]") - ref.type.should == "Foo::Bar" - ref.title.should == "yay" - end - - it "should set the type to 'Class' if it is nil and the title contains no square brackets" do - ref = Puppet::Resource::Reference.new(nil, "yay") - ref.type.should == "Class" - ref.title.should == "yay" - end - - it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains square brackets" do - ref = Puppet::Resource::Reference.new(nil, "foo::bar[yay]") - ref.type.should == "Foo::Bar" - ref.title.should == "yay" - end - - it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains nested square brackets" do - ref = Puppet::Resource::Reference.new(nil, "foo::bar[baz[yay]]") - ref.type.should == "Foo::Bar" - ref.title.should =="baz[yay]" - end - - it "should interpret the type as a reference and assign appropriately if the title is nil and the type contains square brackets" do - ref = Puppet::Resource::Reference.new("foo::bar[baz]") - ref.type.should == "Foo::Bar" - ref.title.should =="baz" - end - - it "should be able to extract its information from a Puppet::Type instance" do - ral = Puppet::Type.type(:file).new :path => "/foo" - ref = Puppet::Resource::Reference.new(ral) - ref.type.should == "File" - ref.title.should == "/foo" - end - - - it "should fail if the title is nil and the type is not a valid resource reference string" do - lambda { Puppet::Resource::Reference.new("foo") }.should raise_error(ArgumentError) - end - - it "should be considered builtin if an existing resource type matches the type" do - Puppet::Resource::Reference.new("file", "/f").should be_builtin_type - end - - it "should be not considered builtin if an existing resource type does not match the type" do - Puppet::Resource::Reference.new("foobar", "/f").should_not be_builtin_type - end - - it "should be able to produce a backward-compatible reference array" do - Puppet::Resource::Reference.new("foobar", "/f").to_trans_ref.should == %w{Foobar /f} - end - - it "should downcase resource types when producing a backward-compatible reference array for builtin resource types" do - Puppet::Resource::Reference.new("file", "/f").to_trans_ref.should == %w{file /f} - end - - it "should be considered equivalent to another reference if their type and title match" do - Puppet::Resource::Reference.new("file", "/f").should == Puppet::Resource::Reference.new("file", "/f") - end - - it "should not be considered equivalent to a non-reference" do - Puppet::Resource::Reference.new("file", "/f").should_not == "foo" - end - - it "should not be considered equivalent to another reference if their types do not match" do - Puppet::Resource::Reference.new("file", "/f").should_not == Puppet::Resource::Reference.new("exec", "/f") - end - - it "should not be considered equivalent to another reference if their titles do not match" do - Puppet::Resource::Reference.new("file", "/foo").should_not == Puppet::Resource::Reference.new("file", "/f") - end - - describe "when resolving resources with a catalog" do - it "should resolve all resources using the catalog" do - config = mock 'catalog' - ref = Puppet::Resource::Reference.new("foo::bar", "yay") - ref.catalog = config - - config.expects(:resource).with("Foo::Bar[yay]").returns(:myresource) - - ref.resolve.should == :myresource - end - end -end diff --git a/spec/unit/resource/type.rb b/spec/unit/resource/type.rb index 0a2f447ef..1a19cf4f0 100755 --- a/spec/unit/resource/type.rb +++ b/spec/unit/resource/type.rb @@ -456,13 +456,13 @@ describe Puppet::Resource::Type do end it "should fail unless it is a class" do - lambda { Puppet::Resource::Type.new(:node, "bar").merge("foo") }.should raise_error(ArgumentError) + lambda { Puppet::Resource::Type.new(:node, "bar").merge("foo") }.should raise_error(Puppet::Error) end it "should fail unless the source instance is a class" do dest = Puppet::Resource::Type.new(:hostclass, "bar") source = Puppet::Resource::Type.new(:node, "foo") - lambda { dest.merge(source) }.should raise_error(ArgumentError) + lambda { dest.merge(source) }.should raise_error(Puppet::Error) end it "should fail if both classes have different parent classes" do @@ -471,7 +471,7 @@ describe Puppet::Resource::Type do code.add Puppet::Resource::Type.new(:hostclass, parent) code.add Puppet::Resource::Type.new(:hostclass, child, :parent => parent) end - lambda { code.hostclass("b").merge(code.hostclass("d")) }.should raise_error(ArgumentError) + lambda { code.hostclass("b").merge(code.hostclass("d")) }.should raise_error(Puppet::Error) end it "should copy the other class's parent if it has not parent" do diff --git a/spec/unit/resource/type_collection.rb b/spec/unit/resource/type_collection.rb index 3de5e504b..a2a213f5a 100644 --- a/spec/unit/resource/type_collection.rb +++ b/spec/unit/resource/type_collection.rb @@ -64,7 +64,32 @@ describe Puppet::Resource::TypeCollection do @code.definition("foo").should equal(define) end + it "should merge new classes with existing classes of the same name" do + loader = Puppet::Resource::TypeCollection.new("env") + first = Puppet::Resource::Type.new(:hostclass, "foo") + second = Puppet::Resource::Type.new(:hostclass, "foo") + loader.add first + first.expects(:merge).with(second) + loader.add(second) + end + + it "should remove all nodes, classes, and definitions when cleared" do + loader = Puppet::Resource::TypeCollection.new("env") + loader.add Puppet::Resource::Type.new(:hostclass, "class") + loader.add Puppet::Resource::Type.new(:definition, "define") + loader.add Puppet::Resource::Type.new(:node, "node") + + loader.clear + loader.hostclass("class").should be_nil + loader.definition("define").should be_nil + loader.node("node").should be_nil + end + %w{hostclass node definition}.each do |data| + before do + @instance = Puppet::Resource::Type.new(data, "foo") + end + it "should have a method for adding a #{data}" do Puppet::Resource::TypeCollection.new("env").should respond_to("add_" + data) end @@ -75,10 +100,12 @@ describe Puppet::Resource::TypeCollection do loader.send(data, @instance.name).should equal(@instance) end - it "should fail to add a #{data} when one already exists" do - loader = Puppet::Resource::TypeCollection.new("env") - loader.add @instance - lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError) + unless data == "hostclass" + it "should fail to add a #{data} when one already exists" do + loader = Puppet::Resource::TypeCollection.new("env") + loader.add @instance + lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError) + end end it "should return the added #{data}" do @@ -127,6 +154,13 @@ describe Puppet::Resource::TypeCollection do loader.find("namespace", "::foo::bar", :hostclass).should be_nil end + it "should be able to find classes in the base namespace" do + loader = Puppet::Resource::TypeCollection.new("env") + instance = Puppet::Resource::Type.new(:hostclass, "foo") + loader.add instance + loader.find("", "foo", :hostclass).should equal(instance) + end + it "should return the partially qualified object if it exists in a provided namespace" do loader = Puppet::Resource::TypeCollection.new("env") instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz") diff --git a/spec/unit/transportable.rb b/spec/unit/transportable.rb new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/spec/unit/transportable.rb diff --git a/spec/unit/type.rb b/spec/unit/type.rb index 73f249faa..b2f4bcbd4 100755 --- a/spec/unit/type.rb +++ b/spec/unit/type.rb @@ -464,13 +464,13 @@ describe Puppet::Type::RelationshipMetaparam do @metaparam = Puppet::Type.metaparamclass(:require).new :resource => @resource end - it "should accept Puppet::Resource::Reference instances" do - ref = Puppet::Resource::Reference.new(:file, "/foo") + it "should accept Puppet::Resource instances" do + ref = Puppet::Resource.new(:file, "/foo") @metaparam.munge(ref)[0].should equal(ref) end - it "should turn any string into a Puppet::Resource::Reference" do - @metaparam.munge("File[/ref]")[0].should be_instance_of(Puppet::Resource::Reference) + it "should turn any string into a Puppet::Resource" do + @metaparam.munge("File[/ref]")[0].should be_instance_of(Puppet::Resource) end end diff --git a/spec/unit/type/tidy.rb b/spec/unit/type/tidy.rb index ccec9ed7c..9bee7d700 100755 --- a/spec/unit/type/tidy.rb +++ b/spec/unit/type/tidy.rb @@ -390,7 +390,7 @@ describe tidy do "/what/ever/one/subone" => ["/what/ever/one/subone/ssone"] }.each do |parent, children| children.each do |child| - ref = Puppet::Resource::Reference.new(:file, child) + ref = Puppet::Resource.new(:file, child) result[parent][:require].find { |req| req.to_s == ref.to_s }.should_not be_nil end end |