예제 #1
0
    def test_sequential_flow_iter_suspend_resume(self):
        flow = lf.Flow('flow-2').add(
            utils.ProgressingTask(name='task1'),
            utils.ProgressingTask(name='task2')
        )
        lb, fd = p_utils.temporary_flow_detail(self.backend)

        engine = self._make_engine(flow, flow_detail=fd)
        with utils.CaptureListener(engine, capture_flow=False) as capturer:
            it = engine.run_iter()
            gathered_states = []
            suspend_it = None
            while True:
                try:
                    s = it.send(suspend_it)
                    gathered_states.append(s)
                    if s == states.WAITING:
                        # Stop it before task2 runs/starts.
                        suspend_it = True
                except StopIteration:
                    break
        self.assertTrue(len(gathered_states) > 0)
        expected = ['task1.t RUNNING', 'task1.t SUCCESS(5)']
        self.assertEqual(expected, capturer.values)
        self.assertEqual(states.SUSPENDED, engine.storage.get_flow_state())

        # Attempt to resume it and see what runs now...
        with utils.CaptureListener(engine, capture_flow=False) as capturer:
            gathered_states = list(engine.run_iter())
        self.assertTrue(len(gathered_states) > 0)
        expected = ['task2.t RUNNING', 'task2.t SUCCESS(5)']
        self.assertEqual(expected, capturer.values)
        self.assertEqual(states.SUCCESS, engine.storage.get_flow_state())
예제 #2
0
    def test_revert_ok_for_unordered_in_linear(self):
        flow = lf.Flow('p-root').add(
            utils.ProgressingTask(name='task1'),
            utils.ProgressingTask(name='task2'),
            uf.Flow('p-inner').add(
                utils.ProgressingTask(name='task3'),
                utils.FailingTask('fail')
            )
        )
        engine = self._make_engine(flow)
        with utils.CaptureListener(engine, capture_flow=False) as capturer:
            self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)

        # NOTE(imelnikov): we don't know if task 3 was run, but if it was,
        # it should have been reverted in correct order.
        possible_values_no_task3 = [
            'task1.t RUNNING', 'task2.t RUNNING',
            'fail.t FAILURE(Failure: RuntimeError: Woot!)',
            'task2.t REVERTED', 'task1.t REVERTED'
        ]
        self.assertIsSuperAndSubsequence(capturer.values,
                                         possible_values_no_task3)
        if 'task3' in capturer.values:
            possible_values_task3 = [
                'task1.t RUNNING', 'task2.t RUNNING', 'task3.t RUNNING',
                'task3.t REVERTED', 'task2.t REVERTED', 'task1.t REVERTED'
            ]
            self.assertIsSuperAndSubsequence(capturer.values,
                                             possible_values_task3)
예제 #3
0
 def test_retry_tasks_that_has_not_been_reverted(self):
     flow = lf.Flow('flow-1', retry.Times(3, 'r1', provides='x')).add(
         utils.ConditionalTask('c'),
         utils.ProgressingTask('t1')
     )
     engine = self._make_engine(flow)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine) as capturer:
         engine.run()
     expected = ['flow-1.f RUNNING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(1)',
                 'c.t RUNNING',
                 'c.t FAILURE(Failure: RuntimeError: Woot!)',
                 'c.t REVERTING',
                 'c.t REVERTED',
                 'r1.r RETRYING',
                 'c.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(2)',
                 'c.t RUNNING',
                 'c.t SUCCESS(None)',
                 't1.t RUNNING',
                 't1.t SUCCESS(5)',
                 'flow-1.f SUCCESS']
     self.assertEqual(capturer.values, expected)
예제 #4
0
 def test_resume_flow_that_should_be_retried(self):
     flow = lf.Flow('flow-1', retry.Times(3, 'r1')).add(
         utils.ProgressingTask('t1'),
         utils.ProgressingTask('t2')
     )
     engine = self._make_engine(flow)
     engine.compile()
     engine.prepare()
     with utils.CaptureListener(engine) as capturer:
         engine.storage.set_atom_intention('r1', st.RETRY)
         engine.storage.set_atom_state('r1', st.SUCCESS)
         engine.storage.set_atom_state('t1', st.REVERTED)
         engine.storage.set_atom_state('t2', st.REVERTED)
         engine.run()
     expected = ['flow-1.f RUNNING',
                 'r1.r RETRYING',
                 't1.t PENDING',
                 't2.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(1)',
                 't1.t RUNNING',
                 't1.t SUCCESS(5)',
                 't2.t RUNNING',
                 't2.t SUCCESS(5)',
                 'flow-1.f SUCCESS']
     self.assertEqual(expected, capturer.values)
