blob: d20f45d44cf8aee79f3e9eeab0eeb4b675eb004d [file]
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations
import datetime
import pendulum
import pytest
from airflow.example_dags.plugins.workday import AfterWorkdayTimetable
from airflow.settings import TIMEZONE
from airflow.timetables.base import DagRunInfo, DataInterval, TimeRestriction, Timetable
START_DATE = pendulum.DateTime(2021, 9, 4, tzinfo=TIMEZONE) # This is a Saturday.
WEEK_1_WEEKDAYS = [
pendulum.DateTime(2021, 9, 6, tzinfo=TIMEZONE), # This is a US holiday
pendulum.DateTime(2021, 9, 7, tzinfo=TIMEZONE),
pendulum.DateTime(2021, 9, 8, tzinfo=TIMEZONE),
pendulum.DateTime(2021, 9, 9, tzinfo=TIMEZONE),
pendulum.DateTime(2021, 9, 10, tzinfo=TIMEZONE),
]
WEEK_1_SATURDAY = pendulum.DateTime(2021, 9, 11, tzinfo=TIMEZONE)
WEEK_2_MONDAY = pendulum.DateTime(2021, 9, 13, tzinfo=TIMEZONE)
WEEK_2_TUESDAY = pendulum.DateTime(2021, 9, 14, tzinfo=TIMEZONE)
@pytest.fixture()
def restriction():
return TimeRestriction(earliest=START_DATE, latest=None, catchup=True)
@pytest.fixture()
def timetable():
return AfterWorkdayTimetable()
@pytest.mark.parametrize(
"start, end",
list(zip(WEEK_1_WEEKDAYS[:-1], WEEK_1_WEEKDAYS[1:])),
)
def test_dag_run_info_interval(start: pendulum.DateTime, end: pendulum.DateTime):
expected_info = DagRunInfo(run_after=end, data_interval=DataInterval(start, end))
assert DagRunInfo.interval(start, end) == expected_info
def test_first_schedule(timetable: Timetable, restriction: TimeRestriction):
"""Since DAG starts on Saturday, and the first Monday is a holiday,
the first ever run covers the next Tuesday and schedules on Wednesday."""
next_info = timetable.next_dagrun_info(last_automated_data_interval=None, restriction=restriction)
assert next_info == DagRunInfo.interval(WEEK_1_WEEKDAYS[1], WEEK_1_WEEKDAYS[2])
@pytest.mark.parametrize(
"last_automated_data_interval, expected_next_info",
[
pytest.param(
DataInterval(day, day + datetime.timedelta(days=1)),
DagRunInfo.interval(
day + datetime.timedelta(days=1),
day + datetime.timedelta(days=2),
),
)
for day in WEEK_1_WEEKDAYS[:-1] # Data intervals for Monday to Tuesday.
],
)
def test_subsequent_weekday_schedule(
timetable: Timetable,
restriction: TimeRestriction,
last_automated_data_interval: DataInterval,
expected_next_info: DagRunInfo,
):
"""The next four subsequent runs cover the next four weekdays each."""
next_info = timetable.next_dagrun_info(
last_automated_data_interval=last_automated_data_interval,
restriction=restriction,
)
assert next_info == expected_next_info
def test_next_schedule_after_friday(timetable: Timetable, restriction: TimeRestriction):
"""The run after Friday's run covers Monday."""
last_automated_data_interval = DataInterval(WEEK_1_WEEKDAYS[-1], WEEK_1_SATURDAY)
expected_next_info = DagRunInfo.interval(WEEK_2_MONDAY, WEEK_2_TUESDAY)
next_info = timetable.next_dagrun_info(
last_automated_data_interval=last_automated_data_interval,
restriction=restriction,
)
assert next_info == expected_next_info