summaryrefslogtreecommitdiffstats
path: root/spec/unit
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-12-01 16:41:38 -0800
committerJames Turnbull <james@lovedthanlost.net>2009-12-09 02:13:03 +1100
commit8971d8beae2c409f9052f27c3f80ad3bdfff4de2 (patch)
treec6f7eda0523c31c2b2f3a02b3761bf43ef716ebf /spec/unit
parent39d4a935d47f1d42241ce492c48818dc5b533c29 (diff)
downloadpuppet-8971d8beae2c409f9052f27c3f80ad3bdfff4de2.tar.gz
puppet-8971d8beae2c409f9052f27c3f80ad3bdfff4de2.tar.xz
puppet-8971d8beae2c409f9052f27c3f80ad3bdfff4de2.zip
Fixing #2596 - Node, Class, Definition are not AST
This commit extracts these three classes into a single ResourceType class in the Parser heirarchy, now completely independent of the AST heirarchy. Most of the other changes are just changing the interface to the new class, which is greatly simplified over the previous classes. This opens up the possibility of drastically simplifying a lot of this other code, too -- in particular, replacing the reference to the parser with a reference to the (soon to be renamed) LoadedCode class. Signed-off-by: Luke Kanies <luke@madstop.com>
Diffstat (limited to 'spec/unit')
-rw-r--r--spec/unit/parser/ast.rb6
-rwxr-xr-xspec/unit/parser/ast/definition.rb213
-rwxr-xr-xspec/unit/parser/ast/hostclass.rb148
-rwxr-xr-xspec/unit/parser/ast/leaf.rb72
-rwxr-xr-xspec/unit/parser/ast/node.rb145
-rwxr-xr-xspec/unit/parser/ast/resource_reference.rb6
-rwxr-xr-xspec/unit/parser/compiler.rb32
-rw-r--r--spec/unit/parser/loaded_code.rb218
-rwxr-xr-xspec/unit/parser/parser.rb126
-rwxr-xr-xspec/unit/parser/resource/reference.rb4
-rwxr-xr-xspec/unit/parser/resource_type.rb522
-rwxr-xr-xspec/unit/util/rdoc/parser.rb23
12 files changed, 713 insertions, 802 deletions
diff --git a/spec/unit/parser/ast.rb b/spec/unit/parser/ast.rb
index 35f575b1b..ca6f8080a 100644
--- a/spec/unit/parser/ast.rb
+++ b/spec/unit/parser/ast.rb
@@ -20,9 +20,9 @@ describe Puppet::Parser::AST do
ast.should respond_to(:use_docs)
end
- [ Puppet::Parser::AST::Collection, Puppet::Parser::AST::Definition, Puppet::Parser::AST::Else,
- Puppet::Parser::AST::Function, Puppet::Parser::AST::HostClass, Puppet::Parser::AST::IfStatement,
- Puppet::Parser::AST::Node, Puppet::Parser::AST::Resource, Puppet::Parser::AST::ResourceDefaults,
+ [ Puppet::Parser::AST::Collection, Puppet::Parser::AST::Else,
+ Puppet::Parser::AST::Function, Puppet::Parser::AST::IfStatement,
+ Puppet::Parser::AST::Resource, Puppet::Parser::AST::ResourceDefaults,
Puppet::Parser::AST::ResourceOverride, Puppet::Parser::AST::VarDef
].each do |k|
it "#{k}.use_docs should return true" do
diff --git a/spec/unit/parser/ast/definition.rb b/spec/unit/parser/ast/definition.rb
deleted file mode 100755
index c26706524..000000000
--- a/spec/unit/parser/ast/definition.rb
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../../../spec_helper'
-
-describe Puppet::Parser::AST::Definition, "when initializing" do
-end
-
-describe Puppet::Parser::AST::Definition, "when evaluating" do
- before do
- @type = Puppet::Parser::Resource
- @parser = Puppet::Parser::Parser.new :Code => ""
- @source = @parser.newclass ""
- @definition = @parser.newdefine "mydefine"
- @node = Puppet::Node.new("yaynode")
- @compiler = Puppet::Parser::Compiler.new(@node, @parser)
- @scope = @compiler.topscope
-
- @resource = Puppet::Parser::Resource.new(:type => "mydefine", :title => "myresource", :scope => @scope, :source => @source)
- end
-
- it "should create a new scope" do
- scope = nil
- code = mock 'code'
- code.expects(:safeevaluate).with do |scope|
- scope.object_id.should_not == @scope.object_id
- true
- end
- @definition.stubs(:code).returns(code)
- @definition.evaluate_code(@resource)
- end
-
- it "should have a get_classname method" do
- @definition.should respond_to(:get_classname)
- end
-
- it "should return the current classname with get_classname" do
- @definition.expects(:classname)
-
- @definition.get_classname(@scope)
- end
-
- describe "when evaluating" do
- it "should create a resource whose title comes from get_classname" do
- @definition.expects(:get_classname).returns("classname")
-
- @definition.evaluate(@scope)
- end
- end
-
-# it "should copy its namespace to the scope"
-#
-# it "should mark the scope virtual if the resource is virtual"
-#
-# it "should mark the scope exported if the resource is exported"
-#
-# it "should set the resource's parameters as variables in the scope"
-#
-# it "should set the resource's title as a variable in the scope"
-#
-# it "should copy the resource's title in a 'name' variable in the scope"
-#
-# it "should not copy the resource's title as the name if 'name' is one of the resource parameters"
-#
-# it "should evaluate the associated code with the new scope"
-
- def old_test_initialize
- parser = mkparser
-
- # Create a new definition
- klass = parser.newdefine "yayness",
- :arguments => [["owner", stringobj("nobody")], %w{mode}],
- :code => AST::ASTArray.new(
- :children => [resourcedef("file", "/tmp/$name",
- "owner" => varref("owner"), "mode" => varref("mode"))]
- )
-
- # Test validattr? a couple different ways
- [:owner, "owner", :schedule, "schedule"].each do |var|
- assert(klass.validattr?(var), "%s was not considered valid" % var.inspect)
- end
-
- [:random, "random"].each do |var|
- assert(! klass.validattr?(var), "%s was considered valid" % var.inspect)
- end
-
- end
-
- def oldtest_evaluate
- parser = mkparser
- config = mkcompiler
- config.send(:evaluate_main)
- scope = config.topscope
- klass = parser.newdefine "yayness",
- :arguments => [["owner", stringobj("nobody")], %w{mode}],
- :code => AST::ASTArray.new(
- :children => [resourcedef("file", "/tmp/$name",
- "owner" => varref("owner"), "mode" => varref("mode"))]
- )
-
- resource = Puppet::Parser::Resource.new(
- :title => "first",
- :type => "yayness",
- :exported => false,
- :virtual => false,
- :scope => scope,
- :source => scope.source
- )
- resource.send(:set_parameter, "name", "first")
- resource.send(:set_parameter, "mode", "755")
-
- resource.stubs(:title)
- assert_nothing_raised do
- klass.evaluate_code(resource)
- end
-
- firstobj = config.findresource("File[/tmp/first]")
- assert(firstobj, "Did not create /tmp/first obj")
-
- assert_equal("File", firstobj.type)
- assert_equal("/tmp/first", firstobj.title)
- assert_equal("nobody", firstobj[:owner])
- assert_equal("755", firstobj[:mode])
-
- # Make sure we can't evaluate it with the same args
- assert_raise(Puppet::ParseError) do
- klass.evaluate_code(resource)
- end
-
- # Now create another with different args
- resource2 = Puppet::Parser::Resource.new(
- :title => "second",
- :type => "yayness",
- :exported => false,
- :virtual => false,
- :scope => scope,
- :source => scope.source
- )
- resource2.send(:set_parameter, "name", "second")
- resource2.send(:set_parameter, "mode", "755")
- resource2.send(:set_parameter, "owner", "daemon")
-
- assert_nothing_raised do
- klass.evaluate_code(resource2)
- end
-
- secondobj = config.findresource("File[/tmp/second]")
- assert(secondobj, "Did not create /tmp/second obj")
-
- assert_equal("File", secondobj.type)
- assert_equal("/tmp/second", secondobj.title)
- assert_equal("daemon", secondobj[:owner])
- assert_equal("755", secondobj[:mode])
- end
-
- # #539 - definitions should support both names and titles
- def oldtest_names_and_titles
- parser = mkparser
- scope = mkscope :parser => parser
-
- [
- {:name => "one", :title => "two"},
- {:title => "mytitle"}
- ].each_with_index do |hash, i|
- # Create a definition that uses both name and title. Put this
- # inside the loop so the subscope expectations work.
- klass = parser.newdefine "yayness%s" % i
-
- resource = Puppet::Parser::Resource.new(
- :title => hash[:title],
- :type => "yayness%s" % i,
- :exported => false,
- :virtual => false,
- :scope => scope,
- :source => scope.source
- )
-
- subscope = klass.subscope(scope, resource)
-
- klass.expects(:subscope).returns(subscope)
-
- if hash[:name]
- resource.stubs(:to_hash).returns({:name => hash[:name]})
- end
-
- assert_nothing_raised("Could not evaluate definition with %s" % hash.inspect) do
- klass.evaluate_code(resource)
- end
-
- name = hash[:name] || hash[:title]
- title = hash[:title]
-
- assert_equal(name, subscope.lookupvar("name"),
- "Name did not get set correctly")
- assert_equal(title, subscope.lookupvar("title"),
- "title did not get set correctly")
-
- [:name, :title].each do |param|
- val = resource.send(param)
- assert(subscope.tags.include?(val),
- "Scope was not tagged with %s '%s'" % [param, val])
- end
- end
- end
-
- # Testing the root cause of #615. We should be using the fqname for the type, instead
- # of just the short name.
- def oldtest_fully_qualified_types
- parser = mkparser
- klass = parser.newclass("one::two")
-
- assert_equal("one::two", klass.classname, "Class did not get fully qualified class name")
- end
-end
diff --git a/spec/unit/parser/ast/hostclass.rb b/spec/unit/parser/ast/hostclass.rb
deleted file mode 100755
index 10aa62176..000000000
--- a/spec/unit/parser/ast/hostclass.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../../../spec_helper'
-
-describe Puppet::Parser::AST::HostClass do
- before :each do
- @node = Puppet::Node.new "testnode"
- @parser = Puppet::Parser::Parser.new :environment => "development"
- @scope_resource = stub 'scope_resource', :builtin? => true
- @compiler = Puppet::Parser::Compiler.new(@node, @parser)
-
- @scope = @compiler.topscope
- end
-
- describe Puppet::Parser::AST::HostClass, "when evaluating" do
-
- before do
- @top = @parser.newclass "top"
- @middle = @parser.newclass "middle", :parent => "top"
- end
-
- it "should create a resource that references itself" do
- @top.evaluate(@scope)
-
- @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
- end
-
- it "should evaluate the parent class if one exists" do
- @middle.evaluate(@scope)
-
- @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
- end
-
- it "should fail to evaluate if a parent class is defined but cannot be found" do
- othertop = @parser.newclass "something", :parent => "yay"
- lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError)
- end
-
- it "should not create a new resource if one already exists" do
- @compiler.catalog.expects(:resource).with(:class, "top").returns("something")
- @compiler.catalog.expects(:add_resource).never
- @top.evaluate(@scope)
- end
-
- it "should return the existing resource when not creating a new one" do
- @compiler.catalog.expects(:resource).with(:class, "top").returns("something")
- @compiler.catalog.expects(:add_resource).never
- @top.evaluate(@scope).should == "something"
- end
-
- it "should not create a new parent resource if one already exists and it has a parent class" do
- @top.evaluate(@scope)
-
- top_resource = @compiler.catalog.resource(:class, "top")
-
- @middle.evaluate(@scope)
-
- @compiler.catalog.resource(:class, "top").should equal(top_resource)
- end
-
- # #795 - tag before evaluation.
- it "should tag the catalog with the resource tags when it is evaluated" do
- @middle.evaluate(@scope)
-
- @compiler.catalog.should be_tagged("middle")
- end
-
- it "should tag the catalog with the parent class tags when it is evaluated" do
- @middle.evaluate(@scope)
-
- @compiler.catalog.should be_tagged("top")
- end
- end
-
- describe Puppet::Parser::AST::HostClass, "when evaluating code" do
-
- before do
- @top_resource = stub "top_resource"
- @top = @parser.newclass "top", :code => @top_resource
-
- @middle_resource = stub "middle_resource"
- @middle = @parser.newclass "top::middle", :parent => "top", :code => @middle_resource
- end
-
- it "should set its namespace to its fully qualified name" do
- @middle.namespace.should == "top::middle"
- end
-
- it "should evaluate the code referred to by the class" do
- @top_resource.expects(:safeevaluate)
-
- resource = @top.evaluate(@scope)
-
- @top.evaluate_code(resource)
- end
-
- it "should evaluate the parent class's code if it has a parent" do
- @top_resource.expects(:safeevaluate)
- @middle_resource.expects(:safeevaluate)
-
- resource = @middle.evaluate(@scope)
-
- @middle.evaluate_code(resource)
- end
-
- it "should not evaluate the parent class's code if the parent has already been evaluated" do
- @top_resource.stubs(:safeevaluate)
- resource = @top.evaluate(@scope)
- @top.evaluate_code(resource)
-
- @top_resource.expects(:safeevaluate).never
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- @middle.evaluate_code(resource)
- end
-
- it "should use the parent class's scope as its parent scope" do
- @top_resource.stubs(:safeevaluate)
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- @middle.evaluate_code(resource)
-
- @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top))
- end
-
- it "should add the class's name and title to its own scope" do
- @top_resource.stubs(:safeevaluate)
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- scope = stub_everything 'scope', :compiler => @compiler
- @middle.stubs(:subscope).returns(scope)
-
- scope.expects(:setvar).with("title","top::middle")
- scope.expects(:setvar).with("name","top::middle")
-
- @middle.evaluate_code(resource)
- end
-
- it "should add the parent class's namespace to its namespace search path" do
- @top_resource.stubs(:safeevaluate)
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- @middle.evaluate_code(resource)
-
- @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace)
- end
- end
-end
diff --git a/spec/unit/parser/ast/leaf.rb b/spec/unit/parser/ast/leaf.rb
index fecfba386..ee1ee04a7 100755
--- a/spec/unit/parser/ast/leaf.rb
+++ b/spec/unit/parser/ast/leaf.rb
@@ -195,40 +195,6 @@ describe Puppet::Parser::AST::HostName do
@host.evaluate(@scope).should == @value
end
- it "should implement to_classname" do
- @host.should respond_to(:to_classname)
- end
-
- it "should return the downcased nodename as classname" do
- host = Puppet::Parser::AST::HostName.new( :value => "KLASSNAME" )
- host.to_classname.should == "klassname"
- end
-
- it "should preserve '_' in to_classname with a string nodename" do
- host = Puppet::Parser::AST::HostName.new( :value => "node_with_underscore")
- host.to_classname.should == "node_with_underscore"
- end
-
- it "should preserve '_' in to_classname with a regex nodename" do
- host = Puppet::Parser::AST::HostName.new( :value => Puppet::Parser::AST::Regex.new(:value => "/\dnode_with_underscore\.+/") )
- host.to_classname.should == "dnode_with_underscore."
- end
-
- it "should return a string usable as classname when calling to_classname" do
- host = Puppet::Parser::AST::HostName.new( :value => Puppet::Parser::AST::Regex.new(:value => "/^this-is not@a classname$/") )
- host.to_classname.should == "this-isnotaclassname"
- end
-
- it "should return a string usable as a tag when calling to_classname" do
- host = Puppet::Parser::AST::HostName.new( :value => Puppet::Parser::AST::Regex.new(:value => "/.+.reductivelabs\.com/") )
- host.to_classname.should == "reductivelabs.com"
- end
-
- it "should delegate 'match' to the underlying value if it is an HostName" do
- @value.expects(:match).with("value")
- @host.match("value")
- end
-
it "should delegate eql? to the underlying value if it is an HostName" do
@value.expects(:eql?).with("value")
@host.eql?("value")
@@ -244,42 +210,4 @@ describe Puppet::Parser::AST::HostName do
@value.expects(:hash)
@host.hash
end
-
- it "should return true when regex? is called and value is a Regex" do
- @value.expects(:is_a?).with(Puppet::Parser::AST::Regex).returns(true)
- @host.regex?.should be_true
- end
-
- it "should return the results of comparing the regexes if asked whether a regex matches another regex" do
- hosts = [1,2].collect do |num|
- vreg = /vreg#{num}/
- value = Puppet::Parser::AST::Regex.new(:value => vreg)
- Puppet::Parser::AST::HostName.new(:value => value)
- end
-
- hosts[0].match(hosts[1]).should be_false
- hosts[0].match(hosts[0]).should be_true
- end
-
- it "should return false when comparing a non-regex to a regex" do
- vreg = /vreg/
- value = Puppet::Parser::AST::Regex.new(:value => vreg)
- regex = Puppet::Parser::AST::HostName.new(:value => value)
-
- value = Puppet::Parser::AST::Regex.new(:value => "foo")
- normal = Puppet::Parser::AST::HostName.new(:value => value)
-
- normal.match(regex).should be_false
- end
-
- it "should true when a provided string matches a regex" do
- vreg = /r/
- value = Puppet::Parser::AST::Regex.new(:value => vreg)
- regex = Puppet::Parser::AST::HostName.new(:value => value)
-
- value = Puppet::Parser::AST::Leaf.new(:value => "bar")
- normal = Puppet::Parser::AST::HostName.new(:value => value)
-
- regex.match(normal).should be_true
- end
end
diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb
deleted file mode 100755
index 5a4a5efe4..000000000
--- a/spec/unit/parser/ast/node.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../../../spec_helper'
-
-describe Puppet::Parser::AST::Node do
- before :each do
- @node = Puppet::Node.new "testnode"
- @parser = Puppet::Parser::Parser.new :environment => "development"
- @scope_resource = stub 'scope_resource', :builtin? => true
- @compiler = Puppet::Parser::Compiler.new(@node, @parser)
-
- @scope = @compiler.topscope
- end
-
- describe "when calling get_classname" do
- it "should return current node name if name is a Regex" do
- name = stub 'name', :regex? => true
- node = @parser.newnode("node").shift
- node.stubs(:name).returns(name)
-
- @scope.expects(:host).returns("testnode")
-
- node.get_classname(@scope).should == "testnode"
- end
-
- it "should return the current node classname if name is not a Regex" do
- name = stub 'name', :regex? => false
- node = @parser.newnode("node").shift
- node.stubs(:name).returns(name)
-
- node.get_classname(@scope).should == "node"
- end
- end
-
- describe Puppet::Parser::AST::Node, "when evaluating" do
-
- before do
- @top = @parser.newnode("top").shift
- @middle = @parser.newnode("middle", :parent => "top").shift
- end
-
- it "should create a resource that references itself" do
- @top.evaluate(@scope)
-
- @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource)
- end
-
- it "should evaluate the parent class if one exists" do
- @middle.evaluate(@scope)
-
- @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource)
- end
-
- it "should fail to evaluate if a parent class is defined but cannot be found" do
- othertop = @parser.newnode("something", :parent => "yay").shift
- lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError)
- end
-
- it "should not create a new resource if one already exists" do
- @compiler.catalog.expects(:resource).with(:node, "top").returns("something")
- @compiler.catalog.expects(:add_resource).never
- @top.evaluate(@scope)
- end
-
- it "should not create a new parent resource if one already exists and it has a parent class" do
- @top.evaluate(@scope)
-
- top_resource = @compiler.catalog.resource(:node, "top")
-
- @middle.evaluate(@scope)
-
- @compiler.catalog.resource(:node, "top").should equal(top_resource)
- end
-
- # #795 - tag before evaluation.
- it "should tag the catalog with the resource tags when it is evaluated" do
- @middle.evaluate(@scope)
-
- @compiler.catalog.should be_tagged("middle")
- end
-
- it "should tag the catalog with the parent class tags when it is evaluated" do
- @middle.evaluate(@scope)
-
- @compiler.catalog.should be_tagged("top")
- end
- end
-
- describe Puppet::Parser::AST::Node, "when evaluating code" do
-
- before do
- @top_resource = stub "top_resource"
- @top = @parser.newnode("top", :code => @top_resource).shift
-
- @middle_resource = stub "middle_resource"
- @middle = @parser.newnode("middle", :parent => "top", :code => @middle_resource).shift
- end
-
- it "should evaluate the code referred to by the class" do
- @top_resource.expects(:safeevaluate)
-
- resource = @top.evaluate(@scope)
-
- @top.evaluate_code(resource)
- end
-
- it "should evaluate the parent class's code if it has a parent" do
- @top_resource.expects(:safeevaluate)
- @middle_resource.expects(:safeevaluate)
-
- resource = @middle.evaluate(@scope)
-
- @middle.evaluate_code(resource)
- end
-
- it "should not evaluate the parent class's code if the parent has already been evaluated" do
- @top_resource.stubs(:safeevaluate)
- resource = @top.evaluate(@scope)
- @top.evaluate_code(resource)
-
- @top_resource.expects(:safeevaluate).never
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- @middle.evaluate_code(resource)
- end
-
- it "should use the parent class's scope as its parent scope" do
- @top_resource.stubs(:safeevaluate)
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- @middle.evaluate_code(resource)
-
- @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top))
- end
-
- it "should add the parent class's namespace to its namespace search path" do
- @top_resource.stubs(:safeevaluate)
- @middle_resource.stubs(:safeevaluate)
- resource = @middle.evaluate(@scope)
- @middle.evaluate_code(resource)
-
- @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace)
- end
- end
-end
diff --git a/spec/unit/parser/ast/resource_reference.rb b/spec/unit/parser/ast/resource_reference.rb
index 24865e846..10d9678c3 100755
--- a/spec/unit/parser/ast/resource_reference.rb
+++ b/spec/unit/parser/ast/resource_reference.rb
@@ -21,7 +21,7 @@ describe Puppet::Parser::AST::ResourceReference do
%{ "one::two" "one-two"}.each do |type|
it "should evaluate correctly reference to define" do
- klass = stub 'klass', :title => "three", :classname => type
+ 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
@@ -29,13 +29,13 @@ describe Puppet::Parser::AST::ResourceReference do
end
it "should be able to call qualified_class" do
- klass = stub 'klass', :title => "three", :classname => "one"
+ 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", :classname => "one"
+ klass = stub 'klass', :title => "one", :name => "one"
@scope.stubs(:find_hostclass).returns(klass)
evaled = newref("one", "class").evaluate(@scope)
diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb
index adc9732dc..8a41242d6 100755
--- a/spec/unit/parser/compiler.rb
+++ b/spec/unit/parser/compiler.rb
@@ -51,7 +51,7 @@ describe Puppet::Parser::Compiler do
it "should be able to retrieve class scopes by object" do
klass = mock 'ast_class'
- klass.expects(:classname).returns("myname")
+ klass.expects(:name).returns("myname")
@compiler.class_set "myname", "myscope"
@compiler.class_scope(klass).should == "myscope"
end
@@ -153,8 +153,8 @@ describe Puppet::Parser::Compiler do
it "should evaluate any existing classes named in the node" do
classes = %w{one two three four}
main = stub 'main'
- one = stub 'one', :classname => "one"
- three = stub 'three', :classname => "three"
+ one = stub 'one', :name => "one"
+ three = stub 'three', :name => "three"
@node.stubs(:name).returns("whatever")
@node.stubs(:classes).returns(classes)
@@ -396,7 +396,7 @@ describe Puppet::Parser::Compiler do
describe "when evaluating found classes" do
before do
- @class = stub 'class', :classname => "my::class"
+ @class = stub 'class', :name => "my::class"
@scope.stubs(:find_hostclass).with("myclass").returns(@class)
@resource = stub 'resource', :ref => "Class[myclass]", :type => "file"
@@ -405,7 +405,7 @@ describe Puppet::Parser::Compiler do
it "should evaluate each class" do
@compiler.catalog.stubs(:tag)
- @class.expects(:evaluate).with(@scope)
+ @class.expects(:mk_plain_resource).with(@scope)
@compiler.evaluate_classes(%w{myclass}, @scope)
end
@@ -415,7 +415,7 @@ describe Puppet::Parser::Compiler do
@resource.expects(:evaluate).never
- @class.expects(:evaluate).returns(@resource)
+ @class.expects(:mk_plain_resource).returns(@resource)
@compiler.evaluate_classes(%w{myclass}, @scope)
end
@@ -424,7 +424,7 @@ describe Puppet::Parser::Compiler do
@compiler.catalog.stubs(:tag)
@resource.expects(:evaluate)
- @class.expects(:evaluate).returns(@resource)
+ @class.expects(:mk_plain_resource).returns(@resource)
@compiler.evaluate_classes(%w{myclass}, @scope, false)
end
@@ -459,7 +459,7 @@ describe Puppet::Parser::Compiler do
@scope.stubs(:find_hostclass).with("notfound").returns(nil)
Puppet::Parser::Resource.stubs(:new).returns(@resource)
- @class.stubs :evaluate
+ @class.stubs :mk_plain_resource
@compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass}
end
end
@@ -495,31 +495,31 @@ describe Puppet::Parser::Compiler do
end
it "should evaluate the first node class matching the node name" do
- node_class = stub 'node', :classname => "c", :evaluate_code => nil
+ node_class = stub 'node', :name => "c", :evaluate_code => nil
@compiler.parser.stubs(:node).with("c").returns(node_class)
node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node"
- node_class.expects(:evaluate).returns(node_resource)
+ node_class.expects(:mk_plain_resource).returns(node_resource)
@compiler.compile
end
it "should match the default node if no matching node can be found" do
- node_class = stub 'node', :classname => "default", :evaluate_code => nil
+ node_class = stub 'node', :name => "default", :evaluate_code => nil
@compiler.parser.stubs(:node).with("default").returns(node_class)
node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil, :type => "node"
- node_class.expects(:evaluate).returns(node_resource)
+ node_class.expects(:mk_plain_resource).returns(node_resource)
@compiler.compile
end
it "should evaluate the node resource immediately rather than using lazy evaluation" do
- node_class = stub 'node', :classname => "c"
+ node_class = stub 'node', :name => "c"
@compiler.parser.stubs(:node).with("c").returns(node_class)
node_resource = stub 'node resource', :ref => "Node[c]", :type => "node"
- node_class.expects(:evaluate).returns(node_resource)
+ node_class.expects(:mk_plain_resource).returns(node_resource)
node_resource.expects(:evaluate)
@@ -528,13 +528,13 @@ describe Puppet::Parser::Compiler do
it "should set the node's scope as the top scope" do
node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node"
- node_class = stub 'node', :classname => "c", :evaluate => node_resource
+ node_class = stub 'node', :name => "c", :mk_plain_resource => node_resource
@compiler.parser.stubs(:node).with("c").returns(node_class)
# The #evaluate method normally does this.
scope = stub 'scope', :source => "mysource"
- @compiler.class_set(node_class.classname, scope)
+ @compiler.class_set(node_class.name, scope)
node_resource.stubs(:evaluate)
@compiler.compile
diff --git a/spec/unit/parser/loaded_code.rb b/spec/unit/parser/loaded_code.rb
index 75f2bc7e2..9b72dab0d 100644
--- a/spec/unit/parser/loaded_code.rb
+++ b/spec/unit/parser/loaded_code.rb
@@ -3,23 +3,92 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/parser/loaded_code'
+require 'puppet/parser/resource_type'
describe Puppet::Parser::LoadedCode do
+ before do
+ @instance = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+ @code = Puppet::Parser::LoadedCode.new
+ end
+
+ it "should be able to add a resource type" do
+ Puppet::Parser::LoadedCode.new.should respond_to(:add)
+ end
+
+ it "should consider '<<' to be an alias to 'add' but should return self" do
+ loader = Puppet::Parser::LoadedCode.new
+ loader.expects(:add).with "foo"
+ loader.expects(:add).with "bar"
+ loader << "foo" << "bar"
+ end
+
+ it "should set itself as the code collection for added resource types" do
+ loader = Puppet::Parser::LoadedCode.new
+
+ node = Puppet::Parser::ResourceType.new(:node, "foo")
+
+ @code.add(node)
+ @code.node("foo").should equal(node)
+
+ node.code_collection.should equal(@code)
+ end
+
+ it "should store node resource types as nodes" do
+ node = Puppet::Parser::ResourceType.new(:node, "foo")
+
+ @code.add(node)
+ @code.node("foo").should equal(node)
+ end
+
+ it "should store hostclasses as hostclasses" do
+ klass = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+
+ @code.add(klass)
+ @code.hostclass("foo").should equal(klass)
+ end
+
+ it "should store definitions as definitions" do
+ define = Puppet::Parser::ResourceType.new(:definition, "foo")
+
+ @code.add(define)
+ @code.definition("foo").should equal(define)
+ end
+
%w{hostclass node definition}.each do |data|
it "should have a method for adding a #{data}" do
Puppet::Parser::LoadedCode.new.should respond_to("add_" + data)
end
+ it "should use the name of the instance to add it" do
+ loader = Puppet::Parser::LoadedCode.new
+ loader.send("add_#{data}", @instance)
+ loader.send(data, @instance.name).should equal(@instance)
+ end
+
+ it "should fail to add a #{data} when one already exists" do
+ loader = Puppet::Parser::LoadedCode.new
+ loader.add @instance
+ lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError)
+ end
+
+ it "should return the added #{data}" do
+ loader = Puppet::Parser::LoadedCode.new
+
+ loader.add(@instance).should equal(@instance)
+ end
+
it "should be able to retrieve #{data} by name" do
loader = Puppet::Parser::LoadedCode.new
- loader.send("add_" + data, "foo", "bar")
- loader.send(data, "foo").should == "bar"
+ instance = Puppet::Parser::ResourceType.new(data, "bar")
+ loader.add instance
+ loader.send(data, "bar").should equal(instance)
end
it "should retrieve #{data} insensitive to case" do
loader = Puppet::Parser::LoadedCode.new
- loader.send("add_" + data, "Foo", "bar")
- loader.send(data, "fOo").should == "bar"
+ instance = Puppet::Parser::ResourceType.new(data, "Bar")
+ loader.add instance
+ loader.send(data, "bAr").should equal(instance)
end
it "should return nil when asked for a #{data} that has not been added" do
@@ -29,16 +98,18 @@ describe Puppet::Parser::LoadedCode do
it "should be able to retrieve all #{data}s" do
plurals = { "hostclass" => "hostclasses", "node" => "nodes", "definition" => "definitions" }
loader = Puppet::Parser::LoadedCode.new
- loader.send("add_" + data , "foo", "bar")
- loader.send(plurals[data]).should == { "foo" => "bar" }
+ instance = Puppet::Parser::ResourceType.new(data, "foo")
+ loader.add instance
+ loader.send(plurals[data]).should == { "foo" => instance }
end
end
describe "when finding a qualified instance" do
it "should return any found instance if the instance name is fully qualified" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar", "yay"
- loader.find("namespace", "::foo::bar", :hostclass).should == "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar")
+ loader.add instance
+ loader.find("namespace", "::foo::bar", :hostclass).should equal(instance)
end
it "should return nil if the instance name is fully qualified and no such instance exists" do
@@ -48,37 +119,43 @@ describe Puppet::Parser::LoadedCode do
it "should return the partially qualified object if it exists in the provided namespace" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar::baz", "yay"
- loader.find("foo", "bar::baz", :hostclass).should == "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar::baz")
+ loader.add instance
+ loader.find("foo", "bar::baz", :hostclass).should equal(instance)
end
it "should return the unqualified object if it exists in the provided namespace" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar", "yay"
- loader.find("foo", "bar", :hostclass).should == "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar")
+ loader.add instance
+ loader.find("foo", "bar", :hostclass).should equal(instance)
end
it "should return the unqualified object if it exists in the parent namespace" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar", "yay"
- loader.find("foo::bar::baz", "bar", :hostclass).should == "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar")
+ loader.add instance
+ loader.find("foo::bar::baz", "bar", :hostclass).should equal(instance)
end
it "should should return the partially qualified object if it exists in the parent namespace" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar::baz", "yay"
- loader.find("foo::bar", "bar::baz", :hostclass).should == "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar::baz")
+ loader.add instance
+ loader.find("foo::bar", "bar::baz", :hostclass).should equal(instance)
end
it "should return the qualified object if it exists in the root namespace" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar::baz", "yay"
- loader.find("foo::bar", "foo::bar::baz", :hostclass).should == "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar::baz")
+ loader.add instance
+ loader.find("foo::bar", "foo::bar::baz", :hostclass).should equal(instance)
end
it "should return nil if the object cannot be found" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_hostclass "foo::bar::baz", "yay"
+ instance = Puppet::Parser::ResourceType.new(:hostclass, "foo::bar::baz")
+ loader.add instance
loader.find("foo::bar", "eh", :hostclass).should be_nil
end
end
@@ -103,7 +180,7 @@ describe Puppet::Parser::LoadedCode do
it "should indicate whether any nodes are defined" do
loader = Puppet::Parser::LoadedCode.new
- loader.add_node("foo", "bar")
+ loader.add_node(Puppet::Parser::ResourceType.new(:node, "foo"))
loader.should be_nodes
end
@@ -111,105 +188,32 @@ describe Puppet::Parser::LoadedCode do
Puppet::Parser::LoadedCode.new.should_not be_nodes
end
- describe "when adding nodes" do
- it "should create an HostName if nodename is a string" do
- Puppet::Parser::AST::HostName.expects(:new).with(:value => "foo")
- loader = Puppet::Parser::LoadedCode.new
- loader.add_node("foo", "bar")
- end
-
- it "should not create an HostName if nodename is an HostName" do
- name = Puppet::Parser::AST::HostName.new(:value => "foo")
-
- Puppet::Parser::AST::HostName.expects(:new).with(:value => "foo").never
-
- loader = Puppet::Parser::LoadedCode.new
- loader.add_node(name, "bar")
- end
- end
-
describe "when finding nodes" do
before :each do
@loader = Puppet::Parser::LoadedCode.new
-
- @nodename1 = stub 'nodename1', :is_a? => true
- @node1 = stub 'node1'
- @nodename2 = stub 'nodename2', :is_a? => true
- @node2 = stub 'node2'
- end
- it "should create an HostName if nodename is a string" do
- Puppet::Parser::AST::HostName.expects(:new).with(:value => "foo")
-
- @loader.node("foo")
- end
-
- it "should not create an HostName if nodename is an HostName" do
- name = Puppet::Parser::AST::HostName.new(:value => "foo")
-
- Puppet::Parser::AST::HostName.expects(:new).with(:value => "foo").never
-
- @loader.node(name)
- end
-
- it "should be able to find node by HostName" do
- namein = Puppet::Parser::AST::HostName.new(:value => "foo")
- nameout = Puppet::Parser::AST::HostName.new(:value => "foo")
-
- @loader.add_node(namein, "bar")
- @loader.node(nameout).should == "bar"
end
- it "should be able to find node by HostName strict equality" do
- namein = Puppet::Parser::AST::HostName.new(:value => "foo")
- nameout = Puppet::Parser::AST::HostName.new(:value => "foo")
+ it "should return any node whose name exactly matches the provided node name" do
+ node = Puppet::Parser::ResourceType.new(:node, "foo")
+ @loader << node
- @loader.add_node(namein, "bar")
- @loader.node_exists?(nameout).should == "bar"
+ @loader.node("foo").should equal(node)
end
- it "should not use node name matching when finding with strict node HostName" do
- name1 = Puppet::Parser::AST::HostName.new(:value => "foo")
- name2 = Puppet::Parser::AST::HostName.new(:value => Puppet::Parser::AST::Regex.new(:value => /foo/))
+ it "should return the first regex node whose regex matches the provided node name" do
+ node1 = Puppet::Parser::ResourceType.new(:node, /\w/)
+ node2 = Puppet::Parser::ResourceType.new(:node, /\d/)
+ @loader << node1 << node2
- @loader.add_node(name1, "bar")
- @loader.add_node(name2, "baz")
- @loader.node_exists?(name1).should == "bar"
+ @loader.node("foo10").should equal(node1)
end
- it "should return the first matching regex nodename" do
- @nodename1.stubs(:regex?).returns(true)
- @nodename1.stubs(:match).returns(true)
- @nodename2.stubs(:regex?).returns(true)
- @nodename2.stubs(:match).returns(true)
-
- @loader.add_node(@nodename1, @node1)
- @loader.add_node(@nodename2, @node2)
-
- @loader.node("test").should == @node1
- end
-
- it "should not scan non-regex node" do
- @nodename1.stubs(:regex?).returns(true)
- @nodename1.stubs(:match).returns(false)
- @nodename2.stubs(:regex?).returns(false)
- @nodename2.expects(:match).never
-
- @loader.add_node(@nodename1,@node1)
- @loader.add_node(@nodename2,@node2)
-
- @loader.node("test")
- end
-
- it "should prefer non-regex nodes to regex nodes" do
- @nodename1.stubs(:regex?).returns(false)
- @nodename1.expects(:match).never
- @nodename2.stubs(:regex?).returns(true)
- @nodename2.expects(:match).never
-
- @loader.add_node(@nodename1,@node1)
- @loader.add_node(@nodename2,@node2)
+ it "should preferentially return a node whose name is string-equal over returning a node whose regex matches a provided name" do
+ node1 = Puppet::Parser::ResourceType.new(:node, /\w/)
+ node2 = Puppet::Parser::ResourceType.new(:node, "foo")
+ @loader << node1 << node2
- @loader.node(@nodename1)
+ @loader.node("foo").should equal(node2)
end
end
end
diff --git a/spec/unit/parser/parser.rb b/spec/unit/parser/parser.rb
index 78caf18b0..a04444674 100755
--- a/spec/unit/parser/parser.rb
+++ b/spec/unit/parser/parser.rb
@@ -174,56 +174,62 @@ describe Puppet::Parser do
end
end
- describe "when instantiating class of same name" do
-
- before :each do
- @one = stub 'one', :is_a? => true
- @one.stubs(:is_a?).with(ast::ASTArray).returns(false)
- @one.stubs(:is_a?).with(ast).returns(true)
-
- @two = stub 'two'
- @two.stubs(:is_a?).with(ast::ASTArray).returns(false)
- @two.stubs(:is_a?).with(ast).returns(true)
+ describe "when providing AST context" do
+ before do
+ @lexer = stub 'lexer', :line => 50, :file => "/foo/bar", :getcomment => "whev"
+ @parser.stubs(:lexer).returns @lexer
end
- it "should return the first class" do
-
- klass1 = @parser.newclass("one", { :code => @one })
+ it "should include the lexer's line" do
+ @parser.ast_context[:line].should == 50
+ end
- @parser.newclass("one", { :code => @two }).should == klass1
+ it "should include the lexer's file" do
+ @parser.ast_context[:file].should == "/foo/bar"
end
- it "should concatenate code" do
- klass1 = @parser.newclass("one", { :code => @one })
+ it "should include the docs if directed to do so" do
+ @parser.ast_context(true)[:doc].should == "whev"
+ end
- @parser.newclass("one", { :code => @two })
+ it "should not include the docs when told not to" do
+ @parser.ast_context(false)[:doc].should be_nil
+ end
- klass1.code.children.should == [@one,@two]
+ it "should not include the docs by default" do
+ @parser.ast_context()[:doc].should be_nil
end
end
- describe "when parsing comments before statement" do
- it "should associate the documentation to the statement AST node" do
- ast = @parser.parse("""
- # comment
- class test {}
- """)
+ describe "when building ast nodes" do
+ before do
+ @lexer = stub 'lexer', :line => 50, :file => "/foo/bar", :getcomment => "whev"
+ @parser.stubs(:lexer).returns @lexer
+ @class = stub 'class', :use_docs => false
+ end
- ast.hostclass("test").doc.should == "comment\n"
+ it "should return a new instance of the provided class created with the provided options" do
+ @class.expects(:new).with { |opts| opts[:foo] == "bar" }
+ @parser.ast(@class, :foo => "bar")
end
- end
- describe "when building ast nodes" do
- it "should get lexer comments if ast node declares use_docs" do
- lexer = stub 'lexer'
- ast = mock 'ast', :nil? => false, :use_docs => true, :doc => ""
- @parser.stubs(:lexer).returns(lexer)
+ it "should merge the ast context into the provided options" do
+ @class.expects(:new).with { |opts| opts[:file] == "/foo" }
+ @parser.expects(:ast_context).returns :file => "/foo"
+ @parser.ast(@class, :foo => "bar")
+ end
- Puppet::Parser::AST::Definition.expects(:new).returns(ast)
- lexer.expects(:getcomment).returns("comment")
- ast.expects(:doc=).with("comment")
+ it "should prefer provided options over AST context" do
+ @class.expects(:new).with { |opts| opts[:file] == "/bar" }
+ @parser.expects(:ast_context).returns :file => "/foo"
+ @parser.ast(@class, :file => "/bar")
+ end
- @parser.ast(Puppet::Parser::AST::Definition)
+ it "should include docs when the AST class uses them" do
+ @class.expects(:use_docs).returns true
+ @class.stubs(:new)
+ @parser.expects(:ast_context).with(true).returns({})
+ @parser.ast(@class, :file => "/bar")
end
end
@@ -233,59 +239,15 @@ describe Puppet::Parser do
@lexer.stubs(:getcomment)
@parser.stubs(:lexer).returns(@lexer)
@node = stub_everything 'node'
- @parser.stubs(:ast).returns(@node)
+ @parser.stubs(:ast_context).returns({})
@parser.stubs(:node).returns(nil)
- @nodename = stub 'nodename', :is_a? => false, :to_classname => "node"
+ @nodename = stub 'nodename', :is_a? => false, :value => "foo"
@nodename.stubs(:is_a?).with(Puppet::Parser::AST::HostName).returns(true)
end
- it "should get the lexer stacked comments" do
- @lexer.expects(:getcomment)
-
- @parser.newnode(@nodename)
- end
-
- it "should create an HostName if needed" do
- Puppet::Parser::AST::HostName.expects(:new).with(:value => "node").returns(@nodename)
-
- @parser.newnode("node")
- end
-
- it "should raise an error if the node already exists" do
- @loaded_code.stubs(:node_exists?).with(@nodename).returns(@node)
-
- lambda { @parser.newnode(@nodename) }.should raise_error
- end
-
- it "should store the created node in the loaded code" do
- @loaded_code.expects(:add_node).with(@nodename, @node)
-
- @parser.newnode(@nodename)
- end
-
- it "should create the node with code if provided" do
- @parser.stubs(:ast).with { |*args| args[1][:code] == :code }.returns(@node)
-
- @parser.newnode(@nodename, :code => :code)
- end
-
- it "should create the node with a parentclass if provided" do
- @parser.stubs(:ast).with { |*args| args[1][:parent] == :parent }.returns(@node)
-
- @parser.newnode(@nodename, :parent => :parent)
- end
-
- it "should set the node classname from the HostName" do
- @nodename.stubs(:to_classname).returns(:classname)
-
- @node.expects(:classname=).with(:classname)
-
- @parser.newnode(@nodename)
- end
-
it "should return an array of nodes" do
- @parser.newnode(@nodename).should == [@node]
+ @parser.newnode(@nodename).should be_instance_of(Array)
end
end
diff --git a/spec/unit/parser/resource/reference.rb b/spec/unit/parser/resource/reference.rb
index 6284e67cc..e082136c5 100755
--- a/spec/unit/parser/resource/reference.rb
+++ b/spec/unit/parser/resource/reference.rb
@@ -84,7 +84,7 @@ describe Puppet::Parser::Resource::Reference, " when modeling defined types" do
scope = @compiler.topscope.class.new(:parent => @compiler.topscope, :namespace => "other", :parser => @parser)
ref = @type.new(:type => "class", :title => "top", :scope => scope)
- ref.definedtype.classname.should equal(top.classname)
+ ref.definedtype.name.should equal(top.name)
end
it "should only look for fully qualified definitions" do
@@ -94,6 +94,6 @@ describe Puppet::Parser::Resource::Reference, " when modeling defined types" do
scope = @compiler.topscope.class.new(:parent => @compiler.topscope, :namespace => "other", :parser => @parser)
ref = @type.new(:type => "top", :title => "foo", :scope => scope)
- ref.definedtype.classname.should equal(top.classname)
+ ref.definedtype.name.should equal(top.name)
end
end
diff --git a/spec/unit/parser/resource_type.rb b/spec/unit/parser/resource_type.rb
new file mode 100755
index 000000000..ddf8ce951
--- /dev/null
+++ b/spec/unit/parser/resource_type.rb
@@ -0,0 +1,522 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/parser/resource_type'
+
+describe Puppet::Parser::ResourceType do
+ it "should have a 'name' attribute" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo").name.should == "foo"
+ end
+
+ [:code, :doc, :line, :file, :code_collection].each do |attr|
+ it "should have a '#{attr}' attribute" do
+ type = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+ type.send(attr.to_s + "=", "yay")
+ type.send(attr).should == "yay"
+ end
+ end
+
+ describe "when a node" do
+ it "should allow a regex as its name" do
+ lambda { Puppet::Parser::ResourceType.new(:node, /foo/) }.should_not raise_error
+ end
+
+ it "should allow a AST::HostName instance as its name" do
+ regex = Puppet::Parser::AST::Regex.new(:value => /foo/)
+ name = Puppet::Parser::AST::HostName.new(:value => regex)
+ lambda { Puppet::Parser::ResourceType.new(:node, name) }.should_not raise_error
+ end
+
+ it "should match against the regexp in the AST::HostName when a HostName instance is provided" do
+ regex = Puppet::Parser::AST::Regex.new(:value => /\w/)
+ name = Puppet::Parser::AST::HostName.new(:value => regex)
+ node = Puppet::Parser::ResourceType.new(:node, name)
+
+ node.match("foo").should be_true
+ end
+
+ it "should return the value of the hostname if provided a string-form AST::HostName instance as the name" do
+ name = Puppet::Parser::AST::HostName.new(:value => "foo")
+ node = Puppet::Parser::ResourceType.new(:node, name)
+
+ node.name.should == "foo"
+ end
+
+ describe "and the name is a regex" do
+ it "should have a method that indicates that this is the case" do
+ Puppet::Parser::ResourceType.new(:node, /w/).should be_name_is_regex
+ end
+
+ it "should set its namespace to ''" do
+ Puppet::Parser::ResourceType.new(:node, /w/).namespace.should == ""
+ end
+
+ it "should return the regex converted to a string when asked for its name" do
+ Puppet::Parser::ResourceType.new(:node, /ww/).name.should == "ww"
+ end
+
+ it "should downcase the regex when returning the name as a string" do
+ Puppet::Parser::ResourceType.new(:node, /W/).name.should == "w"
+ end
+
+ it "should remove non-alpha characters when returning the name as a string" do
+ Puppet::Parser::ResourceType.new(:node, /w*w/).name.should_not include("*")
+ end
+
+ it "should remove leading dots when returning the name as a string" do
+ Puppet::Parser::ResourceType.new(:node, /.ww/).name.should_not =~ /^\./
+ end
+
+ it "should have a method for matching its regex name against a provided name" do
+ Puppet::Parser::ResourceType.new(:node, /.ww/).should respond_to(:match)
+ end
+
+ it "should return true when its regex matches the provided name" do
+ Puppet::Parser::ResourceType.new(:node, /\w/).match("foo").should be_true
+ end
+
+ it "should return false when its regex does not match the provided name" do
+ (!!Puppet::Parser::ResourceType.new(:node, /\d/).match("foo")).should be_false
+ end
+
+ it "should return true when its name, as a string, is matched against an equal string" do
+ Puppet::Parser::ResourceType.new(:node, "foo").match("foo").should be_true
+ end
+
+ it "should return false when its name is matched against an unequal string" do
+ Puppet::Parser::ResourceType.new(:node, "foo").match("bar").should be_false
+ end
+
+ it "should match names insensitive to case" do
+ Puppet::Parser::ResourceType.new(:node, "fOo").match("foO").should be_true
+ end
+ end
+
+ it "should return the name converted to a string when the name is not a regex" do
+ pending "Need to define LoadedCode behaviour first"
+ name = Puppet::Parser::AST::HostName.new(:value => "foo")
+ Puppet::Parser::ResourceType.new(:node, name).name.should == "foo"
+ end
+
+ it "should return the name converted to a string when the name is a regex" do
+ pending "Need to define LoadedCode behaviour first"
+ name = Puppet::Parser::AST::HostName.new(:value => /regex/)
+ Puppet::Parser::ResourceType.new(:node, name).name.should == /regex/.to_s
+ end
+
+ it "should mark any created scopes as a node scope" do
+ pending "Need to define LoadedCode behaviour first"
+ name = Puppet::Parser::AST::HostName.new(:value => /regex/)
+ Puppet::Parser::ResourceType.new(:node, name).name.should == /regex/.to_s
+ end
+ end
+
+ describe "when initializing" do
+ it "should require a resource super type" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo").type.should == :hostclass
+ end
+
+ it "should fail if provided an invalid resource super type" do
+ lambda { Puppet::Parser::ResourceType.new(:nope, "foo") }.should raise_error(ArgumentError)
+ end
+
+ it "should set its name to the downcased, stringified provided name" do
+ Puppet::Parser::ResourceType.new(:hostclass, "Foo::Bar".intern).name.should == "foo::bar"
+ end
+
+ it "should set its namespace to the downcased, stringified qualified portion of the name" do
+ Puppet::Parser::ResourceType.new(:hostclass, "Foo::Bar::Baz".intern).namespace.should == "foo::bar"
+ end
+
+ %w{code line file doc}.each do |arg|
+ it "should set #{arg} if provided" do
+ type = Puppet::Parser::ResourceType.new(:hostclass, "foo", arg.to_sym => "something")
+ type.send(arg).should == "something"
+ end
+ end
+
+ it "should set any provided arguments with the keys as symbols" do
+ type = Puppet::Parser::ResourceType.new(:hostclass, "foo", :arguments => {:foo => "bar", :baz => "biz"})
+ type.should be_validattr("foo")
+ type.should be_validattr("baz")
+ end
+
+ it "should set any provided arguments with they keys as strings" do
+ type = Puppet::Parser::ResourceType.new(:hostclass, "foo", :arguments => {"foo" => "bar", "baz" => "biz"})
+ type.should be_validattr(:foo)
+ type.should be_validattr(:baz)
+ end
+
+ it "should function if provided no arguments" do
+ type = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+ type.should_not be_validattr(:foo)
+ end
+ end
+
+ describe "when testing the validity of an attribute" do
+ it "should return true if the parameter was typed at initialization" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo", :arguments => {"foo" => "bar"}).should be_validattr("foo")
+ end
+
+ it "should return true if it is a metaparam" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo").should be_validattr("require")
+ end
+
+ it "should return true if the parameter is named 'name'" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo").should be_validattr("name")
+ end
+
+ it "should return false if it is not a metaparam and was not provided at initialization" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo").should_not be_validattr("yayness")
+ end
+ end
+
+ describe "when creating a subscope" do
+ before do
+ @scope = stub 'scope', :newscope => nil
+ @resource = stub 'resource'
+ @type = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+ end
+
+ it "should return a new scope created with the provided scope as the parent" do
+ @scope.expects(:newscope).returns "foo"
+ @type.subscope(@scope, @resource).should == "foo"
+ end
+
+ it "should set the source as itself" do
+ @scope.expects(:newscope).with { |args| args[:source] == @type }
+ @type.subscope(@scope, @resource)
+ end
+
+ it "should set the scope's namespace to its namespace" do
+ @type.expects(:namespace).returns "yayness"
+ @scope.expects(:newscope).with { |args| args[:namespace] == "yayness" }
+ @type.subscope(@scope, @resource)
+ end
+
+ it "should set the scope's resource to the provided resource" do
+ @scope.expects(:newscope).with { |args| args[:resource] == @resource }
+ @type.subscope(@scope, @resource)
+ end
+ end
+
+ describe "when setting its parameters in the scope" do
+ before do
+ @scope = stub 'scope', :newscope => nil, :setvar => nil
+ @resource = stub 'resource', :title => "yay", :name => "yea", :ref => "Foo[bar]"
+ @type = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+ end
+
+ it "should set each of the resource's parameters as variables in the scope" do
+ @type.set_arguments :foo => nil, :boo => nil
+ @resource.expects(:to_hash).returns(:foo => "bar", :boo => "baz")
+
+ @scope.expects(:setvar).with("foo", "bar")
+ @scope.expects(:setvar).with("boo", "baz")
+
+ @type.set_resource_parameters(@resource, @scope)
+ end
+
+ it "should set the variables as strings" do
+ @type.set_arguments :foo => nil
+ @resource.expects(:to_hash).returns(:foo => "bar")
+ @scope.expects(:setvar).with("foo", "bar")
+
+ @type.set_resource_parameters(@resource, @scope)
+ end
+
+ it "should fail if any of the resource's parameters are not valid attributes" do
+ @type.set_arguments :foo => nil
+ @resource.expects(:to_hash).returns(:boo => "baz")
+
+ lambda { @type.set_resource_parameters(@resource, @scope) }.should raise_error(Puppet::ParseError)
+ end
+
+ it "should evaluate and set its default values as variables for parameters not provided by the resource" do
+ @type.set_arguments :foo => stub("value", :safeevaluate => "something")
+ @resource.expects(:to_hash).returns({})
+
+ @scope.expects(:setvar).with("foo", "something")
+
+ @type.set_resource_parameters(@resource, @scope)
+ end
+
+ it "should fail if the resource does not provide a value for a required argument" do
+ @type.set_arguments :foo => nil
+ @resource.expects(:to_hash).returns({})
+
+ lambda { @type.set_resource_parameters(@resource, @scope) }.should raise_error(Puppet::ParseError)
+ end
+
+ it "should set the resource's title as a variable if not otherwise provided" do
+ @resource.expects(:to_hash).returns({})
+
+ @resource.expects(:title).returns 'teetle'
+ @scope.expects(:setvar).with("title", "teetle")
+
+ @type.set_resource_parameters(@resource, @scope)
+ end
+
+ it "should set the resource's name as a variable if not otherwise provided" do
+ @resource.expects(:to_hash).returns({})
+
+ @resource.expects(:name).returns 'nombre'
+ @scope.expects(:setvar).with("name", "nombre")
+
+ @type.set_resource_parameters(@resource, @scope)
+ end
+ end
+
+ describe "when describing and managing parent classes" do
+ before do
+ @code = Puppet::Parser::LoadedCode.new
+ @parent = Puppet::Parser::ResourceType.new(:hostclass, "bar")
+ @code.add @parent
+
+ @child = Puppet::Parser::ResourceType.new(:hostclass, "foo", :parent => "bar")
+ @code.add @child
+ end
+
+ it "should be able to define a parent" do
+ Puppet::Parser::ResourceType.new(:hostclass, "foo", :parent => "bar")
+ end
+
+ it "should use the code collection to find the parent resource type" do
+ @child.parent_type.should equal(@parent)
+ end
+
+ it "should be able to find parent nodes" do
+ parent = Puppet::Parser::ResourceType.new(:node, "bar")
+ @code.add parent
+ child = Puppet::Parser::ResourceType.new(:node, "foo", :parent => "bar")
+ @code.add child
+
+ child.parent_type.should equal(parent)
+ end
+
+ it "should cache a reference to the parent type" do
+ @code.expects(:hostclass).once.with("bar").returns @parent
+ @child.parent_type
+ @child.parent_type
+ end
+
+ it "should correctly state when it is another type's child" do
+ @child.should be_child_of(@parent)
+ end
+
+ it "should be considered the child of a parent's parent" do
+ @grandchild = Puppet::Parser::ResourceType.new(:hostclass, "baz", :parent => "foo")
+ @code.add @grandchild
+
+ @grandchild.should be_child_of(@parent)
+ end
+
+ it "should correctly state when it is not another type's child" do
+ @notchild = Puppet::Parser::ResourceType.new(:hostclass, "baz")
+ @code.add @notchild
+
+ @notchild.should_not be_child_of(@parent)
+ end
+ end
+
+ describe "when evaluating its code" do
+ before do
+ @scope = stub 'scope', :newscope => nil, :setvar => nil
+ @resource = stub 'resource', :title => "yay", :name => "yea", :ref => "Foo[bar]", :scope => @scope
+ @type = Puppet::Parser::ResourceType.new(:hostclass, "foo")
+ @type.stubs(:set_resource_parameters)
+ end
+
+ it "should set all of its parameters in a subscope" do
+ subscope = stub 'subscope'
+ @type.expects(:subscope).with(@scope, @resource).returns subscope
+ @type.expects(:set_resource_parameters).with(@resource, subscope)
+
+ @type.evaluate_code(@resource)
+ end
+
+ it "should evaluate the code if any is provided" do
+ code = stub 'code'
+ @type.expects(:code).returns code
+ @type.stubs(:subscope).returns stub("subscope")
+ code.expects(:safeevaluate).with @type.subscope
+
+ @type.evaluate_code(@resource)
+ end
+
+ it "should noop if there is no code" do
+ @type.expects(:code).returns nil
+ @type.stubs(:subscope).returns stub("subscope")
+
+ @type.evaluate_code(@resource)
+ end
+ end
+
+ describe "when creating a resource" do
+ before do
+ @catalog = Puppet::Resource::Catalog.new
+ @node = stub 'node', :name => "foo", :classes => []
+ @compiler = Puppet::Parser::Compiler.new(@node, @catalog)
+ @scope = Puppet::Parser::Scope.new
+ @scope.stubs(:compiler).returns @compiler
+
+ @top = Puppet::Parser::ResourceType.new :hostclass, "top"
+ @middle = Puppet::Parser::ResourceType.new :hostclass, "middle", :parent => "top"
+
+ @code = Puppet::Parser::LoadedCode.new
+ @code.add @top
+ @code.add @middle
+ end
+
+ it "should create a resource instance" do
+ @top.mk_plain_resource(@scope).should be_instance_of(Puppet::Parser::Resource)
+ end
+
+ it "should set its resource type to 'class' when it is a hostclass" do
+ Puppet::Parser::ResourceType.new(:hostclass, "top").mk_plain_resource(@scope).type.should == "Class"
+ end
+
+ it "should set its resource type to 'node' when it is a node" do
+ Puppet::Parser::ResourceType.new(:node, "top").mk_plain_resource(@scope).type.should == "Node"
+ end
+
+ it "should fail when it is a definition" do
+ lambda { Puppet::Parser::ResourceType.new(:definition, "top").mk_plain_resource(@scope) }.should raise_error(ArgumentError)
+ end
+
+ it "should add the created resource to the scope's catalog" do
+ @top.mk_plain_resource(@scope)
+
+ @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
+ end
+
+ it "should evaluate the parent class if one exists" do
+ @middle.mk_plain_resource(@scope)
+
+ @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
+ end
+
+ it "should fail to evaluate if a parent class is defined but cannot be found" do
+ othertop = Puppet::Parser::ResourceType.new :hostclass, "something", :parent => "yay"
+ @code.add othertop
+ lambda { othertop.mk_plain_resource(@scope) }.should raise_error(Puppet::ParseError)
+ end
+
+ it "should not create a new resource if one already exists" do
+ @compiler.catalog.expects(:resource).with(:class, "top").returns("something")
+ @compiler.catalog.expects(:add_resource).never
+ @top.mk_plain_resource(@scope)
+ end
+
+ it "should return the existing resource when not creating a new one" do
+ @compiler.catalog.expects(:resource).with(:class, "top").returns("something")
+ @compiler.catalog.expects(:add_resource).never
+ @top.mk_plain_resource(@scope).should == "something"
+ end
+
+ it "should not create a new parent resource if one already exists and it has a parent class" do
+ @top.mk_plain_resource(@scope)
+
+ top_resource = @compiler.catalog.resource(:class, "top")
+
+ @middle.mk_plain_resource(@scope)
+
+ @compiler.catalog.resource(:class, "top").should equal(top_resource)
+ end
+
+ # #795 - tag before evaluation.
+ it "should tag the catalog with the resource tags when it is evaluated" do
+ @middle.mk_plain_resource(@scope)
+
+ @compiler.catalog.should be_tagged("middle")
+ end
+
+ it "should tag the catalog with the parent class tags when it is evaluated" do
+ @middle.mk_plain_resource(@scope)
+
+ @compiler.catalog.should be_tagged("top")
+ end
+ end
+
+ describe "when merging code from another instance" do
+ def code(str)
+ Puppet::Parser::AST::Leaf.new :value => str
+ end
+
+ it "should fail unless it is a class" do
+ lambda { Puppet::Parser::ResourceType.new(:node, "bar").merge("foo") }.should raise_error(ArgumentError)
+ end
+
+ it "should fail unless the source instance is a class" do
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar")
+ source = Puppet::Parser::ResourceType.new(:node, "foo")
+ lambda { dest.merge(source) }.should raise_error(ArgumentError)
+ end
+
+ it "should fail if both classes have different parent classes" do
+ code = Puppet::Parser::LoadedCode.new
+ {"a" => "b", "c" => "d"}.each do |parent, child|
+ code.add Puppet::Parser::ResourceType.new(:hostclass, parent)
+ code.add Puppet::Parser::ResourceType.new(:hostclass, child, :parent => parent)
+ end
+ lambda { code.hostclass("b").merge(code.hostclass("d")) }.should raise_error(ArgumentError)
+ end
+
+ it "should copy the other class's parent if it has not parent" do
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar")
+
+ parent = Puppet::Parser::ResourceType.new(:hostclass, "parent")
+ source = Puppet::Parser::ResourceType.new(:hostclass, "foo", :parent => "parent")
+ dest.merge(source)
+
+ dest.parent.should == "parent"
+ end
+
+ it "should copy the other class's documentation as its docs if it has no docs" do
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar")
+ source = Puppet::Parser::ResourceType.new(:hostclass, "foo", :doc => "yayness")
+ dest.merge(source)
+
+ dest.doc.should == "yayness"
+ end
+
+ it "should append the other class's docs to its docs if it has any" do
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar", :doc => "fooness")
+ source = Puppet::Parser::ResourceType.new(:hostclass, "foo", :doc => "yayness")
+ dest.merge(source)
+
+ dest.doc.should == "foonessyayness"
+ end
+
+ it "should turn its code into an ASTArray if necessary" do
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar", :code => code("foo"))
+ source = Puppet::Parser::ResourceType.new(:hostclass, "foo", :code => code("bar"))
+
+ dest.merge(source)
+
+ dest.code.should be_instance_of(Puppet::Parser::AST::ASTArray)
+ end
+
+ it "should set the other class's code as its code if it has none" do
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar")
+ source = Puppet::Parser::ResourceType.new(:hostclass, "foo", :code => code("bar"))
+
+ dest.merge(source)
+
+ dest.code.value.should == "bar"
+ end
+
+ it "should append the other class's code to its code if it has any" do
+ dcode = Puppet::Parser::AST::ASTArray.new :children => [code("dest")]
+ dest = Puppet::Parser::ResourceType.new(:hostclass, "bar", :code => dcode)
+
+ scode = Puppet::Parser::AST::ASTArray.new :children => [code("source")]
+ source = Puppet::Parser::ResourceType.new(:hostclass, "foo", :code => scode)
+
+ dest.merge(source)
+
+ dest.code.children.collect { |l| l.value }.should == %w{dest source}
+ end
+ end
+end
diff --git a/spec/unit/util/rdoc/parser.rb b/spec/unit/util/rdoc/parser.rb
index 593e6acc8..19c91bb9a 100755
--- a/spec/unit/util/rdoc/parser.rb
+++ b/spec/unit/util/rdoc/parser.rb
@@ -137,9 +137,9 @@ describe RDoc::Parser do
describe "when parsing AST elements" do
before :each do
- @klass = stub_everything 'klass', :file => "module/manifests/init.pp", :classname => "myclass"
- @definition = stub_everything 'definition', :file => "module/manifests/init.pp"
- @node = stub_everything 'node', :file => "module/manifests/init.pp"
+ @klass = stub_everything 'klass', :file => "module/manifests/init.pp", :name => "myclass", :type => :hostclass
+ @definition = stub_everything 'definition', :file => "module/manifests/init.pp", :type => :definition, :name => "mydef"
+ @node = stub_everything 'node', :file => "module/manifests/init.pp", :type => :node, :name => "mynode"
@loadedcode = Puppet::Parser::LoadedCode.new
@parser.ast = @loadedcode
@@ -148,7 +148,7 @@ describe RDoc::Parser do
end
it "should document classes in the parsed file" do
- @loadedcode.add_hostclass("myclass", @klass)
+ @loadedcode.add_hostclass(@klass)
@parser.expects(:document_class).with("myclass", @klass, @container)
@@ -157,7 +157,7 @@ describe RDoc::Parser do
it "should not document class parsed in an other file" do
@klass.stubs(:file).returns("/not/same/path/file.pp")
- @loadedcode.add_hostclass("myclass", @klass)
+ @loadedcode.add_hostclass(@klass)
@parser.expects(:document_class).with("myclass", @klass, @container).never
@@ -165,10 +165,11 @@ describe RDoc::Parser do
end
it "should document vardefs for the main class" do
- @loadedcode.add_hostclass(:main, @klass)
+ @klass.stubs(:name).returns :main
+ @loadedcode.add_hostclass(@klass)
code = stub 'code', :is_a? => false
- @klass.stubs(:classname).returns("")
+ @klass.stubs(:name).returns("")
@klass.stubs(:code).returns(code)
@parser.expects(:scan_for_vardef).with(@container, code)
@@ -177,7 +178,7 @@ describe RDoc::Parser do
end
it "should document definitions in the parsed file" do
- @loadedcode.add_definition("mydef", @definition)
+ @loadedcode.add_definition(@definition)
@parser.expects(:document_define).with("mydef", @definition, @container)
@@ -186,7 +187,7 @@ describe RDoc::Parser do
it "should not document definitions parsed in an other file" do
@definition.stubs(:file).returns("/not/same/path/file.pp")
- @loadedcode.add_definition("mydef", @definition)
+ @loadedcode.add_definition(@definition)
@parser.expects(:document_define).with("mydef", @definition, @container).never
@@ -194,7 +195,7 @@ describe RDoc::Parser do
end
it "should document nodes in the parsed file" do
- @loadedcode.add_node("mynode", @node)
+ @loadedcode.add_node(@node)
@parser.expects(:document_node).with("mynode", @node, @container)
@@ -203,7 +204,7 @@ describe RDoc::Parser do
it "should not document node parsed in an other file" do
@node.stubs(:file).returns("/not/same/path/file.pp")
- @loadedcode.add_node("mynode", @node)
+ @loadedcode.add_node(@node)
@parser.expects(:document_node).with("mynode", @node, @container).never