Skip to content

Commit addfebb

Browse files
committed
dev: added minmax check in ResourceRequirement
1 parent aa13f7b commit addfebb

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

cwl_utils/parser/cwl_v1_2.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18131,6 +18131,14 @@ def fromDoc(
1813118131
"is not valid because:",
1813218132
)
1813318133
)
18134+
if coresMin is not None and coresMax is not None and coresMin > coresMax:
18135+
_errors__.append(
18136+
ValidationException(
18137+
"the `coresMin` field is greater than the `coresMax` field",
18138+
None
18139+
)
18140+
)
18141+
1813418142
ramMin = None
1813518143
if "ramMin" in _doc:
1813618144
try:
@@ -18225,6 +18233,14 @@ def fromDoc(
1822518233
"is not valid because:",
1822618234
)
1822718235
)
18236+
if ramMin is not None and ramMax is not None and ramMin > ramMax:
18237+
_errors__.append(
18238+
ValidationException(
18239+
"the `ramMin` field is greater than the `ramMax` field",
18240+
None
18241+
)
18242+
)
18243+
1822818244
tmpdirMin = None
1822918245
if "tmpdirMin" in _doc:
1823018246
try:
@@ -18319,6 +18335,14 @@ def fromDoc(
1831918335
"is not valid because:",
1832018336
)
1832118337
)
18338+
if tmpdirMin is not None and tmpdirMax is not None and tmpdirMin > tmpdirMax:
18339+
_errors__.append(
18340+
ValidationException(
18341+
"the `tmpdirMin` field is greater than the `tmpdirMax` field",
18342+
None
18343+
)
18344+
)
18345+
1832218346
outdirMin = None
1832318347
if "outdirMin" in _doc:
1832418348
try:
@@ -18413,6 +18437,14 @@ def fromDoc(
1841318437
"is not valid because:",
1841418438
)
1841518439
)
18440+
if outdirMin is not None and outdirMax is not None and outdirMin > outdirMax:
18441+
_errors__.append(
18442+
ValidationException(
18443+
"the `outdirMin` field is greater than the `outdirMax` field",
18444+
None
18445+
)
18446+
)
18447+
1841618448
extension_fields: dict[str, Any] = {}
1841718449
for k in _doc.keys():
1841818450
if k not in cls.attrs:
@@ -18478,6 +18510,11 @@ def save(
1847818510
r["coresMax"] = save(
1847918511
self.coresMax, top=False, base_url=base_url, relative_uris=relative_uris
1848018512
)
18513+
if r.get("coresMax") and r.get("coresMin") and r["coresMax"] < r["coresMin"]:
18514+
raise ValidationException(
18515+
"the `coresMax` field is less than the `coresMin` field"
18516+
)
18517+
1848118518
if self.ramMin is not None:
1848218519
r["ramMin"] = save(
1848318520
self.ramMin, top=False, base_url=base_url, relative_uris=relative_uris
@@ -18486,6 +18523,11 @@ def save(
1848618523
r["ramMax"] = save(
1848718524
self.ramMax, top=False, base_url=base_url, relative_uris=relative_uris
1848818525
)
18526+
if r.get("ramMax") and r.get("ramMin") and r["ramMax"] < r["ramMin"]:
18527+
raise ValidationException(
18528+
"the `ramMax` field is less than the `ramMin` field"
18529+
)
18530+
1848918531
if self.tmpdirMin is not None:
1849018532
r["tmpdirMin"] = save(
1849118533
self.tmpdirMin,
@@ -18500,6 +18542,11 @@ def save(
1850018542
base_url=base_url,
1850118543
relative_uris=relative_uris,
1850218544
)
18545+
if r.get("tmpdirMax") and r.get("tmpdirMin") and r["tmpdirMax"] < r["tmpdirMin"]:
18546+
raise ValidationException(
18547+
"the `tmpdirMax` field is less than the `tmpdirMin` field"
18548+
)
18549+
1850318550
if self.outdirMin is not None:
1850418551
r["outdirMin"] = save(
1850518552
self.outdirMin,
@@ -18514,6 +18561,10 @@ def save(
1851418561
base_url=base_url,
1851518562
relative_uris=relative_uris,
1851618563
)
18564+
if r.get("outdirMax") and r.get("outdirMin") and r["outdirMax"] < r["outdirMin"]:
18565+
raise ValidationException(
18566+
"the `outdirMax` field is less than the `outdirMin` field"
18567+
)
1851718568

1851818569
# top refers to the directory level
1851918570
if top:

tests/test_resreq_minmax.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from cwl_utils.parser.cwl_v1_2 import ResourceRequirement, WorkflowStep, Workflow, CommandLineTool, save
2+
import pytest
3+
from schema_salad.exceptions import ValidationException
4+
5+
# Helper functions
6+
def create_commandlinetool(requirements=None, inputs=None, outputs=None):
7+
return CommandLineTool(
8+
requirements=requirements or [],
9+
inputs=inputs or [],
10+
outputs=outputs or [],
11+
)
12+
13+
14+
def create_workflow(requirements=None, steps=None, inputs=None, outputs=None):
15+
return Workflow(
16+
requirements=requirements or [],
17+
steps=steps or [],
18+
inputs=inputs or [],
19+
outputs=outputs or [],
20+
)
21+
22+
23+
def create_step(requirements=None, run=None, in_=None, out=None):
24+
return WorkflowStep(
25+
requirements=requirements or [],
26+
run=run,
27+
in_=in_ or [],
28+
out=out or [],
29+
)
30+
31+
@pytest.mark.parametrize(
32+
"bad_min_max_reqs",
33+
[
34+
# cores
35+
ResourceRequirement(coresMin=4, coresMax=2),
36+
# ram
37+
ResourceRequirement(ramMin=2048, ramMax=1024),
38+
# tmpdir
39+
ResourceRequirement(tmpdirMin=1024, tmpdirMax=512),
40+
# outdir
41+
ResourceRequirement(outdirMin=512, outdirMax=256),
42+
],
43+
)
44+
def test_bad_min_max_resource_reqs(bad_min_max_reqs):
45+
"""
46+
Test invalid min/max resource requirements in CWL objects.
47+
"""
48+
49+
# CommandlineTool with bad minmax reqs
50+
clt = create_commandlinetool(requirements=[bad_min_max_reqs])
51+
with pytest.raises(ValidationException):
52+
save(clt)
53+
54+
# WorkflowStep.run with bad minmax reqs
55+
step_bad_run = create_step(run=clt)
56+
workflow = create_workflow(steps=[step_bad_run])
57+
with pytest.raises(ValidationException):
58+
save(workflow)
59+
60+
# WorkflowStep with bad minmax reqs
61+
clt = create_commandlinetool()
62+
step = create_step(run=clt, requirements=[bad_min_max_reqs])
63+
workflow = create_workflow(steps=[step])
64+
with pytest.raises(ValidationException):
65+
save(workflow)
66+
67+
# Workflow with bad minmax reqs
68+
workflow = create_workflow(requirements=[bad_min_max_reqs])
69+
with pytest.raises(ValidationException):
70+
save(workflow)
71+
72+
# NestedWorkflow with bad minmax reqs
73+
nest_workflow = create_workflow(requirements=[bad_min_max_reqs])
74+
step = create_step(run=nest_workflow)
75+
workflow = create_workflow(steps=[step])
76+
with pytest.raises(ValidationException):
77+
save(workflow)
78+
79+
# DeepNestedWorkflow with bad minmax reqs
80+
deep_workflow = create_workflow(requirements=[bad_min_max_reqs])
81+
deep_step = create_step(run=deep_workflow)
82+
nest_workflow = create_workflow(steps=[deep_step])
83+
step = create_step(run=nest_workflow)
84+
workflow = create_workflow(steps=[step])
85+
with pytest.raises(ValidationException):
86+
save(workflow)

0 commit comments

Comments
 (0)