Test Setup Failed
Pull Request — master (#4154)
by W
03:25
created

test_fail_output_rendering()   B

Complexity

Conditions 1

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 37
rs 8.8571
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
from __future__ import absolute_import
17
18
import mock
19
20
from orchestra import states as wf_states
21
22
import st2tests
23
24
# XXX: actionsensor import depends on config being setup.
25
import st2tests.config as tests_config
26
tests_config.parse_args()
27
28
from tests.unit import base
29
30
from st2common.bootstrap import actionsregistrar
31
from st2common.bootstrap import runnersregistrar
32
from st2common.constants import action as ac_const
33
from st2common.models.db import liveaction as lv_db_models
34
from st2common.persistence import execution as ex_db_access
35
from st2common.persistence import liveaction as lv_db_access
36
from st2common.persistence import workflow as wf_db_access
37
from st2common.runners import base as runners
38
from st2common.services import action as ac_svc
39
from st2common.services import workflows as wf_svc
40
from st2common.transport import liveaction as lv_ac_xport
41
from st2common.transport import workflow as wf_ex_xport
42
from st2common.transport import publishers
43
from st2tests.mocks import liveaction as mock_lv_ac_xport
44
from st2tests.mocks import workflow as mock_wf_ex_xport
45
46
47
TEST_PACK = 'orchestra_tests'
48
TEST_PACK_PATH = st2tests.fixturesloader.get_fixtures_packs_base_path() + '/' + TEST_PACK
49
50
PACKS = [
51
    TEST_PACK_PATH,
52
    st2tests.fixturesloader.get_fixtures_packs_base_path() + '/core'
53
]
54
55
56
@mock.patch.object(
57
    publishers.CUDPublisher,
58
    'publish_update',
59
    mock.MagicMock(return_value=None))
60
@mock.patch.object(
61
    lv_ac_xport.LiveActionPublisher,
62
    'publish_create',
63
    mock.MagicMock(side_effect=mock_lv_ac_xport.MockLiveActionPublisher.publish_create))
64
@mock.patch.object(
65
    lv_ac_xport.LiveActionPublisher,
66
    'publish_state',
67
    mock.MagicMock(side_effect=mock_lv_ac_xport.MockLiveActionPublisher.publish_state))
68
@mock.patch.object(
69
    wf_ex_xport.WorkflowExecutionPublisher,
70
    'publish_create',
71
    mock.MagicMock(side_effect=mock_wf_ex_xport.MockWorkflowExecutionPublisher.publish_create))
72
@mock.patch.object(
73
    wf_ex_xport.WorkflowExecutionPublisher,
74
    'publish_state',
75
    mock.MagicMock(side_effect=mock_wf_ex_xport.MockWorkflowExecutionPublisher.publish_state))
76
class OrchestraErrorHandlingTest(st2tests.DbTestCase):
77
78
    @classmethod
79
    def setUpClass(cls):
80
        super(OrchestraErrorHandlingTest, cls).setUpClass()
81
82
        # Register runners.
83
        runnersregistrar.register_runners()
84
85
        # Register test pack(s).
86
        actions_registrar = actionsregistrar.ActionsRegistrar(
87
            use_pack_cache=False,
88
            fail_on_failure=True
89
        )
90
91
        for pack in PACKS:
92
            actions_registrar.register_from_pack(pack)
93
94
    @classmethod
95
    def get_runner_class(cls, runner_name):
96
        return runners.get_runner(runner_name, runner_name).__class__
97
98
    def sort_wf_runtime_errors(self, errors):
99
        return sorted(errors, key=lambda x: x.get('task_id', None))
100
101
    def test_fail_inspection(self):
102
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-inspection.yaml')
103
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
104
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
105
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
106
107
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
108
        self.assertIn('errors', lv_ac_db.result)
109
        self.assertIn('expressions', lv_ac_db.result['errors'])
110
        self.assertGreater(len(lv_ac_db.result['errors']['expressions']), 0)
111
        self.assertIn('context', lv_ac_db.result['errors'])
112
        self.assertGreater(len(lv_ac_db.result['errors']['context']), 0)
113
        self.assertIn('syntax', lv_ac_db.result['errors'])
114
        self.assertGreater(len(lv_ac_db.result['errors']['syntax']), 0)
115
116
    def test_fail_input_rendering(self):
117
        expected_errors = [
118
            {
119
                'message': 'Unknown function "#property#value"'
120
            }
121
        ]
122
123
        expected_result = {'output': None, 'errors': expected_errors}
124
125
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-input-rendering.yaml')
126
127
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
128
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
129
130
        # Assert action execution for task is not started and workflow failed.
131
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
132
        tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))
133
        self.assertEqual(len(tk_ex_dbs), 0)
134
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
135
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
136
137
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
138
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
139
        self.assertDictEqual(lv_ac_db.result, expected_result)
140
141
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
142
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
143
        self.assertDictEqual(ac_ex_db.result, expected_result)
