buildframework/helium/sf/python/pythoncore/lib/ats3/__init__.py
changeset 587 85df38eb4012
child 588 c7c26511138f
child 618 df88fead2976
equal deleted inserted replaced
217:0f5e3a7fb6af 587:85df38eb4012
       
     1 # -*- encoding: latin-1 -*-
       
     2 
       
     3 #============================================================================ 
       
     4 #Name        : __init__.py 
       
     5 #Part of     : Helium 
       
     6 
       
     7 #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     8 #All rights reserved.
       
     9 #This component and the accompanying materials are made available
       
    10 #under the terms of the License "Eclipse Public License v1.0"
       
    11 #which accompanies this distribution, and is available
       
    12 #at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    13 #
       
    14 #Initial Contributors:
       
    15 #Nokia Corporation - initial contribution.
       
    16 #
       
    17 #Contributors:
       
    18 #
       
    19 #Description:
       
    20 #===============================================================================
       
    21 
       
    22 """ATS3 test drop generation."""
       
    23 
       
    24 #W0142 => * and ** were used
       
    25 #R*    => will be fixed while refactoring
       
    26 #F0401 => pylint didn't find "path" module
       
    27 #C0302 => Too many lines
       
    28 
       
    29 from optparse import OptionParser
       
    30 import ats3.testconfigurator as acp
       
    31 import ats3.dropgenerator as adg
       
    32 import logging
       
    33 import os
       
    34 import re
       
    35 
       
    36 import ats3.parsers as parser
       
    37 
       
    38 from path import path # pylint: disable-msg=F0401
       
    39 
       
    40 _logger = logging.getLogger('ats')
       
    41 
       
    42 class Configuration(object):
       
    43     """
       
    44     ATS3 drop generation configuration.
       
    45     """
       
    46     def __init__(self, opts, tsrc_paths):
       
    47         """
       
    48         Initialize from optparse configuration options.
       
    49         """
       
    50         self._opts = opts
       
    51         c_parser = parser.CppParser()
       
    52         temp_dict = {}
       
    53         pkg_parser = parser.PkgFileParser()
       
    54         
       
    55         # Customize some attributes from how optparse leaves them.
       
    56         self.build_drive = path(self._opts.build_drive)
       
    57         self.file_store = path(self._opts.file_store)
       
    58         self.flash_images = split_paths(self._opts.flash_images)
       
    59         self.sis_files = split_paths(self._opts.sis_files)
       
    60         self.config_file = self._opts.config
       
    61         self.obey_pkgfiles = to_bool(self._opts.obey_pkgfiles)
       
    62         self.hti = to_bool(self._opts.hti)
       
    63         self.specific_pkg = self._opts.specific_pkg
       
    64         if self.specific_pkg == '':
       
    65             self.specific_pkg = None
       
    66         self.tsrc_paths_dict = {}
       
    67 
       
    68         ats_nd = self._opts.ctc_run_process_params.strip()
       
    69         if ats_nd != "":
       
    70             ats_nd = ats_nd.split("#")[0].strip()
       
    71             if ats_nd == "":
       
    72                 self._opts.ctc_run_process_params = ""
       
    73                 _logger.warning("Property \'ats.ctc.host\' is not set. Code coverage measurement report(s) will not be created.")
       
    74                 
       
    75         main_comps = []
       
    76                 
       
    77         for tsrc in tsrc_paths:
       
    78             hrh = os.path.join(self.build_drive + os.sep, 'epoc32', 'include', 'feature_settings.hrh')
       
    79             if os.path.exists(hrh):
       
    80                 temp_dict = c_parser.get_cpp_output(path(tsrc), "d", hrh)
       
    81             else:
       
    82                 temp_dict = c_parser.get_cpp_output(path(tsrc), "d")
       
    83             for t_key, t_value in temp_dict.items():
       
    84                 self.tsrc_paths_dict[t_key] = t_value
       
    85         
       
    86         #preparing a list of main components
       
    87         for main_component in self.tsrc_paths_dict.keys():
       
    88             if self.obey_pkgfiles == "True":
       
    89                 if pkg_parser.get_pkg_files(main_component) != []:
       
    90                     main_comps.append(main_component)
       
    91             else:
       
    92                 main_comps.append(main_component)    
       
    93                     
       
    94                     
       
    95         self.tsrc_paths = main_comps
       
    96 
       
    97     def __getattr__(self, attr):
       
    98         return getattr(self._opts, attr)
       
    99     
       
   100     def __str__(self):
       
   101         dump = "Configuration:\n"
       
   102         seen = set()
       
   103         for key, value in vars(self).items():
       
   104             if not key.startswith("_"):
       
   105                 dump += "\t%s = %s\n" % (key, value)
       
   106                 seen.add(key)
       
   107         for key, value in vars(self._opts).items():
       
   108             if key not in seen:
       
   109                 dump += "\t%s = %s\n" % (key, value)
       
   110                 seen.add(key)                
       
   111         return dump
       
   112     
       
   113 
       
   114 class Ats3TestPlan(object):
       
   115     """
       
   116     Tells ATS3 server what to test and how.
       
   117     
       
   118     The ATS3 test plan from which the test.xml file can be written. The test
       
   119     plan captures all the data related to a test run: flashing, installation
       
   120     of data files and configuration files, test cases, and the notifications.
       
   121     
       
   122     """
       
   123     EMAIL_SUBJECT = (u"ATS3 report for §RUN_NAME§ §RUN_START_DATE§ "
       
   124                      u"§RUN_START_TIME§")
       
   125     REPORT_PATH = u"§RUN_NAME§" + os.sep + u"§RUN_START_DATE§_§RUN_START_TIME§"
       
   126 
       
   127     def __init__(self, config):
       
   128         self.diamonds_build_url = config.diamonds_build_url
       
   129         self.ctc_run_process_params = config.ctc_run_process_params
       
   130         self.testrun_name = config.testrun_name
       
   131         self.harness = config.harness
       
   132         self.device_type = config.device_type
       
   133         self.device_hwid = config.device_hwid
       
   134         self.plan_name = config.plan_name
       
   135         self.report_email = config.report_email
       
   136         self.file_store = config.file_store
       
   137         self.test_timeout = config.test_timeout
       
   138         self.eunitexerunner_flags = config.eunitexerunner_flags
       
   139         self.sets = []
       
   140         self.src_dst = []
       
   141         self.pmd_files = []
       
   142         self.trace_activation_files = []
       
   143         self.trace_enabled = to_bool(config.trace_enabled)
       
   144         self.ctc_enabled = to_bool(config.ctc_enabled)
       
   145         self.multiset_enabled = to_bool(config.multiset_enabled)
       
   146         self.monsym_files = config.monsym_files
       
   147         self.hti = config.hti
       
   148         self.component_path = ""
       
   149         self.custom_dir = None
       
   150     
       
   151     def insert_set(self, data_files=None, config_files=None, 
       
   152                    engine_ini_file=None,  image_files=None, sis_files=None,
       
   153                    testmodule_files=None, test_timeout=None,eunitexerunner_flags=None , test_harness=None,
       
   154                    src_dst=None, pmd_files=None, trace_activation_files=None, custom_dir=None, component_path=None):
       
   155         """
       
   156         Insert a test set into the test plan.
       
   157         """
       
   158         
       
   159         if not custom_dir is None:
       
   160             self.custom_dir = custom_dir
       
   161         if data_files is None:
       
   162             data_files = []
       
   163         if config_files is None:
       
   164             config_files = []
       
   165         if image_files is None:
       
   166             image_files = []
       
   167         if sis_files is None:
       
   168             sis_files = []
       
   169         if testmodule_files is None:
       
   170             testmodule_files = []
       
   171         if test_timeout is None:
       
   172             test_timeout = []
       
   173         if test_harness is None:
       
   174             test_harness = self.harness
       
   175         if src_dst is None:
       
   176             src_dst = []
       
   177         if pmd_files is None:
       
   178             pmd_files = []
       
   179         if trace_activation_files is None:
       
   180             trace_activation_files = []
       
   181         if component_path is None:
       
   182             component_path = self.component_path
       
   183             
       
   184         setd = dict(name="set%d" % len(self.sets),
       
   185                     image_files=image_files, engine_ini_file=engine_ini_file, ctc_enabled=self.ctc_enabled, component_path=component_path)
       
   186         
       
   187         setd = dict(setd, custom_dir=custom_dir)
       
   188         if sis_files:
       
   189             setd = dict(setd, sis_files=sis_files, test_timeout=test_timeout, eunitexerunner_flags=eunitexerunner_flags, test_harness=test_harness, )
       
   190         else:
       
   191             setd = dict(setd, data_files=data_files, config_files=config_files,
       
   192                         testmodule_files=testmodule_files, test_timeout=test_timeout, eunitexerunner_flags=eunitexerunner_flags, test_harness=test_harness,
       
   193                         src_dst=src_dst)
       
   194         if self.trace_enabled != "":
       
   195             if self.trace_enabled.lower() == "true":
       
   196                 setd = dict(setd, pmd_files=pmd_files, 
       
   197                             trace_path=self.file_store.joinpath(self.REPORT_PATH, "traces", setd["name"], "tracelog.blx"),
       
   198                             trace_activation_files=trace_activation_files)
       
   199             else:
       
   200                 setd = dict(setd, pmd_files=[], 
       
   201                             trace_path="",trace_activation_files=[])
       
   202         self.sets.append(setd)
       
   203 
       
   204     def set_plan_harness(self):
       
   205         """setting up test harness for a plan"""
       
   206         eunit = False
       
   207         stif = False
       
   208         stifunit = False
       
   209         for setd in self.sets:
       
   210             if setd["test_harness"] == "STIF":
       
   211                 stif = True
       
   212             elif setd["test_harness"] == "EUNIT":
       
   213                 eunit = True
       
   214             elif setd["test_harness"] == "STIFUNIT":
       
   215                 stifunit = True
       
   216                 
       
   217         if eunit and stif:
       
   218             self.harness = "MULTI_HARNESS"
       
   219         elif eunit:
       
   220             self.harness = "EUNIT"
       
   221         elif stif:
       
   222             self.harness = "STIF"
       
   223         elif stifunit:
       
   224             self.harness = "STIFUNIT"
       
   225         else:
       
   226             self.harness = "GENERIC"
       
   227 
       
   228     @property
       
   229     def post_actions(self):
       
   230         """ATS3 post actions."""
       
   231         actions = []
       
   232         temp_var = ""
       
   233         include_ctc_runprocess = False
       
   234         report_path = self.file_store.joinpath(self.REPORT_PATH)
       
   235         
       
   236         if self.ctc_enabled and adg.CTC_PATHS_LIST != [] and self.monsym_files != "" and not "${" in self.monsym_files:
       
   237             include_ctc_runprocess = True
       
   238             ctc_params = "--ctcdata_files="
       
   239             for cdl in adg.CTC_PATHS_LIST:
       
   240                 ctc_params += cdl + '\\ctcdata.txt' + ";"
       
   241                 temp_var = cdl
       
   242             
       
   243             drop_count = self.ctc_run_process_params.rsplit("#", 1)[1]
       
   244             temp_var = temp_var.split("ctc_helium"+os.sep)[1]
       
   245             diamonds_id = temp_var.split(os.sep)[0]
       
   246             drop_id = temp_var.split(os.sep)[1].split(os.sep)[0]
       
   247             drop_id = re.findall(".*drop(\d*)", drop_id.lower())[0] #extracting int part of drop name
       
   248            
       
   249             ctc_params += r" --monsym_files=" + self.monsym_files
       
   250             ctc_params += r" --diamonds_build_id=" + diamonds_id
       
   251             ctc_params += r" --drop_id=" + drop_id
       
   252             ctc_params += r" --total_amount_of_drops=" + drop_count
       
   253             
       
   254             runprocess_action = ("RunProcessAction", 
       
   255                             (("file", r"catsctc2html/catsctc2html.exe"), #this line will be executing on Windows machine.
       
   256                              ("parameters", ctc_params)))
       
   257             
       
   258             email_url = " CTC report can be found from: " + self.diamonds_build_url
       
   259 
       
   260             email_action = ("SendEmailAction", 
       
   261                             (("subject", self.EMAIL_SUBJECT),
       
   262                              ("type", "ATS3_REPORT"),
       
   263                              ("send-files", "true"),
       
   264                              ("additional-description", email_url),
       
   265                              ("to", self.report_email)))
       
   266         else:
       
   267             email_action = ("SendEmailAction", 
       
   268                             (("subject", self.EMAIL_SUBJECT),
       
   269                              ("type", "ATS3_REPORT"),
       
   270                              ("send-files", "true"),
       
   271                              ("to", self.report_email)))
       
   272         ats3_report = ("FileStoreAction", 
       
   273                        (("to-folder", report_path.joinpath("ATS3_REPORT")),
       
   274                         ("report-type", "ATS3_REPORT"),
       
   275                         ("date-format", "yyyyMMdd"),
       
   276                         ("time-format", "HHmmss")))
       
   277         stif_report = ("FileStoreAction", 
       
   278                        (("to-folder", report_path.joinpath("STIF_REPORT")),
       
   279                         ("report-type", "STIF_COMPONENT_REPORT_ALL_CASES"),
       
   280                         ("run-log", "true"),
       
   281                         ("date-format", "yyyyMMdd"),
       
   282                         ("time-format", "HHmmss")))
       
   283         eunit_report = ("FileStoreAction", 
       
   284                        (("to-folder", report_path.joinpath("EUNIT_REPORT")),
       
   285                         ("report-type", "EUNIT_COMPONENT_REPORT_ALL_CASES"),
       
   286                         ("run-log", "true"),
       
   287                         ("date-format", "yyyyMMdd"),
       
   288                         ("time-format", "HHmmss")))
       
   289         diamonds_action = ("DiamondsAction", ())
       
   290 
       
   291         
       
   292         if include_ctc_runprocess:
       
   293             actions.append(runprocess_action)
       
   294             
       
   295         if self.diamonds_build_url:
       
   296             actions.append(diamonds_action)
       
   297         if self.file_store:
       
   298             actions.append(ats3_report)
       
   299             if self.harness == "STIF":
       
   300                 actions.append(stif_report)
       
   301             elif self.harness == "EUNIT":
       
   302                 actions.append(eunit_report)
       
   303         if self.report_email:
       
   304             actions.append(email_action)
       
   305         return actions               
       
   306 
       
   307     def __getitem__(self, key):
       
   308         return self.__dict__[key]
       
   309 
       
   310 def encode_for_xml(unicode_data, encoding='ascii'):
       
   311     """
       
   312     Encode unicode_data for use as XML or HTML, with characters outside
       
   313     of the encoding converted to XML numeric character references.
       
   314     """
       
   315     try:
       
   316         return unicode_data.encode(encoding, 'xmlcharrefreplace')
       
   317     except ValueError:
       
   318         # ValueError is raised if there are unencodable chars in the
       
   319         # data and the 'xmlcharrefreplace' error handler is not found.
       
   320         # Pre-2.3 Python doesn't support the 'xmlcharrefreplace' error
       
   321         # handler, so we'll emulate it.
       
   322         return _xmlcharref_encode(unicode_data, encoding)
       
   323 
       
   324 def _xmlcharref_encode(unicode_data, encoding):
       
   325     """Emulate Python 2.3's 'xmlcharrefreplace' encoding error handler."""
       
   326     chars = []
       
   327     # Step through the unicode_data string one character at a time in
       
   328     # order to catch unencodable characters:
       
   329     for char in unicode_data:
       
   330         try:
       
   331             chars.append(char.encode(encoding, 'strict'))
       
   332         except UnicodeError:
       
   333             chars.append('&#%i;' % ord(char))
       
   334     return ''.join(chars)
       
   335 
       
   336 
       
   337 def create_drop(config):
       
   338     """Create a test drop."""
       
   339     _logger.debug("initialize test plan")
       
   340         
       
   341     test_plan = Ats3TestPlan(config)
       
   342     component_parser = acp.Ats3ComponentParser(config)
       
   343     
       
   344     for tsrc in config.tsrc_paths:
       
   345         lst_check_harness = []
       
   346         _logger.info("inspecting tsrc path: %s" % tsrc)
       
   347         #checking if there are components without harness
       
   348         for sub_component in config.tsrc_paths_dict[tsrc]['content'].keys():
       
   349             _harness_ = config.tsrc_paths_dict[tsrc]['content'][sub_component]['harness']
       
   350             if _harness_ != "":
       
   351                 lst_check_harness.append(_harness_)
       
   352 
       
   353         #if component has harness then insert to test set 
       
   354         if len(lst_check_harness) > 0:
       
   355             component_parser.insert_test_set(test_plan, path(tsrc), config.tsrc_paths_dict)
       
   356 
       
   357     test_plan.set_plan_harness()
       
   358 
       
   359 
       
   360     #Checking if any non executable set exists
       
   361     #if yes, delete the set
       
   362     tesplan_counter = 0
       
   363     for plan_sets in test_plan.sets:
       
   364         tesplan_counter += 1
       
   365         exe_flag = False
       
   366         for srcanddst in plan_sets['src_dst']:
       
   367             _ext = srcanddst[0].rsplit(".")[1]
       
   368             #the list below are the files which are executable
       
   369             #if none exists, set is not executable
       
   370             for mat in ["dll", "ini", "cfg", "exe", "script"]:
       
   371                 if mat == _ext.lower():
       
   372                     exe_flag = True
       
   373                     break
       
   374             if exe_flag: 
       
   375                 break
       
   376 
       
   377         if not exe_flag: #the set does not have executable, deleting the set
       
   378             _logger.info(plan_sets['component_path'] + ' has no executables so not including in xml')
       
   379             del test_plan.sets[tesplan_counter - 1]
       
   380         
       
   381     if config.ats4_enabled.lower() == 'true':
       
   382         generator = adg.Ats3TemplateTestDropGenerator()
       
   383     else:
       
   384         generator = adg.Ats3TestDropGenerator()
       
   385     _logger.info("generating drop file: %s" % config.drop_file)
       
   386     generator.generate(test_plan, output_file=config.drop_file, config_file=config.config_file)
       
   387 
       
   388 def split_paths(arg, delim=","):
       
   389     """
       
   390     Split the string by delim, removing extra whitespace.
       
   391     """
       
   392     return [path(part.strip()) 
       
   393             for part in arg.split(delim) if part.strip()]
       
   394 
       
   395 def to_bool(param):
       
   396     """setting a true or false based on a param value"""
       
   397     param = str(param).lower()
       
   398     if "true" == param or "t" == param or "1" == param:
       
   399         return "True"
       
   400     else:
       
   401         return "False"
       
   402 
       
   403 def main():
       
   404     """Main entry point."""
       
   405     cli = OptionParser(usage="%prog [options] TSRC1 [TSRC2 [TSRC3 ...]]")
       
   406     cli.add_option("--build-drive", help="Build area root drive")
       
   407     cli.add_option("--data-dir", help="Data directory name", action="append", 
       
   408                    default=[])
       
   409     cli.add_option("--device-type", help="Device type (e.g. 'PRODUCT')", 
       
   410                    default="unknown")
       
   411     cli.add_option("--device-hwid", help="Device hwid", 
       
   412                    default="")
       
   413     cli.add_option("--trace-enabled", help="Tracing enabled", default="False")
       
   414     cli.add_option("--ctc-enabled", help="CTC enabled", default="False")
       
   415     cli.add_option("--multiset-enabled", help="Multiset enabled", default="False")
       
   416     cli.add_option("--diamonds-build-url", help="Diamonds build url")
       
   417     cli.add_option("--ctc-run-process-params", help="ctc parameters include ctc host, drop id and total number of drops, separated by '#'")
       
   418     cli.add_option("--drop-file", help="Name for the final drop zip file",
       
   419                    default="ATS3Drop.zip")
       
   420     cli.add_option("--file-store", help="Destination path for reports.",
       
   421                    default="")
       
   422     cli.add_option("--flash-images", help="Paths to the flash image files",
       
   423                    default="")     
       
   424     cli.add_option("--minimum-flash-images", help="Minimum amount of flash images",
       
   425                    default=2)    
       
   426     cli.add_option("--harness", help="Test harness (default: %default)",
       
   427                    default="")
       
   428     cli.add_option("--report-email", help="Email notification receivers", 
       
   429                    default="")
       
   430     cli.add_option("--plan-name", help="Name of the test plan", 
       
   431                    default="plan")
       
   432     cli.add_option("--sis-files", help="Paths to the sis files",
       
   433                    default="")
       
   434     cli.add_option("--monsym-files", help="Paths to MON.sym files, for ctc useage",
       
   435                    default="")
       
   436     cli.add_option("--target-platform", help="Target platform (default: %default)",
       
   437                    default="armv5 urel")
       
   438     cli.add_option("--test-timeout", help="Test execution timeout value (default: %default)",
       
   439                    default="60")
       
   440     cli.add_option("--eunitexerunner-flags", help="Eunitexerunner flags",
       
   441                    default="")
       
   442     cli.add_option("--testrun-name", help="Name of the test run", 
       
   443                    default="run")
       
   444     cli.add_option("--config", help="Path to the config file",
       
   445                    default="")
       
   446     cli.add_option("--specific-pkg", help="Text in name of pkg files to use", default='')
       
   447     cli.add_option("--ats4-enabled", help="ATS4 enabled", default="False")
       
   448     cli.add_option("--obey-pkgfiles", help="If this option is True, then only test components having PKG file are executable and if the compnents don't have PKG files they will be ignored.", default="False")
       
   449     cli.add_option("--verbose", help="Increase output verbosity", action="store_true", default=False)
       
   450     cli.add_option("--hti", help="HTI enabled", default="True")
       
   451     
       
   452     opts, tsrc_paths = cli.parse_args()
       
   453 
       
   454     if not tsrc_paths:
       
   455         cli.error("no tsrc directories given")
       
   456     if not opts.build_drive:
       
   457         cli.error("no build drive given")      
       
   458     if len(opts.flash_images.split(",")) < int(opts.minimum_flash_images):
       
   459         cli.error("Not enough flash files: %i defined, %i needed" % (len(opts.flash_images.split(",")), int(opts.minimum_flash_images) ))
       
   460 
       
   461     if opts.verbose:
       
   462         _logger.setLevel(logging.DEBUG)
       
   463         logging.basicConfig(level=logging.DEBUG)
       
   464     
       
   465     config = Configuration(opts, tsrc_paths)
       
   466     create_drop(config)
       
   467 
       
   468 
       
   469 if __name__ == "__main__":
       
   470     main()