comparison planemo/lib/python3.7/site-packages/cwltool/tests/test_examples.py @ 0:d30785e31577 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:18:57 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d30785e31577
1 import json
2 import logging
3 import os
4 import stat
5 import sys
6 from io import BytesIO, StringIO
7 import pytest
8 from typing_extensions import Text
9
10 import schema_salad.validate
11
12 import cwltool.checker
13 import cwltool.expression as expr
14 import cwltool.factory
15 import cwltool.pathmapper
16 import cwltool.process
17 import cwltool.workflow
18 from cwltool.context import RuntimeContext
19 from cwltool.errors import WorkflowException
20 from cwltool.main import main
21 from cwltool.utils import onWindows
22 from cwltool.resolver import Path
23 from cwltool.process import CWL_IANA
24 from cwltool.sandboxjs import JavascriptException
25 from .util import (get_data, get_main_output, get_windows_safe_factory, subprocess,
26 needs_docker, working_directory, needs_singularity, temp_dir, windows_needs_docker)
27
28 import six
29
30 try:
31 reload
32 except: # pylint: disable=bare-except
33 try:
34 from imp import reload
35 except:
36 from importlib import reload
37
38 sys.argv = ['']
39
40 expression_match = [
41 ("(foo)", True),
42 ("(foo.bar)", True),
43 ("(foo['bar'])", True),
44 ("(foo[\"bar\"])", True),
45 ("(foo.bar.baz)", True),
46 ("(foo['bar'].baz)", True),
47 ("(foo['bar']['baz'])", True),
48 ("(foo['b\\'ar']['baz'])", True),
49 ("(foo['b ar']['baz'])", True),
50 ("(foo_bar)", True),
51
52 ("(foo.[\"bar\"])", False),
53 ("(.foo[\"bar\"])", False),
54 ("(foo [\"bar\"])", False),
55 ("( foo[\"bar\"])", False),
56 ("(foo[bar].baz)", False),
57 ("(foo['bar\"].baz)", False),
58 ("(foo['bar].baz)", False),
59 ("{foo}", False),
60 ("(foo.bar", False),
61 ("foo.bar)", False),
62 ("foo.b ar)", False),
63 ("foo.b\'ar)", False),
64 ("(foo+bar", False),
65 ("(foo bar", False)
66 ]
67
68
69 @pytest.mark.parametrize('expression,expected', expression_match)
70 def test_expression_match(expression, expected):
71 match = expr.param_re.match(expression)
72 assert (match is not None) == expected
73
74
75 interpolate_input = {
76 "foo": {
77 "bar": {
78 "baz": "zab1"
79 },
80 "b ar": {
81 "baz": 2
82 },
83 "b'ar": {
84 "baz": True
85 },
86 'b"ar': {
87 "baz": None
88 }
89 },
90 "lst": ["A", "B"]
91 }
92
93 interpolate_parameters = [
94 ("$(foo)", interpolate_input["foo"]),
95
96 ("$(foo.bar)", interpolate_input["foo"]["bar"]),
97 ("$(foo['bar'])", interpolate_input["foo"]["bar"]),
98 ("$(foo[\"bar\"])", interpolate_input["foo"]["bar"]),
99
100 ("$(foo.bar.baz)", interpolate_input['foo']['bar']['baz']),
101 ("$(foo['bar'].baz)", interpolate_input['foo']['bar']['baz']),
102 ("$(foo['bar'][\"baz\"])", interpolate_input['foo']['bar']['baz']),
103 ("$(foo.bar['baz'])", interpolate_input['foo']['bar']['baz']),
104
105 ("$(foo['b\\'ar'].baz)", True),
106 ("$(foo[\"b'ar\"].baz)", True),
107 ("$(foo['b\\\"ar'].baz)", None),
108
109 ("$(lst[0])", "A"),
110 ("$(lst[1])", "B"),
111 ("$(lst.length)", 2),
112 ("$(lst['length'])", 2),
113
114 ("-$(foo.bar)", """-{"baz": "zab1"}"""),
115 ("-$(foo['bar'])", """-{"baz": "zab1"}"""),
116 ("-$(foo[\"bar\"])", """-{"baz": "zab1"}"""),
117
118 ("-$(foo.bar.baz)", "-zab1"),
119 ("-$(foo['bar'].baz)", "-zab1"),
120 ("-$(foo['bar'][\"baz\"])", "-zab1"),
121 ("-$(foo.bar['baz'])", "-zab1"),
122
123 ("-$(foo['b ar'].baz)", "-2"),
124 ("-$(foo['b\\'ar'].baz)", "-true"),
125 ("-$(foo[\"b\\'ar\"].baz)", "-true"),
126 ("-$(foo['b\\\"ar'].baz)", "-null"),
127
128 ("$(foo.bar) $(foo.bar)", """{"baz": "zab1"} {"baz": "zab1"}"""),
129 ("$(foo['bar']) $(foo['bar'])", """{"baz": "zab1"} {"baz": "zab1"}"""),
130 ("$(foo[\"bar\"]) $(foo[\"bar\"])", """{"baz": "zab1"} {"baz": "zab1"}"""),
131
132 ("$(foo.bar.baz) $(foo.bar.baz)", "zab1 zab1"),
133 ("$(foo['bar'].baz) $(foo['bar'].baz)", "zab1 zab1"),
134 ("$(foo['bar'][\"baz\"]) $(foo['bar'][\"baz\"])", "zab1 zab1"),
135 ("$(foo.bar['baz']) $(foo.bar['baz'])", "zab1 zab1"),
136
137 ("$(foo['b ar'].baz) $(foo['b ar'].baz)", "2 2"),
138 ("$(foo['b\\'ar'].baz) $(foo['b\\'ar'].baz)", "true true"),
139 ("$(foo[\"b\\'ar\"].baz) $(foo[\"b\\'ar\"].baz)", "true true"),
140 ("$(foo['b\\\"ar'].baz) $(foo['b\\\"ar'].baz)", "null null")
141 ]
142
143
144 @pytest.mark.parametrize('pattern,expected', interpolate_parameters)
145 def test_expression_interpolate(pattern, expected):
146 assert expr.interpolate(pattern, interpolate_input) == expected
147
148 interpolate_bad_parameters = [
149 ("$(fooz)"),
150 ("$(foo.barz)"),
151 ("$(foo['barz'])"),
152 ("$(foo[\"barz\"])"),
153
154 ("$(foo.bar.bazz)"),
155 ("$(foo['bar'].bazz)"),
156 ("$(foo['bar'][\"bazz\"])"),
157 ("$(foo.bar['bazz'])"),
158
159 ("$(foo['b\\'ar'].bazz)"),
160 ("$(foo[\"b'ar\"].bazz)"),
161 ("$(foo['b\\\"ar'].bazz)"),
162
163 ("$(lst[O])"), # not "0" the number, but the letter O
164 ("$(lst[2])"),
165 ("$(lst.lengthz)"),
166 ("$(lst['lengthz'])"),
167
168 ("-$(foo.barz)"),
169 ("-$(foo['barz'])"),
170 ("-$(foo[\"barz\"])"),
171
172 ("-$(foo.bar.bazz)"),
173 ("-$(foo['bar'].bazz)"),
174 ("-$(foo['bar'][\"bazz\"])"),
175 ("-$(foo.bar['bazz'])"),
176
177 ("-$(foo['b ar'].bazz)"),
178 ("-$(foo['b\\'ar'].bazz)"),
179 ("-$(foo[\"b\\'ar\"].bazz)"),
180 ("-$(foo['b\\\"ar'].bazz)"),
181 ]
182
183 @pytest.mark.parametrize('pattern', interpolate_bad_parameters)
184 def test_expression_interpolate_failures(pattern):
185 result = None
186 try:
187 result = expr.interpolate(pattern, interpolate_input)
188 except JavascriptException:
189 return
190 assert false, 'Should have produced a JavascriptException, got "{}".'.format(result)
191
192
193 @windows_needs_docker
194 def test_factory():
195 factory = get_windows_safe_factory()
196 echo = factory.make(get_data("tests/echo.cwl"))
197
198 assert echo(inp="foo") == {"out": "foo\n"}
199
200
201 def test_factory_bad_outputs():
202 factory = cwltool.factory.Factory()
203
204 with pytest.raises(schema_salad.validate.ValidationException):
205 factory.make(get_data("tests/echo_broken_outputs.cwl"))
206
207
208 def test_factory_default_args():
209 factory = cwltool.factory.Factory()
210
211 assert factory.runtime_context.use_container is True
212 assert factory.runtime_context.on_error == "stop"
213
214
215 def test_factory_redefined_args():
216 runtime_context = RuntimeContext()
217 runtime_context.use_container = False
218 runtime_context.on_error = "continue"
219 factory = cwltool.factory.Factory(runtime_context=runtime_context)
220
221 assert factory.runtime_context.use_container is False
222 assert factory.runtime_context.on_error == "continue"
223
224
225 def test_factory_partial_scatter():
226 runtime_context = RuntimeContext()
227 runtime_context.on_error = "continue"
228 factory = cwltool.factory.Factory(runtime_context=runtime_context)
229
230 with pytest.raises(cwltool.factory.WorkflowStatus) as err_info:
231 factory.make(get_data("tests/wf/scatterfail.cwl"))()
232
233 err = err_info.value
234 assert err.out["out"][0]["checksum"] == 'sha1$e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e'
235 assert err.out["out"][1] is None
236 assert err.out["out"][2]["checksum"] == 'sha1$a3db5c13ff90a36963278c6a39e4ee3c22e2a436'
237
238
239 def test_factory_partial_output():
240 runtime_context = RuntimeContext()
241 runtime_context.on_error = "continue"
242 factory = cwltool.factory.Factory(runtime_context=runtime_context)
243
244 with pytest.raises(cwltool.factory.WorkflowStatus) as err_info:
245 factory.make(get_data("tests/wf/wffail.cwl"))()
246
247 err = err_info.value
248 assert err.out["out1"]["checksum"] == 'sha1$e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e'
249 assert err.out["out2"] is None
250
251
252 def test_scandeps():
253 obj = {
254 "id": "file:///example/foo.cwl",
255 "steps": [
256 {
257 "id": "file:///example/foo.cwl#step1",
258 "inputs": [{
259 "id": "file:///example/foo.cwl#input1",
260 "default": {
261 "class": "File",
262 "location": "file:///example/data.txt"
263 }
264 }],
265 "run": {
266 "id": "file:///example/bar.cwl",
267 "inputs": [{
268 "id": "file:///example/bar.cwl#input2",
269 "default": {
270 "class": "Directory",
271 "location": "file:///example/data2",
272 "listing": [{
273 "class": "File",
274 "location": "file:///example/data3.txt",
275 "secondaryFiles": [{
276 "class": "File",
277 "location": "file:///example/data5.txt"
278 }]
279 }]
280 },
281 }, {
282 "id": "file:///example/bar.cwl#input3",
283 "default": {
284 "class": "Directory",
285 "listing": [{
286 "class": "File",
287 "location": "file:///example/data4.txt"
288 }]
289 }
290 }, {
291 "id": "file:///example/bar.cwl#input4",
292 "default": {
293 "class": "File",
294 "contents": "file literal"
295 }
296 }]
297 }
298 }
299 ]
300 }
301
302 def loadref(base, p):
303 if isinstance(p, dict):
304 return p
305 raise Exception("test case can't load things")
306
307 scanned_deps = cwltool.process.scandeps(
308 obj["id"], obj,
309 {"$import", "run"},
310 {"$include", "$schemas", "location"},
311 loadref)
312
313 scanned_deps.sort(key=lambda k: k["basename"])
314
315 expected_deps = [
316 {"basename": "bar.cwl",
317 "nameroot": "bar",
318 "class": "File",
319 "format": CWL_IANA,
320 "nameext": ".cwl",
321 "location": "file:///example/bar.cwl"},
322 {"basename": "data.txt",
323 "nameroot": "data",
324 "class": "File",
325 "nameext": ".txt",
326 "location": "file:///example/data.txt"},
327 {"basename": "data2",
328 "class": "Directory",
329 "location": "file:///example/data2",
330 "listing": [
331 {"basename": "data3.txt",
332 "nameroot": "data3",
333 "class": "File",
334 "nameext": ".txt",
335 "location": "file:///example/data3.txt",
336 "secondaryFiles": [
337 {"class": "File",
338 "basename": "data5.txt",
339 "location": "file:///example/data5.txt",
340 "nameext": ".txt",
341 "nameroot": "data5"
342 }]
343 }]
344 }, {
345 "basename": "data4.txt",
346 "nameroot": "data4",
347 "class": "File",
348 "nameext": ".txt",
349 "location": "file:///example/data4.txt"
350 }]
351
352 assert scanned_deps == expected_deps
353
354 scanned_deps = cwltool.process.scandeps(
355 obj["id"], obj,
356 set(("run"), ),
357 set(), loadref)
358
359 scanned_deps.sort(key=lambda k: k["basename"])
360
361 expected_deps = [{
362 "basename": "bar.cwl",
363 "nameroot": "bar",
364 "format": CWL_IANA,
365 "class": "File",
366 "nameext": ".cwl",
367 "location": "file:///example/bar.cwl"
368 }]
369
370 assert scanned_deps == expected_deps
371
372 def test_trick_scandeps():
373 if sys.version_info[0] < 3:
374 stream = BytesIO()
375 else:
376 stream = StringIO()
377
378 main(["--print-deps", "--debug", get_data("tests/wf/trick_defaults.cwl")], stdout=stream)
379 assert json.loads(stream.getvalue())["secondaryFiles"][0]["location"][:2] != "_:"
380
381
382 def test_input_deps():
383 if sys.version_info[0] < 3:
384 stream = BytesIO()
385 else:
386 stream = StringIO()
387
388 main(["--print-input-deps", get_data("tests/wf/count-lines1-wf.cwl"),
389 get_data("tests/wf/wc-job.json")], stdout=stream)
390
391 expected = {"class": "File",
392 "location": "wc-job.json",
393 "format": CWL_IANA,
394 "secondaryFiles": [{"class": "File",
395 "location": "whale.txt",
396 "basename": "whale.txt",
397 "nameroot": "whale",
398 "nameext": ".txt"}]}
399 assert json.loads(stream.getvalue()) == expected
400
401
402 def test_input_deps_cmdline_opts():
403 if sys.version_info[0] < 3:
404 stream = BytesIO()
405 else:
406 stream = StringIO()
407
408 main(["--print-input-deps",
409 get_data("tests/wf/count-lines1-wf.cwl"),
410 "--file1", get_data("tests/wf/whale.txt")], stdout=stream)
411 expected = {"class": "File",
412 "location": "",
413 "format": CWL_IANA,
414 "secondaryFiles": [{"class": "File",
415 "location": "whale.txt",
416 "basename": "whale.txt",
417 "nameroot": "whale",
418 "nameext": ".txt"}]}
419 assert json.loads(stream.getvalue()) == expected
420
421
422 def test_input_deps_cmdline_opts_relative_deps_cwd():
423 if sys.version_info[0] < 3:
424 stream = BytesIO()
425 else:
426 stream = StringIO()
427
428 data_path = get_data("tests/wf/whale.txt")
429 main(["--print-input-deps", "--relative-deps", "cwd",
430 get_data("tests/wf/count-lines1-wf.cwl"),
431 "--file1", data_path], stdout=stream)
432
433 goal = {"class": "File",
434 "location": "",
435 "format": CWL_IANA,
436 "secondaryFiles": [{"class": "File",
437 "location": str(
438 Path(os.path.relpath(
439 data_path, os.path.curdir))),
440 "basename": "whale.txt",
441 "nameroot": "whale",
442 "nameext": ".txt"}]}
443 assert json.loads(stream.getvalue()) == goal
444
445
446 def test_dedupe():
447 not_deduped = [
448 {"class": "File",
449 "location": "file:///example/a"},
450 {"class": "File",
451 "location": "file:///example/a"},
452 {"class": "File",
453 "location": "file:///example/d"},
454 {"class": "Directory",
455 "location": "file:///example/c",
456 "listing": [
457 {"class": "File",
458 "location": "file:///example/d"}
459 ]}
460 ]
461
462 expected = [
463 {"class": "File",
464 "location": "file:///example/a"},
465 {"class": "Directory",
466 "location": "file:///example/c",
467 "listing": [
468 {"class": "File",
469 "location": "file:///example/d"}
470 ]}
471 ]
472
473 assert cwltool.pathmapper.dedup(not_deduped) == expected
474
475
476 record = {
477 'fields': [
478 {'type': {'items': 'string', 'type': 'array'},
479 'name': u'file:///home/chapmanb/drive/work/cwl/test_bcbio_cwl/run_info-cwl-workflow/wf-variantcall.cwl#vc_rec/vc_rec/description'
480 },
481 {'type': {'items': 'File', 'type': 'array'},
482 'name': u'file:///home/chapmanb/drive/work/cwl/test_bcbio_cwl/run_info-cwl-workflow/wf-variantcall.cwl#vc_rec/vc_rec/vrn_file'
483 }],
484 'type': 'record',
485 'name': u'file:///home/chapmanb/drive/work/cwl/test_bcbio_cwl/run_info-cwl-workflow/wf-variantcall.cwl#vc_rec/vc_rec'
486 }
487
488 source_to_sink = [
489 ('0',
490 {'items': ['string', 'null'], 'type': 'array'},
491 {'items': ['string', 'null'], 'type': 'array'},
492 True
493 ),
494 ('1',
495 {'items': ['string'], 'type': 'array'},
496 {'items': ['string', 'null'], 'type': 'array'},
497 True
498 ),
499 ('2',
500 {'items': ['string', 'null'], 'type': 'array'},
501 {'items': ['string'], 'type': 'array'},
502 True
503 ),
504 ('3',
505 {'items': ['string'], 'type': 'array'},
506 {'items': ['int'], 'type': 'array'},
507 False
508 ),
509 ('record 0',
510 record, record,
511 True
512 ),
513 ('record 1',
514 record, {'items': 'string', 'type': 'array'},
515 False
516 )
517 ]
518
519
520 @pytest.mark.parametrize('name, source, sink, expected', source_to_sink)
521 def test_compare_types(name, source, sink, expected):
522 assert cwltool.workflow.can_assign_src_to_sink(source, sink) == expected, name
523
524
525 source_to_sink_strict = [
526 ('0',
527 ['string', 'null'], ['string', 'null'],
528 True
529 ),
530 ('1',
531 ['string'], ['string', 'null'],
532 True
533 ),
534 ('2',
535 ['string', 'int'], ['string', 'null'],
536 False
537 ),
538 ('3',
539 {'items': ['string'], 'type': 'array'},
540 {'items': ['string', 'null'], 'type': 'array'},
541 True
542 ),
543 ('4',
544 {'items': ['string', 'int'], 'type': 'array'},
545 {'items': ['string', 'null'], 'type': 'array'},
546 False
547 )
548 ]
549
550
551 @pytest.mark.parametrize('name, source, sink, expected', source_to_sink_strict)
552 def test_compare_types_strict(name, source, sink, expected):
553 assert cwltool.workflow.can_assign_src_to_sink(source, sink, strict=True) == expected, name
554
555
556 typechecks = [
557 (['string', 'int'], ['string', 'int', 'null'],
558 None, None,
559 "pass"
560 ),
561 (['string', 'int'], ['string', 'null'],
562 None, None,
563 "warning"
564 ),
565 (['File', 'int'], ['string', 'null'],
566 None, None,
567 "exception"
568 ),
569 ({'items': ['string', 'int'], 'type': 'array'},
570 {'items': ['string', 'int', 'null'], 'type': 'array'},
571 None, None,
572 "pass"
573 ),
574 ({'items': ['string', 'int'], 'type': 'array'},
575 {'items': ['string', 'null'], 'type': 'array'},
576 None, None,
577 "warning"
578 ),
579 ({'items': ['File', 'int'], 'type': 'array'},
580 {'items': ['string', 'null'], 'type': 'array'},
581 None, None,
582 "exception"
583 ),
584 # check linkMerge when sinktype is not an array
585 (['string', 'int'], ['string', 'int', 'null'],
586 "merge_nested", None,
587 "exception"
588 ),
589 # check linkMerge: merge_nested
590 (['string', 'int'],
591 {'items': ['string', 'int', 'null'], 'type': 'array'},
592 "merge_nested", None,
593 "pass"
594 ),
595 (['string', 'int'],
596 {'items': ['string', 'null'], 'type': 'array'},
597 "merge_nested", None,
598 "warning"
599 ),
600 (['File', 'int'],
601 {'items': ['string', 'null'], 'type': 'array'},
602 "merge_nested", None,
603 "exception"
604 ),
605 # check linkMerge: merge_nested and sinktype is "Any"
606 (['string', 'int'], "Any",
607 "merge_nested", None,
608 "pass"
609 ),
610 # check linkMerge: merge_flattened
611 (['string', 'int'],
612 {'items': ['string', 'int', 'null'], 'type': 'array'},
613 "merge_flattened", None,
614 "pass"
615 ),
616 (['string', 'int'],
617 {'items': ['string', 'null'], 'type': 'array'},
618 "merge_flattened", None,
619 "warning"
620 ),
621 (['File', 'int'],
622 {'items': ['string', 'null'], 'type': 'array'},
623 "merge_flattened", None,
624 "exception"
625 ),
626 ({'items': ['string', 'int'], 'type': 'array'},
627 {'items': ['string', 'int', 'null'], 'type': 'array'},
628 "merge_flattened", None,
629 "pass"
630 ),
631 ({'items': ['string', 'int'], 'type': 'array'},
632 {'items': ['string', 'null'], 'type': 'array'},
633 "merge_flattened", None,
634 "warning"
635 ),
636 ({'items': ['File', 'int'], 'type': 'array'},
637 {'items': ['string', 'null'], 'type': 'array'},
638 "merge_flattened", None,
639 "exception"),
640 # check linkMerge: merge_flattened and sinktype is "Any"
641 (['string', 'int'], "Any",
642 "merge_flattened", None,
643 "pass"
644 ),
645 ({'items': ['string', 'int'], 'type': 'array'}, "Any",
646 "merge_flattened", None,
647 "pass"
648 ),
649 # check linkMerge: merge_flattened when srctype is a list
650 ([{'items': 'string', 'type': 'array'}],
651 {'items': 'string', 'type': 'array'},
652 "merge_flattened", None,
653 "pass"
654 ),
655 # check valueFrom
656 ({'items': ['File', 'int'], 'type': 'array'},
657 {'items': ['string', 'null'], 'type': 'array'},
658 "merge_flattened", "special value",
659 "pass"
660 )
661 ]
662
663
664 @pytest.mark.parametrize('src_type,sink_type,link_merge,value_from,expected_type', typechecks)
665 def test_typechecking(src_type, sink_type, link_merge, value_from, expected_type):
666 assert cwltool.checker.check_types(
667 src_type, sink_type, linkMerge=link_merge, valueFrom=value_from
668 ) == expected_type
669
670
671 def test_lifting():
672 # check that lifting the types of the process outputs to the workflow step
673 # fails if the step 'out' doesn't match.
674 factory = cwltool.factory.Factory()
675 with pytest.raises(schema_salad.validate.ValidationException):
676 echo = factory.make(get_data("tests/test_bad_outputs_wf.cwl"))
677 assert echo(inp="foo") == {"out": "foo\n"}
678
679
680 def test_malformed_outputs():
681 # check that tool validation fails if one of the outputs is not a valid CWL type
682 factory = cwltool.factory.Factory()
683 with pytest.raises(schema_salad.validate.ValidationException):
684 factory.make(get_data("tests/wf/malformed_outputs.cwl"))()
685
686
687 def test_separate_without_prefix():
688 # check that setting 'separate = false' on an inputBinding without prefix fails the workflow
689 factory = cwltool.factory.Factory()
690 with pytest.raises(WorkflowException):
691 factory.make(get_data("tests/wf/separate_without_prefix.cwl"))()
692
693
694 def test_static_checker():
695 # check that the static checker raises exception when a source type
696 # mismatches its sink type.
697 factory = cwltool.factory.Factory()
698
699 with pytest.raises(schema_salad.validate.ValidationException):
700 factory.make(get_data("tests/checker_wf/broken-wf.cwl"))
701
702 with pytest.raises(schema_salad.validate.ValidationException):
703 factory.make(get_data("tests/checker_wf/broken-wf2.cwl"))
704
705 with pytest.raises(schema_salad.validate.ValidationException):
706 factory.make(get_data("tests/checker_wf/broken-wf3.cwl"))
707
708
709 def test_var_spool_cwl_checker1():
710 """Confirm that references to /var/spool/cwl are caught."""
711 stream = StringIO()
712 streamhandler = logging.StreamHandler(stream)
713 _logger = logging.getLogger("cwltool")
714 _logger.addHandler(streamhandler)
715
716 factory = cwltool.factory.Factory()
717 try:
718 factory.make(get_data("tests/non_portable.cwl"))
719 assert "non_portable.cwl:18:4: Non-portable reference to /var/spool/cwl detected" in stream.getvalue()
720 finally:
721 _logger.removeHandler(streamhandler)
722
723
724 def test_var_spool_cwl_checker2():
725 """Confirm that references to /var/spool/cwl are caught."""
726 stream = StringIO()
727 streamhandler = logging.StreamHandler(stream)
728 _logger = logging.getLogger("cwltool")
729 _logger.addHandler(streamhandler)
730
731 factory = cwltool.factory.Factory()
732 try:
733 factory.make(get_data("tests/non_portable2.cwl"))
734 assert "non_portable2.cwl:19:4: Non-portable reference to /var/spool/cwl detected" in stream.getvalue()
735 finally:
736 _logger.removeHandler(streamhandler)
737
738
739 def test_var_spool_cwl_checker3():
740 """Confirm that references to /var/spool/cwl are caught."""
741 stream = StringIO()
742 streamhandler = logging.StreamHandler(stream)
743 _logger = logging.getLogger("cwltool")
744 _logger.addHandler(streamhandler)
745
746 factory = cwltool.factory.Factory()
747 try:
748 factory.make(get_data("tests/portable.cwl"))
749 assert "Non-portable reference to /var/spool/cwl detected" not in stream.getvalue()
750 finally:
751 _logger.removeHandler(streamhandler)
752
753
754 def test_print_dot():
755 assert main(["--print-dot", get_data('tests/wf/revsort.cwl')]) == 0
756
757 test_factors = [(""), ("--parallel"), ("--debug"), ("--parallel --debug")]
758
759 @pytest.mark.parametrize("factor", test_factors)
760 def test_js_console_cmd_line_tool(factor):
761 for test_file in ("js_output.cwl", "js_output_workflow.cwl"):
762 commands = factor.split()
763 commands.extend(["--js-console", "--no-container", get_data("tests/wf/" + test_file)])
764 error_code, _, stderr = get_main_output(commands)
765
766 assert "[log] Log message" in stderr
767 assert "[err] Error message" in stderr
768
769 assert error_code == 0, stderr
770
771 @pytest.mark.parametrize("factor", test_factors)
772 def test_no_js_console(factor):
773 for test_file in ("js_output.cwl", "js_output_workflow.cwl"):
774 commands = factor.split()
775 commands.extend(["--no-container", get_data("tests/wf/" + test_file)])
776 _, _, stderr = get_main_output(commands)
777
778 assert "[log] Log message" not in stderr
779 assert "[err] Error message" not in stderr
780
781
782 @needs_docker
783 @pytest.mark.parametrize("factor", test_factors)
784 def test_cid_file_dir(tmpdir, factor):
785 test_file = "cache_test_workflow.cwl"
786 cwd = tmpdir.chdir()
787 commands = factor.split()
788 commands.extend(["--cidfile-dir", str(tmpdir), get_data("tests/wf/" + test_file)])
789 error_code, stdout, stderr = get_main_output(commands)
790 assert "completed success" in stderr
791 assert error_code == 0
792 cidfiles_count = sum(1 for _ in tmpdir.visit(fil="*"))
793 assert cidfiles_count == 2
794 cwd.chdir()
795 tmpdir.remove(ignore_errors=True)
796
797
798 @needs_docker
799 @pytest.mark.parametrize("factor", test_factors)
800 def test_cid_file_dir_arg_is_file_instead_of_dir(tmpdir, factor):
801 test_file = "cache_test_workflow.cwl"
802 bad_cidfile_dir = Text(tmpdir.ensure("cidfile-dir-actually-a-file"))
803 commands = factor.split()
804 commands.extend(["--cidfile-dir", bad_cidfile_dir,
805 get_data("tests/wf/" + test_file)])
806 error_code, _, stderr = get_main_output(commands)
807 assert "is not a directory, please check it first" in stderr, stderr
808 assert error_code == 2 or error_code == 1, stderr
809 tmpdir.remove(ignore_errors=True)
810
811
812 @needs_docker
813 @pytest.mark.parametrize("factor", test_factors)
814 def test_cid_file_non_existing_dir(tmpdir, factor):
815 test_file = "cache_test_workflow.cwl"
816 bad_cidfile_dir = Text(tmpdir.join("cidfile-dir-badpath"))
817 commands = factor.split()
818 commands.extend(['--record-container-id',"--cidfile-dir", bad_cidfile_dir,
819 get_data("tests/wf/" + test_file)])
820 error_code, _, stderr = get_main_output(commands)
821 assert "directory doesn't exist, please create it first" in stderr, stderr
822 assert error_code == 2 or error_code == 1, stderr
823 tmpdir.remove(ignore_errors=True)
824
825
826 @needs_docker
827 @pytest.mark.parametrize("factor", test_factors)
828 def test_cid_file_w_prefix(tmpdir, factor):
829 test_file = "cache_test_workflow.cwl"
830 cwd = tmpdir.chdir()
831 try:
832 commands = factor.split()
833 commands.extend(['--record-container-id', '--cidfile-prefix=pytestcid',
834 get_data("tests/wf/" + test_file)])
835 error_code, stdout, stderr = get_main_output(commands)
836 finally:
837 listing = tmpdir.listdir()
838 cwd.chdir()
839 cidfiles_count = sum(1 for _ in tmpdir.visit(fil="pytestcid*"))
840 tmpdir.remove(ignore_errors=True)
841 assert "completed success" in stderr
842 assert error_code == 0
843 assert cidfiles_count == 2, '{}/n{}'.format(listing, stderr)
844
845
846 @needs_docker
847 @pytest.mark.parametrize("factor", test_factors)
848 def test_secondary_files_v1_1(factor):
849 test_file = "secondary-files.cwl"
850 test_job_file = "secondary-files-job.yml"
851 try:
852 old_umask = os.umask(stat.S_IWOTH) # test run with umask 002
853 commands = factor.split()
854 commands.extend(["--enable-dev",
855 get_data(os.path.join("tests", test_file)),
856 get_data(os.path.join("tests", test_job_file))])
857 error_code, _, stderr = get_main_output(commands)
858 finally:
859 assert stat.S_IMODE(os.stat('lsout').st_mode) == 436 # 664 in octal, '-rw-rw-r--'
860 os.umask(old_umask) # revert back to original umask
861 assert "completed success" in stderr
862 assert error_code == 0
863
864 @needs_docker
865 @pytest.mark.parametrize("factor", test_factors)
866 def test_secondary_files_v1_0(factor):
867 test_file = "secondary-files-string-v1.cwl"
868 test_job_file = "secondary-files-job.yml"
869 try:
870 old_umask = os.umask(stat.S_IWOTH) # test run with umask 002
871 commands = factor.split()
872 commands.extend([
873 get_data(os.path.join("tests", test_file)),
874 get_data(os.path.join("tests", test_job_file))
875 ])
876 error_code, _, stderr = get_main_output(commands)
877 finally:
878 assert stat.S_IMODE(os.stat('lsout').st_mode) == 436 # 664 in octal, '-rw-rw-r--'
879 os.umask(old_umask) # revert back to original umask
880 assert "completed success" in stderr
881 assert error_code == 0
882
883
884 @needs_docker
885 @pytest.mark.parametrize("factor", test_factors)
886 def test_wf_without_container(tmpdir, factor):
887 test_file = "hello-workflow.cwl"
888 with temp_dir("cwltool_cache") as cache_dir:
889 commands = factor.split()
890 commands.extend(["--cachedir", cache_dir, "--outdir", str(tmpdir),
891 get_data("tests/wf/" + test_file),
892 "--usermessage",
893 "hello"])
894 error_code, _, stderr = get_main_output(commands)
895
896 assert "completed success" in stderr
897 assert error_code == 0
898
899
900 @needs_docker
901 @pytest.mark.parametrize("factor", test_factors)
902 def test_issue_740_fixed(factor):
903 test_file = "cache_test_workflow.cwl"
904 with temp_dir("cwltool_cache") as cache_dir:
905 commands = factor.split()
906 commands.extend(["--cachedir", cache_dir, get_data("tests/wf/" + test_file)])
907 error_code, _, stderr = get_main_output(commands)
908
909 assert "completed success" in stderr
910 assert error_code == 0
911
912 commands = factor.split()
913 commands.extend(["--cachedir", cache_dir, get_data("tests/wf/" + test_file)])
914 error_code, _, stderr = get_main_output(commands)
915
916 assert "Output of job will be cached in" not in stderr
917 assert error_code == 0, stderr
918
919
920 @needs_docker
921 def test_compute_checksum():
922 runtime_context = RuntimeContext()
923 runtime_context.compute_checksum = True
924 runtime_context.use_container = onWindows()
925 factory = cwltool.factory.Factory(runtime_context=runtime_context)
926 echo = factory.make(get_data("tests/wf/cat-tool.cwl"))
927 output = echo(
928 file1={"class": "File",
929 "location": get_data("tests/wf/whale.txt")},
930 reverse=False)
931 assert output['output']["checksum"] == "sha1$327fc7aedf4f6b69a42a7c8b808dc5a7aff61376"
932
933
934 @needs_docker
935 @pytest.mark.parametrize("factor", test_factors)
936 def test_no_compute_chcksum(tmpdir, factor):
937 test_file = "tests/wf/wc-tool.cwl"
938 job_file = "tests/wf/wc-job.json"
939 commands = factor.split()
940 commands.extend(["--no-compute-checksum", "--outdir", str(tmpdir),
941 get_data(test_file), get_data(job_file)])
942 error_code, stdout, stderr = get_main_output(commands)
943 assert "completed success" in stderr
944 assert error_code == 0
945 assert "checksum" not in stdout
946
947
948 @pytest.mark.parametrize("factor", test_factors)
949 def test_bad_userspace_runtime(factor):
950 test_file = "tests/wf/wc-tool.cwl"
951 job_file = "tests/wf/wc-job.json"
952 commands = factor.split()
953 commands.extend([
954 "--user-space-docker-cmd=quaquioN", "--default-container=debian",
955 get_data(test_file), get_data(job_file)])
956 error_code, stdout, stderr = get_main_output(commands)
957 assert "or quaquioN is missing or broken" in stderr, stderr
958 assert error_code == 1
959
960 @windows_needs_docker
961 @pytest.mark.parametrize("factor", test_factors)
962 def test_bad_basecommand(factor):
963 test_file = "tests/wf/missing-tool.cwl"
964 commands = factor.split()
965 commands.extend([get_data(test_file)])
966 error_code, stdout, stderr = get_main_output(commands)
967 assert "'neenooGo' not found" in stderr, stderr
968 assert error_code == 1
969
970
971 @needs_docker
972 @pytest.mark.parametrize("factor", test_factors)
973 def test_bad_basecommand_docker(factor):
974 test_file = "tests/wf/missing-tool.cwl"
975 commands = factor.split()
976 commands.extend(
977 ["--debug", "--default-container", "debian", get_data(test_file)])
978 error_code, stdout, stderr = get_main_output(commands)
979 assert "permanentFail" in stderr, stderr
980 assert error_code == 1
981
982 @pytest.mark.parametrize("factor", test_factors)
983 def test_v1_0_position_expression(factor):
984 test_file = "tests/echo-position-expr.cwl"
985 test_job = "tests/echo-position-expr-job.yml"
986 commands = factor.split()
987 commands.extend(
988 ['--debug', get_data(test_file), get_data(test_job)])
989 error_code, stdout, stderr = get_main_output(commands)
990 assert "is not int" in stderr, stderr
991 assert error_code == 1
992
993
994 @windows_needs_docker
995 @pytest.mark.parametrize("factor", test_factors)
996 def test_optional_numeric_output_0(factor):
997 test_file = "tests/wf/optional-numerical-output-0.cwl"
998 commands = factor.split()
999 commands.extend([get_data(test_file)])
1000 error_code, stdout, stderr = get_main_output(commands)
1001
1002 assert "completed success" in stderr
1003 assert error_code == 0
1004 assert json.loads(stdout)['out'] == 0
1005
1006 @pytest.mark.parametrize("factor", test_factors)
1007 @windows_needs_docker
1008 def test_env_filtering(factor):
1009 test_file = "tests/env.cwl"
1010 commands = factor.split()
1011 commands.extend([get_data(test_file)])
1012 error_code, stdout, stderr = get_main_output(commands)
1013
1014 process = subprocess.Popen(["sh", "-c", r"""getTrueShellExeName() {
1015 local trueExe nextTarget 2>/dev/null
1016 trueExe=$(ps -o comm= $$) || return 1
1017 [ "${trueExe#-}" = "$trueExe" ] || trueExe=${trueExe#-}
1018 [ "${trueExe#/}" != "$trueExe" ] || trueExe=$([ -n "$ZSH_VERSION" ] && which -p "$trueExe" || which "$trueExe")
1019 while nextTarget=$(readlink "$trueExe"); do trueExe=$nextTarget; done
1020 printf '%s\n' "$(basename "$trueExe")"
1021 } ; getTrueShellExeName"""], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=None)
1022 sh_name, sh_name_err = process.communicate()
1023 sh_name = sh_name.decode('utf-8').strip()
1024
1025 assert "completed success" in stderr, (error_code, stdout, stderr)
1026 assert error_code == 0, (error_code, stdout, stderr)
1027 if onWindows():
1028 target = 5
1029 elif sh_name == "dash":
1030 target = 4
1031 else: # bash adds "SHLVL" and "_" environment variables
1032 target = 6
1033 result = json.loads(stdout)['env_count']
1034 details = ''
1035 if result != target:
1036 _, details, _ = get_main_output(["--quiet", get_data("tests/env2.cwl")])
1037 print(sh_name)
1038 print(sh_name_err)
1039 print(details)
1040 assert result == target, (error_code, sh_name, sh_name_err, details, stdout, stderr)
1041
1042 @windows_needs_docker
1043 def test_v1_0_arg_empty_prefix_separate_false():
1044 test_file = "tests/arg-empty-prefix-separate-false.cwl"
1045 error_code, stdout, stderr = get_main_output(
1046 ['--debug', get_data(test_file), "--echo"])
1047 assert "completed success" in stderr
1048 assert error_code == 0