Skip to content

Commit

Permalink
update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kimpham54 committed Jan 16, 2025
1 parent 5094a19 commit 1bd7271
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/jp2_remediator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def main():
"--output-bucket", help="Name of the AWS S3 bucket to upload the modified file (optional)", required=True
)
s3_file_parser.add_argument(
"--output-key", help="Full key (path) for the uploaded file (overrides output-prefix)"
"--output-key", help="Full key (path) for the uploaded file"
)
s3_file_parser.set_defaults(
func=lambda args: processor.process_s3_file(
Expand Down
65 changes: 41 additions & 24 deletions src/jp2_remediator/tests/unit/test_box_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,35 +382,52 @@ def test_process_trc_tag_size_mismatch(self):
curv_trc_field_length}). Modifying the size..."""
self.reader.logger.warning.assert_any_call(expected_warning)

# Test for process_trc_tag: when curv_trc_gamma_n != 1, in this case is 2
def test_process_trc_tag_sets_skip_remediation(self):
"""
Ensure that if curv_trc_gamma_n != 1, skip_remediation is set to True.
"""
# Prepare minimal file_contents with a single TRC tag
self.reader.file_contents = bytearray(
b"\x00" * 50 +
b"\x72\x54\x52\x43" + # 'rTRC'
b"\x00\x00\x00\x64" + # Some offset (100) in big-endian
b"\x00\x00\x00\x20" + # Tag size (32) in big-endian
b"\x00" * 200 # Just extra space
)
# Test for process_trc_tag: when curv_trc_gamma_n != 1, in this case is 2
def test_process_trc_tag_sets_skip_remediation(self):
"""
Ensure that if curv_trc_gamma_n != 1, skip_remediation is set to True.
"""
# Prepare minimal file_contents with a single TRC tag
self.reader.file_contents = bytearray(
b"\x00" * 50 +
b"\x72\x54\x52\x43" + # 'rTRC'
b"\x00\x00\x00\x64" + # Some offset (100) in big-endian
b"\x00\x00\x00\x20" + # Tag size (32) in big-endian
b"\x00" * 200 # Just extra space
)

# Force a header_offset_position that points to 'curv' data
header_offset_position = 50

# Force a header_offset_position that points to 'curv' data
header_offset_position = 50
# Insert a 'curv' signature + reserved + gamma_n != 1 at position (100 + header_offset_position)
curv_trc_position = 100 + header_offset_position
curv_data = b"curv" + (0).to_bytes(4, 'big') + (2).to_bytes(4, 'big') # gamma_n = 2
self.reader.file_contents[curv_trc_position:curv_trc_position + 12] = curv_data

# Insert a 'curv' signature + reserved + gamma_n != 1 at position (100 + header_offset_position)
curv_trc_position = 100 + header_offset_position
curv_data = b"curv" + (0).to_bytes(4, 'big') + (2).to_bytes(4, 'big') # gamma_n = 2
self.reader.file_contents[curv_trc_position:curv_trc_position + 12] = curv_data
new_contents = bytearray(self.reader.file_contents)

new_contents = bytearray(self.reader.file_contents)
# Call the method
self.reader.process_trc_tag(b"\x72\x54\x52\x43", "rTRC", new_contents, header_offset_position)

# Call the method
self.reader.process_trc_tag(b"\x72\x54\x52\x43", "rTRC", new_contents, header_offset_position)
# Assert skip_remediation is now True
self.assertTrue(self.reader.skip_remediation, "Expected skip_remediation to be True when gamma_n != 1.")

# Assert skip_remediation is now True
self.assertTrue(self.reader.skip_remediation, "Expected skip_remediation to be True when gamma_n != 1.")
def test_read_jp2_file_skip_remediation(self):
"""
Ensure coverage for lines that handle skip_remediation in read_jp2_file().
"""
self.reader.file_contents = b"SomeJP2Content"
self.reader.skip_remediation = True # Force skipping

with patch.object(self.reader, 'write_modified_file') as mock_write:
self.reader.read_jp2_file()
# Because skip_remediation is True, we do not call write_modified_file
mock_write.assert_not_called()

# Check the log was called with that specific skip message
self.reader.logger.info.assert_any_call(
"Skipping 'write_modified_file' because gamma_n != 1 for at least one TRC channel."
)


if __name__ == "__main__":
Expand Down
107 changes: 106 additions & 1 deletion src/jp2_remediator/tests/unit/test_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def test_process_s3_file_file_does_not_exist(
mock_s3_client.download_file.return_value = None

mock_reader = MagicMock()
mock_reader.skip_remediation = False
mock_reader.skip_remediation = False # Mock that skip_remediation is False, not testing this here
mock_box_reader_factory.get_reader.return_value = mock_reader

processor.process_s3_file(input_bucket, input_key, output_bucket, output_key=output_key)
Expand All @@ -120,3 +120,108 @@ def test_process_s3_file_file_does_not_exist(
all_logger_msgs = [call.args[0] for call in processor.logger.info.mock_calls]
assert any("not created" in msg for msg in all_logger_msgs), \
"Expected 'not created' log message not found."

@patch("jp2_remediator.processor.os.path.exists", return_value=True)
@patch("jp2_remediator.processor.boto3.client", autospec=True)
def test_process_s3_file_no_output_key(
self, mock_boto3_client, mock_os_path_exists, processor, mock_box_reader_factory
):
"""
Test coverage for the branch where output_key is NOT provided.
"""
mock_s3_client = MagicMock()
mock_boto3_client.return_value = mock_s3_client

input_bucket = "test-bucket"
input_key = "test-folder/no_output_key.jp2"
output_bucket = "output-bucket"

# Simulate everything existing
mock_s3_client.download_file.return_value = None
mock_s3_client.upload_file.return_value = None

# Provide a BoxReader whose skip_remediation remains False
mock_reader = MagicMock()
mock_reader.skip_remediation = False
mock_box_reader_factory.get_reader.return_value = mock_reader

# Call process_s3_file WITHOUT passing output_key
processor.process_s3_file(input_bucket, input_key, output_bucket)

# Now check that the method generated an output_key internally AND uploaded
mock_s3_client.upload_file.assert_called_once()

# Also check that we see the upload log
all_logger_msgs = [call.args[0] for call in processor.logger.info.mock_calls]
assert any("Uploading modified file to bucket: output-bucket, key:" in msg
for msg in all_logger_msgs), "Expected log about uploading file."

@patch("jp2_remediator.processor.boto3.client", autospec=True)
def test_process_s3_file_skip_remediation(
self, mock_boto3_client, processor, mock_box_reader_factory
):
"""
Covers lines where skip_remediation is True -> log + return (no upload).
"""
mock_s3_client = MagicMock()
mock_boto3_client.return_value = mock_s3_client

input_bucket = "test-bucket"
input_key = "test-folder/skip_rem.jp2"
output_bucket = "output-bucket"

# Ensure the downloaded file "exists", so we skip for skip_remediation, not missing file
with patch("jp2_remediator.processor.os.path.exists", return_value=True):
mock_s3_client.download_file.return_value = None

# This time skip_remediation is True
mock_reader = MagicMock()
mock_reader.skip_remediation = True
mock_box_reader_factory.get_reader.return_value = mock_reader

processor.process_s3_file(input_bucket, input_key, output_bucket, output_key="some-output-file.jp2")

# Because skip_remediation is True, we never call upload_file
mock_s3_client.upload_file.assert_not_called()

# Also confirm we logged the skip message
all_logger_msgs = [call.args[0] for call in processor.logger.info.mock_calls]
assert any("Skipping upload for /tmp/skip_rem.jp2 because curv_trc_gamma_n" in msg
for msg in all_logger_msgs), "Expected skip_remediation log message."

@patch("jp2_remediator.processor.os.path.exists", return_value=True)
@patch("jp2_remediator.processor.os.remove", autospec=True)
@patch("jp2_remediator.processor.boto3.client", autospec=True)
def test_process_s3_file_file_removed_successfully(
self, mock_boto3_client, mock_remove, mock_os_path_exists, processor, mock_box_reader_factory
):
"""
Covers the line where 'Deleted temporary file:' is logged after a successful os.remove().
"""
mock_s3_client = MagicMock()
mock_boto3_client.return_value = mock_s3_client

input_bucket = "test-bucket"
input_key = "test-folder/file.jp2"
output_bucket = "output-bucket"
output_key = "output-folder/file_modified.jp2"

# Simulate successful S3 calls
mock_s3_client.download_file.return_value = None
mock_s3_client.upload_file.return_value = None

# Ensure skip_remediation is False so we don't exit early
mock_reader = MagicMock()
mock_reader.skip_remediation = False
mock_box_reader_factory.get_reader.return_value = mock_reader

# Run the method
processor.process_s3_file(input_bucket, input_key, output_bucket, output_key=output_key)

# Confirm remove was called
mock_remove.assert_called_once()

# Confirm we logged the 'Deleted temporary file:' message
all_logger_msgs = [call.args[0] for call in processor.logger.info.mock_calls]
assert any("Deleted temporary file:" in msg for msg in all_logger_msgs), \
"Expected 'Deleted temporary file:' log message not found."

0 comments on commit 1bd7271

Please sign in to comment.