def test_nested(self): r = gf.Flow("root") r_1 = test_utils.TaskOneReturn("root.1") r_2 = test_utils.TaskOneReturn("root.2") r.add(r_1, r_2) r.link(r_1, r_2) subroot = gf.Flow("subroot") subroot_r_1 = test_utils.TaskOneReturn("subroot.1") subroot_r_2 = test_utils.TaskOneReturn("subroot.2") subroot.add(subroot_r_1, subroot_r_2) subroot.link(subroot_r_1, subroot_r_2) r.add(subroot) r_3 = test_utils.TaskOneReturn("root.3") r.add(r_3) r.link(r_2, r_3) c = compiler.PatternCompiler(r).compile() self.assertEqual([], _get_scopes(c, r_1)) self.assertEqual([['root.1']], _get_scopes(c, r_2)) self.assertEqual([['root.2', 'root.1']], _get_scopes(c, r_3)) self.assertEqual([], _get_scopes(c, subroot_r_1)) self.assertEqual([['subroot.1']], _get_scopes(c, subroot_r_2))
def test_checks_for_dups_globally(self): flo = gf.Flow("test").add( gf.Flow("int1").add(test_utils.DummyTask(name="a")), gf.Flow("int2").add(test_utils.DummyTask(name="a"))) e = engines.load(flo) self.assertRaisesRegex(exc.Duplicate, '^Atoms with duplicate names', e.compile)
def test_graph_nested_graph(self): a, b, c, d, e, f, g = test_utils.make_many(7) flo = gf.Flow("test") flo.add(a, b, c, d) flo2 = gf.Flow('test2') flo2.add(e, f, g) flo.add(flo2) g = _replicate_graph_with_names( compiler.PatternCompiler(flo).compile()) self.assertEqual(11, len(g)) self.assertItemsEqual(g.edges(), [ ('test', 'a'), ('test', 'b'), ('test', 'c'), ('test', 'd'), ('test', 'test2'), ('test2', 'e'), ('test2', 'f'), ('test2', 'g'), ('e', 'test2[$]'), ('f', 'test2[$]'), ('g', 'test2[$]'), ('test2[$]', 'test[$]'), ('a', 'test[$]'), ('b', 'test[$]'), ('c', 'test[$]'), ('d', 'test[$]'), ])
def test_graph_linear_scope(self): r = gf.Flow("root") r_1 = test_utils.TaskOneReturn("root.1") r_2 = test_utils.TaskOneReturn("root.2") r.add(r_1, r_2) r.link(r_1, r_2) s = lf.Flow("subroot") s_1 = test_utils.TaskOneReturn("subroot.1") s_2 = test_utils.TaskOneReturn("subroot.2") s.add(s_1, s_2) r.add(s) t = gf.Flow("subroot2") t_1 = test_utils.TaskOneReturn("subroot2.1") t_2 = test_utils.TaskOneReturn("subroot2.2") t.add(t_1, t_2) t.link(t_1, t_2) r.add(t) r.link(s, t) c = compiler.PatternCompiler(r).compile() self.assertEqual([], _get_scopes(c, r_1)) self.assertEqual([['root.1']], _get_scopes(c, r_2)) self.assertEqual([], _get_scopes(c, s_1)) self.assertEqual([['subroot.1']], _get_scopes(c, s_2)) self.assertEqual([[], ['subroot.2', 'subroot.1']], _get_scopes(c, t_1)) self.assertEqual([["subroot2.1"], ['subroot.2', 'subroot.1']], _get_scopes(c, t_2))
def create_flow(): # Setup the set of things to do (mini-nova). flow = lf.Flow("root").add( PrintText("Starting vm creation.", no_slow=True), lf.Flow('vm-maker').add( # First create a specification for the final vm to-be. DefineVMSpec("define_spec"), # This does all the image stuff. gf.Flow("img-maker").add( LocateImages("locate_images"), DownloadImages("download_images"), ), # This does all the network stuff. gf.Flow("net-maker").add( AllocateIP("get_my_ips"), CreateNetworkTpl("fetch_net_settings"), WriteNetworkSettings("write_net_settings"), ), # This does all the volume stuff. gf.Flow("volume-maker").add( AllocateVolumes("allocate_my_volumes", provides='volumes'), FormatVolumes("volume_formatter"), ), # Finally boot it all. BootVM("boot-it"), ), # Ya it worked! PrintText("Finished vm create.", no_slow=True), PrintText("Instance is running!", no_slow=True)) return flow
def test_iter_nodes(self): task1 = _task('task1', provides=['a'], requires=['c']) task2 = _task('task2', provides=['b'], requires=['a']) task3 = _task('task3', provides=['c']) f1 = gf.Flow('nested') f1.add(task3) tasks = set([task1, task2, f1]) f = gf.Flow('test').add(task1, task2, f1) for (n, data) in f.iter_nodes(): self.assertTrue(n in tasks) self.assertDictEqual({}, data)
def test_graph_flow_stringy(self): f = gf.Flow('test') expected = 'graph_flow.Flow: test(len=0)' self.assertEqual(expected, str(f)) task1 = _task(name='task1') task2 = _task(name='task2') task3 = _task(name='task3') f = gf.Flow('test') f.add(task1, task2, task3) expected = 'graph_flow.Flow: test(len=3)' self.assertEqual(expected, str(f))
def test_iter_links(self): task1 = _task('task1') task2 = _task('task2') task3 = _task('task3') f1 = gf.Flow('nested') f1.add(task3) tasks = set([task1, task2, f1]) f = gf.Flow('test').add(task1, task2, f1) for (u, v, data) in f.iter_links(): self.assertTrue(u in tasks) self.assertTrue(v in tasks) self.assertDictEqual({}, data)
def test_graph_flow_resolve_existing(self): task1 = _task(name='task1', requires=['a', 'b']) task2 = _task(name='task2', provides=['a', 'b']) f = gf.Flow('test') f.add(task1) f.add(task2, resolve_existing=True) self.assertEqual(set([]), f.requires)
def test_dependent(self): r = gf.Flow("root") customer = test_utils.ProvidesRequiresTask("customer", provides=['dog'], requires=[]) washer = test_utils.ProvidesRequiresTask("washer", requires=['dog'], provides=['wash']) dryer = test_utils.ProvidesRequiresTask("dryer", requires=['dog', 'wash'], provides=['dry_dog']) shaved = test_utils.ProvidesRequiresTask("shaver", requires=['dry_dog'], provides=['shaved_dog']) happy_customer = test_utils.ProvidesRequiresTask( "happy_customer", requires=['shaved_dog'], provides=['happiness']) r.add(customer, washer, dryer, shaved, happy_customer) c = compiler.PatternCompiler(r).compile() self.assertEqual([], _get_scopes(c, customer)) self.assertEqual([['washer', 'customer']], _get_scopes(c, dryer)) self.assertEqual([['shaver', 'dryer', 'washer', 'customer']], _get_scopes(c, happy_customer))
def test_graph_nested_requires(self): a = test_utils.ProvidesRequiresTask('a', provides=['x'], requires=[]) b = test_utils.ProvidesRequiresTask('b', provides=[], requires=[]) c = test_utils.ProvidesRequiresTask('c', provides=[], requires=['x']) inner_flo = lf.Flow("test2").add(b, c) flo = gf.Flow("test").add(a, inner_flo) g = _replicate_graph_with_names( compiler.PatternCompiler(flo).compile()) self.assertEqual(7, len(g)) self.assertItemsEqual(g.edges(data=True), [ ('test', 'a', { 'invariant': True }), ('test2', 'b', { 'invariant': True }), ('a', 'test2', { 'reasons': set(['x']) }), ('b', 'c', { 'invariant': True }), ('c', 'test2[$]', { 'invariant': True }), ('test2[$]', 'test[$]', { 'invariant': True }), ]) self.assertItemsEqual(['test'], list(g.no_predecessors_iter())) self.assertItemsEqual(['test[$]'], list(g.no_successors_iter()))
def test_graph_links(self): a, b, c, d = test_utils.make_many(4) flo = gf.Flow("test") flo.add(a, b, c, d) flo.link(a, b) flo.link(b, c) flo.link(c, d) g = _replicate_graph_with_names( compiler.PatternCompiler(flo).compile()) self.assertEqual(6, len(g)) self.assertItemsEqual(g.edges(data=True), [ ('test', 'a', { 'invariant': True }), ('a', 'b', { 'manual': True }), ('b', 'c', { 'manual': True }), ('c', 'd', { 'manual': True }), ('d', 'test[$]', { 'invariant': True }), ]) self.assertItemsEqual(['test'], g.no_predecessors_iter()) self.assertItemsEqual(['test[$]'], g.no_successors_iter())
def test_graph(self): a, b, c, d = test_utils.make_many(4) flo = gf.Flow("test") flo.add(a, b, c, d) compilation = compiler.PatternCompiler(flo).compile() self.assertEqual(6, len(compilation.execution_graph)) self.assertEqual(8, compilation.execution_graph.number_of_edges())
def test_retry_in_graph_flow_with_tasks(self): r = retry.AlwaysRevert("r") a, b, c = test_utils.make_many(3) flo = gf.Flow("test", r).add(a, b, c).link(b, c) g = _replicate_graph_with_names( compiler.PatternCompiler(flo).compile()) self.assertItemsEqual(g.edges(data=True), [ ('test', 'r', { 'invariant': True }), ('r', 'a', { 'invariant': True, 'retry': True }), ('r', 'b', { 'invariant': True, 'retry': True }), ('b', 'c', { 'manual': True }), ('a', 'test[$]', { 'invariant': True }), ('c', 'test[$]', { 'invariant': True }), ]) self.assertItemsEqual(['test'], g.no_predecessors_iter()) self.assertItemsEqual(['test[$]'], g.no_successors_iter()) self.assertIs(r, g.node['a']['retry']) self.assertIs(r, g.node['b']['retry']) self.assertIs(r, g.node['c']['retry'])
def test_shadow_graph(self): r = gf.Flow("root") customer = test_utils.ProvidesRequiresTask("customer", provides=['dog'], requires=[]) customer2 = test_utils.ProvidesRequiresTask("customer2", provides=['dog'], requires=[]) washer = test_utils.ProvidesRequiresTask("washer", requires=['dog'], provides=['wash']) r.add(customer, washer) r.add(customer2, resolve_requires=False) r.link(customer2, washer) c = compiler.PatternCompiler(r).compile() # The order currently is *not* guaranteed to be 'customer' before # 'customer2' or the reverse, since either can occur before the # washer; since *either* is a valid topological ordering of the # dependencies... # # This may be different after/if the following is resolved: # # https://github.com/networkx/networkx/issues/1181 (and a few others) self.assertEqual(set(['customer', 'customer2']), set(_get_scopes(c, washer)[0])) self.assertEqual([], _get_scopes(c, customer2)) self.assertEqual([], _get_scopes(c, customer))
def test_graph_cyclic_dependency(self): flow = gf.Flow('g-3-cyclic') self.assertRaisesRegex( exceptions.DependencyFailure, '^No path', flow.add, utils.TaskOneArgOneReturn(provides='a', requires=['b']), utils.TaskOneArgOneReturn(provides='b', requires=['c']), utils.TaskOneArgOneReturn(provides='c', requires=['a']))
def test_graph_flow_ambiguous_provides(self): task1 = _task(name='task1', provides=['a', 'b']) task2 = _task(name='task2', provides=['a']) f = gf.Flow('test') f.add(task1, task2) self.assertEqual(set(['a', 'b']), f.provides) task3 = _task(name='task3', requires=['a']) self.assertRaises(exc.AmbiguousDependency, f.add, task3)
def test_graph_flow_with_retry(self): ret = retry.AlwaysRevert(requires=['a'], provides=['b']) f = gf.Flow('test', ret) self.assertIs(f.retry, ret) self.assertEqual('test_retry', ret.name) self.assertEqual(set(['a']), f.requires) self.assertEqual(set(['b']), f.provides)
def test_graph_flow_multi_provides_and_requires_values(self): flow = gf.Flow('gf').add( utils.TaskMultiArgMultiReturn('task1', rebind=['a', 'b', 'c'], provides=['d', 'e', 'f']), utils.TaskMultiArgMultiReturn('task2', provides=['i', 'j', 'k'])) self.assertEqual(set(['a', 'b', 'c', 'x', 'y', 'z']), flow.requires) self.assertEqual(set(['d', 'e', 'f', 'i', 'j', 'k']), flow.provides)
def test_graph_flow_two_independent_tasks(self): task1 = _task(name='task1') task2 = _task(name='task2') f = gf.Flow('test').add(task1, task2) self.assertEqual(2, len(f)) self.assertItemsEqual(f, [task1, task2]) self.assertEqual([], list(f.iter_links()))
def test_graph_flow_links(self): task1 = _task('task1') task2 = _task('task2') f = gf.Flow('test').add(task1, task2) linked = f.link(task1, task2) self.assertIs(linked, f) self.assertItemsEqual(list(f.iter_links()), [(task1, task2, { 'manual': True })])
def test_graph_flow_starts_as_empty(self): f = gf.Flow('test') self.assertEqual(0, len(f)) self.assertEqual([], list(f)) self.assertEqual([], list(f.iter_links())) self.assertEqual(set(), f.requires) self.assertEqual(set(), f.provides)
def test_graph_flow_links_and_dependencies(self): task1 = _task('task1', provides=['a']) task2 = _task('task2', requires=['a']) f = gf.Flow('test').add(task1, task2) linked = f.link(task1, task2) self.assertIs(linked, f) expected_meta = {'manual': True, 'reasons': set(['a'])} self.assertItemsEqual(list(f.iter_links()), [(task1, task2, expected_meta)])
def test_graph_flow_retry_and_task(self): flow = gf.Flow( 'gf', retry.AlwaysRevert('rt', requires=['x', 'y'], provides=['a', 'b'])) flow.add( utils.TaskMultiArgOneReturn(rebind=['a', 'x', 'c'], provides=['z'])) self.assertEqual(set(['x', 'y', 'c']), flow.requires) self.assertEqual(set(['a', 'b', 'z']), flow.provides)
def test_no_visible(self): r = gf.Flow("root") atoms = [] for i in range(0, 10): atoms.append(test_utils.TaskOneReturn("root.%s" % i)) r.add(*atoms) c = compiler.PatternCompiler(r).compile() for a in atoms: self.assertEqual([], _get_scopes(c, a))
def test_graph_flow_two_dependent_tasks_two_different_calls(self): task1 = _task(name='task1', provides=['a']) task2 = _task(name='task2', requires=['a']) f = gf.Flow('test').add(task1).add(task2) self.assertEqual(2, len(f)) self.assertItemsEqual(f, [task1, task2]) self.assertEqual([(task1, task2, { 'reasons': set(['a']) })], list(f.iter_links()))
def test_graph_flow_one_task(self): f = gf.Flow('test') task = _task(name='task1', requires=['a', 'b'], provides=['c', 'd']) result = f.add(task) self.assertIs(f, result) self.assertEqual(1, len(f)) self.assertEqual([task], list(f)) self.assertEqual([], list(f.iter_links())) self.assertEqual(set(['a', 'b']), f.requires) self.assertEqual(set(['c', 'd']), f.provides)
def test_invalid_decider_depth(self): g_1 = utils.ProgressingTask(name='g-1') g_2 = utils.ProgressingTask(name='g-2') for not_a_depth in ['not-a-depth', object(), 2, 3.4, False]: flow = gf.Flow('g') flow.add(g_1, g_2) self.assertRaises((ValueError, TypeError), flow.link, g_1, g_2, decider=lambda history: False, decider_depth=not_a_depth)
def test_empty_flow_in_graph_flow_linkage(self): flow = gf.Flow('lf') a = test_utils.ProvidesRequiresTask('a', provides=[], requires=[]) b = test_utils.ProvidesRequiresTask('b', provides=[], requires=[]) empty_flow = lf.Flow("empty") flow.add(a, empty_flow, b) flow.link(a, b) compilation = compiler.PatternCompiler(flow).compile() g = compilation.execution_graph self.assertTrue(g.has_edge(a, b)) self.assertTrue(g.has_edge(flow, a)) self.assertTrue(g.has_edge(flow, empty_flow))
def test_graph_flow_ordering(self): task1 = _task('task1', provides=set(['a', 'b'])) task2 = _task('task2', provides=['c'], requires=['a', 'b']) task3 = _task('task3', provides=[], requires=['c']) f = gf.Flow('test').add(task1, task2, task3) self.assertEqual(3, len(f)) self.assertItemsEqual(list(f.iter_links()), [(task1, task2, { 'reasons': set(['a', 'b']) }), (task2, task3, { 'reasons': set(['c']) })])