toil 5.12.0__py3-none-any.whl → 6.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- toil/__init__.py +18 -13
- toil/batchSystems/abstractBatchSystem.py +39 -13
- toil/batchSystems/abstractGridEngineBatchSystem.py +24 -24
- toil/batchSystems/awsBatch.py +14 -14
- toil/batchSystems/cleanup_support.py +7 -3
- toil/batchSystems/contained_executor.py +3 -3
- toil/batchSystems/htcondor.py +0 -1
- toil/batchSystems/kubernetes.py +34 -31
- toil/batchSystems/local_support.py +3 -1
- toil/batchSystems/lsf.py +7 -7
- toil/batchSystems/mesos/batchSystem.py +7 -7
- toil/batchSystems/options.py +32 -83
- toil/batchSystems/registry.py +104 -23
- toil/batchSystems/singleMachine.py +16 -13
- toil/batchSystems/slurm.py +87 -16
- toil/batchSystems/torque.py +0 -1
- toil/bus.py +44 -8
- toil/common.py +544 -753
- toil/cwl/__init__.py +28 -32
- toil/cwl/cwltoil.py +595 -574
- toil/cwl/utils.py +55 -10
- toil/exceptions.py +1 -1
- toil/fileStores/__init__.py +2 -2
- toil/fileStores/abstractFileStore.py +88 -14
- toil/fileStores/cachingFileStore.py +610 -549
- toil/fileStores/nonCachingFileStore.py +46 -22
- toil/job.py +182 -101
- toil/jobStores/abstractJobStore.py +161 -95
- toil/jobStores/aws/jobStore.py +23 -9
- toil/jobStores/aws/utils.py +6 -6
- toil/jobStores/fileJobStore.py +116 -18
- toil/jobStores/googleJobStore.py +16 -7
- toil/jobStores/utils.py +5 -6
- toil/leader.py +87 -56
- toil/lib/accelerators.py +10 -5
- toil/lib/aws/__init__.py +3 -14
- toil/lib/aws/ami.py +22 -9
- toil/lib/aws/iam.py +21 -13
- toil/lib/aws/session.py +2 -16
- toil/lib/aws/utils.py +4 -5
- toil/lib/compatibility.py +1 -1
- toil/lib/conversions.py +26 -3
- toil/lib/docker.py +22 -23
- toil/lib/ec2.py +10 -6
- toil/lib/ec2nodes.py +106 -100
- toil/lib/encryption/_nacl.py +2 -1
- toil/lib/generatedEC2Lists.py +325 -18
- toil/lib/io.py +49 -2
- toil/lib/misc.py +1 -1
- toil/lib/resources.py +9 -2
- toil/lib/threading.py +101 -38
- toil/options/common.py +736 -0
- toil/options/cwl.py +336 -0
- toil/options/wdl.py +37 -0
- toil/provisioners/abstractProvisioner.py +9 -4
- toil/provisioners/aws/__init__.py +3 -6
- toil/provisioners/aws/awsProvisioner.py +6 -0
- toil/provisioners/clusterScaler.py +3 -2
- toil/provisioners/gceProvisioner.py +2 -2
- toil/realtimeLogger.py +2 -1
- toil/resource.py +24 -18
- toil/server/app.py +2 -3
- toil/server/cli/wes_cwl_runner.py +4 -4
- toil/server/utils.py +1 -1
- toil/server/wes/abstract_backend.py +3 -2
- toil/server/wes/amazon_wes_utils.py +5 -4
- toil/server/wes/tasks.py +2 -3
- toil/server/wes/toil_backend.py +2 -10
- toil/server/wsgi_app.py +2 -0
- toil/serviceManager.py +12 -10
- toil/statsAndLogging.py +41 -9
- toil/test/__init__.py +29 -54
- toil/test/batchSystems/batchSystemTest.py +11 -111
- toil/test/batchSystems/test_slurm.py +24 -8
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +58 -0
- toil/test/cwl/cwlTest.py +438 -223
- toil/test/cwl/glob_dir.cwl +15 -0
- toil/test/cwl/preemptible.cwl +21 -0
- toil/test/cwl/preemptible_expression.cwl +28 -0
- toil/test/cwl/revsort.cwl +1 -1
- toil/test/cwl/revsort2.cwl +1 -1
- toil/test/docs/scriptsTest.py +2 -3
- toil/test/jobStores/jobStoreTest.py +34 -21
- toil/test/lib/aws/test_iam.py +4 -14
- toil/test/lib/aws/test_utils.py +0 -3
- toil/test/lib/dockerTest.py +4 -4
- toil/test/lib/test_ec2.py +12 -17
- toil/test/mesos/helloWorld.py +4 -5
- toil/test/mesos/stress.py +1 -1
- toil/test/{wdl/conftest.py → options/__init__.py} +0 -10
- toil/test/options/options.py +37 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
- toil/test/provisioners/clusterScalerTest.py +6 -4
- toil/test/provisioners/clusterTest.py +23 -11
- toil/test/provisioners/gceProvisionerTest.py +0 -6
- toil/test/provisioners/restartScript.py +3 -2
- toil/test/server/serverTest.py +1 -1
- toil/test/sort/restart_sort.py +2 -1
- toil/test/sort/sort.py +2 -1
- toil/test/sort/sortTest.py +2 -13
- toil/test/src/autoDeploymentTest.py +45 -45
- toil/test/src/busTest.py +5 -5
- toil/test/src/checkpointTest.py +2 -2
- toil/test/src/deferredFunctionTest.py +1 -1
- toil/test/src/fileStoreTest.py +32 -16
- toil/test/src/helloWorldTest.py +1 -1
- toil/test/src/importExportFileTest.py +1 -1
- toil/test/src/jobDescriptionTest.py +2 -1
- toil/test/src/jobServiceTest.py +1 -1
- toil/test/src/jobTest.py +18 -18
- toil/test/src/miscTests.py +5 -3
- toil/test/src/promisedRequirementTest.py +3 -3
- toil/test/src/realtimeLoggerTest.py +1 -1
- toil/test/src/resourceTest.py +2 -2
- toil/test/src/restartDAGTest.py +1 -1
- toil/test/src/resumabilityTest.py +36 -2
- toil/test/src/retainTempDirTest.py +1 -1
- toil/test/src/systemTest.py +2 -2
- toil/test/src/toilContextManagerTest.py +2 -2
- toil/test/src/userDefinedJobArgTypeTest.py +1 -1
- toil/test/utils/toilDebugTest.py +98 -32
- toil/test/utils/toilKillTest.py +2 -2
- toil/test/utils/utilsTest.py +23 -3
- toil/test/wdl/wdltoil_test.py +223 -45
- toil/toilState.py +7 -6
- toil/utils/toilClean.py +1 -1
- toil/utils/toilConfig.py +36 -0
- toil/utils/toilDebugFile.py +60 -33
- toil/utils/toilDebugJob.py +39 -12
- toil/utils/toilDestroyCluster.py +1 -1
- toil/utils/toilKill.py +1 -1
- toil/utils/toilLaunchCluster.py +13 -2
- toil/utils/toilMain.py +3 -2
- toil/utils/toilRsyncCluster.py +1 -1
- toil/utils/toilSshCluster.py +1 -1
- toil/utils/toilStats.py +445 -305
- toil/utils/toilStatus.py +2 -5
- toil/version.py +10 -10
- toil/wdl/utils.py +2 -122
- toil/wdl/wdltoil.py +1257 -492
- toil/worker.py +55 -46
- toil-6.1.0.dist-info/METADATA +124 -0
- toil-6.1.0.dist-info/RECORD +241 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/WHEEL +1 -1
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/entry_points.txt +0 -1
- toil/batchSystems/parasol.py +0 -379
- toil/batchSystems/tes.py +0 -459
- toil/test/batchSystems/parasolTestSupport.py +0 -117
- toil/test/wdl/builtinTest.py +0 -506
- toil/test/wdl/toilwdlTest.py +0 -522
- toil/wdl/toilwdl.py +0 -141
- toil/wdl/versions/dev.py +0 -107
- toil/wdl/versions/draft2.py +0 -980
- toil/wdl/versions/v1.py +0 -794
- toil/wdl/wdl_analysis.py +0 -116
- toil/wdl/wdl_functions.py +0 -997
- toil/wdl/wdl_synthesis.py +0 -1011
- toil/wdl/wdl_types.py +0 -243
- toil-5.12.0.dist-info/METADATA +0 -118
- toil-5.12.0.dist-info/RECORD +0 -244
- /toil/{wdl/versions → options}/__init__.py +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/LICENSE +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/top_level.txt +0 -0
toil/test/cwl/cwlTest.py
CHANGED
|
@@ -17,6 +17,7 @@ import logging
|
|
|
17
17
|
import os
|
|
18
18
|
import re
|
|
19
19
|
import shutil
|
|
20
|
+
import stat
|
|
20
21
|
import subprocess
|
|
21
22
|
import sys
|
|
22
23
|
import unittest
|
|
@@ -25,25 +26,36 @@ import zipfile
|
|
|
25
26
|
from functools import partial
|
|
26
27
|
from io import StringIO
|
|
27
28
|
from pathlib import Path
|
|
28
|
-
from typing import
|
|
29
|
+
from typing import (TYPE_CHECKING,
|
|
30
|
+
Any,
|
|
31
|
+
Callable,
|
|
32
|
+
Dict,
|
|
33
|
+
List,
|
|
34
|
+
MutableMapping,
|
|
35
|
+
Optional,
|
|
36
|
+
cast)
|
|
29
37
|
from unittest.mock import Mock, call
|
|
30
38
|
from urllib.request import urlretrieve
|
|
31
39
|
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from cwltool.utils import CWLObjectType
|
|
42
|
+
|
|
32
43
|
import pytest
|
|
33
44
|
|
|
34
45
|
pkg_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) # noqa
|
|
35
46
|
sys.path.insert(0, pkg_root) # noqa
|
|
36
47
|
|
|
37
|
-
from
|
|
48
|
+
from schema_salad.exceptions import ValidationException
|
|
49
|
+
|
|
50
|
+
from toil.cwl.utils import (DirectoryStructure,
|
|
51
|
+
download_structure,
|
|
38
52
|
visit_cwl_class_and_reduce,
|
|
39
53
|
visit_top_cwl_class)
|
|
40
54
|
from toil.exceptions import FailedJobsException
|
|
41
55
|
from toil.fileStores import FileID
|
|
42
56
|
from toil.fileStores.abstractFileStore import AbstractFileStore
|
|
43
|
-
from toil.lib.aws import zone_to_region
|
|
44
57
|
from toil.lib.threading import cpu_count
|
|
45
58
|
from toil.provisioners import cluster_factory
|
|
46
|
-
from toil.provisioners.aws import get_best_aws_zone
|
|
47
59
|
from toil.test import (ToilTest,
|
|
48
60
|
needs_aws_ec2,
|
|
49
61
|
needs_aws_s3,
|
|
@@ -57,17 +69,15 @@ from toil.test import (ToilTest,
|
|
|
57
69
|
needs_local_cuda,
|
|
58
70
|
needs_lsf,
|
|
59
71
|
needs_mesos,
|
|
60
|
-
|
|
72
|
+
needs_online,
|
|
61
73
|
needs_slurm,
|
|
62
74
|
needs_torque,
|
|
63
75
|
needs_wes_server,
|
|
64
76
|
slow)
|
|
65
|
-
from toil.test.provisioners.aws.awsProvisionerTest import \
|
|
66
|
-
AbstractAWSAutoscaleTest
|
|
67
77
|
from toil.test.provisioners.clusterTest import AbstractClusterTest
|
|
68
78
|
|
|
69
79
|
log = logging.getLogger(__name__)
|
|
70
|
-
CONFORMANCE_TEST_TIMEOUT =
|
|
80
|
+
CONFORMANCE_TEST_TIMEOUT = 10000
|
|
71
81
|
|
|
72
82
|
|
|
73
83
|
def run_conformance_tests(
|
|
@@ -75,14 +85,14 @@ def run_conformance_tests(
|
|
|
75
85
|
yml: str,
|
|
76
86
|
runner: Optional[str] = None,
|
|
77
87
|
caching: bool = False,
|
|
78
|
-
batchSystem: str = None,
|
|
79
|
-
selected_tests: str = None,
|
|
80
|
-
selected_tags: str = None,
|
|
81
|
-
skipped_tests: str = None,
|
|
88
|
+
batchSystem: Optional[str] = None,
|
|
89
|
+
selected_tests: Optional[str] = None,
|
|
90
|
+
selected_tags: Optional[str] = None,
|
|
91
|
+
skipped_tests: Optional[str] = None,
|
|
82
92
|
extra_args: Optional[List[str]] = None,
|
|
83
93
|
must_support_all_features: bool = False,
|
|
84
94
|
junit_file: Optional[str] = None,
|
|
85
|
-
):
|
|
95
|
+
) -> None:
|
|
86
96
|
"""
|
|
87
97
|
Run the CWL conformance tests.
|
|
88
98
|
|
|
@@ -137,10 +147,12 @@ def run_conformance_tests(
|
|
|
137
147
|
"--logDebug",
|
|
138
148
|
"--statusWait=10",
|
|
139
149
|
"--retryCount=2",
|
|
150
|
+
"--relax-path-checks",
|
|
151
|
+
# Defaults to 20s but we can't start hundreds of nodejs processes that fast on our CI potatoes
|
|
152
|
+
"--eval-timeout=600",
|
|
153
|
+
f"--caching={caching}"
|
|
140
154
|
]
|
|
141
155
|
|
|
142
|
-
args_passed_directly_to_runner.append(f"--caching={caching}")
|
|
143
|
-
|
|
144
156
|
if extra_args:
|
|
145
157
|
args_passed_directly_to_runner += extra_args
|
|
146
158
|
|
|
@@ -149,6 +161,10 @@ def run_conformance_tests(
|
|
|
149
161
|
"--setEnv=SINGULARITY_DOCKER_HUB_MIRROR"
|
|
150
162
|
)
|
|
151
163
|
|
|
164
|
+
if batchSystem is None or batchSystem == "single_machine":
|
|
165
|
+
# Make sure we can run on small machines
|
|
166
|
+
args_passed_directly_to_runner.append("--scale=0.1")
|
|
167
|
+
|
|
152
168
|
job_store_override = None
|
|
153
169
|
|
|
154
170
|
if batchSystem == "kubernetes":
|
|
@@ -159,7 +175,8 @@ def run_conformance_tests(
|
|
|
159
175
|
else:
|
|
160
176
|
# Run tests in parallel on the local machine. Don't run too many
|
|
161
177
|
# tests at once; we want at least a couple cores for each.
|
|
162
|
-
|
|
178
|
+
# But we need to have at least a few going in parallel or we risk hitting our timeout.
|
|
179
|
+
parallel_tests = max(int(cpu_count() / 2), 4)
|
|
163
180
|
cmd.append(f"-j{parallel_tests}")
|
|
164
181
|
|
|
165
182
|
if batchSystem:
|
|
@@ -193,6 +210,8 @@ def run_conformance_tests(
|
|
|
193
210
|
raise e
|
|
194
211
|
|
|
195
212
|
|
|
213
|
+
TesterFuncType = Callable[[str, str, "CWLObjectType"], None]
|
|
214
|
+
|
|
196
215
|
@needs_cwl
|
|
197
216
|
class CWLWorkflowTest(ToilTest):
|
|
198
217
|
"""
|
|
@@ -201,27 +220,53 @@ class CWLWorkflowTest(ToilTest):
|
|
|
201
220
|
inputs.
|
|
202
221
|
"""
|
|
203
222
|
|
|
204
|
-
def setUp(self):
|
|
223
|
+
def setUp(self) -> None:
|
|
205
224
|
"""Runs anew before each test to create farm fresh temp dirs."""
|
|
206
225
|
self.outDir = f"/tmp/toil-cwl-test-{str(uuid.uuid4())}"
|
|
207
226
|
os.makedirs(self.outDir)
|
|
208
227
|
self.rootDir = self._projectRootPath()
|
|
209
228
|
|
|
210
|
-
def tearDown(self):
|
|
229
|
+
def tearDown(self) -> None:
|
|
211
230
|
"""Clean up outputs."""
|
|
212
231
|
if os.path.exists(self.outDir):
|
|
213
232
|
shutil.rmtree(self.outDir)
|
|
214
233
|
unittest.TestCase.tearDown(self)
|
|
215
234
|
|
|
216
|
-
def
|
|
235
|
+
def test_cwl_cmdline_input(self) -> None:
|
|
236
|
+
"""
|
|
237
|
+
Test that running a CWL workflow with inputs specified on the command line passes.
|
|
238
|
+
"""
|
|
239
|
+
from toil.cwl import cwltoil
|
|
240
|
+
cwlfile = "src/toil/test/cwl/conditional_wf.cwl"
|
|
241
|
+
args = [cwlfile, "--message", "str", "--sleep", "2"]
|
|
242
|
+
st = StringIO()
|
|
243
|
+
# If the workflow runs, it must have had options
|
|
244
|
+
cwltoil.main(args, stdout=st)
|
|
245
|
+
|
|
246
|
+
def _tester(
|
|
247
|
+
self,
|
|
248
|
+
cwlfile: str,
|
|
249
|
+
jobfile: str,
|
|
250
|
+
expect: "CWLObjectType",
|
|
251
|
+
main_args: List[str] = [],
|
|
252
|
+
out_name: str = "output",
|
|
253
|
+
output_here: bool = False,
|
|
254
|
+
) -> None:
|
|
217
255
|
from toil.cwl import cwltoil
|
|
218
256
|
|
|
219
257
|
st = StringIO()
|
|
220
258
|
main_args = main_args[:]
|
|
259
|
+
if not output_here:
|
|
260
|
+
# Don't just dump output in the working directory.
|
|
261
|
+
main_args.extend(
|
|
262
|
+
[
|
|
263
|
+
"--logDebug",
|
|
264
|
+
"--outdir",
|
|
265
|
+
self.outDir
|
|
266
|
+
]
|
|
267
|
+
)
|
|
221
268
|
main_args.extend(
|
|
222
269
|
[
|
|
223
|
-
"--outdir",
|
|
224
|
-
self.outDir,
|
|
225
270
|
os.path.join(self.rootDir, cwlfile),
|
|
226
271
|
os.path.join(self.rootDir, jobfile),
|
|
227
272
|
]
|
|
@@ -233,7 +278,16 @@ class CWLWorkflowTest(ToilTest):
|
|
|
233
278
|
out.get(out_name, {}).pop("nameroot", None)
|
|
234
279
|
self.assertEqual(out, expect)
|
|
235
280
|
|
|
236
|
-
|
|
281
|
+
for k, v in expect.items():
|
|
282
|
+
if isinstance(v, dict) and "class" in v and v["class"] == "File" and "path" in v:
|
|
283
|
+
# This is a top-level output file.
|
|
284
|
+
# None of our output files should be executable.
|
|
285
|
+
self.assertTrue(os.path.exists(v["path"]))
|
|
286
|
+
self.assertFalse(os.stat(v["path"]).st_mode & stat.S_IXUSR)
|
|
287
|
+
|
|
288
|
+
def _debug_worker_tester(
|
|
289
|
+
self, cwlfile: str, jobfile: str, expect: "CWLObjectType"
|
|
290
|
+
) -> None:
|
|
237
291
|
from toil.cwl import cwltoil
|
|
238
292
|
|
|
239
293
|
st = StringIO()
|
|
@@ -253,21 +307,21 @@ class CWLWorkflowTest(ToilTest):
|
|
|
253
307
|
out["output"].pop("nameroot", None)
|
|
254
308
|
self.assertEqual(out, expect)
|
|
255
309
|
|
|
256
|
-
def revsort(self, cwl_filename, tester_fn):
|
|
310
|
+
def revsort(self, cwl_filename: str, tester_fn: TesterFuncType) -> None:
|
|
257
311
|
tester_fn(
|
|
258
312
|
"src/toil/test/cwl/" + cwl_filename,
|
|
259
313
|
"src/toil/test/cwl/revsort-job.json",
|
|
260
314
|
self._expected_revsort_output(self.outDir),
|
|
261
315
|
)
|
|
262
316
|
|
|
263
|
-
def revsort_no_checksum(self, cwl_filename, tester_fn):
|
|
317
|
+
def revsort_no_checksum(self, cwl_filename: str, tester_fn: TesterFuncType) -> None:
|
|
264
318
|
tester_fn(
|
|
265
319
|
"src/toil/test/cwl/" + cwl_filename,
|
|
266
320
|
"src/toil/test/cwl/revsort-job.json",
|
|
267
321
|
self._expected_revsort_nochecksum_output(self.outDir),
|
|
268
322
|
)
|
|
269
323
|
|
|
270
|
-
def download(self, inputs, tester_fn):
|
|
324
|
+
def download(self, inputs: str, tester_fn: TesterFuncType) -> None:
|
|
271
325
|
input_location = os.path.join("src/toil/test/cwl", inputs)
|
|
272
326
|
tester_fn(
|
|
273
327
|
"src/toil/test/cwl/download.cwl",
|
|
@@ -275,7 +329,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
275
329
|
self._expected_download_output(self.outDir),
|
|
276
330
|
)
|
|
277
331
|
|
|
278
|
-
def load_contents(self, inputs, tester_fn):
|
|
332
|
+
def load_contents(self, inputs: str, tester_fn: TesterFuncType) -> None:
|
|
279
333
|
input_location = os.path.join("src/toil/test/cwl", inputs)
|
|
280
334
|
tester_fn(
|
|
281
335
|
"src/toil/test/cwl/load_contents.cwl",
|
|
@@ -283,7 +337,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
283
337
|
self._expected_load_contents_output(self.outDir),
|
|
284
338
|
)
|
|
285
339
|
|
|
286
|
-
def download_directory(self, inputs, tester_fn):
|
|
340
|
+
def download_directory(self, inputs: str, tester_fn: TesterFuncType) -> None:
|
|
287
341
|
input_location = os.path.join("src/toil/test/cwl", inputs)
|
|
288
342
|
tester_fn(
|
|
289
343
|
"src/toil/test/cwl/download_directory.cwl",
|
|
@@ -291,7 +345,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
291
345
|
self._expected_download_output(self.outDir),
|
|
292
346
|
)
|
|
293
347
|
|
|
294
|
-
def download_subdirectory(self, inputs, tester_fn):
|
|
348
|
+
def download_subdirectory(self, inputs: str, tester_fn: TesterFuncType) -> None:
|
|
295
349
|
input_location = os.path.join("src/toil/test/cwl", inputs)
|
|
296
350
|
tester_fn(
|
|
297
351
|
"src/toil/test/cwl/download_subdirectory.cwl",
|
|
@@ -299,7 +353,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
299
353
|
self._expected_download_output(self.outDir),
|
|
300
354
|
)
|
|
301
355
|
|
|
302
|
-
def test_mpi(self):
|
|
356
|
+
def test_mpi(self) -> None:
|
|
303
357
|
from toil.cwl import cwltoil
|
|
304
358
|
|
|
305
359
|
stdout = StringIO()
|
|
@@ -324,7 +378,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
324
378
|
self.assertTrue(isinstance(two_pids[1], int))
|
|
325
379
|
|
|
326
380
|
@needs_aws_s3
|
|
327
|
-
def test_s3_as_secondary_file(self):
|
|
381
|
+
def test_s3_as_secondary_file(self) -> None:
|
|
328
382
|
from toil.cwl import cwltoil
|
|
329
383
|
|
|
330
384
|
stdout = StringIO()
|
|
@@ -343,21 +397,21 @@ class CWLWorkflowTest(ToilTest):
|
|
|
343
397
|
with open(out["output"]["location"][len("file://") :]) as f:
|
|
344
398
|
self.assertEqual(f.read().strip(), "When is s4 coming out?")
|
|
345
399
|
|
|
346
|
-
def test_run_revsort(self):
|
|
400
|
+
def test_run_revsort(self) -> None:
|
|
347
401
|
self.revsort("revsort.cwl", self._tester)
|
|
348
402
|
|
|
349
|
-
def test_run_revsort_nochecksum(self):
|
|
403
|
+
def test_run_revsort_nochecksum(self) -> None:
|
|
350
404
|
self.revsort_no_checksum(
|
|
351
405
|
"revsort.cwl", partial(self._tester, main_args=["--no-compute-checksum"])
|
|
352
406
|
)
|
|
353
407
|
|
|
354
|
-
def test_run_revsort2(self):
|
|
408
|
+
def test_run_revsort2(self) -> None:
|
|
355
409
|
self.revsort("revsort2.cwl", self._tester)
|
|
356
410
|
|
|
357
|
-
def test_run_revsort_debug_worker(self):
|
|
411
|
+
def test_run_revsort_debug_worker(self) -> None:
|
|
358
412
|
self.revsort("revsort.cwl", self._debug_worker_tester)
|
|
359
413
|
|
|
360
|
-
def test_run_colon_output(self):
|
|
414
|
+
def test_run_colon_output(self) -> None:
|
|
361
415
|
self._tester(
|
|
362
416
|
"src/toil/test/cwl/colon_test_output.cwl",
|
|
363
417
|
"src/toil/test/cwl/colon_test_output_job.yaml",
|
|
@@ -365,50 +419,78 @@ class CWLWorkflowTest(ToilTest):
|
|
|
365
419
|
out_name="result",
|
|
366
420
|
)
|
|
367
421
|
|
|
422
|
+
def test_glob_dir_bypass_file_store(self) -> None:
|
|
423
|
+
self.maxDiff = 1000
|
|
424
|
+
try:
|
|
425
|
+
# We need to output to the current directory to make sure that
|
|
426
|
+
# works.
|
|
427
|
+
self._tester(
|
|
428
|
+
"src/toil/test/cwl/glob_dir.cwl",
|
|
429
|
+
"src/toil/test/cwl/empty.json",
|
|
430
|
+
self._expected_glob_dir_output(os.getcwd()),
|
|
431
|
+
main_args=["--bypass-file-store"],
|
|
432
|
+
output_here=True
|
|
433
|
+
)
|
|
434
|
+
finally:
|
|
435
|
+
# Clean up anything we made in the current directory.
|
|
436
|
+
try:
|
|
437
|
+
shutil.rmtree(os.path.join(os.getcwd(), "shouldmake"))
|
|
438
|
+
except FileNotFoundError:
|
|
439
|
+
pass
|
|
440
|
+
|
|
368
441
|
@needs_aws_s3
|
|
369
|
-
def test_download_s3(self):
|
|
442
|
+
def test_download_s3(self) -> None:
|
|
370
443
|
self.download("download_s3.json", self._tester)
|
|
371
444
|
|
|
372
|
-
def test_download_http(self):
|
|
445
|
+
def test_download_http(self) -> None:
|
|
373
446
|
self.download("download_http.json", self._tester)
|
|
374
447
|
|
|
375
|
-
def test_download_https(self):
|
|
448
|
+
def test_download_https(self) -> None:
|
|
376
449
|
self.download("download_https.json", self._tester)
|
|
377
450
|
|
|
378
|
-
def
|
|
451
|
+
def test_download_https_reference(self) -> None:
|
|
452
|
+
self.download("download_https.json", partial(self._tester, main_args=["--reference-inputs"]))
|
|
453
|
+
|
|
454
|
+
def test_download_file(self) -> None:
|
|
379
455
|
self.download("download_file.json", self._tester)
|
|
380
456
|
|
|
381
457
|
@needs_aws_s3
|
|
382
|
-
def test_download_directory_s3(self):
|
|
458
|
+
def test_download_directory_s3(self) -> None:
|
|
383
459
|
self.download_directory("download_directory_s3.json", self._tester)
|
|
384
460
|
|
|
385
|
-
|
|
461
|
+
@needs_aws_s3
|
|
462
|
+
def test_download_directory_s3_reference(self) -> None:
|
|
463
|
+
self.download_directory("download_directory_s3.json", partial(self._tester, main_args=["--reference-inputs"]))
|
|
464
|
+
|
|
465
|
+
def test_download_directory_file(self) -> None:
|
|
386
466
|
self.download_directory("download_directory_file.json", self._tester)
|
|
387
467
|
|
|
388
468
|
@needs_aws_s3
|
|
389
|
-
def test_download_subdirectory_s3(self):
|
|
469
|
+
def test_download_subdirectory_s3(self) -> None:
|
|
390
470
|
self.download_subdirectory("download_subdirectory_s3.json", self._tester)
|
|
391
471
|
|
|
392
|
-
def test_download_subdirectory_file(self):
|
|
472
|
+
def test_download_subdirectory_file(self) -> None:
|
|
393
473
|
self.download_subdirectory("download_subdirectory_file.json", self._tester)
|
|
394
474
|
|
|
395
475
|
# We also want to make sure we can run a bare tool with loadContents on the inputs, which requires accessing the input data early in the leader.
|
|
396
476
|
|
|
397
477
|
@needs_aws_s3
|
|
398
|
-
def test_load_contents_s3(self):
|
|
478
|
+
def test_load_contents_s3(self) -> None:
|
|
399
479
|
self.load_contents("download_s3.json", self._tester)
|
|
400
480
|
|
|
401
|
-
def test_load_contents_http(self):
|
|
481
|
+
def test_load_contents_http(self) -> None:
|
|
402
482
|
self.load_contents("download_http.json", self._tester)
|
|
403
483
|
|
|
404
|
-
def test_load_contents_https(self):
|
|
484
|
+
def test_load_contents_https(self) -> None:
|
|
405
485
|
self.load_contents("download_https.json", self._tester)
|
|
406
486
|
|
|
407
|
-
def test_load_contents_file(self):
|
|
487
|
+
def test_load_contents_file(self) -> None:
|
|
408
488
|
self.load_contents("download_file.json", self._tester)
|
|
409
489
|
|
|
410
490
|
@slow
|
|
411
|
-
|
|
491
|
+
@pytest.mark.integrative
|
|
492
|
+
@unittest.skip("Fails too often due to remote service")
|
|
493
|
+
def test_bioconda(self) -> None:
|
|
412
494
|
self._tester(
|
|
413
495
|
"src/toil/test/cwl/seqtk_seq.cwl",
|
|
414
496
|
"src/toil/test/cwl/seqtk_seq_job.json",
|
|
@@ -418,7 +500,19 @@ class CWLWorkflowTest(ToilTest):
|
|
|
418
500
|
)
|
|
419
501
|
|
|
420
502
|
@needs_docker
|
|
421
|
-
def
|
|
503
|
+
def test_default_args(self) -> None:
|
|
504
|
+
self._tester(
|
|
505
|
+
"src/toil/test/cwl/seqtk_seq.cwl",
|
|
506
|
+
"src/toil/test/cwl/seqtk_seq_job.json",
|
|
507
|
+
self._expected_seqtk_output(self.outDir),
|
|
508
|
+
main_args=["--default-container", "quay.io/biocontainers/seqtk:r93--0"],
|
|
509
|
+
out_name="output1",
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
@needs_docker
|
|
513
|
+
@pytest.mark.integrative
|
|
514
|
+
@unittest.skip("Fails too often due to remote service")
|
|
515
|
+
def test_biocontainers(self) -> None:
|
|
422
516
|
self._tester(
|
|
423
517
|
"src/toil/test/cwl/seqtk_seq.cwl",
|
|
424
518
|
"src/toil/test/cwl/seqtk_seq_job.json",
|
|
@@ -430,7 +524,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
430
524
|
@needs_docker
|
|
431
525
|
@needs_docker_cuda
|
|
432
526
|
@needs_local_cuda
|
|
433
|
-
def test_cuda(self):
|
|
527
|
+
def test_cuda(self) -> None:
|
|
434
528
|
self._tester(
|
|
435
529
|
"src/toil/test/cwl/nvidia_smi.cwl",
|
|
436
530
|
"src/toil/test/cwl/empty.json",
|
|
@@ -439,7 +533,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
439
533
|
)
|
|
440
534
|
|
|
441
535
|
@slow
|
|
442
|
-
def test_restart(self):
|
|
536
|
+
def test_restart(self) -> None:
|
|
443
537
|
"""
|
|
444
538
|
Enable restarts with toil-cwl-runner -- run failing test, re-run correct test.
|
|
445
539
|
Only implemented for single machine.
|
|
@@ -468,7 +562,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
468
562
|
][-1]
|
|
469
563
|
os.symlink(os.path.join(cal_path, "date"), f'{os.path.join(outDir, "rev")}')
|
|
470
564
|
|
|
471
|
-
def path_with_bogus_rev():
|
|
565
|
+
def path_with_bogus_rev() -> str:
|
|
472
566
|
# append to the front of the PATH so that we check there first
|
|
473
567
|
return f"{outDir}:" + os.environ["PATH"]
|
|
474
568
|
|
|
@@ -491,7 +585,7 @@ class CWLWorkflowTest(ToilTest):
|
|
|
491
585
|
pass
|
|
492
586
|
|
|
493
587
|
@needs_aws_s3
|
|
494
|
-
def test_streamable(self):
|
|
588
|
+
def test_streamable(self, extra_args: Optional[List[str]] = None) -> None:
|
|
495
589
|
"""
|
|
496
590
|
Test that a file with 'streamable'=True is a named pipe.
|
|
497
591
|
This is a CWL1.2 feature.
|
|
@@ -504,12 +598,16 @@ class CWLWorkflowTest(ToilTest):
|
|
|
504
598
|
|
|
505
599
|
st = StringIO()
|
|
506
600
|
args = [
|
|
601
|
+
"--logDebug",
|
|
507
602
|
"--outdir",
|
|
508
603
|
self.outDir,
|
|
509
604
|
jobstore,
|
|
510
605
|
os.path.join(self.rootDir, cwlfile),
|
|
511
606
|
os.path.join(self.rootDir, jobfile),
|
|
512
607
|
]
|
|
608
|
+
if extra_args:
|
|
609
|
+
args = extra_args + args
|
|
610
|
+
log.info("Run CWL run: %s", " ".join(args))
|
|
513
611
|
cwltoil.main(args, stdout=st)
|
|
514
612
|
out = json.loads(st.getvalue())
|
|
515
613
|
out[out_name].pop("http://commonwl.org/cwltool#generation", None)
|
|
@@ -519,12 +617,68 @@ class CWLWorkflowTest(ToilTest):
|
|
|
519
617
|
with open(out[out_name]["location"][len("file://") :]) as f:
|
|
520
618
|
self.assertEqual(f.read().strip(), "When is s4 coming out?")
|
|
521
619
|
|
|
620
|
+
@needs_aws_s3
|
|
621
|
+
def test_streamable_reference(self) -> None:
|
|
622
|
+
"""
|
|
623
|
+
Test that a streamable file is a stream even when passed around by URI.
|
|
624
|
+
"""
|
|
625
|
+
self.test_streamable(extra_args=["--reference-inputs"])
|
|
626
|
+
|
|
627
|
+
def test_preemptible(self) -> None:
|
|
628
|
+
"""
|
|
629
|
+
Tests that the http://arvados.org/cwl#UsePreemptible extension is supported.
|
|
630
|
+
"""
|
|
631
|
+
cwlfile = "src/toil/test/cwl/preemptible.cwl"
|
|
632
|
+
jobfile = "src/toil/test/cwl/empty.json"
|
|
633
|
+
out_name = "output"
|
|
634
|
+
from toil.cwl import cwltoil
|
|
635
|
+
|
|
636
|
+
st = StringIO()
|
|
637
|
+
args = [
|
|
638
|
+
"--outdir",
|
|
639
|
+
self.outDir,
|
|
640
|
+
os.path.join(self.rootDir, cwlfile),
|
|
641
|
+
os.path.join(self.rootDir, jobfile),
|
|
642
|
+
]
|
|
643
|
+
cwltoil.main(args, stdout=st)
|
|
644
|
+
out = json.loads(st.getvalue())
|
|
645
|
+
out[out_name].pop("http://commonwl.org/cwltool#generation", None)
|
|
646
|
+
out[out_name].pop("nameext", None)
|
|
647
|
+
out[out_name].pop("nameroot", None)
|
|
648
|
+
with open(out[out_name]["location"][len("file://") :]) as f:
|
|
649
|
+
self.assertEqual(f.read().strip(), "hello")
|
|
650
|
+
|
|
651
|
+
def test_preemptible_expression(self) -> None:
|
|
652
|
+
"""
|
|
653
|
+
Tests that the http://arvados.org/cwl#UsePreemptible extension is validated.
|
|
654
|
+
"""
|
|
655
|
+
cwlfile = "src/toil/test/cwl/preemptible_expression.cwl"
|
|
656
|
+
jobfile = "src/toil/test/cwl/preemptible_expression.json"
|
|
657
|
+
from toil.cwl import cwltoil
|
|
658
|
+
|
|
659
|
+
st = StringIO()
|
|
660
|
+
args = [
|
|
661
|
+
"--outdir",
|
|
662
|
+
self.outDir,
|
|
663
|
+
os.path.join(self.rootDir, cwlfile),
|
|
664
|
+
os.path.join(self.rootDir, jobfile),
|
|
665
|
+
]
|
|
666
|
+
try:
|
|
667
|
+
cwltoil.main(args, stdout=st)
|
|
668
|
+
raise RuntimeError("Did not raise correct exception")
|
|
669
|
+
except ValidationException as e:
|
|
670
|
+
# Make sure we chastise the user appropriately.
|
|
671
|
+
assert "expressions are not allowed" in str(e)
|
|
672
|
+
|
|
673
|
+
|
|
522
674
|
@staticmethod
|
|
523
|
-
def _expected_seqtk_output(outDir):
|
|
524
|
-
|
|
675
|
+
def _expected_seqtk_output(outDir: str) -> "CWLObjectType":
|
|
676
|
+
path = os.path.join(outDir, "out")
|
|
677
|
+
loc = "file://" + path
|
|
525
678
|
return {
|
|
526
679
|
"output1": {
|
|
527
680
|
"location": loc,
|
|
681
|
+
"path": path,
|
|
528
682
|
"checksum": "sha1$322e001e5a99f19abdce9f02ad0f02a17b5066c2",
|
|
529
683
|
"basename": "out",
|
|
530
684
|
"class": "File",
|
|
@@ -533,11 +687,13 @@ class CWLWorkflowTest(ToilTest):
|
|
|
533
687
|
}
|
|
534
688
|
|
|
535
689
|
@staticmethod
|
|
536
|
-
def _expected_revsort_output(outDir):
|
|
537
|
-
|
|
690
|
+
def _expected_revsort_output(outDir: str) -> "CWLObjectType":
|
|
691
|
+
path = os.path.join(outDir, "output.txt")
|
|
692
|
+
loc = "file://" + path
|
|
538
693
|
return {
|
|
539
694
|
"output": {
|
|
540
695
|
"location": loc,
|
|
696
|
+
"path": path,
|
|
541
697
|
"basename": "output.txt",
|
|
542
698
|
"size": 1111,
|
|
543
699
|
"class": "File",
|
|
@@ -546,11 +702,13 @@ class CWLWorkflowTest(ToilTest):
|
|
|
546
702
|
}
|
|
547
703
|
|
|
548
704
|
@staticmethod
|
|
549
|
-
def _expected_revsort_nochecksum_output(outDir):
|
|
550
|
-
|
|
705
|
+
def _expected_revsort_nochecksum_output(outDir: str) -> "CWLObjectType":
|
|
706
|
+
path = os.path.join(outDir, "output.txt")
|
|
707
|
+
loc = "file://" + path
|
|
551
708
|
return {
|
|
552
709
|
"output": {
|
|
553
710
|
"location": loc,
|
|
711
|
+
"path": path,
|
|
554
712
|
"basename": "output.txt",
|
|
555
713
|
"size": 1111,
|
|
556
714
|
"class": "File",
|
|
@@ -558,8 +716,9 @@ class CWLWorkflowTest(ToilTest):
|
|
|
558
716
|
}
|
|
559
717
|
|
|
560
718
|
@staticmethod
|
|
561
|
-
def _expected_download_output(outDir):
|
|
562
|
-
|
|
719
|
+
def _expected_download_output(outDir: str) -> "CWLObjectType":
|
|
720
|
+
path = os.path.join(outDir, "output.txt")
|
|
721
|
+
loc = "file://" + path
|
|
563
722
|
return {
|
|
564
723
|
"output": {
|
|
565
724
|
"location": loc,
|
|
@@ -567,11 +726,41 @@ class CWLWorkflowTest(ToilTest):
|
|
|
567
726
|
"size": 0,
|
|
568
727
|
"class": "File",
|
|
569
728
|
"checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
|
729
|
+
"path": path
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
@staticmethod
|
|
734
|
+
def _expected_glob_dir_output(out_dir: str) -> "CWLObjectType":
|
|
735
|
+
dir_path = os.path.join(out_dir, "shouldmake")
|
|
736
|
+
dir_loc = "file://" + dir_path
|
|
737
|
+
file_path = os.path.join(dir_path, "test.txt")
|
|
738
|
+
file_loc = os.path.join(dir_loc, "test.txt")
|
|
739
|
+
return {
|
|
740
|
+
"shouldmake": {
|
|
741
|
+
"location": dir_loc,
|
|
742
|
+
"path": dir_path,
|
|
743
|
+
"basename": "shouldmake",
|
|
744
|
+
"nameroot": "shouldmake",
|
|
745
|
+
"nameext": "",
|
|
746
|
+
"class": "Directory",
|
|
747
|
+
"listing": [
|
|
748
|
+
{
|
|
749
|
+
"class": "File",
|
|
750
|
+
"location": file_loc,
|
|
751
|
+
"path": file_path,
|
|
752
|
+
"basename": "test.txt",
|
|
753
|
+
"checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
|
754
|
+
"size": 0,
|
|
755
|
+
"nameroot": "test",
|
|
756
|
+
"nameext": ".txt"
|
|
757
|
+
}
|
|
758
|
+
]
|
|
570
759
|
}
|
|
571
760
|
}
|
|
572
761
|
|
|
573
762
|
@classmethod
|
|
574
|
-
def _expected_load_contents_output(cls, out_dir):
|
|
763
|
+
def _expected_load_contents_output(cls, out_dir: str) -> "CWLObjectType":
|
|
575
764
|
"""
|
|
576
765
|
Generate the putput we expect from load_contents.cwl, when sending
|
|
577
766
|
output files to the given directory.
|
|
@@ -581,11 +770,13 @@ class CWLWorkflowTest(ToilTest):
|
|
|
581
770
|
return expected
|
|
582
771
|
|
|
583
772
|
@staticmethod
|
|
584
|
-
def _expected_colon_output(outDir):
|
|
773
|
+
def _expected_colon_output(outDir: str) -> "CWLObjectType":
|
|
774
|
+
path = os.path.join(outDir, "A:Gln2Cys_result")
|
|
585
775
|
loc = "file://" + os.path.join(outDir, "A%3AGln2Cys_result")
|
|
586
776
|
return {
|
|
587
777
|
"result": {
|
|
588
778
|
"location": loc,
|
|
779
|
+
"path": path,
|
|
589
780
|
"basename": "A:Gln2Cys_result",
|
|
590
781
|
"class": "Directory",
|
|
591
782
|
"listing": [
|
|
@@ -597,16 +788,19 @@ class CWLWorkflowTest(ToilTest):
|
|
|
597
788
|
"size": 1111,
|
|
598
789
|
"nameroot": "whale",
|
|
599
790
|
"nameext": ".txt",
|
|
791
|
+
"path": f"{path}/whale.txt"
|
|
600
792
|
}
|
|
601
793
|
],
|
|
602
794
|
}
|
|
603
795
|
}
|
|
604
796
|
|
|
605
|
-
def _expected_streaming_output(self, outDir):
|
|
606
|
-
|
|
797
|
+
def _expected_streaming_output(self, outDir: str) -> "CWLObjectType":
|
|
798
|
+
path = os.path.join(outDir, "output.txt")
|
|
799
|
+
loc = "file://" + path
|
|
607
800
|
return {
|
|
608
801
|
"output": {
|
|
609
802
|
"location": loc,
|
|
803
|
+
"path": path,
|
|
610
804
|
"basename": "output.txt",
|
|
611
805
|
"size": 24,
|
|
612
806
|
"class": "File",
|
|
@@ -616,12 +810,13 @@ class CWLWorkflowTest(ToilTest):
|
|
|
616
810
|
|
|
617
811
|
|
|
618
812
|
@needs_cwl
|
|
813
|
+
@needs_online
|
|
619
814
|
class CWLv10Test(ToilTest):
|
|
620
815
|
"""
|
|
621
816
|
Run the CWL 1.0 conformance tests in various environments.
|
|
622
817
|
"""
|
|
623
818
|
|
|
624
|
-
def setUp(self):
|
|
819
|
+
def setUp(self) -> None:
|
|
625
820
|
"""Runs anew before each test to create farm fresh temp dirs."""
|
|
626
821
|
self.outDir = f"/tmp/toil-cwl-test-{str(uuid.uuid4())}"
|
|
627
822
|
os.makedirs(self.outDir)
|
|
@@ -642,7 +837,7 @@ class CWLv10Test(ToilTest):
|
|
|
642
837
|
shutil.move("common-workflow-language-%s" % testhash, self.cwlSpec)
|
|
643
838
|
os.remove("spec.zip")
|
|
644
839
|
|
|
645
|
-
def tearDown(self):
|
|
840
|
+
def tearDown(self) -> None:
|
|
646
841
|
"""Clean up outputs."""
|
|
647
842
|
if os.path.exists(self.outDir):
|
|
648
843
|
shutil.rmtree(self.outDir)
|
|
@@ -650,121 +845,121 @@ class CWLv10Test(ToilTest):
|
|
|
650
845
|
|
|
651
846
|
@slow
|
|
652
847
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
653
|
-
def test_run_conformance_with_caching(self):
|
|
848
|
+
def test_run_conformance_with_caching(self) -> None:
|
|
654
849
|
self.test_run_conformance(caching=True)
|
|
655
850
|
|
|
656
851
|
@slow
|
|
657
852
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
658
853
|
def test_run_conformance(
|
|
659
|
-
self,
|
|
660
|
-
|
|
854
|
+
self,
|
|
855
|
+
batchSystem: Optional[str] = None,
|
|
856
|
+
caching: bool = False,
|
|
857
|
+
selected_tests: Optional[str] = None,
|
|
858
|
+
skipped_tests: Optional[str] = None,
|
|
859
|
+
extra_args: Optional[List[str]] = None,
|
|
860
|
+
) -> None:
|
|
661
861
|
run_conformance_tests(
|
|
662
862
|
workDir=self.workDir,
|
|
663
863
|
yml="conformance_test_v1.0.yaml",
|
|
664
864
|
caching=caching,
|
|
665
865
|
batchSystem=batchSystem,
|
|
666
866
|
selected_tests=selected_tests,
|
|
867
|
+
skipped_tests=skipped_tests,
|
|
868
|
+
extra_args=extra_args,
|
|
667
869
|
)
|
|
668
870
|
|
|
669
871
|
@slow
|
|
670
872
|
@needs_lsf
|
|
671
|
-
@unittest.skip
|
|
672
|
-
def test_lsf_cwl_conformance(self,
|
|
673
|
-
|
|
873
|
+
@unittest.skip("Not run")
|
|
874
|
+
def test_lsf_cwl_conformance(self, caching: bool = False) -> None:
|
|
875
|
+
self.test_run_conformance(batchSystem="lsf", caching=caching)
|
|
674
876
|
|
|
675
877
|
@slow
|
|
676
878
|
@needs_slurm
|
|
677
|
-
@unittest.skip
|
|
678
|
-
def test_slurm_cwl_conformance(self,
|
|
679
|
-
|
|
879
|
+
@unittest.skip("Not run")
|
|
880
|
+
def test_slurm_cwl_conformance(self, caching: bool = False) -> None:
|
|
881
|
+
self.test_run_conformance(batchSystem="slurm", caching=caching)
|
|
680
882
|
|
|
681
883
|
@slow
|
|
682
884
|
@needs_torque
|
|
683
|
-
@unittest.skip
|
|
684
|
-
def test_torque_cwl_conformance(self,
|
|
685
|
-
|
|
885
|
+
@unittest.skip("Not run")
|
|
886
|
+
def test_torque_cwl_conformance(self, caching: bool = False) -> None:
|
|
887
|
+
self.test_run_conformance(batchSystem="torque", caching=caching)
|
|
686
888
|
|
|
687
889
|
@slow
|
|
688
890
|
@needs_gridengine
|
|
689
|
-
@unittest.skip
|
|
690
|
-
def test_gridengine_cwl_conformance(self,
|
|
691
|
-
|
|
891
|
+
@unittest.skip("Not run")
|
|
892
|
+
def test_gridengine_cwl_conformance(self, caching: bool = False) -> None:
|
|
893
|
+
self.test_run_conformance(batchSystem="grid_engine", caching=caching)
|
|
692
894
|
|
|
693
895
|
@slow
|
|
694
896
|
@needs_mesos
|
|
695
|
-
@unittest.skip
|
|
696
|
-
def test_mesos_cwl_conformance(self,
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
@slow
|
|
700
|
-
@needs_parasol
|
|
701
|
-
@unittest.skip
|
|
702
|
-
def test_parasol_cwl_conformance(self, **kwargs):
|
|
703
|
-
return self.test_run_conformance(batchSystem="parasol", **kwargs)
|
|
897
|
+
@unittest.skip("Not run")
|
|
898
|
+
def test_mesos_cwl_conformance(self, caching: bool = False) -> None:
|
|
899
|
+
self.test_run_conformance(batchSystem="mesos", caching=caching)
|
|
704
900
|
|
|
705
901
|
@slow
|
|
706
902
|
@needs_kubernetes
|
|
707
|
-
def test_kubernetes_cwl_conformance(self,
|
|
708
|
-
|
|
903
|
+
def test_kubernetes_cwl_conformance(self, caching: bool = False) -> None:
|
|
904
|
+
self.test_run_conformance(
|
|
905
|
+
caching=caching,
|
|
709
906
|
batchSystem="kubernetes",
|
|
710
907
|
extra_args=["--retryCount=3"],
|
|
711
908
|
# This test doesn't work with
|
|
712
909
|
# Singularity; see
|
|
713
910
|
# https://github.com/common-workflow-language/cwltool/blob/7094ede917c2d5b16d11f9231fe0c05260b51be6/conformance-test.sh#L99-L117
|
|
714
911
|
skipped_tests="docker_entrypoint",
|
|
715
|
-
**kwargs,
|
|
716
912
|
)
|
|
717
913
|
|
|
718
914
|
@slow
|
|
719
915
|
@needs_lsf
|
|
720
|
-
@unittest.skip
|
|
721
|
-
def test_lsf_cwl_conformance_with_caching(self):
|
|
722
|
-
|
|
916
|
+
@unittest.skip("Not run")
|
|
917
|
+
def test_lsf_cwl_conformance_with_caching(self) -> None:
|
|
918
|
+
self.test_lsf_cwl_conformance(caching=True)
|
|
723
919
|
|
|
724
920
|
@slow
|
|
725
921
|
@needs_slurm
|
|
726
|
-
@unittest.skip
|
|
727
|
-
def test_slurm_cwl_conformance_with_caching(self):
|
|
728
|
-
|
|
922
|
+
@unittest.skip("Not run")
|
|
923
|
+
def test_slurm_cwl_conformance_with_caching(self) -> None:
|
|
924
|
+
self.test_slurm_cwl_conformance(caching=True)
|
|
729
925
|
|
|
730
926
|
@slow
|
|
731
927
|
@needs_torque
|
|
732
|
-
@unittest.skip
|
|
733
|
-
def test_torque_cwl_conformance_with_caching(self):
|
|
734
|
-
|
|
928
|
+
@unittest.skip("Not run")
|
|
929
|
+
def test_torque_cwl_conformance_with_caching(self) -> None:
|
|
930
|
+
self.test_torque_cwl_conformance(caching=True)
|
|
735
931
|
|
|
736
932
|
@slow
|
|
737
933
|
@needs_gridengine
|
|
738
|
-
@unittest.skip
|
|
739
|
-
def test_gridengine_cwl_conformance_with_caching(self):
|
|
740
|
-
|
|
934
|
+
@unittest.skip("Not run")
|
|
935
|
+
def test_gridengine_cwl_conformance_with_caching(self) -> None:
|
|
936
|
+
self.test_gridengine_cwl_conformance(caching=True)
|
|
741
937
|
|
|
742
938
|
@slow
|
|
743
939
|
@needs_mesos
|
|
744
|
-
@unittest.skip
|
|
745
|
-
def test_mesos_cwl_conformance_with_caching(self):
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
@slow
|
|
749
|
-
@needs_parasol
|
|
750
|
-
@unittest.skip
|
|
751
|
-
def test_parasol_cwl_conformance_with_caching(self):
|
|
752
|
-
return self.test_parasol_cwl_conformance(caching=True)
|
|
940
|
+
@unittest.skip("Not run")
|
|
941
|
+
def test_mesos_cwl_conformance_with_caching(self) -> None:
|
|
942
|
+
self.test_mesos_cwl_conformance(caching=True)
|
|
753
943
|
|
|
754
944
|
@slow
|
|
755
945
|
@needs_kubernetes
|
|
756
|
-
def test_kubernetes_cwl_conformance_with_caching(self):
|
|
757
|
-
|
|
946
|
+
def test_kubernetes_cwl_conformance_with_caching(self) -> None:
|
|
947
|
+
self.test_kubernetes_cwl_conformance(caching=True)
|
|
758
948
|
|
|
759
949
|
|
|
760
950
|
@needs_cwl
|
|
951
|
+
@needs_online
|
|
761
952
|
class CWLv11Test(ToilTest):
|
|
762
953
|
"""
|
|
763
954
|
Run the CWL 1.1 conformance tests in various environments.
|
|
764
955
|
"""
|
|
765
956
|
|
|
957
|
+
rootDir: str
|
|
958
|
+
cwlSpec: str
|
|
959
|
+
test_yaml: str
|
|
960
|
+
|
|
766
961
|
@classmethod
|
|
767
|
-
def setUpClass(cls):
|
|
962
|
+
def setUpClass(cls) -> None:
|
|
768
963
|
"""Runs anew before each test."""
|
|
769
964
|
cls.rootDir = cls._projectRootPath()
|
|
770
965
|
cls.cwlSpec = os.path.join(cls.rootDir, "src/toil/test/cwl/spec_v11")
|
|
@@ -778,94 +973,146 @@ class CWLv11Test(ToilTest):
|
|
|
778
973
|
)
|
|
779
974
|
p.communicate()
|
|
780
975
|
|
|
781
|
-
def tearDown(self):
|
|
976
|
+
def tearDown(self) -> None:
|
|
782
977
|
"""Clean up outputs."""
|
|
783
978
|
unittest.TestCase.tearDown(self)
|
|
784
979
|
|
|
785
980
|
@slow
|
|
786
981
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
787
|
-
def test_run_conformance(
|
|
788
|
-
|
|
982
|
+
def test_run_conformance(
|
|
983
|
+
self,
|
|
984
|
+
caching: bool = False,
|
|
985
|
+
batchSystem: Optional[str] = None,
|
|
986
|
+
skipped_tests: Optional[str] = None,
|
|
987
|
+
extra_args: Optional[List[str]] = None,
|
|
988
|
+
) -> None:
|
|
989
|
+
run_conformance_tests(
|
|
990
|
+
workDir=self.cwlSpec,
|
|
991
|
+
yml=self.test_yaml,
|
|
992
|
+
caching=caching,
|
|
993
|
+
batchSystem=batchSystem,
|
|
994
|
+
skipped_tests=skipped_tests,
|
|
995
|
+
extra_args=extra_args,
|
|
996
|
+
)
|
|
789
997
|
|
|
790
998
|
@slow
|
|
791
999
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
792
|
-
def test_run_conformance_with_caching(self):
|
|
1000
|
+
def test_run_conformance_with_caching(self) -> None:
|
|
793
1001
|
self.test_run_conformance(caching=True)
|
|
794
1002
|
|
|
795
1003
|
@slow
|
|
796
1004
|
@needs_kubernetes
|
|
797
|
-
def test_kubernetes_cwl_conformance(self,
|
|
798
|
-
|
|
1005
|
+
def test_kubernetes_cwl_conformance(self, caching: bool = False) -> None:
|
|
1006
|
+
self.test_run_conformance(
|
|
799
1007
|
batchSystem="kubernetes",
|
|
800
1008
|
extra_args=["--retryCount=3"],
|
|
801
1009
|
# These tests don't work with
|
|
802
1010
|
# Singularity; see
|
|
803
1011
|
# https://github.com/common-workflow-language/cwltool/blob/7094ede917c2d5b16d11f9231fe0c05260b51be6/conformance-test.sh#L99-L117
|
|
804
1012
|
skipped_tests="docker_entrypoint,stdin_shorcut",
|
|
805
|
-
|
|
1013
|
+
caching=caching,
|
|
806
1014
|
)
|
|
807
1015
|
|
|
808
1016
|
@slow
|
|
809
1017
|
@needs_kubernetes
|
|
810
|
-
def test_kubernetes_cwl_conformance_with_caching(self):
|
|
811
|
-
|
|
1018
|
+
def test_kubernetes_cwl_conformance_with_caching(self) -> None:
|
|
1019
|
+
self.test_kubernetes_cwl_conformance(caching=True)
|
|
812
1020
|
|
|
813
1021
|
|
|
814
1022
|
@needs_cwl
|
|
1023
|
+
@needs_online
|
|
815
1024
|
class CWLv12Test(ToilTest):
|
|
816
1025
|
"""
|
|
817
1026
|
Run the CWL 1.2 conformance tests in various environments.
|
|
818
1027
|
"""
|
|
819
1028
|
|
|
1029
|
+
rootDir: str
|
|
1030
|
+
cwlSpec: str
|
|
1031
|
+
test_yaml: str
|
|
1032
|
+
|
|
820
1033
|
@classmethod
|
|
821
|
-
def setUpClass(cls):
|
|
1034
|
+
def setUpClass(cls) -> None:
|
|
822
1035
|
"""Runs anew before each test."""
|
|
823
1036
|
cls.rootDir = cls._projectRootPath()
|
|
824
1037
|
cls.cwlSpec = os.path.join(cls.rootDir, "src/toil/test/cwl/spec_v12")
|
|
825
1038
|
cls.test_yaml = os.path.join(cls.cwlSpec, "conformance_tests.yaml")
|
|
826
1039
|
# TODO: Use a commit zip in case someone decides to rewrite master's history?
|
|
827
1040
|
url = "https://github.com/common-workflow-language/cwl-v1.2.git"
|
|
828
|
-
commit = "
|
|
1041
|
+
commit = "0d538a0dbc5518f3c6083ce4571926f65cb84f76"
|
|
829
1042
|
p = subprocess.Popen(
|
|
830
1043
|
f"git clone {url} {cls.cwlSpec} && cd {cls.cwlSpec} && git checkout {commit}",
|
|
831
1044
|
shell=True,
|
|
832
1045
|
)
|
|
833
1046
|
p.communicate()
|
|
834
1047
|
|
|
835
|
-
def tearDown(self):
|
|
1048
|
+
def tearDown(self) -> None:
|
|
836
1049
|
"""Clean up outputs."""
|
|
837
1050
|
unittest.TestCase.tearDown(self)
|
|
838
1051
|
|
|
839
1052
|
@slow
|
|
840
1053
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
841
|
-
def test_run_conformance(
|
|
842
|
-
|
|
1054
|
+
def test_run_conformance(
|
|
1055
|
+
self,
|
|
1056
|
+
runner: Optional[str] = None,
|
|
1057
|
+
caching: bool = False,
|
|
1058
|
+
batchSystem: Optional[str] = None,
|
|
1059
|
+
selected_tests: Optional[str] = None,
|
|
1060
|
+
skipped_tests: Optional[str] = None,
|
|
1061
|
+
extra_args: Optional[List[str]] = None,
|
|
1062
|
+
must_support_all_features: bool = False,
|
|
1063
|
+
junit_file: Optional[str] = None,
|
|
1064
|
+
) -> None:
|
|
1065
|
+
if junit_file is None:
|
|
1066
|
+
junit_file = os.path.join(self.rootDir, "conformance-1.2.junit.xml")
|
|
1067
|
+
run_conformance_tests(
|
|
1068
|
+
workDir=self.cwlSpec,
|
|
1069
|
+
yml=self.test_yaml,
|
|
1070
|
+
runner=runner,
|
|
1071
|
+
caching=caching,
|
|
1072
|
+
batchSystem=batchSystem,
|
|
1073
|
+
selected_tests=selected_tests,
|
|
1074
|
+
skipped_tests=skipped_tests,
|
|
1075
|
+
extra_args=extra_args,
|
|
1076
|
+
must_support_all_features=must_support_all_features,
|
|
1077
|
+
junit_file=junit_file,
|
|
1078
|
+
)
|
|
843
1079
|
|
|
844
1080
|
@slow
|
|
845
1081
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
846
|
-
def test_run_conformance_with_caching(self):
|
|
847
|
-
self.test_run_conformance(
|
|
1082
|
+
def test_run_conformance_with_caching(self) -> None:
|
|
1083
|
+
self.test_run_conformance(
|
|
1084
|
+
caching=True,
|
|
1085
|
+
junit_file = os.path.join(
|
|
1086
|
+
self.rootDir, "caching-conformance-1.2.junit.xml"
|
|
1087
|
+
)
|
|
1088
|
+
)
|
|
848
1089
|
|
|
849
1090
|
@slow
|
|
850
1091
|
@pytest.mark.timeout(CONFORMANCE_TEST_TIMEOUT)
|
|
851
|
-
def test_run_conformance_with_in_place_update(self):
|
|
1092
|
+
def test_run_conformance_with_in_place_update(self) -> None:
|
|
852
1093
|
"""
|
|
853
1094
|
Make sure that with --bypass-file-store we properly support in place
|
|
854
1095
|
update on a single node, and that this doesn't break any other
|
|
855
1096
|
features.
|
|
856
1097
|
"""
|
|
857
1098
|
self.test_run_conformance(
|
|
858
|
-
extra_args=["--bypass-file-store"], must_support_all_features=True
|
|
1099
|
+
extra_args=["--bypass-file-store"], must_support_all_features=True,
|
|
1100
|
+
junit_file = os.path.join(
|
|
1101
|
+
self.rootDir, "in-place-update-conformance-1.2.junit.xml"
|
|
1102
|
+
)
|
|
859
1103
|
)
|
|
860
1104
|
|
|
861
1105
|
@slow
|
|
862
1106
|
@needs_kubernetes
|
|
863
|
-
def test_kubernetes_cwl_conformance(
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1107
|
+
def test_kubernetes_cwl_conformance(
|
|
1108
|
+
self, caching: bool = False, junit_file: Optional[str] = None
|
|
1109
|
+
) -> None:
|
|
1110
|
+
if junit_file is None:
|
|
1111
|
+
junit_file = os.path.join(
|
|
1112
|
+
self.rootDir, "kubernetes-conformance-1.2.junit.xml"
|
|
867
1113
|
)
|
|
868
|
-
|
|
1114
|
+
self.test_run_conformance(
|
|
1115
|
+
caching=caching,
|
|
869
1116
|
batchSystem="kubernetes",
|
|
870
1117
|
extra_args=["--retryCount=3"],
|
|
871
1118
|
# This test doesn't work with
|
|
@@ -874,22 +1121,22 @@ class CWLv12Test(ToilTest):
|
|
|
874
1121
|
# and
|
|
875
1122
|
# https://github.com/common-workflow-language/cwltool/issues/1441#issuecomment-826747975
|
|
876
1123
|
skipped_tests="docker_entrypoint",
|
|
877
|
-
|
|
1124
|
+
junit_file=junit_file,
|
|
878
1125
|
)
|
|
879
1126
|
|
|
880
1127
|
@slow
|
|
881
1128
|
@needs_kubernetes
|
|
882
|
-
def test_kubernetes_cwl_conformance_with_caching(self):
|
|
883
|
-
|
|
1129
|
+
def test_kubernetes_cwl_conformance_with_caching(self) -> None:
|
|
1130
|
+
self.test_kubernetes_cwl_conformance(
|
|
884
1131
|
caching=True,
|
|
885
1132
|
junit_file=os.path.join(
|
|
886
|
-
self.rootDir, "kubernetes-caching-conformance.junit.xml"
|
|
1133
|
+
self.rootDir, "kubernetes-caching-conformance-1.2.junit.xml"
|
|
887
1134
|
),
|
|
888
1135
|
)
|
|
889
1136
|
|
|
890
1137
|
@slow
|
|
891
1138
|
@needs_wes_server
|
|
892
|
-
def test_wes_server_cwl_conformance(self):
|
|
1139
|
+
def test_wes_server_cwl_conformance(self) -> None:
|
|
893
1140
|
"""
|
|
894
1141
|
Run the CWL conformance tests via WES. TOIL_WES_ENDPOINT must be
|
|
895
1142
|
specified. If the WES server requires authentication, set TOIL_WES_USER
|
|
@@ -914,7 +1161,7 @@ class CWLv12Test(ToilTest):
|
|
|
914
1161
|
# 1. `cwltool --print-deps` doesn't seem to include secondary files from the default
|
|
915
1162
|
# e.g.: https://github.com/common-workflow-language/cwl-v1.2/blob/1.2.1_proposed/tests/mixed-versions/wf-v10.cwl#L4-L10
|
|
916
1163
|
|
|
917
|
-
|
|
1164
|
+
self.test_run_conformance(
|
|
918
1165
|
runner="toil-wes-cwl-runner",
|
|
919
1166
|
selected_tests="1-309,313-337",
|
|
920
1167
|
extra_args=extra_args,
|
|
@@ -929,7 +1176,7 @@ class CWLOnARMTest(AbstractClusterTest):
|
|
|
929
1176
|
Run the CWL 1.2 conformance tests on ARM specifically.
|
|
930
1177
|
"""
|
|
931
1178
|
|
|
932
|
-
def __init__(self, methodName):
|
|
1179
|
+
def __init__(self, methodName: str) -> None:
|
|
933
1180
|
super().__init__(methodName=methodName)
|
|
934
1181
|
self.clusterName = "cwl-test-" + str(uuid.uuid4())
|
|
935
1182
|
self.leaderNodeType = "t4g.2xlarge"
|
|
@@ -937,12 +1184,12 @@ class CWLOnARMTest(AbstractClusterTest):
|
|
|
937
1184
|
# We need to be running in a directory which Flatcar and the Toil Appliance both have
|
|
938
1185
|
self.cwl_test_dir = "/tmp/toil/cwlTests"
|
|
939
1186
|
|
|
940
|
-
def setUp(self):
|
|
1187
|
+
def setUp(self) -> None:
|
|
941
1188
|
super().setUp()
|
|
942
1189
|
self.jobStore = f"aws:{self.awsRegion()}:cluster-{uuid.uuid4()}"
|
|
943
1190
|
|
|
944
1191
|
@needs_env_var("CI_COMMIT_SHA", "a git commit sha")
|
|
945
|
-
def test_cwl_on_arm(self):
|
|
1192
|
+
def test_cwl_on_arm(self) -> None:
|
|
946
1193
|
# Make a cluster
|
|
947
1194
|
self.launchCluster()
|
|
948
1195
|
# get the leader so we know the IP address - we don't need to wait since create cluster
|
|
@@ -991,10 +1238,19 @@ class CWLOnARMTest(AbstractClusterTest):
|
|
|
991
1238
|
]
|
|
992
1239
|
)
|
|
993
1240
|
|
|
1241
|
+
# We know if it succeeds it should save a junit XML for us to read.
|
|
1242
|
+
# Bring it back to be an artifact.
|
|
1243
|
+
self.rsync_util(
|
|
1244
|
+
f":{self.cwl_test_dir}/toil/conformance-1.2.junit.xml",
|
|
1245
|
+
os.path.join(
|
|
1246
|
+
self._projectRootPath(),
|
|
1247
|
+
"arm-conformance-1.2.junit.xml"
|
|
1248
|
+
)
|
|
1249
|
+
)
|
|
994
1250
|
|
|
995
1251
|
@needs_cwl
|
|
996
1252
|
@pytest.mark.cwl_small_log_dir
|
|
997
|
-
def test_workflow_echo_string_scatter_stderr_log_dir(tmp_path: Path):
|
|
1253
|
+
def test_workflow_echo_string_scatter_stderr_log_dir(tmp_path: Path) -> None:
|
|
998
1254
|
log_dir = tmp_path / "cwl-logs"
|
|
999
1255
|
job_store = "test_workflow_echo_string_scatter_stderr_log_dir"
|
|
1000
1256
|
toil = "toil-cwl-runner"
|
|
@@ -1101,7 +1357,7 @@ def test_log_dir_echo_stderr(tmp_path: Path) -> None:
|
|
|
1101
1357
|
|
|
1102
1358
|
@needs_cwl
|
|
1103
1359
|
@pytest.mark.cwl_small_log_dir
|
|
1104
|
-
def test_filename_conflict_resolution(tmp_path: Path):
|
|
1360
|
+
def test_filename_conflict_resolution(tmp_path: Path) -> None:
|
|
1105
1361
|
out_dir = tmp_path / "cwl-out-dir"
|
|
1106
1362
|
toil = "toil-cwl-runner"
|
|
1107
1363
|
options = [
|
|
@@ -1124,7 +1380,7 @@ def test_filename_conflict_resolution(tmp_path: Path):
|
|
|
1124
1380
|
@needs_cwl
|
|
1125
1381
|
@needs_docker
|
|
1126
1382
|
@pytest.mark.cwl_small_log_dir
|
|
1127
|
-
def test_filename_conflict_detection(tmp_path: Path):
|
|
1383
|
+
def test_filename_conflict_detection(tmp_path: Path) -> None:
|
|
1128
1384
|
"""
|
|
1129
1385
|
Make sure we don't just stage files over each other when using a container.
|
|
1130
1386
|
"""
|
|
@@ -1146,7 +1402,7 @@ def test_filename_conflict_detection(tmp_path: Path):
|
|
|
1146
1402
|
@needs_cwl
|
|
1147
1403
|
@needs_docker
|
|
1148
1404
|
@pytest.mark.cwl_small_log_dir
|
|
1149
|
-
def test_filename_conflict_detection_at_root(tmp_path: Path):
|
|
1405
|
+
def test_filename_conflict_detection_at_root(tmp_path: Path) -> None:
|
|
1150
1406
|
"""
|
|
1151
1407
|
Make sure we don't just stage files over each other.
|
|
1152
1408
|
|
|
@@ -1170,7 +1426,7 @@ def test_filename_conflict_detection_at_root(tmp_path: Path):
|
|
|
1170
1426
|
|
|
1171
1427
|
@needs_cwl
|
|
1172
1428
|
@pytest.mark.cwl_small
|
|
1173
|
-
def test_pick_value_with_one_null_value(caplog):
|
|
1429
|
+
def test_pick_value_with_one_null_value(caplog: pytest.LogCaptureFixture) -> None:
|
|
1174
1430
|
"""
|
|
1175
1431
|
Make sure toil-cwl-runner does not false log a warning when pickValue is
|
|
1176
1432
|
used but outputSource only contains one null value. See: #3991.
|
|
@@ -1189,57 +1445,7 @@ def test_pick_value_with_one_null_value(caplog):
|
|
|
1189
1445
|
|
|
1190
1446
|
@needs_cwl
|
|
1191
1447
|
@pytest.mark.cwl_small
|
|
1192
|
-
def
|
|
1193
|
-
"""
|
|
1194
|
-
This is purely to ensure a (more) helpful error message is printed if a user does
|
|
1195
|
-
not order their positional args correctly [cwl, cwl-job (json/yml/yaml), jobstore].
|
|
1196
|
-
"""
|
|
1197
|
-
toil = "toil-cwl-runner"
|
|
1198
|
-
cwl = "test/cwl/revsort.cwl"
|
|
1199
|
-
cwl_job_json = "test/cwl/revsort-job.json"
|
|
1200
|
-
jobstore = "delete-test-toil"
|
|
1201
|
-
random_option_1 = "--logInfo"
|
|
1202
|
-
random_option_2 = "--disableChaining"
|
|
1203
|
-
cmd_wrong_ordering_1 = [
|
|
1204
|
-
toil,
|
|
1205
|
-
cwl,
|
|
1206
|
-
cwl_job_json,
|
|
1207
|
-
jobstore,
|
|
1208
|
-
random_option_1,
|
|
1209
|
-
random_option_2,
|
|
1210
|
-
]
|
|
1211
|
-
cmd_wrong_ordering_2 = [
|
|
1212
|
-
toil,
|
|
1213
|
-
cwl,
|
|
1214
|
-
jobstore,
|
|
1215
|
-
random_option_1,
|
|
1216
|
-
random_option_2,
|
|
1217
|
-
cwl_job_json,
|
|
1218
|
-
]
|
|
1219
|
-
cmd_wrong_ordering_3 = [
|
|
1220
|
-
toil,
|
|
1221
|
-
jobstore,
|
|
1222
|
-
random_option_1,
|
|
1223
|
-
random_option_2,
|
|
1224
|
-
cwl,
|
|
1225
|
-
cwl_job_json,
|
|
1226
|
-
]
|
|
1227
|
-
|
|
1228
|
-
for cmd in [cmd_wrong_ordering_1, cmd_wrong_ordering_2, cmd_wrong_ordering_3]:
|
|
1229
|
-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
1230
|
-
stdout, stderr = p.communicate()
|
|
1231
|
-
assert (
|
|
1232
|
-
b"Usage: toil-cwl-runner [options] example.cwl example-job.yaml" in stderr
|
|
1233
|
-
)
|
|
1234
|
-
assert (
|
|
1235
|
-
b"All positional arguments [cwl, yml_or_json] "
|
|
1236
|
-
b"must always be specified last for toil-cwl-runner." in stderr
|
|
1237
|
-
)
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
@needs_cwl
|
|
1241
|
-
@pytest.mark.cwl_small
|
|
1242
|
-
def test_workflow_echo_string():
|
|
1448
|
+
def test_workflow_echo_string() -> None:
|
|
1243
1449
|
toil = "toil-cwl-runner"
|
|
1244
1450
|
jobstore = f"--jobStore=file:explicit-local-jobstore-{uuid.uuid4()}"
|
|
1245
1451
|
option_1 = "--strict-memory-limit"
|
|
@@ -1249,14 +1455,18 @@ def test_workflow_echo_string():
|
|
|
1249
1455
|
cmd = [toil, jobstore, option_1, option_2, option_3, cwl]
|
|
1250
1456
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
1251
1457
|
stdout, stderr = p.communicate()
|
|
1252
|
-
|
|
1253
|
-
|
|
1458
|
+
stdout2 = stdout.decode("utf-8")
|
|
1459
|
+
stderr2 = stderr.decode("utf-8")
|
|
1460
|
+
assert (
|
|
1461
|
+
stdout2.strip() == "{}"
|
|
1462
|
+
), f"Got wrong output: {stdout2}\nWith error: {stderr2}"
|
|
1463
|
+
assert "Finished toil run successfully" in stderr2
|
|
1254
1464
|
assert p.returncode == 0
|
|
1255
1465
|
|
|
1256
1466
|
|
|
1257
1467
|
@needs_cwl
|
|
1258
1468
|
@pytest.mark.cwl_small
|
|
1259
|
-
def test_workflow_echo_string_scatter_capture_stdout():
|
|
1469
|
+
def test_workflow_echo_string_scatter_capture_stdout() -> None:
|
|
1260
1470
|
toil = "toil-cwl-runner"
|
|
1261
1471
|
jobstore = f"--jobStore=file:explicit-local-jobstore-{uuid.uuid4()}"
|
|
1262
1472
|
option_1 = "--strict-memory-limit"
|
|
@@ -1289,7 +1499,7 @@ def test_workflow_echo_string_scatter_capture_stdout():
|
|
|
1289
1499
|
|
|
1290
1500
|
@needs_cwl
|
|
1291
1501
|
@pytest.mark.cwl_small
|
|
1292
|
-
def test_visit_top_cwl_class():
|
|
1502
|
+
def test_visit_top_cwl_class() -> None:
|
|
1293
1503
|
structure = {
|
|
1294
1504
|
"class": "Directory",
|
|
1295
1505
|
"listing": [
|
|
@@ -1315,7 +1525,7 @@ def test_visit_top_cwl_class():
|
|
|
1315
1525
|
|
|
1316
1526
|
counter = 0
|
|
1317
1527
|
|
|
1318
|
-
def increment(thing:
|
|
1528
|
+
def increment(thing: "CWLObjectType") -> None:
|
|
1319
1529
|
"""
|
|
1320
1530
|
Make sure we are at something CWL object like, and count it.
|
|
1321
1531
|
"""
|
|
@@ -1340,7 +1550,7 @@ def test_visit_top_cwl_class():
|
|
|
1340
1550
|
|
|
1341
1551
|
@needs_cwl
|
|
1342
1552
|
@pytest.mark.cwl_small
|
|
1343
|
-
def test_visit_cwl_class_and_reduce():
|
|
1553
|
+
def test_visit_cwl_class_and_reduce() -> None:
|
|
1344
1554
|
structure = {
|
|
1345
1555
|
"class": "Directory",
|
|
1346
1556
|
"listing": [
|
|
@@ -1366,7 +1576,7 @@ def test_visit_cwl_class_and_reduce():
|
|
|
1366
1576
|
|
|
1367
1577
|
down_count = 0
|
|
1368
1578
|
|
|
1369
|
-
def op_down(thing:
|
|
1579
|
+
def op_down(thing: "CWLObjectType") -> int:
|
|
1370
1580
|
"""
|
|
1371
1581
|
Grab the ID of the thing we are at, and count what we visit going
|
|
1372
1582
|
down.
|
|
@@ -1378,7 +1588,7 @@ def test_visit_cwl_class_and_reduce():
|
|
|
1378
1588
|
up_count = 0
|
|
1379
1589
|
up_child_count = 0
|
|
1380
1590
|
|
|
1381
|
-
def op_up(thing:
|
|
1591
|
+
def op_up(thing: "CWLObjectType", down_value: int, child_results: List[str]) -> str:
|
|
1382
1592
|
"""
|
|
1383
1593
|
Check the down return value and the up return values, and count
|
|
1384
1594
|
what we visit going up and what child relationships we have.
|
|
@@ -1401,7 +1611,7 @@ def test_visit_cwl_class_and_reduce():
|
|
|
1401
1611
|
|
|
1402
1612
|
@needs_cwl
|
|
1403
1613
|
@pytest.mark.cwl_small
|
|
1404
|
-
def test_download_structure(tmp_path) -> None:
|
|
1614
|
+
def test_download_structure(tmp_path: Path) -> None:
|
|
1405
1615
|
"""
|
|
1406
1616
|
Make sure that download_structure makes the right calls to what it thinks is the file store.
|
|
1407
1617
|
"""
|
|
@@ -1411,7 +1621,7 @@ def test_download_structure(tmp_path) -> None:
|
|
|
1411
1621
|
fid2 = FileID("adifferentfile", 1000, True)
|
|
1412
1622
|
|
|
1413
1623
|
# And what directory structure it would be in
|
|
1414
|
-
structure = {
|
|
1624
|
+
structure: DirectoryStructure = {
|
|
1415
1625
|
"dir1": {
|
|
1416
1626
|
"dir2": {
|
|
1417
1627
|
"f1": "toilfile:" + fid1.pack(),
|
|
@@ -1432,9 +1642,9 @@ def test_download_structure(tmp_path) -> None:
|
|
|
1432
1642
|
# These will be populated.
|
|
1433
1643
|
# TODO: This cache seems unused. Remove it?
|
|
1434
1644
|
# This maps filesystem path to CWL URI
|
|
1435
|
-
index = {}
|
|
1645
|
+
index: Dict[str, str] = {}
|
|
1436
1646
|
# This maps CWL URI to filesystem path
|
|
1437
|
-
existing = {}
|
|
1647
|
+
existing: Dict[str, str] = {}
|
|
1438
1648
|
|
|
1439
1649
|
# Do the download
|
|
1440
1650
|
download_structure(file_store, index, existing, structure, to_dir)
|
|
@@ -1450,11 +1660,16 @@ def test_download_structure(tmp_path) -> None:
|
|
|
1450
1660
|
assert os.path.join(to_dir, "dir1/dir2/f1again") in index
|
|
1451
1661
|
assert os.path.join(to_dir, "anotherfile") in index
|
|
1452
1662
|
assert (
|
|
1453
|
-
index[os.path.join(to_dir, "dir1/dir2/f1")]
|
|
1663
|
+
index[os.path.join(to_dir, "dir1/dir2/f1")]
|
|
1664
|
+
== cast(
|
|
1665
|
+
DirectoryStructure, cast(DirectoryStructure, structure["dir1"])["dir2"]
|
|
1666
|
+
)["f1"]
|
|
1454
1667
|
)
|
|
1455
1668
|
assert (
|
|
1456
1669
|
index[os.path.join(to_dir, "dir1/dir2/f1again")]
|
|
1457
|
-
==
|
|
1670
|
+
== cast(
|
|
1671
|
+
DirectoryStructure, cast(DirectoryStructure, structure["dir1"])["dir2"]
|
|
1672
|
+
)["f1again"]
|
|
1458
1673
|
)
|
|
1459
1674
|
assert index[os.path.join(to_dir, "anotherfile")] == structure["anotherfile"]
|
|
1460
1675
|
|
|
@@ -1476,9 +1691,9 @@ def test_download_structure(tmp_path) -> None:
|
|
|
1476
1691
|
# The file store should have been asked to do the download
|
|
1477
1692
|
file_store.readGlobalFile.assert_has_calls(
|
|
1478
1693
|
[
|
|
1479
|
-
call(fid1, os.path.join(to_dir, "dir1/dir2/f1"), symlink=
|
|
1480
|
-
call(fid1, os.path.join(to_dir, "dir1/dir2/f1again"), symlink=
|
|
1481
|
-
call(fid2, os.path.join(to_dir, "anotherfile"), symlink=
|
|
1694
|
+
call(fid1, os.path.join(to_dir, "dir1/dir2/f1"), symlink=False),
|
|
1695
|
+
call(fid1, os.path.join(to_dir, "dir1/dir2/f1again"), symlink=False),
|
|
1696
|
+
call(fid2, os.path.join(to_dir, "anotherfile"), symlink=False),
|
|
1482
1697
|
],
|
|
1483
1698
|
any_order=True,
|
|
1484
1699
|
)
|