예제 #5
0
 def test_revert_all_retry(self):
     flow = lf.Flow('flow-1', retry.Times(3, 'r1', provides='x')).add(
         utils.ProgressingTask("task1"),
         lf.Flow('flow-2', retry.AlwaysRevertAll('r2')).add(
             utils.ConditionalTask("task2"))
     )
     engine = self._make_engine(flow)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine) as capturer:
         self.assertRaisesRegexp(RuntimeError, '^Woot', engine.run)
     self.assertEqual(engine.storage.fetch_all(), {'y': 2})
     expected = ['flow-1.f RUNNING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(1)',
                 'task1.t RUNNING',
                 'task1.t SUCCESS(5)',
                 'r2.r RUNNING',
                 'r2.r SUCCESS(None)',
                 'task2.t RUNNING',
                 'task2.t FAILURE(Failure: RuntimeError: Woot!)',
                 'task2.t REVERTING',
                 'task2.t REVERTED',
                 'r2.r REVERTING',
                 'r2.r REVERTED',
                 'task1.t REVERTING',
                 'task1.t REVERTED',
                 'r1.r REVERTING',
                 'r1.r REVERTED',
                 'flow-1.f REVERTED']
     self.assertEqual(expected, capturer.values)
예제 #6
0
 def test_unordered_flow_task_fails_parallel_tasks_should_be_reverted(self):
     flow = uf.Flow('flow-1', retry.Times(3, 'r', provides='x')).add(
         utils.ProgressingTask("task1"),
         utils.ConditionalTask("task2")
     )
     engine = self._make_engine(flow)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine) as capturer:
         engine.run()
     self.assertEqual(engine.storage.fetch_all(), {'y': 2, 'x': 2})
     expected = ['flow-1.f RUNNING',
                 'r.r RUNNING',
                 'r.r SUCCESS(1)',
                 'task1.t RUNNING',
                 'task2.t RUNNING',
                 'task1.t SUCCESS(5)',
                 'task2.t FAILURE(Failure: RuntimeError: Woot!)',
                 'task2.t REVERTING',
                 'task1.t REVERTING',
                 'task2.t REVERTED',
                 'task1.t REVERTED',
                 'r.r RETRYING',
                 'task1.t PENDING',
                 'task2.t PENDING',
                 'r.r RUNNING',
                 'r.r SUCCESS(2)',
                 'task1.t RUNNING',
                 'task2.t RUNNING',
                 'task1.t SUCCESS(5)',
                 'task2.t SUCCESS(None)',
                 'flow-1.f SUCCESS']
     self.assertItemsEqual(capturer.values, expected)
예제 #7
0
 def test_when_subflow_fails_revert_running_tasks(self):
     waiting_task = utils.WaitForOneFromTask('task1', 'task2',
                                             [st.SUCCESS, st.FAILURE])
     flow = uf.Flow('flow-1', retry.Times(3, 'r', provides='x')).add(
         waiting_task,
         utils.ConditionalTask('task2')
     )
     engine = self._make_engine(flow)
     engine.task_notifier.register('*', waiting_task.callback)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     self.assertEqual(engine.storage.fetch_all(), {'y': 2, 'x': 2})
     expected = ['r.r RUNNING',
                 'r.r SUCCESS(1)',
                 'task1.t RUNNING',
                 'task2.t RUNNING',
                 'task2.t FAILURE(Failure: RuntimeError: Woot!)',
                 'task2.t REVERTING',
                 'task2.t REVERTED',
                 'task1.t SUCCESS(5)',
                 'task1.t REVERTING',
                 'task1.t REVERTED',
                 'r.r RETRYING',
                 'task1.t PENDING',
                 'task2.t PENDING',
                 'r.r RUNNING',
                 'r.r SUCCESS(2)',
                 'task1.t RUNNING',
                 'task2.t RUNNING',
                 'task2.t SUCCESS(None)',
                 'task1.t SUCCESS(5)']
     self.assertItemsEqual(capturer.values, expected)
