summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-02-11 17:24:02 -0600
committerLuke Kanies <luke@madstop.com>2008-02-11 17:24:02 -0600
commit6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0 (patch)
treedf96556dd073aa5d0c23c735a2456da8f144f6b9
parent3b740ff7a6ab7127ec5e4935782c33245687c429 (diff)
downloadpuppet-6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0.tar.gz
puppet-6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0.tar.xz
puppet-6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0.zip
Fixed #1030 - class and definition evaluation has been significantly
refactored, fixing this problem and making the whole interplay between the classes, definitions, and nodes, and the Compile class much cleaner.
-rw-r--r--CHANGELOG11
-rw-r--r--lib/puppet/node/catalog.rb5
-rw-r--r--lib/puppet/parser/ast/definition.rb31
-rw-r--r--lib/puppet/parser/ast/hostclass.rb14
-rw-r--r--lib/puppet/parser/compile.rb10
-rwxr-xr-xspec/unit/parser/ast/hostclass.rb131
-rwxr-xr-xspec/unit/parser/compile.rb206
-rwxr-xr-xtest/language/ast/hostclass.rb184
8 files changed, 264 insertions, 328 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 1df2e53c4..8a8ebdbef 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,11 @@
- Exec resources must now have unique names. This is easily accomplished
- by just specifying a unique name with whatever (unique or otherwise)
- command you need.
+ Fixed #1030 - class and definition evaluation has been significantly
+ refactored, fixing this problem and making the whole interplay
+ between the classes, definitions, and nodes, and the Compile class much
+ cleaner.
+
+ Exec resources must now have unique names. This is easily accomplished by
+ just specifying a unique name with whatever (unique or otherwise) command
+ you need.
Fixed #989 -- missing CRL files are correctly ignored, and the
value should be set to 'false' to explicitly not look for these
diff --git a/lib/puppet/node/catalog.rb b/lib/puppet/node/catalog.rb
index 03187cc94..f93d2786d 100644
--- a/lib/puppet/node/catalog.rb
+++ b/lib/puppet/node/catalog.rb
@@ -395,6 +395,11 @@ class Puppet::Node::Catalog < Puppet::PGraph
nil
end
+ # Does our tag list include this tag?
+ def tagged?(tag)
+ @tags.include?(tag)
+ end
+
# Return the list of tags.
def tags
@tags.dup
diff --git a/lib/puppet/parser/ast/definition.rb b/lib/puppet/parser/ast/definition.rb
index bf57942d7..e3f6414c3 100644
--- a/lib/puppet/parser/ast/definition.rb
+++ b/lib/puppet/parser/ast/definition.rb
@@ -24,7 +24,12 @@ class Puppet::Parser::AST::Definition < Puppet::Parser::AST::Branch
# Create a resource that knows how to evaluate our actual code.
def evaluate(scope)
- resource = Puppet::Parser::Resource.new(:type => "class", :title => klass.classname, :scope => scope, :source => scope.source)
+ # Do nothing if the resource already exists; this provides the singleton nature classes need.
+ return if scope.catalog.resource(:class, self.classname)
+
+ resource = Puppet::Parser::Resource.new(:type => "class", :title => self.classname, :scope => scope, :source => scope.source)
+
+ scope.catalog.tag(*resource.tags)
scope.compile.store_resource(scope, resource)
@@ -91,23 +96,21 @@ class Puppet::Parser::AST::Definition < Puppet::Parser::AST::Branch
# Hunt down our class object.
def parentobj
- if @parentclass
- # Cache our result, since it should never change.
- unless defined?(@parentobj)
- unless tmp = find_parentclass
- parsefail "Could not find %s %s" % [self.class.name, @parentclass]
- end
+ return nil unless @parentclass
- if tmp == self
- parsefail "Parent classes must have dissimilar names"
- end
+ # Cache our result, since it should never change.
+ unless defined?(@parentobj)
+ unless tmp = find_parentclass
+ parsefail "Could not find %s parent %s" % [self.class.name, @parentclass]
+ end
- @parentobj = tmp
+ if tmp == self
+ parsefail "Parent classes must have dissimilar names"
end
- @parentobj
- else
- nil
+
+ @parentobj = tmp
end
+ @parentobj
end
# Create a new subscope in which to evaluate our code.
diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb
index 251d5eba6..4f2d00f0c 100644
--- a/lib/puppet/parser/ast/hostclass.rb
+++ b/lib/puppet/parser/ast/hostclass.rb
@@ -18,6 +18,15 @@ class Puppet::Parser::AST::HostClass < Puppet::Parser::AST::Definition
end
end
+ # Make sure our parent class has been evaluated, if we have one.
+ def evaluate(scope)
+ if parentclass and ! scope.catalog.resource(:class, parentclass)
+ resource = parentobj.evaluate(scope)
+ end
+
+ super
+ end
+
# Evaluate the code associated with this class.
def evaluate_code(resource)
scope = resource.scope
@@ -58,11 +67,6 @@ class Puppet::Parser::AST::HostClass < Puppet::Parser::AST::Definition
end
end
- def initialize(options)
- @parentclass = nil
- super
- end
-
def parent_scope(scope, klass)
if s = scope.compile.class_scope(klass)
return s
diff --git a/lib/puppet/parser/compile.rb b/lib/puppet/parser/compile.rb
index 46ce1cb9b..bceead271 100644
--- a/lib/puppet/parser/compile.rb
+++ b/lib/puppet/parser/compile.rb
@@ -115,16 +115,11 @@ class Puppet::Parser::Compile
if klass = scope.findclass(name)
found << name and next if class_scope(klass)
- # Create a resource to model this class, and then add it to the list
- # of resources.
- resource = Puppet::Parser::Resource.new(:type => "class", :title => klass.classname, :scope => scope, :source => scope.source)
-
- store_resource(scope, resource)
+ resource = klass.evaluate(scope)
# If they've disabled lazy evaluation (which the :include function does),
# then evaluate our resource immediately.
resource.evaluate unless lazy_evaluate
- @catalog.tag(klass.classname)
found << name
else
Puppet.info "Could not find class %s for %s" % [name, node.name]
@@ -412,9 +407,6 @@ class Puppet::Parser::Compile
# but they each refer back to the scope that created them.
@collections = []
- # A list of tags we've generated; most class names.
- @tags = []
-
# A graph for maintaining scope relationships.
@scope_graph = Puppet::SimpleGraph.new
diff --git a/spec/unit/parser/ast/hostclass.rb b/spec/unit/parser/ast/hostclass.rb
new file mode 100755
index 000000000..b1e8a48ea
--- /dev/null
+++ b/spec/unit/parser/ast/hostclass.rb
@@ -0,0 +1,131 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+module HostClassTesting
+ def setup
+ @node = Puppet::Node.new "testnode"
+ @parser = Puppet::Parser::Parser.new :environment => "development"
+ @scope_resource = stub 'scope_resource', :builtin? => true
+ @compile = Puppet::Parser::Compile.new(@node, @parser)
+
+ @scope = @compile.topscope
+ end
+end
+
+describe Puppet::Parser::AST::HostClass, "when evaluating" do
+ include HostClassTesting
+
+ 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)
+
+ @compile.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)
+
+ @compile.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
+ @compile.catalog.expects(:resource).with(:class, "top").returns("something")
+ @compile.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 = @compile.catalog.resource(:class, "top")
+
+ @middle.evaluate(@scope)
+
+ @compile.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)
+
+ @compile.catalog.should be_tagged("middle")
+ end
+
+ it "should tag the catalog with the parent class tags when it is evaluated" do
+ @middle.evaluate(@scope)
+
+ @compile.catalog.should be_tagged("top")
+ end
+end
+
+describe Puppet::Parser::AST::HostClass, "when evaluating code" do
+ include HostClassTesting
+
+ 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)
+
+ @compile.class_scope(@middle).parent.should equal(@compile.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)
+
+ @compile.class_scope(@middle).namespaces.should be_include(@top.namespace)
+ end
+end
diff --git a/spec/unit/parser/compile.rb b/spec/unit/parser/compile.rb
index d495ac343..ff205f7a5 100755
--- a/spec/unit/parser/compile.rb
+++ b/spec/unit/parser/compile.rb
@@ -13,6 +13,78 @@ module CompileTesting
end
end
+describe Puppet::Parser::Compile do
+ include CompileTesting
+
+ it "should be able to store references to class scopes" do
+ lambda { @compile.class_set "myname", "myscope" }.should_not raise_error
+ end
+
+ it "should be able to retrieve class scopes by name" do
+ @compile.class_set "myname", "myscope"
+ @compile.class_scope("myname").should == "myscope"
+ end
+
+ it "should be able to retrieve class scopes by object" do
+ klass = mock 'ast_class'
+ klass.expects(:classname).returns("myname")
+ @compile.class_set "myname", "myscope"
+ @compile.class_scope(klass).should == "myscope"
+ end
+
+ it "should be able to return a class list containing all set classes" do
+ @compile.class_set "", "empty"
+ @compile.class_set "one", "yep"
+ @compile.class_set "two", "nope"
+
+ @compile.classlist.sort.should == %w{one two}.sort
+ end
+end
+
+describe Puppet::Parser::Compile, " when initializing" do
+ include CompileTesting
+
+ it "should set its node attribute" do
+ @compile.node.should equal(@node)
+ end
+
+ it "should set its parser attribute" do
+ @compile.parser.should equal(@parser)
+ end
+
+ it "should detect when ast nodes are absent" do
+ @compile.ast_nodes?.should be_false
+ end
+
+ it "should detect when ast nodes are present" do
+ @parser.nodes["testing"] = "yay"
+ @compile.ast_nodes?.should be_true
+ end
+end
+
+describe Puppet::Parser::Compile, "when managing scopes" do
+ include CompileTesting
+
+ it "should create a top scope" do
+ @compile.topscope.should be_instance_of(Puppet::Parser::Scope)
+ end
+
+ it "should be able to create new scopes" do
+ @compile.newscope(@compile.topscope).should be_instance_of(Puppet::Parser::Scope)
+ end
+
+ it "should correctly set the level of newly created scopes" do
+ @compile.newscope(@compile.topscope, :level => 5).level.should == 5
+ end
+
+ it "should set the parent scope of the new scope to be the passed-in parent" do
+ scope = mock 'scope'
+ newscope = @compile.newscope(scope)
+
+ @compile.parent(newscope).should equal(scope)
+ end
+end
+
describe Puppet::Parser::Compile, " when compiling" do
include CompileTesting
@@ -174,21 +246,6 @@ describe Puppet::Parser::Compile, " when compiling" do
end
end
-describe Puppet::Parser::Compile, " when evaluating classes" do
- include CompileTesting
-
- it "should fail if there's no source listed for the scope" do
- scope = stub 'scope', :source => nil
- proc { @compile.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError)
- end
-
- it "should tag the catalog with the name of each not-found class" do
- @compile.catalog.expects(:tag).with("notfound")
- @scope.expects(:findclass).with("notfound").returns(nil)
- @compile.evaluate_classes(%w{notfound}, @scope)
- end
-end
-
describe Puppet::Parser::Compile, " when evaluating collections" do
include CompileTesting
@@ -235,6 +292,20 @@ describe Puppet::Parser::Compile, " when evaluating collections" do
end
end
+describe Puppet::Parser::Compile, "when told to evaluate missing classes" do
+ include CompileTesting
+
+ it "should fail if there's no source listed for the scope" do
+ scope = stub 'scope', :source => nil
+ proc { @compile.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError)
+ end
+
+ it "should tag the catalog with the name of each not-found class" do
+ @compile.catalog.expects(:tag).with("notfound")
+ @scope.expects(:findclass).with("notfound").returns(nil)
+ @compile.evaluate_classes(%w{notfound}, @scope)
+ end
+end
describe Puppet::Parser::Compile, " when evaluating found classes" do
include CompileTesting
@@ -243,53 +314,33 @@ describe Puppet::Parser::Compile, " when evaluating found classes" do
@class = stub 'class', :classname => "my::class"
@scope.stubs(:findclass).with("myclass").returns(@class)
- @resource = stub 'resource', :ref => 'Class[myclass]'
- end
-
- it "should create a resource for each found class" do
- @compile.catalog.stubs(:tag)
-
- @compile.stubs :store_resource
-
- Puppet::Parser::Resource.expects(:new).with(:scope => @scope, :source => @scope.source, :title => "my::class", :type => "class").returns(@resource)
- @compile.evaluate_classes(%w{myclass}, @scope)
+ @resource = stub 'resource', :ref => "Class[myclass]"
end
- it "should store each created resource in the compile" do
+ it "should evaluate each class" do
@compile.catalog.stubs(:tag)
- @compile.expects(:store_resource).with(@scope, @resource)
-
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
- @compile.evaluate_classes(%w{myclass}, @scope)
- end
-
- it "should tag the catalog with the fully-qualified name of each found class" do
- @compile.catalog.expects(:tag).with("my::class")
+ @class.expects(:evaluate).with(@scope)
- @compile.stubs(:store_resource)
-
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
@compile.evaluate_classes(%w{myclass}, @scope)
end
it "should not evaluate the resources created for found classes unless asked" do
@compile.catalog.stubs(:tag)
- @compile.stubs(:store_resource)
@resource.expects(:evaluate).never
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
+ @class.expects(:evaluate).returns(@resource)
+
@compile.evaluate_classes(%w{myclass}, @scope)
end
it "should immediately evaluate the resources created for found classes when asked" do
@compile.catalog.stubs(:tag)
- @compile.stubs(:store_resource)
@resource.expects(:evaluate)
+ @class.expects(:evaluate).returns(@resource)
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
@compile.evaluate_classes(%w{myclass}, @scope, false)
end
@@ -313,6 +364,7 @@ describe Puppet::Parser::Compile, " when evaluating found classes" do
@scope.stubs(:findclass).with("notfound").returns(nil)
Puppet::Parser::Resource.stubs(:new).returns(@resource)
+ @class.stubs :evaluate
@compile.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass}
end
end
@@ -411,78 +463,6 @@ describe Puppet::Parser::Compile, " when evaluating AST nodes with AST nodes pre
end
end
-describe Puppet::Parser::Compile, " when initializing" do
- include CompileTesting
-
- it "should set its node attribute" do
- @compile.node.should equal(@node)
- end
-
- it "should set its parser attribute" do
- @compile.parser.should equal(@parser)
- end
-
- it "should detect when ast nodes are absent" do
- @compile.ast_nodes?.should be_false
- end
-
- it "should detect when ast nodes are present" do
- @parser.nodes["testing"] = "yay"
- @compile.ast_nodes?.should be_true
- end
-end
-
-describe Puppet::Parser::Compile do
- include CompileTesting
-
- it "should be able to store references to class scopes" do
- lambda { @compile.class_set "myname", "myscope" }.should_not raise_error
- end
-
- it "should be able to retrieve class scopes by name" do
- @compile.class_set "myname", "myscope"
- @compile.class_scope("myname").should == "myscope"
- end
-
- it "should be able to retrieve class scopes by object" do
- klass = mock 'ast_class'
- klass.expects(:classname).returns("myname")
- @compile.class_set "myname", "myscope"
- @compile.class_scope(klass).should == "myscope"
- end
-
- it "should be able to return a class list containing all set classes" do
- @compile.class_set "", "empty"
- @compile.class_set "one", "yep"
- @compile.class_set "two", "nope"
-
- @compile.classlist.sort.should == %w{one two}.sort
- end
-end
-
-describe Puppet::Parser::Compile, "when managing scopes" do
- include CompileTesting
-
- it "should create a top scope" do
- @compile.topscope.should be_instance_of(Puppet::Parser::Scope)
- end
-
- it "should be able to create new scopes" do
- @compile.newscope(@compile.topscope).should be_instance_of(Puppet::Parser::Scope)
- end
-
- it "should correctly set the level of newly created scopes" do
- @compile.newscope(@compile.topscope, :level => 5).level.should == 5
- end
-
- it "should set the parent scope of the new scope to be the passed-in parent" do
- scope = mock 'scope'
- newscope = @compile.newscope(scope)
-
- @compile.parent(newscope).should equal(scope)
- end
-end
-
describe Puppet::Parser::Compile, "when storing compiled resources" do
include CompileTesting
diff --git a/test/language/ast/hostclass.rb b/test/language/ast/hostclass.rb
deleted file mode 100755
index 7697317a6..000000000
--- a/test/language/ast/hostclass.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env ruby
-#
-# Created by Luke A. Kanies on 2006-02-20.
-# Copyright (c) 2006. All rights reserved.
-
-require File.dirname(__FILE__) + '/../../lib/puppettest'
-
-require 'puppettest'
-require 'puppettest/parsertesting'
-require 'puppettest/resourcetesting'
-require 'mocha'
-
-class TestASTHostClass < Test::Unit::TestCase
- include PuppetTest
- include PuppetTest::ParserTesting
- include PuppetTest::ResourceTesting
- AST = Puppet::Parser::AST
-
- def test_hostclass
- scope = mkscope
- parser = scope.compile.parser
-
- # Create the class we're testing, first with no parent
- klass = parser.newclass "first",
- :code => AST::ASTArray.new(
- :children => [resourcedef("file", "/tmp",
- "owner" => "nobody", "mode" => "755")]
- )
-
- resource = Puppet::Parser::Resource.new(:type => "class", :title => "first", :scope => scope)
- assert_nothing_raised do
- klass.evaluate_code(resource)
- end
-
- # Then try it again
- assert_nothing_raised do
- klass.evaluate_code(resource)
- end
-
- assert(scope.compile.class_scope(klass), "Class was not considered evaluated")
-
- tmp = scope.findresource("File[/tmp]")
- assert(tmp, "Could not find file /tmp")
- assert_equal("nobody", tmp[:owner])
- assert_equal("755", tmp[:mode])
-
- # Now create a couple more classes.
- newbase = parser.newclass "newbase",
- :code => AST::ASTArray.new(
- :children => [resourcedef("file", "/tmp/other",
- "owner" => "nobody", "mode" => "644")]
- )
-
- newsub = parser.newclass "newsub",
- :parent => "newbase",
- :code => AST::ASTArray.new(
- :children => [resourcedef("file", "/tmp/yay",
- "owner" => "nobody", "mode" => "755"),
- resourceoverride("file", "/tmp/other",
- "owner" => "daemon")
- ]
- )
-
- # Override a different variable in the top scope.
- moresub = parser.newclass "moresub",
- :parent => "newbase",
- :code => AST::ASTArray.new(
- :children => [resourceoverride("file", "/tmp/other",
- "mode" => "755")]
- )
-
- assert_nothing_raised do
- newsub.evaluate_code(resource)
- end
-
- assert_nothing_raised do
- moresub.evaluate_code(resource)
- end
-
- assert(scope.compile.class_scope(newbase), "Did not eval newbase")
- assert(scope.compile.class_scope(newsub), "Did not eval newsub")
-
- yay = scope.findresource("File[/tmp/yay]")
- assert(yay, "Did not find file /tmp/yay")
- assert_equal("nobody", yay[:owner])
- assert_equal("755", yay[:mode])
-
- other = scope.findresource("File[/tmp/other]")
- assert(other, "Did not find file /tmp/other")
- assert_equal("daemon", other[:owner])
- assert_equal("755", other[:mode])
- end
-
- # Make sure that classes set their namespaces to themselves. This
- # way they start looking for definitions in their own namespace.
- def test_hostclass_namespace
- scope = mkscope
- parser = scope.compile.parser
-
- # Create a new class
- klass = nil
- assert_nothing_raised do
- klass = parser.newclass "funtest"
- end
-
- # Now define a definition in that namespace
-
- define = nil
- assert_nothing_raised do
- define = parser.newdefine "funtest::mydefine"
- end
-
- assert_equal("funtest", klass.namespace,
- "component namespace was not set in the class")
-
- assert_equal("funtest", define.namespace,
- "component namespace was not set in the definition")
-
- newscope = klass.subscope(scope, mock("resource"))
-
- assert_equal(["funtest"], newscope.namespaces,
- "Scope did not inherit namespace")
-
- # Now make sure we can find the define
- assert(newscope.finddefine("mydefine"),
- "Could not find definition in my enclosing class")
- end
-
- # Make sure that our scope is a subscope of the parentclass's scope.
- # At the same time, make sure definitions in the parent class can be
- # found within the subclass (#517).
- def test_parent_scope_from_parentclass
- scope = mkscope
- parser = scope.compile.parser
-
- source = parser.newclass ""
- parser.newclass("base")
- fun = parser.newdefine("base::fun")
- parser.newclass("middle", :parent => "base")
- parser.newclass("sub", :parent => "middle")
- scope = mkscope :parser => parser
-
- ret = nil
- assert_nothing_raised do
- ret = scope.compile.evaluate_classes(["sub"], scope)
- end
- scope.compile.send(:evaluate_generators)
-
- subscope = scope.compile.class_scope(scope.findclass("sub"))
- assert(subscope, "could not find sub scope")
- mscope = scope.compile.class_scope(scope.findclass("middle"))
- assert(mscope, "could not find middle scope")
- pscope = scope.compile.class_scope(scope.findclass("base"))
- assert(pscope, "could not find parent scope")
-
- assert(pscope == mscope.parent, "parent scope of middle was not set correctly")
- assert(mscope == subscope.parent, "parent scope of sub was not set correctly")
-
- result = mscope.finddefine("fun")
- assert(result, "could not find parent-defined definition from middle")
- assert(fun == result, "found incorrect parent-defined definition from middle")
-
- result = subscope.finddefine("fun")
- assert(result, "could not find parent-defined definition from sub")
- assert(fun == result, "found incorrect parent-defined definition from sub")
- end
-
- # #795 - make sure the subclass's tags get set before we
- # evaluate the parent class, so we can be sure that the parent
- # class can switch based on the sub classes.
- def test_tags_set_before_parent_is_evaluated
- scope = mkscope
- parser = scope.compile.parser
- base = parser.newclass "base"
- sub = parser.newclass "sub", :parent => "base"
-
- base.expects(:evaluate_code).with do |*args|
- assert(scope.catalog.tags.include?("sub"), "Did not tag with sub class name before evaluating base class")
- base.evaluate_code(*args)
- true
- end
- sub.evaluate_code scope.resource
- end
-end