deb-heat/heat/tests/test_dependencies.py
Angus Salkeld ad104c51bf convergence: sync_point fixes
This is a merge of 4 reviews:
I52f1611d34def3474acba0e5eee054e11c5fc5ad
Ic374a38c9d76763be341d3a80f53fa396c9c2256
Iecd21ccb4392369f66fa1b3a0cf55aad754aeac4
I77b81097d2dcf01efa540237ed5ae14896ed1670

- make sure sender is a tuple (otherwise the serialization
  function in sync_point breaks.)
- Update updated_time on any lifecycle operation(CREATE/UPDATE/DELETE)
  over a stack.
- adjust sync_point logic to account for deletes
   Done by having only a single stack sync point
   for both updates and deletes.
- Serialize/deserialize input_data for RPC
- Make GraphKey's the norm in convergence worker
- move temp_update_requires functionality to tests
  During intial stages of convergence to simulate the entire cycle
  some part of worker code was written in stack.py.
  Now that the convergence worker is implemented, this code needs to
  be executed only in tests.
- Fix dictionary structure that's passed to resoure.(create/update)
- Temporarily disable loading cache_data for stack to help fix other
  issues.

Change-Id: Iecd21ccb4392369f66fa1b3a0cf55aad754aeac4
Co-Authored-by: Sirushti Murugesan <sirushti.murugesan@hp.com>
Co-Authored-by: Rakesh H S <rh-s@hp.com>
2015-06-19 08:24:19 +05:30

245 lines
9.5 KiB
Python