예제 #8
0
 def test_nested_provides_graph_reverts_correctly(self):
     flow = gf.Flow("test").add(
         utils.ProgressingTask('a', requires=['x']),
         lf.Flow("test2", retry=retry.Times(2)).add(
             utils.ProgressingTask('b', provides='x'),
             utils.FailingTask('c')))
     engine = self._make_engine(flow)
     engine.compile()
     engine.prepare()
     engine.storage.save('test2_retry', 1)
     engine.storage.save('b', 11)
     engine.storage.save('a', 10)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         self.assertRaisesRegexp(RuntimeError, '^Woot', engine.run)
     expected = ['c.t RUNNING',
                 'c.t FAILURE(Failure: RuntimeError: Woot!)',
                 'a.t REVERTING',
                 'c.t REVERTING',
                 'a.t REVERTED',
                 'c.t REVERTED',
                 'b.t REVERTING',
                 'b.t REVERTED']
     self.assertItemsEqual(capturer.values[:8], expected)
     # Task 'a' was or was not executed again, both cases are ok.
     self.assertIsSuperAndSubsequence(capturer.values[8:], [
         'b.t RUNNING',
         'c.t FAILURE(Failure: RuntimeError: Woot!)',
         'b.t REVERTED',
     ])
     self.assertEqual(engine.storage.get_flow_state(), st.REVERTED)
예제 #9
0
 def test_run_task_as_flow(self):
     flow = utils.ProgressingTask(name='task1')
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = ['task1.t RUNNING', 'task1.t SUCCESS(5)']
     self.assertEqual(expected, capturer.values)
예제 #10
0
 def test_nested_flow_reverts_parent_retries(self):
     retry1 = retry.Times(3, 'r1', provides='x')
     retry2 = retry.Times(0, 'r2', provides='x2')
     flow = lf.Flow('flow-1', retry1).add(
         utils.ProgressingTask("task1"),
         lf.Flow('flow-2', retry2).add(utils.ConditionalTask("task2")))
     engine = self._make_engine(flow)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine) as capturer:
         engine.run()
     self.assertEqual(engine.storage.fetch_all(), {'y': 2, 'x': 2, 'x2': 1})
     expected = [
         'flow-1.f RUNNING', 'r1.r RUNNING', 'r1.r SUCCESS(1)',
         'task1.t RUNNING', 'task1.t SUCCESS(5)', 'r2.r RUNNING',
         'r2.r SUCCESS(1)', 'task2.t RUNNING',
         'task2.t FAILURE(Failure: RuntimeError: Woot!)',
         'task2.t REVERTING', 'task2.t REVERTED', 'r2.r REVERTING',
         'r2.r REVERTED', 'task1.t REVERTING', 'task1.t REVERTED',
         'r1.r RETRYING', 'task1.t PENDING', 'r2.r PENDING',
         'task2.t PENDING', 'r1.r RUNNING', 'r1.r SUCCESS(2)',
         'task1.t RUNNING', 'task1.t SUCCESS(5)', 'r2.r RUNNING',
         'r2.r SUCCESS(1)', 'task2.t RUNNING', 'task2.t SUCCESS(None)',
         'flow-1.f SUCCESS'
     ]
     self.assertEqual(expected, capturer.values)
예제 #11
0
 def test_states_retry_failure_parent_flow_fails(self):
     flow = lf.Flow('flow-1', retry.Times(3, 'r1', provides='x1')).add(
         utils.TaskNoRequiresNoReturns("task1"),
         lf.Flow('flow-2', retry.Times(3, 'r2', provides='x2')).add(
             utils.TaskNoRequiresNoReturns("task2"),
             utils.TaskNoRequiresNoReturns("task3")),
         utils.ConditionalTask("task4", rebind={'x': 'x1'}))
     engine = self._make_engine(flow)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine) as capturer:
         engine.run()
     self.assertEqual(engine.storage.fetch_all(), {
         'y': 2,
         'x1': 2,
         'x2': 1
     })
     expected = [
         'flow-1.f RUNNING', 'r1.r RUNNING', 'r1.r SUCCESS(1)',
         'task1.t RUNNING', 'task1.t SUCCESS(None)', 'r2.r RUNNING',
         'r2.r SUCCESS(1)', 'task2.t RUNNING', 'task2.t SUCCESS(None)',
         'task3.t RUNNING', 'task3.t SUCCESS(None)', 'task4.t RUNNING',
         'task4.t FAILURE(Failure: RuntimeError: Woot!)',
         'task4.t REVERTING', 'task4.t REVERTED', 'task3.t REVERTING',
         'task3.t REVERTED', 'task2.t REVERTING', 'task2.t REVERTED',
         'r2.r REVERTING', 'r2.r REVERTED', 'task1.t REVERTING',
         'task1.t REVERTED', 'r1.r RETRYING', 'task1.t PENDING',
         'r2.r PENDING', 'task2.t PENDING', 'task3.t PENDING',
         'task4.t PENDING', 'r1.r RUNNING', 'r1.r SUCCESS(2)',
         'task1.t RUNNING', 'task1.t SUCCESS(None)', 'r2.r RUNNING',
         'r2.r SUCCESS(1)', 'task2.t RUNNING', 'task2.t SUCCESS(None)',
         'task3.t RUNNING', 'task3.t SUCCESS(None)', 'task4.t RUNNING',
         'task4.t SUCCESS(None)', 'flow-1.f SUCCESS'
     ]
     self.assertEqual(expected, capturer.values)
