summaryrefslogtreecommitdiffstats
path: root/spec/unit
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit')
-rwxr-xr-xspec/unit/indirector/code/configuration.rb4
-rwxr-xr-xspec/unit/indirector/indirection.rb162
-rwxr-xr-xspec/unit/indirector/indirector.rb10
-rwxr-xr-xspec/unit/indirector/terminus.rb65
-rwxr-xr-xspec/unit/node/configuration.rb186
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