144
145
    def test_fail_vars_rendering(self):
146
        expected_errors = [
147
            {
148
                'message': 'Unknown function "#property#value"'
149
            }
150
        ]
151
152
        expected_result = {'output': None, 'errors': expected_errors}
153
154
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-vars-rendering.yaml')
155
156
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
157
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
158
159
        # Assert action execution for task is not started and workflow failed.
160
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
161
        tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))
162
        self.assertEqual(len(tk_ex_dbs), 0)
163
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
164
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
165
166
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
167
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
168
        self.assertDictEqual(lv_ac_db.result, expected_result)
169
170
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
171
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
172
        self.assertDictEqual(ac_ex_db.result, expected_result)
173
174
    def test_fail_start_task_action(self):
175
        expected_errors = [
176
            {
177
                'message': 'Unknown function "#property#value"',
178
                'task_id': 'task1'
179
            }
180
        ]
181
182
        expected_result = {'output': None, 'errors': expected_errors}
183
184
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-start-task-action.yaml')
185
186
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
187
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
188
189
        # Assert action execution for task is not started and workflow failed.
190
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
191
        tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))
192
        self.assertEqual(len(tk_ex_dbs), 0)
193
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
194
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
195
196
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
197
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
198
        self.assertDictEqual(lv_ac_db.result, expected_result)
199
200
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
201
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
202
        self.assertDictEqual(ac_ex_db.result, expected_result)
203
204
    def test_fail_start_task_input_expr_eval(self):
205
        expected_errors = [
206
            {
207
                'message': 'Unknown function "#property#value"',
208
                'task_id': 'task1'
209
            }
210
        ]
211
212
        expected_result = {'output': None, 'errors': expected_errors}
213
214
        wf_file = 'fail-start-task-input-expr-eval.yaml'
215
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file)
216
217
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
218
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
219
220
        # Assert action execution for task is not started and workflow failed.
221
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
222
        tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))
223
        self.assertEqual(len(tk_ex_dbs), 0)
224
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
225
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
226
227
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
228
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
229
        self.assertDictEqual(lv_ac_db.result, expected_result)
230
231
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
232
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
233
        self.assertDictEqual(ac_ex_db.result, expected_result)
234
235
    def test_fail_start_task_input_value_type(self):
236
        expected_errors = [
237
            {
238
                'message': 'Value "{u\'x\': u\'foobar\'}" must either '
239
                           'be a string or None. Got "dict".',
240
                'task_id': 'task1'
241
            }
242
        ]
243
244
        expected_result = {'output': None, 'errors': expected_errors}
245
246
        wf_file = 'fail-start-task-input-value-type.yaml'
247
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file)
248
        wf_input = {'var1': {'x': 'foobar'}}
249
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input)
250
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
251
252
        # Assert workflow and task executions failed.
253
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
254
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
255
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
256
257
        tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
258
        self.assertEqual(tk_ex_db.status, wf_states.FAILED)
259
        self.assertDictEqual(tk_ex_db.result, {'errors': expected_errors})
260
261
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
262
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
263
        self.assertDictEqual(lv_ac_db.result, expected_result)
264
265
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
266
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
267
        self.assertDictEqual(ac_ex_db.result, expected_result)
268
269
    def test_fail_next_task_action(self):
270
        expected_errors = [
271
            {
272
                'message': 'Unknown function "#property#value"',
273
                'task_id': 'task2'
274
            }
275
        ]
276
277
        expected_result = {'output': None, 'errors': expected_errors}
278
279
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-action.yaml')
280
281
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
282
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
283
284
        # Assert task1 is already completed.
285
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
286
        tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
287
        tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0]
288
        tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id'])
289
        self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
290
291
        # Manually handle action execution completion for task1 which has an error in publish.
292
        wf_svc.handle_action_execution_completion(tk_ac_ex_db)
293
294
        # Assert task1 succeeded but workflow failed.
295
        tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id)
296
        self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED)
297
        wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id)
298
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
299
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
300
301
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
302
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
303
        self.assertDictEqual(lv_ac_db.result, expected_result)
304
305
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
306
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
307
        self.assertDictEqual(ac_ex_db.result, expected_result)
308
309
    def test_fail_next_task_input_expr_eval(self):
310
        expected_errors = [
311
            {
312
                'message': 'Unknown function "#property#value"',
313
                'task_id': 'task2'
314
            }
315
        ]
316
317
        expected_result = {'output': None, 'errors': expected_errors}
318
319
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-input-expr-eval.yaml')
320
321
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
322
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
323
324
        # Assert task1 is already completed.
325
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
326
        tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
327
        tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0]
328
        tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id'])
329
        self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
330
331
        # Manually handle action execution completion for task1 which has an error in publish.
332
        wf_svc.handle_action_execution_completion(tk_ac_ex_db)
333
334
        # Assert task1 succeeded but workflow failed.
335
        tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id)
336
        self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED)
