Skip to content

Commit

Permalink
Update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
amickan committed Dec 16, 2024
1 parent 0b86ccf commit 1df4405
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 229 deletions.
1 change: 1 addition & 0 deletions app/grandchallenge/algorithms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ def clean(self):

if Job.objects.get_jobs_with_same_inputs(
inputs=cleaned_data["inputs"],
interface=cleaned_data["algorithm_interface"],
algorithm_image=cleaned_data["algorithm_image"],
algorithm_model=cleaned_data["algorithm_model"],
):
Expand Down
4 changes: 2 additions & 2 deletions app/grandchallenge/algorithms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -976,13 +976,13 @@ def retrieve_existing_civs(*, civ_data):
return existing_civs

def get_jobs_with_same_inputs(
self, *, inputs, algorithm_image, algorithm_model
self, *, inputs, interface, algorithm_image, algorithm_model
):
existing_civs = self.retrieve_existing_civs(civ_data=inputs)
unique_kwargs = {
"algorithm_image": algorithm_image,
}
input_interface_count = algorithm_image.algorithm.inputs.count()
input_interface_count = interface.inputs.count()

if algorithm_model:
unique_kwargs["algorithm_model"] = algorithm_model
Expand Down
1 change: 1 addition & 0 deletions app/grandchallenge/algorithms/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ def validate(self, data):

