def test_print_capture():
    def slow_job(sleep_time):
        time.sleep(sleep_time)
        print("Slow job completed")

    sleep_time = 1
    log_file_path = 'testlog.log'
    s = TaskScheduler(log_filepath=log_file_path)
    s.every(1).do(slow_job, sleep_time=sleep_time, do_parallel=True)
    s.check()

    counter = 4
    while counter > 0:
        print("outside")
        counter -= 1
        print('running:', s.jobs[0].is_running)
        s.check()
        time.sleep(0.5)
    print("stopping")
    s.join()
    j0 = s.jobs[0].to_dict()
    assert ('Slow job completed' in j0['logs']['log'])
    assert ('===' in j0['logs']['log'])
    assert ('outside' not in j0['logs']['log'])
    assert ('stopping' not in j0['logs']['log'])
    pretty_print(j0)
    # test log file
    assert (os.path.isfile(log_file_path) == True)
    with open(log_file_path, 'r') as lf:
        assert ('Slow job completed' in lf.read())
    for h in LOGGER.handlers:
        h.close()
        LOGGER.removeHandler(h)
    if os.path.isfile(log_file_path): os.remove(log_file_path)
    assert (os.path.isfile(log_file_path) == False)
def test_error_callback():
    sleep_time = 1
    errors = []
    err_count = 0

    def failing_job(msg):
        raise Exception(msg)

    def err(e):
        nonlocal errors, err_count
        cause = str(e).strip().split()[-1]  # get last word from traceback
        errors.append(cause)
        err_count += 1

    def err_specific(e):
        nonlocal errors, err_count
        cause = str(e).strip().split()[-1]  # get last word from traceback
        errors.append(cause + "_specific")
        err_count += 1

    s = TaskScheduler(on_job_error=err)
    s.every(sleep_time).do(failing_job, msg='one', do_parallel=True)
    s.every(sleep_time).do(failing_job, msg='two')
    s.every(sleep_time).do(failing_job, msg='three',
                           do_parallel=True).catch(err_specific)
    time.sleep(sleep_time + 0.5)
    s.check()
    time.sleep(0.5)
    assert (sorted(errors) == sorted(['one', 'two', 'three_specific'])
            )  # err callbacks were called
    assert (err_count == 3)
    assert (s.jobs[0].did_fail() == True)
    pretty_print(s.jobs[0].to_dict())
def test_repeat():
    d = time.time()
    sleep_time = 1
    s = TaskScheduler()
    s.every(sleep_time).do(job, x="hello", y="world")
    assert (abs(s.jobs[0].next_timestamp - (d + sleep_time)) < 0.1)
    time.sleep(sleep_time + 0.5)
    s.check()
    assert (abs(s.jobs[0].next_timestamp - (d + (2 * sleep_time))) < 0.1)
def test_day_of_week():
    now = dt.now()
    today_str = now.strftime("%A").lower()
    in2sec_str = now.strftime("%H:%M")
    s = TaskScheduler()
    s.every(today_str).at(in2sec_str).do(job, x="hello", y=today_str)
    assert len(s.jobs) == 1
    time.sleep(0.5)
    s.check()
    # test if next run greater than 6 days, less than 8 days from now
    test_timestamp = time.time()
    assert s.jobs[0].next_timestamp > test_timestamp + (6 * 24 * 60 * 60)
    assert s.jobs[0].next_timestamp < test_timestamp + (8 * 24 * 60 * 60)
def test_repeat_parallel():
    d = time.time()
    sleep_time = 1
    s = TaskScheduler()
    s.every(sleep_time).do(job, x="hello", y="world", do_parallel=True)
    s.every(sleep_time).do(job, x="hello", y="world", do_parallel=True)
    ts = s.jobs[0].next_timestamp
    assert (abs(ts - (d + sleep_time)) < 0.1)
    time.sleep(sleep_time + 0.5)
    s.check()
    assert (s.jobs[0].next_timestamp == ts)  # still not rescheduled
    time.sleep(0.5)
    assert (s.jobs[0].next_timestamp != ts)  # rescheduled parallely
    assert (abs(s.jobs[0].next_timestamp - (d + (2 * sleep_time))) < 0.1)
    assert (abs(s.jobs[0].next_timestamp - s.jobs[1].next_timestamp) < 0.1)
def test_onetime():
    yesterday = dt.now() - timedelta(days=1)
    tomorrow = (dt.now() + timedelta(days=1)).replace(hour=23,
                                                      minute=59,
                                                      second=0,
                                                      microsecond=0)
    s = TaskScheduler()
    s.on(yesterday.strftime("%Y-%m-%d")).at("23:59").do(job,
                                                        x="hello",
                                                        y="world")
    s.on(tomorrow.strftime("%Y-%m-%d")).at("23:59").do(job,
                                                       x="hello",
                                                       y="world")
    for j in s.jobs:
        assert (j.next_timestamp == dt.timestamp(tomorrow)
                or j.next_timestamp == 0)
    assert len(s.jobs) == 2
    s.check()
    assert len(s.jobs) == 1