diff options
-rw-r--r-- | lib/puppet/util/log.rb | 27 | ||||
-rwxr-xr-x | spec/unit/util/log.rb | 152 | ||||
-rwxr-xr-x | test/util/log.rb | 59 |
3 files changed, 163 insertions, 75 deletions
diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb index 8824a8b50..f5119bbff 100644 --- a/lib/puppet/util/log.rb +++ b/lib/puppet/util/log.rb @@ -1,10 +1,12 @@ require 'syslog' +require 'puppet/util/tagging' # Pass feedback to the user. Log levels are modeled after syslog's, and it is # expected that that will be the most common log destination. Supports # multiple destinations, one of which is a remote server. class Puppet::Util::Log include Puppet::Util + include Puppet::Util::Tagging @levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit] @loglevel = 2 @@ -470,12 +472,12 @@ class Puppet::Util::Log @levels.include?(level) end - attr_accessor :level, :message, :time, :tags, :remote + attr_accessor :level, :message, :time, :remote attr_reader :source def initialize(args) unless args.include?(:level) && args.include?(:message) - raise Puppet::DevError, "Puppet::Util::Log called incorrectly" + raise ArgumentError, "Puppet::Util::Log called incorrectly" end if args[:level].class == String @@ -483,8 +485,7 @@ class Puppet::Util::Log elsif args[:level].class == Symbol @level = args[:level] else - raise Puppet::DevError, - "Level is not a string or symbol: #{args[:level].class}" + raise ArgumentError, "Level is not a string or symbol: #{args[:level].class}" end # Just return unless we're actually at a level we should send @@ -495,11 +496,11 @@ class Puppet::Util::Log # this should include the host name, and probly lots of other # stuff, at some point unless self.class.validlevel?(level) - raise Puppet::DevError, "Invalid message level #{level}" + raise ArgumentError, "Invalid message level #{level}" end - if args.include?(:tags) - @tags = args[:tags] + if tags = args[:tags] + tags.each { |t| self.tag(t) } end if args.include?(:source) @@ -511,7 +512,7 @@ class Puppet::Util::Log Log.newmessage(self) end - # Was the source of this log an object? + # Was the source of this log a Puppet resource or parameter? def objectsource? if defined? @objectsource and @objectsource @objectsource @@ -533,17 +534,11 @@ class Puppet::Util::Log @objectsource = false @source = source.to_s end - unless defined? @tags and @tags - if source.respond_to?(:tags) - @tags = source.tags - end + if source.respond_to?(:tags) + source.tags.each { |t| tag(t) } end end - def tagged?(tag) - @tags.detect { |t| t.to_s == tag.to_s } - end - def to_report "%s %s (%s): %s" % [self.time, self.source, self.level, self.to_s] end diff --git a/spec/unit/util/log.rb b/spec/unit/util/log.rb new file mode 100755 index 000000000..7f37e9f4c --- /dev/null +++ b/spec/unit/util/log.rb @@ -0,0 +1,152 @@ +#!/usr/bin/env ruby + +Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } + +require 'puppet/util/log' + +describe Puppet::Util::Log do + describe "instances" do + before do + Puppet::Util::Log.stubs(:newmessage) + end + + [:level, :message, :time, :remote].each do |attr| + it "should have a %s attribute" % attr do + log = Puppet::Util::Log.new :level => :notice, :message => "A test message" + log.should respond_to(attr) + log.should respond_to(attr.to_s + "=") + end + end + + it "should fail if created without a level" do + lambda { Puppet::Util::Log.new(:message => "A test message") }.should raise_error(ArgumentError) + end + + it "should fail if created without a message" do + lambda { Puppet::Util::Log.new(:level => :notice) }.should raise_error(ArgumentError) + end + + it "should make available the level passed in at initialization" do + Puppet::Util::Log.new(:level => :notice, :message => "A test message").level.should == :notice + end + + it "should make available the message passed in at initialization" do + Puppet::Util::Log.new(:level => :notice, :message => "A test message").message.should == "A test message" + end + + # LAK:NOTE I don't know why this behavior is here, I'm just testing what's in the code, + # at least at first. + it "should always convert messages to strings" do + Puppet::Util::Log.new(:level => :notice, :message => :foo).message.should == "foo" + end + + it "should convert the level to a symbol if it's passed in as a string" do + Puppet::Util::Log.new(:level => "notice", :message => :foo).level.should == :notice + end + + it "should fail if the level is not a symbol or string" do + lambda { Puppet::Util::Log.new(:level => 50, :message => :foo) }.should raise_error(ArgumentError) + end + + it "should fail if the provided level is not valid" do + Puppet::Util::Log.expects(:validlevel?).with(:notice).returns false + lambda { Puppet::Util::Log.new(:level => :notice, :message => :foo) }.should raise_error(ArgumentError) + end + + it "should set its time to the initialization time" do + time = mock 'time' + Time.expects(:now).returns time + Puppet::Util::Log.new(:level => "notice", :message => :foo).time.should equal(time) + end + + it "should make available any passed-in tags" do + Puppet::Util::Log.new(:level => "notice", :message => :foo, :tags => %w{foo bar}).tags.should == %w{foo bar} + end + + it "should use an passed-in source" do + Puppet::Util::Log.any_instance.expects(:source=).with "foo" + Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => "foo") + end + + it "should default to 'Puppet' as its source" do + Puppet::Util::Log.new(:level => "notice", :message => :foo).source.should == "Puppet" + end + + it "should register itself with Log" do + Puppet::Util::Log.expects(:newmessage) + Puppet::Util::Log.new(:level => "notice", :message => :foo) + end + + it "should have a method for determining if a tag is present" do + Puppet::Util::Log.new(:level => "notice", :message => :foo).should respond_to(:tagged?) + end + + it "should match a tag if any of the tags are equivalent to the passed tag as a string" do + Puppet::Util::Log.new(:level => "notice", :message => :foo, :tags => %w{one two}).should be_tagged(:one) + end + + it "should tag itself with its log level" do + pending "not yet" + Puppet::Util::Log.new(:level => "notice", :message => :foo, :tags => %w{one two}).should be_tagged(:one) + end + + it "should return its message when converted to a string" do + Puppet::Util::Log.new(:level => "notice", :message => :foo).to_s.should == "foo" + end + + it "should include its time, source, level, and message when prepared for reporting" do + log = Puppet::Util::Log.new(:level => "notice", :message => :foo) + report = log.to_report + report.should be_include("notice") + report.should be_include("foo") + report.should be_include(log.source) + report.should be_include(log.time.to_s) + end + + it "should have a method for indicating whether it was created by a resource" do + Puppet::Util::Log.new(:level => "notice", :message => :foo).should respond_to(:objectsource?) + end + + describe "when setting a source" do + it "should mark itself as from a Puppet resource if its source is a Puppet resource" do + file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs" + Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => file).should be_objectsource + end + + it "should use the resource's path when its source is a resource" do + # Use a different path, so we don't use 'clear', which is deprecated in master + file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/path" + file.expects(:path).returns "mypath" + Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => file).source.should == "mypath" + end + + it "should mark itself as from a Puppet resource if its source is a Puppet parameter" do + file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/parameters", :mode => "500" + mode = file.property(:mode) + Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => mode).should be_objectsource + end + + it "should use the resource's path when its source is a Puppet parameter" do + # Use a different path, so we don't use 'clear', which is deprecated in master + file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/path/in/parameters", :mode => "500" + mode = file.property(:mode) + mode.expects(:path).returns "mypath" + Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => mode).source.should == "mypath" + end + + it "should acquire its source's tags if its source has any" do + file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/tags" + file.tag("foo") + file.tag("bar") + log = Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => file) + + log.should be_tagged("foo") + log.should be_tagged("bar") + end + + it "should not set objectsource if the source is not a Parameter or Resource" do + Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => "mysource").should_not be_objectsource + end + end + end +end diff --git a/test/util/log.rb b/test/util/log.rb index 523652f37..8c7703cb9 100755 --- a/test/util/log.rb +++ b/test/util/log.rb @@ -114,44 +114,6 @@ class TestLog < Test::Unit::TestCase assert(FileTest.file?(file)) end - def test_logtags - path = tempfile - File.open(path, "w") { |f| f.puts "yayness" } - - file = Puppet.type(:file).create( - :path => path, - :check => [:owner, :group, :mode, :checksum], - :ensure => :file - ) - file.tags = %w{this is a test} - - property = file.property(:ensure) - assert(property, "Did not get property") - log = nil - assert_nothing_raised { - log = Puppet::Util::Log.new( - :level => :info, - :source => property, - :message => "A test message" - ) - } - - # Now yaml and de-yaml it, and test again - yamllog = YAML.load(YAML.dump(log)) - - {:log => log, :yaml => yamllog}.each do |type, msg| - assert(msg.tags, "Got no tags") - - msg.tags.each do |tag| - assert(msg.tagged?(tag), "Was not tagged with %s" % tag) - end - - assert_equal(msg.tags, property.tags, "Tags were not equal") - assert_equal(msg.source, property.path, "Source was not set correctly") - end - - end - # Verify that we can pass strings that match printf args def test_percentlogs Puppet::Util::Log.newdestination :syslog @@ -182,27 +144,6 @@ class TestLog < Test::Unit::TestCase assert_instance_of(String, msg.source) end - # Verify that loglevel behaves as one expects - def test_loglevel - path = tempfile() - file = Puppet.type(:file).create( - :path => path, - :ensure => "file" - ) - - assert_nothing_raised { - assert_equal(:notice, file[:loglevel]) - } - - assert_nothing_raised { - file[:loglevel] = "warning" - } - - assert_nothing_raised { - assert_equal(:warning, file[:loglevel]) - } - end - def test_destination_matching dest = nil assert_nothing_raised { |