configurationengine/source/cone/public/tests/unittest_rules.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
equal deleted inserted replaced
-1:000000000000 0:2e8eeb919028
       
     1 # *-* coding: utf8 *-*
       
     2 #
       
     3 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 # All rights reserved.
       
     5 # This component and the accompanying materials are made available
       
     6 # under the terms of "Eclipse Public License v1.0"
       
     7 # which accompanies this distribution, and is available
       
     8 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     9 #
       
    10 # Initial Contributors:
       
    11 # Nokia Corporation - initial contribution.
       
    12 #
       
    13 # Contributors:
       
    14 #
       
    15 # Description:
       
    16 #
       
    17 
       
    18 import unittest
       
    19 import sys, os
       
    20 import __init__
       
    21 
       
    22 from cone.public.api import CompositeConfiguration, Feature
       
    23 from cone.public.rules import ASTInterpreter, RelationContainerImpl, RELATIONS, get_tokens
       
    24 from cone.public.rules import ParseException, DefaultContext, BaseRelation, RequireExpression, OPERATORS
       
    25 
       
    26 #### TEST RELATIONS ####
       
    27 
       
    28 AA_BA = 'a.a require b.b'
       
    29 AB_BB = 'a.b require b.b'
       
    30 BA_CA = 'b.a require c.a and c.b and a.b'
       
    31 
       
    32 CB_DA = 'c.b require d.a'
       
    33 DA_DB = 'd.a require d.b'
       
    34 
       
    35 AC_AB_BA = 'a.c and a.a require b.a'
       
    36 
       
    37 EA_FSTAR = 'e.a require f.*'
       
    38 
       
    39 TEST_RELATIONS = {
       
    40     'a.a' : [AA_BA],
       
    41     'a.b' : [AB_BB],
       
    42     'a.c' : [AC_AB_BA],
       
    43     'b.a' : [BA_CA],
       
    44     'c.b' : [CB_DA],
       
    45     'd.a' : [DA_DB],
       
    46     'e.a' : [EA_FSTAR]
       
    47 }
       
    48 
       
    49 class DummyRelationFactory():
       
    50     def get_relations_for(self, configuration, ref):
       
    51         rels = TEST_RELATIONS.get(ref)
       
    52 
       
    53         if rels:
       
    54             relation_container = RelationContainerImpl()
       
    55             for rel in rels:
       
    56                 rel_s = rel.split(' ')
       
    57                 from_ref = rel_s[0]
       
    58                 relation_name = 'require'
       
    59                 to_ref = ' '.join(rel_s[2:])
       
    60                 relation = RELATIONS.get(relation_name)(configuration, from_ref, to_ref)
       
    61                 relation_container.add_relation(relation)
       
    62                 propagated_relations = self.get_relations_for(configuration, to_ref)
       
    63                 if propagated_relations:
       
    64                     for relation in propagated_relations:
       
    65                         relation_container.add_relation(relation)
       
    66                 
       
    67             return relation_container
       
    68         return None
       
    69 
       
    70 class DummyConfiguration(object):
       
    71     VALUES = {
       
    72         'a.a' : True,
       
    73         'a.b' : False,
       
    74         'a.c' : False,
       
    75         'b.a' : True,
       
    76         'b.b' : True,
       
    77         'c.b' : False,
       
    78         'd.a' : True,
       
    79         'e.a' : True,
       
    80         }
       
    81 
       
    82     def get_feature(self, ref):
       
    83         return DummyConfiguration.VALUES.get(ref, False)
       
    84 
       
    85 class DummyContext(DefaultContext):
       
    86     def handle_terminal(self, expression):
       
    87         return DummyConfiguration.VALUES.get(expression, False)
       
    88 
       
    89 class DummyBaseRelation(BaseRelation):
       
    90     def __init__(self, data, left, right):
       
    91         self.context = DummyContext(data)
       
    92         super(DummyBaseRelation, self).__init__(data, left, right)
       
    93 
       
    94 class DummyRequireRelation(DummyBaseRelation):
       
    95     KEY = 'require'
       
    96 
       
    97     def __init__(self, data, left, right):
       
    98         self.context = DummyContext(data)
       
    99         super(DummyRequireRelation, self).__init__(data, left, right)
       
   100 
       
   101 RELATIONS[DummyRequireRelation.KEY] = DummyRequireRelation
       
   102 OPERATORS['require'] = RequireExpression
       
   103 multilines = \
       
   104 """
       
   105 APs.AP configures KCRUidCommsDatCreator.KCommsDatCreatorInputFileName = 'VariantData_commsdat.xml' and
       
   106   KCRUidStartupSettings.KCRKeyAccessPointPlugin = '0' and
       
   107   KCRUidStartupSettings.KCRKeyStreamingPlugin = '0' and
       
   108   KCRUidStartupSettings.KCRKeyMusicShopPlugin = '0' and
       
   109    KCRUidStartupSettings.KCRKeyDeviceManagementPlugin = '0' and
       
   110   KCRUidStartupSettings.KCRKeyAGPSPlugin = '0'
       
   111 """
       
   112 
       
   113 class TestRelations(unittest.TestCase):
       
   114 
       
   115     def setUp(self):
       
   116         self.configuration = DummyConfiguration()
       
   117 
       
   118     def test_has_ref(self):
       
   119         """
       
   120         Tests the relation and relation container
       
   121         """
       
   122         factory = DummyRelationFactory()
       
   123         rels = factory.get_relations_for(self.configuration, 'a.a')
       
   124         ret= rels.execute()
       
   125         self.assertTrue(ret)
       
   126         
       
   127     def test_not_has_ref(self):
       
   128         factory = DummyRelationFactory()
       
   129         # depends on c.a which has no value in conf
       
   130         rels = factory.get_relations_for(self.configuration, 'b.a')
       
   131         ret = rels.execute()
       
   132         self.assertFalse(ret)
       
   133 
       
   134         for rel in rels:
       
   135             ip = rel.interpreter
       
   136             self.assertTrue(ip.errors)
       
   137             errors = ip.errors
       
   138             self.assertTrue(errors.get('b.a'))
       
   139 
       
   140     def test_not_has_ref_in_container(self):
       
   141         factory = DummyRelationFactory()
       
   142         rels = factory.get_relations_for(self.configuration, 'c.b')
       
   143         ret = rels.execute()
       
   144         self.assertFalse(ret)
       
   145 
       
   146     def test_two_on_the_left(self):
       
   147         factory = DummyRelationFactory()
       
   148         rels = factory.get_relations_for(self.configuration, 'a.c')
       
   149         ret = rels.execute()
       
   150         self.assertTrue(ret)
       
   151 
       
   152 
       
   153 class TestASTInterpreter(unittest.TestCase):
       
   154     def test_require(self):
       
   155         ip = ASTInterpreter('a excludes b require 0')
       
   156         ret = ip.eval()
       
   157 
       
   158     def test_get_tokens(self):
       
   159         self.assertEquals(get_tokens("foo=(2+1) * 3"),['foo','=','(','2','+','1',')','*','3'])
       
   160         self.assertEquals(get_tokens("Arithmetic.MixedResult3 = (Arithmetic.Value2 / 2 + Arithmetic.Value1 * 9) - 7"),['Arithmetic.MixedResult3', '=', '(', 'Arithmetic.Value2', '/', '2', '+', 'Arithmetic.Value1', '*', '9', ')', '-', '7'])
       
   161         print get_tokens(multilines)
       
   162         self.assertEquals(len(get_tokens(multilines)),25)
       
   163     
       
   164     def test_get_unindented_multiline_tokens(self):
       
   165         self.assertEquals(
       
   166             get_tokens("foo = 2+bar\nand foobar = 3 and\nfubar=4"),
       
   167             ['foo', '=', '2', '+', 'bar', 'and', 'foobar', '=', '3', 'and', 'fubar', '=', '4'])
       
   168     
       
   169     def test_get_tab_separated_tokens(self):
       
   170         self.assertEquals(
       
   171             get_tokens("foo\tconfigures\t\tbar\t=\t5"),
       
   172             ['foo', 'configures', 'bar', '=', '5'])
       
   173 
       
   174     def test_get_unicode_tokens(self):
       
   175         self.assertEquals(
       
   176             get_tokens(u'xÿz configures xzÿ = ÿxá'),
       
   177             [u'xÿz', 'configures', u'xzÿ', '=', u'ÿxá'])
       
   178     
       
   179     def test_get_unicode_tokens_2(self):
       
   180         self.assertEquals(
       
   181             get_tokens(u'ελληνικά configures ünicode = u"test string" + ελληνικά'),
       
   182             [u'ελληνικά', 'configures', u'ünicode', '=', 'u"test string"', '+', u'ελληνικά'])
       
   183     
       
   184     def test_get_unicode_tokens_3(self):
       
   185         self.assertEquals(
       
   186             get_tokens(u'oöoä äöoö oöo öoö äaäa'),
       
   187             [u'oöoä', u'äöoö', u'oöo', u'öoö', u'äaäa'])
       
   188     
       
   189     def test_get_unicode_tokens_4(self):
       
   190         self.assertEquals(
       
   191             get_tokens(u'ünicode.rêf1 require rêf2 . ελληνικά'),
       
   192             [u'ünicode.rêf1', u'require', u'rêf2.ελληνικά'])
       
   193     
       
   194     def test_get_unicode_tokens_multiline(self):
       
   195         tokenstr = u"""
       
   196             foo=(2+1) * 3
       
   197             xÿz configures xzÿ = ÿxá
       
   198             ελληνικά configures ünicode = u"test string" + ελληνικά"""
       
   199         expected = [
       
   200             'foo', '=', '(', '2', '+', '1', ')', '*', '3',
       
   201             u'xÿz', 'configures', u'xzÿ', '=', u'ÿxá',
       
   202             u'ελληνικά', 'configures', u'ünicode', '=', 'u"test string"', '+', u'ελληνικά',
       
   203         ]
       
   204         actual = get_tokens(tokenstr)
       
   205         self.assertEquals(actual, expected, '\n%r \n!= \n%r' % (actual, expected))
       
   206     
       
   207     def test_multiline_string(self):
       
   208         tokenstr = '''
       
   209 """
       
   210 tes-
       
   211 ti
       
   212 """
       
   213         '''
       
   214         expected = ['"""\ntes-\nti\n"""']
       
   215         self.assertEquals(get_tokens(tokenstr), expected)
       
   216 
       
   217     def test_syntax_error(self):
       
   218         try:
       
   219             ip = ASTInterpreter('a and and')
       
   220             self.assertTrue(False)
       
   221         except ParseException:
       
   222             self.assertTrue(True)
       
   223 
       
   224     def test_empty_expression(self):
       
   225         expression = ''
       
   226         ip = ASTInterpreter(expression)
       
   227         result = ip.eval()
       
   228         self.assertFalse(result)
       
   229 
       
   230     def test_no_expression(self):
       
   231         ip = ASTInterpreter()
       
   232         result = ip.eval()
       
   233         self.assertFalse(result)       
       
   234 
       
   235         try:
       
   236             ip.create_ast(None)
       
   237             self.assertFalse(True)
       
   238         except ParseException:
       
   239             self.assertTrue(True)
       
   240 
       
   241         ip.create_ast('1 and 1')
       
   242         result = ip.eval()
       
   243         self.assertTrue(result)       
       
   244 
       
   245     def test_one_param_ops(self):
       
   246         ip = ASTInterpreter('1 and truth 1')
       
   247         result = ip.eval()
       
   248         self.assertTrue(result)
       
   249         
       
   250         ip.create_ast('1 and truth 0')
       
   251         result = ip.eval()
       
   252         self.assertFalse(result)
       
   253 
       
   254         ip.create_ast(u'1 and truth not 0')
       
   255         result = ip.eval()
       
   256         self.assertTrue(result)
       
   257 
       
   258     def test_infix_to_postfix(self):
       
   259         expression = '1 and not 1'
       
   260         ip = ASTInterpreter(expression)
       
   261         self.assertEqual(ip.postfix_array, ['1', '1', 'not', 'and'])
       
   262         self.assertFalse(ip.eval())
       
   263 
       
   264     def test_infix_to_postfix_pars(self):
       
   265         expression = '1 and ( 0 or 1 and 1 )'
       
   266         ip = ASTInterpreter(expression)
       
   267         self.assertEqual(ip.postfix_array, ['1', '0', '1', 'or', '1', 'and', 'and'])
       
   268         self.assertTrue(ip.eval())
       
   269 
       
   270     def test_not(self):
       
   271         ip = ASTInterpreter(u'not 1',)
       
   272         ret = ip.eval()
       
   273         self.assertFalse(ret)
       
   274 
       
   275         ip.create_ast(u'not 1')
       
   276         ret = ip.eval()
       
   277         self.assertFalse(ret)
       
   278 
       
   279         ip.create_ast('not STRING_VALUE')
       
   280         ret = ip.eval()
       
   281         self.assertFalse(ret)
       
   282 
       
   283     def test_not_with_multiple(self):
       
   284         ip = ASTInterpreter(u'1 and not 0')
       
   285         ret = ip.eval()
       
   286         self.assertTrue(ret)
       
   287         ip.create_ast(u'1 and not 1')
       
   288         ret = ip.eval()
       
   289         self.assertFalse(ret)
       
   290 
       
   291     def test_and(self):
       
   292         ip = ASTInterpreter(u'1 and 1 and 0')
       
   293         ret = ip.eval()
       
   294         self.assertFalse(ret)
       
   295 
       
   296         ip.create_ast(u'1 and 1 and 1')
       
   297         ret = ip.eval()
       
   298         self.assertTrue(ret)
       
   299 
       
   300     def test_nand(self):
       
   301         ip = ASTInterpreter(u'1 nand 1 nand 1')
       
   302         ret = ip.eval()
       
   303         self.assertTrue(ret)
       
   304 
       
   305         ip.create_ast(u'1 nand 1 nand 0')
       
   306         ret = ip.eval()
       
   307         self.assertTrue(ret)
       
   308 
       
   309         ip.create_ast(u'1 nand 0 nand 1')
       
   310         ret = ip.eval()
       
   311         self.assertFalse(ret)
       
   312 
       
   313         ip.create_ast(u'0 nand 0 nand 0')
       
   314         ret = ip.eval()
       
   315         self.assertTrue(ret)
       
   316 
       
   317     def test_or(self):
       
   318         ip = ASTInterpreter(u'1 or 1 or 0')
       
   319         ret = ip.eval()
       
   320         self.assertTrue(ret)
       
   321 
       
   322     def test_or_for_exclude(self):
       
   323         """
       
   324         On exclude case if OR returns True -> some element is selected
       
   325         and the rule evaluation should fail, the exclude rule should
       
   326         evaluate if PostfixRuleEngine.eval(expression) -> return False
       
   327         """
       
   328         ip = ASTInterpreter(u'1 or 1 or 1')
       
   329         ret = ip.eval()
       
   330         self.assertTrue(ret)
       
   331 
       
   332         ip.create_ast(u'1 or 1 or 0')
       
   333         ret = ip.eval()
       
   334         self.assertTrue(ret)
       
   335 
       
   336         ip.create_ast(u'1 or 0 or 1')
       
   337         ret = ip.eval()
       
   338         self.assertTrue(ret)
       
   339 
       
   340         ip.create_ast(u'0 or 1 or 1')
       
   341         ret = ip.eval()
       
   342         self.assertTrue(ret)
       
   343 
       
   344         ip.create_ast(u'1 or 0 or 0')
       
   345         ret = ip.eval()
       
   346         self.assertTrue(ret)
       
   347 
       
   348         ip.create_ast(u'0 or 0 or 1')
       
   349         ret = ip.eval()
       
   350         self.assertTrue(ret)
       
   351 
       
   352         ip.create_ast(u'0 or 0 or 0')
       
   353         ret = ip.eval()
       
   354         self.assertFalse(ret)
       
   355 
       
   356     def test_nor(self):
       
   357         ip = ASTInterpreter(u'1 nor 1 nor 1')
       
   358         ret = ip.eval()
       
   359         self.assertFalse(ret)
       
   360 
       
   361         ip.create_ast(u'1 nor 1 nor 0')
       
   362         ret = ip.eval()
       
   363         self.assertTrue(ret)
       
   364 
       
   365         ip.create_ast(u'0 nor 1 nor 0')
       
   366         ret = ip.eval()
       
   367         self.assertTrue(ret)
       
   368 
       
   369         ip.create_ast(u'0 nor 0 nor 0')
       
   370         ret = ip.eval()
       
   371         self.assertFalse(ret)
       
   372 
       
   373 
       
   374     def test_xor(self):
       
   375         ip = ASTInterpreter(u'1 xor 1')
       
   376         ret = ip.eval()
       
   377         self.assertFalse(ret)
       
   378 
       
   379         ip.create_ast(u'1 xor 0 xor 0')
       
   380         ret = ip.eval()
       
   381         self.assertTrue(ret)  
       
   382 
       
   383     def test_eq_cmp(self):
       
   384         ip = ASTInterpreter(u'1 == 0')
       
   385         ret = ip.eval()
       
   386         self.assertFalse(ret)
       
   387         
       
   388         ip.create_ast(u'1 == 1')
       
   389         ret = ip.eval()
       
   390         self.assertTrue(ret)
       
   391 
       
   392         ip.create_ast(u'DEFINED == DEFINED')
       
   393         ret = ip.eval()
       
   394         self.assertTrue(ret)        
       
   395 
       
   396         ip.create_ast(u'DEFINED == UNDEFINED')
       
   397         ret = ip.eval()
       
   398         self.assertFalse(ret)
       
   399 
       
   400     def test_neq_cmp(self):
       
   401         ip = ASTInterpreter(u'1 != 1')
       
   402         ret = ip.eval()
       
   403         self.assertFalse(ret)
       
   404 
       
   405         ip.create_ast(u'1 != 0')
       
   406         ret = ip.eval()
       
   407         self.assertTrue(ret)   
       
   408 
       
   409     def test_lt_cmp(self):
       
   410         ip = ASTInterpreter(u'0 < 1')
       
   411         ret = ip.eval()
       
   412         self.assertTrue(ret)
       
   413 
       
   414         ip.create_ast(u'-1 < 1')
       
   415         ret = ip.eval()
       
   416         self.assertTrue(ret)
       
   417 
       
   418         ip.create_ast(u'-1 < -2')
       
   419         ret = ip.eval()
       
   420         self.assertFalse(ret)
       
   421 
       
   422         ip.create_ast(u'2 < 0')
       
   423         ret = ip.eval()
       
   424         self.assertFalse(ret)
       
   425 
       
   426     def test_gt_cmp(self):
       
   427         ip = ASTInterpreter(u'0 > -1')
       
   428         ret = ip.eval()
       
   429         self.assertTrue(ret)
       
   430 
       
   431         ip.create_ast(u'2 > 1')
       
   432         ret = ip.eval()
       
   433         self.assertTrue(ret)
       
   434 
       
   435         ip.create_ast(u'0 > 1')
       
   436         ret = ip.eval()
       
   437         self.assertFalse(ret)
       
   438 
       
   439         ip.create_ast(u'-1 > 1')
       
   440         ret = ip.eval()
       
   441         self.assertFalse(ret)
       
   442 
       
   443     def test_lte_cmp(self):
       
   444         ip = ASTInterpreter(u'0 <= 1')
       
   445         ret = ip.eval()
       
   446         self.assertTrue(ret)
       
   447 
       
   448         ip.create_ast(u'0 <= 0')
       
   449         ret = ip.eval()
       
   450         self.assertTrue(ret)
       
   451 
       
   452         ip.create_ast(u'1 <= 0')
       
   453         ret = ip.eval()
       
   454         self.assertFalse(ret)
       
   455 
       
   456     def test_gte_cmp(self):
       
   457         ip = ASTInterpreter(u'1 >= 0')
       
   458         ret = ip.eval()
       
   459         self.assertTrue(ret)
       
   460 
       
   461         ip.create_ast(u'0 >= 0')
       
   462         ret = ip.eval()
       
   463         self.assertTrue(ret)
       
   464 
       
   465         ip.create_ast(u'0 >= 1')
       
   466         ret = ip.eval()
       
   467         self.assertFalse(ret)
       
   468 
       
   469     def test_extract_refs(self):
       
   470         refs = ASTInterpreter.extract_refs('a.a and ( b.c and d.e )')
       
   471         self.assertTrue('a.a' in refs)
       
   472         self.assertTrue('b.c' in refs)
       
   473         self.assertTrue('d.e' in refs)
       
   474         self.assertTrue('and' not in refs)
       
   475 
       
   476     def test_one_of(self):
       
   477         """ Test for showing that relation one-of is basically "LEFT and R1 xor R2"
       
   478         """
       
   479         ip = ASTInterpreter(u'1 and 1 and 1 xor 0')
       
   480         ret = ip.eval()
       
   481         self.assertTrue(ret)
       
   482 
       
   483 if __name__ == '__main__':
       
   484     unittest.main()