import unittest import uuid from concurrent.futures.thread import ThreadPoolExecutor from unittest.mock import Mock from sme_logger.logger import LoggerFactory, Level from apollo_delphi_migration import FileSizeValidationPostProcessor, MigrationContext from apollo_delphi_migration.exceptions import ValidationException, PostProcessingException from apollo_delphi_migration.postprocessing import FingerprintValidationPostProcessor, FingerprintTaggingPostProcessor class FileSizeValidationPostProcessorTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() self.__src_bucket_mock = Mock() self.__dst_bucket_mock = Mock() self.__migration_context = MigrationContext( src_bucket=self.__src_bucket_mock, dst_bucket=self.__dst_bucket_mock, renaming_strategies=[], post_processors=[] ) def test_post_process_should_raise_exception_when_sizes_not_equal(self): self.__src_bucket_mock.size.return_value = 10 self.__dst_bucket_mock.size.return_value = 20 self.assertRaises( ValidationException, FileSizeValidationPostProcessor(Mock()).post_process, 'src_key', 'dst_key', self.__migration_context) def test_post_process_should_not_raise_exception_when_sizes_equal(self): self.__src_bucket_mock.size.return_value = 10 self.__dst_bucket_mock.size.return_value = 10 # not raises exception FileSizeValidationPostProcessor(Mock()).post_process('src_key', 'dst_key', self.__migration_context) class FingerprintTaggingPostProcessorTestCase(unittest.TestCase): logger = LoggerFactory('FingerprintValidationPostProcessorTestCase', Level.DEBUG, is_json=False).get_logger() def setUp(self) -> None: super().setUp() self.__src_bucket_mock = Mock() self.__dst_bucket_mock = Mock() self.__migration_context = MigrationContext( src_bucket=self.__src_bucket_mock, dst_bucket=self.__dst_bucket_mock, renaming_strategies=[], post_processors=[] ) def test_post_process_should_raise_PostProcessingException_exception_when_hashes_not_equal(self): self.__dst_bucket_mock.size.return_value = 1000 # size is bigger than hashed self.__dst_bucket_mock.read.return_value = b'qwerty' with ThreadPoolExecutor() as executor: self.assertRaises( PostProcessingException, FingerprintTaggingPostProcessor(self.logger, executor).post_process, 'src_key', 'dst_key', self.__migration_context) def test_post_process_should_put_tag_to_s3_object(self): self.__dst_bucket_mock.read.return_value = data = b'this is data string' self.__dst_bucket_mock.size.return_value = len(data) with ThreadPoolExecutor() as executor: FingerprintTaggingPostProcessor(self.logger, executor).post_process( 'src_key', 'dst_key', self.__migration_context) self.__dst_bucket_mock.add_tags.assert_called_with( 'dst_key', Fingerprint='7920291ded754b43cb5ed1e7535fff2d.8388608') def test_post_process_should_put_tag_to_s3_object_when_object_read_by_chunks(self): data = b'this is data string' self.__dst_bucket_mock.read.side_effect = [data[:8], data[8:16], data[16:]] self.__dst_bucket_mock.size.return_value = len(data) with ThreadPoolExecutor() as executor: FingerprintTaggingPostProcessor(self.logger, executor, chunk_size=8).post_process( 'src_key', 'dst_key', self.__migration_context) self.__dst_bucket_mock.add_tags.assert_called_with( 'dst_key', Fingerprint='6bf3e030cd02be3e8cf7ca28f40a16e3.8') # 8 bytes per chunk class FingerprintValidationPostProcessorTestCase(unittest.TestCase): logger = LoggerFactory('FingerprintValidationPostProcessorTestCase', Level.DEBUG, is_json=False).get_logger() def setUp(self) -> None: super().setUp() self.__src_bucket_mock = Mock() self.__dst_bucket_mock = Mock() self.__migration_context = MigrationContext( src_bucket=self.__src_bucket_mock, dst_bucket=self.__dst_bucket_mock, renaming_strategies=[], post_processors=[] ) def test_post_process_should_raise_PostProcessingException_exception_when_hashes_not_equal(self): self.__src_bucket_mock.size.return_value = 1000 # size is bigger than hashed self.__src_bucket_mock.read.return_value = b'qwerty' self.__dst_bucket_mock.get_tag.return_value = 'd131dd02c5e6eec4693d9a0698aff95c.8388608' with ThreadPoolExecutor() as executor: self.assertRaises( PostProcessingException, FingerprintValidationPostProcessor(self.logger, executor).post_process, 'src_key', 'dst_key', self.__migration_context) def test_post_process_should_raise_ValidationException_exception_when_hashes_not_equal(self): self.__src_bucket_mock.read.return_value = data = uuid.uuid4().bytes self.__src_bucket_mock.size.return_value = len(data) self.__dst_bucket_mock.get_tag.return_value = 'd131dd02c5e6eec4693d9a0698aff95c.8388608' # unexpected value with ThreadPoolExecutor() as executor: self.assertRaises( ValidationException, FingerprintValidationPostProcessor(self.logger, executor).post_process, 'src_key', 'dst_key', self.__migration_context) def test_post_process_should_pass(self): self.__dst_bucket_mock.get_tag.return_value = '7920291ded754b43cb5ed1e7535fff2d.8388608' self.__src_bucket_mock.read.return_value = data = b'this is data string' self.__src_bucket_mock.size.return_value = len(data) with ThreadPoolExecutor() as executor: FingerprintValidationPostProcessor(self.logger, executor).post_process( 'src_key', 'dst_key', self.__migration_context) def test_post_process_should_pass_with_multiple_chunks(self): data = b'this is data string' self.__dst_bucket_mock.get_tag.return_value = '6bf3e030cd02be3e8cf7ca28f40a16e3.8' # 8 bytes per chunk self.__src_bucket_mock.read.side_effect = [data[:8], data[8:16], data[16:]] self.__src_bucket_mock.size.return_value = len(data) with ThreadPoolExecutor() as executor: FingerprintValidationPostProcessor(self.logger, executor).post_process( 'src_key', 'dst_key', self.__migration_context)