From 8db90c2f618a27515e207c8f7e3ee94ca1848691 Mon Sep 17 00:00:00 2001 From: "Douglas Cerna (Soy Douglas)" Date: Mon, 12 Aug 2024 23:15:22 +0000 Subject: [PATCH 1/3] Add tests for identify_file_format script --- mypy.ini | 3 +- .../lib/clientScripts/identify_file_format.py | 14 +- tests/MCPClient/conftest.py | 17 + tests/MCPClient/test_identify_file_format.py | 362 ++++++++++++++++++ 4 files changed, 388 insertions(+), 8 deletions(-) create mode 100644 tests/MCPClient/test_identify_file_format.py diff --git a/mypy.ini b/mypy.ini index b23454ab2a..040b463f9d 100644 --- a/mypy.ini +++ b/mypy.ini @@ -20,7 +20,8 @@ warn_return_any = True warn_unused_ignores = True -[mypy-tests.MCPClient.conftest,tests.MCPClient.test_normalize,tests.MCPClient.test_validate_file,tests.MCPClient.test_policy_check] +[mypy-tests.MCPClient.conftest,tests.MCPClient.test_identify_file_format,tests.MCPClient.test_normalize,tests.MCPClient.test_validate_file,tests.MCPClient.test_policy_check] + check_untyped_defs = True disallow_any_generics = True disallow_incomplete_defs = True diff --git a/src/MCPClient/lib/clientScripts/identify_file_format.py b/src/MCPClient/lib/clientScripts/identify_file_format.py index 4ca12a6164..84c9b4e1f4 100755 --- a/src/MCPClient/lib/clientScripts/identify_file_format.py +++ b/src/MCPClient/lib/clientScripts/identify_file_format.py @@ -163,10 +163,10 @@ def main(job, enabled, file_path, file_uuid, disable_reidentify): # go straight to the FormatVersion table to see if there's a matching PUID try: if command.config == "PUID": - version = FormatVersion.active.get(pronom_id=output) + format_version = FormatVersion.active.get(pronom_id=output) else: rule = IDRule.active.get(command_output=output, command=command) - version = rule.format + format_version = rule.format except IDRule.DoesNotExist: job.print_error( f'Error: No FPR identification rule for tool output "{output}" found' @@ -185,15 +185,15 @@ def main(job, enabled, file_path, file_uuid, disable_reidentify): return 255 (ffv, created) = FileFormatVersion.objects.get_or_create( - file_uuid=file_, defaults={"format_version": version} + file_uuid=file_, defaults={"format_version": format_version} ) if not created: # Update the version if it wasn't created new - ffv.format_version = version + ffv.format_version = format_version ffv.save() - job.print_output(f"{file_path} identified as a {version.description}") + job.print_output(f"{file_path} identified as a {format_version.description}") - write_identification_event(file_uuid, command, format=version.pronom_id) - write_file_id(file_uuid=file_uuid, format=version, output=output) + write_identification_event(file_uuid, command, format=format_version.pronom_id) + write_file_id(file_uuid=file_uuid, format=format_version, output=output) return 0 diff --git a/tests/MCPClient/conftest.py b/tests/MCPClient/conftest.py index 323e71b64f..244772bcf5 100644 --- a/tests/MCPClient/conftest.py +++ b/tests/MCPClient/conftest.py @@ -91,11 +91,21 @@ def fptool() -> fprmodels.FPTool: return fprmodels.FPTool.objects.create() +@pytest.fixture +def idtool() -> fprmodels.IDTool: + return fprmodels.IDTool.objects.create() + + @pytest.fixture def fpcommand(fptool: fprmodels.FPTool) -> fprmodels.FPCommand: return fprmodels.FPCommand.objects.create(tool=fptool) +@pytest.fixture +def idcommand(idtool: fprmodels.IDTool) -> fprmodels.IDCommand: + return fprmodels.IDCommand.objects.create(tool=idtool, config="PUID") + + @pytest.fixture def fprule( fpcommand: fprmodels.FPCommand, format_version: fprmodels.FormatVersion @@ -103,6 +113,13 @@ def fprule( return fprmodels.FPRule.objects.create(command=fpcommand, format=format_version) +@pytest.fixture +def idrule( + idcommand: fprmodels.IDCommand, format_version: fprmodels.FormatVersion +) -> fprmodels.IDRule: + return fprmodels.IDRule.objects.create(command=idcommand, format=format_version) + + @pytest.fixture() def fprule_characterization(fprule: fprmodels.FPRule) -> fprmodels.FPRule: fprule.purpose = fprmodels.FPRule.CHARACTERIZATION diff --git a/tests/MCPClient/test_identify_file_format.py b/tests/MCPClient/test_identify_file_format.py new file mode 100644 index 0000000000..702e5c1962 --- /dev/null +++ b/tests/MCPClient/test_identify_file_format.py @@ -0,0 +1,362 @@ +import pathlib +from unittest import mock + +import identify_file_format +import pytest +from client.job import Job +from fpr import models as fprmodels +from main import models + + +@pytest.fixture +def sip_file_path( + sip_directory_path: pathlib.Path, sip_file: models.File +) -> pathlib.Path: + result = sip_directory_path / pathlib.Path( + sip_file.currentlocation.decode().replace("%SIPDirectory%", "") + ) + result.parent.mkdir(parents=True) + result.touch() + + return result + + +@pytest.fixture +def job(sip_file: models.File, sip_file_path: pathlib.Path) -> mock.Mock: + return mock.Mock( + args=[ + "identify_file_format.py", + "True", + str(sip_file_path), + str(sip_file.uuid), + "--disable-reidentify", + ], + JobContext=mock.MagicMock(), + spec=Job, + ) + + +@pytest.mark.django_db +def test_job_skips_format_identification_explicitly(job: mock.Mock) -> None: + job.args[1] = "False" + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(0) + job.print_output.assert_called_once_with("Skipping file format identification") + + +@pytest.mark.django_db +def test_job_skips_format_identification_if_file_has_format_identification_events( + job: mock.Mock, + sip_file: models.File, + sip_file_path: pathlib.Path, + idcommand: fprmodels.IDCommand, +) -> None: + models.Event.objects.create(file_uuid=sip_file, event_type="format identification") + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(0) + assert job.print_output.mock_calls == [ + mock.call("IDCommand:", idcommand.description), + mock.call("IDCommand UUID:", idcommand.uuid), + mock.call("IDTool:", idcommand.tool.description), + mock.call("IDTool UUID:", idcommand.tool.uuid), + mock.call(f"File: ({sip_file.uuid}) {sip_file_path}"), + mock.call( + "This file has already been identified, and re-identification is disabled. Skipping." + ), + ] + + +@pytest.mark.django_db +def test_job_fails_if_identification_command_does_not_exist(job: mock.Mock) -> None: + fprmodels.IDCommand.objects.all().delete() + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(255) + job.write_error.assert_called_once_with("Unable to determine IDCommand.\n") + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_fails_if_format_identification_command_fails( + execute_or_run: mock.Mock, + job: mock.Mock, + idcommand: fprmodels.IDCommand, +) -> None: + command_error = "error!" + execute_or_run.return_value = (1, "", command_error) + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(255) + assert job.print_error.mock_calls == [ + mock.call(f"Error: IDCommand with UUID {idcommand.uuid} exited non-zero."), + mock.call(f"Error: {command_error}"), + ] + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_fails_if_identification_rule_does_not_exist( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + idcommand: fprmodels.IDCommand, +) -> None: + command_output = ".mp3" + execute_or_run.return_value = (0, command_output, "") + + idcommand.config = "" + idcommand.save() + + fprmodels.IDRule.objects.filter(command_output=command_output).delete() + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(255) + assert ( + models.Event.objects.filter( + file_uuid=sip_file.uuid, + event_type="format identification", + event_detail=f'program="{idcommand.tool.description}"; version="{idcommand.tool.version}"', + event_outcome="Not identified", + event_outcome_detail="No Matching Format", + ).count() + == 1 + ) + job.print_error.assert_called_once_with( + f'Error: No FPR identification rule for tool output "{command_output}" found' + ) + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_fails_if_multiple_identification_rules_exist( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + idcommand: fprmodels.IDCommand, + idrule: fprmodels.IDRule, + format_version: fprmodels.Format, +) -> None: + command_output = ".mp3" + execute_or_run.return_value = (0, command_output, "") + + idcommand.config = "" + idcommand.save() + + fprmodels.IDRule.objects.filter(command_output=command_output).delete() + fprmodels.IDRule.objects.create( + command=idcommand, format=format_version, command_output=command_output + ) + idrule.command_output = command_output + idrule.save() + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(255) + assert ( + models.Event.objects.filter( + file_uuid=sip_file.uuid, + event_type="format identification", + event_detail=f'program="{idcommand.tool.description}"; version="{idcommand.tool.version}"', + event_outcome="Not identified", + event_outcome_detail="No Matching Format", + ).count() + == 1 + ) + job.print_error.assert_called_once_with( + f'Error: Multiple FPR identification rules for tool output "{command_output}" found' + ) + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_fails_if_format_version_does_not_exist( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + idcommand: fprmodels.IDCommand, +) -> None: + command_output = ".mp3" + execute_or_run.return_value = (0, command_output, "") + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(255) + assert ( + models.Event.objects.filter( + file_uuid=sip_file.uuid, + event_type="format identification", + event_detail=f'program="{idcommand.tool.description}"; version="{idcommand.tool.version}"', + event_outcome="Not identified", + event_outcome_detail="No Matching Format", + ).count() + == 1 + ) + job.print_error.assert_called_once_with( + f"Error: No FPR format record found for PUID {command_output}" + ) + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun", return_value=(0, "success!", "")) +def test_job_saves_unit_variable_indicating_file_format_identification_use( + execute_or_run: mock.Mock, + job: mock.Mock, + sip: models.SIP, +) -> None: + identify_file_format.call([job]) + + assert ( + models.UnitVariable.objects.filter( + unituuid=sip.pk, + variable="replacementDict", + variablevalue="{'%IDCommand%': 'True'}", + ).count() + == 1 + ) + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_adds_file_format_version( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + sip_file_path: pathlib.Path, + idcommand: fprmodels.IDCommand, + format_version: fprmodels.FormatVersion, +) -> None: + command_output = "fmt/111" + execute_or_run.return_value = (0, command_output, "") + + fprmodels.FormatVersion.objects.filter(pronom_id=command_output).delete() + format_version.pronom_id = command_output + format_version.save() + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(0) + assert ( + models.FileFormatVersion.objects.filter( + file_uuid=sip_file, format_version=format_version + ).count() + == 1 + ) + assert job.print_output.mock_calls == [ + mock.call("IDCommand:", idcommand.description), + mock.call("IDCommand UUID:", idcommand.uuid), + mock.call("IDTool:", idcommand.tool.description), + mock.call("IDTool UUID:", idcommand.tool.uuid), + mock.call(f"File: ({sip_file.uuid}) {sip_file_path}"), + mock.call("Command output:", command_output), + mock.call(f"{sip_file_path} identified as a {format_version.description}"), + ] + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_updates_file_format_version( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + format: fprmodels.Format, + sip_file_format_version: models.FileFormatVersion, +) -> None: + command_output = "fmt/111" + execute_or_run.return_value = (0, command_output, "") + + fprmodels.FormatVersion.objects.filter(pronom_id=command_output).delete() + format_version = fprmodels.FormatVersion.objects.create( + format=format, pronom_id=command_output + ) + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(0) + assert ( + models.FileFormatVersion.objects.filter( + file_uuid=sip_file, format_version=format_version + ).count() + == 1 + ) + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_adds_successful_format_identification_data( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + idcommand: fprmodels.IDCommand, + format_version: fprmodels.Format, +) -> None: + command_output = "fmt/111" + execute_or_run.return_value = (0, command_output, "") + + fprmodels.FormatVersion.objects.filter(pronom_id=command_output).delete() + format_version.pronom_id = command_output + format_version.save() + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(0) + assert ( + models.Event.objects.filter( + file_uuid=sip_file.uuid, + event_type="format identification", + event_detail=f'program="{idcommand.tool.description}"; version="{idcommand.tool.version}"', + event_outcome="Positive", + event_outcome_detail=command_output, + ).count() + == 1 + ) + assert ( + models.FileID.objects.filter( + file=sip_file, + format_name=format_version.format.description, + format_version="", + format_registry_name="PRONOM", + format_registry_key=format_version.pronom_id, + ).count() + == 1 + ) + + +@pytest.mark.django_db +@mock.patch("identify_file_format.executeOrRun") +def test_job_falls_back_to_identification_rule_if_format_version_does_not_exist( + execute_or_run: mock.Mock, + job: mock.Mock, + sip_file: models.File, + idcommand: fprmodels.IDCommand, + idrule: fprmodels.IDRule, +) -> None: + command_output = ".mp3" + execute_or_run.return_value = (0, command_output, "") + + idcommand.config = "" + idcommand.save() + + fprmodels.IDRule.objects.filter(command_output=command_output).delete() + idrule.command_output = command_output + idrule.save() + + identify_file_format.call([job]) + + job.set_status.assert_called_once_with(0) + assert ( + models.FileID.objects.filter( + file=sip_file, + format_name="", + format_version="", + format_registry_name="Archivematica Format Policy Registry", + format_registry_key=command_output, + ).count() + == 1 + ) From 6e92f9f75e8cabc776e690fde44b5a7275105d60 Mon Sep 17 00:00:00 2001 From: "Douglas Cerna (Soy Douglas)" Date: Tue, 13 Aug 2024 14:21:20 +0000 Subject: [PATCH 2/3] Add type hints for identify_file_format script --- mypy.ini | 3 +- .../lib/clientScripts/identify_file_format.py | 61 +++++++++++++------ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/mypy.ini b/mypy.ini index 040b463f9d..0383811071 100644 --- a/mypy.ini +++ b/mypy.ini @@ -5,7 +5,8 @@ warn_redundant_casts = True warn_unused_configs = True -[mypy-src.MCPClient.lib.client.*,src.MCPClient.*.normalize,src.MCPClient.*.validate_file, src.MCPClient.*.policy_check] +[mypy-src.MCPClient.lib.client.*,src.MCPClient.*.identify_file_format,src.MCPClient.*.normalize,src.MCPClient.*.validate_file, src.MCPClient.*.policy_check] + check_untyped_defs = True disallow_any_generics = True disallow_incomplete_defs = True diff --git a/src/MCPClient/lib/clientScripts/identify_file_format.py b/src/MCPClient/lib/clientScripts/identify_file_format.py index 84c9b4e1f4..ad36a91885 100755 --- a/src/MCPClient/lib/clientScripts/identify_file_format.py +++ b/src/MCPClient/lib/clientScripts/identify_file_format.py @@ -1,17 +1,19 @@ #!/usr/bin/env python import argparse +import dataclasses import multiprocessing import uuid +from typing import List +from typing import Optional import django django.setup() -# dashboard + +from client.job import Job from databaseFunctions import insertIntoEvents from django.db import transaction from django.utils import timezone - -# archivematicaCommon from executeOrRunSubProcess import executeOrRun from fpr.models import FormatVersion from fpr.models import IDCommand @@ -22,11 +24,19 @@ from main.models import UnitVariable -def concurrent_instances(): +@dataclasses.dataclass +class IdentifyFileFormatArgs: + idcommand: str + file_path: str + file_uuid: str + disable_reidentify: bool + + +def concurrent_instances() -> int: return multiprocessing.cpu_count() -def _save_id_preference(file_, value): +def _save_id_preference(file_: File, value: bool) -> None: """ Saves whether file format identification is being used. @@ -35,22 +45,25 @@ def _save_id_preference(file_, value): variable, which will be transformed back into a passVar when a new chain in the same unit is begun. """ - value = str(value) - # The unit_uuid foreign key can point to a transfer or SIP, and this tool # runs in both. # Check the SIP first - if it hasn't been assigned yet, then this is being # run during the transfer. unit = file_.sip or file_.transfer - rd = {"%IDCommand%": value} + rd = {"%IDCommand%": str(value)} UnitVariable.objects.create( unituuid=unit.pk, variable="replacementDict", variablevalue=str(rd) ) -def write_identification_event(file_uuid, command, format=None, success=True): +def write_identification_event( + file_uuid: str, + command: IDCommand, + format: Optional[str] = None, + success: bool = True, +) -> None: event_detail_text = ( f'program="{command.tool.description}"; version="{command.tool.version}"' ) @@ -75,7 +88,7 @@ def write_identification_event(file_uuid, command, format=None, success=True): ) -def write_file_id(file_uuid, format, output): +def write_file_id(file_uuid: str, format: FormatVersion, output: str) -> None: """ Write the identified format to the DB. @@ -102,7 +115,7 @@ def write_file_id(file_uuid, format, output): ) -def _default_idcommand(): +def _default_idcommand() -> IDCommand: """Retrieve the default ``fpr.IDCommand``. We only expect to find one command enabled/active. @@ -110,9 +123,11 @@ def _default_idcommand(): return IDCommand.active.first() -def main(job, enabled, file_path, file_uuid, disable_reidentify): - enabled = True if enabled == "True" else False - if not enabled: +def main( + job: Job, enabled: str, file_path: str, file_uuid: str, disable_reidentify: bool +) -> int: + enabled_bool = True if enabled == "True" else False + if not enabled_bool: job.print_output("Skipping file format identification") return 0 @@ -142,7 +157,7 @@ def main(job, enabled, file_path, file_uuid, disable_reidentify): # Save whether identification was enabled by the user for use in a later # chain. - _save_id_preference(file_, enabled) + _save_id_preference(file_, enabled_bool) exitcode, output, err = executeOrRun( command.script_type, @@ -198,7 +213,7 @@ def main(job, enabled, file_path, file_uuid, disable_reidentify): return 0 -def call(jobs): +def get_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Identify file formats.") # Since AM19 the accepted values are "True" or "False" since the ability to @@ -215,10 +230,22 @@ def call(jobs): help="Disable identification if it has already happened for this file.", ) + return parser + + +def parse_args(parser: argparse.ArgumentParser, job: Job) -> IdentifyFileFormatArgs: + namespace = parser.parse_args(job.args[1:]) + + return IdentifyFileFormatArgs(**vars(namespace)) + + +def call(jobs: List[Job]) -> None: + parser = get_parser() + with transaction.atomic(): for job in jobs: with job.JobContext(): - args = parser.parse_args(job.args[1:]) + args = parse_args(parser, job) job.set_status( main( job, From fa9c1074a1886adbb630ac2f0f8efcc9743cb424 Mon Sep 17 00:00:00 2001 From: "Douglas Cerna (Soy Douglas)" Date: Tue, 13 Aug 2024 14:25:54 +0000 Subject: [PATCH 3/3] Extract script return codes --- .../lib/clientScripts/identify_file_format.py | 19 +++++++++------- tests/MCPClient/test_identify_file_format.py | 22 +++++++++---------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/MCPClient/lib/clientScripts/identify_file_format.py b/src/MCPClient/lib/clientScripts/identify_file_format.py index ad36a91885..24f16e1ac3 100755 --- a/src/MCPClient/lib/clientScripts/identify_file_format.py +++ b/src/MCPClient/lib/clientScripts/identify_file_format.py @@ -23,6 +23,9 @@ from main.models import FileID from main.models import UnitVariable +SUCCESS = 0 +ERROR = 255 + @dataclasses.dataclass class IdentifyFileFormatArgs: @@ -129,12 +132,12 @@ def main( enabled_bool = True if enabled == "True" else False if not enabled_bool: job.print_output("Skipping file format identification") - return 0 + return SUCCESS command = _default_idcommand() if command is None: job.write_error("Unable to determine IDCommand.\n") - return 255 + return ERROR command_uuid = command.uuid job.print_output("IDCommand:", command.description) @@ -153,7 +156,7 @@ def main( job.print_output( "This file has already been identified, and re-identification is disabled. Skipping." ) - return 0 + return SUCCESS # Save whether identification was enabled by the user for use in a later # chain. @@ -171,7 +174,7 @@ def main( if exitcode != 0: job.print_error(f"Error: IDCommand with UUID {command_uuid} exited non-zero.") job.print_error(f"Error: {err}") - return 255 + return ERROR job.print_output("Command output:", output) # PUIDs are the same regardless of tool, so PUID-producing tools don't have "rules" per se - we just @@ -187,17 +190,17 @@ def main( f'Error: No FPR identification rule for tool output "{output}" found' ) write_identification_event(file_uuid, command, success=False) - return 255 + return ERROR except IDRule.MultipleObjectsReturned: job.print_error( f'Error: Multiple FPR identification rules for tool output "{output}" found' ) write_identification_event(file_uuid, command, success=False) - return 255 + return ERROR except FormatVersion.DoesNotExist: job.print_error(f"Error: No FPR format record found for PUID {output}") write_identification_event(file_uuid, command, success=False) - return 255 + return ERROR (ffv, created) = FileFormatVersion.objects.get_or_create( file_uuid=file_, defaults={"format_version": format_version} @@ -210,7 +213,7 @@ def main( write_identification_event(file_uuid, command, format=format_version.pronom_id) write_file_id(file_uuid=file_uuid, format=format_version, output=output) - return 0 + return SUCCESS def get_parser() -> argparse.ArgumentParser: diff --git a/tests/MCPClient/test_identify_file_format.py b/tests/MCPClient/test_identify_file_format.py index 702e5c1962..2c61a2f72e 100644 --- a/tests/MCPClient/test_identify_file_format.py +++ b/tests/MCPClient/test_identify_file_format.py @@ -42,7 +42,7 @@ def test_job_skips_format_identification_explicitly(job: mock.Mock) -> None: identify_file_format.call([job]) - job.set_status.assert_called_once_with(0) + job.set_status.assert_called_once_with(identify_file_format.SUCCESS) job.print_output.assert_called_once_with("Skipping file format identification") @@ -57,7 +57,7 @@ def test_job_skips_format_identification_if_file_has_format_identification_event identify_file_format.call([job]) - job.set_status.assert_called_once_with(0) + job.set_status.assert_called_once_with(identify_file_format.SUCCESS) assert job.print_output.mock_calls == [ mock.call("IDCommand:", idcommand.description), mock.call("IDCommand UUID:", idcommand.uuid), @@ -76,7 +76,7 @@ def test_job_fails_if_identification_command_does_not_exist(job: mock.Mock) -> N identify_file_format.call([job]) - job.set_status.assert_called_once_with(255) + job.set_status.assert_called_once_with(identify_file_format.ERROR) job.write_error.assert_called_once_with("Unable to determine IDCommand.\n") @@ -92,7 +92,7 @@ def test_job_fails_if_format_identification_command_fails( identify_file_format.call([job]) - job.set_status.assert_called_once_with(255) + job.set_status.assert_called_once_with(identify_file_format.ERROR) assert job.print_error.mock_calls == [ mock.call(f"Error: IDCommand with UUID {idcommand.uuid} exited non-zero."), mock.call(f"Error: {command_error}"), @@ -117,7 +117,7 @@ def test_job_fails_if_identification_rule_does_not_exist( identify_file_format.call([job]) - job.set_status.assert_called_once_with(255) + job.set_status.assert_called_once_with(identify_file_format.ERROR) assert ( models.Event.objects.filter( file_uuid=sip_file.uuid, @@ -158,7 +158,7 @@ def test_job_fails_if_multiple_identification_rules_exist( identify_file_format.call([job]) - job.set_status.assert_called_once_with(255) + job.set_status.assert_called_once_with(identify_file_format.ERROR) assert ( models.Event.objects.filter( file_uuid=sip_file.uuid, @@ -187,7 +187,7 @@ def test_job_fails_if_format_version_does_not_exist( identify_file_format.call([job]) - job.set_status.assert_called_once_with(255) + job.set_status.assert_called_once_with(identify_file_format.ERROR) assert ( models.Event.objects.filter( file_uuid=sip_file.uuid, @@ -241,7 +241,7 @@ def test_job_adds_file_format_version( identify_file_format.call([job]) - job.set_status.assert_called_once_with(0) + job.set_status.assert_called_once_with(identify_file_format.SUCCESS) assert ( models.FileFormatVersion.objects.filter( file_uuid=sip_file, format_version=format_version @@ -278,7 +278,7 @@ def test_job_updates_file_format_version( identify_file_format.call([job]) - job.set_status.assert_called_once_with(0) + job.set_status.assert_called_once_with(identify_file_format.SUCCESS) assert ( models.FileFormatVersion.objects.filter( file_uuid=sip_file, format_version=format_version @@ -305,7 +305,7 @@ def test_job_adds_successful_format_identification_data( identify_file_format.call([job]) - job.set_status.assert_called_once_with(0) + job.set_status.assert_called_once_with(identify_file_format.SUCCESS) assert ( models.Event.objects.filter( file_uuid=sip_file.uuid, @@ -349,7 +349,7 @@ def test_job_falls_back_to_identification_rule_if_format_version_does_not_exist( identify_file_format.call([job]) - job.set_status.assert_called_once_with(0) + job.set_status.assert_called_once_with(identify_file_format.SUCCESS) assert ( models.FileID.objects.filter( file=sip_file,