summaryrefslogtreecommitdiffstats
path: root/spec/unit/parser
diff options
context:
space:
mode:
authorLuke Kanies <luke@reductivelabs.com>2010-01-29 20:57:21 -0600
committertest branch <puppet-dev@googlegroups.com>2010-02-17 06:50:53 -0800
commit7089446697ad550c22012bc2b5572030727d67e1 (patch)
tree40d160f11839fe6e20311186ded4e621d23e1242 /spec/unit/parser
parent4871c909cd28c82b64d0b62d8a27e62737d8733d (diff)
downloadpuppet-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/unit/parser')
-rwxr-xr-xspec/unit/parser/ast/resource.rb29
-rwxr-xr-xspec/unit/parser/ast/resource_reference.rb51
-rwxr-xr-xspec/unit/parser/collector.rb3
-rwxr-xr-xspec/unit/parser/compiler.rb11
-rwxr-xr-xspec/unit/parser/functions/defined.rb50
-rwxr-xr-xspec/unit/parser/functions/require.rb2
-rwxr-xr-xspec/unit/parser/functions/tag.rb24
-rwxr-xr-xspec/unit/parser/parser.rb16
-rwxr-xr-xspec/unit/parser/resource.rb143
-rwxr-xr-xspec/unit/parser/resource/reference.rb134
-rwxr-xr-xspec/unit/parser/scope.rb157
11 files changed, 378 insertions, 242 deletions
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