from datetime import timedelta from time import time from unittest import mock from uuid import uuid4 from conftest import patch_import with patch_import(): from src.utils.key import Key from src.utils.lock import LockError, S3Lock def test_lock(s3_client, s3_bucket): s3_key = "test_key" key = Key.from_string(f"test_{int(time())}_{str(uuid4())}") with mock.patch.object(S3Lock, "_s3_key", s3_key): with S3Lock(key): assert str(key) == s3_client.get_object(Bucket=s3_bucket, Key=s3_key)["Body"].read().decode() no_more_lock = False try: s3_client.get_object(Bucket=s3_bucket, Key=s3_key) except s3_client.exceptions.NoSuchKey: no_more_lock = True assert no_more_lock, "Lock didn't release" def test_lock_not_available(s3_client, s3_bucket): locked = False key1 = Key.from_string(f"test_{int(time())}_{str(uuid4())}") key2 = Key.from_string(f"test_{int(time())}_{str(uuid4())}") with mock.patch.object(S3Lock, "_s3_key", "test_key"): with S3Lock(key1): try: S3Lock(key2).get_lock() except LockError: locked = True assert locked, "Lock wasn't applied correctly" def test_lock_expired(s3_client, s3_bucket): s3_key = "test_key" key1 = Key.from_string(f"test_{int(time() - 61)}_{str(uuid4())}") key2 = Key.from_string(f"test_{int(time())}_{str(uuid4())}") with mock.patch.object(S3Lock, "_s3_key", s3_key), mock.patch.object(S3Lock, "_lock_ttl", timedelta(minutes=1)): with S3Lock(key1): with S3Lock(key2): assert str(key2) == s3_client.get_object(Bucket=s3_bucket, Key=s3_key)["Body"].read().decode() def test_lock_release_on_fail(s3_client, s3_bucket): class TestingException(Exception): pass key = Key.from_string(f"test_{int(time())}_{str(uuid4())}") with mock.patch.object(S3Lock, "_s3_key", "test_key"): no_more_lock = False try: with S3Lock(key): raise TestingException except TestingException: no_more_lock = True assert no_more_lock, "Lock didn't release on error"