예제 #12
0
 def test_graph_flow_one_task(self):
     flow = gf.Flow('g-1').add(utils.ProgressingTask(name='task1'))
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = ['task1.t RUNNING', 'task1.t SUCCESS(5)']
     self.assertEqual(expected, capturer.values)
예제 #13
0
    def test_revert_raises_for_unordered_in_linear(self):
        flow = lf.Flow('p-root').add(
            utils.ProgressingTask(name='task1'),
            utils.ProgressingTask(name='task2'),
            uf.Flow('p-inner').add(
                utils.ProgressingTask(name='task3'),
                utils.NastyFailingTask(name='nasty')
            )
        )
        engine = self._make_engine(flow)
        with utils.CaptureListener(engine,
                                   capture_flow=False,
                                   skip_tasks=['nasty']) as capturer:
            self.assertFailuresRegexp(RuntimeError, '^Gotcha', engine.run)

        # NOTE(imelnikov): we don't know if task 3 was run, but if it was,
        # it should have been reverted in correct order.
        possible_values = ['task1.t RUNNING', 'task1.t SUCCESS(5)',
                           'task2.t RUNNING', 'task2.t SUCCESS(5)',
                           'task3.t RUNNING', 'task3.t SUCCESS(5)',
                           'task3.t REVERTING',
                           'task3.t REVERTED']
        self.assertIsSuperAndSubsequence(possible_values, capturer.values)
        possible_values_no_task3 = ['task1.t RUNNING', 'task2.t RUNNING']
        self.assertIsSuperAndSubsequence(capturer.values,
                                         possible_values_no_task3)
예제 #14
0
    def test_graph_flow_four_tasks_revert(self):
        flow = gf.Flow('g-4-failing').add(
            utils.ProgressingTask(name='task4',
                                  provides='d', requires=['c']),
            utils.ProgressingTask(name='task2',
                                  provides='b', requires=['a']),
            utils.FailingTask(name='task3',
                              provides='c', requires=['b']),
            utils.ProgressingTask(name='task1', provides='a'))

        engine = self._make_engine(flow)
        with utils.CaptureListener(engine, capture_flow=False) as capturer:
            self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)
        expected = ['task1.t RUNNING', 'task1.t SUCCESS(5)',
                    'task2.t RUNNING', 'task2.t SUCCESS(5)',
                    'task3.t RUNNING',
                    'task3.t FAILURE(Failure: RuntimeError: Woot!)',
                    'task3.t REVERTING',
                    'task3.t REVERTED',
                    'task2.t REVERTING',
                    'task2.t REVERTED',
                    'task1.t REVERTING',
                    'task1.t REVERTED']
        self.assertEqual(expected, capturer.values)
        self.assertEqual(engine.storage.get_flow_state(), states.REVERTED)