#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from heat.engine import dependencies
from heat.tests import common
class dependenciesTest(common.HeatTestCase):
def _dep_test(self, func, checkorder, deps):
nodes = set.union(*[set(e) for e in deps])
d = dependencies.Dependencies(deps)
order = list(func(d))
for n in nodes:
self.assertTrue(n in order, '"%s" is not in the sequence' % n)
self.assertEqual(1, order.count(n))
self.assertEqual(len(nodes), len(order))
for l, f in deps:
checkorder(order.index(f), order.index(l))
def _dep_test_fwd(self, *deps):
def assertLess(a, b):
self.assertTrue(a < b,
'"%s" is not less than "%s"' % (str(a), str(b)))
self._dep_test(iter, assertLess, deps)
def _dep_test_rev(self, *deps):
def assertGreater(a, b):
self.assertTrue(a > b,
'"%s" is not greater than "%s"' % (str(a), str(b)))
self._dep_test(reversed, assertGreater, deps)
def test_edges(self):
input_edges = [('1', None), ('2', '3'), ('2', '4')]
dp = dependencies.Dependencies(input_edges)
self.assertEqual(set(input_edges), set(dp.graph().edges()))
def test_repr(self):
dp = dependencies.Dependencies([('1', None), ('2', '3'), ('2', '4')])
s = "Dependencies([('1', None), ('2', '3'), ('2', '4')])"
self.assertEqual(s, repr(dp))
def test_single_node(self):
d = dependencies.Dependencies([('only', None)])
l = list(iter(d))
self.assertEqual(1, len(l))
self.assertEqual('only', l[0])
def test_disjoint(self):
d = dependencies.Dependencies([('1', None), ('2', None)])
l = list(iter(d))
self.assertEqual(2, len(l))
self.assertIn('1', l)
self.assertIn('2', l)
def test_single_fwd(self):
self._dep_test_fwd(('second', 'first'))
def test_single_rev(self):
self._dep_test_rev(('second', 'first'))
def test_chain_fwd(self):
self._dep_test_fwd(('third', 'second'), ('second', 'first'))
def test_chain_rev(self):
self._dep_test_rev(('third', 'second'), ('second', 'first'))
def test_diamond_fwd(self):
self._dep_test_fwd(('last', 'mid1'), ('last', 'mid2'),
('mid1', 'first'), ('mid2', 'first'))
def test_diamond_rev(self):
self._dep_test_rev(('last', 'mid1'), ('last', 'mid2'),
('mid1', 'first'), ('mid2', 'first'))
def test_complex_fwd(self):
self._dep_test_fwd(('last', 'mid1'), ('last', 'mid2'),
('mid1', 'mid3'), ('mid1', 'first'),
('mid3', 'first'), ('mid2', 'first'))
def test_complex_rev(self):
self._dep_test_rev(('last', 'mid1'), ('last', 'mid2'),
('mid1', 'mid3'), ('mid1', 'first'),
('mid3', 'first'), ('mid2', 'first'))
def test_many_edges_fwd(self):
self._dep_test_fwd(('last', 'e1'), ('last', 'mid1'), ('last', 'mid2'),
('mid1', 'e2'), ('mid1', 'mid3'),
('mid2', 'mid3'),
('mid3', 'e3'))
def test_many_edges_rev(self):
self._dep_test_rev(('last', 'e1'), ('last', 'mid1'), ('last', 'mid2'),
('mid1', 'e2'), ('mid1', 'mid3'),
('mid2', 'mid3'),
('mid3', 'e3'))
def test_dbldiamond_fwd(self):
self._dep_test_fwd(('last', 'a1'), ('last', 'a2'),
('a1', 'b1'), ('a2', 'b1'), ('a2', 'b2'),
('b1', 'first'), ('b2', 'first'))
def test_dbldiamond_rev(self):
self._dep_test_rev(('last', 'a1'), ('last', 'a2'),
('a1', 'b1'), ('a2', 'b1'), ('a2', 'b2'),
('b1', 'first'), ('b2', 'first'))
def test_circular_fwd(self):
d = dependencies.Dependencies([('first', 'second'),
('second', 'third'),
('third', 'first')])
self.assertRaises(dependencies.CircularDependencyException,
list,
iter(d))
def test_circular_rev(self):
d = dependencies.Dependencies([('first', 'second'),
('second', 'third'),
('third', 'first')])
self.assertRaises(dependencies.CircularDependencyException,
list,
reversed(d))
def test_self_ref(self):
d = dependencies.Dependencies([('node', 'node')])
self.assertRaises(dependencies.CircularDependencyException,
list,
iter(d))
def test_complex_circular_fwd(self):
d = dependencies.Dependencies([('last', 'e1'), ('last', 'mid1'),
('last', 'mid2'), ('mid1', 'e2'),
('mid1', 'mid3'), ('mid2', 'mid3'),
('mid3', 'e3'), ('e3', 'mid1')])
self.assertRaises(dependencies.CircularDependencyException,
list,
iter(d))
def test_complex_circular_rev(self):
d = dependencies.Dependencies([('last', 'e1'), ('last', 'mid1'),
('last', 'mid2'), ('mid1', 'e2'),
('mid1', 'mid3'), ('mid2', 'mid3'),
('mid3', 'e3'), ('e3', 'mid1')])
self.assertRaises(dependencies.CircularDependencyException,
list,
reversed(d))
def test_noexist_partial(self):
d = dependencies.Dependencies([('foo', 'bar')])
get = lambda i: d[i]
self.assertRaises(KeyError, get, 'baz')
def test_single_partial(self):
d = dependencies.Dependencies([('last', 'first')])
p = d['last']
l = list(iter(p))
self.assertEqual(1, len(l))
self.assertEqual('last', l[0])
def test_simple_partial(self):
d = dependencies.Dependencies([('last', 'middle'),
('middle', 'first')])
p = d['middle']
order = list(iter(p))
self.assertEqual(2, len(order))
for n in ('last', 'middle'):
self.assertTrue(n in order,
"'%s' not found in dependency order" % n)
self.assertTrue(order.index('last') > order.index('middle'))
def test_simple_multilevel_partial(self):
d = dependencies.Dependencies([('last', 'middle'),
('middle', 'target'),
('target', 'first')])
p = d['target']
order = list(iter(p))
self.assertEqual(3, len(order))
for n in ('last', 'middle', 'target'):
self.assertTrue(n in order,
"'%s' not found in dependency order" % n)
def test_complex_partial(self):
d = dependencies.Dependencies([('last', 'e1'), ('last', 'mid1'),
('last', 'mid2'), ('mid1', 'e2'),
('mid1', 'mid3'), ('mid2', 'mid3'),
('mid3', 'e3')])
p = d['mid3']
order = list(iter(p))
self.assertEqual(4, len(order))
for n in ('last', 'mid1', 'mid2', 'mid3'):
self.assertTrue(n in order,
"'%s' not found in dependency order" % n)
def test_required_by(self):
d = dependencies.Dependencies([('last', 'e1'), ('last', 'mid1'),
('last', 'mid2'), ('mid1', 'e2'),
('mid1', 'mid3'), ('mid2', 'mid3'),
('mid3', 'e3')])
self.assertEqual(0, len(list(d.required_by('last'))))
required_by = list(d.required_by('mid3'))
self.assertEqual(2, len(required_by))
for n in ('mid1', 'mid2'):
self.assertTrue(n in required_by,
"'%s' not found in required_by" % n)
required_by = list(d.required_by('e2'))
self.assertEqual(1, len(required_by))
self.assertTrue('mid1' in required_by,
"'%s' not found in required_by" % n)
self.assertRaises(KeyError, d.required_by, 'foo')
def test_leaves(self):
d = dependencies.Dependencies([('last1', 'mid'), ('last2', 'mid'),
('mid', 'first1'), ('mid', 'first2')])
leaves = sorted(list(d.leaves()))
self.assertEqual(['first1', 'first2'], leaves)
def test_roots(self):
d = dependencies.Dependencies([('last1', 'mid'), ('last2', 'mid'),
('mid', 'first1'), ('mid', 'first2')])
leaves = sorted(list(d.roots()))
self.assertEqual(['last1', 'last2'], leaves)