From 9a37e23ef0feb05a91607a76a0f60d09fe5979f5 Mon Sep 17 00:00:00 2001 From: ojab Date: Thu, 29 Mar 2018 13:32:17 +0000 Subject: [PATCH 1/4] Lock rake version '~> 11.0 to fix rspec deprecated method 'last_comment' that is used by rspec was removed in 12.0 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index a90d48a..044c6d1 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,4 @@ source "http://rubygems.org" gemspec gem "ZenTest", "4.6.0" -gem "rake" +gem "rake", '~> 11.0' From c0192072680657f7196fe475a2c90a95669dac89 Mon Sep 17 00:00:00 2001 From: ojab Date: Thu, 29 Mar 2018 13:32:17 +0000 Subject: [PATCH 2/4] Update rspec to 3.7.0 and unlock rake version --- .rspec | 2 +- Gemfile | 2 +- parse-cron.gemspec | 2 +- spec/cron_parser_spec.rb | 27 +++++++++++++-------------- spec/spec_helper.rb | 34 +++++++++++++++++++++++++++------- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/.rspec b/.rspec index 4e1e0d2..c99d2e7 100644 --- a/.rspec +++ b/.rspec @@ -1 +1 @@ ---color +--require spec_helper diff --git a/Gemfile b/Gemfile index 044c6d1..a90d48a 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,4 @@ source "http://rubygems.org" gemspec gem "ZenTest", "4.6.0" -gem "rake", '~> 11.0' +gem "rake" diff --git a/parse-cron.gemspec b/parse-cron.gemspec index a6d1f61..629f4cd 100644 --- a/parse-cron.gemspec +++ b/parse-cron.gemspec @@ -19,5 +19,5 @@ Gem::Specification.new do |s| s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] - s.add_development_dependency 'rspec', '~>2.6.0' + s.add_development_dependency 'rspec', '~> 3.7.0' end diff --git a/spec/cron_parser_spec.rb b/spec/cron_parser_spec.rb index 94f7ad0..3b52f86 100644 --- a/spec/cron_parser_spec.rb +++ b/spec/cron_parser_spec.rb @@ -1,5 +1,4 @@ require "time" -require "./spec/spec_helper" require "cron_parser" require "date" @@ -8,7 +7,7 @@ def parse_date(str) Time.local(dt.year, dt.month, dt.day, dt.hour, dt.min, 0) end -describe "CronParser#parse_element" do +RSpec.describe "CronParser#parse_element" do [ ["*", 0..59, (0..59).to_a], ["*/10", 0..59, [0, 10, 20, 30, 40, 50]], @@ -19,12 +18,12 @@ def parse_date(str) ].each do |element, range, expected| it "should return #{expected} for '#{element}' when range is #{range}" do parser = CronParser.new('* * * * *') - parser.parse_element(element, range).first.to_a.sort.should == expected.sort + expect(parser.parse_element(element, range).first).to match_array(expected) end end end -describe "CronParser#next" do +RSpec.describe "CronParser#next" do [ ["* * * * *", "2011-08-15 12:00", "2011-08-15 12:01",1], ["* * * * *", "2011-08-15 02:25", "2011-08-15 02:26",1], @@ -83,30 +82,30 @@ def parse_date(str) parsed_now = parse_date(now) expected = parse_date(expected_next) parser = CronParser.new(line) - parser.next(parsed_now).xmlschema.should == expected.xmlschema + expect(parser.next(parsed_now).xmlschema).to eql(expected.xmlschema) end it "returns the expected class" do parsed_now = parse_date(now) expected = parse_date(expected_next) parser = CronParser.new(line) result = parser.next(parsed_now,num) - result.class.to_s.should == (num > 1 ? 'Array' : 'Time') + expect(result).to be_a(num > 1 ? Array : Time) end it "returns the expected count" do parsed_now = parse_date(now) expected = parse_date(expected_next) parser = CronParser.new(line) result = parser.next(parsed_now,num) - if result.class.to_s == 'Array' - result.size.should == num + if result.is_a?(Array) + expect(result.size).to eql(num) else - result.class.to_s.should == 'Time' + expect(result).to be_a(Time) end end end end -describe "CronParser#last" do +RSpec.describe "CronParser#last" do [ ["* * * * *", "2011-08-15 12:00", "2011-08-15 11:59"], ["* * * * *", "2011-08-15 02:25", "2011-08-15 02:24"], @@ -164,12 +163,12 @@ def parse_date(str) parser = CronParser.new(line) - parser.last(now).should == expected_next + expect(parser.last(now)).to eql(expected_next) end end end -describe "CronParser#new" do +RSpec.describe "CronParser#new" do it 'should not raise error when given a valid cronline' do expect { CronParser.new('30 * * * *') }.not_to raise_error end @@ -179,10 +178,10 @@ def parse_date(str) end end -describe "time source" do +RSpec.describe "time source" do it "should use an alternate specified time source" do ExtendedTime = Class.new(Time) - ExtendedTime.should_receive(:local).once + expect(ExtendedTime).to receive(:local).once CronParser.new("* * * * *",ExtendedTime).next end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1917de2..83a5d3d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,9 +1,29 @@ -spec_dir = File.dirname(__FILE__) -lib_dir = File.expand_path(File.join(spec_dir, '..', 'lib')) -$:.unshift(lib_dir) -$:.uniq! - RSpec.configure do |config| -end + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups + + config.filter_run_when_matching :focus + + config.example_status_persistence_file_path = 'spec/examples.txt' -require 'cron_parser' + config.disable_monkey_patching! + + config.warnings = true + + if config.files_to_run.one? + config.default_formatter = 'doc' + end + + config.profile_examples = 10 + + config.order = :random + + Kernel.srand config.seed +end From 268094aba4ceb4c60514eafa99aed18decbb8914 Mon Sep 17 00:00:00 2001 From: ojab Date: Thu, 29 Mar 2018 13:32:18 +0000 Subject: [PATCH 3/4] Update rubies in travis --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d41c52e..c731eac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: ruby rvm: - - "2.1.8" - - "2.2.4" - - "2.3.0" + - 2.1.10 + - 2.2.10 + - 2.3.7 + - 2.4.3 + - 2.5.1 From db5c8b747b96fb5647872114fb4c2095a3391fbc Mon Sep 17 00:00:00 2001 From: ojab Date: Thu, 29 Mar 2018 13:32:18 +0000 Subject: [PATCH 4/4] Support `L` in dom field --- lib/cron_parser.rb | 13 ++++++++++--- spec/cron_parser_spec.rb | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/cron_parser.rb b/lib/cron_parser.rb index 41a8a5e..d0a54d0 100644 --- a/lib/cron_parser.rb +++ b/lib/cron_parser.rb @@ -136,14 +136,18 @@ def last(now = @time_source.now, num=1) end - SUBELEMENT_REGEX = %r{^(\d+)(-(\d+)(/(\d+))?)?$} - def parse_element(elem, allowed_range) + SUBELEMENT_REGEX = %r{^(\d+|l)(-(\d+)(/(\d+))?)?$} + def parse_element(elem, allowed_range, field_name = nil) values = elem.split(',').map do |subel| if subel =~ /^\*/ step = subel.length > 1 ? subel[2..-1].to_i : 1 stepped_range(allowed_range, step) else if SUBELEMENT_REGEX === subel + if field_name != :dom && $1.include?('l') + raise ArgumentError, "'L' specification is supported only for DOM field" + end + if $5 # with range stepped_range($1.to_i..$3.to_i, $5.to_i) elsif $3 # range without step @@ -191,6 +195,9 @@ def interpolate_weekdays_without_cache(year, month) # Careful: crontabs may use either 0 or 7 for Sunday: valid_wday << 0 if valid_wday.include?(7) + # L is converted to 0 + valid_mday << (t.next_month - 1).day if valid_mday.include?(0) + result = [] while t.month == month result << t.mday if valid_mday.include?(t.mday) || valid_wday.include?(t.wday) @@ -251,7 +258,7 @@ def time_specs { :minute => parse_element(tokens[0], 0..59), #minute :hour => parse_element(tokens[1], 0..23), #hour - :dom => parse_element(tokens[2], 1..31), #DOM + :dom => parse_element(tokens[2], 1..31, :dom), #DOM :month => parse_element(tokens[3], 1..12), #mon :dow => parse_element(tokens[4], 0..6) #DOW } diff --git a/spec/cron_parser_spec.rb b/spec/cron_parser_spec.rb index 3b52f86..9938cef 100644 --- a/spec/cron_parser_spec.rb +++ b/spec/cron_parser_spec.rb @@ -77,6 +77,10 @@ def parse_date(str) ["15-59/15 * * * *", "2014-02-01 15:45", "2014-02-01 16:15",4], ["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 16:15",3], ["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 16:15",2], + ["* * L 2 *", "2015-02-01 15:36", "2015-02-28 00:00",1], + ["* * L 2 *", "2016-02-01 15:36", "2016-02-29 00:00",1], + ["* * 15,L 2 *", "2015-02-01 15:36", "2015-02-15 00:00",1], + ["* * 15,L 2 *", "2015-02-16 15:36", "2015-02-28 00:00",1] ].each do |line, now, expected_next,num| it "returns #{expected_next} for '#{line}' when now is #{now}" do parsed_now = parse_date(now) @@ -156,6 +160,10 @@ def parse_date(str) ["15-59/15 * * * *", "2014-02-01 15:36", "2014-02-01 15:30"], ["15-59/15 * * * *", "2014-02-01 15:45", "2014-02-01 15:30"], ["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 15:45"], + ["* * L 2 *", "2014-02-01 15:36", "2013-02-28 23:59"], + ["* * L 2 *", "2017-02-01 15:36", "2016-02-29 23:59"], + ["* * 15,L 2 *", "2015-02-01 15:36", "2014-02-28 23:59"], + ["* * 15,L 2 *", "2015-02-16 15:36", "2015-02-15 23:59"] ].each do |line, now, expected_next| it "should return #{expected_next} for '#{line}' when now is #{now}" do now = parse_date(now) @@ -176,6 +184,19 @@ def parse_date(str) it 'should raise error when given an invalid cronline' do expect { CronParser.new('* * * *') }.to raise_error('not a valid cronline') end + + it 'should not raise error when L is passed in DOM field' do + expect { CronParser.new('* * L * *').next }.not_to raise_error + end + + (0..4).each do |n| + next if n == 2 + it "should raise error when L is passed in #{n} field" do + spec = Array.new(5) { '*' } + spec[n] = 'L' + expect { CronParser.new(spec.join(' ')).next }.to raise_error("'L' specification is supported only for DOM field") + end + end end RSpec.describe "time source" do