Example #1
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)
 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)
     utils.register_notifiers(engine, self.values)
     engine.storage.inject({'y': 2})
     engine.run()
     self.assertEqual(engine.storage.fetch_all(), {
         'y': 2,
         'x1': 2,
         'x2': 1
     })
     expected = [
         'flow RUNNING', 'r1 RUNNING', 'r1 SUCCESS', 'task1 RUNNING',
         'task1 SUCCESS', 'r2 RUNNING', 'r2 SUCCESS', 'task2 RUNNING',
         'task2 SUCCESS', 'task3 RUNNING', 'task3 SUCCESS', 'task4 RUNNING',
         'task4', 'task4 FAILURE', 'task4 REVERTING',
         u'task4 reverted(Failure: RuntimeError: Woot!)', 'task4 REVERTED',
         'task3 REVERTING', 'task3 REVERTED', 'task2 REVERTING',
         'task2 REVERTED', 'r2 REVERTING', 'r2 REVERTED', 'task1 REVERTING',
         'task1 REVERTED', 'r1 RETRYING', 'task1 PENDING', 'r2 PENDING',
         'task2 PENDING', 'task3 PENDING', 'task4 PENDING', 'r1 RUNNING',
         'r1 SUCCESS', 'task1 RUNNING', 'task1 SUCCESS', 'r2 RUNNING',
         'r2 SUCCESS', 'task2 RUNNING', 'task2 SUCCESS', 'task3 RUNNING',
         'task3 SUCCESS', 'task4 RUNNING', 'task4', 'task4 SUCCESS',
         'flow SUCCESS'
     ]
     self.assertEqual(self.values, expected)
Example #3
0
    def test_task_graph_property(self):
        flow = gf.Flow('test').add(utils.TaskNoRequiresNoReturns(name='task1'),
                                   utils.TaskNoRequiresNoReturns(name='task2'))

        engine = self._make_engine(flow)
        graph = engine.execution_graph
        self.assertIsInstance(graph, networkx.DiGraph)
Example #4
0
 def test_parallel_revert_common(self):
     flow = uf.Flow('p-r-3').add(
         utils.TaskNoRequiresNoReturns(name='task1'),
         utils.FailingTask(sleep=0.01),
         utils.TaskNoRequiresNoReturns(name='task2'))
     engine = self._make_engine(flow)
     with self.assertRaisesRegexp(RuntimeError, '^Woot'):
         engine.run()
Example #5
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)
     self.assertFailuresRegexp(RuntimeError, '^Woot', engine.run)
     self.assertIn('fail reverted(Failure: RuntimeError: Woot!)',
                   self.values)
Example #6
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)
Example #7
0
    def test_task_graph_property_for_one_task(self):
        flow = utils.TaskNoRequiresNoReturns(name='task1')

        engine = self._make_engine(flow)
        engine.compile()
        graph = engine.compilation.execution_graph
        self.assertIsInstance(graph, gr.DiGraph)
Example #8
0
 def test_using_common_executor(self):
     flow = utils.TaskNoRequiresNoReturns(name='task1')
     executor = futures.ThreadPoolExecutor(self._EXECUTOR_WORKERS)
     try:
         e1 = self._make_engine(flow, executor=executor)
         e2 = self._make_engine(flow, executor=executor)
         self.assertIs(e1.options['executor'], e2.options['executor'])
     finally:
         executor.shutdown(wait=True)
Example #9
0
 def test_using_common_executor(self):
     flow = utils.TaskNoRequiresNoReturns(name='task1')
     executor = futures.ThreadPoolExecutor(2)
     try:
         e1 = self._make_engine(flow, executor=executor)
         e2 = self._make_engine(flow, executor=executor)
         self.assertIs(e1._executor, e2._executor)
     finally:
         executor.shutdown(wait=True)
Example #10
0
 def test_parallel_revert_exception_is_reraised(self):
     # NOTE(imelnikov): if we put NastyTask and FailingTask
     # into the same unordered flow, it is not guaranteed
     # that NastyTask execution would be attempted before
     # FailingTask fails.
     flow = lf.Flow('p-r-r-l').add(
         uf.Flow('p-r-r').add(utils.TaskNoRequiresNoReturns(name='task1'),
                              utils.NastyTask()), utils.FailingTask())
     engine = self._make_engine(flow)
     self.assertFailuresRegexp(RuntimeError, '^Gotcha', engine.run)
Example #11
0
 def test_dynamic(self):
     flow = lf.Flow("test")
     flow.add(test_utils.TaskNoRequiresNoReturns("test-1"))
     e = self._make_engine(flow)
     log, handler = self._make_logger()
     with logging_listeners.DynamicLoggingListener(e, log=log):
         e.run()
     self.assertGreater(0, handler.counts[logging.DEBUG])
     for levelno in _LOG_LEVELS - set([logging.DEBUG]):
         self.assertEqual(0, handler.counts[levelno])
     self.assertEqual([], handler.exc_infos)
Example #12
0
 def test_basic_customized(self):
     flow = lf.Flow("test")
     flow.add(test_utils.TaskNoRequiresNoReturns("test-1"))
     e = self._make_engine(flow)
     log, handler = self._make_logger()
     listener = logging_listeners.LoggingListener(
         e, log=log, level=logging.INFO)
     with listener:
         e.run()
     self.assertGreater(0, handler.counts[logging.INFO])
     for levelno in _LOG_LEVELS - set([logging.INFO]):
         self.assertEqual(0, handler.counts[levelno])
     self.assertEqual([], handler.exc_infos)
Example #13
0
 def test_record_ending_exception(self, mocked_warn):
     with contextlib.closing(impl_memory.MemoryBackend()) as be:
         flow = lf.Flow("test")
         flow.add(test_utils.TaskNoRequiresNoReturns("test-1"))
         (lb, fd) = persistence_utils.temporary_flow_detail(be)
         e = self._make_engine(flow, fd, be)
         timing_listener = timing.TimingListener(e)
         with mock.patch.object(timing_listener._engine.storage,
                                'update_atom_metadata') as mocked_uam:
             mocked_uam.side_effect = exc.StorageFailure('Woot!')
             with timing_listener:
                 e.run()
     mocked_warn.assert_called_once_with(mock.ANY, mock.ANY, 'test-1',
                                         exc_info=True)
Example #14
0
 def test_task_without_dependencies(self):
     flow = utils.TaskNoRequiresNoReturns()
     self.assertEquals(flow.requires, set())
     self.assertEquals(flow.provides, set())
Example #15
0
    def test_task_graph_property_for_one_task(self):
        flow = utils.TaskNoRequiresNoReturns(name='task1')

        engine = self._make_engine(flow)
        graph = engine.execution_graph
        self.assertTrue(isinstance(graph, networkx.DiGraph))
Example #16
0
 def test_unordered_flow_without_dependencies(self):
     flow = uf.Flow('uf').add(utils.TaskNoRequiresNoReturns('task1'),
                              utils.TaskNoRequiresNoReturns('task2'))
     self.assertEqual(flow.requires, set())
     self.assertEqual(flow.provides, set())
Example #17
0
 def test_unordered_flow_self_requires(self):
     flow = uf.Flow('uf')
     with self.assertRaises(exceptions.InvariantViolationException):
         flow.add(utils.TaskNoRequiresNoReturns(rebind=['x'], provides='x'))
Example #18
0
 def test_linear_flow_without_dependencies(self):
     flow = lf.Flow('lf').add(utils.TaskNoRequiresNoReturns('task1'),
                              utils.TaskNoRequiresNoReturns('task2'))
     self.assertEquals(flow.requires, set())
     self.assertEquals(flow.provides, set())