BigW Consortium Gitlab

cron_parser_spec.rb 6.26 KB
Newer Older
1 2 3 4 5 6 7 8
require 'spec_helper'

describe Gitlab::Ci::CronParser do
  shared_examples_for "returns time in the future" do
    it { is_expected.to be > Time.now }
  end

  describe '#next_time_from' do
9
    subject { described_class.new(cron, cron_timezone).next_time_from(Time.now) }
10

11
    context 'when cron and cron_timezone are valid' do
12 13
      context 'when specific time' do
        let(:cron) { '3 4 5 6 *' }
14
        let(:cron_timezone) { 'UTC' }
15 16 17 18 19 20 21 22 23 24 25 26 27

        it_behaves_like "returns time in the future"

        it 'returns exact time' do
          expect(subject.min).to eq(3)
          expect(subject.hour).to eq(4)
          expect(subject.day).to eq(5)
          expect(subject.month).to eq(6)
        end
      end

      context 'when specific day of week' do
        let(:cron) { '* * * * 0' }
28
        let(:cron_timezone) { 'UTC' }
29 30 31 32 33 34 35 36 37 38

        it_behaves_like "returns time in the future"

        it 'returns exact day of week' do
          expect(subject.wday).to eq(0)
        end
      end

      context 'when slash used' do
        let(:cron) { '*/10 */6 */10 */10 *' }
39
        let(:cron_timezone) { 'UTC' }
40 41 42 43 44 45 46 47 48 49 50 51 52

        it_behaves_like "returns time in the future"

        it 'returns specific time' do
          expect(subject.min).to be_in([0, 10, 20, 30, 40, 50])
          expect(subject.hour).to be_in([0, 6, 12, 18])
          expect(subject.day).to be_in([1, 11, 21, 31])
          expect(subject.month).to be_in([1, 11])
        end
      end

      context 'when range used' do
        let(:cron) { '0,20,40 * 1-5 * *' }
53
        let(:cron_timezone) { 'UTC' }
54 55 56 57 58 59 60 61 62

        it_behaves_like "returns time in the future"

        it 'returns specific time' do
          expect(subject.min).to be_in([0, 20, 40])
          expect(subject.day).to be_in((1..5).to_a)
        end
      end

63 64 65 66 67
      context 'when cron_timezone is TZInfo format' do
        before do
          allow(Time).to receive(:zone)
            .and_return(ActiveSupport::TimeZone['UTC'])
        end
68

69 70 71 72 73 74 75 76 77 78 79
        let(:hour_in_utc) do
          ActiveSupport::TimeZone[cron_timezone]
            .now.change(hour: 0).in_time_zone('UTC').hour
        end

        context 'when cron_timezone is US/Pacific' do
          let(:cron) { '* 0 * * *' }
          let(:cron_timezone) { 'US/Pacific' }

          it_behaves_like "returns time in the future"

80 81 82 83 84 85 86 87 88 89 90 91 92 93
          context 'when PST (Pacific Standard Time)' do
            it 'converts time in server time zone' do
              Timecop.freeze(Time.utc(2017, 1, 1)) do
                expect(subject.hour).to eq(hour_in_utc)
              end
            end
          end

          context 'when PDT (Pacific Daylight Time)' do
            it 'converts time in server time zone' do
              Timecop.freeze(Time.utc(2017, 6, 1)) do
                expect(subject.hour).to eq(hour_in_utc)
              end
            end
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
          end
        end
      end

      context 'when cron_timezone is ActiveSupport::TimeZone format' do
        before do
          allow(Time).to receive(:zone)
            .and_return(ActiveSupport::TimeZone['UTC'])
        end

        let(:hour_in_utc) do
          ActiveSupport::TimeZone[cron_timezone]
            .now.change(hour: 0).in_time_zone('UTC').hour
        end

        context 'when cron_timezone is Berlin' do
          let(:cron) { '* 0 * * *' }
          let(:cron_timezone) { 'Berlin' }

          it_behaves_like "returns time in the future"

115 116 117 118 119 120 121 122 123 124 125 126 127 128
          context 'when CET (Central European Time)' do
            it 'converts time in server time zone' do
              Timecop.freeze(Time.utc(2017, 1, 1)) do
                expect(subject.hour).to eq(hour_in_utc)
              end
            end
          end

          context 'when CEST (Central European Summer Time)' do
            it 'converts time in server time zone' do
              Timecop.freeze(Time.utc(2017, 6, 1)) do
                expect(subject.hour).to eq(hour_in_utc)
              end
            end
129 130
          end
        end
131

132 133 134 135 136 137
        context 'when cron_timezone is Eastern Time (US & Canada)' do
          let(:cron) { '* 0 * * *' }
          let(:cron_timezone) { 'Eastern Time (US & Canada)' }

          it_behaves_like "returns time in the future"

138 139 140 141 142 143 144 145 146 147 148 149 150 151
          context 'when EST (Eastern Standard Time)' do
            it 'converts time in server time zone' do
              Timecop.freeze(Time.utc(2017, 1, 1)) do
                expect(subject.hour).to eq(hour_in_utc)
              end
            end
          end

          context 'when EDT (Eastern Daylight Time)' do
            it 'converts time in server time zone' do
              Timecop.freeze(Time.utc(2017, 6, 1)) do
                expect(subject.hour).to eq(hour_in_utc)
              end
            end
152
          end
153 154 155 156
        end
      end
    end

157
    context 'when cron and cron_timezone are invalid' do
158
      let(:cron) { 'invalid_cron' }
159
      let(:cron_timezone) { 'invalid_cron_timezone' }
160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
      it { is_expected.to be_nil }
    end

    context 'when cron syntax is quoted' do
      let(:cron) { "'0 * * * *'" }
      let(:cron_timezone) { 'UTC' }

      it { expect(subject).to be_nil }
    end

    context 'when cron syntax is rufus-scheduler syntax' do
      let(:cron) { 'every 3h' }
      let(:cron_timezone) { 'UTC' }

      it { expect(subject).to be_nil }
176 177 178
    end
  end

179 180 181 182 183 184 185
  describe '#cron_valid?' do
    subject { described_class.new(cron, Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_TIME_ZONE).cron_valid? }

    context 'when cron is valid' do
      let(:cron) { '* * * * *' }

      it { is_expected.to eq(true) }
186 187
    end

188 189 190 191
    context 'when cron is invalid' do
      let(:cron) { '*********' }

      it { is_expected.to eq(false) }
192
    end
193 194 195 196 197 198

    context 'when cron syntax is quoted' do
      let(:cron) { "'0 * * * *'" }

      it { is_expected.to eq(false) }
    end
199 200
  end

201 202
  describe '#cron_timezone_valid?' do
    subject { described_class.new(Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_CRON, cron_timezone).cron_timezone_valid? }
203 204

    context 'when cron is valid' do
205
      let(:cron_timezone) { 'Europe/Istanbul' }
206 207 208 209 210

      it { is_expected.to eq(true) }
    end

    context 'when cron is invalid' do
211
      let(:cron_timezone) { 'Invalid-zone' }
212

213
      it { is_expected.to eq(false) }
214
    end
215 216 217 218 219 220

    context 'when cron_timezone is ActiveSupport::TimeZone format' do
      let(:cron_timezone) { 'Eastern Time (US & Canada)' }

      it { is_expected.to eq(true) }
    end
221 222
  end
end