def test_email_job(db): queue_email("sender_name", "sender_email", "recipient", "subject", "plain", "html") def mock_print_dev_email(sender_name, sender_email, recipient, subject, plain, html): assert sender_name == "sender_name" assert sender_email == "sender_email" assert recipient == "recipient" assert subject == "subject" assert plain == "plain" assert html == "html" return print_dev_email(sender_name, sender_email, recipient, subject, plain, html) with patch("couchers.jobs.handlers.print_dev_email", mock_print_dev_email): process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_login_email_full(db): user, api_token = generate_user() user_email = user.email with session_scope() as session: login_token = send_login_email(session, user) def mock_print_dev_email(sender_name, sender_email, recipient, subject, plain, html): assert recipient == user.email assert "login" in subject.lower() assert login_token.token in plain assert login_token.token in html return print_dev_email(sender_name, sender_email, recipient, subject, plain, html) with patch("couchers.jobs.handlers.print_dev_email", mock_print_dev_email): process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_login_email_full(db): user, api_token = generate_user() user_email = user.email with session_scope() as session: login_token, expiry_text = new_login_token(session, user) send_login_email(user, login_token, expiry_text) token = login_token.token def mock_print_dev_email(sender_name, sender_email, recipient, subject, plain, html): assert recipient == user.email assert "login" in subject.lower() assert login_token.token in plain assert login_token.token in html return print_dev_email(sender_name, sender_email, recipient, subject, plain, html) with patch("couchers.jobs.handlers.print_dev_email", mock_print_dev_email): process_job() with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def test_purge_password_reset_tokens(db): user, api_token = generate_user() with session_scope() as session: password_reset_token = PasswordResetToken(token=urlsafe_secure_token(), user=user, expiry=now()) session.add(password_reset_token) assert session.execute( select(func.count()).select_from( PasswordResetToken)).scalar_one() == 1 queue_job(BackgroundJobType.purge_password_reset_tokens, empty_pb2.Empty()) process_job() with session_scope() as session: assert session.execute( select(func.count()).select_from( PasswordResetToken)).scalar_one() == 0 with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_purge_signup_tokens(db): with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Signup(auth_pb2.SignupReq(email="*****@*****.**")) # send email process_job() with session_scope() as session: signup_token = session.query(SignupToken).one() signup_token.expiry = func.now() assert session.query(SignupToken).count() == 1 queue_job(BackgroundJobType.purge_signup_tokens, empty_pb2.Empty()) # purge tokens process_job() with session_scope() as session: assert session.query(SignupToken).count() == 0 with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 2 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def test_job_retry(db): queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty()) called_count = 0 def mock_handler(payload): nonlocal called_count called_count += 1 raise Exception() MOCK_JOBS = { BackgroundJobType.purge_login_tokens: (empty_pb2.Empty, mock_handler), } create_prometheus_server(registry=job_process_registry, port=8001) with patch("couchers.jobs.worker.JOBS", MOCK_JOBS): process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.error)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.error)). scalar_one() == 0) session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.failed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.failed)).scalar_one( ) == 0) _check_job_counter("purge_login_tokens", "error", "4", "Exception") _check_job_counter("purge_login_tokens", "failed", "5", "Exception")
def test_enforce_community_memberships(db): queue_job(BackgroundJobType.enforce_community_membership, empty_pb2.Empty()) process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_purge_account_deletion_tokens(db): user, api_token = generate_user() user2, api_token2 = generate_user() user3, api_token3 = generate_user() with session_scope() as session: """ 3 cases: 1) Token is valid 2) Token expired but account retrievable 3) Account is irretrievable (and expired) """ account_deletion_tokens = [ AccountDeletionToken(token=urlsafe_secure_token(), user=user, expiry=now() - timedelta(hours=2)), AccountDeletionToken(token=urlsafe_secure_token(), user=user2, expiry=now()), AccountDeletionToken(token=urlsafe_secure_token(), user=user3, expiry=now() + timedelta(hours=5)), ] for token in account_deletion_tokens: session.add(token) assert session.execute( select(func.count()).select_from( AccountDeletionToken)).scalar_one() == 3 queue_job(BackgroundJobType.purge_account_deletion_tokens, empty_pb2.Empty()) process_job() with session_scope() as session: assert session.execute( select(func.count()).select_from( AccountDeletionToken)).scalar_one() == 1 with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_no_jobs_no_problem(db): with session_scope() as session: assert session.query(BackgroundJob).count() == 0 assert not process_job() with session_scope() as session: assert session.query(BackgroundJob).count() == 0
def test_no_jobs_no_problem(db): with session_scope() as session: assert session.execute( select(func.count()).select_from(BackgroundJob)).scalar_one() == 0 assert not process_job() with session_scope() as session: assert session.execute( select(func.count()).select_from(BackgroundJob)).scalar_one() == 0
def test_purge_login_tokens(db): user, api_token = generate_user() with session_scope() as session: login_token, expiry_text = new_login_token(session, user) login_token.expiry = func.now() assert session.query(LoginToken).count() == 1 queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty()) process_job() with session_scope() as session: assert session.query(LoginToken).count() == 0 with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def test_job_retry(db): queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty()) called_count = 0 def mock_handler(payload): nonlocal called_count called_count += 1 raise Exception() MOCK_JOBS = { BackgroundJobType.purge_login_tokens: (empty_pb2.Empty, mock_handler), } with patch("couchers.jobs.worker.JOBS", MOCK_JOBS): process_job() with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.error).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.error).count() == 0 session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.failed).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.failed).count() == 0
def test_email_job(db): queue_email("sender_name", "sender_email", "recipient", "subject", "plain", "html") def mock_print_dev_email(sender_name, sender_email, recipient, subject, plain, html): assert sender_name == "sender_name" assert sender_email == "sender_email" assert recipient == "recipient" assert subject == "subject" assert plain == "plain" assert html == "html" return print_dev_email(sender_name, sender_email, recipient, subject, plain, html) with patch("couchers.jobs.handlers.print_dev_email", mock_print_dev_email): process_job() with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def test_process_send_reference_reminders(db): # need to test: # case 1: bidirectional (no emails) # case 2: host left ref (surfer needs an email) # case 3: surfer left ref (host needs an email) # case 4: neither left ref (host & surfer need an email) process_send_reference_reminders(empty_pb2.Empty()) # case 1: bidirectional (no emails) user1, token1 = generate_user(email="*****@*****.**", name="User 1") user2, token2 = generate_user(email="*****@*****.**", name="User 2") # case 2: host left ref (surfer needs an email) # host user3, token3 = generate_user(email="*****@*****.**", name="User 3") # surfer user4, token4 = generate_user(email="*****@*****.**", name="User 4") # case 3: surfer left ref (host needs an email) # host user5, token5 = generate_user(email="*****@*****.**", name="User 5") # surfer user6, token6 = generate_user(email="*****@*****.**", name="User 6") # case 4: neither left ref (host & surfer need an email) # host user7, token7 = generate_user(email="*****@*****.**", name="User 7") # surfer user8, token8 = generate_user(email="*****@*****.**", name="User 8") # case 5: neither left ref, but host blocked surfer, so neither should get an email # host user9, token9 = generate_user(email="*****@*****.**", name="User 9") # surfer user10, token10 = generate_user(email="*****@*****.**", name="User 10") make_user_block(user9, user10) with session_scope() as session: # note that create_host_reference creates a host request whose age is one day older than the timedelta here # case 1: bidirectional (no emails) ref1, hr1 = create_host_reference(session, user2.id, user1.id, timedelta(days=7), surfing=True) create_host_reference(session, user1.id, user2.id, timedelta(days=7), host_request_id=hr1) # case 2: host left ref (surfer needs an email) ref2, hr2 = create_host_reference(session, user3.id, user4.id, timedelta(days=11), surfing=False) # case 3: surfer left ref (host needs an email) ref3, hr3 = create_host_reference(session, user6.id, user5.id, timedelta(days=9), surfing=True) # case 4: neither left ref (host & surfer need an email) hr4 = create_host_request(session, user7.id, user8.id, timedelta(days=4)) # case 5: neither left ref, but host blocked surfer, so neither should get an email hr5 = create_host_request(session, user9.id, user10.id, timedelta(days=7)) expected_emails = [ ("*****@*****.**", "[TEST] You have 3 days to write a reference for User 3!"), ("*****@*****.**", "[TEST] You have 7 days to write a reference for User 6!"), ("*****@*****.**", "[TEST] You have 14 days to write a reference for User 8!"), ("*****@*****.**", "[TEST] You have 14 days to write a reference for User 7!"), ] process_send_reference_reminders(empty_pb2.Empty()) while process_job(): pass with session_scope() as session: emails = [ (email.recipient, email.subject) for email in session.execute( select(Email).order_by(Email.recipient.asc())).scalars().all() ] print(emails) print(expected_emails) assert emails == expected_emails