cronin 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.autospec ADDED
@@ -0,0 +1,9 @@
1
+ Autotest.add_hook(:initialize) {|at|
2
+ at.add_exception %r{^\.git} # ignore Version Control System
3
+ at.add_exception %r{^./tmp} # ignore temp files, lest autotest will run again, and again...
4
+ # at.clear_mappings # take out the default (test/test*rb)
5
+ at.add_mapping(%r{^lib/.*\.rb$}) {|f, _|
6
+ Dir['spec/**/*.rb']
7
+ }
8
+ nil
9
+ }
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.5.2)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rcov (0.9.9)
12
+ rspec (2.3.0)
13
+ rspec-core (~> 2.3.0)
14
+ rspec-expectations (~> 2.3.0)
15
+ rspec-mocks (~> 2.3.0)
16
+ rspec-core (2.3.1)
17
+ rspec-expectations (2.3.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.3.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ bundler (~> 1.0.0)
26
+ jeweler (~> 1.5.2)
27
+ rcov
28
+ rspec (~> 2.3.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 innov8on.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,33 @@
1
+ = cronin
2
+
3
+ Simple gem to find out when given cron task should be executed. It support only basic cron entries:
4
+ * '*'
5
+ * X, where X is a digit from proper range
6
+ * '*/X' where X is a digit
7
+
8
+ == Usage:
9
+
10
+ task = Cronin::CronTask.new('* * * * *')
11
+ start = Time.mktime(2011,1,1,12,12)
12
+ finish = Time.mktime(2011,1,1,12,12)
13
+ task.executions(start,finish)
14
+
15
+ => [Sat Jan 01 12:12:00 0100 2011, Sat Jan 01 12:13:00 0100 2011, Sat Jan 01 12:14:00 0100 2011, Sat Jan 01 12:15:00 0100 2011]
16
+
17
+
18
+
19
+ == Contributing to cronin
20
+
21
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
22
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
23
+ * Fork the project
24
+ * Start a feature/bugfix branch
25
+ * Commit and push until you are happy with your contribution
26
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
27
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
28
+
29
+ == Copyright
30
+
31
+ Copyright (c) 2011 innov8on.com. See LICENSE.txt for
32
+ further details.
33
+
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'rake'
12
+
13
+ require 'jeweler'
14
+ Jeweler::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
16
+ gem.name = "cronin"
17
+ gem.homepage = "http://github.com/innov8n/cronin"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Cronin can determine cron tasks executions}
20
+ gem.description = %Q{Cronin can determine cron tasks executions}
21
+ gem.email = "slawosz@innov8on.com"
22
+ gem.authors = ["Sławosz Sławiński"]
23
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
24
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
25
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
26
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rspec/core'
31
+ require 'rspec/core/rake_task'
32
+ RSpec::Core::RakeTask.new(:spec) do |spec|
33
+ spec.pattern = FileList['spec/**/*_spec.rb']
34
+ end
35
+
36
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
37
+ spec.pattern = 'spec/**/*_spec.rb'
38
+ spec.rcov = true
39
+ end
40
+
41
+ task :default => :spec
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "cronin #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
data/cronin.gemspec ADDED
@@ -0,0 +1,94 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cronin}
8
+ s.version = "0.0.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["S\305\202awosz S\305\202awi\305\204ski"]
12
+ s.date = %q{2011-03-08}
13
+ s.description = %q{Cronin can determine cron tasks executions}
14
+ s.email = %q{slawosz@innov8on.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".autospec",
21
+ ".document",
22
+ ".rspec",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "cronin.gemspec",
30
+ "lib/cronin.rb",
31
+ "lib/cronin/abstract_timing.rb",
32
+ "lib/cronin/cron_task.rb",
33
+ "lib/cronin/hour.rb",
34
+ "lib/cronin/hours.rb",
35
+ "lib/cronin/minutes.rb",
36
+ "lib/cronin/month_days.rb",
37
+ "lib/cronin/months.rb",
38
+ "lib/cronin/parser.rb",
39
+ "lib/cronin/restricted.rb",
40
+ "lib/cronin/week_days.rb",
41
+ "spec/abstract_timing_spec.rb",
42
+ "spec/cron_task_spec.rb",
43
+ "spec/hour_spec.rb",
44
+ "spec/hours_spec.rb",
45
+ "spec/minutes_spec.rb",
46
+ "spec/month_days_spec.rb",
47
+ "spec/months_spec.rb",
48
+ "spec/parser_spec.rb",
49
+ "spec/restrictable_spec.rb",
50
+ "spec/spec_helper.rb",
51
+ "spec/week_days_spec.rb"
52
+ ]
53
+ s.homepage = %q{http://github.com/innov8n/cronin}
54
+ s.licenses = ["MIT"]
55
+ s.require_paths = ["lib"]
56
+ s.rubygems_version = %q{1.3.7}
57
+ s.summary = %q{Cronin can determine cron tasks executions}
58
+ s.test_files = [
59
+ "spec/abstract_timing_spec.rb",
60
+ "spec/cron_task_spec.rb",
61
+ "spec/hour_spec.rb",
62
+ "spec/hours_spec.rb",
63
+ "spec/minutes_spec.rb",
64
+ "spec/month_days_spec.rb",
65
+ "spec/months_spec.rb",
66
+ "spec/parser_spec.rb",
67
+ "spec/restrictable_spec.rb",
68
+ "spec/spec_helper.rb",
69
+ "spec/week_days_spec.rb"
70
+ ]
71
+
72
+ if s.respond_to? :specification_version then
73
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
74
+ s.specification_version = 3
75
+
76
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
77
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
78
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
79
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
80
+ s.add_development_dependency(%q<rcov>, [">= 0"])
81
+ else
82
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
83
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
84
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
85
+ s.add_dependency(%q<rcov>, [">= 0"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
89
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
90
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
91
+ s.add_dependency(%q<rcov>, [">= 0"])
92
+ end
93
+ end
94
+
data/lib/cronin.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'cronin/abstract_timing.rb'
2
+ require 'cronin/restricted.rb'
3
+ require 'cronin/months.rb'
4
+ require 'cronin/month_days.rb'
5
+ require 'cronin/hours.rb'
6
+ require 'cronin/week_days.rb'
7
+ require 'cronin/minutes.rb'
8
+ require 'cronin/parser.rb'
9
+ require 'cronin/cron_task.rb'
10
+ require 'cronin/hour.rb'
@@ -0,0 +1,36 @@
1
+ module Cronin
2
+ # Class contain all logic for getting timing for minute, hour, week day, month day and month
3
+ class AbstractTiming
4
+
5
+ def initialize(cron_value)
6
+ @cron_value = cron_value
7
+ end
8
+
9
+ # Returns array of fixnum, when it should be execute
10
+ def timing
11
+ case @cron_value
12
+ when '*'
13
+ return (min_value..max_value).to_a
14
+ when /^\d{1,2}/
15
+ number = @cron_value.to_i
16
+ if number >= min_value && number <= max_value
17
+ return [number]
18
+ else
19
+ raise ArgumentError, 'wrong value for this entry'
20
+ end
21
+ when /\*\/(\d+)/
22
+ number = $1.to_i
23
+ return (min_value..max_value).to_a.delete_if {|elem| elem % number != 0}
24
+ end
25
+ end
26
+
27
+ def min_value
28
+ self.class.min_value
29
+ end
30
+
31
+ def max_value
32
+ self.class.max_value
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,110 @@
1
+ require 'date'
2
+
3
+ module Cronin
4
+ class CronTask
5
+
6
+ def initialize(entry)
7
+ @parsed_entry = Parser.new(entry).parse
8
+ end
9
+
10
+ def executions(start_time, end_time)
11
+ raise 'end date can not be earlier then start date' if end_time < start_time
12
+ @start_time = start_time
13
+ @end_time = end_time
14
+ get_executions
15
+ end
16
+
17
+ def get_executions
18
+ start_day = Date.parse(time_to_string(@start_time))
19
+ end_day = Date.parse(time_to_string(@end_time))
20
+ executions = []
21
+ execution_days.each do |day|
22
+ if start_day == day
23
+ execution_hours = daily_execution_hours(:start_hour => @start_time.hour, :start_minute => @start_time.min)
24
+ end
25
+ if end_day == day
26
+ execution_hours = daily_execution_hours(:end_hour => @end_time.hour, :end_minute => @end_time.min)
27
+ end
28
+ if end_day == start_day
29
+ options = {
30
+ :start_hour => @start_time.hour,
31
+ :start_minute => @start_time.min,
32
+ :end_hour => @end_time.hour,
33
+ :end_minute => @end_time.min
34
+ }
35
+ execution_hours = daily_execution_hours(options)
36
+ end
37
+ if end_day != day && start_day != day
38
+ execution_hours = daily_execution_hours
39
+ end
40
+ execution_hours.each do |hour|
41
+ executions << Time.mktime(day.year,day.month,day.day,hour.hour,hour.minute)
42
+ end
43
+ end
44
+ executions
45
+ end
46
+
47
+ def execution_days
48
+ get_days.select do |day|
49
+ wday_mday = if both_wday_and_mday_are_restricted?
50
+ (@parsed_entry[:week_days].timing.include?(day.wday) ||
51
+ @parsed_entry[:month_days].timing.include?(day.mday))
52
+ else
53
+ (@parsed_entry[:week_days].timing.include?(day.wday) &&
54
+ @parsed_entry[:month_days].timing.include?(day.mday))
55
+ end
56
+ # maybe it is to long?
57
+ # @parsed_entry[:week_days].timing
58
+ wday_mday && @parsed_entry[:months].timing.include?(day.month)
59
+ end
60
+ end
61
+
62
+ def both_wday_and_mday_are_restricted?
63
+ @parsed_entry[:week_days].restricted? &&
64
+ @parsed_entry[:month_days].restricted?
65
+ end
66
+ private :both_wday_and_mday_are_restricted?
67
+
68
+
69
+ def get_days
70
+ start_day = Date.parse(time_to_string(@start_time))
71
+ end_day = Date.parse(time_to_string(@end_time))
72
+ if start_day == end_day
73
+ return [start_day]
74
+ else
75
+ return (start_day..end_day).to_a
76
+ end
77
+ end
78
+
79
+ def daily_execution_hours(options = {})
80
+ options = {:start_hour => 0, :start_minute => 0, :end_hour => 23, :end_minute => 59}.merge(options)
81
+ execution_hours = []
82
+ hours = @parsed_entry[:hours].timing
83
+ hours = hours.select {|hour| options[:start_hour] <= hour }
84
+ hours = hours.select {|hour| options[:end_hour] >= hour }
85
+ minutes = @parsed_entry[:minutes].timing
86
+ hours.each do |hour|
87
+ _minutes = if hour == options[:start_hour]
88
+ minutes.select { |minute| options[:start_minute] <= minute }
89
+ else
90
+ minutes
91
+ end
92
+ _minutes = if hour == options[:end_hour]
93
+ _minutes.select { |minute| options[:end_minute] >= minute }
94
+ else
95
+ _minutes
96
+ end
97
+ _minutes.each do |minute|
98
+ execution_hours << Cronin::Hour.new(hour,minute)
99
+ end
100
+ end
101
+ execution_hours
102
+ end
103
+
104
+ def time_to_string(time)
105
+ "#{time.year}-#{time.month}-#{time.day}"
106
+ end
107
+ private :time_to_string
108
+
109
+ end
110
+ end
@@ -0,0 +1,14 @@
1
+ module Cronin
2
+ class Hour
3
+
4
+ attr_reader :hour, :minute
5
+ def initialize(hour,minute)
6
+ @hour = hour
7
+ @minute = minute
8
+ end
9
+
10
+ def ==(other)
11
+ other.hour == self.hour && other.minute == self.minute
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Cronin
2
+ class Hours < AbstractTiming
3
+
4
+ class << self
5
+ def min_value
6
+ 0
7
+ end
8
+
9
+ def max_value
10
+ 23
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Cronin
2
+ class Minutes < AbstractTiming
3
+
4
+ class << self
5
+ def min_value
6
+ 0
7
+ end
8
+
9
+ def max_value
10
+ 59
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module Cronin
2
+ class MonthDays < AbstractTiming
3
+ include Restricted
4
+
5
+ class << self
6
+ def min_value
7
+ 1
8
+ end
9
+
10
+ def max_value
11
+ 31
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module Cronin
2
+ class Months < AbstractTiming
3
+
4
+ class << self
5
+ def min_value
6
+ 1
7
+ end
8
+
9
+ def max_value
10
+ 12
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Cronin
2
+ class Parser
3
+ def initialize(entry)
4
+ @entry = entry
5
+ end
6
+
7
+ def parse
8
+ splited = @entry.split[0..4]
9
+ klasses = [Minutes, Hours, MonthDays, Months, WeekDays]
10
+ keys = [:minutes, :hours, :month_days, :months, :week_days]
11
+ result = {}
12
+ splited.each_with_index do |entry,i|
13
+ result[keys[i]] = klasses[i].new(entry)
14
+ end
15
+ result
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Cronin
2
+ module Restricted
3
+
4
+ def restricted?
5
+ case @cron_value
6
+ #TODO: repetition code from abstract timing
7
+ when /^(\d{1,2}|\*\/\d{1,2})$/
8
+ return true
9
+ when "*"
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module Cronin
2
+ class WeekDays < AbstractTiming
3
+ include Restricted
4
+
5
+ class << self
6
+ def min_value
7
+ 0
8
+ end
9
+
10
+ def max_value
11
+ 6
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ class FooTiming < Cronin::AbstractTiming
4
+ class << self
5
+ def min_value
6
+ 0
7
+ end
8
+
9
+ def max_value
10
+ 59
11
+ end
12
+ end
13
+ end
14
+
15
+ class BarTiming < Cronin::AbstractTiming
16
+ class << self
17
+ def min_value
18
+ 0
19
+ end
20
+
21
+ def max_value
22
+ 100
23
+ end
24
+ end
25
+ end
26
+
27
+ describe Cronin::AbstractTiming do
28
+
29
+ it "should get timming correctly" do
30
+ t = FooTiming.new("*")
31
+ t.timing.should == (0..59).to_a # [0,1,2,3,4,...,59]
32
+
33
+ t = FooTiming.new("3")
34
+ t.timing.should == [3]
35
+
36
+ t = FooTiming.new("*/2")
37
+ t.timing.should == (0..59).to_a.delete_if {|elem| elem % 2 != 0} # [0,2,4,6,..,58]
38
+
39
+ t = FooTiming.new("*/3")
40
+ t.timing.should == (0..59).to_a.delete_if {|elem| elem % 3 != 0} # [0,3,6,9,..,57]
41
+
42
+ t = BarTiming.new("*/3")
43
+ t.timing.should == (0..100).to_a.delete_if {|elem| elem % 3 != 0} # [0,3,6,9,..,99]
44
+
45
+ t = BarTiming.new("*/30")
46
+ t.timing.should == (0..100).to_a.delete_if {|elem| elem % 30 != 0} # [0,30,60,90]
47
+ end
48
+
49
+ it "instance should know about its min and max values" do
50
+ t = FooTiming.new('*')
51
+
52
+ t.min_value.should == 0
53
+ t.max_value.should == 59
54
+ end
55
+
56
+ it "should not allow wrong arguments" do
57
+ t = FooTiming.new("66")
58
+ expect { t.timing }.to raise_error(ArgumentError)
59
+ end
60
+
61
+ end
62
+
@@ -0,0 +1,261 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::CronTask do
4
+
5
+ it "should store parse result" do
6
+ cron_task = Cronin::CronTask.new("* * * * *")
7
+ parse_result = cron_task.instance_eval { @parsed_entry }
8
+ parse_result.class.should == Hash
9
+ parse_result.size.should == 5
10
+ end
11
+
12
+ it 'should return execution times' do
13
+ cron_task = Cronin::CronTask.new("* * * * *")
14
+ start_time = Time.mktime(2011,1,22,12,0)
15
+ end_time = Time.mktime(2011,1,22,12,5)
16
+
17
+ expected_executions = [
18
+ Time.mktime(2011,1,22,12,0),
19
+ Time.mktime(2011,1,22,12,1),
20
+ Time.mktime(2011,1,22,12,2),
21
+ Time.mktime(2011,1,22,12,3),
22
+ Time.mktime(2011,1,22,12,4),
23
+ Time.mktime(2011,1,22,12,5)
24
+ ]
25
+ executions = cron_task.executions(start_time, end_time)
26
+
27
+ executions.should == expected_executions
28
+ executions.count.should == 6
29
+
30
+
31
+ cron_task = Cronin::CronTask.new("0 0 * * * ")
32
+ start_time = Time.mktime(2011,1,22,12,0)
33
+ end_time = Time.mktime(2011,1,24,12,5)
34
+
35
+ executions = cron_task.executions(start_time, end_time)
36
+
37
+ expected_executions = [Time.mktime(2011,1,23,0,0),Time.mktime(2011,1,24,0,0)]
38
+ executions.should == expected_executions
39
+
40
+
41
+ cron_task = Cronin::CronTask.new("0 0 1 * * ")
42
+ start_time = Time.mktime(2010,12,22,12,0)
43
+ end_time = Time.mktime(2011,1,24,12,5)
44
+
45
+ executions = cron_task.executions(start_time, end_time)
46
+
47
+ expected_executions = [Time.mktime(2011,1,1,0,0)]
48
+ executions.should == expected_executions
49
+
50
+ cron_task = Cronin::CronTask.new("0 0 1 1 * ")
51
+ start_time = Time.mktime(2010,12,22,12,0)
52
+ end_time = Time.mktime(2012,1,24,12,5)
53
+
54
+ executions = cron_task.executions(start_time, end_time)
55
+
56
+ expected_executions = [Time.mktime(2011,1,1,0,0),Time.mktime(2012,1,1,0,0)]
57
+ executions.should == expected_executions
58
+ end
59
+
60
+ it "start_date should be smaller then end day" do
61
+ cron_task = Cronin::CronTask.new("* * * * *")
62
+ start_time = Time.mktime(2011,1,22,12,0)
63
+ end_time = Time.mktime(2011,1,21,12,1)
64
+
65
+ expect { cron_task.executions(start_time, end_time) }.to raise_error(RuntimeError)
66
+ end
67
+
68
+ it "should know days of executions" do
69
+ cron_task = Cronin::CronTask.new("* * 24 * 6")
70
+ start_time = Time.mktime(2011,1,22,12,0)
71
+ end_time = Time.mktime(2011,1,24,12,1)
72
+
73
+ cron_task.executions(start_time,end_time)
74
+
75
+ cron_task.execution_days.should == [Date.new(2011,1,22), Date.new(2011,1,24)]
76
+
77
+ cron_task = Cronin::CronTask.new("* * 24 2 6")
78
+ start_time = Time.mktime(2011,1,22,12,0)
79
+ end_time = Time.mktime(2011,3,24,12,1)
80
+
81
+ cron_task.executions(start_time,end_time)
82
+
83
+ expected = [
84
+ Date.new(2011,2,5),
85
+ Date.new(2011,2,12),
86
+ Date.new(2011,2,19),
87
+ Date.new(2011,2,24),
88
+ Date.new(2011,2,26)
89
+ ]
90
+
91
+ cron_task.execution_days.should == expected
92
+ end
93
+
94
+ it "should properly consider restricted and not restricted wday and mday entries" do
95
+ cron_task = Cronin::CronTask.new("* * 24 * *")
96
+ start_time = Time.mktime(2011,1,22,12,0)
97
+ end_time = Time.mktime(2011,3,24,12,1)
98
+
99
+ cron_task.executions(start_time,end_time)
100
+
101
+ expected = [
102
+ Date.new(2011,1,24),
103
+ Date.new(2011,2,24),
104
+ Date.new(2011,3,24)
105
+ ]
106
+
107
+ cron_task.execution_days.should == expected
108
+ end
109
+
110
+ context "#both_wday_and_mday_are_restricted?" do
111
+ it "should return proper anwser" do
112
+ cron_task = Cronin::CronTask.new("* * 24 * *")
113
+ cron_task.send(:both_wday_and_mday_are_restricted?).should be_false
114
+
115
+ cron_task = Cronin::CronTask.new("* * * * 12")
116
+ cron_task.send(:both_wday_and_mday_are_restricted?).should be_false
117
+
118
+ cron_task = Cronin::CronTask.new("* * 24 * 12")
119
+ cron_task.send(:both_wday_and_mday_are_restricted?).should be_true
120
+
121
+ cron_task = Cronin::CronTask.new("* * * * *")
122
+ cron_task.send(:both_wday_and_mday_are_restricted?).should be_false
123
+ end
124
+
125
+ it "should be private" do
126
+ cron_task = Cronin::CronTask.new("* * 24 * *")
127
+ expect { cron_task.both_wday_and_mday_are_restricted? }.to raise_error(NoMethodError)
128
+ end
129
+ end
130
+
131
+ context "#daily_execution_hours" do
132
+
133
+ it "should return hours of crontab execution" do
134
+ cron_task = Cronin::CronTask.new("13 * * * *")
135
+
136
+ expected = (0..23).to_a.map {|hour| Cronin::Hour.new(hour,13) }
137
+
138
+ cron_task.send(:daily_execution_hours).should == expected
139
+ end
140
+
141
+ it "should be able to pass start hour and minute" do
142
+ cron_task = Cronin::CronTask.new("13 * * * *")
143
+
144
+ expected = [
145
+ Cronin::Hour.new(22,13),
146
+ Cronin::Hour.new(23,13)
147
+ ]
148
+ options = {:start_hour => 21, :start_minute => 14}
149
+ cron_task.send(:daily_execution_hours, options).should == expected
150
+ end
151
+
152
+ it "should be able to pass start hour" do
153
+ cron_task = Cronin::CronTask.new("13 * * * *")
154
+
155
+ expected = [
156
+ Cronin::Hour.new(21,13),
157
+ Cronin::Hour.new(22,13),
158
+ Cronin::Hour.new(23,13)
159
+ ]
160
+ cron_task.send(:daily_execution_hours, :start_hour => 21).should == expected
161
+ end
162
+
163
+ it "should be able to pass end hour" do
164
+ cron_task = Cronin::CronTask.new("13 * * * *")
165
+
166
+ expected = [
167
+ Cronin::Hour.new(0,13),
168
+ Cronin::Hour.new(1,13),
169
+ Cronin::Hour.new(2,13)
170
+ ]
171
+ cron_task.send(:daily_execution_hours, :end_hour => 2).should == expected
172
+ end
173
+
174
+ it "should be able to pass end hour and minute" do
175
+ cron_task = Cronin::CronTask.new("13 * * * *")
176
+
177
+ expected = [
178
+ Cronin::Hour.new(0,13),
179
+ Cronin::Hour.new(1,13)
180
+ ]
181
+ options = {:end_hour => 2, :end_minute => 12}
182
+ cron_task.send(:daily_execution_hours, options).should == expected
183
+ end
184
+
185
+ it "should be able to limit end and start hour" do
186
+ cron_task = Cronin::CronTask.new("13 * * * *")
187
+
188
+ expected = [
189
+ Cronin::Hour.new(12,13),
190
+ Cronin::Hour.new(13,13),
191
+ Cronin::Hour.new(14,13),
192
+ Cronin::Hour.new(15,13),
193
+ Cronin::Hour.new(16,13)
194
+ ]
195
+ options = {:end_hour => 16, :start_hour => 12}
196
+ cron_task.send(:daily_execution_hours, options).should == expected
197
+ end
198
+
199
+ it "should be able to limit end and start hour and minute" do
200
+ cron_task = Cronin::CronTask.new("13 * * * *")
201
+
202
+ expected = [
203
+ Cronin::Hour.new(13,13),
204
+ Cronin::Hour.new(14,13),
205
+ Cronin::Hour.new(15,13),
206
+ ]
207
+ options = {:end_hour => 16, :start_hour => 12, :start_minute => 14, :end_minute => 12}
208
+ cron_task.send(:daily_execution_hours, options).should == expected
209
+ end
210
+
211
+
212
+ end
213
+
214
+ it "should know days of execution periods" do
215
+ cron_task = Cronin::CronTask.new("* * * * *")
216
+ start_time = Time.mktime(2011,1,22,12,0)
217
+ end_time = Time.mktime(2011,1,22,12,1)
218
+
219
+ cron_task.executions(start_time, end_time)
220
+
221
+ cron_task.get_days.should == [Date.new(2011,1,22)]
222
+
223
+
224
+ start_time = Time.mktime(2011,1,22,12,0)
225
+ end_time = Time.mktime(2011,1,24,12,1)
226
+
227
+ cron_task.executions(start_time, end_time)
228
+
229
+ cron_task.get_days.should == [Date.new(2011,1,22), Date.new(2011,1,23), Date.new(2011,1,24)]
230
+
231
+ start_time = Time.mktime(2011,1,22,12,0)
232
+ end_time = Time.mktime(2012,1,24,12,1)
233
+
234
+ cron_task.executions(start_time, end_time)
235
+
236
+ cron_task.get_days.should == (Date.new(2011,1,22)..Date.new(2012,1,24)).to_a
237
+ end
238
+
239
+ context "#time_to_string" do
240
+ it "should return string representation of day" do
241
+ cron_task = Cronin::CronTask.new("* * * * *")
242
+ start_time = Time.mktime(2011,1,22,12,0)
243
+ end_time = Time.mktime(2011,1,22,12,1)
244
+
245
+ cron_task.executions(start_time,end_time)
246
+
247
+ cron_task.send(:time_to_string,start_time).should == "2011-1-22"
248
+ end
249
+
250
+ it "should be private" do
251
+ cron_task = Cronin::CronTask.new("* * * * *")
252
+ start_time = Time.mktime(2011,1,22,12,0)
253
+ end_time = Time.mktime(2011,1,22,12,1)
254
+
255
+ cron_task.executions(start_time,end_time)
256
+
257
+ expect { cron_task.time_to_string(start_time) }.to raise_error(NoMethodError)
258
+ end
259
+
260
+ end
261
+ end
data/spec/hour_spec.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::Hour do
4
+
5
+ it "should create new instance" do
6
+ hour = Cronin::Hour.new(12,12)
7
+ hour.class.should == Cronin::Hour
8
+ end
9
+
10
+ it "should get hour" do
11
+ hour = Cronin::Hour.new(12,12)
12
+ hour.hour.should == 12
13
+ end
14
+
15
+ it "should get minute" do
16
+ hour = Cronin::Hour.new(12,12)
17
+ hour.minute.should == 12
18
+ end
19
+
20
+ it "should be equal with other hour with the same values" do
21
+ hour1 = Cronin::Hour.new(12,12)
22
+ hour2 = Cronin::Hour.new(12,12)
23
+
24
+ hour1.should == hour2
25
+ end
26
+
27
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::Hours do
4
+ it 'should has proprer max value' do
5
+ Cronin::Hours.max_value.should == 23
6
+ end
7
+
8
+ it 'should has proprer min value' do
9
+ Cronin::Hours.min_value.should == 0
10
+ end
11
+
12
+ it 'should inherited from AbstractTiming' do
13
+ Cronin::Hours.superclass.should == Cronin::AbstractTiming
14
+ end
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::Minutes do
4
+ it 'should has proprer max value' do
5
+ Cronin::Minutes.max_value.should == 59
6
+ end
7
+
8
+ it 'should has proprer min value' do
9
+ Cronin::Minutes.min_value.should == 0
10
+ end
11
+
12
+ it 'should inherited from AbstractTiming' do
13
+ Cronin::Minutes.superclass.should == Cronin::AbstractTiming
14
+ end
15
+
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::MonthDays do
4
+ it 'should has proprer max value' do
5
+ Cronin::MonthDays.max_value.should == 31
6
+ end
7
+
8
+ it 'should has proprer min value' do
9
+ Cronin::MonthDays.min_value.should == 1
10
+ end
11
+
12
+ it 'should inherited from AbstractTiming' do
13
+ Cronin::MonthDays.superclass.should == Cronin::AbstractTiming
14
+ end
15
+
16
+ it "should respond to restricted? method" do
17
+ c = Cronin::MonthDays.new('*')
18
+ c.respond_to?(:restricted?).should be_true
19
+ end
20
+
21
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::Months do
4
+ it 'should has proprer max value' do
5
+ Cronin::Months.max_value.should == 12
6
+ end
7
+
8
+ it 'should has proprer min value' do
9
+ Cronin::Months.min_value.should == 1
10
+ end
11
+
12
+ it 'should inherited from AbstractTiming' do
13
+ Cronin::Months.superclass.should == Cronin::AbstractTiming
14
+ end
15
+
16
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::Parser do
4
+ it "should parse cron entry" do
5
+ parsed = Cronin::Parser.new("1 2 3 4 5").parse
6
+
7
+ parsed.count.should == 5
8
+
9
+ parsed[:minutes].class.should == Cronin::Minutes
10
+ parsed[:minutes].instance_eval { @cron_value }.should == '1'
11
+
12
+ parsed[:hours].class.should == Cronin::Hours
13
+ parsed[:hours].instance_eval { @cron_value }.should == '2'
14
+
15
+ parsed[:month_days].class.should == Cronin::MonthDays
16
+ parsed[:month_days].instance_eval { @cron_value }.should == '3'
17
+
18
+ parsed[:months].class.should == Cronin::Months
19
+ parsed[:months].instance_eval { @cron_value }.should == '4'
20
+
21
+ parsed[:week_days].class.should == Cronin::WeekDays
22
+ parsed[:week_days].instance_eval { @cron_value }.should == '5'
23
+
24
+ parsed = Cronin::Parser.new("1 2 3 4 5 run some command").parse
25
+
26
+ parsed.count.should == 5
27
+
28
+ parsed[:minutes].class.should == Cronin::Minutes
29
+ parsed[:minutes].instance_eval { @cron_value }.should == '1'
30
+
31
+ parsed[:hours].class.should == Cronin::Hours
32
+ parsed[:hours].instance_eval { @cron_value }.should == '2'
33
+
34
+ parsed[:month_days].class.should == Cronin::MonthDays
35
+ parsed[:month_days].instance_eval { @cron_value }.should == '3'
36
+
37
+ parsed[:months].class.should == Cronin::Months
38
+ parsed[:months].instance_eval { @cron_value }.should == '4'
39
+
40
+ parsed[:week_days].class.should == Cronin::WeekDays
41
+ parsed[:week_days].instance_eval { @cron_value }.should == '5'
42
+ end
43
+
44
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ class RestrictedTest < Cronin::AbstractTiming
4
+ include Cronin::Restricted
5
+
6
+ class << self
7
+ def min_value
8
+ 0
9
+ end
10
+
11
+ def max_value
12
+ 59
13
+ end
14
+ end
15
+ end
16
+
17
+ describe RestrictedTest do
18
+
19
+ it "should be restricted" do
20
+ r = RestrictedTest.new("1")
21
+ r.restricted?.should be_true
22
+
23
+ r = RestrictedTest.new("11")
24
+ r.restricted?.should be_true
25
+
26
+ r = RestrictedTest.new("*/2")
27
+ r.restricted?.should be_true
28
+ end
29
+
30
+ it "should not be restricted" do
31
+ r = RestrictedTest.new("*")
32
+ r.restricted?.should be_false
33
+ end
34
+ end
35
+
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'cronin'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cronin::WeekDays do
4
+ it 'should has proprer max value' do
5
+ Cronin::WeekDays.max_value.should == 6
6
+ end
7
+
8
+ it 'should has proprer min value' do
9
+ Cronin::WeekDays.min_value.should == 0
10
+ end
11
+
12
+ it 'should inherited from AbstractTiming' do
13
+ Cronin::WeekDays.superclass.should == Cronin::AbstractTiming
14
+ end
15
+
16
+ it 'should respond to restricted? method' do
17
+ c = Cronin::WeekDays.new("*")
18
+ c.respond_to?(:restricted?).should be_true
19
+ end
20
+
21
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cronin
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - "S\xC5\x82awosz S\xC5\x82awi\xC5\x84ski"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-08 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 2
30
+ - 3
31
+ - 0
32
+ version: 2.3.0
33
+ requirement: *id001
34
+ prerelease: false
35
+ type: :development
36
+ name: rspec
37
+ - !ruby/object:Gem::Dependency
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 1
46
+ - 0
47
+ - 0
48
+ version: 1.0.0
49
+ requirement: *id002
50
+ prerelease: false
51
+ type: :development
52
+ name: bundler
53
+ - !ruby/object:Gem::Dependency
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 7
60
+ segments:
61
+ - 1
62
+ - 5
63
+ - 2
64
+ version: 1.5.2
65
+ requirement: *id003
66
+ prerelease: false
67
+ type: :development
68
+ name: jeweler
69
+ - !ruby/object:Gem::Dependency
70
+ version_requirements: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirement: *id004
80
+ prerelease: false
81
+ type: :development
82
+ name: rcov
83
+ description: Cronin can determine cron tasks executions
84
+ email: slawosz@innov8on.com
85
+ executables: []
86
+
87
+ extensions: []
88
+
89
+ extra_rdoc_files:
90
+ - LICENSE.txt
91
+ - README.rdoc
92
+ files:
93
+ - .autospec
94
+ - .document
95
+ - .rspec
96
+ - Gemfile
97
+ - Gemfile.lock
98
+ - LICENSE.txt
99
+ - README.rdoc
100
+ - Rakefile
101
+ - VERSION
102
+ - cronin.gemspec
103
+ - lib/cronin.rb
104
+ - lib/cronin/abstract_timing.rb
105
+ - lib/cronin/cron_task.rb
106
+ - lib/cronin/hour.rb
107
+ - lib/cronin/hours.rb
108
+ - lib/cronin/minutes.rb
109
+ - lib/cronin/month_days.rb
110
+ - lib/cronin/months.rb
111
+ - lib/cronin/parser.rb
112
+ - lib/cronin/restricted.rb
113
+ - lib/cronin/week_days.rb
114
+ - spec/abstract_timing_spec.rb
115
+ - spec/cron_task_spec.rb
116
+ - spec/hour_spec.rb
117
+ - spec/hours_spec.rb
118
+ - spec/minutes_spec.rb
119
+ - spec/month_days_spec.rb
120
+ - spec/months_spec.rb
121
+ - spec/parser_spec.rb
122
+ - spec/restrictable_spec.rb
123
+ - spec/spec_helper.rb
124
+ - spec/week_days_spec.rb
125
+ has_rdoc: true
126
+ homepage: http://github.com/innov8n/cronin
127
+ licenses:
128
+ - MIT
129
+ post_install_message:
130
+ rdoc_options: []
131
+
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ hash: 3
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
151
+ version: "0"
152
+ requirements: []
153
+
154
+ rubyforge_project:
155
+ rubygems_version: 1.3.7
156
+ signing_key:
157
+ specification_version: 3
158
+ summary: Cronin can determine cron tasks executions
159
+ test_files:
160
+ - spec/abstract_timing_spec.rb
161
+ - spec/cron_task_spec.rb
162
+ - spec/hour_spec.rb
163
+ - spec/hours_spec.rb
164
+ - spec/minutes_spec.rb
165
+ - spec/month_days_spec.rb
166
+ - spec/months_spec.rb
167
+ - spec/parser_spec.rb
168
+ - spec/restrictable_spec.rb
169
+ - spec/spec_helper.rb
170
+ - spec/week_days_spec.rb