buildframework/helium/tools/common/python/lib/integration/quality.py
changeset 1 be27ed110b50
child 179 d8ac696cc51f
equal deleted inserted replaced
0:044383f39525 1:be27ed110b50
       
     1 #============================================================================ 
       
     2 #Name        : quality.py 
       
     3 #Part of     : Helium 
       
     4 
       
     5 #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     6 #All rights reserved.
       
     7 #This component and the accompanying materials are made available
       
     8 #under the terms of the License "Eclipse Public License v1.0"
       
     9 #which accompanies this distribution, and is available
       
    10 #at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    11 #
       
    12 #Initial Contributors:
       
    13 #Nokia Corporation - initial contribution.
       
    14 #
       
    15 #Contributors:
       
    16 #
       
    17 #Description:
       
    18 #===============================================================================
       
    19 
       
    20 """
       
    21 Symbian log based analyser.
       
    22 
       
    23  * Internal export parser
       
    24  * Duplicate generation parser (relying on abld -what)
       
    25 
       
    26 Policy validation.
       
    27 """
       
    28 
       
    29 import symbian.log
       
    30 import re
       
    31 import os
       
    32 import sys
       
    33 import csv
       
    34 import fileutils
       
    35 import pathaddition.match
       
    36 import logging
       
    37 
       
    38 #logging.basicConfig(level=logging.DEBUG)
       
    39 _logger = logging.getLogger("integration.quality")
       
    40 
       
    41 class InternalExportParser(symbian.log.Parser):
       
    42     """ This class extends the Symbian log parser class and implement
       
    43         an "abld -what" analyser which detects file generated/exported inside
       
    44         the source tree.
       
    45     """
       
    46     def __init__(self, _file):
       
    47         """The constructor """
       
    48         symbian.log.Parser.__init__(self, _file)
       
    49         self.__match_what = re.compile("abld(\.bat)?(\s+.*)*\s+-w(hat)?", re.I)
       
    50         self.internalexports = {}
       
    51         
       
    52     def task(self, name, _cmd, _dir, content):
       
    53         """ Analyse task log. """
       
    54         if self.__match_what.match(_cmd) != None:
       
    55             for line in content.splitlines():
       
    56                 if line.startswith(os.path.sep) \
       
    57                     and not os.path.normpath(line.strip().lower()).startswith(os.path.sep+"epoc32"+os.path.sep) \
       
    58                     and os.path.splitext(line.strip().lower())[1] != '':
       
    59                     if name not in self.internalexports:
       
    60                         self.internalexports[name] = []
       
    61                     self.internalexports[name].append(line)
       
    62 
       
    63 
       
    64 class AbldWhatParser(symbian.log.Parser):
       
    65     """ This class extends the Symbian log parser class and implement
       
    66         an "abld -what" analyser which sort the generated files by component. 
       
    67     """
       
    68     def __init__(self, _file):
       
    69         """The constructor """
       
    70         symbian.log.Parser.__init__(self, _file)
       
    71         self.__match_what = re.compile(r"abld(\.bat)?(\s+.*)*\s+-w(hat)?", re.I)
       
    72         self.__match_cmaker_what = re.compile(r"cmaker(\.cmd)?(\s+.*)*\s+ACTION=what", re.I)
       
    73         self.files_per_component = {}
       
    74         self.components_per_file = {}
       
    75         
       
    76     def task(self, name, _cmd, _dir, content):
       
    77         """ Analyse task log. """
       
    78         if _cmd != None and self.__match_what.match(_cmd) != None:
       
    79             for line in content.splitlines():
       
    80                 line = line.strip()
       
    81                 if not os.path.normpath(line).startswith(os.path.sep):
       
    82                     continue
       
    83                 # component per file
       
    84                 if line.lower() not in self.components_per_file:
       
    85                     self.components_per_file[line.lower()] = []
       
    86                 if name not in self.components_per_file[line.lower()]:
       
    87                     self.components_per_file[line.lower()].append(name)
       
    88 
       
    89                 # file per components
       
    90                 if name not in self.files_per_component:
       
    91                     self.files_per_component[name] = []
       
    92                 self.files_per_component[name].append(line)
       
    93         elif _cmd != None and self.__match_cmaker_what.match(_cmd) != None:
       
    94             for line in content.splitlines():
       
    95                 line = line.strip()
       
    96                 if not line.startswith('"'):
       
    97                     continue
       
    98                 if not line.endswith('"'):
       
    99                     continue
       
   100                 line = os.path.normpath(line.strip('"')).lower()
       
   101                 # component per file
       
   102                 if line not in self.components_per_file:
       
   103                     self.components_per_file[line] = []
       
   104                 if name not in self.components_per_file[line]:
       
   105                     self.components_per_file[line].append(name)
       
   106             
       
   107                 # file per components
       
   108                 if name not in self.files_per_component:
       
   109                     self.files_per_component[name] = []
       
   110                 self.files_per_component[name].append(line)
       
   111 
       
   112 
       
   113 class PolicyValidator(object):
       
   114     """ Validate policy files on a hierarchy. """    
       
   115     def __init__(self, policyfiles=None, csvfile=None, ignoreroot=False):
       
   116         """The constructor """
       
   117         if policyfiles is None:
       
   118             policyfiles = ['distribution.policy.s60']
       
   119         self._policyfiles = policyfiles
       
   120         self._ids = None
       
   121         self._ignoreroot = ignoreroot
       
   122 
       
   123     def load_policy_ids(self, csvfile):
       
   124         """ Load the icds from the CSV file.
       
   125             report format by generating array: ['unknownstatus', value, description]
       
   126         """
       
   127         self._ids = {}
       
   128         reader = csv.reader(open(csvfile, "rU"))
       
   129         for row in reader:            
       
   130             if len(row)>=3 and re.match(r"^\s*\d+\s*$", row[0]): 
       
   131                 self._ids[row[0]] = row
       
   132                 if row[1].lower() != "yes" and row[1].lower() != "no" and row[1].lower() != "bin":
       
   133                     yield ["unknownstatus", row[0], row[2]]
       
   134 
       
   135     def validate_content(self, filename):
       
   136         """  Validating the policy file content. If it cannot be decoded, 
       
   137             it reports an 'invalidencoding'.            
       
   138             Case 'notinidlist': value is not defined under the id list.
       
   139         """
       
   140         value = None
       
   141         try:
       
   142             value = fileutils.read_policy_content(filename)
       
   143         except Exception:
       
   144             yield ["invalidencoding", filename, None]
       
   145         if value is not None:                        
       
   146             if self._ids != None:
       
   147                 if value not in self._ids:
       
   148                     yield ["notinidlist", filename, value]
       
   149     
       
   150     def find_policy(self, path):
       
   151         """ find the policy file under path using filenames under the list. """
       
   152         for filename in self._policyfiles:
       
   153             if os.sep != '\\':
       
   154                 for f in os.listdir(path):
       
   155                     if f.lower() == filename.lower():
       
   156                         return os.path.join(path, f)
       
   157             if os.path.exists(os.path.join(path, filename)):
       
   158                 return os.path.join(path, filename)
       
   159         return None
       
   160 
       
   161     def validate(self, path):
       
   162         """ Return a list couple [errortype, location, policy].
       
   163             errortype: missing, invalidencoding, notinidlist .
       
   164             missing: location is a directory.
       
   165             otherwise the doggie policy file.
       
   166         """
       
   167         path = os.path.normpath(path)
       
   168         for dirpath, _, _ in os.walk(path):
       
   169             # skipping the root
       
   170             if dirpath == path and self._ignoreroot:
       
   171                 continue
       
   172             # skip svn dirs
       
   173             if pathaddition.match.ant_match(dirpath, "**/.svn/**"):
       
   174                 continue
       
   175             # Skipping j2me content. Shouln't this be done differently?
       
   176             if pathaddition.match.ant_match(dirpath, "**/j2me/**"):
       
   177                 continue
       
   178             filename = self.find_policy(dirpath)
       
   179             if filename != None:
       
   180                 for result in self.validate_content(filename):
       
   181                     yield result
       
   182             else:
       
   183                 yield ['missing', dirpath, None]
       
   184