if Job.objects.get_jobs_with_same_inputs(
inputs=self.inputs,
interface=None, # TODO fix this in separate PR
algorithm_image=data["algorithm_image"],
algorithm_model=data["algorithm_model"],
):
Expand Down
91 changes: 68 additions & 23 deletions app/tests/algorithms_tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,10 @@ def test_create_job_input_fields(
response = get_view_for_user(
viewname="algorithms:job-create",
client=client,
reverse_kwargs={"slug": alg.slug},
reverse_kwargs={
"slug": alg.slug,
"interface": alg.default_interface.pk,
},
follow=True,
user=creator,
)
Expand Down Expand Up @@ -353,7 +356,10 @@ def test_create_job_json_input_field_validation(
response = get_view_for_user(
viewname="algorithms:job-create",
client=client,
reverse_kwargs={"slug": alg.slug},
reverse_kwargs={
"slug": alg.slug,
"interface": alg.default_interface.pk,
},
method=client.post,
follow=True,
user=creator,
Expand Down Expand Up @@ -384,7 +390,10 @@ def test_create_job_simple_input_field_validation(
response = get_view_for_user(
viewname="algorithms:job-create",
client=client,
reverse_kwargs={"slug": alg.slug},
reverse_kwargs={
"slug": alg.slug,
"interface": alg.default_interface.pk,
},
method=client.post,
follow=True,
user=creator,
Expand All @@ -400,7 +409,11 @@ def create_algorithm_with_input(slug):
VerificationFactory(user=creator, is_verified=True)
alg = AlgorithmFactory()
alg.add_editor(user=creator)
alg.inputs.set([ComponentInterface.objects.get(slug=slug)])
interface = AlgorithmInterfaceFactory(
inputs=[ComponentInterface.objects.get(slug=slug)],
outputs=[ComponentInterfaceFactory()],
)
alg.interfaces.add(interface, through_defaults={"is_default": True})
AlgorithmImageFactory(
algorithm=alg,
is_manifest_valid=True,
Expand Down Expand Up @@ -500,35 +513,53 @@ def test_only_publish_successful_jobs():

@pytest.mark.django_db
class TestJobCreateLimits:

def create_form(self, algorithm, user, algorithm_image=None):
ci = ComponentInterfaceFactory(kind=ComponentInterface.Kind.STRING)
interface = AlgorithmInterfaceFactory(inputs=[ci])
algorithm.interfaces.add(interface)

algorithm_image_kwargs = {}
if algorithm_image:
algorithm_image_kwargs = {
"algorithm_image": str(algorithm_image.pk)
}

return JobCreateForm(
algorithm=algorithm,
user=user,
interface=interface,
data={
**algorithm_image_kwargs,
**get_interface_form_data(interface_slug=ci.slug, data="Foo"),
},
)

def test_form_invalid_without_enough_credits(self, settings):
algorithm = AlgorithmFactory(
minimum_credits_per_job=(
settings.ALGORITHMS_GENERAL_CREDITS_PER_MONTH_PER_USER + 1
),
)
algorithm.inputs.clear()
user = UserFactory()
AlgorithmImageFactory(
algorithm=algorithm,
is_manifest_valid=True,
is_in_registry=True,
is_desired_version=True,
)

form = JobCreateForm(algorithm=algorithm, user=user, data={})

form = self.create_form(algorithm=algorithm, user=user)
assert not form.is_valid()
assert form.errors == {
"__all__": ["You have run out of algorithm credits"],
}
assert "You have run out of algorithm credits" in str(
form.errors["__all__"]
)

def test_form_valid_for_editor(self, settings):
algorithm = AlgorithmFactory(
minimum_credits_per_job=(
settings.ALGORITHMS_GENERAL_CREDITS_PER_MONTH_PER_USER + 1
),
)
algorithm.inputs.clear()
algorithm_image = AlgorithmImageFactory(
algorithm=algorithm,
is_manifest_valid=True,
Expand All @@ -539,17 +570,15 @@ def test_form_valid_for_editor(self, settings):

algorithm.add_editor(user=user)

form = JobCreateForm(
form = self.create_form(
algorithm=algorithm,
user=user,
data={"algorithm_image": str(algorithm_image.pk)},
algorithm_image=algorithm_image,
)

assert form.is_valid()

def test_form_valid_with_credits(self):
algorithm = AlgorithmFactory(minimum_credits_per_job=1)
algorithm.inputs.clear()
algorithm_image = AlgorithmImageFactory(
algorithm=algorithm,
is_manifest_valid=True,
Expand All @@ -558,12 +587,11 @@ def test_form_valid_with_credits(self):
)
user = UserFactory()

form = JobCreateForm(
form = self.create_form(
algorithm=algorithm,
user=user,
data={"algorithm_image": str(algorithm_image.pk)},
algorithm_image=algorithm_image,
)

assert form.is_valid()


Expand Down Expand Up @@ -710,7 +738,12 @@ def test_creator_queryset(
):
algorithm = algorithm_with_image_and_model_and_two_inputs.algorithm
editor = algorithm.editors_group.user_set.first()
form = JobCreateForm(algorithm=algorithm, user=editor, data={})
form = JobCreateForm(
algorithm=algorithm,
user=editor,
interface=algorithm.default_interface,
data={},
)
assert list(form.fields["creator"].queryset.all()) == [editor]
assert form.fields["creator"].initial == editor

Expand All @@ -726,7 +759,12 @@ def test_algorithm_image_queryset(
is_manifest_valid=True,
is_in_registry=True,
)
form = JobCreateForm(algorithm=algorithm, user=editor, data={})
form = JobCreateForm(
algorithm=algorithm,
user=editor,
interface=algorithm.default_interface,
data={},
)
ai_qs = form.fields["algorithm_image"].queryset.all()
assert algorithm.active_image in ai_qs
assert inactive_image not in ai_qs
Expand All @@ -745,12 +783,14 @@ def test_cannot_create_job_with_same_inputs_twice(
algorithm_model=algorithm.active_model,
status=Job.SUCCESS,
time_limit=123,
algorithm_interface=algorithm.default_interface,
)
job.inputs.set(civs)

form = JobCreateForm(
algorithm=algorithm,
user=editor,
interface=algorithm.default_interface,
data={
"algorithm_image": algorithm.active_image,
"algorithm_model": algorithm.active_model,
Expand All @@ -775,13 +815,18 @@ def test_all_inputs_required_on_job_creation(algorithm_with_multiple_inputs):
kind=InterfaceKind.InterfaceKindChoices.ANY,
store_in_database=True,
)
algorithm_with_multiple_inputs.algorithm.inputs.add(
ci_json_in_db_without_schema
interface = AlgorithmInterfaceFactory(
inputs=[ci_json_in_db_without_schema],
outputs=[ComponentInterfaceFactory()],
)
algorithm_with_multiple_inputs.algorithm.interfaces.add(
interface, through_defaults={"is_default": True}
)

form = JobCreateForm(
algorithm=algorithm_with_multiple_inputs.algorithm,
user=algorithm_with_multiple_inputs.editor,
interface=interface,
data={},
)

Expand Down
46 changes: 38 additions & 8 deletions app/tests/algorithms_tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,12 +656,15 @@ def test_job_with_same_image_different_model(
data = self.get_civ_data(civs=civs)

j = AlgorithmJobFactory(
algorithm_image=alg.active_image, time_limit=10
algorithm_image=alg.active_image,
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(civs)

jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=alg.active_model,
)
Expand All @@ -678,10 +681,12 @@ def test_job_with_same_model_different_image(
algorithm_image=AlgorithmImageFactory(),
algorithm_model=alg.active_model,
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(civs)
jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=alg.active_model,
)
Expand All @@ -698,10 +703,12 @@ def test_job_with_same_model_and_image(
algorithm_model=alg.active_model,
algorithm_image=alg.active_image,
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(civs)
jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=alg.active_model,
)
Expand All @@ -719,10 +726,12 @@ def test_job_with_different_image_and_model(
algorithm_model=AlgorithmModelFactory(),
algorithm_image=AlgorithmImageFactory(),
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(civs)
jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=alg.active_model,
)
Expand All @@ -739,10 +748,14 @@ def test_job_with_same_image_no_model_provided(
algorithm_model=alg.active_model,
algorithm_image=alg.active_image,
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(civs)
jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data, algorithm_image=alg.active_image, algorithm_model=None
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=None,
)
assert len(jobs) == 0

Expand All @@ -754,11 +767,16 @@ def test_job_with_same_image_and_without_model(
data = self.get_civ_data(civs=civs)

j = AlgorithmJobFactory(
algorithm_image=alg.active_image, time_limit=10
algorithm_image=alg.active_image,
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(civs)
jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data, algorithm_image=alg.active_image, algorithm_model=None
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=None,
)
assert j in jobs
assert len(jobs) == 1
Expand All @@ -771,7 +789,9 @@ def test_job_with_different_input(
data = self.get_civ_data(civs=civs)

j = AlgorithmJobFactory(
algorithm_image=alg.active_image, time_limit=10
algorithm_image=alg.active_image,
time_limit=10,
algorithm_interface=alg.default_interface,
)
j.inputs.set(
[
Expand All @@ -780,7 +800,10 @@ def test_job_with_different_input(
]
)
jobs = Job.objects.get_jobs_with_same_inputs(
inputs=data, algorithm_image=alg.active_image, algorithm_model=None
inputs=data,
interface=alg.default_interface,
algorithm_image=alg.active_image,
algorithm_model=None,
)
assert len(jobs) == 0

Expand Down Expand Up @@ -982,8 +1005,15 @@ def test_inputs_complete():
ci1, ci2, ci3 = ComponentInterfaceFactory.create_batch(
3, kind=ComponentInterface.Kind.STRING
)
alg.inputs.set([ci1, ci2, ci3])
job = AlgorithmJobFactory(algorithm_image__algorithm=alg, time_limit=10)
interface = AlgorithmInterfaceFactory(
inputs=[ci1, ci2, ci3], outputs=[ComponentInterfaceFactory()]
)
alg.interfaces.add(interface, through_defaults={"is_default": True})
job = AlgorithmJobFactory(
algorithm_image__algorithm=alg,
time_limit=10,
algorithm_interface=alg.default_interface,
)
civ_with_value_1 = ComponentInterfaceValueFactory(
interface=ci1, value="Foo"
)
Expand Down
Loading

0 comments on commit 1df4405

Please sign in to comment.