예제 #15
0
 def test_suspend_linear_flow_on_revert(self):
     flow = lf.Flow('linear').add(
         utils.ProgressingTask('a'),
         utils.ProgressingTask('b'),
         utils.FailingTask('c')
     )
     engine = self._make_engine(flow)
     with SuspendingListener(engine, task_name='b',
                             task_state=states.REVERTED) as capturer:
         engine.run()
     self.assertEqual(engine.storage.get_flow_state(), states.SUSPENDED)
     expected = ['a.t RUNNING',
                 'a.t SUCCESS(5)',
                 'b.t RUNNING',
                 'b.t SUCCESS(5)',
                 'c.t RUNNING',
                 'c.t FAILURE(Failure: RuntimeError: Woot!)',
                 'c.t REVERTING',
                 'c.t REVERTED',
                 'b.t REVERTING',
                 'b.t REVERTED']
     self.assertEqual(expected, capturer.values)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         self.assertRaisesRegexp(RuntimeError, '^Woot', engine.run)
     self.assertEqual(engine.storage.get_flow_state(), states.REVERTED)
     expected = ['a.t REVERTING', 'a.t REVERTED']
     self.assertEqual(expected, capturer.values)
예제 #16
0
 def test_states_retry_success_linear_flow(self):
     flow = lf.Flow('flow-1', retry.Times(4, 'r1', provides='x')).add(
         utils.ProgressingTask("task1"),
         utils.ConditionalTask("task2")
     )
     engine = self._make_engine(flow)
     engine.storage.inject({'y': 2})
     with utils.CaptureListener(engine) as capturer:
         engine.run()
     self.assertEqual(engine.storage.fetch_all(), {'y': 2, 'x': 2})
     expected = ['flow-1.f RUNNING',
                 'r1.r RUNNING', 'r1.r SUCCESS(1)',
                 'task1.t RUNNING', 'task1.t SUCCESS(5)',
                 'task2.t RUNNING',
                 'task2.t FAILURE(Failure: RuntimeError: Woot!)',
                 'task2.t REVERTING', 'task2.t REVERTED',
                 'task1.t REVERTING', 'task1.t REVERTED',
                 'r1.r RETRYING',
                 'task1.t PENDING',
                 'task2.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(2)',
                 'task1.t RUNNING',
                 'task1.t SUCCESS(5)',
                 'task2.t RUNNING',
                 'task2.t SUCCESS(None)',
                 'flow-1.f SUCCESS']
     self.assertEqual(expected, capturer.values)
예제 #17
0
    def test_suspend_and_revert_even_if_task_is_gone(self):
        flow = lf.Flow('linear').add(utils.ProgressingTask('a'),
                                     utils.ProgressingTask('b'),
                                     utils.FailingTask('c'))
        engine = self._make_engine(flow)

        with SuspendingListener(engine,
                                task_name='b',
                                task_state=states.REVERTED) as capturer:
            engine.run()

        expected = [
            'a.t RUNNING', 'a.t SUCCESS(5)', 'b.t RUNNING', 'b.t SUCCESS(5)',
            'c.t RUNNING', 'c.t FAILURE(Failure: RuntimeError: Woot!)',
            'c.t REVERTING', 'c.t REVERTED(None)', 'b.t REVERTING',
            'b.t REVERTED(None)'
        ]
        self.assertEqual(expected, capturer.values)

        # pretend we are resuming, but task 'c' gone when flow got updated
        flow2 = lf.Flow('linear').add(
            utils.ProgressingTask('a'),
            utils.ProgressingTask('b'),
        )
        engine2 = self._make_engine(flow2, engine.storage._flowdetail)
        with utils.CaptureListener(engine2, capture_flow=False) as capturer2:
            self.assertRaisesRegex(RuntimeError, '^Woot', engine2.run)
        self.assertEqual(states.REVERTED, engine2.storage.get_flow_state())
        expected = ['a.t REVERTING', 'a.t REVERTED(None)']
        self.assertEqual(expected, capturer2.values)
예제 #18
0
 def test_nested_provides_graph_retried_correctly(self):
     flow = gf.Flow("test").add(
         utils.ProgressingTask('a', requires=['x']),
         lf.Flow("test2", retry=retry.Times(2)).add(
             utils.ProgressingTask('b', provides='x'),
             utils.ProgressingTask('c')))
     engine = self._make_engine(flow)
     engine.compile()
     engine.prepare()
     engine.storage.save('test2_retry', 1)
     engine.storage.save('b', 11)
     # pretend that 'c' failed
     fail = failure.Failure.from_exception(RuntimeError('Woot!'))
     engine.storage.save('c', fail, st.FAILURE)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = ['c.t REVERTING',
                 'c.t REVERTED',
                 'b.t REVERTING',
                 'b.t REVERTED']
     self.assertItemsEqual(capturer.values[:4], expected)
     expected = ['test2_retry.r RETRYING',
                 'b.t PENDING',
                 'c.t PENDING',
                 'test2_retry.r RUNNING',
                 'test2_retry.r SUCCESS(2)',
                 'b.t RUNNING',
                 'b.t SUCCESS(5)',
                 'a.t RUNNING',
                 'c.t RUNNING',
                 'a.t SUCCESS(5)',
                 'c.t SUCCESS(5)']
     self.assertItemsEqual(expected, capturer.values[4:])
     self.assertEqual(engine.storage.get_flow_state(), st.SUCCESS)
