configurationengine/source/scripts/tests/unittest_generate.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
equal deleted inserted replaced
2:87cfa131b535 3:e7e0ae78773e
    15 # Description:
    15 # Description:
    16 #
    16 #
    17 ## 
    17 ## 
    18 # @author Teemu Rytkonen
    18 # @author Teemu Rytkonen
    19 
    19 
    20 import sys, os, shutil, unittest
    20 import os, unittest
    21 import __init__
    21 import tempfile
       
    22 
    22 from testautomation.base_testcase import BaseTestCase
    23 from testautomation.base_testcase import BaseTestCase
    23 from testautomation import zip_dir
    24 from testautomation import zip_dir
    24 from scripttest_common import get_cmd
    25 from scripttest_common import get_cmd
    25 
    26 
    26 
    27 
    27 ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
    28 ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
    28 testproject = os.path.join(ROOT_PATH,'test_project.cpf')
    29 testproject = os.path.join(ROOT_PATH,'test_project.cpf')
    29 rootconf = 'root3.confml'
    30 rootconf = 'root3.confml'
    30 
    31 
    31 class TestGenerate(BaseTestCase):
    32 class TestGenerate(BaseTestCase):
    32 
       
    33     def test_get_help(self):
    33     def test_get_help(self):
    34         cmd = '%s -h' % get_cmd('generate')
    34         cmd = '%s -h' % get_cmd('generate')
    35         out = self.run_command(cmd)
    35         out = self.run_command(cmd)
    36         lines = out.split('\r\n')
    36         lines = out.split(os.linesep)
    37         self.assertTrue('Options:' in lines)
    37         self.assertTrue('Options:' in lines)
    38         self.assertTrue('  Generate options:' in lines)
    38         self.assertTrue('  Generate options:' in lines)
    39 
    39 
    40     def test_generate(self):
    40     def test_generate(self):
    41         self.set_modification_reference_time(testproject)
    41         self.set_modification_reference_time(testproject)
    44         cmd = '%s -p "%s" -c "%s" -o "%s"' % (get_cmd('generate'),testproject,rootconf,OUTPUT_DIR)
    44         cmd = '%s -p "%s" -c "%s" -o "%s"' % (get_cmd('generate'),testproject,rootconf,OUTPUT_DIR)
    45         out = self.run_command(cmd)
    45         out = self.run_command(cmd)
    46         self.assert_exists_and_contains_something(OUTPUT_DIR)
    46         self.assert_exists_and_contains_something(OUTPUT_DIR)
    47         
    47         
    48         self.assert_not_modified(testproject)
    48         self.assert_not_modified(testproject)
    49     
    49             
       
    50     def test_generate_output_file_from_script(self):
       
    51         testproject = os.path.join(ROOT_PATH, 'testdata/generate/impl_container/project')
       
    52         self.set_modification_reference_time(testproject)
       
    53         OUTPUT_DIR = os.path.join(ROOT_PATH, 'temp/output')
       
    54         self.remove_if_exists(OUTPUT_DIR)
       
    55         LOGFILE = os.path.join(OUTPUT_DIR, 'cone_temp.log')
       
    56         cmd = '%s -p "%s" -c "%s" -o "%s" --log-file "%s"' % (get_cmd('generate'),
       
    57                                                                           testproject,
       
    58                                                                           'base_root.confml',
       
    59                                                                           OUTPUT_DIR,
       
    60                                                                           LOGFILE)
       
    61         out = self.run_command(cmd)
       
    62 
       
    63         self.assertEquals(True, os.path.isfile(os.path.join(OUTPUT_DIR, 'output_test.txt')))
       
    64         self.assert_not_modified(testproject)
       
    65 
       
    66     def test_generate_with_absolute_path(self):
       
    67         self.set_modification_reference_time(testproject)
       
    68         tempdir = os.path.join(tempfile.gettempdir(), 'cone_output')
       
    69         (drive,OUTPUT_DIR) = os.path.splitdrive(os.path.abspath(tempdir))
       
    70         LOGFILE = os.path.join(OUTPUT_DIR, 'cone_temp.log')
       
    71         self.remove_if_exists(OUTPUT_DIR)
       
    72         cmd = '%s -p "%s" -c "%s" -o "%s" --log-file "%s"' % (get_cmd('generate'),
       
    73                                                             testproject,
       
    74                                                             rootconf,
       
    75                                                             OUTPUT_DIR,
       
    76                                                             LOGFILE)
       
    77         out = self.run_command(cmd)
       
    78         self.assert_exists_and_contains_something(OUTPUT_DIR)
       
    79         self.assertTrue(os.path.exists(LOGFILE))
       
    80         self.assert_not_modified(testproject)
       
    81 
    50     def test_generate_with_report(self):
    82     def test_generate_with_report(self):
    51         self.set_modification_reference_time(testproject)
    83         self.set_modification_reference_time(testproject)
    52         OUTPUT_DIR  = os.path.join(ROOT_PATH, 'temp/gen2/output')
    84         OUTPUT_DIR  = os.path.join(ROOT_PATH, 'temp/gen2/output')
    53         REPORT_FILE = os.path.join(ROOT_PATH, 'temp/gen2/report.html')
    85         REPORT_FILE = os.path.join(ROOT_PATH, 'temp/gen2/report.html')
    54         self.remove_if_exists([OUTPUT_DIR, REPORT_FILE])
    86         self.remove_if_exists([OUTPUT_DIR, REPORT_FILE])
   106             project       = os.path.join(ROOT_PATH, 'testdata/generate/test_project_invalid_data_refs.zip'),
   138             project       = os.path.join(ROOT_PATH, 'testdata/generate/test_project_invalid_data_refs.zip'),
   107             output_dir    = 'temp/gen7/output',
   139             output_dir    = 'temp/gen7/output',
   108             report_file   = 'temp/gen7/report.csv',
   140             report_file   = 'temp/gen7/report.csv',
   109             template_path = os.path.join(ROOT_PATH,'test_template/template2.csv'))
   141             template_path = os.path.join(ROOT_PATH,'test_template/template2.csv'))
   110 
   142 
       
   143     def test_generate_with_errors_in_project(self):
       
   144         project = os.path.join(ROOT_PATH, 'testdata/generate/error_test_project')
       
   145         
       
   146         OUTPUT_DIR  = os.path.join(ROOT_PATH, 'temp/gen_err/output')
       
   147         REPORT_FILE = os.path.join(ROOT_PATH, 'temp/gen_err/report.html')
       
   148         LOG_FILE = os.path.join(ROOT_PATH, 'temp/gen_err/cone.log')
       
   149         self.remove_if_exists([OUTPUT_DIR, REPORT_FILE, LOG_FILE])
       
   150         cmd = '%s -p "%s" -c root.confml -o "%s" -r "%s" --log-file "%s"' % (get_cmd('generate'),project, OUTPUT_DIR, REPORT_FILE, LOG_FILE)
       
   151         out = self.run_command(cmd)
       
   152         
       
   153         # Check that output and report are generated even though
       
   154         # there are errors in the project
       
   155         self.assert_exists_and_contains_something(OUTPUT_DIR)
       
   156         self.assert_exists_and_contains_something(REPORT_FILE)
       
   157         self.assert_exists_and_contains_something(LOG_FILE)
       
   158         
       
   159         # Check that the errors are shown in the log correctly
       
   160         self.assert_file_contains(LOG_FILE,
       
   161             ['''ERROR   : cone.rules Exception in get_refs() of relation ConfigureRelation(ref='layer1/implml/rules_with_errors.implml', lineno=11): Expression is None''',
       
   162              '''ERROR   : cone Error executing rule ConfigureRelation(ref='layer1/implml/rules_with_errors.implml', lineno=11): ParseException: Syntax error: " configures ${TempFeature.Int} = 6000"''',
       
   163              '''ERROR   : cone Error executing rule ConfigureRelation(ref='layer1/implml/rules_with_errors.implml', lineno=12): ParseException: Syntax error: "True configures "'''])
       
   164         
       
   165         # Check that the errors are shown in the report correctly
       
   166         self.assert_file_contains(REPORT_FILE, data=[],
       
   167             regexes=[r'Exception:\s*layer1/implml/rules_with_errors.implml:11',
       
   168                      r'Exception:\s*layer1/implml/rules_with_errors.implml:12'])
       
   169         
       
   170         # Check from the output that the other rules were successfully
       
   171         # executed
       
   172         self.assert_file_contains(
       
   173             os.path.join(OUTPUT_DIR, 'content/rules_with_errors_test.txt'),
       
   174             ['TempFeature.String:  testing and more testing',
       
   175             'TempFeature.Int:     501',
       
   176             'TempFeature.Real:    1.75',
       
   177             'TempFeature.Boolean: True'])
       
   178 
   111 class TestGenerateAllImplsOnLastLayer(BaseTestCase):
   179 class TestGenerateAllImplsOnLastLayer(BaseTestCase):
   112     
       
   113     def _prepare_workdir(self, workdir):
   180     def _prepare_workdir(self, workdir):
   114         workdir = os.path.join(ROOT_PATH, workdir)
   181         workdir = os.path.join(ROOT_PATH, workdir)
   115         self.recreate_dir(workdir)
   182         self.recreate_dir(workdir)
   116         
   183         
   117         # Any needed extra preparation can be done here
   184         # Any needed extra preparation can be done here
   174             
   241             
   175             EXPECTED_DIR = os.path.join(ROOT_PATH, "testdata/generate/expected")
   242             EXPECTED_DIR = os.path.join(ROOT_PATH, "testdata/generate/expected")
   176             self.assert_dir_contents_equal('output', EXPECTED_DIR, ['.svn'])
   243             self.assert_dir_contents_equal('output', EXPECTED_DIR, ['.svn'])
   177             
   244             
   178             # Check that output has also been generated to the overridden output root directory
   245             # Check that output has also been generated to the overridden output root directory
   179             self.assert_exists_and_contains_something('overridden_output/output_rootdir_test.txt')
   246             #self.assert_exists_and_contains_something('overridden_output/output_rootdir_test.txt')
   180             self.assert_exists_and_contains_something('overridden_output/test_subdir/output_rootdir_test.txt')
   247             #self.assert_exists_and_contains_something('overridden_output/test_subdir/output_rootdir_test.txt')
   181         finally:
   248         finally:
   182             os.chdir(orig_workdir)
   249             os.chdir(orig_workdir)
   183 
   250 
   184 class TestGenerationImplFilteringByTags(BaseTestCase):
   251 class TestGenerationImplFilteringByTags(BaseTestCase):
   185     
       
   186     def test_no_tag_filtering(self):
   252     def test_no_tag_filtering(self):
   187         self._run_tag_filtering_test(
   253         self._run_tag_filtering_test(
   188             name     = 'no_filter',
   254             name     = 'no_filter',
   189             filter   = '',
   255             filter   = '',
   190             expected = ['none', 't1', 't2', 't3', 't1_t2', 't2_t3', 't1_t3', 't1_t2_t3'])
   256             expected = ['none', 't1', 't2', 't3', 't1_t2', 't2_t3', 't1_t3', 't1_t2_t3'])
   262         OUTPUT      = os.path.join(OUTPUT_ROOT, 'out')
   328         OUTPUT      = os.path.join(OUTPUT_ROOT, 'out')
   263         LOG         = os.path.join(OUTPUT_ROOT, 'cone.log')
   329         LOG         = os.path.join(OUTPUT_ROOT, 'cone.log')
   264         self.remove_if_exists(OUTPUT)
   330         self.remove_if_exists(OUTPUT)
   265         
   331         
   266         cmd = '%s -p "%s" --output "%s" --log-file="%s" %s' % (get_cmd('generate'), PROJECT, OUTPUT, LOG, filter)
   332         cmd = '%s -p "%s" --output "%s" --log-file="%s" %s' % (get_cmd('generate'), PROJECT, OUTPUT, LOG, filter)
       
   333         #print cmd
   267         self.run_command(cmd)
   334         self.run_command(cmd)
   268         
   335         
   269         self.assert_exists_and_contains_something(OUTPUT)
   336         self.assert_exists_and_contains_something(OUTPUT)
   270         
   337         
   271         expected_files = sorted([x + '.txt' for x in expected])
   338         expected_files = sorted([x + '.txt' for x in expected])
   272         actual_files = sorted(os.listdir(OUTPUT))
   339         actual_files = sorted(os.listdir(OUTPUT))
   273         
   340         
   274         self.assertEquals(expected_files, actual_files)
   341         self.assertEquals(expected_files, actual_files)
   275 
   342 
       
   343 class TestGenerationImplFilteringByLayers(BaseTestCase):
       
   344     def test_filter_by_last_layer(self):
       
   345         self._run_layer_filtering_test(
       
   346             name     = 'll1',
       
   347             filter   = '--layer -1',
       
   348             expected = ['layer3'])
       
   349     
       
   350     def test_filter_by_two_last_layers(self):
       
   351         self._run_layer_filtering_test(
       
   352             name     = 'll2',
       
   353             filter   = '--layer -1 --layer 2',
       
   354             expected = ['layer2', 'layer3'])
       
   355     
       
   356     def test_filter_by_regex_1(self):
       
   357         self._run_layer_filtering_test(
       
   358             name     = 'r1',
       
   359             filter   = '--layer-regex layer[13]',
       
   360             expected = ['layer1', 'layer3'])
       
   361     
       
   362     def test_filter_by_regex_2(self):
       
   363         self._run_layer_filtering_test(
       
   364             name     = 'r2',
       
   365             filter   = '--layer-regex [12]/root.confml',
       
   366             expected = ['layer1', 'layer2'])
       
   367     
       
   368     def test_filter_by_regex_3(self):
       
   369         self._run_layer_filtering_test(
       
   370             name     = 'r3',
       
   371             filter   = '--layer-regex layer1 --layer-regex layer3',
       
   372             expected = ['layer1', 'layer3'])
       
   373     
       
   374     def test_filter_by_wildcard(self):
       
   375         self._run_layer_filtering_test(
       
   376             name     = 'w',
       
   377             filter   = '--layer-wildcard *layer*',
       
   378             expected = ['layer1', 'layer2', 'layer3'])
       
   379     
       
   380     def _run_layer_filtering_test(self, name, filter, expected):
       
   381         PROJECT = os.path.join(ROOT_PATH, 'testdata/generate/layer_filtering_project')
       
   382         
       
   383         OUTPUT_ROOT = os.path.join(ROOT_PATH, 'temp/gen_lf/', name)
       
   384         OUTPUT      = os.path.join(OUTPUT_ROOT, 'out')
       
   385         LOG         = os.path.join(OUTPUT_ROOT, 'cone.log')
       
   386         self.remove_if_exists(OUTPUT)
       
   387         
       
   388         cmd = '%s -p "%s" --output "%s" --log-file="%s" %s' % (get_cmd('generate'), PROJECT, OUTPUT, LOG, filter)
       
   389         #print cmd
       
   390         self.run_command(cmd)
       
   391         
       
   392         self.assert_exists_and_contains_something(OUTPUT)
       
   393         
       
   394         expected_files = sorted([x + '.txt' for x in expected])
       
   395         actual_files = sorted(os.listdir(OUTPUT))
       
   396         
       
   397         # Ignore the rule output txt files
       
   398         for f in ('rule_test_v2.txt', 'rule_test_v3.txt'):
       
   399             if f in actual_files: del actual_files[actual_files.index(f)]
       
   400         self.assertEquals(expected_files, actual_files)
       
   401         
       
   402         # Check that the correct rules have been executed
       
   403         expected_str = ' ' + ' '.join(sorted(expected)) + ' x'
       
   404         self.assert_file_content_equals(os.path.join(OUTPUT, 'rule_test_v2.txt'), expected_str)
       
   405         self.assert_file_content_equals(os.path.join(OUTPUT, 'rule_test_v3.txt'), expected_str)
       
   406 
       
   407 class TestGenerateInvalidParameters(BaseTestCase):
       
   408     PROJECT = os.path.join(ROOT_PATH, 'testdata/generate/layer_filtering_project')
       
   409     
       
   410     def _run_test(self, args, expected_msg):
       
   411         if not isinstance(args, basestring):
       
   412             args = ' '.join(args)
       
   413         
       
   414         cmd = get_cmd('generate') + ' ' + args
       
   415         # Note: The following run_command() should really expect the
       
   416         #       return code 2, but for some reason when running from the
       
   417         #       standalone test set, the return value is 0 for some cases
       
   418         #       (specifically, the ones that don't use parser.error() to
       
   419         #       exit the program)
       
   420         out = self.run_command(cmd, expected_return_code = None)
       
   421         
       
   422         self.assertTrue(expected_msg in out,
       
   423                         "Expected message '%s' not in output ('%s')" % (expected_msg, out))
       
   424     
       
   425     def test_invalid_layer_index_1(self):
       
   426         self._run_test(
       
   427             '-p "%s" --layer -1 --layer foobar' % self.PROJECT,
       
   428             "option --layer: invalid integer value: 'foobar'")
       
   429     
       
   430     def test_invalid_layer_index_2(self):
       
   431         self._run_test(
       
   432             '-p "%s" --layer -1 --layer 7' % self.PROJECT,
       
   433             'Invalid layer index: 7')
       
   434     
       
   435     def test_no_matching_layer_for_regex(self):
       
   436         self._run_test(
       
   437             '-p "%s" --layer-regex foo' % self.PROJECT,
       
   438             'No layers matched by layer patterns')
       
   439     
       
   440     def test_no_matching_layer_for_wildcard(self):
       
   441         self._run_test(
       
   442             '-p "%s" --layer-wildcard foo' % self.PROJECT,
       
   443             'No layers matched by layer patterns')
       
   444 
       
   445 class TestGenerateImplContainer(BaseTestCase):
       
   446     def _run_test(self, root, args):
       
   447         PROJECT = os.path.join(ROOT_PATH, 'testdata/generate/impl_container/project')
       
   448         EXPECTED = os.path.join(ROOT_PATH, 'testdata/generate/impl_container/expected', root)
       
   449         
       
   450         OUTPUT_ROOT = os.path.join(ROOT_PATH, 'temp/gen_ic/', root)
       
   451         OUTPUT      = os.path.join(OUTPUT_ROOT, 'out')
       
   452         LOG         = os.path.join(OUTPUT_ROOT, 'cone.log')
       
   453         self.remove_if_exists(OUTPUT)
       
   454         
       
   455         cmd = '%s -p "%s" -c %s --output "%s" --log-file="%s" %s' % (get_cmd('generate'), PROJECT, root, OUTPUT, LOG, args)
       
   456         #print cmd
       
   457         self.run_command(cmd)
       
   458         
       
   459         self.assert_dir_contents_equal(EXPECTED, OUTPUT, ['.svn'])
       
   460     
       
   461     def test_implcontainer_with_triggering_rule_and_templateml(self):
       
   462         self._run_test(
       
   463             root = 'data_root.confml',
       
   464             args = '--layer -1')
       
   465 
       
   466 class TestGenerateSetTempvarValue(BaseTestCase):
       
   467     def test_set_tempvar_value_from_cmdline(self):
       
   468         PROJECT = os.path.join(ROOT_PATH, 'generation_test_project')
       
   469         
       
   470         OUTPUT_ROOT = os.path.join(ROOT_PATH, 'temp/gen_tvs/')
       
   471         OUTPUT      = os.path.join(OUTPUT_ROOT, 'out')
       
   472         LOG         = os.path.join(OUTPUT_ROOT, 'cone.log')
       
   473         self.remove_if_exists(OUTPUT)
       
   474         
       
   475         cmd = ['%(cone_cmd)s',
       
   476                '-p "%(project)s"',
       
   477                '-c root.confml',
       
   478                '--output "%(output)s"',
       
   479                '--log-file="%(log_file)s"',
       
   480                '--impl simple_tempvar',
       
   481                '--set "TempFeature.String=testing from cmdline"',
       
   482                '--set "TempFeature.Int=8090"',
       
   483                '--set "TempFeature.Real=-5.75"',]
       
   484         cmd = ' '.join(cmd) % {'cone_cmd':  get_cmd('generate'),
       
   485                                'project':   PROJECT,
       
   486                                'output':    OUTPUT,
       
   487                                'log_file':  LOG}
       
   488         #print cmd
       
   489         self.run_command(cmd)
       
   490         
       
   491         self.assert_file_contains(
       
   492             os.path.join(OUTPUT, 'content', 'simple_tempvars_test.txt'),
       
   493             ['TempFeature.String:  testing from cmdline and more testing',
       
   494              'TempFeature.Int:     8091',
       
   495              'TempFeature.Real:    -5.5'])
       
   496 
       
   497 class TestGenerateWhatOutput(BaseTestCase):
       
   498     PROJECT = os.path.join(ROOT_PATH, 'generation_test_project')
       
   499     OUTPUT_ROOT = os.path.join(ROOT_PATH, 'temp/gen_wop')
       
   500     OUTPUT      = os.path.join(OUTPUT_ROOT, 'out')
       
   501     LOG         = os.path.join(OUTPUT_ROOT, 'cone.log')
       
   502     WHAT_FILE   = os.path.join(OUTPUT_ROOT, 'what_output.txt')
       
   503     CMP_FILE    = os.path.join(PROJECT, 'what_output.txt')
       
   504     
       
   505     def test_write_what_out(self):        
       
   506         self.remove_if_exists(self.OUTPUT)
       
   507         
       
   508         cmd = ['%(cone_cmd)s',
       
   509                '-p "%(project)s"',
       
   510                '-c root.confml',
       
   511                '--what="%(what_file)s"',
       
   512                '--output "%(output)s"',
       
   513                '--log-file="%(log_file)s"',
       
   514                '--all-layers',]
       
   515         cmd = ' '.join(cmd) % {'cone_cmd':      get_cmd('generate'),
       
   516                                'project':       self.PROJECT,
       
   517                                'what_file':     self.WHAT_FILE,
       
   518                                'output':        self.OUTPUT,
       
   519                                'log_file':      self.LOG}
       
   520         self.run_command(cmd)
       
   521         
       
   522         cmp_what_out_fh = open(self.CMP_FILE, 'r')
       
   523         cmp_files = []
       
   524         try: cmp_files = cmp_what_out_fh.readlines()
       
   525         finally: cmp_what_out_fh.close()
       
   526             
       
   527         self.assert_exists_and_contains_something(self.WHAT_FILE)
       
   528         self.assert_file_contains(self.WHAT_FILE, [self._flip(c.strip()) for c in cmp_files])
       
   529         
       
   530     def _flip(self, path):
       
   531         newpath= path.replace('\\', os.sep)
       
   532         newpath = newpath.replace('/', os.sep)
       
   533         return newpath
       
   534         
       
   535 
   276 if __name__ == '__main__':
   536 if __name__ == '__main__':
   277       unittest.main()
   537     unittest.main()