diff options
Diffstat (limited to 'spec')
-rwxr-xr-x | spec/integration/indirector/catalog/compiler_spec.rb | 7 | ||||
-rwxr-xr-x | spec/integration/type/file_spec.rb | 13 | ||||
-rwxr-xr-x | spec/unit/parser/functions/create_resources_spec.rb | 36 | ||||
-rwxr-xr-x | spec/unit/resource/catalog_spec.rb | 8 | ||||
-rwxr-xr-x | spec/unit/simple_graph_spec.rb | 165 | ||||
-rwxr-xr-x | spec/unit/transaction_spec.rb | 24 | ||||
-rw-r--r-- | spec/unit/type/whit_spec.rb | 4 |
7 files changed, 143 insertions, 114 deletions
diff --git a/spec/integration/indirector/catalog/compiler_spec.rb b/spec/integration/indirector/catalog/compiler_spec.rb index 1146c20b0..dafa1af7c 100755 --- a/spec/integration/indirector/catalog/compiler_spec.rb +++ b/spec/integration/indirector/catalog/compiler_spec.rb @@ -10,11 +10,8 @@ describe Puppet::Resource::Catalog::Compiler do before do Facter.stubs(:value).returns "something" @catalog = Puppet::Resource::Catalog.new - - @one = Puppet::Resource.new(:file, "/one") - - @two = Puppet::Resource.new(:file, "/two") - @catalog.add_resource(@one, @two) + @catalog.add_resource(@one = Puppet::Resource.new(:file, "/one")) + @catalog.add_resource(@two = Puppet::Resource.new(:file, "/two")) end after { Puppet.settings.clear } diff --git a/spec/integration/type/file_spec.rb b/spec/integration/type/file_spec.rb index 46900a0f1..513b96e41 100755 --- a/spec/integration/type/file_spec.rb +++ b/spec/integration/type/file_spec.rb @@ -28,7 +28,8 @@ describe Puppet::Type.type(:file) do bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo" catalog = Puppet::Resource::Catalog.new - catalog.add_resource file, bucket + catalog.add_resource file + catalog.add_resource bucket File.open(file[:path], "w") { |f| f.puts "bar" } @@ -80,7 +81,8 @@ describe Puppet::Type.type(:file) do bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" file = Puppet::Type.type(:file).new :path => link, :target => dest2, :ensure => :link, :backup => "mybucket" catalog = Puppet::Resource::Catalog.new - catalog.add_resource file, bucket + catalog.add_resource file + catalog.add_resource bucket File.open(dest1, "w") { |f| f.puts "whatever" } File.symlink(dest1, link) @@ -113,7 +115,8 @@ describe Puppet::Type.type(:file) do bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo", :force => true catalog = Puppet::Resource::Catalog.new - catalog.add_resource file, bucket + catalog.add_resource file + catalog.add_resource bucket Dir.mkdir(file[:path]) foofile = File.join(file[:path], "foo") @@ -337,10 +340,10 @@ describe Puppet::Type.type(:file) do it "should have an edge to each resource in the relationship graph" do @catalog.apply do |trans| one = @catalog.resource(:file, File.join(@dest, "one")) - @catalog.relationship_graph.should be_edge(@file, one) + @catalog.relationship_graph.edge?(@file, one).should be two = @catalog.resource(:file, File.join(@dest, "two")) - @catalog.relationship_graph.should be_edge(@file, two) + @catalog.relationship_graph.edge?(@file, two).should be end end end diff --git a/spec/unit/parser/functions/create_resources_spec.rb b/spec/unit/parser/functions/create_resources_spec.rb index d4095b777..366fb536c 100755 --- a/spec/unit/parser/functions/create_resources_spec.rb +++ b/spec/unit/parser/functions/create_resources_spec.rb @@ -51,11 +51,12 @@ describe 'function for dynamically creating resources' do it 'should be able to add edges' do @scope.function_create_resources(['notify', {'foo'=>{'require' => 'Notify[test]'}}]) @scope.compiler.compile - edge = @scope.compiler.catalog.to_ral.relationship_graph.edges.detect do |edge| - edge.source.title == 'test' - end - edge.source.title.should == 'test' - edge.target.title.should == 'foo' + rg = @scope.compiler.catalog.to_ral.relationship_graph + test = rg.vertices.find { |v| v.title == 'test' } + foo = rg.vertices.find { |v| v.title == 'foo' } + test.should be + foo.should be + rg.path_between(test,foo).should be end end describe 'when dynamically creating resource types' do @@ -93,11 +94,13 @@ notify{test:} it 'should be able to add edges' do @scope.function_create_resources(['foo', {'blah'=>{'one'=>'two', 'require' => 'Notify[test]'}}]) @scope.compiler.compile - edge = @scope.compiler.catalog.to_ral.relationship_graph.edges.detect do |edge| - edge.source.title == 'test' - end - edge.source.title.should == 'test' - edge.target.title.should == 'blah' + rg = @scope.compiler.catalog.to_ral.relationship_graph + test = rg.vertices.find { |v| v.title == 'test' } + blah = rg.vertices.find { |v| v.title == 'blah' } + test.should be + blah.should be + # (Yoda speak like we do) + rg.path_between(test,blah).should be @compiler.catalog.resource(:notify, "blah")['message'].should == 'two' end end @@ -123,13 +126,12 @@ notify{tester:} it 'should be able to add edges' do @scope.function_create_resources(['class', {'bar'=>{'one'=>'two', 'require' => 'Notify[tester]'}}]) @scope.compiler.compile - edge = @scope.compiler.catalog.to_ral.relationship_graph.edges.detect do |e| - e.source.title == 'tester' - end - edge.source.title.should == 'tester' - edge.target.title.should == 'test' - #@compiler.catalog.resource(:notify, "blah")['message'].should == 'two' + rg = @scope.compiler.catalog.to_ral.relationship_graph + test = rg.vertices.find { |v| v.title == 'test' } + tester = rg.vertices.find { |v| v.title == 'tester' } + test.should be + tester.should be + rg.path_between(tester,test).should be end - end end diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb index 42850c23b..78d1b3223 100755 --- a/spec/unit/resource/catalog_spec.rb +++ b/spec/unit/resource/catalog_spec.rb @@ -398,12 +398,6 @@ describe Puppet::Resource::Catalog, "when compiling" do relgraph.should be_vertex(@one) end - it "should yield added resources if a block is provided" do - yielded = [] - @catalog.add_resource(@one, @two) { |r| yielded << r } - yielded.length.should == 2 - end - it "should set itself as the resource's catalog if it is not a relationship graph" do @one.expects(:catalog=).with(@catalog) @catalog.add_resource @one @@ -740,7 +734,7 @@ describe Puppet::Resource::Catalog, "when compiling" do end it "should copy component relationships to all contained resources" do - @relationships.edge?(@one, @two).should be_true + @relationships.path_between(@one, @two).should be end it "should add automatic relationships to the relationship graph" do diff --git a/spec/unit/simple_graph_spec.rb b/spec/unit/simple_graph_spec.rb index c106f550b..99db2a55c 100755 --- a/spec/unit/simple_graph_spec.rb +++ b/spec/unit/simple_graph_spec.rb @@ -267,7 +267,7 @@ describe Puppet::SimpleGraph do end end - describe "when sorting the graph" do + describe "when reporting cycles in the graph" do before do @graph = Puppet::SimpleGraph.new end @@ -278,29 +278,24 @@ describe Puppet::SimpleGraph do end end - it "should sort the graph topologically" do - add_edges :a => :b, :b => :c - @graph.topsort.should == [:a, :b, :c] - end - it "should fail on two-vertex loops" do add_edges :a => :b, :b => :a - proc { @graph.topsort }.should raise_error(Puppet::Error) + proc { @graph.report_cycles_in_graph }.should raise_error(Puppet::Error) end it "should fail on multi-vertex loops" do add_edges :a => :b, :b => :c, :c => :a - proc { @graph.topsort }.should raise_error(Puppet::Error) + proc { @graph.report_cycles_in_graph }.should raise_error(Puppet::Error) end it "should fail when a larger tree contains a small cycle" do add_edges :a => :b, :b => :a, :c => :a, :d => :c - proc { @graph.topsort }.should raise_error(Puppet::Error) + proc { @graph.report_cycles_in_graph }.should raise_error(Puppet::Error) end it "should succeed on trees with no cycles" do add_edges :a => :b, :b => :e, :c => :a, :d => :c - proc { @graph.topsort }.should_not raise_error + proc { @graph.report_cycles_in_graph }.should_not raise_error end it "should produce the correct relationship text" do @@ -308,7 +303,7 @@ describe Puppet::SimpleGraph do # cycle detection starts from a or b randomly # so we need to check for either ordering in the error message want = %r{Found 1 dependency cycle:\n\((a => b => a|b => a => b)\)\nTry} - expect { @graph.topsort }.to raise_error(Puppet::Error, want) + expect { @graph.report_cycles_in_graph }.to raise_error(Puppet::Error, want) end it "cycle discovery should be the minimum cycle for a simple graph" do @@ -405,17 +400,6 @@ describe Puppet::SimpleGraph do paths = @graph.paths_in_cycle(cycles.first, 21) paths.length.should be == 20 end - - # Our graph's add_edge method is smart enough not to add - # duplicate edges, so we use the objects, which it doesn't - # check. - it "should be able to sort graphs with duplicate edges" do - one = Puppet::Relationship.new(:a, :b) - @graph.add_edge(one) - two = Puppet::Relationship.new(:a, :b) - @graph.add_edge(two) - proc { @graph.topsort }.should_not raise_error - end end describe "when writing dot files" do @@ -521,7 +505,7 @@ describe Puppet::SimpleGraph do require 'puppet/util/graph' - class Container + class Container < Puppet::Type::Component include Puppet::Util::Graph include Enumerable attr_accessor :name @@ -543,6 +527,7 @@ describe Puppet::SimpleGraph do end end + require "puppet/resource/catalog" describe "when splicing the graph" do def container_graph @one = Container.new("one", %w{a b}) @@ -555,13 +540,21 @@ describe Puppet::SimpleGraph do @whit = Puppet::Type.type(:whit) @stage = Puppet::Type.type(:stage).new(:name => "foo") - @contgraph = @top.to_graph + @contgraph = @top.to_graph(Puppet::Resource::Catalog.new) # We have to add the container to the main graph, else it won't # be spliced in the dependency graph. @contgraph.add_vertex(@empty) end + def containers + @contgraph.vertices.select { |x| !x.is_a? String } + end + + def contents_of(x) + @contgraph.direct_dependents_of(x) + end + def dependency_graph @depgraph = Puppet::SimpleGraph.new @contgraph.vertices.each do |v| @@ -570,13 +563,34 @@ describe Puppet::SimpleGraph do # We have to specify a relationship to our empty container, else it # never makes it into the dep graph in the first place. - {@one => @two, "f" => "c", "h" => @middle, "c" => @empty}.each do |source, target| + @explicit_dependencies = {@one => @two, "f" => "c", "h" => @middle, "c" => @empty} + @explicit_dependencies.each do |source, target| @depgraph.add_edge(source, target, :callback => :refresh) end end def splice - @depgraph.splice!(@contgraph, Container) + @contgraph.splice!(@depgraph) + end + + def whit_called(name) + x = @depgraph.vertices.find { |v| v.is_a?(@whit) && v.name =~ /#{name}/ } + x.should_not be_nil + def x.to_s + "Whit[#{name}]" + end + def x.inspect + to_s + end + x + end + + def admissible_sentinal_of(x) + @depgraph.vertex?(x) ? x : whit_called("admissible_#{x.name}") + end + + def completed_sentinal_of(x) + @depgraph.vertex?(x) ? x : whit_called("completed_#{x.name}") end before do @@ -585,63 +599,87 @@ describe Puppet::SimpleGraph do splice end - # This is the real heart of splicing -- replacing all containers in - # our relationship and exploding their relationships so that each - # relationship to a container gets copied to all of its children. + # This is the real heart of splicing -- replacing all containers X in our + # relationship graph with a pair of whits { admissible_X and completed_X } + # such that that + # + # 0) completed_X depends on admissible_X + # 1) contents of X each depend on admissible_X + # 2) completed_X depends on each on the contents of X + # 3) everything which depended on X depends on completed_X + # 4) admissible_X depends on everything X depended on + # 5) the containers and their edges must be removed + # + # Note that this requires attention to the possible case of containers + # which contain or depend on other containers. + # + # Point by point: + + # 0) completed_X depends on admissible_X + # + it "every container's completed sentinal should depend on its admissible sentinal" do + containers.each { |container| + @depgraph.path_between(admissible_sentinal_of(container),completed_sentinal_of(container)).should be + } + end + + # 1) contents of X each depend on admissible_X + # + it "all contained objects should depend on their container's admissible sentinal" do + containers.each { |container| + contents_of(container).each { |leaf| + @depgraph.should be_edge(admissible_sentinal_of(container),admissible_sentinal_of(leaf)) + } + } + end + + # 2) completed_X depends on each on the contents of X + # + it "completed sentinals should depend on their container's contents" do + containers.each { |container| + contents_of(container).each { |leaf| + @depgraph.should be_edge(completed_sentinal_of(leaf),completed_sentinal_of(container)) + } + } + end + + # + # 3) everything which depended on X depends on completed_X + + # + # 4) admissible_X depends on everything X depended on + + # 5) the containers and their edges must be removed + # it "should remove all Container objects from the dependency graph" do @depgraph.vertices.find_all { |v| v.is_a?(Container) }.should be_empty end - # This is a bit hideous, but required to make stages work with relationships - they're - # the top of the graph. it "should remove all Stage resources from the dependency graph" do @depgraph.vertices.find_all { |v| v.is_a?(Puppet::Type.type(:stage)) }.should be_empty end - it "should add container relationships to contained objects" do - @contgraph.leaves(@middle).each do |leaf| - @depgraph.should be_edge("h", leaf) - end - end - - it "should explode container-to-container relationships, making edges between all respective contained objects" do - @one.each do |oobj| - @two.each do |tobj| - @depgraph.should be_edge(oobj, tobj) - end - end - end - - it "should contain a whit-resource to mark the place held by the empty container" do - @depgraph.vertices.find_all { |v| v.is_a?(@whit) }.length.should == 1 - end - - it "should replace edges to empty containers with edges to their residual whit" do - emptys_whit = @depgraph.vertices.find_all { |v| v.is_a?(@whit) }.first - @depgraph.should be_edge("c", emptys_whit) - end - it "should no longer contain anything but the non-container objects" do @depgraph.vertices.find_all { |v| ! v.is_a?(String) and ! v.is_a?(@whit)}.should be_empty end - it "should copy labels" do - @depgraph.edges.each do |edge| - edge.label.should == {:callback => :refresh} - end + it "should retain labels on non-containment edges" do + @explicit_dependencies.each { |f,t| + @depgraph.edges_between(completed_sentinal_of(f),admissible_sentinal_of(t))[0].label.should == {:callback => :refresh} + } end it "should not add labels to edges that have none" do @depgraph.add_edge(@two, @three) splice - @depgraph.edges_between("c", "i")[0].label.should == {} + @depgraph.path_between("c", "i").any? {|segment| segment.all? {|e| e.label == {} }}.should be end it "should copy labels over edges that have none" do @depgraph.add_edge("c", @three, {:callback => :refresh}) splice # And make sure the label got copied. - @depgraph.edges_between("c", "i")[0].label.should == {:callback => :refresh} + @depgraph.path_between("c", "i").flatten.select {|e| e.label == {:callback => :refresh} }.should_not be_empty end it "should not replace a label with a nil label" do @@ -649,7 +687,7 @@ describe Puppet::SimpleGraph do @depgraph.add_edge(@middle, @three) @depgraph.add_edge("c", @three, {:callback => :refresh}) splice - @depgraph.edges_between("c", "i")[0].label.should == {:callback => :refresh} + @depgraph.path_between("c","i").flatten.select {|e| e.label == {:callback => :refresh} }.should_not be_empty end it "should copy labels to all created edges" do @@ -658,8 +696,9 @@ describe Puppet::SimpleGraph do splice @three.each do |child| edge = Puppet::Relationship.new("c", child) - @depgraph.should be_edge(edge.source, edge.target) - @depgraph.edges_between(edge.source, edge.target)[0].label.should == {:callback => :refresh} + (path = @depgraph.path_between(edge.source, edge.target)).should be + path.should_not be_empty + path.flatten.select {|e| e.label == {:callback => :refresh} }.should_not be_empty end end end diff --git a/spec/unit/transaction_spec.rb b/spec/unit/transaction_spec.rb index 3677bfd87..ab76130e3 100755 --- a/spec/unit/transaction_spec.rb +++ b/spec/unit/transaction_spec.rb @@ -114,7 +114,6 @@ describe Puppet::Transaction do describe "when evaluating a resource" do before do @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) - @transaction.stubs(:eval_children_and_apply_resource) @transaction.stubs(:skip?).returns false @resource = Puppet::Type.type(:file).new :path => @basepath @@ -126,12 +125,6 @@ describe Puppet::Transaction do @transaction.eval_resource(@resource) end - it "should eval and apply children" do - @transaction.expects(:eval_children_and_apply_resource).with(@resource, nil) - - @transaction.eval_resource(@resource) - end - it "should process events" do @transaction.event_manager.expects(:process_events).with(@resource) @@ -197,7 +190,7 @@ describe Puppet::Transaction do second.expects(:generate).returns [third] third.expects(:generate) - @transaction.generate_additional_resources(first, :generate) + @transaction.generate_additional_resources(first) end it "should finish all resources" do @@ -213,7 +206,7 @@ describe Puppet::Transaction do resource.expects(:finish) - @transaction.generate_additional_resources(generator, :generate) + @transaction.generate_additional_resources(generator) end it "should skip generated resources that conflict with existing resources" do @@ -230,7 +223,7 @@ describe Puppet::Transaction do resource.expects(:finish).never resource.expects(:info) # log that it's skipped - @transaction.generate_additional_resources(generator, :generate).should be_empty + @transaction.generate_additional_resources(generator) end it "should copy all tags to the newly generated resources" do @@ -244,8 +237,10 @@ describe Puppet::Transaction do @catalog.stubs(:add_resource) child.expects(:tag).with("one", "two") + child.expects(:finish) + generator.expects(:depthfirst?) - @transaction.generate_additional_resources(generator, :generate) + @transaction.generate_additional_resources(generator) end end @@ -387,20 +382,19 @@ describe Puppet::Transaction do describe 'within an evaluate call' do before do - @resource = stub 'resource', :ref => 'some_ref' + @resource = Puppet::Type.type(:notify).new :title => "foobar" @catalog.add_resource @resource @transaction.stubs(:prepare) - @transaction.sorted_resources = [@resource] end it 'should stop processing if :stop_processing? is true' do - @transaction.expects(:stop_processing?).returns(true) + @transaction.stubs(:stop_processing?).returns(true) @transaction.expects(:eval_resource).never @transaction.evaluate end it 'should continue processing if :stop_processing? is false' do - @transaction.expects(:stop_processing?).returns(false) + @transaction.stubs(:stop_processing?).returns(false) @transaction.expects(:eval_resource).returns(nil) @transaction.evaluate end diff --git a/spec/unit/type/whit_spec.rb b/spec/unit/type/whit_spec.rb index 46eb0ab6e..0a3324afa 100644 --- a/spec/unit/type/whit_spec.rb +++ b/spec/unit/type/whit_spec.rb @@ -5,7 +5,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') whit = Puppet::Type.type(:whit).new(:name => "Foo::Bar") describe whit do - it "should stringify as though it were the class it represents" do - whit.to_s.should == "Class[Foo::Bar]" + it "should stringify in a way that users will regognise" do + whit.to_s.should == "(Foo::Bar)" end end |