예제 #19
0
 def test_parameterized_for_each_with_set(self):
     values = ([3, 2, 5])
     retry1 = retry.ParameterizedForEach('r1', provides='x')
     flow = lf.Flow('flow-1', retry1).add(utils.FailingTaskWithOneArg('t1'))
     engine = self._make_engine(flow)
     engine.storage.inject({'values': values, 'y': 1})
     with utils.CaptureListener(engine) as capturer:
         self.assertRaisesRegexp(RuntimeError, '^Woot', engine.run)
     expected = ['flow-1.f RUNNING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(3)',
                 't1.t RUNNING',
                 't1.t FAILURE(Failure: RuntimeError: Woot with 3)',
                 't1.t REVERTING',
                 't1.t REVERTED',
                 'r1.r RETRYING',
                 't1.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(2)',
                 't1.t RUNNING',
                 't1.t FAILURE(Failure: RuntimeError: Woot with 2)',
                 't1.t REVERTING',
                 't1.t REVERTED',
                 'r1.r RETRYING',
                 't1.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(5)',
                 't1.t RUNNING',
                 't1.t FAILURE(Failure: RuntimeError: Woot with 5)',
                 't1.t REVERTING',
                 't1.t REVERTED',
                 'r1.r REVERTING',
                 'r1.r REVERTED',
                 'flow-1.f REVERTED']
     self.assertItemsEqual(capturer.values, expected)
예제 #20
0
 def test_basic_do_not_capture(self):
     flow = lf.Flow("test")
     flow.add(test_utils.ProgressingTask("task1"))
     e = self._make_engine(flow)
     with test_utils.CaptureListener(e, capture_task=False) as capturer:
         e.run()
     expected = ['test.f RUNNING', 'test.f SUCCESS']
     self.assertEqual(expected, capturer.values)
예제 #21
0
 def test_parallel_flow_one_task(self):
     flow = uf.Flow('p-1').add(
         utils.ProgressingTask(name='task1', provides='a'))
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = ['task1.t RUNNING', 'task1.t SUCCESS(5)']
     self.assertEqual(expected, capturer.values)
     self.assertEqual(engine.storage.fetch_all(), {'a': 5})
예제 #22
0
 def test_revert_raises_for_linear_in_unordered(self):
     flow = uf.Flow('p-root').add(
         utils.ProgressingTask(name='task1'),
         lf.Flow('p-inner').add(utils.ProgressingTask(name='task2'),
                                utils.NastyFailingTask()))
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         self.assertFailuresRegexp(RuntimeError, '^Gotcha', engine.run)
     self.assertNotIn('task2.t REVERTED', capturer.values)
예제 #23
0
 def test_failing_task_with_notifications(self):
     values = []
     flow = utils.FailingTask('fail')
     engine = self._make_engine(flow)
     expected = ['fail.f RUNNING', 'fail.t RUNNING',
                 'fail.t FAILURE(Failure: RuntimeError: Woot!)',
                 'fail.t REVERTING', 'fail.t REVERTED',
                 'fail.f REVERTED']
     with utils.CaptureListener(engine, values=values) as capturer:
         self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)
     self.assertEqual(expected, capturer.values)
     self.assertEqual(engine.storage.get_flow_state(), states.REVERTED)
     with utils.CaptureListener(engine, values=values) as capturer:
         self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)
     now_expected = list(expected)
     now_expected.extend(['fail.t PENDING', 'fail.f PENDING'])
     now_expected.extend(expected)
     self.assertEqual(now_expected, values)
     self.assertEqual(engine.storage.get_flow_state(), states.REVERTED)
예제 #24
0
 def test_parallel_revert(self):
     flow = uf.Flow('p-r-3').add(
         utils.TaskNoRequiresNoReturns(name='task1'),
         utils.FailingTask(name='fail'),
         utils.TaskNoRequiresNoReturns(name='task2'))
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)
     self.assertIn('fail.t FAILURE(Failure: RuntimeError: Woot!)',
                   capturer.values)
