9751: Fix unit tests. Rename dir6.cwl to keep-dir-test-input.cwl
[arvados.git] / sdk / cwl / tests / test_job.py
1 import arvados_cwl
2 import logging
3 import mock
4 import unittest
5 import os
6 import functools
7 import cwltool.process
8
9 if not os.getenv('ARVADOS_DEBUG'):
10     logging.getLogger('arvados.cwl-runner').setLevel(logging.WARN)
11     logging.getLogger('arvados.arv-run').setLevel(logging.WARN)
12
13
14 class TestJob(unittest.TestCase):
15
16     # The test passes no builder.resources
17     # Hence the default resources will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
18     def test_run(self):
19         runner = mock.MagicMock()
20         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
21         runner.ignore_docker_for_reuse = False
22         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("draft-3")
23
24         tool = {
25             "inputs": [],
26             "outputs": [],
27             "baseCommand": "ls",
28             "arguments": [{"valueFrom": "$(runtime.outdir)"}]
29         }
30         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="jobs", avsc_names=avsc_names, basedir="")
31         arvtool.formatgraph = None
32         for j in arvtool.job({}, mock.MagicMock(), basedir="",
33         make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess, api_client=runner.api)):
34             j.run()
35             runner.api.jobs().create.assert_called_with(
36                 body={
37                     'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
38                     'runtime_constraints': {},
39                     'script_parameters': {
40                         'tasks': [{
41                             'task.env': {'TMPDIR': '$(task.tmpdir)'},
42                             'command': ['ls', '$(task.outdir)']
43                         }],
44                     },
45                     'script_version': 'master',
46                     'minimum_script_version': '9e5b98e8f5f4727856b53447191f9c06e3da2ba6',
47                     'repository': 'arvados',
48                     'script': 'crunchrunner',
49                     'runtime_constraints': {
50                         'docker_image': 'arvados/jobs',
51                         'min_cores_per_node': 1,
52                         'min_ram_mb_per_node': 1024,
53                         'min_scratch_mb_per_node': 2048 # tmpdirSize + outdirSize
54                     }
55                 },
56                 find_or_create=True,
57                 filters=[['repository', '=', 'arvados'],
58                          ['script', '=', 'crunchrunner'],
59                          ['script_version', 'in git', '9e5b98e8f5f4727856b53447191f9c06e3da2ba6'],
60                          ['docker_image_locator', 'in docker', 'arvados/jobs']]
61             )
62
63     # The test passes some fields in builder.resources
64     # For the remaining fields, the defaults will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
65     def test_resource_requirements(self):
66         runner = mock.MagicMock()
67         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
68         runner.ignore_docker_for_reuse = False
69         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("draft-3")
70
71         tool = {
72             "inputs": [],
73             "outputs": [],
74             "hints": [{
75                 "class": "ResourceRequirement",
76                 "coresMin": 3,
77                 "ramMin": 3000,
78                 "tmpdirMin": 4000
79             }],
80             "baseCommand": "ls"
81         }
82         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="jobs", avsc_names=avsc_names)
83         arvtool.formatgraph = None
84         for j in arvtool.job({}, mock.MagicMock(), basedir=""):
85             j.run()
86         runner.api.jobs().create.assert_called_with(
87             body={
88                 'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
89                 'runtime_constraints': {},
90                 'script_parameters': {
91                     'tasks': [{
92                         'task.env': {'TMPDIR': '$(task.tmpdir)'},
93                         'command': ['ls']
94                     }]
95             },
96             'script_version': 'master',
97                 'minimum_script_version': '9e5b98e8f5f4727856b53447191f9c06e3da2ba6',
98                 'repository': 'arvados',
99                 'script': 'crunchrunner',
100                 'runtime_constraints': {
101                     'docker_image': 'arvados/jobs',
102                     'min_cores_per_node': 3,
103                     'min_ram_mb_per_node': 3000,
104                     'min_scratch_mb_per_node': 5024 # tmpdirSize + outdirSize
105                 }
106             },
107             find_or_create=True,
108             filters=[['repository', '=', 'arvados'],
109                      ['script', '=', 'crunchrunner'],
110                      ['script_version', 'in git', '9e5b98e8f5f4727856b53447191f9c06e3da2ba6'],
111                      ['docker_image_locator', 'in docker', 'arvados/jobs']])
112
113     @mock.patch("arvados.collection.Collection")
114     def test_done(self, col):
115         api = mock.MagicMock()
116
117         runner = mock.MagicMock()
118         runner.api = api
119         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
120         runner.num_retries = 0
121         runner.ignore_docker_for_reuse = False
122
123         col().open.return_value = []
124         api.collections().list().execute.side_effect = ({"items": []},
125                                                         {"items": [{"manifest_text": "XYZ"}]})
126
127         arvjob = arvados_cwl.ArvadosJob(runner)
128         arvjob.name = "testjob"
129         arvjob.builder = mock.MagicMock()
130         arvjob.output_callback = mock.MagicMock()
131         arvjob.collect_outputs = mock.MagicMock()
132
133         arvjob.done({
134             "state": "Complete",
135             "output": "99999999999999999999999999999993+99",
136             "log": "99999999999999999999999999999994+99",
137             "uuid": "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
138         })
139
140         api.collections().list.assert_has_calls([
141             mock.call(),
142             mock.call(filters=[['owner_uuid', '=', 'zzzzz-8i9sb-zzzzzzzzzzzzzzz'],
143                           ['portable_data_hash', '=', '99999999999999999999999999999993+99'],
144                           ['name', '=', 'Output 9999999 of testjob']]),
145             mock.call().execute(num_retries=0),
146             mock.call(limit=1, filters=[['portable_data_hash', '=', '99999999999999999999999999999993+99']],
147                  select=['manifest_text']),
148             mock.call().execute(num_retries=0)])
149
150         api.collections().create.assert_called_with(
151             ensure_unique_name=True,
152             body={'portable_data_hash': '99999999999999999999999999999993+99',
153                   'manifest_text': 'XYZ',
154                   'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
155                   'name': 'Output 9999999 of testjob'})
156
157     @mock.patch("arvados.collection.Collection")
158     def test_done_use_existing_collection(self, col):
159         api = mock.MagicMock()
160
161         runner = mock.MagicMock()
162         runner.api = api
163         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
164         runner.num_retries = 0
165
166         col().open.return_value = []
167         api.collections().list().execute.side_effect = ({"items": [{"uuid": "zzzzz-4zz18-zzzzzzzzzzzzzz2"}]},)
168
169         arvjob = arvados_cwl.ArvadosJob(runner)
170         arvjob.name = "testjob"
171         arvjob.builder = mock.MagicMock()
172         arvjob.output_callback = mock.MagicMock()
173         arvjob.collect_outputs = mock.MagicMock()
174
175         arvjob.done({
176             "state": "Complete",
177             "output": "99999999999999999999999999999993+99",
178             "log": "99999999999999999999999999999994+99",
179             "uuid": "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
180         })
181
182         api.collections().list.assert_has_calls([
183             mock.call(),
184             mock.call(filters=[['owner_uuid', '=', 'zzzzz-8i9sb-zzzzzzzzzzzzzzz'],
185                                ['portable_data_hash', '=', '99999999999999999999999999999993+99'],
186                                ['name', '=', 'Output 9999999 of testjob']]),
187             mock.call().execute(num_retries=0)])
188
189         self.assertFalse(api.collections().create.called)