12 # Contributors: |
12 # Contributors: |
13 # |
13 # |
14 # Description: |
14 # Description: |
15 # |
15 # |
16 |
16 |
17 import operator as ops |
|
18 import unittest |
17 import unittest |
19 import sys, os |
18 |
20 import __init__ |
19 from cone.public import api,exceptions, plugin |
21 import tokenize |
20 from cone.public.rules import RelationContainerImpl |
22 import StringIO |
21 from cone.public.rules import DefaultContext, BaseRelation |
23 |
|
24 from cone.public import api,exceptions, utils |
|
25 from cone.public.rules import ASTInterpreter, RelationContainerImpl |
|
26 from cone.public.rules import ParseException, DefaultContext, BaseRelation |
|
27 from cone.public import rules |
22 from cone.public import rules |
28 |
23 |
29 #### TEST RELATIONS #### |
24 #### TEST RELATIONS #### |
30 |
25 |
31 AA_BA = 'a.a == "foo" requires b.b != 0' |
26 AA_BA = '${a.a} == "foo" requires ${b.b} != 0' |
32 AB_BB = 'a.b configures b.b = a.b+":"+ "test"' |
27 AB_BB = '${a.b} configures ${b.b} = ${a.b}+":"+ "test"' |
33 BA_CA = 'b.a requires c.a and c.b and a.b' |
28 BA_CA = '${b.a} requires ${c.a} and ${c.b} and ${a.b}' |
34 |
29 |
35 CB_DA = 'c.b requires d.a' |
30 CB_DA = '${c.b} requires ${d.a}' |
36 DA_DB = 'd.a requires d.b' |
31 DA_DB = '${d.a} requires ${d.b}' |
37 |
32 |
38 AC_AB_BA = 'a.c and a.a requires b.a' |
33 AC_AB_BA = '${a.c} and ${a.a} requires ${b.a}' |
39 |
34 |
40 EA_FSTAR = 'e.a requires f.*' |
35 EA_FSTAR = '${e.a} requires ${f.*}' |
41 |
36 |
42 TEST_RELATIONS = { |
37 TEST_RELATIONS = { |
43 'a.a' : [AA_BA, 'a.a == "test" requires b.a'], |
38 'a.a' : [AA_BA, '${a.a} == "test" requires ${b.a}'], |
44 'a.b' : [AB_BB], |
39 'a.b' : [AB_BB], |
45 'a.c' : [AC_AB_BA], |
40 'a.c' : [AC_AB_BA], |
46 'b.a' : [BA_CA], |
41 'b.a' : [BA_CA], |
47 'c.b' : [CB_DA], |
42 'c.b' : [CB_DA], |
48 'd.a' : [DA_DB], |
43 'd.a' : [DA_DB], |
130 #print "handle_terminal constant %s" % (expression) |
125 #print "handle_terminal constant %s" % (expression) |
131 try: |
126 try: |
132 return eval(expression) |
127 return eval(expression) |
133 except (NameError,SyntaxError), e: |
128 except (NameError,SyntaxError), e: |
134 return expression |
129 return expression |
135 |
130 |
|
131 def convert_value(self, value): |
|
132 try: |
|
133 # Handle some special literals |
|
134 if value == 'true': return True |
|
135 if value == 'false': return False |
|
136 if value == 'none': return None |
|
137 |
|
138 # Values can be any Python literals, so eval() the string to |
|
139 # get the value |
|
140 return eval(value) |
|
141 except Exception: |
|
142 raise RuntimeError("Could not evaluate '%s'" % value) |
|
143 |
136 def eval(self, ast, expression, value): |
144 def eval(self, ast, expression, value): |
137 #print "expression %s = %s" % (expression,value) |
145 #print "expression %s = %s" % (expression,value) |
138 pass |
146 pass |
139 |
147 |
140 class ConfigurationBaseRelation(BaseRelation): |
148 class ConfigurationBaseRelation(BaseRelation): |
141 def __init__(self, data, left, right): |
149 def __init__(self, data, left, right): |
142 self.context = ConfigurationContext(data) |
150 self.context = None |
143 super(ConfigurationBaseRelation, self).__init__(data, left, right) |
151 super(ConfigurationBaseRelation, self).__init__(data, left, right) |
144 |
152 |
145 class RequireRelation(ConfigurationBaseRelation): |
153 class RequireRelation(ConfigurationBaseRelation): |
146 KEY = 'requires' |
154 KEY = 'requires' |
147 def __init__(self, data, left, right): |
155 def __init__(self, data, left, right): |
148 super(RequireRelation, self).__init__(data, left, right) |
156 super(RequireRelation, self).__init__(data, left, right) |
149 self.context = ConfigurationContext(data) |
157 self.context = None |
150 |
158 |
151 class ConfigureRelation(ConfigurationBaseRelation): |
159 class ConfigureRelation(ConfigurationBaseRelation): |
152 KEY = 'configures' |
160 KEY = 'configures' |
153 def __init__(self, data, left, right): |
161 def __init__(self, data, left, right): |
154 super(ConfigureRelation, self).__init__(data, left, right) |
162 super(ConfigureRelation, self).__init__(data, left, right) |
155 self.context = ConfigurationContext(data) |
163 self.context = None |
156 |
164 |
157 def handle_configure(self, left, right): |
165 def handle_configure(self, left, right): |
158 if left and right: |
166 if left and right: |
159 return True |
167 return True |
160 elif not left: |
168 elif not left: |
167 class ConfigureExpression(rules.TwoOperatorExpression): |
175 class ConfigureExpression(rules.TwoOperatorExpression): |
168 PRECEDENCE = rules.PRECEDENCES['RELATION_OPERATORS'] |
176 PRECEDENCE = rules.PRECEDENCES['RELATION_OPERATORS'] |
169 KEY = 'configures' |
177 KEY = 'configures' |
170 OP = handle_configure |
178 OP = handle_configure |
171 |
179 |
172 def eval(self, context): |
180 def eval(self, context, **kwargs): |
173 super(ConfigureExpression, self).eval(context) |
181 super(ConfigureExpression, self).eval(context, **kwargs) |
174 if not self.value: |
182 if not self.value: |
175 left_keys = [] |
183 left_keys = [] |
176 for ref in self.ast.extract_refs(str(self.left)): |
184 for ref in self.ast.extract_refs(str(self.left)): |
177 for key in context.get_keys(ref): |
185 for key in context.get_keys(ref): |
178 left_keys.append(key) |
186 left_keys.append(key) |
191 class ConcatExpression(rules.TwoOperatorExpression): |
199 class ConcatExpression(rules.TwoOperatorExpression): |
192 PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS'] |
200 PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS'] |
193 KEY= '+' |
201 KEY= '+' |
194 OP = handle_plus |
202 OP = handle_plus |
195 |
203 |
196 |
|
197 class SetExpression(rules.TwoOperatorExpression): |
|
198 PRECEDENCE = rules.PRECEDENCES['SET_OPERATORS'] |
|
199 KEY= '=' |
|
200 OP = handle_set |
|
201 |
|
202 def eval(self, context): |
|
203 try: |
|
204 variable = context.data.get_feature(self.left.expression) |
|
205 variable.set_value(self.right.eval(context)) |
|
206 return True |
|
207 except exceptions.NotFound: |
|
208 return False |
|
209 |
|
210 class TestRelations(unittest.TestCase): |
204 class TestRelations(unittest.TestCase): |
211 |
205 |
212 def setUp(self): |
206 def setUp(self): |
213 self.configuration = get_test_configuration() |
207 self.configuration = get_test_configuration() |
214 |
208 |
221 |
215 |
222 rules.RELATIONS[RequireRelation.KEY] = RequireRelation |
216 rules.RELATIONS[RequireRelation.KEY] = RequireRelation |
223 rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation |
217 rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation |
224 rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression |
218 rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression |
225 rules.OPERATORS[ConcatExpression.KEY] = ConcatExpression |
219 rules.OPERATORS[ConcatExpression.KEY] = ConcatExpression |
226 rules.OPERATORS[SetExpression.KEY] = SetExpression |
|
227 |
220 |
228 def tearDown(self): |
221 def tearDown(self): |
229 rules.RELATIONS = self.RELATIONS_BACKUP |
222 rules.RELATIONS = self.RELATIONS_BACKUP |
230 rules.OPERATORS = self.OPERATORS_BACKUP |
223 rules.OPERATORS = self.OPERATORS_BACKUP |
231 |
224 |
235 """ |
228 """ |
236 factory = TestFactory() |
229 factory = TestFactory() |
237 rels = factory.get_relations_for(self.configuration, 'a.a') |
230 rels = factory.get_relations_for(self.configuration, 'a.a') |
238 ret= rels.execute() |
231 ret= rels.execute() |
239 self.assertTrue(ret) |
232 self.assertTrue(ret) |
240 |
|
241 def test_has_ref(self): |
|
242 """ |
|
243 Tests the relation and relation container |
|
244 """ |
|
245 factory = TestFactory() |
|
246 rels = factory.get_relations_for(self.configuration, 'a.a') |
|
247 ret= rels.execute() |
|
248 self.assertTrue(ret) |
|
249 |
233 |
250 def test_not_has_ref(self): |
234 def test_not_has_ref(self): |
251 factory = TestFactory() |
235 factory = TestFactory() |
252 # depends on c.a which has no value in conf |
236 # depends on c.a which has no value in conf |
253 rels = factory.get_relations_for(self.configuration, 'b.a') |
237 rels = factory.get_relations_for(self.configuration, 'b.a') |
255 self.assertTrue(ret) |
239 self.assertTrue(ret) |
256 |
240 |
257 def test_not_has_ref_in_container(self): |
241 def test_not_has_ref_in_container(self): |
258 factory = TestFactory() |
242 factory = TestFactory() |
259 rels = factory.get_relations_for(self.configuration, 'c.b') |
243 rels = factory.get_relations_for(self.configuration, 'c.b') |
260 ret = rels.execute() |
244 context = plugin.GenerationContext(configuration=self.configuration) |
|
245 ret = rels.execute(context) |
261 self.assertFalse(ret) |
246 self.assertFalse(ret) |
262 |
247 |
263 def test_two_on_the_left(self): |
248 def test_two_on_the_left(self): |
264 factory = TestFactory() |
249 factory = TestFactory() |
265 rels = factory.get_relations_for(self.configuration, 'a.c') |
250 rels = factory.get_relations_for(self.configuration, 'a.c') |
267 self.assertTrue(ret) |
252 self.assertTrue(ret) |
268 |
253 |
269 def test_configure_right_side(self): |
254 def test_configure_right_side(self): |
270 factory = TestFactory() |
255 factory = TestFactory() |
271 rels = factory.get_relations_for(self.configuration, 'a.b') |
256 rels = factory.get_relations_for(self.configuration, 'a.b') |
272 ret = rels.execute() |
257 context = plugin.GenerationContext(configuration=self.configuration) |
|
258 ret = rels.execute(context) |
273 self.assertTrue(ret) |
259 self.assertTrue(ret) |
274 self.assertEquals(self.configuration.get_default_view().get_feature('b.b').get_value(),'hey:test') |
260 self.assertEquals(self.configuration.get_default_view().get_feature('b.b').get_value(),'hey:test') |
|
261 |
|
262 def test_get_refs_from_relation(self): |
|
263 factory = TestFactory() |
|
264 rels = factory.get_relations_for(self.configuration, 'a.b') |
|
265 self.assertEquals(rels.value_list[0].get_refs(), [u'a.b']) |
|
266 self.assertEquals(rels.value_list[0].get_set_refs(), [u'b.b']) |
275 |
267 |
276 if __name__ == '__main__': |
268 if __name__ == '__main__': |
277 unittest.main() |
269 unittest.main() |