diff options
-rwxr-xr-x | lib/puppet/type/schedule.rb | 32 | ||||
-rwxr-xr-x | spec/unit/ral/types/schedule.rb | 374 | ||||
-rwxr-xr-x | test/ral/types/schedule.rb | 356 |
3 files changed, 392 insertions, 370 deletions
diff --git a/lib/puppet/type/schedule.rb b/lib/puppet/type/schedule.rb index 46cff10f5..3fdc008b6 100755 --- a/lib/puppet/type/schedule.rb +++ b/lib/puppet/type/schedule.rb @@ -241,7 +241,7 @@ module Puppet :daily => :day, :monthly => :month, :weekly => proc do |prev, now| - prev.strftime("%U") == now.strftime("%U") + prev.strftime("%U") != now.strftime("%U") end } @@ -256,8 +256,7 @@ module Puppet return method.call(previous, now) else # We negate it, because if they're equal we don't run - val = now.send(method) != previous.send(method) - return val + return now.send(method) != previous.send(method) end when :distance scale = @@scale[value] @@ -266,6 +265,9 @@ module Puppet # than the unit of time, we match. We divide the scale # by the repeat, so that we'll repeat that often within # the scale. + diff = (now.to_i - previous.to_i) + comparison = (scale / @resource[:repeat]) + return (now.to_i - previous.to_i) >= (scale / @resource[:repeat]) end end @@ -312,25 +314,27 @@ module Puppet end def self.mkdefaultschedules - # Create our default schedule - unless self["puppet"] - Puppet.debug "Creating default schedules" - self.create( - :name => "puppet", - :period => :hourly, - :repeat => "2" - ) - end + return [] if self["puppet"] + + result = [] + Puppet.debug "Creating default schedules" + result << self.create( + :name => "puppet", + :period => :hourly, + :repeat => "2" + ) # And then one for every period @parameters.find { |p| p.name == :period }.values.each { |value| unless self[value.to_s] - self.create( + result << self.create( :name => value.to_s, :period => value ) end } + + result end def match?(previous = nil, now = nil) @@ -346,7 +350,7 @@ module Puppet self.class.allattrs.each { |param| if @parameters.include?(param) and @parameters[param].respond_to?(:match?) - #self.notice "Trying to match %s" % param + self.notice "Trying to match %s" % param return false unless @parameters[param].match?(previous, now) end } diff --git a/spec/unit/ral/types/schedule.rb b/spec/unit/ral/types/schedule.rb new file mode 100755 index 000000000..73b3a0bd1 --- /dev/null +++ b/spec/unit/ral/types/schedule.rb @@ -0,0 +1,374 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/schedule' + +module ScheduleTesting + def setup + Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false) + + @schedule = Puppet::Type::Schedule.create(:name => "testing") + end + + def format(time) + time.strftime("%H:%M:%S") + end + + def diff(unit, incr, method, count) + diff = Time.now.to_i.send(method, incr * count) + Time.at(diff) + end + + def month(method, count) + diff(:hour, 3600 * 24 * 30, method, count) + end + + def week(method, count) + diff(:hour, 3600 * 24 * 7, method, count) + end + + def day(method, count) + diff(:hour, 3600 * 24, method, count) + end + + def hour(method, count) + diff(:hour, 3600, method, count) + end + + def min(method, count) + diff(:min, 60, method, count) + end + + def sec(method, count) + diff(:sec, 1, method, count) + end + + def teardown + Puppet::Type::Schedule.clear + end +end + +describe Puppet::Type::Schedule do + include ScheduleTesting + + it "should default to :distance for period-matching" do + @schedule[:periodmatch].should == :distance + end + + it "should default to a :repeat of 1" do + @schedule[:repeat].should == 1 + end + + it "should never match when the period is :never" do + @schedule[:period] = :never + @schedule.match?.should be_false + end +end + +describe Puppet::Type::Schedule, "when producing default schedules" do + include ScheduleTesting + + %w{hourly daily weekly monthly never}.each do |period| + period = period.to_sym + it "should produce a #{period} schedule with the period set appropriately" do + schedules = Puppet::Type::Schedule.mkdefaultschedules + schedules.find { |s| s[:name] == period.to_s and s[:period] == period }.should be_instance_of(Puppet::Type::Schedule) + end + end + + it "should produce a schedule named puppet with a period of hourly and a repeat of 2" do + schedules = Puppet::Type::Schedule.mkdefaultschedules + schedules.find { |s| + s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2 + }.should be_instance_of(Puppet::Type::Schedule) + end +end + +describe Puppet::Type::Schedule, "when matching ranges" do + include ScheduleTesting + + it "should match when the start time is before the current time and the end time is after the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now + 10)] + @schedule.match?.should be_true + end + + it "should not match when the start time is after the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now + 5), format(Time.now + 10)] + @schedule.match?.should be_false + end + + it "should not match when the end time is previous to the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now - 5)] + @schedule.match?.should be_false + end +end + +describe Puppet::Type::Schedule, "when matching hourly by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :hourly + @schedule[:periodmatch] = :distance + end + + it "should match an hour ago" do + @schedule.match?(hour("-", 1)).should be_true + end + + it "should not match now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match 59 minutes ago" do + @schedule.match?(min("-", 59)).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching daily by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :daily + @schedule[:periodmatch] = :distance + end + + it "should match when the previous time was one day ago" do + @schedule.match?(day("-", 1)).should be_true + end + + it "should not match when the previous time is now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match when the previous time was 23 hours ago" do + @schedule.match?(hour("-", 23)).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching weekly by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :weekly + @schedule[:periodmatch] = :distance + end + + it "should match seven days ago" do + @schedule.match?(day("-", 7)).should be_true + end + + it "should not match now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match six days ago" do + @schedule.match?(day("-", 6)).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching monthly by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :monthly + @schedule[:periodmatch] = :distance + end + + it "should match 32 days ago" do + @schedule.match?(day("-", 32)).should be_true + end + + it "should not match now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match 27 days ago" do + @schedule.match?(day("-", 27)).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching hourly by number" do + include ScheduleTesting + + before do + @schedule[:period] = :hourly + @schedule[:periodmatch] = :number + end + + it "should match if the times are one minute apart and the current minute is 0" do + current = Time.now + + # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes. + previous = (current - 3600 - (current.min * 60) + (59 * 60)) + + # Now set the "current" time to the zero minute of the current hour. + now = (current - (current.min * 60)) + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_true + end + + it "should not match if the times are 58 minutes apart and the current minute is 59" do + current = Time.now + + # reset the minute to zero + previous = current - (current.min * 60) + + # Now set the "current" time to the 59th minute of the current hour. + now = (current - (current.min * 60) + (59 * 60)) + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching daily by number" do + include ScheduleTesting + + before do + @schedule[:period] = :daily + @schedule[:periodmatch] = :number + end + + it "should match if the times are one minute apart and the current minute and hour are 0" do + zero = Time.now + + # Reset the current time to X:00:00 + current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec + + # Now set the previous time to one minute before that + previous = current - 60 + + Time.stubs(:now).returns(current) + @schedule.match?(previous).should be_true + end + + it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do + zero = Time.now + + # Reset the previous time to 00:00:00 + previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec + + # Set the current time to 23:59 + now = previous + (23 * 3600) + (59 * 60) + + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching weekly by number" do + include ScheduleTesting + + before do + @schedule[:period] = :weekly + @schedule[:periodmatch] = :number + end + + it "should match if the previous time is prior to the most recent Sunday" do + now = Time.now + + # Subtract the number days we've progressed into the week, plus one because we're zero-indexed. + previous = now - (3600 * 24 * (now.wday + 1)) + + @schedule.match?(previous).should be_true + end + + it "should not match if the previous time is after the most recent Saturday" do + now = Time.now + + # Subtract the number days we've progressed into the week + previous = now - (3600 * 24 * now.wday) + + @schedule.match?(previous).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching monthly by number" do + include ScheduleTesting + + before do + @schedule[:period] = :monthly + @schedule[:periodmatch] = :number + end + + it "should match when the previous time is prior to the first day of this month" do + now = Time.now + + # Subtract the number days we've progressed into the month + previous = now - (3600 * 24 * now.day) + + @schedule.match?(previous).should be_true + end + + it "should not match when the previous time is after the last day of last month" do + now = Time.now + + # Subtract the number days we've progressed into the month, minus one + previous = now - (3600 * 24 * (now.day - 1)) + + @schedule.match?(previous).should be_false + end +end + +describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do + include ScheduleTesting + + before do + @schedule[:period] = :daily + @schedule[:repeat] = 2 + end + + it "should fail if the periodmatch is 'number'" do + @schedule[:periodmatch] = :number + proc { @schedule[:repeat] = 2 }.should raise_error(Puppet::Error) + end + + it "should match if the previous run was further away than the distance divided by the repeat" do + previous = Time.now - (3600 * 13) + @schedule.match?(previous).should be_true + end + + it "should not match if the previous run was closer than the distance divided by the repeat" do + previous = Time.now - (3600 * 11) + @schedule.match?(previous).should be_false + end +end + +module OldTesting + def mksched + @stype.create(:name => "testsched") + end + + def test_period_with_repeat + previous = @now + + s = mksched + s[:period] = :hourly + + assert_nothing_raised("Was not able to set periodmatch") { + s[:periodmatch] = :number + } + assert_raise(Puppet::Error) { + s[:repeat] = 2 + } + assert_nothing_raised("Was not able to reset periodmatch") { + s[:periodmatch] = :distance + } + + assert(! s.match?(min("-", 40)), "matched minus 40 minutes") + + assert_nothing_raised("Was not able to set period") { + s[:repeat] = 2 + } + + assert(! s.match?(min("-", 20)), "matched minus 20 minutes with half-hourly") + assert(s.match?(min("-", 40)), "Did not match minus 40 with half-hourly") + + assert_nothing_raised("Was not able to set period") { + s[:repeat] = 3 + } + + assert(! s.match?(min("-", 15)), "matched minus 15 minutes with half-hourly") + assert(s.match?(min("-", 25)), "Did not match minus 25 with half-hourly") + end +end diff --git a/test/ral/types/schedule.rb b/test/ral/types/schedule.rb deleted file mode 100755 index 2870b8db6..000000000 --- a/test/ral/types/schedule.rb +++ /dev/null @@ -1,356 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppet/type/schedule' - -class TestSchedule < Test::Unit::TestCase - include PuppetTest - - def setup - super - @stype = Puppet::Type::Schedule - - # This will probably get overridden by different tests - @now = Time.now - Puppet[:ignoreschedules] = false - end - - def mksched - s = nil - assert_nothing_raised { - s = @stype.create( - :name => "testsched" - ) - } - - s - end - - def diff(unit, incr, method, count) - diff = @now.to_i.send(method, incr * count) - t = Time.at(diff) - - #Puppet.notice "%s: %s %s %s = %s" % - # [unit, @now.send(unit), method, count, t] - #t.strftime("%H:%M:%S") - t - end - - def month(method, count) - diff(:hour, 3600 * 24 * 30, method, count) - end - - def week(method, count) - diff(:hour, 3600 * 24 * 7, method, count) - end - - def day(method, count) - diff(:hour, 3600 * 24, method, count) - end - - def hour(method, count) - diff(:hour, 3600, method, count) - end - - def min(method, count) - diff(:min, 60, method, count) - end - - def sec(method, count) - diff(:sec, 1, method, count) - end - - def settimes - unless defined? @@times - @@times = [Time.now] - - # Make one with an edge year on each side - ary = Time.now.to_a - [1999, 2000, 2001].each { |y| - ary[5] = y; @@times << Time.local(*ary) - } - - # And with edge hours - ary = Time.now.to_a - #[23, 0].each { |h| ary[2] = h; @@times << Time.local(*ary) } - # 23 hour - ary[2] = 23 - @@times << Time.local(*ary) - # 0 hour, next day - ary[2] = 0 - @@times << addday(Time.local(*ary)) - - # And with edge minutes - #[59, 0].each { |m| ary[1] = m; @@times << Time.local(*ary) } - ary = Time.now.to_a - ary[1] = 59; @@times << Time.local(*ary) - ary[1] = 0 - #if ary[2] == 23 - @@times << Time.local(*ary) - #else - # @@times << addday(Time.local(*ary)) - #end - end - - Puppet.err @@times.inspect - - @@times.each { |time| - @now = time - yield time - } - - @now = Time.now - end - - def test_range - s = mksched - - ary = @now.to_a - ary[2] = 12 - @now = Time.local(*ary) - data = { - true => [ - # An hour previous, an hour after - [hour("-", 1), hour("+", 1)], - - # an hour previous but a couple minutes later, and an hour plus - [min("-", 57), hour("+", 1)] - ], - false => [ - # five minutes from now, an hour from now - [min("+", 5), hour("+", 1)], - - # an hour ago, 20 minutes ago - [hour("-", 1), min("-", 20)] - ] - } - - data.each { |result, values| - values = values.collect { |value| - "%s - %s" % [value[0].strftime("%H:%M:%S"), - value[1].strftime("%H:%M:%S")] - } - values.each { |value| - assert_nothing_raised("Could not parse %s" % value) { - s[:range] = value - } - - assert_equal(result, s.match?(nil, @now), - "%s matched %s incorrectly" % [value.inspect, @now]) - } - - assert_nothing_raised("Could not parse %s" % [values]) { - s[:range] = values - } - - assert_equal(result, s.match?(nil, @now), - "%s matched %s incorrectly" % [values.inspect, @now]) - } - end - - def test_period_by_distance - previous = @now - - s = mksched - - assert_nothing_raised { - s[:period] = :daily - } - - assert(s.match?(day("-", 1)), "did not match minus a day") - assert(s.match?(day("-", 2)), "did not match two days") - assert(! s.match?(@now), "matched today") - assert(! s.match?(hour("-", 11)), "matched minus 11 hours") - - # Now test hourly - assert_nothing_raised { - s[:period] = :hourly - } - - assert(s.match?(hour("-", 1)), "did not match minus an hour") - assert(s.match?(hour("-", 2)), "did not match two hours") - assert(! s.match?(@now), "matched now") - assert(! s.match?(min("-", 59)), "matched minus 11 hours") - - # and weekly - assert_nothing_raised { - s[:period] = :weekly - } - - assert(s.match?(week("-", 1)), "did not match minus a week") - assert(s.match?(day("-", 7)), "did not match minus 7 days") - assert(s.match?(day("-", 8)), "did not match minus 8 days") - assert(s.match?(week("-", 2)), "did not match two weeks") - assert(! s.match?(@now), "matched now") - assert(! s.match?(day("-", 6)), "matched minus 6 days") - - # and monthly - assert_nothing_raised { - s[:period] = :monthly - } - - assert(s.match?(month("-", 1)), "did not match minus a month") - assert(s.match?(week("-", 5)), "did not match minus 5 weeks") - assert(s.match?(week("-", 7)), "did not match minus 7 weeks") - assert(s.match?(day("-", 50)), "did not match minus 50 days") - assert(s.match?(month("-", 2)), "did not match two months") - assert(! s.match?(@now), "matched now") - assert(! s.match?(week("-", 3)), "matched minus 3 weeks") - assert(! s.match?(day("-", 20)), "matched minus 20 days") - end - - # A shortened test... - def test_period_by_number - s = mksched - assert_nothing_raised { - s[:periodmatch] = :number - } - - assert_nothing_raised { - s[:period] = :daily - } - - assert(s.match?(day("+", 1)), "didn't match plus a day") - assert(s.match?(week("+", 1)), "didn't match plus a week") - assert(! s.match?(@now), "matched today") - assert(! s.match?(hour("-", 1)), "matched minus an hour") - assert(! s.match?(hour("-", 2)), "matched plus two hours") - - # Now test hourly - assert_nothing_raised { - s[:period] = :hourly - } - - assert(s.match?(hour("+", 1)), "did not match plus an hour") - assert(s.match?(hour("+", 2)), "did not match plus two hours") - assert(! s.match?(@now), "matched now") - assert(! s.match?(sec("+", 20)), "matched plus 20 seconds") - end - - def test_periodmatch_default - s = mksched - - match = s[:periodmatch] - assert(match, "Could not find periodmatch") - - assert_equal(:distance, match, "Periodmatch was %s" % match) - end - - def test_scheduled_objects - s = mksched - s[:period] = :hourly - - f = nil - path = tempfile() - assert_nothing_raised { - f = Puppet.type(:file).create( - :name => path, - :schedule => s.name, - :ensure => "file" - ) - } - - assert(f.scheduled?, "File is not scheduled to run") - - assert_apply(f) - - assert(! f.scheduled?, "File is scheduled to run already") - File.unlink(path) - - assert_apply(f) - - assert(! FileTest.exists?(path), "File was created when not scheduled") - end - - def test_latebinding_schedules - f = nil - path = tempfile() - assert_nothing_raised { - f = Puppet.type(:file).create( - :name => path, - :schedule => "testsched", - :ensure => "file" - ) - } - - s = mksched - s[:period] = :hourly - - assert_nothing_raised { - f.schedule - } - - assert(f.scheduled?, "File is not scheduled to run") - end - - # Verify that each of our default schedules exist - def test_defaultschedules - assert_nothing_raised do - Puppet.type(:schedule).mkdefaultschedules - end - s = {} - %w{puppet hourly daily weekly monthly}.each { |period| - obj = Puppet.type(:schedule)[period] - assert(obj, "Could not find %s schedule" % - period) - s[period] = obj - } - assert_nothing_raised("Could not rerun mkdefaultschedules") do - Puppet.type(:schedule).mkdefaultschedules - end - s.each do |period, obj| - newobj = Puppet.type(:schedule)[period] - assert(newobj, "somehow lost schedule for %s" % period) - assert_equal(obj.object_id, newobj.object_id, - "created a new schedule instead of reusing existing one") - end - end - - def test_period_with_repeat - previous = @now - - s = mksched - s[:period] = :hourly - - assert_nothing_raised("Was not able to set periodmatch") { - s[:periodmatch] = :number - } - assert_raise(Puppet::Error) { - s[:repeat] = 2 - } - assert_nothing_raised("Was not able to reset periodmatch") { - s[:periodmatch] = :distance - } - - assert(! s.match?(min("-", 40)), "matched minus 40 minutes") - - assert_nothing_raised("Was not able to set period") { - s[:repeat] = 2 - } - - assert(! s.match?(min("-", 20)), "matched minus 20 minutes with half-hourly") - assert(s.match?(min("-", 40)), "Did not match minus 40 with half-hourly") - - assert_nothing_raised("Was not able to set period") { - s[:repeat] = 3 - } - - assert(! s.match?(min("-", 15)), "matched minus 15 minutes with half-hourly") - assert(s.match?(min("-", 25)), "Did not match minus 25 with half-hourly") - end - - # #526 - def test_never_period - schedule = nil - assert_nothing_raised do - schedule = Puppet::Type.type(:schedule).create( - :name => "test", :period => :never - ) - end - - assert(! schedule.match?, "schedule matched with period == never") - end -end - |