예제 #25
0
 def test_resumption_on_crash_after_revert_scheduled(self):
     engine = self._pretend_to_run_a_flow_and_crash('revert scheduled')
     with utils.CaptureListener(engine) as capturer:
         engine.run()
     expected = [
         'task1.t REVERTED', 'flow-1_retry.r RETRYING', 'task1.t PENDING',
         'flow-1_retry.r RUNNING', 'flow-1_retry.r SUCCESS(2)',
         'task1.t RUNNING', 'task1.t SUCCESS(5)', 'flow-1.f SUCCESS'
     ]
     self.assertEqual(capturer.values, expected)
예제 #26
0
 def test_parallel_flow_two_tasks(self):
     flow = uf.Flow('p-2').add(
         utils.ProgressingTask(name='task1'),
         utils.ProgressingTask(name='task2')
     )
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = set(['task2.t SUCCESS(5)', 'task2.t RUNNING',
                     'task1.t RUNNING', 'task1.t SUCCESS(5)'])
     self.assertEqual(expected, set(capturer.values))
예제 #27
0
 def test_sequential_flow_nested_blocks(self):
     flow = lf.Flow('nested-1').add(
         utils.ProgressingTask('task1'),
         lf.Flow('inner-1').add(utils.ProgressingTask('task2')))
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = [
         'task1.t RUNNING', 'task1.t SUCCESS(5)', 'task2.t RUNNING',
         'task2.t SUCCESS(5)'
     ]
     self.assertEqual(expected, capturer.values)
예제 #28
0
 def test_revert_not_run_task_is_not_reverted(self):
     flow = lf.Flow('revert-not-run').add(
         utils.FailingTask('fail'),
         utils.NeverRunningTask(),
     )
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)
     expected = ['fail.t RUNNING',
                 'fail.t FAILURE(Failure: RuntimeError: Woot!)',
                 'fail.t REVERTING', 'fail.t REVERTED']
     self.assertEqual(expected, capturer.values)
예제 #29
0
 def test_sequential_flow_two_tasks(self):
     flow = lf.Flow('flow-2').add(
         utils.ProgressingTask(name='task1'),
         utils.ProgressingTask(name='task2')
     )
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine, capture_flow=False) as capturer:
         engine.run()
     expected = ['task1.t RUNNING', 'task1.t SUCCESS(5)',
                 'task2.t RUNNING', 'task2.t SUCCESS(5)']
     self.assertEqual(expected, capturer.values)
     self.assertEqual(len(flow), 2)
예제 #30
0
 def test_default_times_retry(self):
     flow = lf.Flow('flow-1', retry.Times(3, 'r1')).add(
         utils.ProgressingTask('t1'),
         utils.FailingTask('t2'))
     engine = self._make_engine(flow)
     with utils.CaptureListener(engine) as capturer:
         self.assertRaisesRegexp(RuntimeError, '^Woot', engine.run)
     expected = ['flow-1.f RUNNING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(1)',
                 't1.t RUNNING',
                 't1.t SUCCESS(5)',
                 't2.t RUNNING',
                 't2.t FAILURE(Failure: RuntimeError: Woot!)',
                 't2.t REVERTING',
                 't2.t REVERTED',
                 't1.t REVERTING',
                 't1.t REVERTED',
                 'r1.r RETRYING',
                 't1.t PENDING',
                 't2.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(2)',
                 't1.t RUNNING',
                 't1.t SUCCESS(5)',
                 't2.t RUNNING',
                 't2.t FAILURE(Failure: RuntimeError: Woot!)',
                 't2.t REVERTING',
                 't2.t REVERTED',
                 't1.t REVERTING',
                 't1.t REVERTED',
                 'r1.r RETRYING',
                 't1.t PENDING',
                 't2.t PENDING',
                 'r1.r RUNNING',
                 'r1.r SUCCESS(3)',
                 't1.t RUNNING',
                 't1.t SUCCESS(5)',
                 't2.t RUNNING',
                 't2.t FAILURE(Failure: RuntimeError: Woot!)',
                 't2.t REVERTING',
                 't2.t REVERTED',
                 't1.t REVERTING',
                 't1.t REVERTED',
                 'r1.r REVERTING',
                 'r1.r REVERTED',
                 'flow-1.f REVERTED']
     self.assertEqual(expected, capturer.values)