337
        wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id)
338
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
339
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
340
341
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
342
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
343
        self.assertDictEqual(lv_ac_db.result, expected_result)
344
345
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
346
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
347
        self.assertDictEqual(ac_ex_db.result, expected_result)
348
349
    def test_fail_next_task_input_value_type(self):
350
        expected_errors = [
351
            {
352
                'message': 'Value "{u\'x\': u\'foobar\'}" must either '
353
                           'be a string or None. Got "dict".',
354
                'task_id': 'task2'
355
            }
356
        ]
357
358
        expected_result = {'output': None, 'errors': expected_errors}
359
360
        wf_file = 'fail-task-input-value-type.yaml'
361
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file)
362
        wf_input = {'var1': {'x': 'foobar'}}
363
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input)
364
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
365
366
        # Assert task1 is already completed and workflow execution is still running.
367
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
368
        tk1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
369
        tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0]
370
        tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id'])
371
        self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
372
        self.assertEqual(wf_ex_db.status, wf_states.RUNNING)
373
374
        # Manually handle action execution completion for task1 which has an error in publish.
375
        wf_svc.handle_action_execution_completion(tk1_ac_ex_db)
376
377
        # Assert workflow execution and task2 execution failed.
378
        wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id))
379
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
380
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
381
382
        tk2_ex_db = wf_db_access.TaskExecution.query(task_id='task2')[0]
383
        self.assertEqual(tk2_ex_db.status, wf_states.FAILED)
384
        self.assertDictEqual(tk2_ex_db.result, {'errors': expected_errors})
385
386
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
387
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
388
        self.assertDictEqual(lv_ac_db.result, expected_result)
389
390
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
391
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
392
        self.assertDictEqual(ac_ex_db.result, expected_result)
393
394
    def test_fail_task_transition(self):
395
        expected_errors = [
396
            {
397
                'message': 'Unable to resolve key \'foobar\' in expression '
398
                           '\'<% succeeded() and result().foobar %>\' from context.',
399
                'task_transition_id': 'task2__0',
400
                'task_id': 'task1'
401
            }
402
        ]
403
404
        expected_result = {'output': None, 'errors': expected_errors}
405
406
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-transition.yaml')
407
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
408
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
409
410
        # Assert task1 is already completed.
411
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
412
        tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
413
        tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0]
414
        tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id'])
415
        self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
416
417
        # Manually handle action execution completion for task1 which has an error in publish.
418
        wf_svc.handle_action_execution_completion(tk_ac_ex_db)
419
420
        # Assert task1 succeeded but workflow failed.
421
        tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id)
422
        self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED)
423
        wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id)
424
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
425
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
426
427
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
428
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
429
        self.assertDictEqual(lv_ac_db.result, expected_result)
430
431
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
432
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
433
        self.assertDictEqual(ac_ex_db.result, expected_result)
434
435
    def test_fail_task_publish(self):
436
        expected_errors = [
437
            {
438
                'message': 'Unknown function "foobar"',
439
                'task_transition_id': 'task2__0',
440
                'task_id': 'task1'
441
            }
442
        ]
443
444
        expected_result = {'output': None, 'errors': expected_errors}
445
446
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-publish.yaml')
447
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
448
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
449
450
        # Assert task1 is already completed.
451
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
452
        tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
453
        tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0]
454
        tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id'])
455
        self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
456
457
        # Manually handle action execution completion for task1 which has an error in publish.
458
        wf_svc.handle_action_execution_completion(tk_ac_ex_db)
459
460
        # Assert task1 succeeded but workflow failed.
461
        tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id)
462
        self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED)
463
        wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id)
464
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
465
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
466
467
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
468
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
469
        self.assertDictEqual(lv_ac_db.result, expected_result)
470
471
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
472
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
473
        self.assertDictEqual(ac_ex_db.result, expected_result)
474
475
    def test_fail_output_rendering(self):
476
        expected_errors = [
477
            {
478
                'message': 'Unknown function "#property#value"'
479
            }
480
        ]
481
482
        expected_result = {'output': None, 'errors': expected_errors}
483
484
        wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-output-rendering.yaml')
485
        lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'])
486
        lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db)
487
488
        # Assert task1 is already completed.
489
        wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0]
490
        tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0]
491
        tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0]
492
        tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id'])
493
        self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
494
495
        # Manually handle action execution completion for task1 which has an error in publish.
496
        wf_svc.handle_action_execution_completion(tk_ac_ex_db)
497
498
        # Assert task1 succeeded but workflow failed.
499
        tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id)
500
        self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED)
501
        wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id)
502
        self.assertEqual(wf_ex_db.status, wf_states.FAILED)
503
        self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
504
505
        lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id))
506
        self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED)
507
        self.assertDictEqual(lv_ac_db.result, expected_result)
508
509
        ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id))
510
        self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED)
511
        self.assertDictEqual(ac_ex_db.result, expected_result)
512