diff options
Diffstat (limited to 'spec/unit')
-rwxr-xr-x | spec/unit/indirector/code/configuration.rb | 4 | ||||
-rwxr-xr-x | spec/unit/indirector/indirection.rb | 162 | ||||
-rwxr-xr-x | spec/unit/indirector/indirector.rb | 10 | ||||
-rwxr-xr-x | spec/unit/indirector/terminus.rb | 65 | ||||
-rwxr-xr-x | spec/unit/node/configuration.rb | 186 |
5 files changed, 380 insertions, 47 deletions
diff --git a/spec/unit/indirector/code/configuration.rb b/spec/unit/indirector/code/configuration.rb index bc54f4e1c..0038a038e 100755 --- a/spec/unit/indirector/code/configuration.rb +++ b/spec/unit/indirector/code/configuration.rb @@ -143,7 +143,9 @@ describe Puppet::Indirector::Code::Configuration, " when creating configurations it "should return the results of compiling as the configuration" do config = mock 'config' - @compiler.interpreter.expects(:compile).with(@node).returns(:configuration) + result = mock 'result', :to_transportable => :configuration + + @compiler.interpreter.expects(:compile).with(@node).returns(result) @compiler.find(@name).should == :configuration end diff --git a/spec/unit/indirector/indirection.rb b/spec/unit/indirector/indirection.rb index 4311c88bf..7a1c4531c 100755 --- a/spec/unit/indirector/indirection.rb +++ b/spec/unit/indirector/indirection.rb @@ -7,28 +7,62 @@ require 'puppet/indirector' describe Puppet::Indirector::Indirection do before do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) - @terminus = mock 'terminus' + @terminus = stub 'terminus', :has_most_recent? => false @indirection.stubs(:terminus).returns(@terminus) + @instance = stub 'instance', :version => nil, :version= => nil, :name => "whatever" + @name = :mything + end + + it "should not attempt to set a timestamp if the terminus cannot find the instance" do + @terminus.expects(:find).with(@name).returns(nil) + proc { @indirection.find(@name) }.should_not raise_error end it "should handle lookups of a model instance by letting the appropriate terminus perform the lookup" do - @terminus.expects(:find).with(:mything).returns(:whev) - @indirection.find(:mything).should == :whev + @terminus.expects(:find).with(@name).returns(@instance) + @indirection.find(@name).should == @instance end it "should handle removing model instances from a terminus letting the appropriate terminus remove the instance" do - @terminus.expects(:destroy).with(:mything).returns(:whev) - @indirection.destroy(:mything).should == :whev + @terminus.expects(:destroy).with(@name).returns(@instance) + @indirection.destroy(@name).should == @instance end it "should handle searching for model instances by letting the appropriate terminus find the matching instances" do - @terminus.expects(:search).with(:mything).returns(:whev) - @indirection.search(:mything).should == :whev + @terminus.expects(:search).with(@name).returns(@instance) + @indirection.search(@name).should == @instance end it "should handle storing a model instance by letting the appropriate terminus store the instance" do - @terminus.expects(:save).with(:mything).returns(:whev) - @indirection.save(:mything).should == :whev + @terminus.expects(:save).with(@instance).returns(@instance) + @indirection.save(@instance).should == @instance + end + + it "should add versions to found instances that do not already have them" do + @terminus.expects(:find).with(@name).returns(@instance) + time = mock 'time' + time.expects(:utc).returns(:mystamp) + Time.expects(:now).returns(time) + @instance.expects(:version=).with(:mystamp) + @indirection.find(@name) + end + + it "should add versions to saved instances that do not already have them" do + time = mock 'time' + time.expects(:utc).returns(:mystamp) + Time.expects(:now).returns(time) + @instance.expects(:version=).with(:mystamp) + @terminus.stubs(:save) + @indirection.save(@instance) + end + + # We've already tested this, basically, but... + it "should use the current time in UTC for versions" do + @instance.expects(:version=).with do |time| + time.utc? + end + @terminus.stubs(:save) + @indirection.save(@instance) end after do @@ -189,33 +223,14 @@ describe Puppet::Indirector::Indirection, " when deciding whether to cache" do proc { @indirection.cache_class = :foo }.should raise_error(ArgumentError) end - it "should not use a cache if there no cache setting" do - @indirection.expects(:cache).never - @terminus.stubs(:save) - @indirection.save(:whev) - end - - it "should use a cache if a cache was configured" do - cache = mock 'cache' - cache.expects(:save).with(:whev) - - cache_class = mock 'cache class' - cache_class.expects(:new).returns(cache) - Puppet::Indirector::Terminus.stubs(:terminus_class).with(:mycache, :test).returns(cache_class) - - @indirection.cache_class = :mycache - @terminus.stubs(:save) - @indirection.save(:whev) - end - after do @indirection.delete Puppet::Indirector::Indirection.clear_cache end end -describe Puppet::Indirector::Indirection, " when using a cache" do - before do +module IndirectionCaching + def setup Puppet.settings.stubs(:value).with("test_terminus").returns("test_terminus") @terminus_class = mock 'terminus_class' @terminus = mock 'terminus' @@ -228,13 +243,14 @@ describe Puppet::Indirector::Indirection, " when using a cache" do @indirection.terminus_class = :test_terminus end - it "should copy all writing indirection calls to the cache terminus" do - @cache_class.expects(:new).returns(@cache) - @indirection.cache_class = :cache_terminus - @cache.expects(:save).with(:whev) - @terminus.stubs(:save) - @indirection.save(:whev) + def teardown + @indirection.delete + Puppet::Indirector::Indirection.clear_cache end +end + +describe Puppet::Indirector::Indirection, " when managing the cache terminus" do + include IndirectionCaching it "should not create a cache terminus at initialization" do # This is weird, because all of the code is in the setup. If we got @@ -257,9 +273,77 @@ describe Puppet::Indirector::Indirection, " when using a cache" do @indirection.clear_cache @indirection.cache.should equal(cache2) end +end - after do - @indirection.delete - Puppet::Indirector::Indirection.clear_cache +describe Puppet::Indirector::Indirection, " when saving and using a cache" do + include IndirectionCaching + + before do + @indirection.cache_class = :cache_terminus + @cache_class.expects(:new).returns(@cache) + @name = "testing" + @instance = stub 'instance', :version => 5, :name => @name + end + + it "should not update the cache or terminus if the new object is not different" do + @cache.expects(:has_most_recent?).with(@name, 5).returns(true) + @indirection.save(@instance) + end + + it "should update the original and the cache if the cached object is different" do + @cache.expects(:has_most_recent?).with(@name, 5).returns(false) + @terminus.expects(:save).with(@instance) + @cache.expects(:save).with(@instance) + @indirection.save(@instance) + end +end + +describe Puppet::Indirector::Indirection, " when finding and using a cache" do + include IndirectionCaching + + before do + @indirection.cache_class = :cache_terminus + @cache_class.expects(:new).returns(@cache) + end + + it "should return the cached object if the cache is up to date" do + cached = mock 'cached object' + + name = "myobject" + + @terminus.expects(:version).with(name).returns(1) + @cache.expects(:has_most_recent?).with(name, 1).returns(true) + + @cache.expects(:find).with(name).returns(cached) + + @indirection.find(name).should equal(cached) + end + + it "should return the original object if the cache is not up to date" do + real = stub 'real object', :version => 1 + + name = "myobject" + + @cache.stubs(:save) + @cache.expects(:has_most_recent?).with(name, 1).returns(false) + @terminus.expects(:version).with(name).returns(1) + + @terminus.expects(:find).with(name).returns(real) + + @indirection.find(name).should equal(real) + end + + it "should cache any newly returned objects" do + real = stub 'real object', :version => 1 + + name = "myobject" + + @terminus.expects(:version).with(name).returns(1) + @cache.expects(:has_most_recent?).with(name, 1).returns(false) + + @terminus.expects(:find).with(name).returns(real) + @cache.expects(:save).with(real) + + @indirection.find(name).should equal(real) end end diff --git a/spec/unit/indirector/indirector.rb b/spec/unit/indirector/indirector.rb index 390907ca2..78c8c614a 100755 --- a/spec/unit/indirector/indirector.rb +++ b/spec/unit/indirector/indirector.rb @@ -64,6 +64,16 @@ describe Puppet::Indirector, " when redirecting a model" do @indirection = @thingie.send(:indirects, :test) end + it "should give the model the ability set a version" do + thing = @thingie.new + thing.should respond_to(:version=) + end + + it "should give the model the ability retrieve a version" do + thing = @thingie.new + thing.should respond_to(:version) + end + it "should give the model the ability to lookup a model instance by letting the indirection perform the lookup" do @indirection.expects(:find) @thingie.find diff --git a/spec/unit/indirector/terminus.rb b/spec/unit/indirector/terminus.rb index 44180cf4b..3361bfeeb 100755 --- a/spec/unit/indirector/terminus.rb +++ b/spec/unit/indirector/terminus.rb @@ -1,3 +1,5 @@ +#!/usr/bin/env ruby + require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/defaults' require 'puppet/indirector' @@ -200,8 +202,8 @@ describe Puppet::Indirector::Terminus, " when creating terminus classes" do end end -describe Puppet::Indirector::Terminus, " when a terminus instance" do - before do +module TerminusInstanceTesting + def setup Puppet::Indirector::Terminus.stubs(:register_terminus_class) @indirection = stub 'indirection', :name => :myyaml, :register_terminus_type => nil Puppet::Indirector::Indirection.stubs(:instance).with(:my_stuff).returns(@indirection) @@ -218,6 +220,10 @@ describe Puppet::Indirector::Terminus, " when a terminus instance" do @terminus_class.name = :test @terminus = @terminus_class.new end +end + +describe Puppet::Indirector::Terminus, " when a terminus instance" do + include TerminusInstanceTesting it "should return the class's name as its name" do @terminus.name.should == :test @@ -236,3 +242,58 @@ describe Puppet::Indirector::Terminus, " when a terminus instance" do @terminus.model.should == :yay end end + +describe Puppet::Indirector::Terminus, " when managing indirected instances" do + include TerminusInstanceTesting + + it "should support comparing an instance's version with the terminus's version using just the instance's key" do + @terminus.should respond_to(:has_most_recent?) + end + + it "should fail if the :version method has not been overridden and no :find method is available" do + proc { @terminus.version('yay') }.should raise_error(Puppet::DevError) + end + + it "should use a found instance's version by default" do + name = 'instance' + instance = stub name, :version => 2 + @terminus.expects(:find).with(name).returns(instance) + @terminus.version(name).should == 2 + end + + it "should return nil as the version if no instance can be found" do + name = 'instance' + @terminus.expects(:find).with(name).returns(nil) + @terminus.version(name).should be_nil + end + + it "should consider an instance fresh if its version is more recent than the version provided" do + name = "yay" + @terminus.expects(:version).with(name).returns(5) + @terminus.has_most_recent?(name, 4).should be_true + end + + it "should consider an instance fresh if its version is equal to the version provided" do + name = "yay" + @terminus.expects(:version).with(name).returns(5) + @terminus.has_most_recent?(name, 5).should be_true + end + + it "should consider an instance not fresh if the provided version is more recent than its version" do + name = "yay" + @terminus.expects(:version).with(name).returns(4) + @terminus.has_most_recent?(name, 5).should be_false + end + + # Times annoyingly can't be compared directly to numbers, and our + # default version is 0. + it "should convert versions to floats when checking for freshness" do + existing = mock 'existing version' + new = mock 'new version' + existing.expects(:to_f).returns(1.0) + new.expects(:to_f).returns(1.0) + name = "yay" + @terminus.expects(:version).with(name).returns(existing) + @terminus.has_most_recent?(name, new) + end +end diff --git a/spec/unit/node/configuration.rb b/spec/unit/node/configuration.rb index 153d0b182..ee3834ef3 100755 --- a/spec/unit/node/configuration.rb +++ b/spec/unit/node/configuration.rb @@ -52,10 +52,6 @@ describe Puppet::Node::Configuration, " when extracting" do end end -describe Puppet::Node::Configuration, " when extracting RAL resources" do - it "should support an extraction method for converting a parser configuration into a RAL configuration" -end - describe Puppet::Node::Configuration, " when extracting transobjects" do def mkscope @@ -155,6 +151,153 @@ describe Puppet::Node::Configuration, " when extracting transobjects" do end end +describe Puppet::Node::Configuration, " when converting to a transobject configuration" do + class TestResource + attr_accessor :name, :virtual, :builtin + def initialize(name, options = {}) + @name = name + options.each { |p,v| send(p.to_s + "=", v) } + end + + def ref + if builtin? + "File[%s]" % name + else + "Class[%s]" % name + end + end + + def virtual? + virtual + end + + def builtin? + builtin + end + + def to_transobject + Puppet::TransObject.new(name, builtin? ? "file" : "class") + end + end + + before do + @original = Puppet::Node::Configuration.new("mynode") + @original.tag(*%w{one two three}) + @original.add_class *%w{four five six} + + @top = TestResource.new 'top' + @topobject = TestResource.new 'topobject', :builtin => true + @virtual = TestResource.new 'virtual', :virtual => true + @virtualobject = TestResource.new 'virtualobject', :builtin => true, :virtual => true + @middle = TestResource.new 'middle' + @middleobject = TestResource.new 'middleobject', :builtin => true + @bottom = TestResource.new 'bottom' + @bottomobject = TestResource.new 'bottomobject', :builtin => true + + @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] + + @original.add_edge!(@top, @topobject) + @original.add_edge!(@top, @virtual) + @original.add_edge!(@virtual, @virtualobject) + @original.add_edge!(@top, @middle) + @original.add_edge!(@middle, @middleobject) + @original.add_edge!(@middle, @bottom) + @original.add_edge!(@bottom, @bottomobject) + + @config = @original.to_transportable + end + + it "should add all resources as TransObjects" do + @resources.each { |resource| @config.resource(resource.ref).should be_instance_of(Puppet::TransObject) } + end + + it "should not extract defined virtual resources" do + @config.vertices.find { |v| v.name == "virtual" }.should be_nil + end + + it "should not extract builtin virtual resources" do + @config.vertices.find { |v| v.name == "virtualobject" }.should be_nil + end + + it "should copy the tag list to the new configuration" do + @config.tags.sort.should == @original.tags.sort + end + + it "should copy the class list to the new configuration" do + @config.classes.should == @original.classes + end + + it "should duplicate the original edges" do + @original.edges.each do |edge| + next if edge.source.virtual? or edge.target.virtual? + source = @config.resource(edge.source.ref) + target = @config.resource(edge.target.ref) + + source.should_not be_nil + target.should_not be_nil + @config.edge?(source, target).should be_true + end + end + + it "should set itself as the configuration for each converted resource" do + @config.vertices.each { |v| v.configuration.object_id.should equal(@config.object_id) } + end +end + +describe Puppet::Node::Configuration, " when converting to a RAL configuration" do + before do + @original = Puppet::Node::Configuration.new("mynode") + @original.tag(*%w{one two three}) + @original.add_class *%w{four five six} + + @top = Puppet::TransObject.new 'Class[top]', "component" + @topobject = Puppet::TransObject.new '/topobject', "file" + @middle = Puppet::TransObject.new 'Class[middle]', "component" + @middleobject = Puppet::TransObject.new '/middleobject', "file" + @bottom = Puppet::TransObject.new 'Class[bottom]', "component" + @bottomobject = Puppet::TransObject.new '/bottomobject', "file" + + @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] + + @original.add_resource(*@resources) + + @original.add_edge!(@top, @topobject) + @original.add_edge!(@top, @middle) + @original.add_edge!(@middle, @middleobject) + @original.add_edge!(@middle, @bottom) + @original.add_edge!(@bottom, @bottomobject) + + @config = @original.to_ral + end + + it "should add all resources as RAL instances" do + @resources.each { |resource| @config.resource(resource.ref).should be_instance_of(Puppet::Type) } + end + + it "should copy the tag list to the new configuration" do + @config.tags.sort.should == @original.tags.sort + end + + it "should copy the class list to the new configuration" do + @config.classes.should == @original.classes + end + + it "should duplicate the original edges" do + @original.edges.each do |edge| + @config.edge?(@config.resource(edge.source.ref), @config.resource(edge.target.ref)).should be_true + end + end + + it "should set itself as the configuration for each converted resource" do + @config.vertices.each { |v| v.configuration.object_id.should equal(@config.object_id) } + end + + after do + # Remove all resource instances. + @config.clear(true) + end +end + describe Puppet::Node::Configuration, " when functioning as a resource container" do before do @config = Puppet::Node::Configuration.new("host") @@ -500,7 +643,6 @@ describe Puppet::Node::Configuration, " when indirecting" do @indirection = mock 'indirection' Puppet::Indirector::Indirection.clear_cache - @configuration = Puppet::Node::Facts.new("me") end it "should redirect to the indirection for retrieval" do @@ -518,3 +660,37 @@ describe Puppet::Node::Configuration, " when indirecting" do Puppet::Indirector::Indirection.clear_cache end end + +describe Puppet::Node::Configuration, " when converting to yaml" do + before do + @configuration = Puppet::Node::Configuration.new("me") + @configuration.add_edge!("one", "two") + end + + it "should be able to be dumped to yaml" do + YAML.dump(@configuration).should be_instance_of(String) + end +end + +describe Puppet::Node::Configuration, " when converting from yaml" do + before do + @configuration = Puppet::Node::Configuration.new("me") + @configuration.add_edge!("one", "two") + + text = YAML.dump(@configuration) + @newconfig = YAML.load(text) + end + + it "should get converted back to a configuration" do + @newconfig.should be_instance_of(Puppet::Node::Configuration) + end + + it "should have all vertices" do + @newconfig.vertex?("one").should be_true + @newconfig.vertex?("two").should be_true + end + + it "should have all edges" do + @newconfig.edge?("one", "two").should be_true + end +end |